|
|
1.1 root 1:
2: #include <assert.h>
3: #include <stdio.h>
4: #include <stdlib.h>
5: #include <string.h>
6: #include <ctype.h>
7: #include <stdarg.h>
8: #include "dict.h"
9:
10: #define LAB_LEN 32
11: #define BASE 0x1c
12: FILE *fin;
13: FILE *fout;
14: char buf[4096];
15: Dict labels;
16: int dump_labels = 0;
17: int line_no = 0;
18: int last_op_addr;
19: enum SIZE { BYTE, WORD, LONG, LONG_FIXUP };
20:
21: /* to convert weird move sizes to standard sizes */
22: const int move_size[4] = { 1, 3, 2, 0 };
23: const char *Bcc_str[16] = {
24: "ra",NULL,"hi","ls","cc","cs","ne","eq",
25: "vc","vs","pl","mi","ge","lt","gt","le"
26: };
27: const char *DBcc_str[16] = {
28: "t","f","hi","ls","cc","cs","ne","eq",
29: "vc","vs","pl","mi","ge","lt","gt","le"
30: };
31:
32: #define check(ch) do { \
33: if (*pos != (ch)) error ("Expected '%c'", ch); \
34: pos++; \
35: } while (0);
36: #define check_whitespace() do { \
37: if (!isspace (*pos)) error ("Line malformed."); \
38: while (isspace (*pos)) pos++; \
39: } while (0);
40:
41: #define get_bitpos() ((int)ftell (fout))
42: #define set_bitpos(pos) (fseek (fout,pos,SEEK_SET))
43:
44: #define F_DREG (1<<0)
45: #define F_AREG (1<<1)
46: #define F_IND (1<<2)
47: #define F_POST (1<<3)
48: #define F_PRE (1<<4)
49: #define F_OFFSET (1<<5)
50: #define F_INDEX (1<<6)
51: #define F_MEM_W (1<<7)
52: #define F_MEM_L (1<<8)
53: #define F_IMM (1<<9)
54: #define F_PC_OFFSET (1<<10)
55: #define F_PC_INDEX (1<<11)
56:
57: #define F_NOLABELS (1<<12)
58:
59: #define F_NOIMM_NOPC_NOAREG (F_DREG | F_IND | F_POST | F_PRE | \
60: F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L)
61: #define F_ALL (0xffffffff & (~(F_NOLABELS)))
62: #define F_ALL_NOAREG (F_ALL & (~F_AREG))
63:
64: typedef union Opcode {
65: unsigned short code;
66: struct move {
67: uint src_reg : 3;
68: uint src_mode : 3;
69: uint dest_mode : 3;
70: uint dest_reg : 3;
71: uint size : 2;
72: uint op : 2;
73: } move;
74: struct adr_index {
75: int displacement : 8;
76: uint zeros : 3;
77: uint ind_size : 1;
78: uint reg : 3;
79: uint reg_type : 1;
80: } adr_index;
81: struct addq {
82: uint dest_reg : 3;
83: uint dest_mode : 3;
84: uint size : 2;
85: uint issub : 1;
86: uint data : 3;
87: uint op : 4;
88: } addq;
89: struct jmp {
90: uint dest_reg : 3;
91: uint dest_mode : 3;
92: uint op : 10;
93: } jmp;
94: struct addi {
95: uint dest_reg : 3;
96: uint dest_mode : 3;
97: uint size : 2;
98: uint OP6 : 8;
99: } addi;
100: /* size and effective address */
101: struct type1 {
102: uint ea_reg : 3;
103: uint ea_mode : 3;
104: uint size : 2;
105: uint op : 8;
106: } type1;
107: /* reg, opmode, ea */
108: struct type2 {
109: uint ea_reg : 3;
110: uint ea_mode : 3;
111: uint op_mode : 3;
112: uint reg : 3;
113: uint op : 4;
114: } type2;
115: struct MemShift {
116: uint ea_reg : 3;
117: uint ea_mode : 3;
118: uint OP3 : 2;
119: uint dr : 1;
120: uint type : 2;
121: uint OP0x1c : 5;
122: } MemShift;
123: struct ASx {
124: uint reg : 3;
125: uint OP0 : 2;
126: uint ir : 1;
127: uint size : 2;
128: uint dr : 1;
129: uint count_reg : 3;
130: uint OP0xe : 4;
131: } ASx;
132: struct abcd {
133: uint src_reg : 3;
134: uint rm : 1;
135: uint OP16 : 5;
136: uint dest_reg : 3;
137: uint OP12 : 4;
138: } abcd;
139: struct addx {
140: uint src_reg : 3;
141: uint rm : 1;
142: uint OP0 : 2;
143: uint size : 2;
144: uint OP1 : 1;
145: uint dest_reg : 3;
146: uint op : 4;
147: } addx;
148: struct cmpm {
149: uint src_reg : 3;
150: uint OP1_1 : 3;
151: uint size : 2;
152: uint OP2_1 : 1;
153: uint dest_reg : 3;
154: uint OP0xb : 4;
155: } cmpm;
156: /* branches */
157: struct DBcc {
158: uint reg : 3;
159: uint OP25 : 5;
160: uint cond : 4;
161: uint OP5 : 4;
162: } DBcc;
163: struct Bcc {
164: int displacement : 8;
165: uint cond : 4;
166: uint op : 4;
167: } Bcc;
168: struct bra {
169: int displacement : 8;
170: uint op : 8;
171: } bra;
172: struct movem {
173: uint dest_reg : 3;
174: uint dest_mode : 3;
175: uint sz : 1;
176: uint ONE : 3;
177: uint dr : 1;
178: uint NINE : 5;
179: } movem;
180: struct lea {
181: uint dest_reg : 3;
182: uint dest_mode : 3;
183: uint SEVEN : 3;
184: uint reg : 3;
185: uint FOUR : 4;
186: } lea;
187: struct moveq {
188: int data : 8;
189: uint ZERO : 1;
190: uint reg : 3;
191: uint SEVEN : 4;
192: } moveq;
193: struct exg {
194: uint dest_reg : 3;
195: uint op_mode : 5;
196: uint OP1 : 1;
197: uint src_reg : 3;
198: uint OP0xc : 4;
199: } exg;
200: } Opcode;
201:
202: struct Fixup {
203: int rel_to;
204: int line_no;
205: int size;
206: int adr;
207: char label[LAB_LEN];
208: struct Fixup *next;
209: };
210:
211: struct Label {
212: const char *name;
213: int val;
214: enum LAB_TYPE {
215: L_ADDR,
216: L_CONST
217: } type;
218: };
219:
220: struct ImmVal {
221: int has_label;
222: char label[LAB_LEN];
223: int val;
224: };
225:
226: struct Fixup *fix_first = NULL;
227: struct Fixup *fix_last = NULL;
228: void add_fixup (int adr, int size, const char *label)
229: {
230: struct Fixup *fix = malloc (sizeof (struct Fixup));
231: fix->adr = adr;
232: fix->size = size;
233: fix->next = NULL;
234: fix->rel_to = (last_op_addr + 2) - BASE;
235: fix->line_no = line_no;
236: strcpy (fix->label, label);
237: if (fix_first == NULL) fix_first = fix;
238: if (fix_last == NULL) fix_last = fix;
239: else {
240: fix_last->next = fix;
241: fix_last = fix;
242: }
243: }
244:
245: void error (const char *format, ...)
246: {
247: va_list argptr;
248:
249: printf ("Error at line %d: ", line_no);
250: va_start (argptr, format);
251: vprintf (format, argptr);
252: va_end (argptr);
253: printf ("\n");
254:
255: fclose (fout);
256: remove ("aout.prg");
257: exit (0);
258: }
259:
260: void add_label (const char *name, int type, int val)
261: {
262: struct Label *lab = malloc (sizeof (struct Label));
263: if (dict_get (&labels, name)) error ("Label %s redefined.", name);
264: lab->val = val;
265: lab->type = type;
266: dict_set (&labels, name, lab);
267: }
268:
269: struct Label *get_label (const char *name)
270: {
271: struct Label *lab;
272: struct Node *n = dict_get (&labels, name);
273:
274: if (n == NULL) return NULL;
275: lab = n->obj;
276: lab->name = n->key;
277: return lab;
278: }
279:
280: void wr_byte(unsigned char x)
281: {
282: fputc (x, fout);
283: }
284:
285: void wr_short(short x)
286: {
287: wr_byte((unsigned char)((x>>8) & 0xff));
288: wr_byte((unsigned char)(x & 0xff));
289: }
290:
291: void wr_int(int x)
292: {
293: wr_byte((unsigned char)((x>>24) & 0xff));
294: wr_byte((unsigned char)((x>>16) & 0xff));
295: wr_byte((unsigned char)((x>>8) & 0xff));
296: wr_byte((unsigned char)(x & 0xff));
297: }
298:
299:
300: static inline int get_size (int ch)
301: {
302: switch (ch) {
303: case 'b': return BYTE;
304: case 'w': return WORD;
305: case 'l': return LONG;
306: default: error ("Invalid size '.%c'.", ch); return 0;
307: }
308: }
309:
310: char *rd_label (char *buf, char *lab_buf)
311: {
312: char snipped;
313: char *pos = buf;
314:
315: if (!isalpha (*buf)) error ("Label expected.");
316: /* label */
317: do {
318: pos++;
319: } while (isalnum (*pos) || (*pos == '_'));
320: /* snip */
321: snipped = *pos;
322: *pos = '\0';
323:
324: if (strlen (buf) > LAB_LEN-1) error ("Label too long.");
325: strncpy (lab_buf, buf, LAB_LEN);
326: lab_buf[LAB_LEN-1] = '\0';
327: *pos = snipped;
328: return pos;
329: }
330:
331:
332: void check_range (int *val, enum SIZE size)
333: {
334: switch (size) {
335: case BYTE: if ((*val < -128) || (*val > 255)) goto err;
336: if (*val > 127) *val -= 256;
337: break;
338: case WORD: if ((*val < -32768) || (*val > 65535)) goto err;
339: if (*val > 32767) *val -= 65536;
340: break;
341: default: break;
342: }
343: return;
344: err:
345: error ("Data too large.");
346: }
347:
348:
349: char *get_imm (char *buf, struct ImmVal *imm, int flags)
350: {
351: struct Label *lab;
352:
353: imm->has_label = 0;
354: while (isspace (*buf)) buf++;
355: if (flags & F_IMM) {
356: if (*buf != '#') goto err;
357: buf++;
358: }
359: if (*buf == '$') {
360: /* hex value */
361: buf++;
362: if (sscanf (&buf[0], "%x", &imm->val) != 1) goto err;
363: while (isxdigit (*buf)) buf++;
364: } else if (isdigit (*buf) || (*buf == '-')) {
365: /* dec value */
366: if (sscanf (&buf[0], "%d", &imm->val) != 1) goto err;
367: if (*buf == '-') buf++;
368: while (isdigit (*buf)) buf++;
369: } else if (isalpha (*buf)) {
370: /* label */
371: buf = rd_label (buf, imm->label);
372: lab = get_label (imm->label);
373: imm->val = 0;
374: if (lab) {
375: if (lab->type == L_CONST) imm->val = lab->val;
376: else imm->has_label = 1;
377: } else {
378: imm->has_label = 1;
379: }
380: if ((flags & F_NOLABELS) && (imm->has_label)) {
381: error ("Label not allowed.");
382: }
383: } else {
384: goto err;
385: }
386: return buf;
387: err:
388: error ("Malformed immediate value.");
389: return NULL;
390: }
391:
392: void check_end (const char *buf)
393: {
394: while (isspace (*buf)) buf++;
395: if (*buf) error ("Garbage at end of line.");
396: }
397:
398: typedef struct ea_t {
399: int mode;
400: int reg;
401: int op_size;
402: struct ImmVal imm;
403: union Ext {
404: short ext;
405: struct {
406: int displacement : 8;
407: int ZERO : 3;
408: uint size : 1;
409: uint reg : 3;
410: uint d_or_a : 1;
411: } _;
412: } ext;
413: } ea_t;
414:
415: void wr_ea (ea_t *ea)
416: {
417: if (ea->mode == 5) {
418: if (ea->imm.has_label) error ("Relative not allowed.");
419: wr_short (ea->imm.val);
420: return;
421: }
422: if (ea->mode == 6) {
423: if (ea->imm.has_label) error ("Relative not allowed.");
424: wr_short (ea->ext.ext);
425: return;
426: }
427: if (ea->mode == 7) {
428: /* $xxx.w */
429: if (ea->reg == 0) {
430: wr_short (ea->imm.val);
431: return;
432: }
433: /* $xxx.l */
434: else if (ea->reg == 1) {
435: if (ea->imm.has_label) goto abs_lab32;
436: wr_int (ea->imm.val);
437: return;
438: }
439: /* immediate */
440: else if (ea->reg == 4) {
441: if (ea->imm.has_label) {
442: if (ea->op_size != LONG)
443: error ("Relative not allowed.");
444: goto abs_lab32;
445: }
446: if (ea->op_size == LONG) {
447: wr_int (ea->imm.val);
448: } else if (ea->op_size == WORD) {
449: wr_short (ea->imm.val);
450: } else {
451: wr_short (ea->imm.val & 0xff);
452: }
453: return;
454: }
455: /* PC + offset */
456: else if (ea->reg == 2) {
457: if (ea->imm.has_label) goto rel_lab16;
458: error ("Absolute value not allowed.");
459: return;
460: }
461: /* PC + INDEX + OFFSET */
462: else if (ea->reg == 3) {
463: if (!ea->imm.has_label) error ("Absolute value not allowed.");
464: wr_short (ea->ext.ext);
465: add_fixup (get_bitpos()-1, BYTE, ea->imm.label);
466: return;
467: }
468: }
469: return;
470: rel_lab16:
471: /* resolve a relative 16-bit label (offset) */
472: wr_short (0);
473: add_fixup (get_bitpos()-2, WORD, ea->imm.label);
474: return;
475: abs_lab32:
476: /* resolve an absolute 32-bit label */
477: wr_int (0);
478: add_fixup (get_bitpos ()-4, LONG_FIXUP, ea->imm.label);
479: }
480:
481: char *get_reg (char *buf, int *reg_num, int flags)
482: {
483: int type;
484: while (isspace (*buf)) buf++;
485: if ((flags & F_AREG) && (buf[0] == 'a')) type = 8;
486: else if ((flags & F_DREG) && (buf[0] == 'd')) type = 0;
487: else goto err;
488: buf++;
489: if (sscanf (&buf[0], "%d", reg_num) != 1) goto err;
490:
491: *reg_num += type;
492: while (isdigit (*buf)) buf++;
493: return buf;
494: err:
495: error ("Expected a register.");
496: return NULL;
497: }
498:
499: char *get_ea (char *pos, ea_t *ea, int op_size, int flags)
500: {
501: int reg;
502: int size;
503: char *orig;
504: ea->imm.has_label = 0;
505: ea->op_size = op_size;
506: while (isspace (*pos)) pos++;
507: orig = pos;
508: if ((pos[0] == 'd') && isdigit (pos[1])) {
509: pos++;
510: if (sscanf (&pos[0], "%d", &ea->reg) != 1) goto poopdog;
511: ea->mode = 0;
512: if ((ea->reg < 0) || (ea->reg > 7)) goto poopdog;
513: while (isdigit (*pos)) pos++;
514: if (!(flags & F_DREG)) goto err;
515: return pos;
516: }
517: if ((pos[0] == 'a') && isdigit (pos[1])) {
518: pos++;
519: if (sscanf (&pos[0], "%d", &ea->reg) != 1) goto poopdog;
520: ea->mode = 1;
521: if ((ea->reg < 0) || (ea->reg > 7)) goto poopdog;
522: while (isdigit (*pos)) pos++;
523: if (!(flags & F_AREG)) goto err;
524: return pos;
525: }
526: poopdog:
527: pos = orig;
528: if ((*pos == '#') && (flags & F_IMM)) {
529: pos = get_imm (pos, &ea->imm, F_IMM);
530: check_range (&ea->imm.val, op_size);
531: ea->mode = 7;
532: ea->reg = 4;
533: return pos;
534: }
535: if ((flags & F_PRE) && (pos[0] == '-') && (pos[1] == '(')) {
536: pos += 2;
537: pos = get_reg (pos, &ea->reg, F_AREG);
538: check (')');
539: ea->mode = 0x4;
540: return pos;
541: }
542: if ((flags & (F_IND | F_POST)) && (pos[0] == '(')) {
543: check ('(');
544: pos = get_reg (pos, &ea->reg, F_AREG);
545: check (')');
546: if ((flags & F_POST) && (pos[0] == '+')) {
547: ea->mode = 3;
548: return ++pos;
549: } else if (flags & F_IND) {
550: ea->mode = 2;
551: return pos;
552: } else goto err;
553: }
554: if ((*pos == '$') || isdigit (*pos) || (*pos == '-') || isalpha (*pos)) {
555: if (isalpha (*pos)) {
556: pos = get_imm (pos, &ea->imm, 0);
557: } else if (*pos == '$') {
558: pos++;
559: if (sscanf (pos, "%x", &ea->imm.val) != 1) goto err;
560: while (isxdigit (*pos)) pos++;
561: } else {
562: if (sscanf (pos, "%d", &ea->imm.val) != 1) goto err;
563: if (*pos == '-') pos++;
564: while (isdigit (*pos)) pos++;
565: }
566: /* Immediate memory (not label) */
567: if ((*pos == '.') && (flags & (F_MEM_W | F_MEM_L))) {
568: pos++;
569: size = get_size (*pos);
570: pos++;
571: ea->mode = 0x7;
572: if (size == WORD) {
573: ea->reg = 0;
574: if ((ea->imm.val < 0) || (ea->imm.val > 65535)) error ("Immediate value too large.");
575: }
576: else if (size == LONG) ea->reg = 1;
577: else error ("Bad size.");
578: return pos;
579: }
580: while (isspace (*pos)) pos++;
581: if (((*pos == ',') || (*pos == '\0')) && (flags & F_MEM_L)) {
582: /* Immed memory with label */
583: ea->mode = 0x7;
584: ea->reg = 1;
585: return pos;
586: }
587: if (*pos != '(') goto err;
588: /* adr reg or pc indexed or offset */
589: pos++;
590: if ((pos[0] == 'p') && (pos[1] == 'c')) {
591: /* pc relative */
592: pos += 2;
593: if ((pos [0] == ')') && (flags & F_PC_OFFSET)) {
594: if ((ea->imm.val < -32768) || (ea->imm.val > 32767)) error ("Immediate value too large.");
595: ea->mode = 7;
596: ea->reg = 2;
597: return ++pos;
598: }
599: if (!(flags & F_PC_INDEX)) goto err;
600: check (',');
601: pos = get_reg (pos, ®, F_AREG | F_DREG);
602: ea->ext.ext = 0;
603: if (reg > 7) {
604: ea->ext._.reg = reg-8;
605: ea->ext._.d_or_a = 1;
606: } else {
607: ea->ext._.reg = reg;
608: ea->ext._.d_or_a = 0;
609: }
610: check ('.');
611: if (pos[0] == 'l') {
612: ea->ext._.size = 1;
613: } else if (pos[0] == 'w') {
614: ea->ext._.size = 0;
615: } else error ("Index register must have size.");
616: pos++;
617: check (')');
618: ea->mode = 7;
619: ea->reg = 3;
620: return pos;
621: } else {
622: /* adr with index/offset */
623: pos = get_reg (pos, &ea->reg, F_AREG);
624: if ((flags & F_OFFSET) && (pos[0] == ')')) {
625: /* with offset only */
626: if ((ea->imm.val < -32768) || (ea->imm.val > 32767)) error ("Immediate value too large.");
627: ea->mode = 5;
628: return ++pos;
629: }
630: if (!(flags & F_INDEX)) goto err;
631: check (',');
632: pos = get_reg (pos, ®, F_AREG | F_DREG);
633: if ((ea->imm.val < -128) || (ea->imm.val > 127)) error ("Immediate value too large.");
634: ea->ext.ext = 0;
635: ea->ext._.displacement = ea->imm.val;
636: if (reg > 7) {
637: ea->ext._.reg = reg-8;
638: ea->ext._.d_or_a = 1;
639: } else {
640: ea->ext._.reg = reg;
641: ea->ext._.d_or_a = 0;
642: }
643: check ('.');
644: if (pos[0] == 'l') {
645: ea->ext._.size = 1;
646: } else if (pos[0] == 'w') {
647: ea->ext._.size = 0;
648: } else error ("Index register must have size.");
649: pos++;
650: check (')');
651: ea->mode = 6;
652: return pos;
653: }
654: }
655: error ("Illegal effective address.");
656: err:
657: error ("Malformed effective address. Valid modes are: %s%s%s%s%s%s%s%s%s%s%s%s",
658: (flags & F_DREG ? "dreg " : ""),
659: (flags & F_AREG ? "areg " : ""),
660: (flags & F_IND ? "indirect " : ""),
661: (flags & F_POST ? "postincrement ": ""),
662: (flags & F_PRE ? "predecrement ": ""),
663: (flags & F_OFFSET ? "areg-offset ": ""),
664: (flags & F_OFFSET ? "areg-offset-index ": ""),
665: (flags & F_MEM_W ? "absolute.w ": ""),
666: (flags & F_MEM_L ? "absolute.l ": ""),
667: (flags & F_IMM ? "immediate ": ""),
668: (flags & F_PC_OFFSET ? "pc-relative ": ""),
669: (flags & F_PC_INDEX ? "pc-rel-index ": ""));
670: return NULL;
671: }
672:
673: int _reg_num (char *cunt)
674: {
675: int is_areg;
676: int num;
677:
678: if (cunt[0] == 'a') is_areg = 8;
679: else is_areg = 0;
680: cunt++;
681:
682: if (sscanf (cunt, "%d", &num) != 1) return -1;
683: num += is_areg;
684:
685: while (isdigit (*cunt)) cunt++;
686: if (isalpha (*cunt)) return -1;
687: return num;
688: }
689:
690: /* movem is a wanking cunt of doom */
691: /* this is such a sinful mess :-) */
692: char *parse_movem (char *pos, int size)
693: {
694: union Opcode op;
695: char *start = pos;
696: char lab1[LAB_LEN];
697: int lo, hi;
698: /* d0-7,a0-7 */
699: int regs[16];
700: int dr = 0; /* reg to mem */
701: ea_t ea;
702: memset (regs, 0, 16*sizeof(int));
703: try_again:
704: if ((pos[0] == 'a') || (pos[0] == 'd')) {
705: more_to_come:
706: pos = rd_label (pos, lab1);
707: lo = _reg_num (lab1);
708: if (lo == -1) {
709: mess:
710: /* mem to reg */
711: dr = 1;
712: pos = start;
713: pos = get_ea (pos, &ea, size, F_IND | F_POST | F_INDEX | F_OFFSET | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
714: if (pos[0] != ',') goto err;
715: pos++;
716: goto try_again;
717: }
718:
719: if (*pos == '-') {
720: /* range of fucking registers */
721: pos++;
722: if (sscanf (pos, "%d", &hi) != 1) goto err;
723: pos++;
724: if ((hi < 0) || (hi > 7)) goto err;
725: if (lo > 7) hi += 8;
726: } else {
727: hi = lo;
728: }
729: for (; lo<=hi; lo++) regs[lo] = 1;
730: if (pos[0] == '/') {
731: pos++;
732: goto more_to_come;
733: }
734: } else {
735: goto mess;
736: }
737: if (!dr) {
738: /* reg to mem */
739: if (pos[0] != ',') goto err;
740: pos++;
741: pos = get_ea (pos, &ea, size, F_IND | F_PRE | F_INDEX | F_OFFSET | F_MEM_W | F_MEM_L);
742: }
743: op.code = 0x4880;
744: op.movem.sz = (size == WORD ? 0 : 1);
745: op.movem.dr = dr;
746: op.movem.dest_reg = ea.reg;
747: op.movem.dest_mode = ea.mode;
748: wr_short (op.code);
749:
750: hi = 0;
751: if (ea.mode == 0x4) {
752: /* predecrement mode */
753: for (lo=0; lo < 16; lo++) {
754: if (regs[15-lo]) hi |= (1<<lo);
755: }
756: } else {
757: for (lo=0; lo < 16; lo++) {
758: if (regs[lo]) hi |= (1<<lo);
759: }
760: }
761: wr_short (hi);
762: /* movem seems to count offsets relative to the
763: * register bitfield... */
764: last_op_addr += 2;
765: wr_ea (&ea);
766: return pos;
767: err:
768: error ("your movem is all wanked up.");
769: return NULL;
770: }
771:
772: int asm_pass1 ()
773: {
774: int i, reg, size;
775: union Opcode op;
776: struct ImmVal imm;
777: char lab1[LAB_LEN];
778: char *equ_lab;
779: char *pos;
780: ea_t ea;
781: ea_t ea2;
782:
783: wr_short (0x601a);
784: wr_int (0);
785: wr_int (0);
786: wr_int (0);
787: wr_int (0);
788: wr_int (0);
789: wr_int (0);
790: wr_short (0);
791:
792: dict_init (&labels);
793:
794: while (fgets (buf, sizeof (buf), fin)) {
795: last_op_addr = get_bitpos ();
796: line_no++;
797: pos = &buf[0];
798: /* comments */
799: equ_lab = NULL;
800: while (isspace (*pos)) pos++;
801: if (*pos == '\0') continue;
802: if (*pos == '*') continue;
803: else if (isalpha (*pos)) {
804: equ_lab = pos;
805: pos = rd_label (pos, lab1);
806: if (*pos == ':') {
807: /* add label */
808: add_label (lab1, L_ADDR, get_bitpos () - BASE);
809: if (dump_labels) {
810: printf ("0x%x: %s\n", get_bitpos () - BASE, lab1);
811: }
812: equ_lab = NULL;
813: pos++;
814: check_whitespace ();
815: if (*pos == '\0') continue;
816: }
817: while (isspace (*pos)) pos++;
818: }
819: /* EQU */
820: if (strncmp (pos, "equ", 3) == 0) {
821: pos += 3;
822: check_whitespace();
823: if (!equ_lab) error ("EQU without label.");
824: pos = get_imm (pos, &imm, F_NOLABELS);
825: add_label (lab1, L_CONST, imm.val);
826: continue;
827: }
828: if (equ_lab) {
829: pos = equ_lab;
830: equ_lab = NULL;
831: }
832:
833: /* DC.X */
834: if (strncmp (pos, "dc.", 3) == 0) {
835: size = get_size (pos[3]);
836: pos += 4;
837: check_whitespace();
838: if ((size == BYTE) && (*pos == '"')) {
839: thing:
840: pos++;
841: while (*pos != '"') {
842: wr_byte (*pos);
843: pos++;
844: }
845: /* double '""' escapes */
846: pos++;
847: if (*pos == '"') {
848: wr_byte ('"');
849: goto thing;
850: }
851: while (isspace (*pos)) pos++;
852: if (*pos != ',') {
853: check_end (pos);
854: continue;
855: }
856: pos++;
857: }
858: while (isdigit (*pos) || isalpha (*pos) || (*pos == '$')) {
859: pos = get_imm (pos, &imm, 0);
860: if (imm.has_label) {
861: switch (size) {
862: case BYTE: case WORD: error ("Labels may only be used with dc.l.");
863: case LONG: default:
864: wr_int (0);
865: add_fixup (get_bitpos()-4, LONG_FIXUP, imm.label);
866: break;
867: }
868: } else {
869: switch (size) {
870: case BYTE: wr_byte (imm.val); break;
871: case WORD: wr_short (imm.val); break;
872: case LONG: default: wr_int (imm.val); break;
873: }
874: }
875: while (isspace (*pos)) pos++;
876: if (*pos != ',') break;
877: pos++;
878: while (isspace (*pos)) pos++;
879: }
880: check_end (pos);
881: continue;
882: }
883: /* DS.X */
884: if (strncmp (pos, "ds.", 3) == 0) {
885: size = get_size (pos[3]);
886: pos += 4;
887: check_whitespace();
888: pos = get_imm (pos, &imm, F_NOLABELS);
889: check_end (pos);
890: for (i=0; i<imm.val; i++) {
891: if (size == BYTE) wr_byte (0);
892: else if (size == WORD) wr_short (0);
893: else wr_int (0);
894: }
895: continue;
896: }
897: /* odd address checking */
898: if (last_op_addr & 0x1) error ("Odd address.");
899: /* ADDQ/SUBQ */
900: if ((strncmp (pos, "addq", 4)==0) ||
901: (strncmp (pos, "subq", 4)==0)) {
902: op.code = 0x5000;
903: op.addq.issub = (pos[0] == 's');
904: pos += 4;
905: check ('.');
906: size = get_size (pos[0]);
907: pos++;
908: check_whitespace();
909: pos = get_imm (pos, &imm, F_NOLABELS | F_IMM);
910: if ((imm.val < 1) || (imm.val > 8)) error ("Immediate value too large.");
911: if (imm.val == 8) imm.val = 0;
912: check (',');
913: pos = get_ea (pos, &ea, LONG, F_DREG | F_AREG | F_IND | F_POST | F_PRE | F_INDEX | F_OFFSET | F_MEM_W | F_MEM_L);
914: if ((size == BYTE) && (ea.mode == 1)) error ("Bad size for address reg direct.");
915: check_end (pos);
916: op.addq.dest_reg = ea.reg;
917: op.addq.dest_mode = ea.mode;
918: op.addq.size = size;
919: op.addq.data = imm.val;
920: wr_short (op.code);
921: wr_ea (&ea);
922: continue;
923: }
924: /* NOP */
925: if (strncmp (pos, "nop", 3) == 0) {
926: pos += 3;
927: check_end (pos);
928: wr_short (0x4e71);
929: continue;
930: }
931: /* NOT/NEGX/NEG */
932: if (strncmp (pos, "not", 3) == 0) {
933: pos += 3;
934: check ('.');
935: size = get_size (pos[0]);
936: pos++;
937: check_whitespace();
938: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
939: check_end (pos);
940: op.code = 0x4600;
941: op.type1.size = size;
942: op.type1.ea_reg = ea.reg;
943: op.type1.ea_mode = ea.mode;
944: wr_short (op.code);
945: wr_ea (&ea);
946: continue;
947: }
948: if (strncmp (pos, "negx", 4) == 0) {
949: pos += 4;
950: check ('.');
951: size = get_size (pos[0]);
952: pos++;
953: check_whitespace();
954: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
955: check_end (pos);
956: op.code = 0x4000;
957: op.type1.size = size;
958: op.type1.ea_reg = ea.reg;
959: op.type1.ea_mode = ea.mode;
960: wr_short (op.code);
961: wr_ea (&ea);
962: continue;
963: }
964: if (strncmp (pos, "neg", 3) == 0) {
965: pos += 3;
966: check ('.');
967: size = get_size (pos[0]);
968: pos++;
969: check_whitespace();
970: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
971: check_end (pos);
972: op.code = 0x4400;
973: op.type1.size = size;
974: op.type1.ea_reg = ea.reg;
975: op.type1.ea_mode = ea.mode;
976: wr_short (op.code);
977: wr_ea (&ea);
978: continue;
979: }
980: /* DIVS/DIVU */
981: if (strncmp (pos, "div", 3) == 0) {
982: pos += 3;
983: if (pos[0] == 's') op.code = 0x81c0;
984: else op.code = 0x80c0;
985: pos++;
986: check_whitespace();
987: pos = get_ea (pos, &ea, WORD, F_ALL_NOAREG);
988: check (',');
989: pos = get_reg (pos, &i, F_DREG);
990: check_end (pos);
991: op.type2.reg = i;
992: op.type2.ea_mode = ea.mode;
993: op.type2.ea_reg = ea.reg;
994: wr_short (op.code);
995: wr_ea (&ea);
996: continue;
997: }
998: /* MULS/MULU */
999: if (strncmp (pos, "mul", 3) == 0) {
1000: pos += 3;
1001: if (pos[0] == 's') op.code = 0xc1c0;
1002: else op.code = 0xc0c0;
1003: pos++;
1004: check_whitespace();
1005: pos = get_ea (pos, &ea, WORD, F_ALL_NOAREG);
1006: check (',');
1007: pos = get_reg (pos, &i, F_DREG);
1008: check_end (pos);
1009: op.type2.reg = i;
1010: op.type2.ea_mode = ea.mode;
1011: op.type2.ea_reg = ea.reg;
1012: wr_short (op.code);
1013: wr_ea (&ea);
1014: continue;
1015: }
1016: /* ADDI/SUBI */
1017: if ((strncmp (pos, "addi", 4) == 0) ||
1018: (strncmp (pos, "subi", 4) == 0)) {
1019: if (pos[0] == 'a') op.code = 0x0600;
1020: else op.code = 0x0400;
1021: pos += 4;
1022: check ('.');
1023: size = get_size (pos[0]);
1024: pos++;
1025: check_whitespace();
1026: pos = get_ea (pos, &ea2, size, F_IMM);
1027: check (',');
1028: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
1029: check_end (pos);
1030: op.type1.size = size;
1031: op.type1.ea_reg = ea.reg;
1032: op.type1.ea_mode = ea.mode;
1033: wr_short (op.code);
1034: if (size == BYTE) {
1035: wr_short (ea2.imm.val & 0xff);
1036: } else if (size == WORD) {
1037: wr_short (ea2.imm.val);
1038: } else {
1039: wr_int (ea2.imm.val);
1040: }
1041: wr_ea (&ea);
1042: continue;
1043: }
1044: /* ADDA/SUBA */
1045: if ((strncmp (pos, "adda", 4) == 0) ||
1046: (strncmp (pos, "suba", 4) == 0)) {
1047: if (pos[0] == 'a') op.code = 0xd000;
1048: else op.code = 0x9000;
1049: pos += 4;
1050: check ('.');
1051: size = get_size (pos[0]);
1052: if (size == BYTE) error ("Crap size for adda.");
1053: pos++;
1054: check_whitespace();
1055: pos = get_ea (pos, &ea, size, F_ALL);
1056: check (',');
1057: pos = get_reg (pos, ®, F_AREG);
1058: check_end (pos);
1059: op.type2.reg = reg;
1060: if (size == WORD) size = 3;
1061: else size = 7;
1062: op.type2.op_mode = size;
1063: op.type2.ea_reg = ea.reg;
1064: op.type2.ea_mode = ea.mode;
1065: wr_short (op.code);
1066: wr_ea (&ea);
1067: continue;
1068: }
1069: /* ADDX/SUBX */
1070: if ((strncmp (pos, "addx", 4) == 0) ||
1071: (strncmp (pos, "subx", 4) == 0)) {
1072: if (pos[0] == 'a') op.code = 0xd100;
1073: else op.code = 0x9100;
1074: pos += 4;
1075: check ('.');
1076: size = get_size (pos[0]);
1077: op.addx.size = size;
1078: pos++;
1079: check_whitespace();
1080: pos = get_ea (pos, &ea, size, F_DREG | F_PRE);
1081: if (ea.mode == 0) {
1082: /* Dn,Dn mode */
1083: check (',');
1084: op.addx.src_reg = ea.reg;
1085: op.addx.rm = 0;
1086: pos = get_reg (pos, &i, F_DREG);
1087: check_end (pos);
1088: op.addx.dest_reg = i;
1089: wr_short (op.code);
1090: } else {
1091: /* -(An),-(An) mode */
1092: check (',');
1093: op.addx.src_reg = ea.reg;
1094: op.addx.rm = 1;
1095: pos = get_ea (pos, &ea, size, F_PRE);
1096: op.addx.dest_reg = ea.reg;
1097: wr_short (op.code);
1098: }
1099: check_end (pos);
1100: continue;
1101: }
1102: /* ADD/SUB */
1103: if ((strncmp (pos, "add", 3) == 0) ||
1104: (strncmp (pos, "sub", 3) == 0)) {
1105: if (pos[0] == 'a') op.code = 0xd000;
1106: else op.code = 0x9000;
1107: pos += 3;
1108: check ('.');
1109: size = get_size (pos[0]);
1110: pos++;
1111: check_whitespace();
1112: pos = get_ea (pos, &ea, size, F_ALL);
1113: check (',');
1114: pos = get_ea (pos, &ea2, size, F_DREG | F_IND | F_POST | F_PRE | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L);
1115: if (ea2.mode == 0) {
1116: /* data reg dest */
1117: op.type2.reg = ea2.reg;
1118: op.type2.op_mode = size;
1119: op.type2.ea_reg = ea.reg;
1120: op.type2.ea_mode = ea.mode;
1121: wr_short (op.code);
1122: wr_ea (&ea);
1123: } else {
1124: /* ea dest */
1125: if (ea.mode != 0) error ("One operand must be a data register.");
1126: op.type2.reg = ea.reg;
1127: op.type2.op_mode = size+4;
1128: op.type2.ea_reg = ea2.reg;
1129: op.type2.ea_mode = ea2.mode;
1130: wr_short (op.code);
1131: wr_ea (&ea2);
1132: }
1133: check_end (pos);
1134: continue;
1135: }
1136: /* BCHG/BCLR/BSET/BTST */
1137: if ((strncmp (pos, "bchg", 4)==0) ||
1138: (strncmp (pos, "bclr", 4)==0) ||
1139: (strncmp (pos, "bset", 4)==0) ||
1140: (strncmp (pos, "btst", 4)==0)) {
1141: int type;
1142: switch (pos[2]) {
1143: /* bchg */
1144: case 'h': type = 0; break;
1145: /* bclr */
1146: case 'l': type = 1; break;
1147: /* bset */
1148: case 'e': type = 2; break;
1149: /* btst */
1150: default: case 's': type = 3; break;
1151: }
1152: pos += 4;
1153: check_whitespace();
1154: pos = get_ea (pos, &ea, BYTE, F_IMM | F_DREG);
1155: if (ea.mode == 0) {
1156: /* Dn,<ea> mode */
1157: switch (type) {
1158: case 0: op.code = 0x0140; break;
1159: case 1: op.code = 0x0180; break;
1160: case 2: op.code = 0x01c0; break;
1161: case 3: op.code = 0x0100; break;
1162: }
1163: op.type2.reg = ea.reg;
1164: check (',');
1165: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
1166: op.type2.ea_reg = ea.reg;
1167: op.type2.ea_mode = ea.mode;
1168: wr_short (op.code);
1169: wr_ea (&ea);
1170: continue;
1171: } else {
1172: /* IMM,<ea> mode */
1173: check_range (&ea.imm.val, BYTE);
1174: imm.val = ea.imm.val;
1175: switch (type) {
1176: case 0: op.code = 0x0840; break;
1177: case 1: op.code = 0x0880; break;
1178: case 2: op.code = 0x08c0; break;
1179: case 3: op.code = 0x0800; break;
1180: }
1181: check (',');
1182: if (type == 3) {
1183: pos = get_ea (pos, &ea, size, F_DREG | F_IND | F_POST | F_PRE | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
1184: } else {
1185: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
1186: }
1187: op.type2.ea_mode = ea.mode;
1188: op.type2.ea_reg = ea.reg;
1189: wr_short (op.code);
1190: wr_short (imm.val & 0xff);
1191: wr_ea (&ea);
1192: continue;
1193: }
1194: check_end (pos);
1195: continue;
1196: }
1197: /* ASx/LSx/ROx ROXx */
1198: if ((strncmp (pos, "ls", 2) == 0) ||
1199: (strncmp (pos, "as", 2) == 0) ||
1200: (strncmp (pos, "ro", 2) == 0)) {
1201: char dir;
1202: int type;
1203: dir = pos[2];
1204: if (pos[0] == 'a') type = 0;
1205: else if (pos[0] == 'l') type = 1;
1206: else if (pos[0] == 'r') {
1207: if (pos[2] == 'x') {
1208: type = 2;
1209: dir = pos[3];
1210: }
1211: else type = 3;
1212: } else {
1213: goto blork;
1214: }
1215: if ((dir != 'l') && (dir != 'r')) goto blork;
1216: dir = (dir == 'l' ? 1 : 0);
1217: while (isalpha (*pos)) pos++;
1218: check ('.');
1219: size = get_size (pos[0]);
1220: pos++;
1221: check_whitespace();
1222: pos = get_ea (pos, &ea, size, F_DREG | F_IND | F_POST | F_PRE | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L | F_IMM);
1223: if (ea.mode == 0) {
1224: /* data reg type */
1225: check (',');
1226: pos = get_reg (pos, ®, F_DREG);
1227: check_end (pos);
1228: if (type == 1) op.code = 0xe008;
1229: else if (type == 0) op.code = 0xe000;
1230: else if (type == 2) op.code = 0xe010;
1231: else op.code = 0xe018;
1232: op.ASx.count_reg = ea.reg;
1233: op.ASx.dr = dir;
1234: op.ASx.size = size;
1235: op.ASx.ir = 1;
1236: op.ASx.reg = reg;
1237: wr_short (op.code);
1238: continue;
1239: } else if ((ea.mode == 7) && (ea.reg == 4)) {
1240: /* imm,Dn type */
1241: check (',');
1242: pos = get_reg (pos, ®, F_DREG);
1243: check_end (pos);
1244: if (type == 1) op.code = 0xe008;
1245: else if (type == 0) op.code = 0xe000;
1246: else if (type == 2) op.code = 0xe010;
1247: else op.code = 0xe018;
1248: if ((ea.imm.val < 1) || (ea.imm.val > 8)) error ("Bad immediate value.");
1249: if (ea.imm.val == 8) ea.imm.val = 0;
1250: op.ASx.count_reg = ea.imm.val;
1251: op.ASx.dr = dir;
1252: op.ASx.size = size;
1253: op.ASx.ir = 0;
1254: op.ASx.reg = reg;
1255: wr_short (op.code);
1256: continue;
1257: } else {
1258: /* ea mode */
1259: if (size != WORD) error ("Illegal size.");
1260: check_end (pos);
1261: if (type == 1) op.code = 0xe2c0;
1262: else if (type == 0) op.code = 0xe0c0;
1263: else if (type == 2) op.code = 0xe4c0;
1264: else op.code = 0xe6c0;
1265: op.ASx.dr = dir;
1266: op.type1.ea_reg = ea.reg;
1267: op.type1.ea_mode = ea.mode;
1268: wr_short (op.code);
1269: wr_ea (&ea);
1270: continue;
1271: }
1272: continue;
1273: }
1274: blork:
1275: /* ANDI/EORI/ORI */
1276: if ((strncmp (pos, "andi", 4) == 0) ||
1277: (strncmp (pos, "eori", 4) == 0) ||
1278: (strncmp (pos, "ori", 3) == 0)) {
1279: if (pos[0] == 'a') {
1280: op.code = 0x0200;
1281: } else if (pos[0] == 'e') {
1282: op.code = 0x0a00;
1283: } else {
1284: op.code = 0x0000;
1285: }
1286: while (isalpha (*pos)) pos++;
1287: check ('.');
1288: size = get_size (pos[0]);
1289: pos++;
1290: check_whitespace();
1291: pos = get_imm (pos, &imm, F_NOLABELS | F_IMM);
1292: check_range (&imm.val, size);
1293: check (',');
1294: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
1295: check_end (pos);
1296: op.type1.ea_reg = ea.reg;
1297: op.type1.ea_mode = ea.mode;
1298: op.type1.size = size;
1299: wr_short (op.code);
1300: if (size == BYTE) {
1301: wr_short (imm.val & 0xff);
1302: } else if (size == WORD) {
1303: wr_short (imm.val);
1304: } else {
1305: wr_int (imm.val);
1306: }
1307: wr_ea (&ea);
1308: continue;
1309: }
1310: /* AND/OR */
1311: if ((strncmp (pos, "and", 3) == 0) ||
1312: (strncmp (pos, "or", 2) == 0)) {
1313: if (pos[0] == 'a') op.code = 0xc000;
1314: else op.code = 0x8000;
1315: while (isalpha (*pos)) pos++;
1316: check ('.');
1317: size = get_size (pos[0]);
1318: pos++;
1319: check_whitespace();
1320: pos = get_ea (pos, &ea, size, F_ALL_NOAREG);
1321: check (',');
1322: pos = get_ea (pos, &ea2, size, F_NOIMM_NOPC_NOAREG);
1323: check_end (pos);
1324: if (ea2.mode == 0) {
1325: /* data reg dest */
1326: op.type2.reg = ea2.reg;
1327: op.type2.op_mode = size;
1328: op.type2.ea_reg = ea.reg;
1329: op.type2.ea_mode = ea.mode;
1330: wr_short (op.code);
1331: wr_ea (&ea);
1332: } else {
1333: /* ea dest */
1334: if (ea.mode != 0) error ("One operand must be a data register.");
1335: op.type2.reg = ea.reg;
1336: op.type2.op_mode = size+4;
1337: op.type2.ea_reg = ea2.reg;
1338: op.type2.ea_mode = ea2.mode;
1339: wr_short (op.code);
1340: wr_ea (&ea2);
1341: }
1342: continue;
1343: }
1344: /* EOR */
1345: if (strncmp (pos, "eor", 3) == 0) {
1346: op.code = 0xb000;
1347: pos += 3;
1348: check ('.');
1349: size = get_size (pos[0]);
1350: pos++;
1351: check_whitespace();
1352: pos = get_reg (pos, ®, F_DREG);
1353: check (',');
1354: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
1355: check_end (pos);
1356: op.type2.reg = reg;
1357: size += 4;
1358: op.type2.op_mode = size;
1359: op.type2.ea_reg = ea.reg;
1360: op.type2.ea_mode = ea.mode;
1361: wr_short (op.code);
1362: wr_ea (&ea);
1363: continue;
1364: }
1365: /* SWAP */
1366: if (strncmp (pos, "swap", 4) == 0) {
1367: pos += 4;
1368: pos = get_reg (pos, ®, F_DREG);
1369: op.code = 0x4840;
1370: op.type2.ea_reg = reg;
1371: check_end (pos);
1372: wr_short (op.code);
1373: continue;
1374: }
1375: /* BSR */
1376: if (strncmp (pos, "bsr", 3) == 0) {
1377: pos += 3;
1378: check ('.');
1379: size = pos[0];
1380: pos++;
1381: check_whitespace();
1382: pos = rd_label (pos, lab1);
1383: check_end (pos);
1384: op.code = 0x6100;
1385: wr_short (op.code);
1386: if (size == 's') {
1387: add_fixup (get_bitpos()-1, BYTE, lab1);
1388: } else if (size == 'w') {
1389: wr_short (0);
1390: add_fixup (get_bitpos()-2, WORD, lab1);
1391: } else {
1392: error ("Invalid size '.%c'.", size);
1393: }
1394: continue;
1395: }
1396: /* Bcc.S */
1397: if (pos[0] == 'b') {
1398: for (i=0; i<16; i++) {
1399: if (Bcc_str [i] == NULL) continue;
1400: if (strncmp (&pos[1], Bcc_str[i], 2)==0) break;
1401: }
1402: if (i==16) goto fuckit;
1403: pos += 3;
1404: check ('.');
1405: size = pos[0];
1406: pos++;
1407: check_whitespace();
1408: pos = rd_label (pos, lab1);
1409: check_end (pos);
1410: op.code = 0x6000 | (i<<8);
1411: wr_short (op.code);
1412: if (size == 's') {
1413: add_fixup (get_bitpos()-1, BYTE, lab1);
1414: } else if (size == 'w') {
1415: wr_short (0);
1416: add_fixup (get_bitpos()-2, WORD, lab1);
1417: } else {
1418: error ("Invalid size '.%c'.", size);
1419: }
1420: continue;
1421: }
1422: /* DBcc */
1423: if ((pos[0] == 'd') && (pos[1] == 'b')) {
1424: pos = rd_label (&pos[2], lab1);
1425: for (i=0; i<16; i++) {
1426: if (strncmp (lab1, DBcc_str[i], 2)==0) break;
1427: }
1428: if (i==16) {
1429: if (strncmp (lab1, "ra", 2)==0) {
1430: i = 1;
1431: } else {
1432: goto fuckit;
1433: }
1434: }
1435: while (isalpha (*pos)) pos++;
1436: check_whitespace();
1437: pos = get_reg (pos, ®, F_DREG);
1438: check (',');
1439: pos = rd_label (pos, lab1);
1440: check_end (pos);
1441: op.code = 0x50c8;
1442: op.DBcc.reg = reg;
1443: op.DBcc.cond = i;
1444: wr_short (op.code);
1445: wr_short (0);
1446: add_fixup (get_bitpos()-2, WORD, lab1);
1447: continue;
1448: }
1449: fuckit:
1450: /* CLR */
1451: if (strncmp (pos, "clr", 3) == 0) {
1452: pos += 3;
1453: check ('.');
1454: size = get_size (pos[0]);
1455: pos++;
1456: check_whitespace();
1457: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
1458: check_end (pos);
1459: op.code = 0x4200;
1460: op.type1.size = size;
1461: op.type1.ea_reg = ea.reg;
1462: op.type1.ea_mode = ea.mode;
1463: wr_short (op.code);
1464: wr_ea (&ea);
1465: continue;
1466: }
1467: /* CMPI */
1468: if (strncmp (pos, "cmpi", 4) == 0) {
1469: pos += 4;
1470: check ('.');
1471: size = get_size (*pos);
1472: pos++;
1473: check_whitespace();
1474: pos = get_imm (pos, &imm, F_NOLABELS | F_IMM);
1475: check_range (&imm.val, size);
1476: check (',');
1477: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
1478: check_end (pos);
1479: op.code = 0x0c00;
1480: op.type1.ea_reg = ea.reg;
1481: op.type1.ea_mode = ea.mode;
1482: op.type1.size = size;
1483: wr_short (op.code);
1484: if (size == BYTE) {
1485: wr_short (imm.val & 0xff);
1486: } else if (size == WORD) {
1487: wr_short (imm.val);
1488: } else {
1489: wr_int (imm.val);
1490: }
1491: wr_ea (&ea);
1492: continue;
1493: }
1494: /* CMPA */
1495: if (strncmp (pos, "cmpa", 4) == 0) {
1496: pos += 4;
1497: check ('.');
1498: size = get_size (*pos);
1499: pos++;
1500: if (size == BYTE) error ("Size must be word or long.");
1501: check_whitespace();
1502: pos = get_ea (pos, &ea, size, F_ALL);
1503: check (',');
1504: pos = get_reg (pos, &i, F_AREG);
1505: check_end (pos);
1506:
1507: op.code = 0xb000;
1508: op.type2.reg = i;
1509: op.type2.op_mode = (size == WORD ? 3 : 7);
1510: op.type2.ea_mode = ea.mode;
1511: op.type2.ea_reg = ea.reg;
1512: wr_short (op.code);
1513: wr_ea (&ea);
1514: continue;
1515: }
1516: /* CMPM */
1517: if (strncmp (pos, "cmpm", 4) == 0) {
1518: pos += 4;
1519: check ('.');
1520: size = get_size (*pos);
1521: pos++;
1522: check_whitespace ();
1523: pos = get_ea (pos, &ea, size, F_POST);
1524: op.code = 0xb108;
1525: op.cmpm.src_reg = ea.reg;
1526: op.cmpm.size = size;
1527: check (',');
1528: pos = get_ea (pos, &ea, size, F_POST);
1529: op.cmpm.dest_reg = ea.reg;
1530: wr_short (op.code);
1531: continue;
1532: }
1533: /* CMP */
1534: if (strncmp (pos, "cmp", 3) == 0) {
1535: pos += 3;
1536: check ('.');
1537: size = get_size (*pos);
1538: pos++;
1539: check_whitespace();
1540: pos = get_ea (pos, &ea, size, F_ALL);
1541: check (',');
1542: if ((size == BYTE) && (ea.mode == 0x1))
1543: error ("Bad size for address register gropery.");
1544: pos = get_reg (pos, &i, F_DREG);
1545: check_end (pos);
1546:
1547: op.code = 0xb000;
1548: op.type2.reg = i;
1549: op.type2.op_mode = size;
1550: op.type2.ea_mode = ea.mode;
1551: op.type2.ea_reg = ea.reg;
1552: wr_short (op.code);
1553: wr_ea (&ea);
1554: continue;
1555: }
1556: /* EXG */
1557: if (strncmp (pos, "exg", 3) == 0) {
1558: pos += 3;
1559: op.code = 0xc100;
1560: check_whitespace();
1561: pos = get_reg (pos, ®, F_DREG | F_AREG);
1562: check (',');
1563: if (reg > 7) {
1564: /* Ax,Ay mode */
1565: op.exg.op_mode = 0x9;
1566: op.exg.src_reg = reg;
1567: pos = get_reg (pos, ®, F_AREG);
1568: op.exg.dest_reg = reg;
1569: } else {
1570: /* Dx,Xn mode */
1571: op.exg.src_reg = reg;
1572: pos = get_reg (pos, ®, F_AREG | F_DREG);
1573: if (reg > 7) {
1574: op.exg.op_mode = 0x11;
1575: } else {
1576: op.exg.op_mode = 0x8;
1577: }
1578: op.exg.dest_reg = reg;
1579: }
1580: check_end (pos);
1581: wr_short (op.code);
1582: continue;
1583: }
1584: /* EXT */
1585: if (strncmp (pos, "ext", 3) == 0) {
1586: pos += 3;
1587: check ('.');
1588: size = get_size (pos[0]);
1589: pos++;
1590: check_whitespace();
1591: if (size == BYTE) error ("Ext dislikes bytes.");
1592: pos = get_reg (pos, ®, F_DREG);
1593: check_end (pos);
1594: op.code = 0x4800;
1595: op.type2.ea_reg = reg;
1596: op.type2.op_mode = size+1;
1597: wr_short (op.code);
1598: continue;
1599: }
1600:
1601:
1602: /* MOVEM */
1603: if (strncmp (pos, "movem.", 6)==0) {
1604: pos += 6;
1605: size = get_size (pos[0]);
1606: pos++;
1607: if (size == BYTE) error ("Movem dislikes bytes.");
1608: check_whitespace();
1609: /* register to memory */
1610: pos = parse_movem (pos, size);
1611: check_end (pos);
1612: continue;
1613: }
1614: /* RTE */
1615: if (strncmp (pos, "rte", 3) == 0) {
1616: check_end (&pos[3]);
1617: wr_short (0x4e73);
1618: continue;
1619: }
1620: /* RTS */
1621: if (strncmp (pos, "rts", 3) == 0) {
1622: check_end (&pos[3]);
1623: wr_short (0x4e75);
1624: continue;
1625: }
1626: /* ILLEGAL */
1627: if (strncmp (pos, "illegal", 7) == 0) {
1628: check_end (&pos[7]);
1629: wr_short (0x4afc);
1630: continue;
1631: }
1632: /* HOSTCALL -- Not 68000 */
1633: if (strncmp (pos, "hostcall", 8) == 0) {
1634: pos += 8;
1635: check_end (pos);
1636: wr_short (0x000a);
1637: continue;
1638: }
1639: if (strncmp (pos, "hcall", 5) == 0) {
1640: pos += 5;
1641: check_whitespace();
1642: pos = get_imm (pos, &imm, F_IMM | F_NOLABELS);
1643: check_end (pos);
1644: check_range (&imm.val, WORD);
1645: wr_short (0x000b);
1646: wr_short (imm.val);
1647: continue;
1648: }
1649: /* RESET */
1650: if (strncmp (pos, "reset", 5) == 0) {
1651: check_end (&pos[5]);
1652: wr_short (0x4e70);
1653: continue;
1654: }
1655: /* TRAP */
1656: if (strncmp (pos, "trap", 4) == 0) {
1657: /* TRAPV */
1658: if (pos[4] == 'v') {
1659: check_end (&pos[5]);
1660: wr_short (0x4e76);
1661: continue;
1662: }
1663: pos += 4;
1664: check_whitespace();
1665: pos = get_imm (pos, &imm, F_IMM | F_NOLABELS);
1666: check_end (pos);
1667: if ((imm.val < 0) || (imm.val > 15)) {
1668: error ("Trap vector out of range.");
1669: continue;
1670: }
1671: wr_short (0x4e40 | imm.val);
1672: continue;
1673: }
1674: /* LINK */
1675: if (strncmp (pos, "link", 4) == 0) {
1676: pos += 4;
1677: check_whitespace();
1678: pos = get_reg (pos, ®, F_AREG);
1679: check (',');
1680: pos = get_imm (pos, &imm, F_IMM | F_NOLABELS);
1681: check_end (pos);
1682: check_range (&imm.val, WORD);
1683: op.code = 0x4e50;
1684: op.type1.ea_reg = reg;
1685: wr_short (op.code);
1686: wr_short (imm.val);
1687: continue;
1688: }
1689: /* UNLK */
1690: if (strncmp (pos, "unlk", 4) == 0) {
1691: pos += 4;
1692: check_whitespace();
1693: pos = get_reg (pos, ®, F_AREG);
1694: check_end (pos);
1695: op.code = 0x4e58;
1696: op.type1.ea_reg = reg;
1697: wr_short (op.code);
1698: continue;
1699: }
1700: /* MOVEQ */
1701: if (strncmp (pos, "moveq", 5) == 0){
1702: pos += 5;
1703: check_whitespace();
1704: pos = get_imm (pos, &imm, F_NOLABELS | F_IMM);
1705: check_range (&imm.val, BYTE);
1706: check (',');
1707: pos = get_ea (pos, &ea, LONG, F_DREG);
1708: check_end (pos);
1709: op.code = 0x7000;
1710: op.moveq.reg = ea.reg;
1711: op.moveq.data = imm.val;
1712: wr_short (op.code);
1713: continue;
1714: }
1715: /* MOVEA */
1716: if (strncmp (pos, "movea.", 6) == 0) {
1717: pos += 6;
1718: size = get_size (pos[0]);
1719: pos++;
1720: check_whitespace();
1721: pos = get_ea (pos, &ea, size, F_ALL);
1722: check (',');
1723: pos = get_reg (pos, &i, F_AREG);
1724: check_end (pos);
1725: is_movea:
1726: if (size == BYTE) error ("Illegal size.");
1727: size = move_size[size];
1728: op.code = 0;
1729: op.move.size = size;
1730: op.move.dest_reg = i;
1731: op.move.dest_mode = 1;
1732: op.move.src_reg = ea.reg;
1733: op.move.src_mode = ea.mode;
1734: wr_short (op.code);
1735: wr_ea (&ea);
1736: continue;
1737: }
1738: /* MOVE */
1739: if (strncmp (pos, "move.", 5) == 0) {
1740: pos += 5;
1741: size = get_size (pos[0]);
1742: pos++;
1743: check_whitespace();
1744: pos = get_ea (pos, &ea, size, F_ALL);
1745: check (',');
1746: pos = get_ea (pos, &ea2, size, F_AREG | F_DREG | F_IND | F_PRE | F_POST | F_INDEX | F_OFFSET | F_MEM_W | F_MEM_L);
1747: check_end (pos);
1748:
1749: if ((ea.mode == 7) && (ea.reg == 1) && (ea.imm.has_label)) {
1750: if (strcmp (ea.imm.label, "sr")==0) {
1751: /* move from sr */
1752: if (size != WORD) error ("Illegal size.");
1753: op.code = 0x40c0;
1754: op.type1.ea_reg = ea2.reg;
1755: op.type1.ea_mode = ea2.mode;
1756: wr_short (op.code);
1757: wr_ea (&ea2);
1758: continue;
1759: }
1760: }
1761: if (ea2.mode == 1) {
1762: i = ea2.reg;
1763: goto is_movea;
1764: }
1765: if ((ea2.mode == 7) && (ea2.reg == 1) && (ea2.imm.has_label)) {
1766: if (strcmp (ea2.imm.label, "sr")==0) {
1767: /* move to status reg */
1768: if (size != WORD) error ("Illegal size.");
1769: op.code = 0x46c0;
1770: op.type1.ea_reg = ea.reg;
1771: op.type1.ea_mode = ea.mode;
1772: wr_short (op.code);
1773: wr_ea (&ea);
1774: continue;
1775: }
1776: }
1777: size = move_size[size];
1778: op.code = 0;
1779: op.move.size = size;
1780: op.move.dest_reg = ea2.reg;
1781: op.move.dest_mode = ea2.mode;
1782: op.move.src_reg = ea.reg;
1783: op.move.src_mode = ea.mode;
1784: wr_short (op.code);
1785: wr_ea (&ea);
1786: wr_ea (&ea2);
1787: continue;
1788: }
1789: /* TST */
1790: if (strncmp (pos, "tst.", 4) == 0) {
1791: pos += 4;
1792: size = get_size (pos[0]);
1793: pos++;
1794: check_whitespace();
1795: pos = get_ea (pos, &ea, size, F_NOIMM_NOPC_NOAREG);
1796: check_end (pos);
1797: op.code = 0x4a00;
1798: op.type1.size = size;
1799: op.type1.ea_reg = ea.reg;
1800: op.type1.ea_mode = ea.mode;
1801: wr_short (op.code);
1802: wr_ea (&ea);
1803: continue;
1804: }
1805: /* PEA */
1806: if (strncmp (pos, "pea", 3) == 0) {
1807: pos += 3;
1808: check_whitespace();
1809: pos = get_ea (pos, &ea, LONG, F_IND | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
1810: check_end (pos);
1811: op.code = 0x4840;
1812: op.type2.ea_reg = ea.reg;
1813: op.type2.ea_mode = ea.mode;
1814: wr_short (op.code);
1815: wr_ea (&ea);
1816: continue;
1817: }
1818: /* LEA */
1819: if (strncmp (pos, "lea", 3) == 0) {
1820: pos += 3;
1821: check_whitespace();
1822: pos = get_ea (pos, &ea, LONG, F_IND | F_OFFSET | F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
1823: check (',');
1824: pos = get_reg (pos, &size, F_AREG);
1825: check_end (pos);
1826: op.code = 0x41e0;
1827: op.type2.ea_reg = ea.reg;
1828: op.type2.ea_mode = ea.mode;
1829: op.type2.reg = size-8;
1830: wr_short (op.code);
1831: wr_ea (&ea);
1832: continue;
1833: }
1834:
1835: /* JSR */
1836: if (strncmp (pos, "jsr", 3) == 0) {
1837: pos += 3;
1838: check_whitespace();
1839: pos = get_ea (pos, &ea, LONG, F_IND | F_OFFSET |
1840: F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
1841: check_end (pos);
1842: op.code = 0x4e80;
1843: op.type1.ea_reg = ea.reg;
1844: op.type1.ea_mode = ea.mode;
1845: wr_short (op.code);
1846: wr_ea (&ea);
1847: continue;
1848: }
1849: /* JMP */
1850: if (strncmp (pos, "jmp", 3) == 0) {
1851: pos += 3;
1852: check_whitespace();
1853: pos = get_ea (pos, &ea, LONG, F_IND | F_OFFSET |
1854: F_INDEX | F_MEM_W | F_MEM_L | F_PC_OFFSET | F_PC_INDEX);
1855: check_end (pos);
1856: op.code = 0x4ec0;
1857: op.type1.ea_reg = ea.reg;
1858: op.type1.ea_mode = ea.mode;
1859: wr_short (op.code);
1860: wr_ea (&ea);
1861: continue;
1862: }
1863: /* Scc */
1864: if (pos[0] == 's') {
1865: pos = rd_label (&pos[1], lab1);
1866: for (i=0; i<16; i++) {
1867: if (strncmp (lab1, DBcc_str[i], 2)==0) break;
1868: }
1869: if (i==16) goto fuckit2;
1870: while (isalpha (*pos)) pos++;
1871: check_whitespace();
1872: pos = get_ea (pos, &ea, BYTE, F_NOIMM_NOPC_NOAREG);
1873: check_end (pos);
1874: op.code = 0x50c0;
1875: op.DBcc.cond = i;
1876: op.type1.ea_reg = ea.reg;
1877: op.type1.ea_mode = ea.mode;
1878: wr_short (op.code);
1879: wr_ea (&ea);
1880: continue;
1881: }
1882: fuckit2:
1883: error ("Unknown opcode %s.", pos);
1884: }
1885: /* write text section length */
1886: size = get_bitpos () - BASE;
1887: set_bitpos (2);
1888: wr_int (size);
1889: /* empty reloc table for the moment */
1890: set_bitpos (size + BASE);
1891: wr_int (0);
1892: return size + BASE;
1893: }
1894:
1895: int asm_pass2 (int fixup_pos)
1896: {
1897: struct Label *lab;
1898: struct Fixup *fix;
1899: int last_adr = BASE;
1900: int _first = 1;
1901: int dist;
1902: int num_relocs = 0;
1903:
1904: fix = fix_first;
1905:
1906: while (fix) {
1907: line_no = fix->line_no;
1908: lab = get_label (fix->label);
1909: if (!lab) {
1910: error ("Undefined label '%s'.", fix->label);
1911: }
1912: if (lab->type == L_CONST) {
1913: error ("Illegal absolute value.");
1914: }
1915: set_bitpos (fix->adr);
1916: if (fix->size == BYTE) {
1917: dist = lab->val - fix->rel_to;
1918: if ((dist < -128) || (dist > 127)) {
1919: error ("Offset too big (%d).", dist);
1920: }
1921: wr_byte (dist);
1922: } else if (fix->size == WORD) {
1923: dist = lab->val - fix->rel_to;
1924: if ((dist < -32768) || (dist > 32767)) {
1925: error ("Offset too big (%d).", dist);
1926: }
1927: wr_short (dist);
1928: } else if (fix->size >= LONG) {
1929: num_relocs++;
1930: wr_int (lab->val);
1931: set_bitpos (fixup_pos);
1932: if (_first) {
1933: wr_int (fix->adr - BASE);
1934: last_adr = fix->adr;
1935: fixup_pos+=4;
1936: _first = 0;
1937: } else {
1938: dist = fix->adr - last_adr;
1939: while (dist > 254) {
1940: wr_byte (1);
1941: dist -= 254;
1942: fixup_pos++;
1943: }
1944: wr_byte (dist);
1945: last_adr = fix->adr;
1946: fixup_pos++;
1947: }
1948: } else {error ("Unknown size in fixup tab.");}
1949: fix = fix->next;
1950: }
1951: set_bitpos (fixup_pos);
1952: if (_first) wr_int (0);
1953: else wr_byte (0);
1954:
1955: return num_relocs;
1956: }
1957:
1958: int main (int argc, char **argv)
1959: {
1960: int size, num;
1961: if (argc == 1) {
1962: printf ("Usage: ./as68k [--dump-labels] file.s\n");
1963: exit (0);
1964: }
1965:
1966: argv++;
1967:
1968: if (strcmp (*argv, "--dump-labels") == 0) {
1969: argv++;
1970: dump_labels = 1;
1971: }
1972: if ((fin = fopen (*argv, "r"))==NULL) {
1973: printf ("Error. Cannot open %s.\n", *argv);
1974: exit (0);
1975: }
1976:
1977: fout = fopen ("aout.prg", "w");
1978:
1979: printf ("Pass 1\n");
1980: size = asm_pass1 ();
1981: printf ("Pass 2\n");
1982: num = asm_pass2 (size);
1983: fseek (fout, 0, SEEK_END);
1984: size = ftell (fout);
1985:
1986: printf ("Done! %d bytes and %d relocations.\n", size, num);
1987: return 0;
1988: }
1989:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.