1 |
3 |
riedelx |
/*******************************************
|
2 |
|
|
assem.c
|
3 |
|
|
an assembler for the TinyX CPU
|
4 |
|
|
TGB Ulrich Riedel 20040313
|
5 |
|
|
*******************************************/
|
6 |
|
|
|
7 |
|
|
#include
|
8 |
|
|
#include
|
9 |
|
|
#include
|
10 |
|
|
#include
|
11 |
|
|
|
12 |
|
|
typedef struct _tag_Tmcode {
|
13 |
|
|
struct _tag_Tmcode *prev;
|
14 |
|
|
struct _tag_Tmcode *next;
|
15 |
|
|
int linenumber;
|
16 |
|
|
unsigned long addr; // machinecode address
|
17 |
|
|
char label[34]; // destination label
|
18 |
|
|
char mnemo[16]; // mnemonic or directive
|
19 |
|
|
char operand1[80]; // operands
|
20 |
|
|
char operand2[80];
|
21 |
|
|
char operand3[80];
|
22 |
|
|
unsigned char mcod[128]; // machinecode ( maximum of 1024 bit instruction code )
|
23 |
|
|
unsigned char imm[128];
|
24 |
|
|
unsigned long oaddr1; // operand address1
|
25 |
|
|
unsigned long oaddr2; // operand address2
|
26 |
|
|
unsigned long oaddr3; // operand address2
|
27 |
|
|
char olabel1[34]; // operand label1
|
28 |
|
|
char olabel2[34]; // operand label2
|
29 |
|
|
char olabel3[34]; // operand label3
|
30 |
|
|
} Tmcode;
|
31 |
|
|
|
32 |
|
|
typedef struct {
|
33 |
|
|
unsigned long addr;
|
34 |
|
|
char label[40];
|
35 |
|
|
} Taddress;
|
36 |
|
|
|
37 |
|
|
int g_wordSize; // processor word size
|
38 |
|
|
|
39 |
|
|
char *getvalue(char *str, unsigned char *val); // reads string value
|
40 |
|
|
|
41 |
|
|
int main(int argc,char *argv[])
|
42 |
|
|
{
|
43 |
|
|
FILE *fp;
|
44 |
|
|
char filename[256];
|
45 |
|
|
unsigned char binTemp[128];
|
46 |
|
|
char line[80];
|
47 |
|
|
char tmpStr[40];
|
48 |
|
|
char *tempPtr;
|
49 |
|
|
int linenumber, idx, maxi, jdx, sdx;
|
50 |
|
|
unsigned short slen;
|
51 |
|
|
Tmcode *head, *tail, *cPtr, *hPtr, *tPtr;
|
52 |
|
|
unsigned long addr, val1, val2, val3;
|
53 |
|
|
unsigned char code[128], chksum, lsn, msn;
|
54 |
|
|
Taddress *address;
|
55 |
|
|
unsigned char ccMode;
|
56 |
|
|
unsigned char aluMode;
|
57 |
|
|
unsigned char updateFlag;
|
58 |
|
|
unsigned char carryUse;
|
59 |
|
|
unsigned char writeCycle;
|
60 |
|
|
unsigned char memRead;
|
61 |
|
|
unsigned char immediate;
|
62 |
|
|
unsigned char valmux;
|
63 |
|
|
unsigned char dstReg;
|
64 |
|
|
unsigned char src1Reg;
|
65 |
|
|
unsigned char src2Reg;
|
66 |
|
|
|
67 |
|
|
g_wordSize = 0;
|
68 |
|
|
|
69 |
|
|
if (argc == 1) {
|
70 |
|
|
fprintf(stderr, "usage: tinyx file\n");
|
71 |
|
|
return 1;
|
72 |
|
|
}
|
73 |
|
|
|
74 |
|
|
fp = fopen(argv[1], "r");
|
75 |
|
|
if(NULL == fp) {
|
76 |
|
|
fprintf(stderr, "%s doesn't exist\n", argv[1]);
|
77 |
|
|
return 2;
|
78 |
|
|
}
|
79 |
|
|
strncpy(filename, argv[1], 120);
|
80 |
|
|
strcat(filename, ".HEX");
|
81 |
|
|
|
82 |
|
|
printf("prepass\n");
|
83 |
|
|
/////////// pre pass /////////////////////////////////////
|
84 |
|
|
linenumber = 1; // sourcecode linenumber count
|
85 |
|
|
head = tail = NULL;
|
86 |
|
|
while(fgets(line, 79, fp)) {
|
87 |
|
|
if(line[0] == 0) { // empty line
|
88 |
|
|
linenumber++;
|
89 |
|
|
continue;
|
90 |
|
|
}
|
91 |
|
|
sdx = strlen(line);
|
92 |
|
|
for(idx=0; idx
|
93 |
|
|
if(!isspace(line[idx])) break;
|
94 |
|
|
}
|
95 |
|
|
if(sdx == idx) { // whitespace line
|
96 |
|
|
linenumber++;
|
97 |
|
|
continue;
|
98 |
|
|
}
|
99 |
|
|
///////// make line to uppercase characters, ignoring comment lines
|
100 |
|
|
for(idx=0; line[idx]; idx++) {
|
101 |
|
|
if(line[idx] == 13) { line[idx] = 0; continue; } // return
|
102 |
|
|
if(line[idx] == 10) { line[idx] = 0; continue; } // linefeed
|
103 |
|
|
if(line[idx] == 9) { line[idx] = 32; continue; } // tab
|
104 |
|
|
if((line[idx] & 0xE0) == 0) {
|
105 |
|
|
fprintf(stderr, "%d contains non printable characters.\n", linenumber);
|
106 |
|
|
return 3;
|
107 |
|
|
}
|
108 |
|
|
if(line[idx] < 0) {
|
109 |
|
|
fprintf(stderr, "%d contains non printable characters\n", linenumber);
|
110 |
|
|
return 3;
|
111 |
|
|
}
|
112 |
|
|
line[idx] = toupper(line[idx]);
|
113 |
|
|
}
|
114 |
|
|
if(line[0] == ';') { linenumber++; continue; } // skip comment lines
|
115 |
|
|
if(line[0] == '.') {
|
116 |
|
|
fprintf(stderr, "%d no directive first allowed\n", linenumber);
|
117 |
|
|
linenumber++;
|
118 |
|
|
continue;
|
119 |
|
|
}
|
120 |
|
|
///////// break into up to 5 components //////////////////
|
121 |
|
|
//////// alloc mcode structure for this sourcecode line
|
122 |
|
|
hPtr = (Tmcode *) malloc(sizeof(Tmcode));
|
123 |
|
|
memset(hPtr, 0, sizeof(Tmcode));
|
124 |
|
|
if(head == NULL) {
|
125 |
|
|
head = hPtr;
|
126 |
|
|
tail = hPtr;
|
127 |
|
|
cPtr = head;
|
128 |
|
|
} else {
|
129 |
|
|
tPtr = cPtr;
|
130 |
|
|
cPtr->next = hPtr;
|
131 |
|
|
cPtr = cPtr->next;
|
132 |
|
|
cPtr->prev = tPtr;
|
133 |
|
|
tail = cPtr;
|
134 |
|
|
}
|
135 |
|
|
hPtr->linenumber = linenumber;
|
136 |
|
|
///////// 1st component, label ///////////////////////////
|
137 |
|
|
idx = 0; // start at beginning sourcecode line
|
138 |
|
|
if(!isspace(line[0])) { // first char nonspace?
|
139 |
|
|
for(; line[idx] && (idx<32); idx++) { // label max 32 chars
|
140 |
|
|
if(isspace(line[idx])) break; // delimiter
|
141 |
|
|
if(line[idx] == ';') break; // comment
|
142 |
|
|
tmpStr[idx] = line[idx];
|
143 |
|
|
}
|
144 |
|
|
tmpStr[idx] = 0;
|
145 |
|
|
strcpy(hPtr->label, tmpStr); // save label
|
146 |
|
|
}
|
147 |
|
|
if(0 == line[idx]) { // end of line?, label only
|
148 |
|
|
linenumber++;
|
149 |
|
|
continue;
|
150 |
|
|
}
|
151 |
|
|
///////// 2nd component, mnemonic or directive ///////////
|
152 |
|
|
while(isspace(line[idx])) idx++; // skip space
|
153 |
|
|
for(jdx=0; line[idx] && (jdx<15); jdx++) {
|
154 |
|
|
if(isspace(line[idx])) break; // delimiter
|
155 |
|
|
if(line[idx] == ';') break; // comment
|
156 |
|
|
tmpStr[jdx] = line[idx++];
|
157 |
|
|
}
|
158 |
|
|
tmpStr[jdx] = 0;
|
159 |
|
|
strcpy(hPtr->mnemo, tmpStr); // save mnemonic or directive
|
160 |
|
|
if(0 == line[idx]) { // suddenly end of line?
|
161 |
|
|
fprintf(stderr, "%d operand missing\n", linenumber);
|
162 |
|
|
linenumber++;
|
163 |
|
|
continue;
|
164 |
|
|
}
|
165 |
|
|
while(isspace(line[idx])) idx++; // skip space
|
166 |
|
|
if(0 == line[idx]) { // suddenly end of line?
|
167 |
|
|
fprintf(stderr, "%d operand missing\n", linenumber);
|
168 |
|
|
linenumber++;
|
169 |
|
|
continue;
|
170 |
|
|
}
|
171 |
|
|
///////// 3,4,5th component, operands /////////////////////////
|
172 |
|
|
//// fetch operads strings
|
173 |
|
|
for(jdx=0; line[idx] && (jdx<80); jdx++) {
|
174 |
|
|
tmpStr[jdx] = line[idx++];
|
175 |
|
|
}
|
176 |
|
|
tmpStr[jdx] = 0;
|
177 |
|
|
sdx = jdx;
|
178 |
|
|
jdx = 0;
|
179 |
|
|
//// remove spaces between operands
|
180 |
|
|
for(idx=0; idx
|
181 |
|
|
if(isspace(tmpStr[idx])) continue;
|
182 |
|
|
if(tmpStr[idx] == ';') break; // comment
|
183 |
|
|
tmpStr[jdx++] = tmpStr[idx];
|
184 |
|
|
}
|
185 |
|
|
tmpStr[jdx] = 0;
|
186 |
|
|
hPtr->operand1[0] = 0;
|
187 |
|
|
hPtr->operand2[0] = 0;
|
188 |
|
|
hPtr->operand3[0] = 0;
|
189 |
|
|
idx = 0;
|
190 |
|
|
for(jdx=0; tmpStr[idx] && jdx<70; jdx++) {
|
191 |
|
|
if(tmpStr[idx] == 0) break;
|
192 |
|
|
if(tmpStr[idx] == ',') break;
|
193 |
|
|
hPtr->operand1[jdx] = tmpStr[idx++];
|
194 |
|
|
}
|
195 |
|
|
hPtr->operand1[jdx] = 0;
|
196 |
|
|
if(tmpStr[idx]) {
|
197 |
|
|
idx++;
|
198 |
|
|
for(jdx=0; tmpStr[idx] && jdx<70; jdx++) {
|
199 |
|
|
if(tmpStr[idx] == 0) break;
|
200 |
|
|
if(tmpStr[idx] == ',') break;
|
201 |
|
|
hPtr->operand2[jdx] = tmpStr[idx++];
|
202 |
|
|
}
|
203 |
|
|
hPtr->operand2[jdx] = 0;
|
204 |
|
|
if(tmpStr[idx]) {
|
205 |
|
|
idx++;
|
206 |
|
|
for(jdx=0; tmpStr[idx] && jdx<70; jdx++) {
|
207 |
|
|
if(tmpStr[idx] == 0) break;
|
208 |
|
|
if(tmpStr[idx] == ',') break;
|
209 |
|
|
hPtr->operand3[jdx] = tmpStr[idx++];
|
210 |
|
|
}
|
211 |
|
|
hPtr->operand3[jdx] = 0;
|
212 |
|
|
}
|
213 |
|
|
}
|
214 |
|
|
hPtr->linenumber = linenumber;
|
215 |
|
|
linenumber++;
|
216 |
|
|
}
|
217 |
|
|
fclose(fp);
|
218 |
|
|
|
219 |
|
|
#if 0
|
220 |
|
|
///////////////// test output //////////////////////////////////
|
221 |
|
|
hPtr = head;
|
222 |
|
|
while(hPtr) {
|
223 |
|
|
printf("%d <%s><%s><%s><%s><%s>\n", hPtr->linenumber,
|
224 |
|
|
hPtr->label,
|
225 |
|
|
hPtr->mnemo,
|
226 |
|
|
hPtr->operand1,
|
227 |
|
|
hPtr->operand2,
|
228 |
|
|
hPtr->operand3);
|
229 |
|
|
hPtr = hPtr->next;
|
230 |
|
|
}
|
231 |
|
|
#endif
|
232 |
|
|
|
233 |
|
|
printf("1st pass\n");
|
234 |
|
|
/////////// 1st pass ////////////////////////////////////
|
235 |
|
|
addr = 0;
|
236 |
|
|
hPtr = head;
|
237 |
|
|
while(hPtr) {
|
238 |
|
|
hPtr->addr = addr;
|
239 |
|
|
if(!strlen(hPtr->mnemo)) { // label only
|
240 |
|
|
hPtr = hPtr->next;
|
241 |
|
|
continue;
|
242 |
|
|
}
|
243 |
|
|
///////// check on directives ///////////////////////////
|
244 |
|
|
if(!strcmp(hPtr->mnemo, ".WORDSIZE")) { // set processor wordsize
|
245 |
|
|
if(g_wordSize) {
|
246 |
|
|
fprintf(stderr, "processor wordsize already set!\n");
|
247 |
|
|
return 5;
|
248 |
|
|
}
|
249 |
|
|
g_wordSize = atoi(hPtr->operand1);
|
250 |
|
|
if(g_wordSize < 32) {
|
251 |
|
|
fprintf(stderr, "wordsize at least of 32 and multiple of 8 needed!\n");
|
252 |
|
|
return 6;
|
253 |
|
|
}
|
254 |
|
|
if(g_wordSize & 7) {
|
255 |
|
|
fprintf(stderr, "wordsize at least of 32 and multiple of 8 needed!\n");
|
256 |
|
|
return 7;
|
257 |
|
|
}
|
258 |
|
|
hPtr->linenumber = -1;
|
259 |
|
|
hPtr = hPtr->next;
|
260 |
|
|
continue;
|
261 |
|
|
}
|
262 |
|
|
if(g_wordSize == 0) {
|
263 |
|
|
fprintf(stderr, "missing, wordsize at least of 32 and multiple of 8 needed!\n");
|
264 |
|
|
return 8;
|
265 |
|
|
}
|
266 |
|
|
if(!strcmp(hPtr->mnemo, ".ORG")) { // set location address
|
267 |
|
|
addr = strtol(hPtr->operand1, &tempPtr, 16);
|
268 |
|
|
hPtr->addr = addr;
|
269 |
|
|
hPtr->linenumber = -1;
|
270 |
|
|
hPtr = hPtr->next;
|
271 |
|
|
continue;
|
272 |
|
|
}
|
273 |
|
|
if(!strcmp(hPtr->mnemo, ".DC")) { // define constant
|
274 |
|
|
getvalue(hPtr->operand1, binTemp);
|
275 |
|
|
idx = g_wordSize / 8;
|
276 |
|
|
memset(hPtr->mcod, 0, sizeof(hPtr->mcod));
|
277 |
|
|
memcpy(hPtr->mcod, &binTemp[128-idx], idx);
|
278 |
|
|
hPtr = hPtr->next;
|
279 |
|
|
addr++;
|
280 |
|
|
continue;
|
281 |
|
|
}
|
282 |
|
|
ccMode = 16;
|
283 |
|
|
aluMode = 16;
|
284 |
|
|
updateFlag = 0;
|
285 |
|
|
carryUse = 0;
|
286 |
|
|
writeCycle = 0;
|
287 |
|
|
memRead = 0;
|
288 |
|
|
immediate = 0;
|
289 |
|
|
valmux = 0;
|
290 |
|
|
dstReg = 0;
|
291 |
|
|
src1Reg = 0;
|
292 |
|
|
src2Reg = 0;
|
293 |
|
|
sdx = 0;
|
294 |
|
|
if(!memcmp(&hPtr->mnemo[sdx], "U", 1)) { // update flag after alu operation ?
|
295 |
|
|
updateFlag = 1;
|
296 |
|
|
sdx++;
|
297 |
|
|
}
|
298 |
|
|
////// scan condition code
|
299 |
|
|
if(!memcmp(&hPtr->mnemo[sdx], "A", 1)) { // always
|
300 |
|
|
ccMode = 0; sdx++;
|
301 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "CC", 2)) { // carry clear
|
302 |
|
|
ccMode = 1; sdx += 2;
|
303 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "CS", 2)) { // carry set
|
304 |
|
|
ccMode = 2; sdx += 2;
|
305 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "EQ", 2)) { // equal
|
306 |
|
|
ccMode = 3; sdx += 2;
|
307 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "GE", 2)) { // greater equal
|
308 |
|
|
ccMode = 4; sdx += 2;
|
309 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "GT", 2)) { // greater than
|
310 |
|
|
ccMode = 5; sdx += 2;
|
311 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "HI", 2)) { // higher
|
312 |
|
|
ccMode = 6; sdx += 2;
|
313 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "LE", 2)) { // less equal
|
314 |
|
|
ccMode = 7; sdx += 2;
|
315 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "LS", 2)) { // less
|
316 |
|
|
ccMode = 8; sdx += 2;
|
317 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "LT", 2)) { // less than
|
318 |
|
|
ccMode = 9; sdx += 2;
|
319 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "MI", 2)) { // minus
|
320 |
|
|
ccMode = 10; sdx += 2;
|
321 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "NE", 2)) { // not equal
|
322 |
|
|
ccMode = 11; sdx += 2;
|
323 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "PL", 2)) { // plus
|
324 |
|
|
ccMode = 12; sdx += 2;
|
325 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "VC", 2)) { // overflow clear
|
326 |
|
|
ccMode = 13; sdx += 2;
|
327 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "VS", 2)) { // overflow set
|
328 |
|
|
ccMode = 14; sdx += 2;
|
329 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "N", 1)) { // never
|
330 |
|
|
ccMode = 15; sdx++;
|
331 |
|
|
}
|
332 |
|
|
////// scan alu mode
|
333 |
|
|
if(!memcmp(&hPtr->mnemo[sdx], "MOV", 3)) { // mov
|
334 |
|
|
aluMode = 0;
|
335 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "AND", 3)) { // and
|
336 |
|
|
aluMode = 1;
|
337 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "OR", 2)) { // or
|
338 |
|
|
aluMode = 2;
|
339 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "XOR", 3)) { // xor
|
340 |
|
|
aluMode = 3;
|
341 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "ADD", 3)) { // add
|
342 |
|
|
aluMode = 4;
|
343 |
|
|
if(hPtr->mnemo[sdx+3] == 'C') carryUse = 1;
|
344 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "SUB", 3)) { // sub
|
345 |
|
|
aluMode = 5;
|
346 |
|
|
if(hPtr->mnemo[sdx+3] == 'C') carryUse = 1;
|
347 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "ROR", 3)) { // ror
|
348 |
|
|
aluMode = 6;
|
349 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "LSR", 3)) { // lsr
|
350 |
|
|
aluMode = 7;
|
351 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "LSRA", 4)) { // lsra
|
352 |
|
|
aluMode = 8;
|
353 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "SWAP", 4)) { // swap
|
354 |
|
|
aluMode = 9;
|
355 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "SWAPB", 5)) {// swapb
|
356 |
|
|
aluMode = 10;
|
357 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "INC", 3)) { // inc
|
358 |
|
|
aluMode = 11;
|
359 |
|
|
if(hPtr->mnemo[sdx+3] == 'C') carryUse = 1;
|
360 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "DEC", 3)) { // dec
|
361 |
|
|
aluMode = 12;
|
362 |
|
|
if(hPtr->mnemo[sdx+3] == 'C') carryUse = 1;
|
363 |
|
|
} else if(!memcmp(&hPtr->mnemo[sdx], "RORB", 4)) { // rorb
|
364 |
|
|
aluMode = 13;
|
365 |
|
|
}
|
366 |
|
|
////////////// destination operand
|
367 |
|
|
if(hPtr->operand1[0] == 0) {
|
368 |
|
|
hPtr = hPtr->next; // goto next line
|
369 |
|
|
fprintf(stderr, "%d destination operand missing\n", hPtr->linenumber);
|
370 |
|
|
continue;
|
371 |
|
|
}
|
372 |
|
|
sdx = 0;
|
373 |
|
|
if(hPtr->operand1[0] == '[') {
|
374 |
|
|
sdx++;
|
375 |
|
|
writeCycle = 1;
|
376 |
|
|
}
|
377 |
|
|
if(hPtr->operand1[sdx] != 'R') {
|
378 |
|
|
fprintf(stderr, "%d destination operand error\n", hPtr->linenumber);
|
379 |
|
|
} else {
|
380 |
|
|
if(!isdigit(hPtr->operand1[sdx+1])) {
|
381 |
|
|
fprintf(stderr, "%d destination operand number error\n", hPtr->linenumber);
|
382 |
|
|
} else {
|
383 |
|
|
dstReg = hPtr->operand1[sdx+1] - '0';
|
384 |
|
|
}
|
385 |
|
|
}
|
386 |
|
|
src1Reg = dstReg; // set default register
|
387 |
|
|
src2Reg = dstReg; // set default register, improve to opcode kontext register
|
388 |
|
|
//////////// source1 operand
|
389 |
|
|
if(hPtr->operand2[0]) {
|
390 |
|
|
sdx = 0;
|
391 |
|
|
if(hPtr->operand2[0] == '[') {
|
392 |
|
|
if(writeCycle) {
|
393 |
|
|
hPtr = hPtr->next; // goto next line
|
394 |
|
|
fprintf(stderr, "%d both memory accesses not supported\n", hPtr->linenumber);
|
395 |
|
|
continue;
|
396 |
|
|
}
|
397 |
|
|
sdx++;
|
398 |
|
|
memRead = 1;
|
399 |
|
|
}
|
400 |
|
|
if(hPtr->operand2[sdx] != 'R') { // immediate
|
401 |
|
|
if((hPtr->operand2[0] == '$') || isdigit(hPtr->operand2[0])) {
|
402 |
|
|
getvalue(hPtr->operand2, binTemp);
|
403 |
|
|
memcpy(hPtr->imm, &binTemp[128-g_wordSize/8], g_wordSize/8);
|
404 |
|
|
immediate = 1;
|
405 |
|
|
} else { // label
|
406 |
|
|
strcpy(hPtr->olabel2, hPtr->operand2);
|
407 |
|
|
}
|
408 |
|
|
} else {
|
409 |
|
|
if(!isdigit(hPtr->operand2[sdx+1])) {
|
410 |
|
|
fprintf(stderr, "%d source1 operand number error\n", hPtr->linenumber);
|
411 |
|
|
} else {
|
412 |
|
|
src1Reg = hPtr->operand2[sdx+1] - '0';
|
413 |
|
|
if(writeCycle) {
|
414 |
|
|
src2Reg = dstReg;
|
415 |
|
|
}
|
416 |
|
|
}
|
417 |
|
|
}
|
418 |
|
|
///////// source2 operand
|
419 |
|
|
if(hPtr->operand3[0] == 0) {
|
420 |
|
|
if(writeCycle == 0) {
|
421 |
|
|
src2Reg = src1Reg;
|
422 |
|
|
}
|
423 |
|
|
} else {
|
424 |
|
|
if(hPtr->operand3[0] != 'R') {
|
425 |
|
|
fprintf(stderr, "%d source2 operand number error\n", hPtr->linenumber);
|
426 |
|
|
continue;
|
427 |
|
|
} else {
|
428 |
|
|
if(!isdigit(hPtr->operand3[1])) {
|
429 |
|
|
fprintf(stderr, "%d source2 operand number error\n", hPtr->linenumber);
|
430 |
|
|
} else {
|
431 |
|
|
src2Reg = hPtr->operand3[1] - '0';
|
432 |
|
|
}
|
433 |
|
|
}
|
434 |
|
|
}
|
435 |
|
|
} // if(hPtr->operand2[0] == 0)
|
436 |
|
|
///////// build machine code
|
437 |
|
|
memset(hPtr->mcod, 0, sizeof(hPtr->mcod));
|
438 |
|
|
hPtr->mcod[0] = (ccMode << 4) | aluMode;
|
439 |
|
|
hPtr->mcod[1] = (memRead << 7) | (dstReg << 4) | (writeCycle << 3) | src1Reg;
|
440 |
|
|
hPtr->mcod[2] = (immediate << 7) | (src2Reg << 4) | (updateFlag << 3) | (carryUse << 2);
|
441 |
|
|
idx = g_wordSize / 8;
|
442 |
|
|
memcpy(&hPtr->mcod[3], &hPtr->imm[3], idx-3);
|
443 |
|
|
addr++; // goto next program address
|
444 |
|
|
hPtr = hPtr->next; // goto next line
|
445 |
|
|
}
|
446 |
|
|
/////////// count label addresses ///////////////////////
|
447 |
|
|
hPtr = head;
|
448 |
|
|
maxi = 0;
|
449 |
|
|
while(hPtr) {
|
450 |
|
|
if(hPtr->label[0]) maxi++;
|
451 |
|
|
hPtr = hPtr->next;
|
452 |
|
|
}
|
453 |
|
|
/////////// table with label address ////////////////////
|
454 |
|
|
address = (Taddress *) malloc(maxi * sizeof(Taddress));
|
455 |
|
|
hPtr = head;
|
456 |
|
|
idx = 0;
|
457 |
|
|
while(hPtr) {
|
458 |
|
|
if(hPtr->label[0]) {
|
459 |
|
|
address[idx].addr = hPtr->addr;
|
460 |
|
|
strcpy(address[idx].label, hPtr->label);
|
461 |
|
|
idx++;
|
462 |
|
|
}
|
463 |
|
|
hPtr = hPtr->next;
|
464 |
|
|
}
|
465 |
|
|
|
466 |
|
|
printf("2nd pass\n");
|
467 |
|
|
/////////// 2nd pass ////////////////////////////////////
|
468 |
|
|
hPtr = head;
|
469 |
|
|
while(hPtr) {
|
470 |
|
|
if(hPtr->olabel2[0]) { // resolve label, treated as immediate operand
|
471 |
|
|
for(idx=0; idx
|
472 |
|
|
if(!strcmp(address[idx].label, hPtr->olabel2)) {
|
473 |
|
|
hPtr->mcod[2] |= 0x80; // set immediate operand flag
|
474 |
|
|
jdx = g_wordSize / 8;
|
475 |
|
|
switch(jdx) {
|
476 |
|
|
case 4:
|
477 |
|
|
hPtr->mcod[3] = (unsigned char) address[idx].addr;
|
478 |
|
|
break;
|
479 |
|
|
case 5:
|
480 |
|
|
hPtr->mcod[3] = (unsigned char) (address[idx].addr >> 8);
|
481 |
|
|
hPtr->mcod[4] = (unsigned char) address[idx].addr;
|
482 |
|
|
break;
|
483 |
|
|
case 6:
|
484 |
|
|
hPtr->mcod[3] = (unsigned char) (address[idx].addr >> 16);
|
485 |
|
|
hPtr->mcod[4] = (unsigned char) (address[idx].addr >> 8);
|
486 |
|
|
hPtr->mcod[5] = (unsigned char) address[idx].addr;
|
487 |
|
|
break;
|
488 |
|
|
default:
|
489 |
|
|
jdx -= 4;
|
490 |
|
|
hPtr->mcod[jdx++] = (unsigned char) (address[idx].addr >> 24);
|
491 |
|
|
hPtr->mcod[jdx++] = (unsigned char) (address[idx].addr >> 16);
|
492 |
|
|
hPtr->mcod[jdx++] = (unsigned char) (address[idx].addr >> 8);
|
493 |
|
|
hPtr->mcod[jdx++] = (unsigned char) address[idx].addr;
|
494 |
|
|
}
|
495 |
|
|
break;
|
496 |
|
|
}
|
497 |
|
|
}
|
498 |
|
|
if(idx == maxi) {
|
499 |
|
|
fprintf(stderr, "%d unknown label\n", hPtr->linenumber);
|
500 |
|
|
}
|
501 |
|
|
}
|
502 |
|
|
hPtr = hPtr->next;
|
503 |
|
|
}
|
504 |
|
|
|
505 |
|
|
////////// output ///////////////////////////////////////
|
506 |
|
|
fp = fopen(filename, "w"); // write into Intel HEX file
|
507 |
|
|
if(NULL == fp) {
|
508 |
|
|
fprintf(stderr, "can't write to %s\n", filename);
|
509 |
|
|
return 0;
|
510 |
|
|
}
|
511 |
|
|
hPtr = head;
|
512 |
|
|
maxi = g_wordSize / 8;
|
513 |
|
|
while(hPtr) {
|
514 |
|
|
if(hPtr->linenumber < 0) {
|
515 |
|
|
hPtr = hPtr->next;
|
516 |
|
|
continue;
|
517 |
|
|
}
|
518 |
|
|
/*
|
519 |
|
|
printf("%04X ", hPtr->addr);
|
520 |
|
|
for(idx=0; idxmcod[idx]);
|
521 |
|
|
printf("<%s><%s><%s><%s><%s>\n", hPtr->label, hPtr->mnemo, hPtr->operand1, hPtr->operand2, hPtr->operand3);
|
522 |
|
|
*/
|
523 |
|
|
|
524 |
|
|
if(maxi) {
|
525 |
|
|
sprintf(line, ":%02X%04X00", maxi, hPtr->addr);
|
526 |
|
|
for(idx=0; idx
|
527 |
|
|
sprintf(tmpStr, "%02X", hPtr->mcod[idx]);
|
528 |
|
|
strcat(line, tmpStr);
|
529 |
|
|
}
|
530 |
|
|
chksum = 0;
|
531 |
|
|
for(idx=1; line[idx]; idx += 2) {
|
532 |
|
|
msn = line[idx] - '0';
|
533 |
|
|
if(msn > 9) msn -= 7;
|
534 |
|
|
lsn = line[idx+1] - '0';
|
535 |
|
|
if(lsn > 9) lsn -= 7;
|
536 |
|
|
chksum += ((msn<<4) + lsn);
|
537 |
|
|
}
|
538 |
|
|
chksum = 256 - chksum;
|
539 |
|
|
sprintf(tmpStr, "%02X", chksum);
|
540 |
|
|
strcat(line, tmpStr);
|
541 |
|
|
fprintf(fp, "%s\015\012", line);
|
542 |
|
|
}
|
543 |
|
|
hPtr = hPtr->next;
|
544 |
|
|
}
|
545 |
|
|
fprintf(fp, ":00000001FF\015\012"); // end of HEX file
|
546 |
|
|
fclose(fp);
|
547 |
|
|
return 0;
|
548 |
|
|
}
|
549 |
|
|
|
550 |
|
|
////////// gets a decimal or hexadecimal value
|
551 |
|
|
// decimal is ddd
|
552 |
|
|
// hexadecimal is $hhh
|
553 |
|
|
// returns ptr after value
|
554 |
|
|
char *getvalue(char *str, unsigned char *val)
|
555 |
|
|
{
|
556 |
|
|
int idx, jdx, kdx, radix, cy;
|
557 |
|
|
unsigned short temp[128];
|
558 |
|
|
unsigned short help[128];
|
559 |
|
|
|
560 |
|
|
memset(temp, 0, sizeof(temp));
|
561 |
|
|
memset(help, 0, sizeof(help));
|
562 |
|
|
radix = 10;
|
563 |
|
|
if(str[0] == '$') radix = 16;
|
564 |
|
|
if(radix == 10) {
|
565 |
|
|
for(idx=0; str[idx]; idx++) {
|
566 |
|
|
if(!isdigit(str[idx])) break;
|
567 |
|
|
cy = 0;
|
568 |
|
|
for(jdx=127; jdx >=0; jdx--) { // shift left
|
569 |
|
|
temp[jdx] <<= 1;
|
570 |
|
|
if(cy) temp[jdx]++;
|
571 |
|
|
cy = 0;
|
572 |
|
|
if(temp[jdx] > 255) {
|
573 |
|
|
cy++;
|
574 |
|
|
temp[jdx] &= 255;
|
575 |
|
|
}
|
576 |
|
|
}
|
577 |
|
|
memcpy(help, temp, sizeof(help));
|
578 |
|
|
for(kdx=0; kdx<2; kdx++) {
|
579 |
|
|
cy = 0;
|
580 |
|
|
for(jdx=127; jdx >=0; jdx--) { // shift left
|
581 |
|
|
temp[jdx] <<= 1;
|
582 |
|
|
if(cy) temp[jdx]++;
|
583 |
|
|
cy = 0;
|
584 |
|
|
if(temp[jdx] > 255) {
|
585 |
|
|
cy++;
|
586 |
|
|
temp[jdx] &= 255;
|
587 |
|
|
}
|
588 |
|
|
}
|
589 |
|
|
}
|
590 |
|
|
cy = 0;
|
591 |
|
|
for(jdx=127; jdx >=0; jdx--) { // add
|
592 |
|
|
temp[jdx] += help[jdx];
|
593 |
|
|
if(cy) temp[jdx]++;
|
594 |
|
|
cy = 0;
|
595 |
|
|
if(temp[jdx] > 255) {
|
596 |
|
|
cy++;
|
597 |
|
|
temp[jdx] &= 255;
|
598 |
|
|
}
|
599 |
|
|
}
|
600 |
|
|
temp[127] += (str[idx] - '0');
|
601 |
|
|
cy = 0;
|
602 |
|
|
if(temp[127] > 255) {
|
603 |
|
|
cy++;
|
604 |
|
|
temp[127] &= 255;
|
605 |
|
|
}
|
606 |
|
|
for(jdx=126; jdx >=0; jdx--) {
|
607 |
|
|
temp[jdx] += cy;
|
608 |
|
|
cy = 0;
|
609 |
|
|
if(temp[jdx] > 255) {
|
610 |
|
|
cy++;
|
611 |
|
|
temp[jdx] &= 255;
|
612 |
|
|
}
|
613 |
|
|
}
|
614 |
|
|
} // end for
|
615 |
|
|
} else {
|
616 |
|
|
for(idx=1; str[idx]; idx++) {
|
617 |
|
|
if(!isxdigit(str[idx])) break;
|
618 |
|
|
for(jdx=0; jdx<127; jdx++) { // shift 4 bits left
|
619 |
|
|
temp[jdx] <<= 4;
|
620 |
|
|
temp[jdx] |= (15 & (temp[jdx+1] >> 4));
|
621 |
|
|
}
|
622 |
|
|
temp[127] <<= 4;
|
623 |
|
|
jdx = str[idx] - '0';
|
624 |
|
|
if(jdx > 9) jdx -= 7;
|
625 |
|
|
temp[127] |= jdx;
|
626 |
|
|
} // end for
|
627 |
|
|
}
|
628 |
|
|
for(idx=128-(g_wordSize/8); idx<128; idx++) {
|
629 |
|
|
val[idx] = temp[idx];
|
630 |
|
|
}
|
631 |
|
|
return &str[idx];
|
632 |
|
|
}
|