annotate src/asm.c @ 58:bed2d84eeabe

Fix ldimh special casing of loading labels for the case when the label is not a forward reference
author Michael Pavone <pavone@retrodev.com>
date Tue, 06 Sep 2016 09:42:31 -0700
parents c44170825b16
children b15187a99d6f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
1 #include <stdint.h>
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
2 #include <string.h>
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
3 #include <stdio.h>
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
4 #include <stddef.h>
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
5 #include <stdlib.h>
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
6 #include <ctype.h>
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
7 #include "cpu.h"
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
8
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
9 typedef enum {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
10 IMMED4,
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
11 IMMED8,
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
12 IMMEDHI,
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
13 BCCDST,
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
14 DCB,
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
15 DCW,
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
16 DCL
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
17 } reftype;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
18
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
19 typedef struct {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
20 uint16_t address;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
21 reftype type;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
22 } reference;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
23
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
24
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
25 typedef struct {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
26 char *name;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
27 reference *references;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
28 size_t num_references;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
29 size_t reference_storage;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
30 uint16_t address;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
31 uint8_t valid;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
32 } label;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
33
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
34 typedef struct {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
35 label *labels;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
36 size_t num_labels;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
37 size_t label_storage;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
38 } label_meta;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
39
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
40 typedef struct {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
41 int immed_min;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
42 int immed_max;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
43 uint16_t base;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
44 uint8_t first_shift;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
45 uint8_t second_shift;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
46 uint8_t expected_args;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
47 } inst_info;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
48
55
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
49 #define MAX_SIZE (4*1024*1024)
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
50
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
51 label *add_label(label_meta *labels, char *name, uint16_t address, uint8_t valid)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
52 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
53 if (labels->num_labels == labels->label_storage) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
54 labels->label_storage *= 2;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
55 labels->labels = realloc(labels->labels, sizeof(label) * labels->label_storage);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
56 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
57 labels->labels[labels->num_labels].name = strdup(name);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
58 labels->labels[labels->num_labels].references = NULL;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
59 labels->labels[labels->num_labels].address = address;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
60 labels->labels[labels->num_labels].valid = valid;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
61 labels->num_labels++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
62 return labels->labels + labels->num_labels - 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
63 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
64
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
65 label *find_label(label_meta *meta, char *name)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
66 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
67 for (size_t i = 0; i < meta->num_labels; i++)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
68 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
69 if (!strcmp(name, meta->labels[i].name)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
70 return meta->labels + i;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
71 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
72 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
73 return NULL;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
74 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
75
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
76 uint16_t find_string_arr(char ** list, char *str, uint16_t num_entries)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
77 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
78 for (uint16_t i = 0; i < num_entries; i++)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
79 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
80 if (!strcmp(list[i], str)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
81 return i;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
82 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
83 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
84 return num_entries;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
85 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
86
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
87 inst_info find_mnemonic(char *mnemonic)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
88 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
89 uint16_t index = find_string_arr(mnemonics, mnemonic, SINGLE_SOURCE);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
90 inst_info ret;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
91 if (index < SINGLE_SOURCE) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
92 ret.base = index;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
93 ret.first_shift = 4;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
94 if (index == LDIM || index == LDIMH) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
95 ret.second_shift = 12;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
96 ret.expected_args = 2;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
97 ret.immed_min = -128;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
98 ret.immed_max = 256;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
99 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
100 ret.second_shift = 8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
101 ret.expected_args = 3;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
102 ret.immed_min = ret.immed_max = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
103 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
104 return ret;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
105 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
106 index = find_string_arr(mnemonics_single_src, mnemonic, SINGLE_REG);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
107 if (index < SINGLE_REG) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
108 ret.base = index << 4 | SINGLE_SOURCE;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
109 ret.first_shift = 8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
110 ret.second_shift = 12;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
111 ret.expected_args = 2;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
112 if (index >= INI) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
113 if (index >= ADDI) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
114 ret.immed_min = -8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
115 ret.immed_max = 8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
116 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
117 ret.immed_min = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
118 ret.immed_max = 15;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
119 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
120 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
121 ret.immed_min = ret.immed_max = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
122 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
123 return ret;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
124 }
57
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
125 if (!strcmp("lsli", mnemonic) || !strcmp("lsri", mnemonic)) {
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
126 ret.base = LSI << 4 | SINGLE_SOURCE;
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
127 if (mnemonic[2] == 'r') {
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
128 ret.base |= 0x800;
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
129 }
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
130 ret.immed_min = 1;
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
131 ret.immed_max = 8;
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
132 ret.first_shift = 8;
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
133 ret.second_shift = 12;
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
134 ret.expected_args = 2;
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
135 return ret;
c44170825b16 Implement lsli and lsri in assembler
Michael Pavone <pavone@retrodev.com>
parents: 55
diff changeset
136 }
46
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
137 index = find_string_arr(mnemonics_single_reg, mnemonic, SETVBR+1);
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
138 if (index > SETVBR) {
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
139 ret.base = 0xFFFF;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
140 return ret;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
141 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
142 ret.base = index << 8 | SINGLE_REG << 4 | SINGLE_SOURCE;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
143 ret.immed_min = ret.immed_max = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
144 ret.first_shift = 12;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
145 ret.second_shift = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
146 ret.expected_args = 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
147 return ret;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
148 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
149
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
150 void add_reference(label *label, uint16_t address, reftype type)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
151 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
152 if (!label->references) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
153 label->reference_storage = 4;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
154 label->references = malloc(sizeof(reference) * label->reference_storage);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
155 label->num_references = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
156 } else if (label->num_references == label->reference_storage) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
157 label->reference_storage *= 2;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
158 label->references = realloc(label->references, sizeof(reference) * label->reference_storage);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
159 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
160
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
161 label->references[label->num_references].address = address;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
162 label->references[label->num_references].type = type;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
163 label->num_references++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
164 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
165
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
166 char * get_arg(char **pos)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
167 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
168 char *linebuf = *pos;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
169 while (*linebuf && isspace(*linebuf) && *linebuf != ';')
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
170 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
171 linebuf++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
172 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
173 char * start = linebuf;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
174 char * end = start;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
175 while (*linebuf && *linebuf != ';' && *linebuf != ',')
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
176 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
177 if (!isspace(*linebuf)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
178 end = linebuf+1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
179 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
180 linebuf++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
181 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
182 if (start == end) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
183 return NULL;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
184 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
185 if (*end) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
186 if (*linebuf == ',') {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
187 linebuf++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
188 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
189 linebuf = end;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
190 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
191 *end = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
192 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
193 *pos = linebuf;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
194 return start;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
195 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
196
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
197 void free_labels (label_meta *meta)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
198 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
199 for (size_t i = 0; i < meta->num_labels; i++)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
200 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
201 free(meta->labels[i].name);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
202 if(meta->labels[i].references) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
203 free(meta->labels[i].references);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
204 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
205 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
206 free(meta->labels);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
207 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
208
55
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
209 int handle_dc(char size, char *linebuf, uint8_t *outbuf, uint32_t *pc, label_meta *meta)
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
210 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
211 char *arg;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
212 long value;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
213 char *start = linebuf;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
214 char *orig = strdup(linebuf);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
215 int in_string = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
216 while ((arg = in_string ? linebuf : get_arg(&linebuf)))
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
217 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
218 //TODO: actual error checking
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
219 if (arg[0] == '$' || (arg[0] == '0' && arg[1] == 'x')) {
10
9f575f77a157 Fix parsing of hex literals in assembler
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
220 value = strtol(arg[0] == '$' ? arg+1 : arg+2, NULL, 16);
12
d4112095b93f Allow negative decimal literals
Michael Pavone <pavone@retrodev.com>
parents: 10
diff changeset
221 } else if (arg[0] >= '0' && arg[0] <= '9' || arg[0] == '-') {
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
222 value = strtol(arg, NULL, 10);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
223 } else if (arg[0] == '"') {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
224 if (arg[1] == '"') {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
225 //emtpy string or end of string
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
226 in_string = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
227 continue;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
228 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
229 if (arg[1] == '\\' && arg[2]) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
230 switch(arg[2])
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
231 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
232 case 'n':
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
233 value = '\n';
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
234 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
235 case 't':
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
236 value = '\t';
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
237 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
238 case 'r':
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
239 value = '\r';
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
240 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
241 case '"':
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
242 case '\\':
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
243 value = arg[2];
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
244 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
245 default:
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
246 fprintf(stderr, "WARNING: Unrecognized escape char %c\n", arg[2]);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
247 value = arg[2];
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
248 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
249 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
250 arg++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
251 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
252 value = arg[1];
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
253 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
254 in_string = 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
255 arg[1] = '"';
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
256 linebuf = arg+1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
257 int len = strlen(linebuf);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
258 //undo termination done by get_arg
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
259 linebuf[len] = orig[len + linebuf-start];
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
260 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
261 label *l = find_label(meta, arg);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
262 if (!l) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
263 l = add_label(meta, arg, 0, 0);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
264 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
265 if (l->valid) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
266 value = l->address;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
267 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
268 value = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
269 add_reference(l, *pc, size == 'b' ? DCB : size == 'w' ? DCW : DCL);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
270 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
271 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
272 switch (size)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
273 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
274 case 'b':
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
275 if (value < -128 || value > 255) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
276 fprintf(stderr, "WARNING: %s is too large to fit in a byte\n", arg);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
277 }
55
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
278 if (*pc >= MAX_SIZE) {
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
279 fputs("ERROR: Hit end of ROM space\n", stderr);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
280 free(orig);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
281 return 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
282 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
283 outbuf[(*pc)++] = value;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
284 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
285 case 'w':
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
286 if (value < -32768 || value > 65535) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
287 fprintf(stderr, "WARNING: %s is too large to fit in a word\n", arg);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
288 }
55
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
289 if (*pc >= MAX_SIZE - 1) {
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
290 fputs("ERROR: Hit end of ROM space\n", stderr);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
291 free(orig);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
292 return 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
293 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
294 outbuf[(*pc)++] = value >> 8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
295 outbuf[(*pc)++] = value;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
296 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
297 case 'l':
55
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
298 if (*pc >= MAX_SIZE - 3) {
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
299 fputs("ERROR: Hit end of ROM space\n", stderr);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
300 free(orig);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
301 return 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
302 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
303 outbuf[(*pc)++] = value >> 24;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
304 outbuf[(*pc)++] = value >> 16;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
305 outbuf[(*pc)++] = value >> 8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
306 outbuf[(*pc)++] = value;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
307 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
308 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
309 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
310 free(orig);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
311 return 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
312 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
313
55
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
314 int process_arg(uint16_t *inst, char *arg, int arg_shift, int immed_min, int immed_max, label_meta *meta, uint32_t pc)
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
315 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
316 long value;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
317 if (arg[0] == 'r' && arg[1] >= '0' && arg[1] <= '9' && (arg[2] == 0 || arg[3] == 0)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
318 //posible register
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
319 value = strtol(arg+1, NULL, 10);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
320 if (value >= 0 && value < 16) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
321 *inst |= value << arg_shift;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
322 return 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
323 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
324 }
46
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
325 if (!strcmp(arg, "db")) {
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
326 *inst |= REG_DB << arg_shift;
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
327 return 1;
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
328 }
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
329 if (!strcmp(arg, "sp")) {
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
330 *inst |= REG_SP << arg_shift;
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
331 return 1;
51672bd41cdd Rework data segment setup to allow a stack segment and to add space for push and pop instructions
Michael Pavone <pavone@retrodev.com>
parents: 44
diff changeset
332 }
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
333 if (!strcmp(arg, "pc")) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
334 *inst |= REG_PC << arg_shift;
25
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 12
diff changeset
335 return 1;
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
336 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
337 if (!strcmp(arg, "sr")) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
338 *inst |= REG_SR << arg_shift;
25
fb14515266f4 Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
Michael Pavone <pavone@retrodev.com>
parents: 12
diff changeset
339 return 1;
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
340 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
341 if (immed_min == immed_max) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
342 fprintf(stderr, "ERROR: Non-register argument %s where a register is required\n", arg);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
343 return 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
344 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
345
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
346 //TODO: actual error checking
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
347 if (arg[0] == '$' || (arg[0] == '0' && arg[1] == 'x')) {
10
9f575f77a157 Fix parsing of hex literals in assembler
Michael Pavone <pavone@retrodev.com>
parents: 6
diff changeset
348 value = strtol(arg[0] == '$' ? arg+1 : arg+2, NULL, 16);
12
d4112095b93f Allow negative decimal literals
Michael Pavone <pavone@retrodev.com>
parents: 10
diff changeset
349 } else if (arg[0] >= '0' && arg[0] <= '9' || arg[0] == '-') {
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
350 value = strtol(arg, NULL, 10);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
351 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
352 label *l = find_label(meta, arg);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
353 if (!l) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
354 l = add_label(meta, arg, 0, 0);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
355 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
356 if (l->valid) {
58
bed2d84eeabe Fix ldimh special casing of loading labels for the case when the label is not a forward reference
Michael Pavone <pavone@retrodev.com>
parents: 57
diff changeset
357 if (*inst == LDIMH) {
bed2d84eeabe Fix ldimh special casing of loading labels for the case when the label is not a forward reference
Michael Pavone <pavone@retrodev.com>
parents: 57
diff changeset
358 value = l->address >> 8;
bed2d84eeabe Fix ldimh special casing of loading labels for the case when the label is not a forward reference
Michael Pavone <pavone@retrodev.com>
parents: 57
diff changeset
359 } else {
bed2d84eeabe Fix ldimh special casing of loading labels for the case when the label is not a forward reference
Michael Pavone <pavone@retrodev.com>
parents: 57
diff changeset
360 value = l->address;
bed2d84eeabe Fix ldimh special casing of loading labels for the case when the label is not a forward reference
Michael Pavone <pavone@retrodev.com>
parents: 57
diff changeset
361 }
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
362 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
363 value = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
364 add_reference(l, pc, (*inst & 0xF) == LDIMH ? IMMEDHI : (*inst & 0xF) == LDIM ? IMMED8 : IMMED4);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
365 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
366 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
367 if (value > immed_max || value < immed_min) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
368 fprintf(stderr, "WARNING: %s is too big to fit in an %s\n", arg, (*inst & 0xF) <= LDIMH ? "byte" : "nibble");
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
369 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
370 if (immed_max == 8) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
371 if (value == 8) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
372 value = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
373 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
374 value &= 0xF;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
375 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
376 value &= 0xFF;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
377 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
378 *inst |= value << arg_shift;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
379 return 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
380 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
381
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
382 char * condition_names[] = {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
383 "ra", "rn", "eq", "ne", "mi", "pl", "cs", "cc", "gr", "le"
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
384 };
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
385
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
386 int handle_bcc(char *cc, char *args, uint8_t *outbuf, uint16_t pc, label_meta *meta)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
387 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
388 uint16_t intcc = find_string_arr(condition_names, cc, COND_LEQ+1);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
389 if (intcc > COND_LEQ) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
390 fprintf(stderr, "ERROR: Invalid condition code %s\n", cc);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
391 return 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
392 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
393 char *dest = get_arg(&args);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
394 if (!dest) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
395 fprintf(stderr, "ERROR: Missing argument to b%s\n", cc);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
396 return 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
397 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
398 char *extra = get_arg(&args);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
399 if (extra) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
400 fprintf(stderr, "ERROR: Extra argument %s to b%s\n", extra, cc);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
401 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
402 label *l = find_label(meta, dest);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
403 if (!l) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
404 l = add_label(meta, dest, 0, 0);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
405 add_reference(l, pc, BCCDST);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
406 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
407 uint16_t dest_addr = l->valid ? l->address : pc + 4;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
408 if (dest_addr & 1) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
409 fprintf(stderr, "ERROR: Label %s refers to odd address %X which is illegal for b%s\n", dest, dest_addr, cc);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
410 return 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
411 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
412 int32_t diff = dest_addr - (pc + 4);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
413 if (diff < -512 || diff > 510) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
414 fprintf(stderr, "ERROR: Label %s is out of range for b%s\n", dest, cc);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
415 return 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
416 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
417 diff &= 0x1FE;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
418 uint16_t inst = BCC | diff << 3 | intcc << 12;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
419 outbuf[pc] = inst >> 8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
420 outbuf[pc+1] = inst;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
421 return 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
422 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
423
55
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
424 uint8_t handle_incbin(char *cur, uint8_t *outbuf, uint32_t *pc)
29
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
425 {
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
426 char * end = strchr(cur, ';');
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
427 if (end) {
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
428 *end = 0;
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
429 } else {
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
430 end = cur + strlen(cur);
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
431 }
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
432 while (end - cur > 1 && isspace(*(end-1)))
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
433 {
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
434 end--;
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
435 }
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
436 *end = 0;
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
437 FILE *incfile = fopen(cur, "rb");
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
438 if (!incfile) {
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
439 fprintf(stderr, "Failed to open inclued file %s for reading\n", cur);
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
440 return 0;
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
441 }
55
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
442 size_t read = fread(outbuf + *pc, 1, MAX_SIZE-*pc, incfile);
29
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
443 fclose(incfile);
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
444 *pc += read;
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
445 return 1;
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
446 }
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
447
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
448 uint8_t assemble_file(FILE *input, FILE *output)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
449 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
450 //fixed size buffers are lame, but so are lines longer than 4K characters
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
451 //this is good enough for the really simple first version
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
452 char linebuf[4096];
55
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
453 uint8_t outbuf[MAX_SIZE];
f9846719aa26 Remove old 48K limit in assembler
Michael Pavone <pavone@retrodev.com>
parents: 46
diff changeset
454 uint32_t pc = 0;
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
455
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
456 size_t num_labels = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
457 size_t label_storage = 1024;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
458 label_meta labels = {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
459 .labels = malloc(sizeof(label) * 1024),
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
460 .label_storage = 1024,
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
461 .num_labels = 0
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
462 };
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
463 int line = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
464
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
465 while (fgets(linebuf, sizeof(linebuf), input) && pc < sizeof(outbuf)/sizeof(uint16_t))
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
466 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
467 line++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
468 char *lname = NULL;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
469 char *cur = linebuf;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
470 if (!isspace(*cur)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
471 lname = cur;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
472 while(*cur && *cur != ':' && !isspace(*cur))
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
473 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
474 cur++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
475 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
476 if (*cur) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
477 *cur = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
478 cur++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
479 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
480 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
481 while (*cur && isspace(*cur))
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
482 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
483 cur++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
484 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
485 if (!*cur || *cur == ';') {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
486 if (lname) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
487 label *l = find_label(&labels, lname);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
488 if (l) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
489 l->address = pc;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
490 l->valid = 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
491 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
492 add_label(&labels, lname, pc, 1);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
493 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
494 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
495 continue;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
496 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
497 char *mnemonic = cur;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
498 while (*cur && !isspace(*cur) && *cur != ';')
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
499 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
500 cur++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
501 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
502 if (!*cur || *cur == ';') {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
503 *cur = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
504 fprintf(stderr, "Missing arguments to instruction %s on line %d\n", mnemonic, line);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
505 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
506 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
507 *cur = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
508 cur++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
509 if (!strncmp(mnemonic, "dc.", 3) && (mnemonic[3] == 'b' || mnemonic[3] == 'w' || mnemonic[3] == 'l')) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
510 if (mnemonic[3] != 'b' && pc & 1) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
511 outbuf[pc] = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
512 pc++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
513 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
514 if (lname) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
515 label *l = find_label(&labels, lname);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
516 if (l) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
517 l->address = pc;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
518 l->valid = 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
519 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
520 add_label(&labels, lname, pc, 1);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
521 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
522 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
523 if (!handle_dc(mnemonic[3], cur, outbuf, &pc, &labels)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
524 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
525 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
526 continue;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
527 }
29
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
528 if (!strcmp(mnemonic, "incbin")) {
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
529 if (!handle_incbin(cur, outbuf, &pc)) {
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
530 goto error;
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
531 }
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
532 continue;
5a8b5f9fc50a Added incbin directive to assembler
Michael Pavone <pavone@retrodev.com>
parents: 25
diff changeset
533 }
6
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
534 //automatically align to word boundary
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
535 if (pc & 1) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
536 outbuf[pc] = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
537 pc++;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
538 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
539 if (lname) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
540 label *l = find_label(&labels, lname);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
541 if (l) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
542 l->address = pc;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
543 l->valid = 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
544 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
545 add_label(&labels, lname, pc, 1);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
546 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
547 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
548 if (mnemonic[0] == 'b' && strlen(mnemonic) == 3) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
549 if (!handle_bcc(mnemonic + 1, cur, outbuf, pc, &labels)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
550 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
551 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
552 pc+=2;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
553 continue;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
554 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
555 char *firstarg = get_arg(&cur);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
556
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
557 if (!firstarg) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
558 fprintf(stderr, "Missing arguments to instruction %s on line %d\n", mnemonic, line);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
559 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
560 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
561 char *secondarg = get_arg(&cur);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
562 char *thirdarg;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
563 int num_args;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
564 if (secondarg) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
565 thirdarg = get_arg(&cur);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
566 num_args = thirdarg ? 3 : 2;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
567 } else {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
568 thirdarg = NULL;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
569 num_args = 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
570 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
571
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
572 inst_info inf = find_mnemonic(mnemonic);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
573 if (inf.base == 0xFFFF) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
574 fprintf(stderr, "Invalid mnemonic %s on line %d\n", mnemonic, line);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
575 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
576 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
577 if (inf.expected_args != num_args) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
578 fprintf(stderr, "Instruction %s expects %d args, but %d were given on line %d\n", mnemonic, inf.expected_args, num_args, line);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
579 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
580 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
581
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
582 uint16_t inst = inf.base;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
583 if (!process_arg(&inst, firstarg, inf.first_shift, inf.immed_min, inf.immed_max, &labels, pc)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
584 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
585 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
586 if (secondarg) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
587 if (!process_arg(&inst, secondarg, inf.second_shift, 0, 0, &labels, pc)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
588 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
589 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
590 if (thirdarg) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
591 if (!process_arg(&inst, thirdarg, inf.second_shift+4, 0, 0, &labels, pc)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
592 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
593 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
594 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
595 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
596 outbuf[pc++] = inst >> 8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
597 outbuf[pc++] = inst;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
598 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
599 for (int i = 0; i < labels.num_labels; i++)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
600 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
601 if (labels.labels[i].references) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
602 if (!labels.labels[i].valid) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
603 fprintf(stderr, "ERROR: label %s is used but not defined\n", labels.labels[i].name);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
604 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
605 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
606 uint16_t address = labels.labels[i].address;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
607 for(reference *ref = labels.labels[i].references;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
608 ref < labels.labels[i].references + labels.labels[i].num_references;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
609 ref++
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
610 )
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
611 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
612 //TODO: Warn when addresses don't fit
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
613 switch(ref->type)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
614 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
615 case IMMED4:
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
616 if (address == 8) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
617 address = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
618 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
619 outbuf[ref->address] |= address & 0xF;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
620 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
621 case IMMED8:
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
622 outbuf[ref->address] |= (address & 0xF0) >> 4;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
623 outbuf[ref->address+1] |= (address & 0xF) << 4;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
624 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
625 case IMMEDHI:
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
626 outbuf[ref->address] |= (address & 0xF000) >> 12;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
627 outbuf[ref->address+1] |= (address & 0xF00) >> 4;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
628 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
629 case BCCDST: {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
630 if (address & 1) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
631 fprintf(stderr, "ERROR: Label %s refers to odd address %X which is illegal for bcc\n", labels.labels[i].name, address);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
632 goto error;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
633 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
634 int diff = address - (ref->address + 4);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
635 if (diff < -512 || diff > 510) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
636 fprintf(stderr, "ERROR: Label %s has address %X which is out of range of bcc at %X\n", labels.labels[i].name, address, ref->address);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
637 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
638 outbuf[ref->address] |= (diff & 0x1E0) >> 5;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
639 outbuf[ref->address+1] |= (diff & 0x01E) << 3;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
640 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
641 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
642 case DCB:
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
643 outbuf[ref->address] = address;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
644 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
645 case DCW:
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
646 outbuf[ref->address] = address >> 8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
647 outbuf[ref->address+1] = address;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
648 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
649 case DCL:
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
650 outbuf[ref->address] = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
651 outbuf[ref->address+1] = 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
652 outbuf[ref->address+2] = address >> 8;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
653 outbuf[ref->address+3] = address;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
654 break;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
655 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
656 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
657 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
658 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
659 if (pc == fwrite(outbuf, 1, pc, output)) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
660 free_labels(&labels);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
661 return 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
662 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
663 fputs("Error writing to output file\n", stderr);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
664 error:
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
665 free_labels(&labels);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
666 return 0;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
667 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
668
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
669
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
670 int main(int argc, char ** argv)
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
671 {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
672 if (argc < 3) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
673 fputs("Usage: asm INFILE OUTFILE\n", stderr);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
674 return 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
675 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
676 FILE *infile = strcmp("-", argv[1]) ? fopen(argv[1], "r") : stdin;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
677 if (!infile) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
678 fprintf(stderr, "Failed to open %s for reading\n", argv[1]);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
679 return 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
680 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
681 FILE *outfile = strcmp("-", argv[2]) ? fopen(argv[2], "w") : stdout;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
682 if (!outfile) {
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
683 fprintf(stderr, "Failed to open %s for writing\n", argv[2]);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
684 return 1;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
685 }
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
686 int ret = assemble_file(infile, outfile);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
687 fclose(infile);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
688 fclose(outfile);
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
689 return ret;
74a6d629b78f Added assembler. Removed hand-assembled version of hello world example
Michael Pavone <pavone@retrodev.com>
parents:
diff changeset
690 }