// PARMODE.C - Addressing Modes Parser Include
// Copyright (C) 199x Landon Dyer, 2011 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
-// Source Utilised with the Kind Permission of Landon Dyer
+// Source utilised with the kind permission of Landon Dyer
//
// This file is included (twice) to parse two addressing modes, into slightly
}
else if (*tok == '#')
{
- ++tok;
+ tok++;
+
if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
return ERROR;
AMn = IMMED;
}
+
+ // Small problem with this is that the opening parentheses might be an
+ // expression that's part of a displacement; this code will falsely flag
+ // that as an error.
+
// (An)
// (An)+
// (An,Xn[.siz][*scale])
// ([bd,PC,Xn],od)
else if (*tok == '(')
{
- ++tok;
+ tok++;
if ((*tok >= KW_A0) && (*tok <= KW_A7))
{
if (*tok == ')')
{
- ++tok;
+ tok++;
if (*tok == '+')
{
- ++tok;
+ tok++;
AMn = APOSTINC;
}
else
}
else if (*tok == KW_PC)
{ // (PC,Xn[.siz][*scale])
- ++tok;
+ tok++;
AMn = PCINDEXED;
// Common index handler; enter here with `tok' pointing at the comma.
switch ((int)*tok)
{ // Index reg size: <empty> | .W | .L
case DOTW:
- ++tok;
+ tok++;
default:
AnIXSIZ = 0;
break;
case DOTL:
AnIXSIZ = 0x0800;
- ++tok;
+ tok++;
break;
case DOTB: // .B not allowed here...
goto badmode;
if (*tok == '*')
{ // scale: *1, *2, *4, *8
- ++tok;
+ tok++;
+
if (*tok++ != CONST || *tok > 8)
goto badmode;
if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
return ERROR;
+ // It could be that this is really just an expression prefixing a
+ // register as a displacement...
+ if (*tok == ')')
+ {
+ tok++;
+ goto CHK_FOR_DISPn;
+ }
+
+ // Otherwise, check for PC & etc displacements...
if (*tok++ != ',')
goto badmode;
if ((*tok >= KW_A0) && (*tok <= KW_A7))
{
AnREG = *tok & 7;
- ++tok;
+ tok++;
if (*tok == ',')
{
else if (*tok == ')')
{
AMn = ADISP;
- ++tok;
+ tok++;
goto AnOK;
}
else
else if (*tok == ')')
{
AMn = PCDISP; // expr(PC)
- ++tok;
+ tok++;
goto AnOK;
}
else
else if (*tok == KW_CCR)
{
AMn = AM_CCR;
- ++tok;
+ tok++;
goto AnOK;
}
else if (*tok == KW_SR)
{
AMn = AM_SR;
- ++tok;
+ tok++;
goto AnOK;
}
else if (*tok == KW_USP)
{
AMn = AM_USP;
- ++tok;
+ tok++;
goto AnOK;
}
// expr
if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
return ERROR;
+CHK_FOR_DISPn:
if (*tok == DOTW)
- { // expr.W
- ++tok;
+ {
+ // expr.W
+ tok++;
AMn = ABSW;
goto AnOK;
}
else if (*tok != '(')
- { // expr[.L]
+ {
+ // expr[.L]
AMn = ABSL;
- // Defined, absolute values from $FFFF8000..$00007FFF get optimized to absolute short
- if ((AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
+ // Defined, absolute values from $FFFF8000..$00007FFF get optimized
+ // to absolute short
+ if (optim_flag && (AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL + 0x8000) < 0x10000)
+ {
AMn = ABSW;
+ if (sbra_flag)
+ warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
+ }
+ // Is .L forced here?
if (*tok == DOTL)
- { // force .L
- ++tok;
+ {
+ tok++;
AMn = ABSL;
}
goto AnOK;
}
- ++tok;
+ tok++;
if ((*tok >= KW_A0) && (*tok <= KW_A7))
{
if (*tok == ')')
{
AMn = ADISP;
- ++tok;
+ tok++;
goto AnOK;
}
if (*++tok == ')')
{
AMn = PCDISP;
- ++tok;
+ tok++;
goto AnOK;
}
;
}
-// Cleanup dirty little macros
+// Clean up dirty little macros
#undef AnOK
#undef AMn
#undef AnREG
#undef AnESYM
#undef AMn_IX0
#undef AMn_IXN
+#undef CHK_FOR_DISPn