//
-// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
+// RMAC - Reboot's Macro Assembler for all Atari computers
// PARMODE.C - Addressing Modes Parser Include
-// Copyright (C) 199x Landon Dyer, 2017 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2017 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
// Source utilised with the kind permission of Landon Dyer
//
else if (*tok == 'L')
{
// TODO: does DINDL gets used at all?
- //AMn=DINDL; // (Dn.l)
- //AnEXTEN = 1 << 1; // Long index size
- //tok++;
+ AMn=DINDL; // (Dn.l)
+ AnEXTEN = 1 << 1; // Long index size
+ tok++;
}
else if (*tok == 'W') // (Dn.w)
{
// TODO: does DINDW gets used at all?
- //AMn=DINDW;
- //AnEXTEN = 1 << 1; // Word index size
- //tok++;
+ AMn=DINDW;
+ AnEXTEN = 1 << 1; // Word index size
+ tok++;
}
else if (*tok == ',')
{
goto CHECKODn;
}
else
+ {
return error("(Dn) error");
+ }
+
+ if (*tok == '*')
+ { // scale: *1, *2, *4, *8
+ tok++;
+
+ if (*tok == SYMBOL)
+ {
+ if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
+ return error("scale factor expression must evaluate");
+
+ switch (AnEXVAL)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
+ }
+ else if (*tok++ != CONST || *tok > 8)
+ goto badmode;
+ else
+ {
+ switch ((int)*tok++)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
+ }
+ }
if (*tok == ')')
{
AMn = MEMPOST;
goto AnOK;
}
+ else if (*tok==',')
+ {
+ tok++; // eat the comma
+ // It might be (Dn[.wl][*scale],od)
+ // Maybe this is wrong and we have to write some code here
+ // instead of reusing that path...
+ goto CHECKODn;
+ }
else
return error("unhandled so far");
}
{ // scale: *1, *2, *4, *8
tok++;
- if (*tok++ != CONST || *tok > 8)
- goto badmode;
+ if (*tok == SYMBOL)
+ {
+ if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
+ return error("scale factor expression must evaluate");
- switch ((int)*tok++)
- {
- case 1:
- break;
- case 2:
- AnIXSIZ |= TIMES2;
- break;
- case 4:
- AnIXSIZ |= TIMES4;
- break;
- case 8:
- AnIXSIZ |= TIMES8;
- break;
- default:
+ switch (AnEXVAL)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
+ }
+ else if (*tok++ != CONST || *tok > 8)
goto badmode;
+ else
+ {
+ switch ((int)*tok++)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
}
}
+ if (*tok == ',')
+ {
+ tok++;
+ goto CHECKODn;
+ }
if (*tok++ != ')') // final ")"
goto badmode;
else
{
expr(AnBEXPR, &AnBEXVAL, &AnBEXATTR, &AnESYM);
- if (optim_flags[OPT_BASE_DISP] && AnBEXVAL==0 && AnEXATTR!=0)
+ if (CHECK_OPTS(OPT_BASE_DISP) && AnBEXVAL==0 && AnEXATTR!=0)
{
// bd=0 so let's optimise it out
AnEXTEN|=EXT_BDSIZE0;
}
else if (*tok==DOTL)
- { // ([bd.l,...
+ { // ([bd.l,...
AnEXTEN|=EXT_BDSIZEL;
tok++;
}
else
- { // ([bd[.w],... or ([bd,...
+ { // ([bd[.w],... or ([bd,...
// Is .W forced here?
if (*tok == DOTW)
{
{
// Defined, absolute values from $FFFF8000..$00007FFF get optimized
// to absolute short
- if (optim_flags[OPT_ABS_SHORT]
+ if (CHECK_OPTS(OPT_ABS_SHORT)
&& ((AnBEXATTR & (TDB | DEFINED)) == DEFINED)
&& ((AnBEXVAL + 0x8000) < 0x10000))
{
// Check for scale
if (*tok == '*') // ([bd,An/PC],Xn*...)
- {
+ { // scale: *1, *2, *4, *8
tok++;
- if (*tok == CONST) // TODO: I suppose the scale is stored as a CONST and nothing else? So prolly the if is not needed?
- tok++;
-
- switch ((int)*tok++)
+ if (*tok == SYMBOL)
{
- case 1:
- break;
- case 2:
- AnEXTEN |= EXT_TIMES2;
- break;
- case 4:
- AnEXTEN |= EXT_TIMES4;
- break;
- case 8:
- AnEXTEN |= EXT_TIMES8;
- break;
- default:
+ if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
+ return error("scale factor expression must evaluate");
+ switch (AnEXVAL)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
+ }
+ else if (*tok++ != CONST || *tok > 8)
goto badmode;
+ else
+ {
+ switch ((int)*tok++)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
}
}
-
if (*tok == ']') // ([bd,Dn]...
{
tok++;
if (*tok == ')')
{
//Xn and od are non existent, get out of jail free card
+ tok++;
AMn = MEMPRE; // ([bc,An,Xn],od) with no Xn and od
AnEXTEN |= EXT_IS | EXT_IISPREN; //Suppress Xn and od
- tok++;
goto AnOK;
}
else if (*tok != ',')
{
//No index found, suppress it
AnEXTEN |= EXT_IS;
- tok--; // Rewind tok to point to the comma
- goto IS_SUPPRESSEDn; // https://xkcd.com/292/ - what does he know anyway?
+ tok--; // Rewind tok to point to the comma
+ goto IS_SUPPRESSEDn; // https://xkcd.com/292/ - what does he know anyway?
}
// Check for size
}
// Check for scale
- if (*tok == '*')
- {
- // ([bd,An/PC],Xn*...)
+ if (*tok == '*') // ([bd,An/PC],Xn*...)
+ { // scale: *1, *2, *4, *8
tok++;
- if (*tok == CONST) // TODO: I suppose the scale is stored as a CONST and nothing else? So prolly the if is not needed?
- tok++;
-
- switch ((int)*tok++)
+ if (*tok == SYMBOL)
{
- case 1:
- break;
- case 2:
- AnEXTEN |= EXT_TIMES2;
- break;
- case 4:
- AnEXTEN |= EXT_TIMES4;
- break;
- case 8:
- AnEXTEN |= EXT_TIMES8;
- break;
- default:
+ if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
+ return error("scale factor expression must evaluate");
+
+ switch (AnEXVAL)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
+ }
+ else if (*tok++ != CONST || *tok > 8)
goto badmode;
+ else
+ {
+ switch ((int)*tok++)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
}
}
tok++; // eat the comma
CHECKODn:
-
if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
goto badmode;
- if (optim_flags[OPT_BASE_DISP] && (AnEXVAL == 0))
+ if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXVAL == 0))
{
// od=0 so optimise it out
AMn = MEMPOST; // let's say it's ([bd,An],Xn,od) with od=0 then
tok++;
goto AnOK;
}
-
// ([bd,An/PC],Xn,od)
if (*tok == DOTL)
{
// expr.L
AnEXTEN |= EXT_IISPOSL; // Long outer displacement
AMn = MEMPOST;
+ tok++;
// Defined, absolute values from $FFFF8000..$00007FFF get
// optimized to absolute short
- if (optim_flags[OPT_ABS_SHORT]
+ if (CHECK_OPTS(OPT_ABS_SHORT)
&& ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
&& ((AnEXVAL + 0x8000) < 0x10000))
{
expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM);
- if (optim_flags[OPT_BASE_DISP] && (AnEXVAL == 0))
+ if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXVAL == 0))
{
// od=0 so optimise it out
AMn = MEMPOST; // let's say it's ([bd,An],Xn,od) with od=0 then
// expr[.W][]
AnEXTEN |= EXT_IISNOIW; // Word outer displacement with IS suppressed
AMn = MEMPRE;
-
if (*tok == DOTW)
{
//AnEXTEN|=EXT_IISNOIW; // Word outer displacement
// Defined, absolute values from $FFFF8000..$00007FFF get
// optimized to absolute short
- else if (optim_flags[OPT_BASE_DISP]
+ else if (CHECK_OPTS(OPT_BASE_DISP)
&& ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
&& ((AnEXVAL + 0x8000) < 0x10000))
{
// Check for scale
if (*tok == '*') // ([bd,An/PC],Xn*...)
- {
+ { // scale: *1, *2, *4, *8
tok++;
- if (*tok == CONST) // TODO: I suppose the scale is stored as a CONST and nothing else? So prolly the if is not needed?
- tok++;
-
- switch ((int)*tok++)
+ if (*tok == SYMBOL)
{
- case 1:
- break;
- case 2:
- AnEXTEN |= EXT_TIMES2;
- break;
- case 4:
- AnEXTEN |= EXT_TIMES4;
- break;
- case 8:
- AnEXTEN |= EXT_TIMES8;
- break;
- default:
+ if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
+ return error("scale factor expression must evaluate");
+ switch (AnEXVAL)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
+ }
+ else if (*tok++ != CONST || *tok > 8)
goto badmode;
+ else
+ {
+ switch ((int)*tok++)
+ {
+ case 1:
+ break;
+ case 2:
+ AnIXSIZ |= TIMES2;
+ break;
+ case 4:
+ AnIXSIZ |= TIMES4;
+ break;
+ case 8:
+ AnIXSIZ |= TIMES8;
+ break;
+ default:
+ goto badmode;
+ }
}
}
//Check for ]
if (*tok != ']')
return error("Expected closing bracket ]");
-
tok++; // Eat the bracket
//Check for od
if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK)
goto badmode;
- if (optim_flags[OPT_BASE_DISP] && (AnEXVAL == 0))
+ if (CHECK_OPTS(OPT_BASE_DISP) && (AnEXVAL == 0))
{
// od=0 so optimise it out
AMn = MEMPRE; // let's say it's ([bd,An],Xn,od) with od=0 then
// Defined, absolute values from $FFFF8000..$00007FFF get optimized
// to absolute short
- else if (optim_flags[OPT_BASE_DISP]
+ else if (CHECK_OPTS(OPT_BASE_DISP)
&& ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
&& ((AnEXVAL + 0x8000) < 0x10000))
{
}
else if (*tok == ')')
{
- AMn = PCDISP; // expr(PC)
+ AMn = PCDISP; // expr(PC)
tok++;
goto AnOK;
}
// After a cache keyword only a comma or EOL is allowed
if ((*tok != ',') && (*tok != EOL))
return ERROR;
-
goto AnOK;
}
else if ((*tok >= KW_SFC) && (*tok <= KW_CRP))
// Defined, absolute values from $FFFF8000..$00007FFF get optimized
// to absolute short
- if (optim_flags[OPT_ABS_SHORT]
+ if (CHECK_OPTS(OPT_ABS_SHORT)
&& ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
&& ((AnEXVAL + 0x8000) < 0x10000))
{
AMn = PCINDEXED;
goto AMn_IXN;
}
+
goto badmode;
}