X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=blobdiff_plain;f=amode.c;h=2608d79793f32493ab4d0cf11dd2f8f678fda7e6;hp=2c89911b3c87fc643f0bf5d7f65b97fdcd10316c;hb=f3c7d186a15b89c39e360b9cc89545a0d24bd6a4;hpb=6c1bc379012b1c1ca369e71e39509f3538042382 diff --git a/amode.c b/amode.c index 2c89911..2608d79 100644 --- a/amode.c +++ b/amode.c @@ -1,51 +1,83 @@ // -// RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System +// RMAC - Reboot's Macro Assembler for all Atari computers // AMODE.C - Addressing Modes -// Copyright (C) 199x Landon Dyer, 2011 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 +// Source utilised with the kind permission of Landon Dyer // #include "amode.h" #include "error.h" -#include "token.h" #include "expr.h" +#include "mach.h" +#include "procln.h" #include "rmac.h" +#include "sect.h" +#include "token.h" #define DEF_KW #include "kwtab.h" #define DEF_MN #include "mntab.h" +extern char unsupport[]; + // Address-mode information -int nmodes; // Number of addr'ing modes found -int am0; // Addressing mode -int a0reg; // Register -TOKEN a0expr[EXPRSIZE]; // Expression -VALUE a0exval; // Expression's value -WORD a0exattr; // Expression's attribute -int a0ixreg; // Index register -int a0ixsiz; // Index register size (and scale) -TOKEN a0oexpr[EXPRSIZE]; // Outer displacement expression -VALUE a0oexval; // Outer displacement value -WORD a0oexattr; // Outer displacement attribute -SYM * a0esym; // External symbol involved in expr - -int am1; // Addressing mode -int a1reg; // Register -TOKEN a1expr[EXPRSIZE]; // Expression -VALUE a1exval; // Expression's value -WORD a1exattr; // Expression's attribute -int a1ixreg; // Index register -int a1ixsiz; // Index register size (and scale) -TOKEN a1oexpr[EXPRSIZE]; // Outer displacement expression -VALUE a1oexval; // Outer displacement value -WORD a1oexattr; // Outer displacement attribute -SYM * a1esym; // External symbol involved in expr +int nmodes; // Number of addr'ing modes found +int am0; // Addressing mode +int a0reg; // Register +TOKEN a0expr[EXPRSIZE]; // Expression +uint64_t a0exval; // Expression's value +WORD a0exattr; // Expression's attribute +int a0ixreg; // Index register +int a0ixsiz; // Index register size (and scale) +TOKEN a0oexpr[EXPRSIZE]; // Outer displacement expression +uint64_t a0oexval; // Outer displacement value +WORD a0oexattr; // Outer displacement attribute +SYM * a0esym; // External symbol involved in expr +TOKEN a0bexpr[EXPRSIZE]; // Base displacement expression +uint64_t a0bexval; // Base displacement value +WORD a0bexattr; // Base displacement attribute +WORD a0bsize; // Base displacement size +WORD a0extension; // 020+ extension address word +WORD am0_030; // ea bits for 020+ addressing modes + +int am1; // Addressing mode +int a1reg; // Register +TOKEN a1expr[EXPRSIZE]; // Expression +uint64_t a1exval; // Expression's value +WORD a1exattr; // Expression's attribute +int a1ixreg; // Index register +int a1ixsiz; // Index register size (and scale) +TOKEN a1oexpr[EXPRSIZE]; // Outer displacement expression +uint64_t a1oexval; // Outer displacement value +WORD a1oexattr; // Outer displacement attribute +SYM * a1esym; // External symbol involved in expr +TOKEN a1bexpr[EXPRSIZE]; // Base displacement expression +uint64_t a1bexval; // Base displacement value +WORD a1bexattr; // Base displacement attribute +WORD a1bsize; // Base displacement size +WORD a1extension; // 020+ extension address word +WORD am1_030; // ea bits for 020+ addressing modes + +int a2reg; // Register for div.l (68020+) +WORD mulmode; // to distinguish between 32 and 64 bit multiplications (68020+) + +int bfparam1; // bfxxx / fmove instruction parameter 1 +int bfparam2; // bfxxx / fmove instruction parameter 2 +int bfval1; // bfxxx / fmove value 1 +int bfval2; // bfxxx / fmove value 2 +TOKEN bf0expr[EXPRSIZE]; // Expression +uint64_t bf0exval; // Expression's value +WORD bf0exattr; // Expression's attribute +SYM * bf0esym; // External symbol involved in expr + +// Function prototypes +int check030bf(void); // -// Parse Addressing Mode +// Parse addressing mode // int amode(int acount) { @@ -54,10 +86,18 @@ int amode(int acount) am0 = am1 = AM_NONE; a0expr[0] = a0oexpr[0] = a1expr[0] = a1oexpr[0] = ENDEXPR; a0exattr = a0oexattr = a1exattr = a1oexattr = 0; - a0esym = a1esym = (SYM *)NULL; + a0esym = a1esym = NULL; + a0bexpr[0] = a1bexpr[0] = ENDEXPR; + a0bexval = a1bexval = 0; + a0bsize = a0extension = a1bsize = a1extension = 0; + am0_030 = am1_030 = 0; + bfparam1 = bfparam2 = 0; + bf0expr[0] = ENDEXPR; + bf0exattr = 0; + bf0esym = NULL; // If at EOL, then no addr modes at all - if (*tok == EOL) + if (*tok.u32 == EOL) return 0; // Parse first addressing mode @@ -66,26 +106,41 @@ int amode(int acount) #define AnREG a0reg #define AnIXREG a0ixreg #define AnIXSIZ a0ixsiz - #define AnEXPR a0expr + #define AnEXPR (TOKENPTR)a0expr #define AnEXVAL a0exval #define AnEXATTR a0exattr - #define AnOEXPR a0oexpr + #define AnOEXPR (TOKENPTR)a0oexpr #define AnOEXVAL a0oexval #define AnOEXATTR a0oexattr #define AnESYM a0esym #define AMn_IX0 am0_ix0 #define AMn_IXN am0_ixn + #define CHK_FOR_DISPn CheckForDisp0 + #define AnBEXPR (TOKENPTR)a0bexpr + #define AnBEXVAL a0bexval + #define AnBEXATTR a0bexattr + #define AnBZISE a0bsize + #define AnEXTEN a0extension + #define AMn_030 am0_030 + #define IS_SUPPRESSEDn IS_SUPPRESSED0 + #define CHECKODn CHECKOD0 #include "parmode.h" - // If caller wants only one mode, return just one (ignore comma); - // If there is no second addressing mode (no comma), then return just one anyway. + // If caller wants only one mode, return just one (ignore comma);. If there + // is no second addressing mode (no comma), then return just one anyway. nmodes = 1; - if (acount == 0 || *tok != ',') + // it's a bitfield instruction--check the parameters inside the {} block + // for validity + if (*tok.u32 == '{') + if (check030bf() == ERROR) + return ERROR; + + if ((acount == 0) || (*tok.u32 != ',')) return 1; // Eat the comma - tok++; + tok.u32++; // Parse second addressing mode #define AnOK a1ok @@ -93,31 +148,79 @@ int amode(int acount) #define AnREG a1reg #define AnIXREG a1ixreg #define AnIXSIZ a1ixsiz - #define AnEXPR a1expr + #define AnEXPR (TOKENPTR)a1expr #define AnEXVAL a1exval #define AnEXATTR a1exattr - #define AnOEXPR a1oexpr + #define AnOEXPR (TOKENPTR)a1oexpr #define AnOEXVAL a1oexval #define AnOEXATTR a1oexattr #define AnESYM a1esym #define AMn_IX0 am1_ix0 #define AMn_IXN am1_ixn + #define CHK_FOR_DISPn CheckForDisp1 + #define AnBEXPR (TOKENPTR)a1bexpr + #define AnBEXVAL a1bexval + #define AnBEXATTR a1bexattr + #define AnBZISE a1bsize + #define AnEXTEN a1extension + #define AMn_030 am1_030 + #define IS_SUPPRESSEDn IS_SUPPRESSED1 + #define CHECKODn CHECKOD1 #include "parmode.h" + // It's a bitfield instruction--check the parameters inside the {} block + // for validity + if (*tok.u32 == '{') + if (check030bf() == ERROR) + return ERROR; + + // At this point, it is legal for 020+ to have a ':'. For example divu.l + // d0,d2:d3 + if (*tok.u32 == ':') + { + if ((activecpu & (CPU_68020 | CPU_68030 | CPU_68040)) == 0) + return error(unsupport); + + // TODO: protect this from combinations like Dx:FPx etc :) + tok.u32++; //eat the colon + + if ((*tok.u32 >= KW_D0) && (*tok.u32 <= KW_D7)) + { + a2reg = (*tok.u32 - KW_D0); + mulmode = 1 << 10; + } + else if ((*tok.u32 >= KW_FP0) && (*tok.u32 <= KW_FP7)) + { + a2reg = (*tok.u32 - KW_FP0); + mulmode = 1 << 10; + } + else + return error("a data or FPU register must follow a :"); + + *tok.u32++; + } + else + { + // If no ':' is present then maybe we have something like divs.l d0,d1 + // which sould translate to divs.l d0,d1:d1 + a2reg = a1reg; + mulmode = 0; + } + nmodes = 2; return 2; // Error messages: - badmode: +badmode: return error("addressing mode syntax"); - unmode: - return error("unimplemented addressing mode"); + //unmode: + //return error("unimplemented addressing mode"); } // -// Parse Register List +// Parse register list // int reglist(WORD * a_rmask) { @@ -133,18 +236,18 @@ int reglist(WORD * a_rmask) for(;;) { - if (*tok >= KW_D0 && *tok <= KW_A7) - r = *tok++ & 15; + if ((*tok.u32 >= KW_D0) && (*tok.u32 <= KW_A7)) + r = *tok.u32++ & 0x0F; else break; - if (*tok == '-') + if (*tok.u32 == '-') { - tok++; + tok.u32++; - if (*tok >= KW_D0 && *tok <= KW_A7) - cnt = *tok++ & 15; - else + if ((*tok.u32 >= KW_D0) && (*tok.u32 <= KW_A7)) + cnt = *tok.u32++ & 0x0F; + else return error("register list syntax"); if (cnt < r) @@ -152,16 +255,119 @@ int reglist(WORD * a_rmask) cnt -= r; } - else + else cnt = 0; while (cnt-- >= 0) rmask |= msktab[r++]; - if (*tok != '/') + if (*tok.u32 != '/') + break; + + tok.u32++; + } + + *a_rmask = rmask; + + return OK; +} + + +// +// Parse FPU register list +// +int fpu_reglist_left(WORD * a_rmask) +{ + static WORD msktab_minus[] = { + 0x0080, 0x0040, 0x0020, 0x0010, + 0x0008, 0x0004, 0x0002, 0x0001 + }; + + WORD rmask = 0; + int r, cnt; + + for(;;) + { + if ((*tok.u32 >= KW_FP0) && (*tok.u32 <= KW_FP7)) + r = *tok.u32++ & 0x07; + else + break; + + if (*tok.u32 == '-') + { + tok.u32++; + + if ((*tok.u32 >= KW_FP0) && (*tok.u32 <= KW_FP7)) + cnt = *tok.u32++ & 0x07; + else + return error("register list syntax"); + + if (cnt < r) + return error("register list order"); + + cnt -= r; + } + else + cnt = 0; + + r = 0; + + while (cnt-- >= 0) + rmask |= msktab_minus[r++]; + + if (*tok.u32 != '/') + break; + + tok.u32++; + } + + *a_rmask = rmask; + + return OK; +} + + +int fpu_reglist_right(WORD * a_rmask) +{ + static WORD msktab_plus[] = { + 0x0001, 0x0002, 0x0004, 0x0008, + 0x0010, 0x0020, 0x0040, 0x0080 + }; + + WORD rmask = 0; + int r, cnt; + + for(;;) + { + if ((*tok.u32 >= KW_FP0) && (*tok.u32 <= KW_FP7)) + r = *tok.u32++ & 0x07; + else break; - tok++; + if (*tok.u32 == '-') + { + tok.u32++; + + if ((*tok.u32 >= KW_FP0) && (*tok.u32 <= KW_FP7)) + cnt = *tok.u32++ & 0x07; + else + return error("register list syntax"); + + if (cnt < r) + return error("register list order"); + + cnt -= r; + } + else + cnt = 0; + + while (cnt-- >= 0) + rmask |= msktab_plus[r++]; + + if (*tok.u32 != '/') + break; + + tok.u32++; } *a_rmask = rmask; @@ -169,3 +375,101 @@ int reglist(WORD * a_rmask) return OK; } + +// +// Check for bitfield instructions extra params +// These are 020+ instructions and have the following syntax: +// bfxxx {param1,param2} +// param1/2 are either data registers or immediate values +// +int check030bf(void) +{ + CHECK00; + tok.u32++; + + if (*tok.u32 == CONST) + { + tok.u32++; +// bfval1 = (int)*(uint64_t *)tok.u32; + bfval1 = (int)*tok.u64; + + // Do=0, offset=immediate - shift it to place + bfparam1 = (0 << 11); +// tok.u32++; +// tok.u32++; + tok.u64++; + } + else if (*tok.u32 == SYMBOL) + { + if (expr((TOKENPTR)bf0expr, &bf0exval, &bf0exattr, &bf0esym) != OK) + return ERROR; + + if (!(bf0exattr & DEFINED)) + return error("bfxxx offset: immediate value must evaluate"); + + bfval1 = (int)bf0exval; + + // Do=0, offset=immediate - shift it to place + bfparam1 = (0 << 11); + } + else if ((*tok.u32 >= KW_D0) && (*tok.u32 <= KW_D7)) + { + // Do=1, offset=data register - shift it to place + bfparam1 = (1 << 11); + bfval1 = (*(int *)tok.u32 - 128); + tok.u32++; + } + else + return ERROR; + + // Eat the ':', if any + if (*tok.u32 == ':') + tok.u32++; + + if (*tok.u32 == '}' && tok.u32[1] == EOL) + { + // It is ok to have }, EOL here - it might be "fmove fpn, {dx}" + tok.u32++; + return OK; + } + + if (*tok.u32 == CONST) + { + tok.u32++; +// bfval2 = (int)*(uint64_t *)tok.u32; + bfval2 = (int)*tok.u64; + + // Do=0, offset=immediate - shift it to place + bfparam2 = (0 << 5); +// tok.u32++; +// tok.u32++; + tok.u64++; + } + else if (*tok.u32 == SYMBOL) + { + if (expr((TOKENPTR)bf0expr, &bf0exval, &bf0exattr, &bf0esym) != OK) + return ERROR; + + bfval2 = (int)bf0exval; + + if (!(bf0exattr & DEFINED)) + return error("bfxxx width: immediate value must evaluate"); + + // Do=0, offset=immediate - shift it to place + bfparam2 = (0 << 5); + } + else if ((*tok.u32 >= KW_D0) && (*tok.u32 <= KW_D7)) + { + // Do=1, offset=data register - shift it to place + bfval2 = ((*(int *)tok.u32 - 128)); + bfparam2 = (1 << 5); + tok.u32++; + } + else + return ERROR; + + tok.u32++; // Eat the '}' + + return OK; +} +