//
-// RMAC - Reboot's Macro Assembler for all Atari computers
+// RMAC - Renamed Macro Assembler for all Atari computers
// PARMODE.C - Addressing Modes Parser Include
-// Copyright (C) 199x Landon Dyer, 2011-2020 Reboot and Friends
+// Copyright (C) 199x Landon Dyer, 2011-2021 Reboot and Friends
// RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
// Source utilised with the kind permission of Landon Dyer
//
// Dn
// An
// # expression
- if ((*tok >= KW_D0) && (*tok <= KW_D7))
+ if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
{
AMn = DREG;
AnREG = *tok++ & 7;
}
- else if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ else if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
{
AMn = AREG;
AnREG = *tok++ & 7;
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])
int ea_PC = 0; // Flag that let us know if we have PC or An relative ea
tok++;
- if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
{
AnREG = *tok++ & 7;
AMn = AINDEXED;
goto AMn_IX0; // Handle ",Xn[.siz][*scale])"
}
- else if ((*tok >= KW_D0) && (*tok <= KW_D7))
+ else if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
{
// Since index register isn't used here, store register number in this field
AnIXREG = *tok++ & 7; // (Dn)
else
return error("unhandled so far");
}
- else if (*tok == KW_PC)
+ else if (*tok == REG68_PC)
{ // (PC,Xn[.siz][*scale])
tok++;
AMn = PCINDEXED;
if (*tok++ != ',')
goto badmode;
- if (*tok < KW_D0 || *tok > KW_A7)
+ if (*tok < REG68_D0 || *tok > REG68_A7)
goto badmode;
AnIXREG = *tok++ & 15;
AnEXTEN |= EXT_BDSIZEW;
if (optim_warn_flag)
- warn("absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
+ warn("o5: absolute value in base displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
}
else
{
tok++;
}
- // Check for address register or PC,
- // suppress base register otherwise
+ // Check for address register or PC, suppress base register
+ // otherwise
- if (*tok == KW_PC)
+ if (*tok == REG68_PC)
{ // ([bd,PC,...
ea_PC = 3; // Set flag in order to set proper value to AMn below when we can make a decision on ea
// (why "3"? Well, MEMPOST is 3 away from PCMPOST, etc. Have a look at amode.h)
AnREG = (7 << 3) | 3; // PC is special case - stuff 011 to register field and 111 to the mode field
tok++;
}
- else if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ else if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
{ // ([bd,An,...
AnREG = (6 << 3) | (*tok & 7);
tok++;
}
- else if ((*tok >= KW_D0) && (*tok <= KW_D7))
+ else if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
{
// ([bd,Dn,...
AnREG = (6 << 3);
else
tok++; // eat the comma
- if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
{
AnIXREG = ((*tok & 7) << 12);
AnEXTEN |= EXT_A;
tok++;
}
- else if ((*tok >= KW_D0) && (*tok <= KW_D7))
+ else if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
{
AnEXTEN |= ((*tok & 7) << 12);
AnEXTEN |= EXT_D;
default:
goto badmode;
}
-
+
}
// Check for od
if (*tok == DOTL)
tok++; // Doesn't matter, we're going for .L anyway
+ WORD od_ea = 0;
+
// od.L
if (!(AnEXTEN & EXT_BS))
- AnEXTEN |= EXT_IISPOSL; // Long outer displacement
+ od_ea = EXT_IISPOSL; // Long outer displacement
else
{
// bd is suppressed, so sticking the od size in bd
- AnEXTEN |= EXT_BDSIZEL;
+ od_ea = EXT_BDSIZEL;
// And of course the expression has to be copied to
// AnBEXPR instead of AnEXPR. Yay. :-/
int i = 0;
{
AnBEXPR[i] = AnEXPR[i];
i++;
- } while (AnEXPR[i] != 'E');
+ }
+ while (AnEXPR[i] != 'E');
AnBEXPR[i] = 'E';
}
&& ((AnEXATTR & (TDB | DEFINED)) == DEFINED)
&& (((uint32_t)AnEXVAL + 0x8000) < 0x10000))
{
- AnEXTEN |= EXT_IISPOSW; // Word outer displacement
+ od_ea = EXT_IISPOSW; // Word outer displacement
AMn = MEMPOST + ea_PC;
+
if (optim_warn_flag)
- warn("absolute value in outer displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
+ warn("o5: absolute value in outer displacement ranging $FFFF8000..$00007FFF optimised to absolute short");
}
+ AnEXTEN |= od_ea;
}
// Check for final closing parenthesis
{
//AnEXTEN|=EXT_IISNOIW; // Word outer displacement with IS suppressed
if (optim_warn_flag)
- warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
+ warn("o5: outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
}
}
tok++; // ([bd,An,Xn.size*scale],od)
// Check for Xn
- if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
{
AnEXTEN |= ((*tok & 7) << 12);
AnEXTEN |= EXT_A;
tok++;
}
- else if ((*tok >= KW_D0) && (*tok <= KW_D7))
+ else if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
{
AnEXTEN |= ((*tok & 7) << 12);
AnEXTEN |= EXT_D;
expr_size = EXT_IISPREW;
if (optim_warn_flag)
- warn("outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
+ warn("o5: outer displacement absolute value from $FFFF8000..$00007FFF optimised to absolute short");
}
}
else
{
// (expr...
+ // We have an aliasing problem here, because a couple of differenct cases end up here:
+ // (a0), 0(a0,d0), (-288,a0,d0.l) can be easily detected and parsed.
+ // But what about (160*150)+4(A1)? With the old scheme, i.e. skip past the left parenthesis and try to parse the inside
+ // tokens will only parse (160*150) and everything else is assumed that it's part of the ea, i.e. +4(a1). This would produce
+ // an error since the parser would expect (a1). The way to work around this used to be to wrap all the displacement in
+ // parenthesis, ((160*150)+4)(a1). But that's something the user really doesn't want to think about.
+ // What we can do is to peek ahead in the token stream and see if we have something that reminds of an expression
+ // (i.e. no register tokens or commas) until we hit an open parenthesis plus a register (parenthesis balance during the scan
+ // has to be maintained of course, otherwise we might be led into false conclusions).
+ TOKEN *look_ahead = tok;
+ int parenthesis_level = 1; // We count the opening parenthesis so we're not at level 0
+ int this_is_an_expression = 0;
+ while (1)
+ {
+ if (*look_ahead == EOL)
+ {
+ // Something really bad happened, abort
+ return error("reached end of line while parsing expression");
+ }
+ if (*look_ahead == '(')
+ {
+ if (parenthesis_level == 0)
+ {
+ if (look_ahead[1] == EOL)
+ {
+ return error("reached end of line while parsing expression");
+ }
+ if ((look_ahead[1] >= REG68_A0 && look_ahead[1] <= REG68_A7) || look_ahead[1] == REG68_PC)
+ {
+ tok--; // Rewind token pointer to start of parenthesis
+ this_is_an_expression = 1;
+ break;
+ }
+ }
+ parenthesis_level++;
+ look_ahead++;
+ continue;
+ }
+ if (*look_ahead == ',' || (*look_ahead >= REG68_A0 && *look_ahead <= REG68_A7))
+ {
+ // Nope, this is a different case, abort
+ break;
+ }
+ if (*look_ahead == ')')
+ {
+ parenthesis_level--;
+ if (parenthesis_level < 0) return error("unbalanced parenthesis in expression");
+ look_ahead++;
+ continue;
+ }
+ if (*look_ahead == ACONST||*look_ahead==FCONST)
+ {
+ look_ahead += 3; // Skip all the data associated with ACONST
+ continue;
+ }
+
+ look_ahead++;
+ }
+
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 == ')')
+ if (*tok == '(')
{
- tok++;
goto CHK_FOR_DISPn;
}
if (*tok++ != ',')
goto badmode;
- if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
{
AnREG = *tok & 7;
tok++;
AnBEXVAL = AnEXVAL;
AnBEXATTR = AnEXATTR;
- if ((*tok >= KW_D0) && (*tok <= KW_D7))
+ if ((*tok >= REG68_D0) && (*tok <= REG68_D7))
{
AnEXTEN |= ((*tok++) & 7) << 12;
// Check for size
else
goto badmode;
}
- else if (*tok == KW_PC)
+ else if (*tok == REG68_PC)
{
if (*++tok == ',')
{ // expr(PC,Xn...)
goto badmode;
}
}
- else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= KW_A0) && (tok[2] <= KW_A7)) && tok[3] == ')')
+ else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= REG68_A0) && (tok[2] <= REG68_A7)) && tok[3] == ')')
{
AMn = APREDEC;
AnREG = tok[2] & 7;
tok += 4;
}
- else if (*tok == KW_CCR)
+ else if (*tok == REG68_CCR)
{
AMn = AM_CCR;
tok++;
goto AnOK;
}
- else if (*tok == KW_SR)
+ else if (*tok == REG68_SR)
{
AMn = AM_SR;
tok++;
goto AnOK;
}
- else if (*tok == KW_USP)
+ else if (*tok == REG68_USP)
{
AMn = AM_USP;
tok++;
AnREG = 2; // Added this for the case of USP used in movec (see CREGlut in mach.c). Hopefully nothing gets broken!
goto AnOK;
}
- else if ((*tok >= KW_IC40) && (*tok <= KW_BC40))
+ else if ((*tok >= REG68_IC40) && (*tok <= REG68_BC40))
{
AMn = CACHES;
- AnREG = *tok++ - KW_IC40;
+ AnREG = *tok++ - REG68_IC40;
// 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))
+ else if ((*tok >= REG68_SFC) && (*tok <= REG68_CRP))
{
AMn = CREG;
- AnREG = (*tok++) - KW_SFC;
+ AnREG = (*tok++) - REG68_SFC;
goto AnOK;
}
- else if ((*tok >= KW_FP0) && (*tok <= KW_FP7))
+ else if ((*tok >= REG68_FP0) && (*tok <= REG68_FP7))
{
AMn = FREG;
AnREG = (*tok++ & 7);
}
- else if ((*tok >= KW_FPIAR) && (*tok <= KW_FPCR))
+ else if ((*tok >= REG68_FPIAR) && (*tok <= REG68_FPCR))
{
AMn = FPSCR;
- AnREG = (1 << ((*tok++) - KW_FPIAR + 10));
+ AnREG = (1 << ((*tok++) - REG68_FPIAR + 10));
}
// expr
// expr.w
// expr[.L]
AMn = ABSL;
- // When PC relative is enforced, check for any symbols that aren't
- // EQU'd, in this case it's an illegal mode
- if ((CHECK_OPTS(OPT_PC_RELATIVE)) && (AnEXATTR & REFERENCED) && (AnEXATTR & DEFINED) && (!(AnEXATTR & EQUATED)))
- return error("relocation not allowed");
-
// .L is forced here
if (*tok == DOTL)
{
+ // When PC relative is enforced, check for any symbols that aren't
+ // EQU'd, in this case it's an illegal mode
+ if ((CHECK_OPTS(OPT_PC_RELATIVE)) && ((AnEXATTR & (DEFINED | REFERENCED | EQUATED)) == (DEFINED | REFERENCED)))
+ return error("relocation not allowed when o30 is enabled");
+
tok++;
- AMn = ABSL;
}
else
{
AMn = ABSW;
if (optim_warn_flag)
- warn("absolute value from $FFFF8000..$00007FFF optimised to absolute short");
+ warn("o0: absolute value from $FFFF8000..$00007FFF optimised to absolute short");
}
}
tok++;
- if ((*tok >= KW_A0) && (*tok <= KW_A7))
+ if ((*tok >= REG68_A0) && (*tok <= REG68_A7))
{
AnREG = *tok++ & 7;
AMn = AINDEXED;
goto AMn_IXN;
}
- else if (*tok == KW_PC)
+ else if (*tok == REG68_PC)
{
if (*++tok == ')')
{