2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // MACH.C - Code Generation
4 // Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source utilised with the kind permission of Landon Dyer
22 // Fucntion prototypes
23 int m_unimp(WORD, WORD), m_badmode(WORD, WORD), m_bad6mode(WORD, WORD), m_bad6inst(WORD, WORD);
24 int m_self(WORD, WORD);
25 int m_abcd(WORD, WORD);
26 int m_reg(WORD, WORD);
27 int m_imm(WORD, WORD);
28 int m_imm8(WORD, WORD);
29 int m_shi(WORD, WORD);
30 int m_shr(WORD, WORD);
31 int m_bitop(WORD, WORD);
32 int m_exg(WORD, WORD);
35 int m_dbra(WORD, WORD);
36 int m_link(WORD, WORD);
37 int m_adda(WORD, WORD);
38 int m_addq(WORD, WORD);
39 //int m_move(WORD, int);
40 int m_move(WORD, WORD);
41 int m_moveq(WORD, WORD);
42 int m_usp(WORD, WORD);
43 int m_movep(WORD, WORD);
44 int m_trap(WORD, WORD);
45 int m_movem(WORD, WORD);
46 int m_clra(WORD, WORD);
48 // Common error messages
49 char range_error[] = "expression out of range";
50 char abs_error[] = "illegal absolute expression";
51 char seg_error[] = "bad (section) expression";
52 char rel_error[] = "illegal relative address";
53 char siz_error[] = "bad size specified";
54 char undef_error[] = "undefined expression";
55 char fwd_error[] = "forward or undefined expression";
57 extern int ea0gen(WORD);
58 extern int ea1gen(WORD);
60 // Include code tables
62 // { (WORD)-1, (unsigned long)-1L, (unsigned long)-1L, 0x0000, 0, m_badmode }, // 0
63 { 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0000, 0, m_badmode }, // 0
65 { 0, 0L, 0L, 0x0000, 0, m_unimp } // Last entry
68 // Register number << 9
70 0, 1 << 9, 2 << 9, 3 << 9, 4 << 9, 5 << 9, 6 << 9, 7 << 9
73 // SIZB==>00, SIZW==>01, SIZL==>10, SIZN==>01 << 6
77 1<<6, (WORD)-1, // SIZW, n/a
78 2<<6, (WORD)-1, (WORD)-1, (WORD)-1, // SIZL, n/a, n/a, n/a
82 // Byte/word/long size for MOVE instrs
86 0x3000, (WORD)-1, // Word
87 0x2000, (WORD)-1, (WORD)-1, (WORD)-1, // Long
91 // Word/long size (0=.w, 1=.l) in bit 8
95 0, (WORD)-1, // SIZW, n/a
96 1<<8, (WORD)-1, (WORD)-1, (WORD)-1, // SIZL, n/a, n/a, n/a
100 // Addressing mode in bits 6..11 (register/mode fields are reversed)
102 00000, 01000, 02000, 03000, 04000, 05000, 06000, 07000,
103 00100, 01100, 02100, 03100, 04100, 05100, 06100, 07100,
104 00200, 01200, 02200, 03200, 04200, 05200, 06200, 07200,
105 00300, 01300, 02300, 03300, 04300, 05300, 06300, 07300,
106 00400, 01400, 02400, 03400, 04400, 05400, 06400, 07400,
107 00500, 01500, 02500, 03500, 04500, 05500, 06500, 07500,
108 00600, 01600, 02600, 03600, 04600, 05600, 06600, 07600,
109 00700, 01700, 02700, 03700, 04700, 05700, 06700, 07700
114 int m_unimp(WORD unused1, WORD unused2)
116 return (int)error("unimplemented mnemonic");
120 //int m_badmode(void)
121 int m_badmode(WORD unused1, WORD unused2)
123 return (int)error("inappropriate addressing mode");
127 int m_self(WORD inst, WORD usused)
135 // Do one EA in bits 0..5
137 // Bits in `inst' have the following meaning:
139 // Bit zero specifies which ea (ea0 or ea1) to generate in the lower six bits
142 // If bit one is set, the OTHER ea (the one that wasn't generated by bit zero)
143 // is generated after the instruction. Regardless of bit 0's value, ea0 is
144 // always deposited in memory before ea1.
146 // If bit two is set, standard size bits are set in the instr in bits 6 and 7.
148 // If bit four is set, bit three specifies which eaXreg to place in bits 9..11
151 int m_ea(WORD inst, WORD siz)
153 WORD flg = inst; // Save flag bits
154 inst &= ~0x3F; // Clobber flag bits in instr
156 // Install "standard" instr size bits
162 // OR-in register number
164 inst |= reg_9[a1reg]; // ea1reg in bits 9..11
166 inst |= reg_9[a0reg]; // ea0reg in bits 9..11
172 inst |= am1 | a1reg; // Get ea1 into instr
173 D_word(inst); // Deposit instr
175 // Generate ea0 if requested
179 ea1gen(siz); // Generate ea1
184 inst |= am0 | a0reg; // Get ea0 into instr
185 D_word(inst); // Deposit instr
186 ea0gen(siz); // Generate ea0
188 // Generate ea1 if requested
198 // Dx,Dy nnnnXXXnssnnnYYY If bit 0 of `inst' is set, install size bits in bits
201 int m_abcd(WORD inst, WORD siz)
210 inst |= a0reg | reg_9[a1reg];
220 int m_adda(WORD inst, WORD siz)
222 inst |= am0 | a0reg | lwsiz_8[siz] | reg_9[a1reg];
224 ea0gen(siz); // Generate EA
231 // If bit 0 of `inst' is 1, install size bits in bits 6..7 of instr.
232 // If bit 1 of `inst' is 1, install a1reg in bits 9..11 of instr.
234 int m_reg(WORD inst, WORD siz)
241 // Install other register (9..11)
242 inst |= reg_9[a1reg];
244 inst &= ~7; // Clear off crufty bits
245 inst |= a0reg; // Install first register
255 int m_imm(WORD inst, WORD siz)
267 int m_imm8(WORD inst, WORD siz)
280 int m_shr(WORD inst, WORD siz)
282 inst |= reg_9[a0reg] | a1reg | siz_6[siz];
292 int m_shi(WORD inst, WORD siz)
294 inst |= a1reg | siz_6[siz];
296 if (a0exattr & DEFINED)
299 return error(range_error);
301 inst |= (a0exval & 7) << 9;
306 AddFixup(FU_QUICK, sloc, a0expr);
315 // {bset, btst, bchg, bclr} -- #immed,ea -- Dn,ea
317 int m_bitop(WORD inst, WORD siz)
319 // Enforce instruction sizes
321 { // X,Dn must be .n or .l
322 if (siz & (SIZB | SIZW))
323 return error(siz_error);
325 else if (siz & (SIZW | SIZL)) // X,ea must be .n or .b
326 return error(siz_error);
328 // Construct instr and EAs
334 ea0gen(SIZB); // Immediate bit number
338 inst |= reg_9[a0reg];
349 int m_dbra(WORD inst, WORD siz)
357 if (a1exattr & DEFINED)
359 if ((a1exattr & TDB) != cursect)
360 return error(rel_error);
364 if (v + 0x8000 > 0x10000)
365 return error(range_error);
371 AddFixup(FU_WORD | FU_PCREL | FU_ISBRA, sloc, a1expr);
382 int m_exg(WORD inst, WORD siz)
388 if (am0 == DREG && am1 == DREG)
390 else if (am0 == AREG && am1 == AREG)
396 m = a1reg; // Get AREG into a1reg
404 inst |= m | reg_9[a0reg] | a1reg;
414 int m_link(WORD inst, WORD siz)
426 // Handle MOVE <C_ALL> <C_ALTDATA>
427 // MOVE <C_ALL> <M_AREG>
429 // Optimize MOVE.L #<smalldata>,D0 to a MOVEQ
431 int m_move(WORD inst, WORD size)
433 // Cast the passed in value to an int
436 // Try to optimize to MOVEQ
437 if (optim_flag && siz == SIZL && am0 == IMMED && am1 == DREG
438 && (a0exattr & (TDB|DEFINED)) == DEFINED && a0exval + 0x80 < 0x100)
440 m_moveq((WORD)0x7000, (WORD)0);
443 warn("move.l #size,dx converted to moveq");
447 inst |= siz_12[siz] | am_6[am1] | reg_9[a1reg] | am0 | a0reg;
463 // move USP,An -- move An,USP
465 int m_usp(WORD inst, WORD siz)
470 inst |= a1reg; // USP, An
472 inst |= a0reg; // An, USP
483 int m_moveq(WORD inst, WORD siz)
487 // Arrange for future fixup
488 if (!(a0exattr & DEFINED))
490 AddFixup(FU_BYTE | FU_SEXT, sloc + 1, a0expr);
493 else if (a0exval + 0x100 >= 0x200)
494 return error(range_error);
496 inst |= reg_9[a1reg] | (a0exval & 0xFF);
504 // movep Dn, disp(An) -- movep disp(An), Dn
506 int m_movep(WORD inst, WORD siz)
513 inst |= reg_9[a0reg] | a1reg;
523 inst |= reg_9[a1reg] | a0reg;
539 int m_br(WORD inst, WORD siz)
543 if (a0exattr & DEFINED)
545 if ((a0exattr & TDB) != cursect)
547 //printf("m_br(): a0exattr = %X, cursect = %X, a0exval = %X, sloc = %X\n", a0exattr, cursect, a0exval, sloc);
548 return error(rel_error);
551 v = a0exval - (sloc + 2);
553 // Optimize branch instr. size
556 if (optim_flag && v != 0 && v + 0x80 < 0x100)
562 warn("Bcc.w/BSR.w converted to .s");
568 if (v + 0x8000 > 0x10000)
569 return error(range_error);
579 if (v + 0x80 >= 0x100)
580 return error(range_error);
587 if (v + 0x8000 >= 0x10000)
588 return error(range_error);
596 else if (siz == SIZN)
602 AddFixup(FU_BBRA | FU_PCREL | FU_SEXT, sloc, a0expr);
610 AddFixup(FU_WORD | FU_PCREL | FU_LBRA | FU_ISBRA, sloc, a0expr);
621 int m_addq(WORD inst, WORD siz)
623 inst |= siz_6[siz] | am1 | a1reg;
625 if (a0exattr & DEFINED)
627 if (a0exval > 8 || a0exval == 0) // Range in 1..8
628 return error(range_error);
630 inst |= (a0exval & 7) << 9;
635 AddFixup(FU_QUICK, sloc, a0expr);
648 int m_trap(WORD inst, WORD siz)
652 if (a0exattr & DEFINED)
655 return error(abs_error);
658 return error(range_error);
664 return error(undef_error);
671 // movem <rlist>,ea -- movem ea,<rlist>
673 int m_movem(WORD inst, WORD siz)
681 return error("bad size suffix");
688 // Handle #<expr>, ea
691 if (abs_expr(&eval) != OK)
694 if (eval >= 0x10000L)
695 return error(range_error);
701 if (*tok >= KW_D0 && *tok <= KW_A7)
704 if (reglist(&rmask) < 0)
709 return error("missing comma");
716 if (!(amsktab[am0] & (C_ALTCTRL | M_APREDEC)))
717 return error("invalid addressing mode");
719 // If APREDEC, reverse register mask
725 for(i=0x8000; i; i>>=1, w>>=1)
726 rmask = (WORD)((rmask << 1) | w & 1);
735 inst |= 0x0400 | am0 | a0reg;
738 return error("missing comma");
741 return error("missing register list");
748 if (abs_expr(&eval) != OK)
752 return error(range_error);
756 else if (reglist(&rmask) < 0)
759 if (!(amsktab[am0] & (C_CTRL | M_APOSTINC)))
760 return error("invalid addressing mode");
772 // CLR.x An ==> SUBA.x An,An
774 int m_clra(WORD inst, WORD siz)
776 inst |= a0reg | reg_9[a0reg] | lwsiz_8[siz];