2 // RMAC - Reboot's Macro Assembler for all Atari computers
3 // PARMODE.C - Addressing Modes Parser Include
4 // Copyright (C) 199x Landon Dyer, 2011-2017 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
9 // This file is included (twice) to parse two addressing modes, into slightly
10 // different var names
15 if ((*tok >= KW_D0) && (*tok <= KW_D7))
20 else if ((*tok >= KW_A0) && (*tok <= KW_A7))
29 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
35 // Small problem with this is that the opening parentheses might be an
36 // expression that's part of a displacement; this code will falsely flag
41 // (An,Xn[.siz][*scale])
42 // (PC,Xn[.siz][*scale])
44 // (d8,An,Xn[.siz][*scale])
46 // (d8,PC,Xn[.siz][*scale])
55 if ((*tok >= KW_A0) && (*tok <= KW_A7))
75 goto AMn_IX0; // Handle ",Xn[.siz][*scale])"
77 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
79 //Since index register isn't used here, store register number in this field
80 AnIXREG = *tok++ & 7; // (Dn)
84 AnEXTEN |= EXT_FULLWORD; // Definitely using full extension format, so set bit 8
85 AnEXTEN |= EXT_BS; // Base register suppressed
86 AnEXTEN |= EXT_BDSIZE0; // Base displacement null
87 AnEXTEN |= EXT_IISPOSN; // Indirect Postindexed with Null Outer Displacement
89 AnREG = 6 << 3; // stuff 110 to mode field
94 // TODO: does DINDL gets used at all?
96 AnEXTEN = 1 << 1; // Long index size
99 else if (*tok == 'W') // (Dn.w)
101 // TODO: does DINDW gets used at all?
103 AnEXTEN = 1 << 1; // Word index size
106 else if (*tok == ',')
108 // ([bd,An],Xn..) without bd, An
109 // Base displacement is suppressed
110 AnEXTEN |= EXT_FULLWORD; // Definitely using full extension format, so set bit 8
111 AnEXTEN |= EXT_BS; // Base register suppressed
112 AnEXTEN |= EXT_BDSIZE0;
113 AnREG = 6 << 3; // stuff 110 to mode field
119 return error("(Dn) error");
123 { // scale: *1, *2, *4, *8
128 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
129 return error("scale factor expression must evaluate");
147 else if (*tok++ != CONST || *tok > 8)
173 AnEXTEN |= EXT_FULLWORD; // Definitely using full extension format, so set bit 8
174 AnEXTEN |= EXT_BS; // Base register suppressed
175 AnEXTEN |= EXT_BDSIZE0; // Base displacement null
176 AnEXTEN |= EXT_IISPOSN; // Indirect Postindexed with Null Outer Displacement
177 AnREG = 6 << 3; // stuff 110 to mode field
183 tok++; // eat the comma
184 // It might be (Dn[.wl][*scale],od)
185 // Maybe this is wrong and we have to write some code here
186 // instead of reusing that path...
190 return error("unhandled so far");
192 else if (*tok == KW_PC)
193 { // (PC,Xn[.siz][*scale])
197 // Common index handler; enter here with 'tok' pointing at the
200 AMn_IX0: // Handle indexed with missing expr
203 AnEXATTR = ABS | DEFINED;
205 AMn_IXN: // Handle any indexed (tok -> a comma)
210 if (*tok < KW_D0 || *tok > KW_A7)
213 AnIXREG = *tok++ & 15;
216 { // Index reg size: <empty> | .W | .L
226 case DOTB: // .B not allowed here...
231 { // scale: *1, *2, *4, *8
236 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
237 return error("scale factor expression must evaluate");
255 else if (*tok++ != CONST || *tok > 8)
283 if (*tok++ != ')') // final ")"
288 else if (*tok == '[')
291 AnEXTEN|=EXT_FULLWORD; //Definitely using full extension format, so set bit 8
292 // Check to see if base displacement is present
293 //WARNING("expr will return a bad expression error here but this is expected, it needs to be silenced!");
294 if (*tok!=CONST && *tok !=SYMBOL)
295 //if (expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM) != OK)
297 AnEXTEN|=EXT_BDSIZE0;
299 //tok--; //Rewind tok since expr advances it forward
303 expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
304 if (optim_flags[OPT_BASE_DISP] && AnBEXVAL==0 && AnEXATTR!=0)
306 // bd=0 so let's optimise it out
307 AnEXTEN|=EXT_BDSIZE0;
311 AnEXTEN|=EXT_BDSIZEL;
315 { // ([bd[.w],... or ([bd,...
316 // Is .W forced here?
319 AnEXTEN|=EXT_BDSIZEW;
324 // Defined, absolute values from $FFFF8000..$00007FFF get optimized
326 if (optim_flags[OPT_ABS_SHORT]
327 && ((AnBEXATTR & (TDB | DEFINED)) == DEFINED)
328 && ((AnBEXVAL + 0x8000) < 0x10000))
330 AnEXTEN |= EXT_BDSIZEW;
331 warn("absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
335 AnEXTEN |= EXT_BDSIZEL;
343 // return error("Comma expected after base displacement");
346 // Check for address register or PC, suppress base register
351 AnREG = (7 << 3) | 3; // PC is special case - stuff 011 to register field and 111 to the mode field
354 else if ((*tok >= KW_A0) && (*tok <= KW_A7))
356 AnREG = (6<<3)|*tok & 7;
359 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
363 AnEXTEN |= ((*tok & 7) << 12);
365 AnEXTEN |= EXT_BS; // Oh look, a data register! Which means that base register is suppressed
370 // ([bd,An/PC],Xn.W/L...)
373 // Index reg size: <empty> | .W | .L
384 // .B not allowed here...
390 if (*tok == '*') // ([bd,An/PC],Xn*...)
391 { // scale: *1, *2, *4, *8
396 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
397 return error("scale factor expression must evaluate");
415 else if (*tok++ != CONST || *tok > 8)
437 if (*tok == ']') // ([bd,Dn]...
443 else if (*tok == ']')
445 // PC and Xn is suppressed
446 AnREG = 6 << 3; // stuff 110 to mode field
447 //AnEXTEN|=EXT_BS|EXT_IS;
455 // At a crossroads here. We can accept either ([bd,An/PC],... or ([bd,An/PC,Xn*scale],...
464 //Xn and od are non existent, get out of jail free card
466 AMn = MEMPRE; // ([bc,An,Xn],od) with no Xn and od
467 AnEXTEN |= EXT_IS | EXT_IISPREN; //Suppress Xn and od
470 else if (*tok != ',')
471 return error("comma expected after ]");
473 tok++; // eat the comma
475 if ((*tok >= KW_A0) && (*tok <= KW_A7))
477 AnIXREG = ((*tok & 7) << 12);
481 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
483 AnEXTEN |= ((*tok & 7) << 12);
489 //No index found, suppress it
491 tok--; // Rewind tok to point to the comma
492 goto IS_SUPPRESSEDn; // https://xkcd.com/292/ - what does he know anyway?
497 // ([bd,An/PC],Xn.W/L...)
500 // Index reg size: <empty> | .W | .L
511 // .B not allowed here...
517 if (*tok == '*') // ([bd,An/PC],Xn*...)
518 { // scale: *1, *2, *4, *8
523 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
524 return error("scale factor expression must evaluate");
542 else if (*tok++ != CONST || *tok > 8)
566 if (*tok == ')') // ([bd,An/PC],Xn)
568 //od is non existant, get out of jail free card
569 AMn = MEMPOST; // let's say it's ([bd,An],Xn,od) with od=0 then
570 AnEXTEN |= EXT_IISPOSN; // No outer displacement
575 return error("comma expected");
577 tok++; // eat the comma
580 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
583 if (optim_flags[OPT_BASE_DISP] && (AnEXVAL == 0))
585 // od=0 so optimise it out
586 AMn = MEMPOST; // let's say it's ([bd,An],Xn,od) with od=0 then
587 AnEXTEN |= EXT_IISPOSN; // No outer displacement
591 // ([bd,An/PC],Xn,od)
595 AnEXTEN |= EXT_IISPOSL; // Long outer displacement
599 // Defined, absolute values from $FFFF8000..$00007FFF get
600 // optimized to absolute short
601 if (optim_flags[OPT_ABS_SHORT]
602 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
603 && ((AnEXVAL + 0x8000) < 0x10000))
605 AnEXTEN |= EXT_IISPOSW; // Word outer displacement
607 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
614 AnEXTEN |= EXT_IISPOSW; // Word outer displacement
617 // Is .W forced here?
624 // Check for final closing parenthesis
631 return error("Closing parenthesis missing on addressing mode");
636 if (*tok == ')') // ([bd,An/PC],Xn)
638 //od is non existant, get out of jail free card
639 AMn = MEMPOST; // let's say it's ([bd,An],Xn,od) with od=0 then
640 AnEXTEN |= EXT_IISNOIN; // No outer displacement
645 return error("comma expected");
647 tok++; // eat the comma
649 if ((*tok != CONST) && (*tok != SYMBOL))
652 expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
654 if (optim_flags[OPT_BASE_DISP] && (AnEXVAL == 0))
656 // od=0 so optimise it out
657 AMn = MEMPOST; // let's say it's ([bd,An],Xn,od) with od=0 then
658 AnEXTEN |= EXT_IISNOIN; // No outer displacement
663 // ([bd,An/PC],Xn,od)
669 AnEXTEN |= EXT_IISNOIL; // Long outer displacement with IS suppressed
674 AnEXTEN |= EXT_IISNOIW; // Word outer displacement with IS suppressed
678 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement
683 // Defined, absolute values from $FFFF8000..$00007FFF get
684 // optimized to absolute short
685 else if (optim_flags[OPT_BASE_DISP]
686 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
687 && ((AnEXVAL + 0x8000) < 0x10000))
689 //AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
690 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
694 // Check for final closing parenthesis
701 return error("Closing parenthesis missing on addressing mode");
703 else if (*tok == ',')
705 *tok++; // ([bd,An,Xn.size*scale],od)
708 if ((*tok >= KW_A0) && (*tok <= KW_A7))
710 AnEXTEN |= ((*tok & 7) << 12);
714 else if ((*tok >= KW_D0) && (*tok <= KW_D7))
716 AnEXTEN |= ((*tok & 7) << 12);
723 // ([bd,An/PC],Xn.W/L...)
726 // Index reg size: <empty> | .W | .L
737 // .B not allowed here...
743 if (*tok == '*') // ([bd,An/PC],Xn*...)
744 { // scale: *1, *2, *4, *8
749 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
750 return error("scale factor expression must evaluate");
768 else if (*tok++ != CONST || *tok > 8)
793 return error("Expected closing bracket ]");
794 tok++; // Eat the bracket
797 if (*tok == ')') // ([bd,An/PC,Xn]...
799 //od is non existant, get out of jail free card
800 //AnEXVAL=0; // zero outer displacement
801 AMn = MEMPRE; // let's say it's ([bd,An,Xn],od) with od suppressed then
802 AnEXTEN |= EXT_IISPREN; // No outer displacement
806 else if (*tok++!=',')
807 return error("comma expected after ]");
809 WARNING(Put symbol and constant checks here!)
811 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
814 if (optim_flags[OPT_BASE_DISP] && (AnEXVAL == 0))
816 // od=0 so optimise it out
817 AMn = MEMPRE; // let's say it's ([bd,An],Xn,od) with od=0 then
818 AnEXTEN |= EXT_IISPRE0; // No outer displacement
823 // ([bd,An/PC,Xn],od)
829 AnEXTEN |= EXT_IISPREL;
836 AnEXTEN |= EXT_IISPREW;
839 // Is .W forced here?
845 // Defined, absolute values from $FFFF8000..$00007FFF get optimized
847 else if (optim_flags[OPT_BASE_DISP]
848 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
849 && ((AnEXVAL + 0x8000) < 0x10000))
851 AnEXTEN |= EXT_IISPREW;
852 warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
856 // Check for final closing parenthesis
863 return error("Closing parenthesis missing on addressing mode");
871 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
874 // It could be that this is really just an expression prefixing a
875 // register as a displacement...
882 // Otherwise, check for PC & etc displacements...
886 if ((*tok >= KW_A0) && (*tok <= KW_A7))
896 else if (*tok == ')')
905 else if (*tok == KW_PC)
912 else if (*tok == ')')
914 AMn = PCDISP; // expr(PC)
925 else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= KW_A0) && (tok[2] <= KW_A7)) && tok[3] == ')')
931 else if (*tok == KW_CCR)
937 else if (*tok == KW_SR)
943 else if (*tok == KW_USP)
947 AnREG = 2; //Added this for the case of USP used in movec (see CREGlut in mach.c). Hopefully nothing gets broken!
950 else if ((*tok >= KW_IC40) && (*tok <= KW_BC40))
953 AnREG = *tok++ - KW_IC40;
955 // After a cache keyword only a comma or EOL is allowed
956 if ((*tok != ',') && (*tok != EOL))
960 else if ((*tok >= KW_SFC) && (*tok <= KW_CRP))
963 AnREG = (*tok++) - KW_SFC;
966 else if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
969 AnREG = (*tok++ & 7);
971 else if ((*tok >= KW_FPIAR) && (*tok <= KW_FPCR))
974 AnREG = (1 << ((*tok++) - KW_FPIAR + 10));
985 if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
995 if (((AnEXATTR & (TDB | DEFINED)) == DEFINED) && (AnEXVAL < 0x10000))
996 AnEXVAL = (int32_t)(int16_t)AnEXVAL; // Sign extend value
1000 else if (*tok != '(')
1005 // Defined, absolute values from $FFFF8000..$00007FFF get optimized
1006 // to absolute short
1007 if (optim_flags[OPT_ABS_SHORT]
1008 && ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
1009 && ((AnEXVAL + 0x8000) < 0x10000))
1014 warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
1017 // Is .L forced here?
1029 if ((*tok >= KW_A0) && (*tok <= KW_A7))
1043 else if (*tok == KW_PC)
1058 // Addressing mode OK
1063 // Clean up dirty little macros
1078 #undef CHK_FOR_DISPn
1085 #undef IS_SUPPRESSEDn