X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=parmode.h;h=521f787e9fe39897b4bfe5d7797fc79b3aabd7cd;hp=4637d72dda1bca9613a2484de82f4bf68ffb9f4c;hb=66be644c3e5fbd7446d86c79e9e51b75c0442b49;hpb=3385b366632d03745033fa6b19faabf60219bc6b diff --git a/parmode.h b/parmode.h index 4637d72..521f787 100644 --- a/parmode.h +++ b/parmode.h @@ -3,7 +3,7 @@ // 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 @@ -24,12 +24,18 @@ } 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]) @@ -44,7 +50,7 @@ // ([bd,PC,Xn],od) else if (*tok == '(') { - ++tok; + tok++; if ((*tok >= KW_A0) && (*tok <= KW_A7)) { @@ -52,11 +58,11 @@ if (*tok == ')') { - ++tok; + tok++; if (*tok == '+') { - ++tok; + tok++; AMn = APOSTINC; } else @@ -66,21 +72,22 @@ } AMn = AINDEXED; - goto AMn_IX0; // Handle ",Xn[.siz][*scale])" + goto AMn_IX0; // Handle ",Xn[.siz][*scale])" } else if (*tok == KW_PC) { // (PC,Xn[.siz][*scale]) - ++tok; + tok++; AMn = PCINDEXED; - // Common index handler; enter here with `tok' pointing at the comma. + // Common index handler; enter here with 'tok' pointing at the + // comma. - AMn_IX0: // Handle indexed with missing expr + AMn_IX0: // Handle indexed with missing expr AnEXVAL = 0; AnEXATTR = ABS | DEFINED; - AMn_IXN: // Handle any indexed (tok -> a comma) + AMn_IXN: // Handle any indexed (tok -> a comma) if (*tok++ != ',') goto badmode; @@ -91,23 +98,24 @@ AnIXREG = *tok++ & 15; switch ((int)*tok) - { // Index reg size: | .W | .L + { // Index reg size: | .W | .L case DOTW: - ++tok; + tok++; default: AnIXSIZ = 0; break; case DOTL: AnIXSIZ = 0x0800; - ++tok; + tok++; break; - case DOTB: // .B not allowed here... + case DOTB: // .B not allowed here... goto badmode; } if (*tok == '*') - { // scale: *1, *2, *4, *8 - ++tok; + { // scale: *1, *2, *4, *8 + tok++; + if (*tok++ != CONST || *tok > 8) goto badmode; @@ -129,7 +137,7 @@ } } - if (*tok++ != ')') // final ")" + if (*tok++ != ')') // final ")" goto badmode; goto AnOK; @@ -139,17 +147,26 @@ goto unmode; } else - { // (expr... + { // (expr... 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 == ',') { @@ -159,7 +176,7 @@ else if (*tok == ')') { AMn = ADISP; - ++tok; + tok++; goto AnOK; } else @@ -174,8 +191,8 @@ } else if (*tok == ')') { - AMn = PCDISP; // expr(PC) - ++tok; + AMn = PCDISP; // expr(PC) + tok++; goto AnOK; } else @@ -185,7 +202,7 @@ goto badmode; } } - else if (*tok=='-' && tok[1]=='(' && ((tok[2]>=KW_A0) && (tok[2]<=KW_A7)) && tok[3]==')') + else if (*tok == '-' && tok[1] == '(' && ((tok[2] >= KW_A0) && (tok[2] <= KW_A7)) && tok[3] == ')') { AMn = APREDEC; AnREG = tok[2] & 7; @@ -194,19 +211,19 @@ 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 @@ -221,30 +238,44 @@ if (expr(AnEXPR, &AnEXVAL, &AnEXATTR, &AnESYM) != OK) return ERROR; +CHK_FOR_DISPn: if (*tok == DOTW) - { // expr.W - ++tok; + { + // expr.W + tok++; AMn = ABSW; + + if ((AnEXATTR & (TDB|DEFINED)) == DEFINED && (AnEXVAL < 0x10000)) + AnEXVAL = (int32_t)(int16_t)AnEXVAL; // Sign extend value + 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)) { @@ -253,7 +284,7 @@ if (*tok == ')') { AMn = ADISP; - ++tok; + tok++; goto AnOK; } @@ -265,7 +296,7 @@ if (*++tok == ')') { AMn = PCDISP; - ++tok; + tok++; goto AnOK; } @@ -281,7 +312,7 @@ ; } -// Cleanup dirty little macros +// Clean up dirty little macros #undef AnOK #undef AMn #undef AnREG @@ -296,3 +327,4 @@ #undef AnESYM #undef AMn_IX0 #undef AMn_IXN +#undef CHK_FOR_DISPn