From: Shamus Hammons Date: Wed, 7 Aug 2019 23:24:52 +0000 (-0500) Subject: The deed has been accomplished. X-Git-Tag: v2.1.0~65 X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?p=rmac;a=commitdiff_plain;h=29fa5dcf504b966803063a1c2891f58f97126d04 The deed has been accomplished. As far as I can tell, there should be no more regressions, but that's no guarantee of anything. Assuming no more are found, this should go out as version 2.0.0. :-D --- diff --git a/6502.c b/6502.c index 27a8e1a..4c188cf 100644 --- a/6502.c +++ b/6502.c @@ -645,46 +645,39 @@ badmode: if (sloc > 0x10000L) fatal("6502 code pointer > 64K"); -//Now why use this instead of at_eol()? - if (*tok != EOL) - error(extra_stuff); + ErrorIfNotAtEOL(); } // // Generate 6502 object output file. +// ggn: Converted to COM/EXE/XEX output format // -// ggn: converted into a com/exe/xex output format void m6502obj(int ofd) { - uint16_t exeheader[3]; - int headsize = 6; - uint16_t * headpoint = exeheader; + uint8_t header[4]; CHUNK * ch = sect[M6502].scode; - // If no 6502 code was generated, forget it + // If no 6502 code was generated, bail out if ((ch == NULL) || (ch->challoc == 0)) return; - exeheader[0] = 0xFFFF; // Mandatory for first segment register uint8_t * p = ch->chptr; + // Write out mandatory $FFFF header + header[0] = header[1] = 0xFF; + ssize_t unused = write(ofd, header, 2); + for(uint16_t * l=&orgmap[0][0]; lstart && dsp_written_data_in_current_org) + { + dsp_currentorg->end = chptr; + dsp_currentorg++; + } + + // Maybe we switched from a non-DSP section (TEXT, DATA, etc) and + // scode isn't initialised yet. Not that it's going to be a valid + // scenario, but if we try it anyhow it's going to lead to a crash. So + // let's fudge a value of 0 and get on with it. + orgaddr = (scode != NULL ? sloc : 0); + SaveSection(); + + if (tok[1] != ':') + return error(syntax_error); + + int sectionToSwitch = 0; + + switch (tok[0]) + { + case KW_X: + dsp_currentorg->memtype = ORG_X; + sectionToSwitch = M56001X; + break; + + case KW_Y: + dsp_currentorg->memtype = ORG_Y; + sectionToSwitch = M56001Y; + break; + + case KW_P: + dsp_currentorg->memtype = ORG_P; + sectionToSwitch = M56001P; + break; + + case KW_L: + dsp_currentorg->memtype = ORG_L; + sectionToSwitch = M56001L; + break; + + default: + return error("unknown type in ORG"); + } + + if ((obj_format == LOD) || (obj_format == P56)) + SwitchSection(sectionToSwitch); + + tok += 2; + chcheck(3); // Ensure we got a valid address to write + dsp_currentorg->chunk = scode; // Mark down which chunk this org starts from (will be needed when outputting) + + if (*tok == EOL) + { + // Well, the user didn't specify an address at all so we'll have to + // use the last used address of that section (or 0 if there wasn't one) + address = orgaddr; + dsp_currentorg->start = chptr; + dsp_currentorg->orgadr = orgaddr; + } + else + { + if (abs_expr(&address) == ERROR) + { + error("cannot determine org'd address"); + return ERROR; + } + + dsp_currentorg->start = chptr; + dsp_currentorg->orgadr = (uint32_t)address; + sect[cursect].orgaddr = (uint32_t)address; + } + + if (address > DSP_MAX_RAM) + { + return error(range_error); + } + + dsp_written_data_in_current_org = 0; + + // Copied from 6502 above: kludge `lsloc' so the listing generator + // doesn't try to spew out megabytes. + lsloc = sloc = (int32_t)address; +// N.B.: It seems that by enabling this, even though it works elsewhere, will cause symbols to royally fuck up. Will have to do some digging to figure out why. +// orgactive = 1; } - at_eol(); + ErrorIfNotAtEOL(); return 0; } @@ -830,7 +918,7 @@ int d_assert(void) break; } - at_eol(); + ErrorIfNotAtEOL(); return 0; } @@ -1011,7 +1099,7 @@ int d_ds(WORD siz) dep_block(eval, siz, 0, (WORD)(DEFINED | ABS), NULL); } - at_eol(); + ErrorIfNotAtEOL(); return 0; } @@ -1029,7 +1117,9 @@ int d_dc(WORD siz) return error("illegal initialization of section"); // Do an auto_even if it's not BYTE sized (hmm, should we be doing this???) - if (cursect != M6502 && (siz != SIZB) && (sloc & 1)) + if ((cursect != M6502) && (cursect != M56001P) && (cursect != M56001X) + && (cursect != M56001Y) && (cursect != M56001L) + && (siz != SIZB) && (sloc & 1)) auto_even(); // Check to see if we're trying to set LONGS on a non 32-bit aligned @@ -1086,6 +1176,138 @@ int d_dc(WORD siz) uint16_t tdb = eattr & TDB; uint16_t defined = eattr & DEFINED; +// N.B.: This is awful. This needs better handling, rather than just bodging something in that, while works, is basically an ugly wart on the assembler. !!! FIX !!! + if (dsp56001) + { + if (cursect != M56001L) + { + if (!defined) + { + AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf); + D_dsp(0); + } + else + { + if (eattr & FLOAT) + { + double fval = *(double *)&eval; + + if (fval >= 1) + { + warn("value clamped to +1."); + eval = 0x7fffff; + } + else if (fval <= -1) + { + warn("value clamped to -1."); + eval = 0x800000; + } + else + { + // Convert fraction to 24 bits fixed point with sign and rounding + // Yeah, that cast to int32_t has to be there because casting + // a float to unsigned int is "undefined" according to the C + // standard. Which most compilers seem to do the sensible thing + // and just cast the f**king value properly, except gcc 4.x.x + // for arm (tested on raspbian). + // Thanks, C and gcc! Thanks for making me waste a few hours \o/ + eval = 0;//!!! FIX !!! (uint32_t)(int32_t)round(fval*(1 << 23)); + } + } + else + { + if ((uint32_t)eval + 0x1000000 >= 0x2000000) + return error(range_error); + } + + // Deposit DSP word (24-bit) + D_dsp(eval); + } + } + else + { + // In L: we deposit stuff to both X: and Y: instead + // We will be a bit lazy and require that there is a 2nd value in the same source line. + // (Motorola's assembler can parse 12-digit hex values, which we can't do at the moment) + // This of course requires to parse 2 values in one pass. + // If there isn't another value in this line, assume X: value is 0. + int secondword = 0; + uint32_t evaly; +l_parse_loop: + + if (!defined) + { + AddFixup(FU_DSPIMM24 | FU_SEXT, sloc, exprbuf); + D_dsp(0); + } + else + { + if (eattr & FLOAT) + { + float fval = *(float *)&eval; + if (fval >= 1) + { + warn("value clamped to +1."); + eval = 0x7fffff; + } + else if (fval <= -1) + { + warn("value clamped to -1."); + eval = 0x800000; + } + else + { + // Convert fraction to 24 bits fixed point with sign and rounding + // Yeah, that cast to int32_t has to be there because casting + // a float to unsigned int is "undefined" according to the C + // standard. Which most compilers seem to do the sensible thing + // and just cast the f**king value properly, except gcc 4.x.x + // for arm (tested on raspbian). + // Thanks, C and gcc! Thanks for making me waste a few hours \o/ + eval = 0;//!!! FIX !!! (uint32_t)(int32_t)round(fval*(1 << 23)); + } + } + else + { + if (eval + 0x1000000 >= 0x2000000) + return error(range_error); + } + + // Parse 2nd value if we didn't do this yet + if (secondword == 0) + { + evaly = (uint32_t)eval; + secondword = 1; + + if (*tok != ':') + { + // If we don't have a : then we're probably at EOL, + // which means the X: value will be 0 + eval = 0; + ErrorIfNotAtEOL(); + } + else + { + tok++; // Eat the comma; + + if (expr(exprbuf, &eval, &eattr, NULL) != OK) + return 0; + + defined = (WORD)(eattr & DEFINED); + goto l_parse_loop; + } + } + + // Deposit DSP words (24-bit) + D_dsp(eval); + D_dsp(evaly); + sloc--; // We do write 2 DSP words but as far as L: space is concerned we actually advance our counter by one + } + + } + goto comma; + } + switch (siz) { case SIZB: @@ -1252,7 +1474,7 @@ comma: break; } - at_eol(); + ErrorIfNotAtEOL(); return 0; } @@ -1480,7 +1702,7 @@ int d_comm(void) return 0; sym->svalue = eval; // Install common symbol's size - at_eol(); + ErrorIfNotAtEOL(); return 0; } @@ -1612,7 +1834,7 @@ int d_56001(void) rgpu = rdsp = robjproc = 0; SaveSection(); - if (obj_format == LOD || obj_format == P56) + if ((obj_format == LOD) || (obj_format == P56)) SwitchSection(M56001P); return 0; diff --git a/dsp56k.h b/dsp56k.h index 18395fc..7b61d63 100644 --- a/dsp56k.h +++ b/dsp56k.h @@ -6,7 +6,8 @@ // Source utilised with the kind permission of Landon Dyer // -#pragma once +#ifndef __DSP56K_H__ +#define __DSP56K_H__ #include "rmac.h" #include "sect.h" @@ -36,7 +37,8 @@ extern DSP_ORG dsp_orgmap[1024]; // Mark all 56001 org changes extern DSP_ORG * dsp_currentorg; extern int dsp_written_data_in_current_org; -#define dprintf(...) p_buf += sprintf(p_buf, __VA_ARGS__) +#define D_printf(...) chptr += sprintf(chptr, __VA_ARGS__) // Exported functions +#endif // __DSP56K_H__ diff --git a/dsp56k_amode.c b/dsp56k_amode.c index 6c8bc25..f5f6766 100644 --- a/dsp56k_amode.c +++ b/dsp56k_amode.c @@ -76,73 +76,73 @@ static inline LONG checkea(const uint32_t termchar, const int strings); #define P_ERRORS 3 const char *ea_errors[][12] = { - // X: - { - "unrecognised X: parallel move syntax: expected '(' after 'X:-'", // 0 - "unrecognised X: parallel move syntax: expected ')' after 'X:-(Rn'", // 1 - "unrecognised X: parallel move syntax: expected R0-R7 after 'X:-('", // 2 - "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn+'", // 3 - "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn+Nn)'", // 4 - "unrecognised X: parallel move syntax: expected ')' after 'X:(Rn+Nn'", // 5 - "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)+Nn'", // 6 - "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)+'", // 7 - "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)-Nn'", // 8 - "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)-'", // 9 - "unrecognised X: parallel move syntax: expected '+', '-' or ',' after 'X:(Rn)'", // 10 - "unrecognised X: parallel move syntax: expected '+' or ')' after 'X:(Rn'", // 11 - }, - // Y: - { - "unrecognised Y: parallel move syntax: expected '(' after 'Y:-'", // 0 - "unrecognised Y: parallel move syntax: expected ')' after 'Y:-(Rn'", // 1 - "unrecognised Y: parallel move syntax: expected R0-R7 after 'Y:-('", // 2 - "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn+'", // 3 - "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn+Nn)'", // 4 - "unrecognised Y: parallel move syntax: expected ')' after 'Y:(Rn+Nn'", // 5 - "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)+Nn'", // 6 - "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)+'", // 7 - "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)-Nn'", // 8 - "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)-'", // 9 - "unrecognised Y: parallel move syntax: expected '+', '-' or ',' after 'Y:(Rn)'", // 10 - "unrecognised Y: parallel move syntax: expected '+' or ')' after 'Y:(Rn'", // 11 - }, - // L: - { - "unrecognised L: parallel move syntax: expected '(' after 'L:-'", // 0 - "unrecognised L: parallel move syntax: expected ')' after 'L:-(Rn'", // 1 - "unrecognised L: parallel move syntax: expected R0-R7 after 'L:-('", // 2 - "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn+'", // 3 - "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn+Nn)'", // 4 - "unrecognised L: parallel move syntax: expected ')' after 'L:(Rn+Nn'", // 5 - "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)+Nn'", // 6 - "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)+'", // 7 - "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)-Nn'", // 8 - "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)-'", // 9 - "unrecognised L: parallel move syntax: expected '+', '-' or ',' after 'L:(Rn)'", // 10 - "unrecognised L: parallel move syntax: expected '+' or ')' after 'L:(Rn'", // 11 - }, - // P: - { - "unrecognised P: effective address syntax: expected '(' after 'P:-'", // 0 - "unrecognised P: effective address syntax: expected ')' after 'P:-(Rn'", // 1 - "unrecognised P: effective address syntax: expected R0-R7 after 'P:-('", // 2 - "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn+'", // 3 - "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn+Nn)'", // 4 - "unrecognised P: effective address syntax: expected ')' after 'P:(Rn+Nn'", // 5 - "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)+Nn'", // 6 - "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)+'", // 7 - "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)-Nn'", // 8 - "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)-'", // 9 - "unrecognised P: effective address syntax: expected '+', '-' or ',' after 'P:(Rn)'", // 10 - "unrecognised P: effective address syntax: expected '+' or ')' after 'P:(Rn'", // 11 - } + // X: + { + "unrecognised X: parallel move syntax: expected '(' after 'X:-'", // 0 + "unrecognised X: parallel move syntax: expected ')' after 'X:-(Rn'", // 1 + "unrecognised X: parallel move syntax: expected R0-R7 after 'X:-('", // 2 + "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn+'", // 3 + "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn+Nn)'", // 4 + "unrecognised X: parallel move syntax: expected ')' after 'X:(Rn+Nn'", // 5 + "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)+Nn'", // 6 + "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)+'", // 7 + "unrecognised X: parallel move syntax: expected same register number in Rn and Nn for 'X:(Rn)-Nn'", // 8 + "unrecognised X: parallel move syntax: expected N0-N7 after 'X:(Rn)-'", // 9 + "unrecognised X: parallel move syntax: expected '+', '-' or ',' after 'X:(Rn)'", // 10 + "unrecognised X: parallel move syntax: expected '+' or ')' after 'X:(Rn'", // 11 + }, + // Y: + { + "unrecognised Y: parallel move syntax: expected '(' after 'Y:-'", // 0 + "unrecognised Y: parallel move syntax: expected ')' after 'Y:-(Rn'", // 1 + "unrecognised Y: parallel move syntax: expected R0-R7 after 'Y:-('", // 2 + "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn+'", // 3 + "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn+Nn)'", // 4 + "unrecognised Y: parallel move syntax: expected ')' after 'Y:(Rn+Nn'", // 5 + "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)+Nn'", // 6 + "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)+'", // 7 + "unrecognised Y: parallel move syntax: expected same register number in Rn and Nn for 'Y:(Rn)-Nn'", // 8 + "unrecognised Y: parallel move syntax: expected N0-N7 after 'Y:(Rn)-'", // 9 + "unrecognised Y: parallel move syntax: expected '+', '-' or ',' after 'Y:(Rn)'", // 10 + "unrecognised Y: parallel move syntax: expected '+' or ')' after 'Y:(Rn'", // 11 + }, + // L: + { + "unrecognised L: parallel move syntax: expected '(' after 'L:-'", // 0 + "unrecognised L: parallel move syntax: expected ')' after 'L:-(Rn'", // 1 + "unrecognised L: parallel move syntax: expected R0-R7 after 'L:-('", // 2 + "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn+'", // 3 + "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn+Nn)'", // 4 + "unrecognised L: parallel move syntax: expected ')' after 'L:(Rn+Nn'", // 5 + "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)+Nn'", // 6 + "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)+'", // 7 + "unrecognised L: parallel move syntax: expected same register number in Rn and Nn for 'L:(Rn)-Nn'", // 8 + "unrecognised L: parallel move syntax: expected N0-N7 after 'L:(Rn)-'", // 9 + "unrecognised L: parallel move syntax: expected '+', '-' or ',' after 'L:(Rn)'", // 10 + "unrecognised L: parallel move syntax: expected '+' or ')' after 'L:(Rn'", // 11 + }, + // P: + { + "unrecognised P: effective address syntax: expected '(' after 'P:-'", // 0 + "unrecognised P: effective address syntax: expected ')' after 'P:-(Rn'", // 1 + "unrecognised P: effective address syntax: expected R0-R7 after 'P:-('", // 2 + "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn+'", // 3 + "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn+Nn)'", // 4 + "unrecognised P: effective address syntax: expected ')' after 'P:(Rn+Nn'", // 5 + "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)+Nn'", // 6 + "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)+'", // 7 + "unrecognised P: effective address syntax: expected same register number in Rn and Nn for 'P:(Rn)-Nn'", // 8 + "unrecognised P: effective address syntax: expected N0-N7 after 'P:(Rn)-'", // 9 + "unrecognised P: effective address syntax: expected '+', '-' or ',' after 'P:(Rn)'", // 10 + "unrecognised P: effective address syntax: expected '+' or ')' after 'P:(Rn'", // 11 + } }; enum { - NUM_NORMAL = 0, - NUM_FORCE_LONG = 1, - NUM_FORCE_SHORT = 2 + NUM_NORMAL = 0, + NUM_FORCE_LONG = 1, + NUM_FORCE_SHORT = 2 }; // @@ -150,106 +150,114 @@ enum // static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnEXVAL, WORD * AnEXATTR, SYM ** AnESYM, LONG *memspace, LONG *perspace, const int operand) { - if (*tok == KW_A || *tok == KW_B) - { - *am = M_ACC56; - *areg = *tok++; - return OK; - } - else if (*tok == '#') - { - tok++; + if (*tok == KW_A || *tok == KW_B) + { + *am = M_ACC56; + *areg = *tok++; + return OK; + } + else if (*tok == '#') + { + tok++; - if (*tok == '<') - { - // Immediate Short Addressing Mode Force Operator - tok++; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; - if (*AnEXVAL > 0xfff && *AnEXVAL<-4096) - return error("immediate short addressing mode forced but address is bigger than $fff"); - if ((int32_t)*AnEXVAL <= 0xff && (int32_t)*AnEXVAL>-0x100) - { - *am = M_DSPIM8; - return OK; - } - *am = M_DSPIM12; - return OK; - } - else if (*tok == '>') - { - // Immediate Long Addressing Mode Force Operator - tok++; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; - if ((int32_t)*AnEXVAL > 0xffffff || (int32_t)*AnEXVAL < -0xffffff) - return error("long immediate is bigger than $ffffff"); - *am = M_DSPIM; - return OK; - } + if (*tok == '<') + { + // Immediate Short Addressing Mode Force Operator + tok++; + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; + if (*AnEXVAL > 0xFFF && *AnEXVAL < -4096) + return error("immediate short addressing mode forced but address is bigger than $FFF"); - if (*AnEXATTR & DEFINED) - { + if ((int32_t)*AnEXVAL <= 0xFF && (int32_t)*AnEXVAL > -0x100) + { + *am = M_DSPIM8; + return OK; + } + + *am = M_DSPIM12; + return OK; + } + else if (*tok == '>') + { + // Immediate Long Addressing Mode Force Operator + tok++; + + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; + + if ((int32_t)*AnEXVAL > 0xFFFFFF || (int32_t)*AnEXVAL < -0xFFFFFF) + return error("long immediate is bigger than $FFFFFF"); + + *am = M_DSPIM; + return OK; + } + + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; + + if (*AnEXATTR & DEFINED) + { if ((int32_t)*AnEXVAL < 0x100 && (int32_t)*AnEXVAL >= -0x100) { - *AnEXVAL &= 0xff; + *AnEXVAL &= 0xFF; *am = M_DSPIM8; } - else if (*AnEXVAL < 0x1000) - *am = M_DSPIM12; - else - *am = M_DSPIM; - } - else - { - // We have no clue what size our immediate will be - // so we have to assume the worst - *am = M_DSPIM; - } - return OK; - } - else if (*tok >= KW_X0 && *tok <= KW_Y1) - { - *am = M_ALU24; - *areg = *tok++; - return OK; - } - else if (*tok == KW_X && *(tok + 1) == ':') - { - tok = tok + 2; - if (*tok == CONST || *tok == FCONST || *tok == SYMBOL) - { - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; + else if (*AnEXVAL < 0x1000) + *am = M_DSPIM12; + else + *am = M_DSPIM; + } + else + { + // We have no clue what size our immediate will be + // so we have to assume the worst + *am = M_DSPIM; + } + + return OK; + } + else if (*tok >= KW_X0 && *tok <= KW_Y1) + { + *am = M_ALU24; + *areg = *tok++; + return OK; + } + else if (*tok == KW_X && *(tok + 1) == ':') + { + tok = tok + 2; + + if (*tok == CONST || *tok == FCONST || *tok == SYMBOL) + { + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; + if (*AnEXATTR & DEFINED) { - if (*AnEXVAL > 0xffffff) - return error("long address is bigger than $ffffff"); + if (*AnEXVAL > 0xFFFFFF) + return error("long address is bigger than $FFFFFF"); + *memspace = 0 << 6; // Mark we're on X memory space - // Check if value is between $ffc0 and $ffff, AKA X:pp - { - uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits - if ((temp >= 0xffffffc0 /* Check for 32bit sign extended number */ - && ((int32_t)*AnEXVAL<0)) /* Check if 32bit signed number is negative*/ - ||(*AnEXVAL<0xffff && *AnEXVAL>=0x8000)) /* Check if 16bit number is negative*/ - { - *AnEXVAL = temp; - *am = M_DSPPP; - *memspace = 0 << 6; // Mark we're on X memory space - *perspace = 0 << 16; // Mark we're on X peripheral space - *areg = *AnEXVAL & 0x3f; // Since this is only going to get used in dsp_ea_imm5... - return OK; - } + // Check if value is between $FFC0 and $FFFF, AKA X:pp + uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits + if ((temp >= 0xFFFFFFC0 /* Check for 32bit sign extended number */ + && ((int32_t)*AnEXVAL < 0)) /* Check if 32bit signed number is negative*/ + || (*AnEXVAL < 0xFFFF && *AnEXVAL >= 0x8000)) /* Check if 16bit number is negative*/ + { + *AnEXVAL = temp; + *am = M_DSPPP; + *memspace = 0 << 6; // Mark we're on X memory space + *perspace = 0 << 16; // Mark we're on X peripheral space + *areg = *AnEXVAL & 0x3F; // Since this is only going to get used in dsp_ea_imm5... + return OK; } // If the symbol/expression is defined then check for valid range. // Otherwise the value had better fit or Fixups will bark! - if (*AnEXVAL > 0x3f) + if (*AnEXVAL > 0x3F) { *am = M_DSPEA; *areg = DSP_EA_ABS; @@ -266,33 +274,36 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE *am = M_DSPEA; *areg = DSP_EA_ABS; } - return OK; - } - else if (*tok == '<') - { - // X:aa - // Short Addressing Mode Force Operator in the case of '<' - tok++; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; + + return OK; + } + else if (*tok == '<') + { + // X:aa + // Short Addressing Mode Force Operator in the case of '<' + tok++; + + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; // If the symbol/expression is defined then check for valid range. // Otherwise the value had better fit or Fixups will bark! if (*AnEXATTR & DEFINED) { - if (*AnEXVAL > 0x3f) - return error("short addressing mode forced but address is bigger than $3f"); + if (*AnEXVAL > 0x3F) + return error("short addressing mode forced but address is bigger than $3F"); } - else - { - // Mark it as a fixup - deposit_extra_ea = DEPOSIT_EXTRA_FIXUP; - } - *am = M_DSPAA; - *memspace = 0 << 6; // Mark we're on X memory space - *areg = (int)*AnEXVAL; // Since this is only going to get used in dsp_ea_imm5... - return OK; - } + else + { + // Mark it as a fixup + deposit_extra_ea = DEPOSIT_EXTRA_FIXUP; + } + + *am = M_DSPAA; + *memspace = 0 << 6; // Mark we're on X memory space + *areg = (int)*AnEXVAL; // Since this is only going to get used in dsp_ea_imm5... + return OK; + } else if (*tok == '>') { // Long Addressing Mode Force Operator @@ -302,12 +313,13 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE { if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) return ERROR; + if (*AnEXATTR&DEFINED) { - if (*AnEXVAL > 0xffffff) - return error("long address is bigger than $ffffff"); - *memspace = 0 << 6; // Mark we're on X memory space + if (*AnEXVAL > 0xFFFFFF) + return error("long address is bigger than $FFFFFF"); + *memspace = 0 << 6; // Mark we're on X memory space *am = M_DSPEA; *areg = DSP_EA_ABS; } @@ -321,73 +333,75 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE return OK; } } - else if (*tok == SHL) // '<<' - { - // I/O Short Addressing Mode Force Operator - // X:pp - tok++; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; + else if (*tok == SHL) // '<<' + { + // I/O Short Addressing Mode Force Operator + // X:pp + tok++; + + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; // If the symbol/expression is defined then check for valid range. // Otherwise the value had better fit or Fixups will bark! if (*AnEXATTR & DEFINED) { *AnEXVAL = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits - if (*AnEXVAL < 0xffffffc0) - return error("I/O Short Addressing Mode addresses must be between $ffc0 and $ffff"); + + if (*AnEXVAL < 0xFFFFFFC0) + return error("I/O Short Addressing Mode addresses must be between $FFC0 and $FFFF"); } - *am = M_DSPPP; - *memspace = 0 << 6; // Mark we're on X memory space - *perspace = 0 << 16; // Mark we're on X peripheral space - *areg = *AnEXVAL & 0x3f; // Since this is only going to get used in dsp_ea_imm5... - return OK; - } - if ((*areg = checkea(0, X_ERRORS)) != ERROR) - { - // TODO: what if we need M_DSPAA here???? - *memspace = 0 << 6; // Mark we're on X memory space - *am = M_DSPEA; - return OK; - } - else - return ERROR; + *am = M_DSPPP; + *memspace = 0 << 6; // Mark we're on X memory space + *perspace = 0 << 16; // Mark we're on X peripheral space + *areg = *AnEXVAL & 0x3f; // Since this is only going to get used in dsp_ea_imm5... + return OK; + } - } - else if (*tok == KW_Y && *(tok + 1) == ':') - { - tok = tok + 2; + if ((*areg = checkea(0, X_ERRORS)) != ERROR) + { + // TODO: what if we need M_DSPAA here???? + *memspace = 0 << 6; // Mark we're on X memory space + *am = M_DSPEA; + return OK; + } + else + return ERROR; + } + else if (*tok == KW_Y && *(tok + 1) == ':') + { + tok = tok + 2; - if (*tok == CONST || *tok == FCONST || *tok == SYMBOL) - { - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; - if (*AnEXVAL > 0xffffff) - return error("long address is bigger than $ffffff"); - *memspace = 1 << 6; // Mark we're on Y memory space + if (*tok == CONST || *tok == FCONST || *tok == SYMBOL) + { + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; + + if (*AnEXVAL > 0xFFFFFF) + return error("long address is bigger than $FFFFFF"); + + *memspace = 1 << 6; // Mark we're on Y memory space // Check if value is between $ffc0 and $ffff, AKA Y:pp - { - uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits - if ((temp >= 0xffffffc0 /* Check for 32bit sign extended number */ - && ((int32_t)*AnEXVAL<0)) /* Check if 32bit signed number is negative*/ - || (*AnEXVAL<0xffff && *AnEXVAL >= 0x8000)) /* Check if 16bit number is negative*/ - { - *AnEXVAL = temp; - *am = M_DSPPP; - *perspace = 1 << 16; // Mark we're on X peripheral space - *areg = *AnEXVAL & 0x3f; // Since this is only going to get used in dsp_ea_imm5... - return OK; - } + uint32_t temp = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits + if ((temp >= 0xFFFFFFC0 /* Check for 32bit sign extended number */ + && ((int32_t)*AnEXVAL < 0)) /* Check if 32bit signed number is negative*/ + || (*AnEXVAL < 0xFFFF && *AnEXVAL >= 0x8000)) /* Check if 16bit number is negative*/ + { + *AnEXVAL = temp; + *am = M_DSPPP; + *perspace = 1 << 16; // Mark we're on X peripheral space + *areg = *AnEXVAL & 0x3F; // Since this is only going to get used in dsp_ea_imm5... + return OK; } // If the symbol/expression is defined then check for valid range. // Otherwise the value had better fit or Fixups will bark! if (*AnEXATTR & DEFINED) { - if (*AnEXVAL > 0x3f) + if (*AnEXVAL > 0x3F) { *am = M_DSPEA; *areg = DSP_EA_ABS; @@ -403,53 +417,56 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE *areg = DSP_EA_ABS; } - return OK; - } - else if (*tok == '<') - { - // Y:aa - // Short Addressing Mode Force Operator in the case of '<' - tok++; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; + return OK; + } + else if (*tok == '<') + { + // Y:aa + // Short Addressing Mode Force Operator in the case of '<' + tok++; + + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; // If the symbol/expression is defined then check for valid range. // Otherwise the value had better fit or Fixups will bark! if (*AnEXATTR & DEFINED) { - if (*AnEXVAL > 0x3f) + if (*AnEXVAL > 0x3F) { - warn("short addressing mode forced but address is bigger than $3f - switching to long"); + warn("short addressing mode forced but address is bigger than $3F - switching to long"); *am = M_DSPEA; *memspace = 1 << 6; // Mark we're on Y memory space *areg = DSP_EA_ABS; return OK; } } - else - { - // Mark it as a fixup - deposit_extra_ea = DEPOSIT_EXTRA_FIXUP; - } + else + { + // Mark it as a fixup + deposit_extra_ea = DEPOSIT_EXTRA_FIXUP; + } - *am = M_DSPAA; - *memspace = 1 << 6; // Mark we're on Y memory space - *areg = (int)*AnEXVAL; // Since this is only going to get used in dsp_ea_imm5... - return OK; - } - else if (*tok == '>') - { - // Long Addressing Mode Force Operator + *am = M_DSPAA; + *memspace = 1 << 6; // Mark we're on Y memory space + *areg = (int)*AnEXVAL; // Since this is only going to get used in dsp_ea_imm5... + return OK; + } + else if (*tok == '>') + { + // Long Addressing Mode Force Operator tok++; if (*tok == CONST || *tok == FCONST || *tok == SYMBOL) { if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) return ERROR; + if (*AnEXATTR&DEFINED) { - if (*AnEXVAL > 0xffffff) - return error("long address is bigger than $ffffff"); + if (*AnEXVAL > 0xFFFFFF) + return error("long address is bigger than $FFFFFF"); + *memspace = 1 << 6; // Mark we're on Y memory space *am = M_DSPEA; @@ -465,364 +482,389 @@ static inline int dsp_parmode(int *am, int *areg, TOKEN * AnEXPR, uint64_t * AnE return OK; } } - else if (*tok == SHL) // '<<' - { - // I/O Short Addressing Mode Force Operator - // Y:pp - tok++; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; + else if (*tok == SHL) // '<<' + { + // I/O Short Addressing Mode Force Operator + // Y:pp + tok++; + + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; // If the symbol/expression is defined then check for valid range. // Otherwise the value had better fit or Fixups will bark! if (*AnEXATTR & DEFINED) { *AnEXVAL = (LONG)(((int32_t)(((uint32_t)*AnEXVAL) << (32 - 6))) >> (32 - 6)); // Sign extend 6 to 32 bits - if (*AnEXVAL < 0xffffffc0) - return error("I/O Short Addressing Mode addresses must be between $ffe0 and $1f"); + + if (*AnEXVAL < 0xFFFFFFC0) + return error("I/O Short Addressing Mode addresses must be between $FFE0 and $1F"); } - *am = M_DSPPP; - *memspace = 1 << 6; // Mark we're on Y memory space - *perspace = 1 << 16; // Mark we're on Y peripheral space - *areg = *AnEXVAL & 0x3f; // Since this is only going to get used in dsp_ea_imm5... - return OK; - } - if ((*areg = checkea(0, X_ERRORS)) != ERROR) - { - *memspace = 1 << 6; // Mark we're on Y memory space - *am = M_DSPEA; - return OK; - } - else - return ERROR; - // TODO: add absolute address checks + *am = M_DSPPP; + *memspace = 1 << 6; // Mark we're on Y memory space + *perspace = 1 << 16; // Mark we're on Y peripheral space + *areg = *AnEXVAL & 0x3F; // Since this is only going to get used in dsp_ea_imm5... + return OK; + } - } - else if (*tok >= KW_X&&*tok <= KW_Y) - { - *am = M_INP48; - *areg = *tok++; - return OK; - } - else if (*tok >= KW_M0 && *tok <= KW_M7) - { - *am = M_DSPM; - *areg = (*tok++) & 7; - return OK; - } - else if (*tok >= KW_R0 && *tok <= KW_R7) - { - *am = M_DSPR; - *areg = (*tok++) - KW_R0; - return OK; - } - else if (*tok >= KW_N0 && *tok <= KW_N7) - { - *am = M_DSPN; - *areg = (*tok++) & 7; - return OK; - } - else if (*tok == KW_A0 || *tok == KW_A1 || *tok == KW_B0 || *tok == KW_B1) - { - *am = M_ACC24; - *areg = *tok++; - return OK; - } - else if (*tok == KW_A2 || *tok == KW_B2) - { - *am = M_ACC8; - *areg = *tok++; - return OK; - } - else if (*tok == '-' && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1)) - { - // '-X0', '-Y0', '-X1' or '-Y1', used in multiplications - tok++; + if ((*areg = checkea(0, X_ERRORS)) != ERROR) + { + *memspace = 1 << 6; // Mark we're on Y memory space + *am = M_DSPEA; + return OK; + } + else + return ERROR; + // TODO: add absolute address checks + } + else if ((*tok >= KW_X) && (*tok <= KW_Y)) + { + *am = M_INP48; + *areg = *tok++; + return OK; + } + else if ((*tok >= KW_M0) && (*tok <= KW_M7)) + { + *am = M_DSPM; + *areg = (*tok++) & 7; + return OK; + } + else if ((*tok >= KW_R0) && (*tok <= KW_R7)) + { + *am = M_DSPR; + *areg = (*tok++) - KW_R0; + return OK; + } + else if ((*tok >= KW_N0) && (*tok <= KW_N7)) + { + *am = M_DSPN; + *areg = (*tok++) & 7; + return OK; + } + else if ((*tok == KW_A0) || (*tok == KW_A1) || (*tok == KW_B0) + || (*tok == KW_B1)) + { + *am = M_ACC24; + *areg = *tok++; + return OK; + } + else if ((*tok == KW_A2) || (*tok == KW_B2)) + { + *am = M_ACC8; + *areg = *tok++; + return OK; + } + else if ((*tok == '-') && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1)) + { + // '-X0', '-Y0', '-X1' or '-Y1', used in multiplications + tok++; - // Check to see if this is the first operand - if (operand != 0) - return error("-x0/-x1/-y0/-y1 only allowed in the first operand"); + // Check to see if this is the first operand + if (operand != 0) + return error("-x0/-x1/-y0/-y1 only allowed in the first operand"); + + *am = M_ALU24; + *areg = *tok++; + dsp_k = 1 << 2; + return OK; + } + else if (*tok == '+' && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1)) + { + // '+X0', '+Y0', '+X1' or '+Y1', used in multiplications + tok++; - *am = M_ALU24; - *areg = *tok++; - dsp_k = 1 << 2; - return OK; - } - else if (*tok == '+' && (*(tok + 1) == KW_X0 || *(tok + 1) == KW_X1 || *(tok + 1) == KW_Y0 || *(tok + 1) == KW_Y1)) - { - // '+X0', '+Y0', '+X1' or '+Y1', used in multiplications - tok++; + // Check to see if this is the first operand + if (operand != 0) + return error("+x0/+x1/+y0/+y1 only allowed in the first operand"); + + *am = M_ALU24; + *areg = *tok++; + dsp_k = 0 << 2; + return OK; + } + else if (*tok == '(' || *tok == '-') + { + // Could be either an expression or ea mode + if (*tok + 1 == SYMBOL) + { + tok++; - // Check to see if this is the first operand - if (operand != 0) - return error("+x0/+x1/+y0/+y1 only allowed in the first operand"); + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; - *am = M_ALU24; - *areg = *tok++; - dsp_k = 0 << 2; - return OK; - } - else if (*tok == '(' || *tok == '-') - { - // Could be either an expression or ea mode - if (*tok + 1 == SYMBOL) - { - tok++; + *am = M_DSPIM; + return OK; + } - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; + if ((*areg = checkea(0, P_ERRORS)) != ERROR) + { + *am = M_DSPEA; + return OK; + } + else + return ERROR; + + // TODO: add absolute address checks + return error("internal assembler error: parmode checking for '(' and '-' does not have absolute address checks yet!"); + } + else if (*tok == KW_P && *(tok + 1) == ':') + { + tok = tok + 2; - *am = M_DSPIM; - return OK; - } - if ((*areg = checkea(0, P_ERRORS)) != ERROR) - { - *am = M_DSPEA; - return OK; - } - else - return ERROR; - // TODO: add absolute address checks - return error("internal assembler error: parmode checking for '(' and '-' does not have absolute address checks yet!"); - } - else if (*tok == KW_P && *(tok + 1) == ':') - { - tok = tok + 2; if (*tok == CONST || *tok == FCONST || *tok == SYMBOL) - { - // Address - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; - if (*AnEXVAL > 0xffffff) - return error("long address is bigger than $ffffff"); - if (*AnEXVAL > 0x3f) - { - *am = M_DSPEA; - *areg = DSP_EA_ABS; - } - else - { - *areg = (int)*AnEXVAL; // Lame, but what the hell - *am = M_DSPAA; - } - return OK; - } - else if (*tok == '<') - { - // X:aa - // Short Addressing Mode Force Operator in the case of '<' - tok++; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; - if (*AnEXVAL > 0x3f) - return error("short addressing mode forced but address is bigger than $3f"); - *am = M_DSPAA; - *areg = (int)*AnEXVAL; // Since this is only going to get used in dsp_ea_imm5... - return OK; - } - else if (*tok == '>') - { - // Long Addressing Mode Force Operator - tok++; - // Immediate Short Addressing Mode Force Operator - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; - if (*AnEXATTR & DEFINED) - { - if (*AnEXVAL > 0xffffff) - return error("long address is bigger than $ffffff"); - } - *am = M_DSPEA; - *areg = DSP_EA_ABS; - return OK; - } + { + // Address + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; - if ((*areg = checkea(0, P_ERRORS)) != ERROR) - { - *am = M_DSPEA; - return OK; - } - else - return ERROR; + if (*AnEXVAL > 0xFFFFFF) + return error("long address is bigger than $FFFFFF"); - } - else if (*tok == SHL) - { - // I/O Short Addressing Mode Force Operator - tok++; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; - if (*AnEXVAL > 0xfff) - return error("I/O short addressing mode forced but address is bigger than $fff"); - *am = M_DSPABS06; - return OK; - } - else if (*tok == '<') - { - // Short Addressing Mode Force Operator - tok++; - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; - if (*AnEXATTR & DEFINED) - { - if (*AnEXVAL > 0xfff) - return error("short addressing mode forced but address is bigger than $fff"); - } - *am = M_DSPABS12; - return OK; - } - else if (*tok == '>') - { - // Long Addressing Mode Force Operator - tok++; - // Immediate Short Addressing Mode Force Operator - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; - if (*AnEXATTR & DEFINED) - { - if (*AnEXVAL > 0xffffff) - return error("long address is bigger than $ffffff"); - } - *am = M_DSPEA; - *areg = DSP_EA_ABS; - return OK; - } + if (*AnEXVAL > 0x3F) + { + *am = M_DSPEA; + *areg = DSP_EA_ABS; + } + else + { + *areg = (int)*AnEXVAL; // Lame, but what the hell + *am = M_DSPAA; + } - else if (*tok == KW_PC || *tok == KW_CCR || *tok == KW_SR || *tok == KW_SP || (*tok >= KW_MR&&*tok <= KW_SS)) - { - *areg = *tok++; - *am = M_DSPPCU; - return OK; - } - // expr - else - { - if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) - return ERROR; + return OK; + } + else if (*tok == '<') + { + // X:aa + // Short Addressing Mode Force Operator in the case of '<' + tok++; - // We'll store M_DSPEA_ABS in areg and if we have - // any extra info, it'll go in am - if (*AnEXATTR & DEFINED) - { - *areg = DSP_EA_ABS; - if (*AnEXVAL < 0x1000) - *am = M_DSPABS12; - else if (*AnEXVAL < 0x10000) - *am = M_DSPABS16; - else if (*AnEXVAL < 0x1000000) - *am = M_DSPABS24; - else - return error("address must be smaller than $1000000"); - return OK; - } - else - { - // Well, we have no opinion on the expression's size, so let's assume the worst - *areg = DSP_EA_ABS; - *am = M_DSPABS24; - return OK; - } - } - return error("internal assembler error: Please report this error message: 'reached the end of dsp_parmode' with the line of code that caused it. Thanks, and sorry for the inconvenience"); // Something bad happened -} + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; -// -// Parse all addressing modes except parallel moves -// -int dsp_amode(int maxea) -{ - LONG dummy; - // Initialize global return values - nmodes = dsp_a0reg = dsp_a1reg = 0; - dsp_am0 = dsp_am1 = M_AM_NONE; - dsp_a0expr[0] = dsp_a1expr[0] = ENDEXPR; - dsp_a0exval = 0; - dsp_a1exval = 0; - dsp_a0exattr = dsp_a1exattr = 0; - dsp_a0esym = dsp_a1esym = (SYM *)NULL; - dsp_a0memspace = dsp_a1memspace = -1; - dsp_a0perspace = dsp_a1perspace = -1; - dsp_k = 0; - - // If at EOL, then no addr modes at all - if (*tok == EOL) - return 0; - - if (dsp_parmode(&dsp_am0, &dsp_a0reg, dsp_a0expr, &dsp_a0exval, &dsp_a0exattr, &dsp_a0esym, &dsp_a0memspace, &dsp_a0perspace, 0) == ERROR) - return ERROR; - - - // 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 (*tok != ',') - { - if (dsp_k != 0) - return error("-x0/-x1/-y0/-y1 only allowed in multiply operations"); + if (*AnEXVAL > 0x3F) + return error("short addressing mode forced but address is bigger than $3F"); - return 1; - } + *am = M_DSPAA; + *areg = (int)*AnEXVAL; // Since this is only going to get used in dsp_ea_imm5... + return OK; + } + else if (*tok == '>') + { + // Long Addressing Mode Force Operator + tok++; - // Eat the comma - tok++; + // Immediate Short Addressing Mode Force Operator + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; - // Parse second addressing mode - if (dsp_parmode(&dsp_am1, &dsp_a1reg, dsp_a1expr, &dsp_a1exval, &dsp_a1exattr, &dsp_a1esym, &dsp_a1memspace, &dsp_a1perspace, 1) == ERROR) - return ERROR; + if (*AnEXATTR & DEFINED) + { + if (*AnEXVAL > 0xFFFFFF) + return error("long address is bigger than $FFFFFF"); + } - if (maxea == 2 || *tok == EOL) - { - if (dsp_k != 0) - return error("-x0/-x1/-y0/-y1 only allowed in multiply operations"); + *am = M_DSPEA; + *areg = DSP_EA_ABS; + return OK; + } - nmodes = 2; - return 2; - } + if ((*areg = checkea(0, P_ERRORS)) != ERROR) + { + *am = M_DSPEA; + return OK; + } + else + return ERROR; + } + else if (*tok == SHL) + { + // I/O Short Addressing Mode Force Operator + tok++; - if (*tok == ',') - { - // Only MAC-like or jsset/clr/tst/chg instructions here - tok++; - if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR) - return ERROR; - if (maxea == 3) - return 3; - if (*tok != EOL) - return error(extra_stuff); - nmodes = 3; - return 3; + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; - } + if (*AnEXVAL > 0xFFF) + return error("I/O short addressing mode forced but address is bigger than $FFF"); - // Only Tcc instructions here, and then only those that accept 4 operands + *am = M_DSPABS06; + return OK; + } + else if (*tok == '<') + { + // Short Addressing Mode Force Operator + tok++; - if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR) - return ERROR; + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; - if (*tok++ != ',') - return error("expected 4 parameters"); + if (*AnEXATTR & DEFINED) + { + if (*AnEXVAL > 0xFFF) + return error("short addressing mode forced but address is bigger than $FFF"); + } - if (dsp_parmode(&dsp_am3, &dsp_a3reg, dsp_a3expr, &dsp_a3exval, &dsp_a3exattr, &dsp_a3esym, &dummy, &dummy, 3) == ERROR) - return ERROR; + *am = M_DSPABS12; + return OK; + } + else if (*tok == '>') + { + // Long Addressing Mode Force Operator + tok++; - if (*tok == EOL) - { - if (dsp_k != 0) - return error("-x0/-x1/-y0/-y1 only allowed in multiply operations"); + // Immediate Short Addressing Mode Force Operator + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; - nmodes = 4; - return 4; - } - else - { - // Tcc instructions do not support parallel moves, so any remaining tokens are garbage - return error(extra_stuff); - } + if (*AnEXATTR & DEFINED) + { + if (*AnEXVAL > 0xFFFFFF) + return error("long address is bigger than $FFFFFF"); + } + + *am = M_DSPEA; + *areg = DSP_EA_ABS; + return OK; + } + else if (*tok == KW_PC || *tok == KW_CCR || *tok == KW_SR || *tok == KW_SP || (*tok >= KW_MR&&*tok <= KW_SS)) + { + *areg = *tok++; + *am = M_DSPPCU; + return OK; + } + // expr + else + { + if (expr(AnEXPR, AnEXVAL, AnEXATTR, AnESYM) != OK) + return ERROR; + + // We'll store M_DSPEA_ABS in areg and if we have + // any extra info, it'll go in am + if (*AnEXATTR & DEFINED) + { + *areg = DSP_EA_ABS; + + if (*AnEXVAL < 0x1000) + *am = M_DSPABS12; + else if (*AnEXVAL < 0x10000) + *am = M_DSPABS16; + else if (*AnEXVAL < 0x1000000) + *am = M_DSPABS24; + else + return error("address must be smaller than $1000000"); + + return OK; + } + else + { + // Well, we have no opinion on the expression's size, so let's assume the worst + *areg = DSP_EA_ABS; + *am = M_DSPABS24; + return OK; + } + } + + return error("internal assembler error: Please report this error message: 'reached the end of dsp_parmode' with the line of code that caused it. Thanks, and sorry for the inconvenience"); // Something bad happened +} - return error("internal assembler error: Please report this error message: 'reached the end of dsp_amode' with the line of code that caused it. Thanks, and sorry for the inconvenience"); //Something bad happened +// +// Parse all addressing modes except parallel moves +// +int dsp_amode(int maxea) +{ + LONG dummy; + // Initialize global return values + nmodes = dsp_a0reg = dsp_a1reg = 0; + dsp_am0 = dsp_am1 = M_AM_NONE; + dsp_a0expr[0] = dsp_a1expr[0] = ENDEXPR; + dsp_a0exval = 0; + dsp_a1exval = 0; + dsp_a0exattr = dsp_a1exattr = 0; + dsp_a0esym = dsp_a1esym = (SYM *)NULL; + dsp_a0memspace = dsp_a1memspace = -1; + dsp_a0perspace = dsp_a1perspace = -1; + dsp_k = 0; + + // If at EOL, then no addr modes at all + if (*tok == EOL) + return 0; + + if (dsp_parmode(&dsp_am0, &dsp_a0reg, dsp_a0expr, &dsp_a0exval, &dsp_a0exattr, &dsp_a0esym, &dsp_a0memspace, &dsp_a0perspace, 0) == ERROR) + return ERROR; + + + // 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 (*tok != ',') + { + if (dsp_k != 0) + return error("-x0/-x1/-y0/-y1 only allowed in multiply operations"); + + return 1; + } + + // Eat the comma + tok++; + + // Parse second addressing mode + if (dsp_parmode(&dsp_am1, &dsp_a1reg, dsp_a1expr, &dsp_a1exval, &dsp_a1exattr, &dsp_a1esym, &dsp_a1memspace, &dsp_a1perspace, 1) == ERROR) + return ERROR; + + if (maxea == 2 || *tok == EOL) + { + if (dsp_k != 0) + return error("-x0/-x1/-y0/-y1 only allowed in multiply operations"); + + nmodes = 2; + return 2; + } + + if (*tok == ',') + { + // Only MAC-like or jsset/clr/tst/chg instructions here + tok++; + if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR) + return ERROR; + if (maxea == 3) + return 3; + if (*tok != EOL) + return error(extra_stuff); + nmodes = 3; + return 3; + + } + + // Only Tcc instructions here, and then only those that accept 4 operands + + if (dsp_parmode(&dsp_am2, &dsp_a2reg, dsp_a2expr, &dsp_a2exval, &dsp_a2exattr, &dsp_a2esym, &dummy, &dummy, 2) == ERROR) + return ERROR; + + if (*tok++ != ',') + return error("expected 4 parameters"); + + if (dsp_parmode(&dsp_am3, &dsp_a3reg, dsp_a3expr, &dsp_a3exval, &dsp_a3exattr, &dsp_a3esym, &dummy, &dummy, 3) == ERROR) + return ERROR; + + if (*tok == EOL) + { + if (dsp_k != 0) + return error("-x0/-x1/-y0/-y1 only allowed in multiply operations"); + + nmodes = 4; + return 4; + } + else + { + // Tcc instructions do not support parallel moves, so any remaining tokens are garbage + return error(extra_stuff); + } + + return error("internal assembler error: Please report this error message: 'reached the end of dsp_amode' with the line of code that caused it. Thanks, and sorry for the inconvenience"); //Something bad happened } @@ -831,43 +873,43 @@ int dsp_amode(int maxea) // static inline int SDreg(int reg) { - if (reg >= KW_X0 && reg <= KW_N7) - return reg & 0xff; - else if (reg >= KW_A0&® <= KW_A2) - return (8 >> (reg & 7)) | 8; - else //if (reg>=KW_R0&®<=KW_R7) - return reg - KW_R0 + 16; - // Handy map for the above: - // (values are of course taken from keytab) - // Register | Value | Return value - // x0 | 260 | 4 - // x1 | 261 | 5 - // y0 | 262 | 6 - // y1 | 263 | 7 - // b0 | 265 | 8 - // b2 | 267 | 9 - // b1 | 269 | 10 - // a | 270 | 14 - // b | 271 | 15 - // n0 | 280 | 24 - // n1 | 281 | 25 - // n2 | 282 | 26 - // n3 | 283 | 27 - // n4 | 284 | 28 - // n5 | 285 | 29 - // n6 | 286 | 30 - // n7 | 287 | 31 - // a0 | 136 | 0 - // a1 | 137 | 1 - // a2 | 138 | 2 - // r0 | 151 | 16 - // r1 | 152 | 17 - // r2 | 153 | 18 - // r3 | 154 | 19 - // r4 | 155 | 20 - // r5 | 156 | 21 - // r6 | 157 | 22 - // r7 | 158 | 23 + if (reg >= KW_X0 && reg <= KW_N7) + return reg & 0xFF; + else if (reg >= KW_A0&® <= KW_A2) + return (8 >> (reg & 7)) | 8; + else //if (reg>=KW_R0&®<=KW_R7) + return reg - KW_R0 + 16; + // Handy map for the above: + // (values are of course taken from keytab) + // Register | Value | Return value + // x0 | 260 | 4 + // x1 | 261 | 5 + // y0 | 262 | 6 + // y1 | 263 | 7 + // b0 | 265 | 8 + // b2 | 267 | 9 + // b1 | 269 | 10 + // a | 270 | 14 + // b | 271 | 15 + // n0 | 280 | 24 + // n1 | 281 | 25 + // n2 | 282 | 26 + // n3 | 283 | 27 + // n4 | 284 | 28 + // n5 | 285 | 29 + // n6 | 286 | 30 + // n7 | 287 | 31 + // a0 | 136 | 0 + // a1 | 137 | 1 + // a2 | 138 | 2 + // r0 | 151 | 16 + // r1 | 152 | 17 + // r2 | 153 | 18 + // r3 | 154 | 19 + // r4 | 155 | 20 + // r5 | 156 | 21 + // r6 | 157 | 22 + // r7 | 158 | 23 } @@ -876,668 +918,714 @@ static inline int SDreg(int reg) // static inline LONG check_x_y(LONG ea1, LONG S1) { - LONG inst; - LONG eax_temp, eay_temp; - LONG D1, D2, S2, ea2; - LONG K_D1, K_D2; - LONG w = 1 << 7; // S1=0, D1=1<<14 - if ((ea1 & 0x38) == DSP_EA_POSTINC || (ea1 & 0x38) == DSP_EA_POSTINC1 || - (ea1 & 0x38) == DSP_EA_POSTDEC1 || (ea1 & 0x38) == DSP_EA_NOUPD) - { - - switch (ea1 & 0x38) - { - case DSP_EA_POSTINC: ea1 = (ea1&(~0x38)) | 0x8;break; - case DSP_EA_POSTINC1: ea1 = (ea1&(~0x38)) | 0x18;break; - case DSP_EA_POSTDEC1: ea1 = (ea1&(~0x38)) | 0x10;break; - case DSP_EA_NOUPD: ea1 = (ea1&(~0x38)) | 0x00;break; - } + LONG inst; + LONG eax_temp, eay_temp; + LONG D1, D2, S2, ea2; + LONG K_D1, K_D2; + LONG w = 1 << 7; // S1=0, D1=1<<14 + + if ((ea1 & 0x38) == DSP_EA_POSTINC || (ea1 & 0x38) == DSP_EA_POSTINC1 || + (ea1 & 0x38) == DSP_EA_POSTDEC1 || (ea1 & 0x38) == DSP_EA_NOUPD) + { + switch (ea1 & 0x38) + { + case DSP_EA_POSTINC: ea1 = (ea1 & (~0x38)) | 0x8; break; + case DSP_EA_POSTINC1: ea1 = (ea1 & (~0x38)) | 0x18; break; + case DSP_EA_POSTDEC1: ea1 = (ea1 & (~0x38)) | 0x10; break; + case DSP_EA_NOUPD: ea1 = (ea1 & (~0x38)) | 0x00; break; + } - if (S1 == 0) - { - // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay' - // Check for D1 - switch (K_D1 = *tok++) - { - case KW_X0: D1 = 0 << 10; break; - case KW_X1: D1 = 1 << 10; break; - case KW_A: D1 = 2 << 10; break; - case KW_B: D1 = 3 << 10; break; - default: return error("unrecognised X:Y: parallel move syntax: expected x0, x1, a or b after 'X:eax,'"); - } - } - else - { - // 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay' - w = 0; - switch (S1) - { - case 4: D1 = 0 << 10; break; - case 5: D1 = 1 << 10; break; - case 14: D1 = 2 << 10; break; - case 15: D1 = 3 << 10; break; - default: return error("unrecognised X:Y: parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:eax'"); - } - } + if (S1 == 0) + { + // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay' + // Check for D1 + switch (K_D1 = *tok++) + { + case KW_X0: D1 = 0 << 10; break; + case KW_X1: D1 = 1 << 10; break; + case KW_A: D1 = 2 << 10; break; + case KW_B: D1 = 3 << 10; break; + default: return error("unrecognised X:Y: parallel move syntax: expected x0, x1, a or b after 'X:eax,'"); + } + } + else + { + // 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay' + w = 0; - if (*tok == KW_Y) - { - tok++; - // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2' - if (*tok++ != ':') - return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'"); - if (*tok++ == '(') - { - if (*tok >= KW_R0 && *tok <= KW_R7) - { - ea2 = (*tok++ - KW_R0); - if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4)) - return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea Y:eay,D2'"); - } - else - return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea Y:('"); - // If eax register is r0-r3 then eay register is r4-r7. - // Encode that to 2 bits (i.e. eay value is 0-3) - eax_temp = (ea2 & 3) << 5; // Store register temporarily - if (*tok++ != ')') - return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea Y:(Rn'"); - if (*tok == '+') - { - tok++; - if (*tok == ',') - { - // (Rn)+ - ea2 = 3 << 12; - tok++; - } - else if (*tok >= KW_N0 && *tok <= KW_N7) - { - // (Rn)+Nn - if ((*tok++ & 7) != ea2) - return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea Y:(Rn)+Nn,D')"); - ea2 = 1 << 12; - if (*tok++ != ',') - return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)+Nn'"); - } - else - return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea Y:(Rn)+'"); + switch (S1) + { + case 4: D1 = 0 << 10; break; + case 5: D1 = 1 << 10; break; + case 14: D1 = 2 << 10; break; + case 15: D1 = 3 << 10; break; + default: return error("unrecognised X:Y: parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:eax'"); + } + } - } - else if (*tok == '-') - { - // (Rn)- - ea2 = 2 << 12; - tok++; - if (*tok++ != ',') - return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)-'"); - } - else if (*tok++ == ',') - { - // (Rn) - ea2 = 0 << 12; - } - else - return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:eay'"); + if (*tok == KW_Y) + { + tok++; + // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2' + if (*tok++ != ':') + return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'"); - ea2 |= eax_temp; // OR eay back from temp + if (*tok++ == '(') + { + if (*tok >= KW_R0 && *tok <= KW_R7) + { + ea2 = (*tok++ - KW_R0); - switch (K_D2 = *tok++) - { - case KW_Y0: D2 = 0 << 8; break; - case KW_Y1: D2 = 1 << 8; break; - case KW_A: D2 = 2 << 8; break; - case KW_B: D2 = 3 << 8; break; - default: return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'"); - } + if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4)) + return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea Y:eay,D2'"); + } + else + return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea Y:('"); - if (*tok != EOL) - return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea Y:eay,D'"); + // If eax register is r0-r3 then eay register is r4-r7. + // Encode that to 2 bits (i.e. eay value is 0-3) + eax_temp = (ea2 & 3) << 5; // Store register temporarily - if (S1 == 0) - if (K_D1 == K_D2) - return error("unrecognised X:Y: parallel move syntax: D1 and D2 cannot be the same in 'X:ea,D1 Y:eay,D2'"); + if (*tok++ != ')') + return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea Y:(Rn'"); - inst = B16(11000000, 00000000) | w; - inst |= ea1 | D1 | ea2 | D2; - return inst; - } - else - return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'"); - } - else if (*tok == KW_Y0 || *tok == KW_Y1 || *tok == KW_A || *tok == KW_B) - { - // 'X:eax,D1 S2,Y:eay' 'S1,X:eax1 S2,Y:eay' - switch (*tok++) - { - case KW_Y0: S2 = 0 << 8; break; - case KW_Y1: S2 = 1 << 8; break; - case KW_A: S2 = 2 << 8; break; - case KW_B: S2 = 3 << 8; break; - default: return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'"); - } + if (*tok == '+') + { + tok++; - if (*tok++ != ',') - return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea S2'"); + if (*tok == ',') + { + // (Rn)+ + ea2 = 3 << 12; + tok++; + } + else if (*tok >= KW_N0 && *tok <= KW_N7) + { + // (Rn)+Nn + if ((*tok++ & 7) != ea2) + return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea Y:(Rn)+Nn,D')"); - if (*tok++ == KW_Y) - { - // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2' - if (*tok++ != ':') - return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'"); - if (*tok++ == '(') - { - if (*tok >= KW_R0 && *tok <= KW_R7) - { - ea2 = (*tok++ - KW_R0); - if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4)) - return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea S2,Y:eay'"); - } - else - return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea S2,Y:('"); - // If eax register is r0-r3 then eay register is r4-r7. - // Encode that to 2 bits (i.e. eay value is 0-3) - eay_temp = (ea2 & 3) << 5; //Store register temporarily - if (*tok++ != ')') - return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea S2,Y:(Rn'"); - if (*tok == '+') - { - tok++; - if (*tok == EOL) - // (Rn)+ - ea2 = 3 << 12; - else if (*tok >= KW_N0 && *tok <= KW_N7) - { - // (Rn)+Nn - if ((*tok++ & 7) != ea2) - return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn')"); - ea2 = 1 << 12; - if (*tok != EOL) - return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn'"); - } - else - return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+'"); + ea2 = 1 << 12; - } - else if (*tok == '-') - { - // (Rn)- - ea2 = 2 << 12; - tok++; - if (*tok != EOL) - return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)-'"); - } - else if (*tok == EOL) - { - // (Rn) - ea2 = 0 << 12; - } - else - return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:eay'"); + if (*tok++ != ',') + return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)+Nn'"); + } + else + return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea Y:(Rn)+'"); - ea2 |= eay_temp; //OR eay back from temp + } + else if (*tok == '-') + { + // (Rn)- + ea2 = 2 << 12; + tok++; - inst = B16(10000000, 00000000) | w; - inst |= (ea1 & 0x1f) | D1 | S2 | ea2; - return inst; - } - else - return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'"); + if (*tok++ != ',') + return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:(Rn)-'"); + } + else if (*tok++ == ',') + { + // (Rn) + ea2 = 0 << 12; + } + else + return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea Y:eay'"); - } - else - return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'"); - } - else - return error("unrecognised X:Y: or X:R parallel move syntax: expected Y:, A or B after 'X:ea,D1/S1,X:ea S2,'"); + ea2 |= eax_temp; // OR eay back from temp + switch (K_D2 = *tok++) + { + case KW_Y0: D2 = 0 << 8; break; + case KW_Y1: D2 = 1 << 8; break; + case KW_A: D2 = 2 << 8; break; + case KW_B: D2 = 3 << 8; break; + default: return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'"); + } - } - return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'"); -} + if (*tok != EOL) + return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea Y:eay,D'"); -// -// Parse X: addressing space parallel moves -// -static inline LONG parse_x(const int W, LONG inst, const LONG S1, const int check_for_x_y) -{ - int immreg; // Immediate register destination - LONG S2, D1, D2; // Source and Destinations - LONG ea1; // ea bitfields - uint32_t termchar = ','; // Termination character for ea checks - int force_imm = NUM_NORMAL; // Holds forced immediate value (i.e. '<' or '>') - ea1 = -1; // initialise e1 (useful for some code paths) - if (W == 0) - termchar = EOL; - if (*tok == '-') - { - if (tok[1] == CONST || tok[1] == FCONST) - { - tok++; - dspImmedEXVAL = *tok++; - goto x_check_immed; - } - // This could be either -(Rn), -aa or -ea. Check for immediate first - if (tok[1] == SYMBOL) - { - if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK) - { - if (S1 != 0) - { - x_checkea_right: + if (S1 == 0) + if (K_D1 == K_D2) + return error("unrecognised X:Y: parallel move syntax: D1 and D2 cannot be the same in 'X:ea,D1 Y:eay,D2'"); - // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B', 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay' - if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_A) - { - // 'A,X:ea X0,A' - if (ea1 == DSP_EA_ABS) - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - if (S1 != 14) - return error("unrecognised X:R parallel move syntax: S1 can only be a in 'a,X:ea x0,a'"); - if (ea1 == -1) - return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'a,X:ea x0,a'"); - if (ea1 == B8(00110100)) - return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'a,X:ea x0,a'"); - inst = B16(00001000, 00000000) | ea1 | (0 << 8); - return inst; - } - else if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_B) - { - // 'B,X:ea X0,B' - if (ea1 == DSP_EA_ABS) - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - if (S1 != 15) - return error("unrecognised X:R parallel move syntax: S1 can only be b in 'b,X:ea x0,b'"); - if (ea1 == -1) - return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'b,X:ea x0,b'"); - if (ea1 == B8(00110100)) - return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'b,X:ea x0,b'"); - inst = B16(00001001, 00000000) | ea1 | (1 << 8); - return inst; - } - else if (*tok == KW_A || *tok == KW_B) - { - // 'S1,X:ea S2,D2', 'S1,X:eax S2,Y:eay' + inst = B16(11000000, 00000000) | w; + inst |= ea1 | D1 | ea2 | D2; + return inst; + } + else + return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'"); + } + else if (*tok == KW_Y0 || *tok == KW_Y1 || *tok == KW_A || *tok == KW_B) + { + // 'X:eax,D1 S2,Y:eay' 'S1,X:eax1 S2,Y:eay' + switch (*tok++) + { + case KW_Y0: S2 = 0 << 8; break; + case KW_Y1: S2 = 1 << 8; break; + case KW_A: S2 = 2 << 8; break; + case KW_B: S2 = 3 << 8; break; + default: return error("unrecognised X:Y: parallel move syntax: expected y0, y1, a or b after 'X:ea,D1/S1,X:ea Y:eay,'"); + } - switch (S1) - { - case 4: D1 = 0 << 10; break; - case 5: D1 = 1 << 10; break; - case 14: D1 = 2 << 10; break; - case 15: D1 = 3 << 10; break; - default: return error("unrecognised X:R parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:ea S2,D2'"); - } + if (*tok++ != ',') + return error("unrecognised X:Y: parallel move syntax: expected ',' after 'X:ea,D1/S1,X:ea S2'"); - if (tok[1] == ',' && tok[2] == KW_Y) - { - // 'S1,X:eax S2,Y:eay' - return check_x_y(ea1, S1); - } + if (*tok++ == KW_Y) + { + // 'X:eax,D1 Y:eay,D2' 'S1,X:eax Y:eay,D2' + if (*tok++ != ':') + return error("unrecognised X:Y: parallel move syntax: expected ':' after 'X:ea,D1/S1,X:ea Y'"); - // 'S1,X:ea S2,D2' - if (ea1 == DSP_EA_ABS) - deposit_extra_ea = DEPOSIT_EXTRA_WORD; + if (*tok++ == '(') + { + if (*tok >= KW_R0 && *tok <= KW_R7) + { + ea2 = (*tok++ - KW_R0); - switch (*tok++) - { - case KW_A: S2 = 0 << 9; break; - case KW_B: S2 = 1 << 9; break; - default: return error("unrecognised X:R parallel move syntax: expected a or b after 'S1,X:eax'"); - } - if (*tok++ != ',') - return error("unrecognised X:R parallel move syntax: expected ',' after 'S1,X:eax S2'"); + if (((ea1 & 7) < 4 && ea2 < 4) || ((ea1 & 7) >= 4 && ea2 > 4)) + return error("unrecognised X:Y: parallel move syntax: eax and eay register banks must be different in 'X:ea,D1/S1,X:ea S2,Y:eay'"); + } + else + return error("unrecognised X:Y: parallel move syntax: expected 'Rn' after 'X:ea,D1/S1,X:ea S2,Y:('"); + // If eax register is r0-r3 then eay register is r4-r7. + // Encode that to 2 bits (i.e. eay value is 0-3) + eay_temp = (ea2 & 3) << 5; //Store register temporarily - if (*tok == KW_Y0 || *tok == KW_Y1) - { - if (*tok++ == KW_Y0) - D2 = 0 << 8; - else - D2 = 1 << 8; + if (*tok++ != ')') + return error("unrecognised X:Y: parallel move syntax: expected ')' after 'X:ea,D1/S1,X:ea S2,Y:(Rn'"); - if (*tok != EOL) - return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'"); + if (*tok == '+') + { + tok++; - inst = B16(00010000, 00000000) | (0 << 7); - inst |= ea1 | D1 | S2 | D2; - return inst; - } - else - return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'"); + if (*tok == EOL) + // (Rn)+ + ea2 = 3 << 12; + else if (*tok >= KW_N0 && *tok <= KW_N7) + { + // (Rn)+Nn + if ((*tok++ & 7) != ea2) + return error("unrecognised X:Y: parallel move syntax(Same register number expected for Rn, Nn in 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn')"); - } - else if (*tok == KW_Y) - { - // 'S1,X:eax Y:eay,D2' - return check_x_y(ea1, S1); - } - else if (*tok == KW_Y0 || *tok == KW_Y1) - { - // 'S1,X:eax S2,Y:eay' - return check_x_y(ea1, S1); - } - else - return error("unrecognised X:Y or X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1/X:ea,D1"); - } - else - { - // Only check for aa if we have a defined number in our hands or we've - // been asked to use a short number format. The former case we'll just test - // it to see if it's small enough. The later - it's the programmer's call - // so he'd better have a small address or the fixups will bite him/her in the arse! - if (dspImmedEXATTR&DEFINED || force_imm == NUM_FORCE_SHORT) - { + ea2 = 1 << 12; - // It's an immediate, so ea or eax is probably an absolute address - // (unless it's aa if the immediate is small enough) - // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay' - x_check_immed: - // Check for aa (which is 6 bits zero extended) - if (dspImmedEXVAL < 0x40 && force_imm != NUM_FORCE_LONG) - { - if (W == 1) - { - // It might be X:aa but we're not 100% sure yet. - // If it is, the only possible syntax here is 'X:aa,D'. - // So check ahead to see if EOL follows D, then we're good to go. - if (*tok == ',' && ((*(tok + 1) >= KW_X0 && *(tok + 1) <= KW_N7) || (*(tok + 1) >= KW_R0 && *(tok + 1) <= KW_R7) || (*(tok + 1) >= KW_A0 && *(tok + 1) <= KW_A2)) && *(tok + 2) == EOL) - { - // Yup, we're good to go - 'X:aa,D' it is - tok++; - immreg = SDreg(*tok++); - inst = inst | (uint32_t)dspImmedEXVAL; - inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8); - inst |= 1 << 7; // W - return inst; - } - } - else - { - if (*tok == EOL) - { - // 'S,X:aa' - inst = inst | (uint32_t)dspImmedEXVAL; - inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8); - return inst; - } - else - { - // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B', - // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay' - ea1 = DSP_EA_ABS; - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - goto x_checkea_right; - } - } - } - } + if (*tok != EOL) + return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+Nn'"); + } + else + return error("unrecognised X:Y: parallel move syntax: expected ',' or 'Nn' after 'X:ea,D1/S1,X:ea S2,Y:(Rn)+'"); - // Well, that settles it - we do have an ea in our hands - if (W == 1) - { - // 'X:ea,D' [... S2,d2] - if (*tok++ != ',') - return error("unrecognised X: parallel move syntax: expected ',' after 'X:ea'"); - if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) - { - D1 = SDreg(*tok++); - if (*tok == EOL) - { - // 'X:ea,D' - inst = inst | B8(01000000) | (1 << 7); - inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8); - inst |= ea1; - if (ea1 == DSP_EA_ABS) - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - return inst; - } - else - { - // 'X:ea,D1 S2,D2' - if (*tok == KW_A || *tok == KW_B) - { - S2 = SDreg(*tok++); - if (*tok++ != ',') - return error("unrecognised X:R parallel move syntax: expected comma after X:ea,D1 S2"); - if (*tok == KW_Y0 || *tok == KW_Y1) - { - D2 = SDreg(*tok++); - if (*tok != EOL) - return error("unrecognised X:R parallel move syntax: expected EOL after X:ea,D1 S2,D2"); - inst = B16(00010000, 00000000) | (1 << 7); - inst |= ((D1 & 0x8) << (12 - 4)) + ((D1 & 1) << 10); - inst |= (S2 & 1) << 9; - inst |= (D2 & 1) << 8; - inst |= ea1; - return inst; - } - else - return error("unrecognised X:R parallel move syntax: expected y0,y1 after X:ea,D1 S2,"); - } - else - return error("unrecognised X:R parallel move syntax: expected a,b after X:ea,D1"); - } - } - else - return error("unrecognised X: parallel move syntax: expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after 'X:ea,'"); - } - else - { - if (*tok == EOL) - { - // 'S,X:ea' - inst = inst | B8(01000000) | (0 << 7); - inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8); - inst |= ea1; - if (ea1 == DSP_EA_ABS) - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - return inst; - } - else - { - // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B', - // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay' - goto x_checkea_right; - } - } + } + else if (*tok == '-') + { + // (Rn)- + ea2 = 2 << 12; + tok++; + if (*tok != EOL) + return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:(Rn)-'"); + } + else if (*tok == EOL) + { + // (Rn) + ea2 = 0 << 12; + } + else + return error("unrecognised X:Y: parallel move syntax: expected end-of-line after 'X:ea,D1/S1,X:ea S2,Y:eay'"); - } - } - } - else - { - // It's not an immediate, check for '-(Rn)' - ea1 = checkea(termchar, X_ERRORS); + ea2 |= eay_temp; //OR eay back from temp - if (ea1 == ERROR) - return ERROR; + inst = B16(10000000, 00000000) | w; + inst |= (ea1 & 0x1f) | D1 | S2 | ea2; + return inst; + } + else + return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' after 'X:ea,D1/S1,X:ea Y:'"); + } + else + return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'"); + } + else + return error("unrecognised X:Y: or X:R parallel move syntax: expected Y:, A or B after 'X:ea,D1/S1,X:ea S2,'"); + } - goto x_gotea1; + return error("unrecognised X:Y: parallel move syntax: expected '(Rn)', '(Rn)+', '(Rn)-', '(Rn)+Nn' in 'X:ea,D1/S1,X:ea'"); +} - } - } - else if (*tok == '#') - { - tok++; - if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) - return ERROR; - // Okay so we have immediate data - mark it down - ea1 = DSP_EA_IMM; - // Now, proceed to the main code for this branch - goto x_gotea1; - } - else if (*tok == '(') - { - // Maybe we got an expression here, check for it - if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING) - { - // Evaluate the expression and go to immediate code path - expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM); - goto x_check_immed; - } +// +// Parse X: addressing space parallel moves +// +static inline LONG parse_x(const int W, LONG inst, const LONG S1, const int check_for_x_y) +{ + int immreg; // Immediate register destination + LONG S2, D1, D2; // Source and Destinations + LONG ea1; // ea bitfields + uint32_t termchar = ','; // Termination character for ea checks + int force_imm = NUM_NORMAL; // Holds forced immediate value (i.e. '<' or '>') + ea1 = -1; // initialise e1 (useful for some code paths) + + if (W == 0) + termchar = EOL; + + if (*tok == '-') + { + if (tok[1] == CONST || tok[1] == FCONST) + { + tok++; + dspImmedEXVAL = *tok++; + goto x_check_immed; + } - // Nope, let's check for ea then - ea1 = checkea(termchar, X_ERRORS); - if (ea1 == ERROR) - return ERROR; + // This could be either -(Rn), -aa or -ea. Check for immediate first + if (tok[1] == SYMBOL) + { + if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) == OK) + { + if (S1 != 0) + { +x_checkea_right: + // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B', 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay' + if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_A) + { + // 'A,X:ea X0,A' + if (ea1 == DSP_EA_ABS) + deposit_extra_ea = DEPOSIT_EXTRA_WORD; - x_gotea1: - if (W == 1) - { - if (*tok++ != ',') - return error("Comma expected after 'X:(Rn)')"); + if (S1 != 14) + return error("unrecognised X:R parallel move syntax: S1 can only be a in 'a,X:ea x0,a'"); - // It might be 'X:(Rn..)..,D' but we're not 100% sure yet. - // If it is, the only possible syntax here is 'X:ea,D'. - // So check ahead to see if EOL follows D, then we're good to go. - if (((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) && *(tok + 1) == EOL) - { - //'X:ea,D' - D1 = SDreg(*tok++); + if (ea1 == -1) + return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'a,X:ea x0,a'"); - inst = inst | B8(01000000) | (1 << 7); - inst |= ea1; - inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8); - return inst; - } - } - else - { - if (*tok == EOL) - { - //'S,X:ea' - inst = inst | B8(01000000) | (0 << 7); - inst |= ea1; - inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8); - return inst; - } - else - { - goto x_checkea_right; - } - } - // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay' or 'X:ea,D1 S2,D2' - // Check ahead for S2,D2 - if that's true then we have 'X:ea,D1 S2,D2' - if ((*tok == KW_X0 || *tok == KW_X1 || *tok == KW_A || *tok == KW_B) && (*(tok + 1) == KW_A || *(tok + 1) == KW_B) && (*(tok + 2) == ',') && (*(tok + 3) == KW_Y0 || (*(tok + 3) == KW_Y1))) - { - // 'X:ea,D1 S2,D2' - // Check if D1 is x0, x1, a or b - switch (*tok++) - { - case KW_X0: D1 = 0 << 10; break; - case KW_X1: D1 = 1 << 10; break; - case KW_A: D1 = 2 << 10; break; - case KW_B: D1 = 3 << 10; break; - default: return error("unrecognised X:R parallel move syntax: expected x0, x1, a or b after 'X:eax,'"); - } + if (ea1 == B8(00110100)) + return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'a,X:ea x0,a'"); - switch (*tok++) - { - case KW_A: S2 = 0 << 9; break; - case KW_B: S2 = 1 << 9; break; - default: return error("unrecognised X:R parallel move syntax: expected a or b after 'X:eax,D1 '"); - } + inst = B16(00001000, 00000000) | ea1 | (0 << 8); + return inst; + } + else if (*tok == KW_X0 && tok[1] == ',' && tok[2] == KW_B) + { + // 'B,X:ea X0,B' + if (ea1 == DSP_EA_ABS) + deposit_extra_ea = DEPOSIT_EXTRA_WORD; - if (*tok++ != ',') - return error("unrecognised X:R parallel move syntax: expected ',' after 'X:eax,D1 S2'"); + if (S1 != 15) + return error("unrecognised X:R parallel move syntax: S1 can only be b in 'b,X:ea x0,b'"); - if (*tok == KW_Y0 || *tok == KW_Y1) - { - if (*tok++ == KW_Y0) - D2 = 0 << 8; - else - D2 = 1 << 8; + if (ea1 == -1) + return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'b,X:ea x0,b'"); - if (*tok != EOL) - return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'"); + if (ea1 == B8(00110100)) + return error("unrecognised X:R parallel move syntax: immediate data not allowed in 'b,X:ea x0,b'"); - inst = B16(00010000, 00000000) | (W << 7); - inst |= ea1 | D1 | S2 | D2; - return inst; - } - else - return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'"); + inst = B16(00001001, 00000000) | ea1 | (1 << 8); + return inst; + } + else if (*tok == KW_A || *tok == KW_B) + { + // 'S1,X:ea S2,D2', 'S1,X:eax S2,Y:eay' + switch (S1) + { + case 4: D1 = 0 << 10; break; + case 5: D1 = 1 << 10; break; + case 14: D1 = 2 << 10; break; + case 15: D1 = 3 << 10; break; + default: return error("unrecognised X:R parallel move syntax: S1 can only be x0, x1, a or b in 'S1,X:ea S2,D2'"); + } - } + if (tok[1] == ',' && tok[2] == KW_Y) + { + // 'S1,X:eax S2,Y:eay' + return check_x_y(ea1, S1); + } - // Check to see if we got eax (which is a subset of ea) - if (check_for_x_y) - { - if ((inst = check_x_y(ea1, 0)) != 0) - return inst; - else - { - // Rewind pointer as it might be an expression and check for it - tok--; - if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK) - return ERROR; - // Yes, we have an expression, so we now check for - // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay' - goto x_check_immed; - } - } - } - else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL) - { - // Check for immediate address - if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) - return ERROR; + // 'S1,X:ea S2,D2' + if (ea1 == DSP_EA_ABS) + deposit_extra_ea = DEPOSIT_EXTRA_WORD; - // We set ea1 here - if it's aa instead of ea - // then it won't be used anyway - ea1 = DSP_EA_ABS; - if (!(dspImmedEXATTR&DEFINED)) - { - force_imm = NUM_FORCE_LONG; - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - } + switch (*tok++) + { + case KW_A: S2 = 0 << 9; break; + case KW_B: S2 = 1 << 9; break; + default: return error("unrecognised X:R parallel move syntax: expected a or b after 'S1,X:eax'"); + } - goto x_check_immed; - } - else if (*tok == '>') - { - // Check for immediate address forced long - tok++; - if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) - return ERROR; - if (dspImmedEXATTR & DEFINED) - if (dspImmedEXVAL > 0xffffff) - return error("long address is bigger than $ffffff"); + if (*tok++ != ',') + return error("unrecognised X:R parallel move syntax: expected ',' after 'S1,X:eax S2'"); - deposit_extra_ea = DEPOSIT_EXTRA_WORD; + if (*tok == KW_Y0 || *tok == KW_Y1) + { + if (*tok++ == KW_Y0) + D2 = 0 << 8; + else + D2 = 1 << 8; - force_imm = NUM_FORCE_LONG; - ea1 = DSP_EA_ABS; - goto x_check_immed; - } - else if (*tok == '<') - { - // Check for immediate address forced short - tok++; - if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) - return ERROR; - force_imm = NUM_FORCE_SHORT; - if (dspImmedEXATTR & DEFINED) - { - if (dspImmedEXVAL > 0x3f) - { - warn("short addressing mode forced but address is bigger than $3f - switching to long"); - force_imm = NUM_FORCE_LONG; - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - ea1 = DSP_EA_ABS; - } - } - else - { - // This might end up as something like 'move Y:= KW_X0 && *(tok + 1) <= KW_N7) || (*(tok + 1) >= KW_R0 && *(tok + 1) <= KW_R7) || (*(tok + 1) >= KW_A0 && *(tok + 1) <= KW_A2)) && *(tok + 2) == EOL) + { + // Yup, we're good to go - 'X:aa,D' it is + tok++; + immreg = SDreg(*tok++); + inst = inst | (uint32_t)dspImmedEXVAL; + inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8); + inst |= 1 << 7; // W + return inst; + } + } + else + { + if (*tok == EOL) + { + // 'S,X:aa' + inst = inst | (uint32_t)dspImmedEXVAL; + inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8); + return inst; + } + else + { + // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B', + // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay' + ea1 = DSP_EA_ABS; + deposit_extra_ea = DEPOSIT_EXTRA_WORD; + goto x_checkea_right; + } + } + } + } + + // Well, that settles it - we do have an ea in our hands + if (W == 1) + { + // 'X:ea,D' [... S2,d2] + if (*tok++ != ',') + return error("unrecognised X: parallel move syntax: expected ',' after 'X:ea'"); + + if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) + { + D1 = SDreg(*tok++); + + if (*tok == EOL) + { + // 'X:ea,D' + inst = inst | B8(01000000) | (1 << 7); + inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8); + inst |= ea1; + + if (ea1 == DSP_EA_ABS) + deposit_extra_ea = DEPOSIT_EXTRA_WORD; + + return inst; + } + else + { + // 'X:ea,D1 S2,D2' + if (*tok == KW_A || *tok == KW_B) + { + S2 = SDreg(*tok++); + + if (*tok++ != ',') + return error("unrecognised X:R parallel move syntax: expected comma after X:ea,D1 S2"); + + if (*tok == KW_Y0 || *tok == KW_Y1) + { + D2 = SDreg(*tok++); + + if (*tok != EOL) + return error("unrecognised X:R parallel move syntax: expected EOL after X:ea,D1 S2,D2"); + + inst = B16(00010000, 00000000) | (1 << 7); + inst |= ((D1 & 0x8) << (12 - 4)) + ((D1 & 1) << 10); + inst |= (S2 & 1) << 9; + inst |= (D2 & 1) << 8; + inst |= ea1; + return inst; + } + else + return error("unrecognised X:R parallel move syntax: expected y0,y1 after X:ea,D1 S2,"); + } + else + return error("unrecognised X:R parallel move syntax: expected a,b after X:ea,D1"); + } + } + else + return error("unrecognised X: parallel move syntax: expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after 'X:ea,'"); + } + else + { + if (*tok == EOL) + { + // 'S,X:ea' + inst = inst | B8(01000000) | (0 << 7); + inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8); + inst |= ea1; + + if (ea1 == DSP_EA_ABS) + deposit_extra_ea = DEPOSIT_EXTRA_WORD; + + return inst; + } + else + { + // 'S1,X:ea S2,D2', 'A,X:ea X0,A', 'B,X:ea X0,B', + // 'S1,X:eax Y:eay,D2', 'S1,X:eax S2,Y:eay' + goto x_checkea_right; + } + } + + } + } + } + else + { + // It's not an immediate, check for '-(Rn)' + ea1 = checkea(termchar, X_ERRORS); + + if (ea1 == ERROR) + return ERROR; + + goto x_gotea1; + + } + } + else if (*tok == '#') + { + tok++; + + if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) + return ERROR; + + // Okay so we have immediate data - mark it down + ea1 = DSP_EA_IMM; + // Now, proceed to the main code for this branch + goto x_gotea1; + } + else if (*tok == '(') + { + // Maybe we got an expression here, check for it + if (tok[1] == CONST || tok[1] == FCONST || tok[1] == SUNARY || tok[1] == SYMBOL || tok[1] == STRING) + { + // Evaluate the expression and go to immediate code path + expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM); + goto x_check_immed; + } + + // Nope, let's check for ea then + ea1 = checkea(termchar, X_ERRORS); + + if (ea1 == ERROR) + return ERROR; + +x_gotea1: + if (W == 1) + { + if (*tok++ != ',') + return error("Comma expected after 'X:(Rn)')"); + + // It might be 'X:(Rn..)..,D' but we're not 100% sure yet. + // If it is, the only possible syntax here is 'X:ea,D'. + // So check ahead to see if EOL follows D, then we're good to go. + if (((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) && *(tok + 1) == EOL) + { + //'X:ea,D' + D1 = SDreg(*tok++); + + inst = inst | B8(01000000) | (1 << 7); + inst |= ea1; + inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8); + return inst; + } + } + else + { + if (*tok == EOL) + { + //'S,X:ea' + inst = inst | B8(01000000) | (0 << 7); + inst |= ea1; + inst |= ((S1 & 0x18) << (12 - 3)) + ((S1 & 7) << 8); + return inst; + } + else + { + goto x_checkea_right; + } + } + + // 'X:eax,D1 Y:eay,D2', 'X:eax,D1 S2,Y:eay' or 'X:ea,D1 S2,D2' + // Check ahead for S2,D2 - if that's true then we have 'X:ea,D1 S2,D2' + if ((*tok == KW_X0 || *tok == KW_X1 || *tok == KW_A || *tok == KW_B) && (*(tok + 1) == KW_A || *(tok + 1) == KW_B) && (*(tok + 2) == ',') && (*(tok + 3) == KW_Y0 || (*(tok + 3) == KW_Y1))) + { + // 'X:ea,D1 S2,D2' + // Check if D1 is x0, x1, a or b + switch (*tok++) + { + case KW_X0: D1 = 0 << 10; break; + case KW_X1: D1 = 1 << 10; break; + case KW_A: D1 = 2 << 10; break; + case KW_B: D1 = 3 << 10; break; + default: return error("unrecognised X:R parallel move syntax: expected x0, x1, a or b after 'X:eax,'"); + } + + switch (*tok++) + { + case KW_A: S2 = 0 << 9; break; + case KW_B: S2 = 1 << 9; break; + default: return error("unrecognised X:R parallel move syntax: expected a or b after 'X:eax,D1 '"); + } + + if (*tok++ != ',') + return error("unrecognised X:R parallel move syntax: expected ',' after 'X:eax,D1 S2'"); + + if (*tok == KW_Y0 || *tok == KW_Y1) + { + if (*tok++ == KW_Y0) + D2 = 0 << 8; + else + D2 = 1 << 8; + + if (*tok != EOL) + return error("unrecognised X:R parallel move syntax: unexpected text after 'X:eax,D1 S2,S2'"); + + inst = B16(00010000, 00000000) | (W << 7); + inst |= ea1 | D1 | S2 | D2; + return inst; + } + else + return error("unrecognised X:R parallel move syntax: expected y0 or y1 after 'X:eax,D1 S2,'"); + } + + // Check to see if we got eax (which is a subset of ea) + if (check_for_x_y) + { + if ((inst = check_x_y(ea1, 0)) != 0) + return inst; + else + { + // Rewind pointer as it might be an expression and check for it + tok--; + + if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK) + return ERROR; + + // Yes, we have an expression, so we now check for + // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay' + goto x_check_immed; + } + } + } + else if (*tok == CONST || *tok == FCONST || *tok == SYMBOL) + { + // Check for immediate address + if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) + return ERROR; + + // We set ea1 here - if it's aa instead of ea + // then it won't be used anyway + ea1 = DSP_EA_ABS; + + if (!(dspImmedEXATTR&DEFINED)) + { + force_imm = NUM_FORCE_LONG; + deposit_extra_ea = DEPOSIT_EXTRA_WORD; + } + + goto x_check_immed; + } + else if (*tok == '>') + { + // Check for immediate address forced long + tok++; + + if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) + return ERROR; + + if (dspImmedEXATTR & DEFINED) + if (dspImmedEXVAL > 0xffffff) + return error("long address is bigger than $ffffff"); + + deposit_extra_ea = DEPOSIT_EXTRA_WORD; + + force_imm = NUM_FORCE_LONG; + ea1 = DSP_EA_ABS; + goto x_check_immed; + } + else if (*tok == '<') + { + // Check for immediate address forced short + tok++; + + if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) + return ERROR; + + force_imm = NUM_FORCE_SHORT; + + if (dspImmedEXATTR & DEFINED) + { + if (dspImmedEXVAL > 0x3F) + { + warn("short addressing mode forced but address is bigger than $3F - switching to long"); + force_imm = NUM_FORCE_LONG; + deposit_extra_ea = DEPOSIT_EXTRA_WORD; + ea1 = DSP_EA_ABS; + } + } + else + { + // This might end up as something like 'move Y:') - { - force_imm = NUM_FORCE_LONG; - tok++; - } - else if (*tok == '<') - { - force_imm = NUM_FORCE_SHORT; - tok++; - } + if (*tok == '>') + { + force_imm = NUM_FORCE_LONG; + tok++; + } + else if (*tok == '<') + { + force_imm = NUM_FORCE_SHORT; + tok++; + } - if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) - return ERROR; + if (expr(dspImmedEXPR, &dspImmedEXVAL, &dspImmedEXATTR, &dspImmedESYM) != OK) + return ERROR; - if (*tok++ != ',') - return error("expected comma"); + if (*tok++ != ',') + return error("expected comma"); - if (!((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))) - return error("expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after immediate"); - immreg = SDreg(*tok++); + if (!((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2))) + return error("expected x0,x1,y0,y1,a0,b0,a2,b2,a1,b1,a,b,r0-r7,n0-n7 after immediate"); - if (*tok == EOL) - { - if (!(dspImmedEXATTR & FLOAT)) - { - if (dspImmedEXATTR & DEFINED) - { - // From I parallel move: - // "If the destination register D is X0, X1, Y0, Y1, A, or B, the 8-bit immediate short operand - // is interpreted as a signed fraction and is stored in the specified destination register. - // That is, the 8 - bit data is stored in the eight MS bits of the destination operand, and the - // remaining bits of the destination operand D are zeroed." - // The funny bit is that Motorola assembler can parse something like 'move #$FF0000,b' into an - // I (immediate short move) - so let's do that as well then... - if (((immreg >= 4 && immreg <= 7) || immreg == 14 || immreg == 15) && force_imm != NUM_FORCE_LONG) - { - if ((dspImmedEXVAL & 0xffff) == 0) - { - dspImmedEXVAL >>= 16; - } - } - if (force_imm == NUM_FORCE_SHORT) - { - if (dspImmedEXVAL<0xff && (int32_t)dspImmedEXVAL>-0x100) - { - // '#xx,D' - // value fits in 8 bits - immediate move - inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL; - return inst; - } - else - { - warn("forced short immediate value doesn't fit in 8 bits - switching to long"); - force_imm = NUM_FORCE_LONG; - } - } - if (force_imm == NUM_FORCE_LONG) - { - // '#xxxxxx,D' - // it can either be - // X or Y Data move. I don't think it matters much - // which of the two it will be, so let's use X. - deposit_immediate_long_with_register: - inst = B16(01000000, 11110100); - inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8); - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - return inst; - } - if (((int32_t)dspImmedEXVAL < 0x100) && ((int32_t)dspImmedEXVAL >= -0x100)) - { - // value fits in 8 bits - immediate move - deposit_immediate_short_with_register: - inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL; - return inst; - } - else - { - // value doesn't fit in 8 bits, so it can either be - // X or Y Data move. I don't think it matters much - // which of the two it will be, so let's use X:. - // TODO: if we're just goto'ing perhaps the logic can be simplified - goto deposit_immediate_long_with_register; - } - } - else - { - if (force_imm != NUM_FORCE_SHORT) - { - // '#xxxxxx,D' - // TODO: if we're just goto'ing perhaps the logic can be simplified - goto deposit_immediate_long_with_register; - } - else - { - // '#xx,D' - I mode - // No visibility of the number so let's add a fixup for this - AddFixup(FU_DSPIMM8, sloc, dspImmedEXPR); - inst = B16(00100000, 00000000); - inst |= ((immreg & 0x18) << (11 - 3)) + ((immreg & 7) << 8); - return inst; - } + immreg = SDreg(*tok++); - } - } - else - { - // Float constant - if (dspImmedEXATTR & DEFINED) - { + if (*tok == EOL) + { + if (!(dspImmedEXATTR & FLOAT)) + { + if (dspImmedEXATTR & DEFINED) + { + // From I parallel move: + // "If the destination register D is X0, X1, Y0, Y1, A, or B, the 8-bit immediate short operand + // is interpreted as a signed fraction and is stored in the specified destination register. + // That is, the 8 - bit data is stored in the eight MS bits of the destination operand, and the + // remaining bits of the destination operand D are zeroed." + // The funny bit is that Motorola assembler can parse something like 'move #$FF0000,b' into an + // I (immediate short move) - so let's do that as well then... + if (((immreg >= 4 && immreg <= 7) || immreg == 14 || immreg == 15) && force_imm != NUM_FORCE_LONG) + { + if ((dspImmedEXVAL & 0xffff) == 0) + { + dspImmedEXVAL >>= 16; + } + } + + if (force_imm == NUM_FORCE_SHORT) + { + if (dspImmedEXVAL < 0xFF && (int32_t)dspImmedEXVAL > -0x100) + { + // '#xx,D' + // value fits in 8 bits - immediate move + inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL; + return inst; + } + else + { + warn("forced short immediate value doesn't fit in 8 bits - switching to long"); + force_imm = NUM_FORCE_LONG; + } + } + + if (force_imm == NUM_FORCE_LONG) + { + // '#xxxxxx,D' + // it can either be + // X or Y Data move. I don't think it matters much + // which of the two it will be, so let's use X. +deposit_immediate_long_with_register: + inst = B16(01000000, 11110100); + inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8); + deposit_extra_ea = DEPOSIT_EXTRA_WORD; + return inst; + } + + if (((int32_t)dspImmedEXVAL < 0x100) && ((int32_t)dspImmedEXVAL >= -0x100)) + { + // value fits in 8 bits - immediate move +deposit_immediate_short_with_register: + inst = B16(00100000, 00000000) + (immreg << 8) + (uint32_t)dspImmedEXVAL; + return inst; + } + else + { + // value doesn't fit in 8 bits, so it can either be + // X or Y Data move. I don't think it matters much + // which of the two it will be, so let's use X:. + // TODO: if we're just goto'ing perhaps the logic can be simplified + goto deposit_immediate_long_with_register; + } + } + else + { + if (force_imm != NUM_FORCE_SHORT) + { + // '#xxxxxx,D' + // TODO: if we're just goto'ing perhaps the logic can be simplified + goto deposit_immediate_long_with_register; + } + else + { + // '#xx,D' - I mode + // No visibility of the number so let's add a fixup for this + AddFixup(FU_DSPIMM8, sloc, dspImmedEXPR); + inst = B16(00100000, 00000000); + inst |= ((immreg & 0x18) << (11 - 3)) + ((immreg & 7) << 8); + return inst; + } + } + } + else + { + // Float constant + if (dspImmedEXATTR & DEFINED) + { + double f = *(double *)&dspImmedEXVAL; + // Check direct.c for ossom comments regarding conversion! +//N.B.: This is bogus, we need to fix this so it does this the right way... !!! FIX !!! + dspImmedEXVAL = ((uint32_t)(int32_t)round(f * (1 << 23))) & 0xFFFFFF; + double g; + g = f * (1 << 23); + g = round(g); + + if ((dspImmedEXVAL & 0xFFFF) == 0) + { + // Value's 16 lower bits are not set so the value can fit in a single byte + // (check parallel I move quoted above) + warn("Immediate value fits inside 8 bits, so using instruction short format"); + dspImmedEXVAL >>= 16; + goto deposit_immediate_short_with_register; + } - double f = *(double *)&dspImmedEXVAL; - // Check direct.c for ossom comments regarding conversion! - dspImmedEXVAL = ((uint32_t)(int32_t)round(f*(1 << 23))) & 0xffffff; - double g; - g = f*(1 << 23); - g = round(g); + if (force_imm == NUM_FORCE_SHORT) + { + if ((dspImmedEXVAL & 0xFFFF) != 0) + { + warn("Immediate value short format forced but value does not fit inside 8 bits - switching to long format"); + goto deposit_immediate_long_with_register; + } - if ((dspImmedEXVAL & 0xffff) == 0) - { - // Value's 16 lower bits are not set so the value can fit in a single byte - // (check parallel I move quoted above) - warn("Immediate value fits inside 8 bits, so using instruction short format"); - dspImmedEXVAL >>= 16; - goto deposit_immediate_short_with_register; - } + return error("internal assembler error: we haven't implemented floating point constants in parallel mode parser yet!"); + } - if (force_imm == NUM_FORCE_SHORT) - { - if ((dspImmedEXVAL & 0xffff) != 0) - { - warn("Immediate value short format forced but value does not fit inside 8 bits - switching to long format"); - goto deposit_immediate_long_with_register; - } - return error("internal assembler error: we haven't implemented floating point constants in parallel mode parser yet!"); - } - // If we reach here we either have NUM_FORCE_LONG or nothing, so we might as well store a long. - goto deposit_immediate_long_with_register; - } - else - { - if (force_imm == NUM_FORCE_SHORT) - { + // If we reach here we either have NUM_FORCE_LONG or nothing, so we might as well store a long. + goto deposit_immediate_long_with_register; + } + else + { + if (force_imm == NUM_FORCE_SHORT) + { goto deposit_immediate_short_with_register; - } - else - { - // Just deposit a float fixup - AddFixup(FU_DSPIMMFL8, sloc, dspImmedEXPR); - inst = B16(00100000, 00000000); - inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8); - return inst; - } - } - } - } - else - { - // At this point we can only have '#xxxxxx,D1 S2,D2' (X:R Class I) - - switch (immreg) - { - case 4: D1 = 0 << 10;break; // X0 - case 5: D1 = 1 << 10;break; // X1 - case 14: D1 = 2 << 10;break; // A - case 15: D1 = 3 << 10;break; // B - default: return error("unrecognised X:R parallel move syntax: D1 can only be x0,x1,a,b in '#xxxxxx,D1 S2,D2'"); break; - } + } + else + { + // Just deposit a float fixup + AddFixup(FU_DSPIMMFL8, sloc, dspImmedEXPR); + inst = B16(00100000, 00000000); + inst |= ((immreg & 0x18) << (12 - 3)) + ((immreg & 7) << 8); + return inst; + } + } + } + } + else + { + // At this point we can only have '#xxxxxx,D1 S2,D2' (X:R Class I) + switch (immreg) + { + case 4: D1 = 0 << 10;break; // X0 + case 5: D1 = 1 << 10;break; // X1 + case 14: D1 = 2 << 10;break; // A + case 15: D1 = 3 << 10;break; // B + default: return error("unrecognised X:R parallel move syntax: D1 can only be x0,x1,a,b in '#xxxxxx,D1 S2,D2'"); break; + } - switch (*tok++) - { - case KW_A: S2 = 0 << 9; break; - case KW_B: S2 = 1 << 9; break; - default: return error("unrecognised X:R parallel move syntax: S2 can only be A or B in '#xxxxxx,D1 S2,D2'"); break; - } + switch (*tok++) + { + case KW_A: S2 = 0 << 9; break; + case KW_B: S2 = 1 << 9; break; + default: return error("unrecognised X:R parallel move syntax: S2 can only be A or B in '#xxxxxx,D1 S2,D2'"); break; + } - if (*tok++ != ',') - return error("unrecognised X:R parallel move syntax: expected comma after '#xxxxxx,D1 S2'"); + if (*tok++ != ',') + return error("unrecognised X:R parallel move syntax: expected comma after '#xxxxxx,D1 S2'"); - switch (*tok++) - { - case KW_Y0: D2 = 0 << 8; break; - case KW_Y1: D2 = 1 << 8; break; - default: return error("unrecognised X:R parallel move syntax: D2 can only be Y0 or Y1 in '#xxxxxx,D1 S2,D2'"); break; - } + switch (*tok++) + { + case KW_Y0: D2 = 0 << 8; break; + case KW_Y1: D2 = 1 << 8; break; + default: return error("unrecognised X:R parallel move syntax: D2 can only be Y0 or Y1 in '#xxxxxx,D1 S2,D2'"); break; + } - if (*tok != EOL) - return error("unrecognised X:R parallel move syntax: expected end-of-line after '#xxxxxx,D1 S2,D2'"); + if (*tok != EOL) + return error("unrecognised X:R parallel move syntax: expected end-of-line after '#xxxxxx,D1 S2,D2'"); - inst = B16(00010000, 10110100) | D1 | S2 | D2; - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - return inst; - } - } - else if (*tok == KW_X) - { + inst = B16(00010000, 10110100) | D1 | S2 | D2; + deposit_extra_ea = DEPOSIT_EXTRA_WORD; + return inst; + } + } + else if (*tok == KW_X) + { if (tok[1] == ',') // Hey look, it's just the register X and not the addressing mode - fall through to general case goto parse_everything_else; @@ -2538,269 +2633,307 @@ LONG parmoves(WORD dest) tok++; if (*tok++ != ':') - return error("expected ':' after 'X' in parallel move (i.e. X:)"); + return error("expected ':' after 'X' in parallel move (i.e. X:)"); // 'X:ea,D' or 'X:aa,D' or 'X:ea,D1 S2,D2' or 'X:eax,D1 Y:eay,D2' or 'X:eax,D1 S2,Y:eay' return parse_x(1, B16(01000000, 00000000), 0, 1); - } - else if (*tok == KW_Y) - { + } + else if (*tok == KW_Y) + { if (tok[1] == ',') // Hey look, it's just the register y and not the addressing mode - fall through to general case goto parse_everything_else; tok++; + if (*tok++ != ':') - return error("expected ':' after 'Y' in parallel move (i.e. Y:)"); + return error("expected ':' after 'Y' in parallel move (i.e. Y:)"); // 'Y:ea,D' or 'Y:aa,D' - return parse_y(B16(01001000, 10000000), 0, 0, 0); - } - else if (*tok == KW_L) - { - // 'L:ea,D' or 'L:aa,D' - tok++; - if (*tok++ != ':') - return error("expected ':' after 'L' in parallel move (i.e. L:)"); - - return parse_l(1, B16(01000000, 11000000), 0); - } - else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2) || (*tok >= KW_A10 && *tok <= KW_BA)) - { - // Everything else - brace for impact! - // R: 'S,D' - // X: 'S,X:ea' 'S,X:aa' - // X:R 'S,X:ea S2,D2' 'A,X:ea X0,A' 'B,X:ea X0,B' - // Y: 'S,Y:ea' 'S,Y:aa' - // R:Y: 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 #xxxxxx,D2' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' - // L: 'S,L:ea' 'S,L:aa' + return parse_y(B16(01001000, 10000000), 0, 0, 0); + } + else if (*tok == KW_L) + { + // 'L:ea,D' or 'L:aa,D' + tok++; + if (*tok++ != ':') + return error("expected ':' after 'L' in parallel move (i.e. L:)"); + + return parse_l(1, B16(01000000, 11000000), 0); + } + else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2) || (*tok >= KW_A10 && *tok <= KW_BA)) + { + // Everything else - brace for impact! + // R: 'S,D' + // X: 'S,X:ea' 'S,X:aa' + // X:R 'S,X:ea S2,D2' 'A,X:ea X0,A' 'B,X:ea X0,B' + // Y: 'S,Y:ea' 'S,Y:aa' + // R:Y: 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 #xxxxxx,D2' 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' + // L: 'S,L:ea' 'S,L:aa' LONG L_S1; parse_everything_else: L_S1 = *tok++; S1 = SDreg(L_S1); - if (*tok++ != ',') - return error("Comma expected after 'S')"); + if (*tok++ != ',') + return error("Comma expected after 'S')"); - if (*tok == KW_X) - { - // 'S,X:ea' 'S,X:aa' 'S,X:ea S2,D2' 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay' - // 'A,X:ea X0,A' 'B,X:ea X0,B' - tok++; - if (*tok++ != ':') - return error("unrecognised X: parallel move syntax: expected ':' after 'S,X'"); - return parse_x(0, B16(01000000, 00000000), S1, 1); - } - else if (*tok == KW_Y) - { - // 'S,Y:ea' 'S,Y:aa' - tok++; - if (*tok++ != ':') - return error("unrecognised Y: parallel move syntax: expected ':' after 'S,Y'"); - return parse_y(B16(0000000, 00000000), S1, 0, 0); - } - else if (*tok == KW_L) - { - // 'S,L:ea' 'S,L:aa' - tok++; - if (*tok++ != ':') - return error("unrecognised L: parallel move syntax: expected ':' after 'S,L'"); - return parse_l(1, B16(00000000, 00000000), L_S1); - } - else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) - { - // 'S,D' - // 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'S1,D1 #xxxxxx,D2' - // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' - D1 = SDreg(*tok++); - if (*tok == EOL) - { - // R 'S,D' - inst = B16(00100000, 00000000); - inst |= (S1 << 5) | (D1); - return inst; - } - else if (*tok == KW_Y) - { - // 'S1,D1 Y:ea,D2' - tok++; - if (*tok++ != ':') - return error("expected ':' after 'Y' in parallel move (i.e. Y:)"); - return parse_y(B16(00010000, 01000000), S1, D1, 0); + if (*tok == KW_X) + { + // 'S,X:ea' 'S,X:aa' 'S,X:ea S2,D2' 'S1,X:eax Y:eay,D2' 'S1,X:eax S2,Y:eay' + // 'A,X:ea X0,A' 'B,X:ea X0,B' + tok++; - } - else if (*tok == KW_A || *tok == KW_B || *tok == KW_Y0 || *tok == KW_Y1) - { - // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 S2,Y:ea' - S2 = SDreg(*tok++); - if (S1 == 6 && D1 == 14 && S2 == 14) - { - // 'Y0,A A,Y:ea' - if (*tok++ != ',') - return error("unrecognised Y: parallel move syntax: expected ',' after Y0,A A"); - if (*tok++ != KW_Y) - return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,A A,"); - if (*tok++ != ':') - return error("unrecognised Y: parallel move syntax: expected ':' after Y0,A A,Y"); - ea1 = checkea_full(EOL, Y_ERRORS); - if (ea1 == ERROR) - return ERROR; - inst = B16(00001000, 10000000); - inst |= 0 << 8; - inst |= ea1; - return inst; - } - else if (S1 == 6 && D1 == 15 && S2 == 15) - { - // 'Y0,B B,Y:ea' - if (*tok++ != ',') - return error("unrecognised Y: parallel move syntax: expected ',' after Y0,B B"); - if (*tok++ != KW_Y) - return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,B B,"); - if (*tok++ != ':') - return error("unrecognised Y: parallel move syntax: expected ':' after Y0,B B,Y"); - ea1 = checkea_full(EOL, Y_ERRORS); - if (ea1 == ERROR) - return ERROR; - inst = B16(00001000, 10000000); - inst |= 1 << 8; - inst |= ea1; - return inst; - } - else if ((S1 == 14 || S1 == 15) && (D1 == 4 || D1 == 5) && (S2 == 6 || S2 == 7 || S2 == 14 || S2 == 15)) - { - //'S1,D1 S2,Y:ea' - if (*tok++ != ',') - return error("unrecognised Y: parallel move syntax: expected ',' after S1,D1 S2"); - if (*tok++ != KW_Y) - return error("unrecognised Y: parallel move syntax: expected 'Y' after S1,D1 S2,"); - if (*tok++ != ':') - return error("unrecognised Y: parallel move syntax: expected ':' after S1,D1 S2,Y"); - ea1 = checkea_full(EOL, Y_ERRORS); - if (ea1 == ERROR) - return ERROR; - inst = B16(00010000, 01000000); - inst |= (S1 & 1) << 11; - inst |= (D1 & 1) << 10; - inst |= ((S2 & 8) << (10 - 4)) | ((S2 & 1) << 8); - inst |= ea1; - return inst; - } - else - return error("unrecognised Y: parallel move syntax: only 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' allowed'"); - // Check for Y: - } - else if (*tok == '#') - { - // R:Y: 'S1,D1 #xxxxxx,D2' - tok++; - if (*tok == '>') - { - // Well, forcing an immediate to be 24 bits is legal here - // but then it's the only available option so my guess is that this - // is simply superfluous. So let's just eat the character - tok++; - } - if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK) - return ERROR; - if (dspImmedEXATTR & DEFINED) - if (dspImmedEXVAL > 0xffffff) - return error("immediate is bigger than $ffffff"); - deposit_extra_ea = DEPOSIT_EXTRA_WORD; - if (*tok++ != ',') - return error("Comma expected after 'S1,D1 #xxxxxx')"); - // S1 is a or b, D1 is x0 or x1 and d2 is y0, y1, a or b - switch (*tok++) - { - case KW_Y0: D2 = 0 << 8; break; - case KW_Y1: D2 = 1 << 8; break; - case KW_A: D2 = 2 << 8; break; - case KW_B: D2 = 3 << 8; break; - default: return error("unrecognised R:Y: parallel move syntax: D2 must be y0, y1, a or b in 'S1,D1 #xxxxxx,D2'"); - } + if (*tok++ != ':') + return error("unrecognised X: parallel move syntax: expected ':' after 'S,X'"); - if (S1 == 14 || S1 == 15) - { - if (D1 == 4 || D1 == 5) - { - inst = B16(00010000, 11110100); - inst |= (S1 & 1) << 11; - inst |= (D1 & 1) << 10; - inst |= D2; - dspImmedEXVAL = dspaaEXVAL; - return inst; - } - else - return error("unrecognised R:Y: parallel move syntax: D1 must be x0 or x1 in 'S1,D1 #xxxxxx,D2'"); - } - else - return error("unrecognised R:Y: parallel move syntax: S1 must be a or b in 'S1,D1 #xxxxxx,D2'"); - } - else - return error("unrecognised R:Y: parallel move syntax: Unexpected text after S,D in 'S1,D1 #xxxxxx,D2'"); - } - else - return error("unrecognised R:Y: parallel move syntax: Unexpected text after 'S,'"); - } - else if (*tok == '(') - { - // U: 'ea' - // U 'ea' can only be '(Rn)-Nn', '(Rn)+Nn', '(Rn)-' or '(Rn)+' - tok++; - if (*tok >= KW_R0 && *tok <= KW_R7) - { - ea1 = (*tok++ - KW_R0); - } - else - return error("unrecognised U parallel move syntax: expected 'Rn' after '('"); - if (*tok++ != ')') - return error("unrecognised U parallel move syntax: expected ')' after '(Rn'"); - if (*tok == '+') - { - tok++; - if (*tok == EOL) - // (Rn)+ - ea1 |= 3 << 3; - else if (*tok >= KW_N0 && *tok <= KW_N7) - { - // (Rn)+Nn - if ((*tok++ & 7) != ea1) - return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)+Nn')"); - ea1 |= 1 << 3; - if (*tok != EOL) - return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)+Nn'"); - } - else - return error("unrecognised U parallel move syntax: expected End-Of-Line or 'Nn' after '(Rn)+'"); + return parse_x(0, B16(01000000, 00000000), S1, 1); + } + else if (*tok == KW_Y) + { + // 'S,Y:ea' 'S,Y:aa' + tok++; - } - else if (*tok == '-') - { - tok++; - if (*tok == EOL) - { - // (Rn)- - ea1 |= 2 << 3; - tok++; - } - else if (*tok >= KW_N0 && *tok <= KW_N7) - { - // (Rn)-Nn - if ((*tok++ & 7) != ea1) - return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)-Nn')"); - ea1 |= 0 << 3; - if (*tok != EOL) - return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)-Nn'"); - } - } + if (*tok++ != ':') + return error("unrecognised Y: parallel move syntax: expected ':' after 'S,Y'"); - inst = B16(00100000, 01000000); - inst |= ea1; - return inst; - } - else - return error("extra (unexpected) text found"); + return parse_y(B16(0000000, 00000000), S1, 0, 0); + } + else if (*tok == KW_L) + { + // 'S,L:ea' 'S,L:aa' + tok++; + + if (*tok++ != ':') + return error("unrecognised L: parallel move syntax: expected ':' after 'S,L'"); + + return parse_l(1, B16(00000000, 00000000), L_S1); + } + else if ((*tok >= KW_X0 && *tok <= KW_N7) || (*tok >= KW_R0 && *tok <= KW_R7) || (*tok >= KW_A0 && *tok <= KW_A2)) + { + // 'S,D' + // 'S1,D1 Y:ea,D2' 'S1,D1 S2,Y:ea' 'S1,D1 #xxxxxx,D2' + // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' + D1 = SDreg(*tok++); + + if (*tok == EOL) + { + // R 'S,D' + inst = B16(00100000, 00000000); + inst |= (S1 << 5) | (D1); + return inst; + } + else if (*tok == KW_Y) + { + // 'S1,D1 Y:ea,D2' + tok++; + if (*tok++ != ':') + return error("expected ':' after 'Y' in parallel move (i.e. Y:)"); + return parse_y(B16(00010000, 01000000), S1, D1, 0); + + } + else if (*tok == KW_A || *tok == KW_B || *tok == KW_Y0 || *tok == KW_Y1) + { + // 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' 'S1,D1 S2,Y:ea' + S2 = SDreg(*tok++); + + if (S1 == 6 && D1 == 14 && S2 == 14) + { + // 'Y0,A A,Y:ea' + if (*tok++ != ',') + return error("unrecognised Y: parallel move syntax: expected ',' after Y0,A A"); + + if (*tok++ != KW_Y) + return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,A A,"); + + if (*tok++ != ':') + return error("unrecognised Y: parallel move syntax: expected ':' after Y0,A A,Y"); + + ea1 = checkea_full(EOL, Y_ERRORS); + + if (ea1 == ERROR) + return ERROR; + + inst = B16(00001000, 10000000); + inst |= 0 << 8; + inst |= ea1; + return inst; + } + else if (S1 == 6 && D1 == 15 && S2 == 15) + { + // 'Y0,B B,Y:ea' + if (*tok++ != ',') + return error("unrecognised Y: parallel move syntax: expected ',' after Y0,B B"); + + if (*tok++ != KW_Y) + return error("unrecognised Y: parallel move syntax: expected 'Y' after Y0,B B,"); + + if (*tok++ != ':') + return error("unrecognised Y: parallel move syntax: expected ':' after Y0,B B,Y"); + + ea1 = checkea_full(EOL, Y_ERRORS); + + if (ea1 == ERROR) + return ERROR; + + inst = B16(00001000, 10000000); + inst |= 1 << 8; + inst |= ea1; + return inst; + } + else if ((S1 == 14 || S1 == 15) && (D1 == 4 || D1 == 5) && (S2 == 6 || S2 == 7 || S2 == 14 || S2 == 15)) + { + //'S1,D1 S2,Y:ea' + if (*tok++ != ',') + return error("unrecognised Y: parallel move syntax: expected ',' after S1,D1 S2"); + + if (*tok++ != KW_Y) + return error("unrecognised Y: parallel move syntax: expected 'Y' after S1,D1 S2,"); + + if (*tok++ != ':') + return error("unrecognised Y: parallel move syntax: expected ':' after S1,D1 S2,Y"); + + ea1 = checkea_full(EOL, Y_ERRORS); + + if (ea1 == ERROR) + return ERROR; + + inst = B16(00010000, 01000000); + inst |= (S1 & 1) << 11; + inst |= (D1 & 1) << 10; + inst |= ((S2 & 8) << (10 - 4)) | ((S2 & 1) << 8); + inst |= ea1; + return inst; + } + else + return error("unrecognised Y: parallel move syntax: only 'Y0,A A,Y:ea' 'Y0,B B,Y:ea' allowed'"); + // Check for Y: + } + else if (*tok == '#') + { + // R:Y: 'S1,D1 #xxxxxx,D2' + tok++; + + if (*tok == '>') + { + // Well, forcing an immediate to be 24 bits is legal here + // but then it's the only available option so my guess is that this + // is simply superfluous. So let's just eat the character + tok++; + } + + if (expr(dspaaEXPR, &dspaaEXVAL, &dspaaEXATTR, &dspaaESYM) != OK) + return ERROR; + + if (dspImmedEXATTR & DEFINED) + if (dspImmedEXVAL > 0xffffff) + return error("immediate is bigger than $ffffff"); + + deposit_extra_ea = DEPOSIT_EXTRA_WORD; + + if (*tok++ != ',') + return error("Comma expected after 'S1,D1 #xxxxxx')"); + + // S1 is a or b, D1 is x0 or x1 and d2 is y0, y1, a or b + switch (*tok++) + { + case KW_Y0: D2 = 0 << 8; break; + case KW_Y1: D2 = 1 << 8; break; + case KW_A: D2 = 2 << 8; break; + case KW_B: D2 = 3 << 8; break; + default: return error("unrecognised R:Y: parallel move syntax: D2 must be y0, y1, a or b in 'S1,D1 #xxxxxx,D2'"); + } + + if (S1 == 14 || S1 == 15) + { + if (D1 == 4 || D1 == 5) + { + inst = B16(00010000, 11110100); + inst |= (S1 & 1) << 11; + inst |= (D1 & 1) << 10; + inst |= D2; + dspImmedEXVAL = dspaaEXVAL; + return inst; + } + else + return error("unrecognised R:Y: parallel move syntax: D1 must be x0 or x1 in 'S1,D1 #xxxxxx,D2'"); + } + else + return error("unrecognised R:Y: parallel move syntax: S1 must be a or b in 'S1,D1 #xxxxxx,D2'"); + } + else + return error("unrecognised R:Y: parallel move syntax: Unexpected text after S,D in 'S1,D1 #xxxxxx,D2'"); + } + else + return error("unrecognised R:Y: parallel move syntax: Unexpected text after 'S,'"); + } + else if (*tok == '(') + { + // U: 'ea' + // U 'ea' can only be '(Rn)-Nn', '(Rn)+Nn', '(Rn)-' or '(Rn)+' + tok++; + + if (*tok >= KW_R0 && *tok <= KW_R7) + { + ea1 = (*tok++ - KW_R0); + } + else + return error("unrecognised U parallel move syntax: expected 'Rn' after '('"); + + if (*tok++ != ')') + return error("unrecognised U parallel move syntax: expected ')' after '(Rn'"); + + if (*tok == '+') + { + tok++; + + if (*tok == EOL) + // (Rn)+ + ea1 |= 3 << 3; + else if (*tok >= KW_N0 && *tok <= KW_N7) + { + // (Rn)+Nn + if ((*tok++ & 7) != ea1) + return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)+Nn')"); + + ea1 |= 1 << 3; + + if (*tok != EOL) + return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)+Nn'"); + } + else + return error("unrecognised U parallel move syntax: expected End-Of-Line or 'Nn' after '(Rn)+'"); + } + else if (*tok == '-') + { + tok++; + + if (*tok == EOL) + { + // (Rn)- + ea1 |= 2 << 3; + tok++; + } + else if (*tok >= KW_N0 && *tok <= KW_N7) + { + // (Rn)-Nn + if ((*tok++ & 7) != ea1) + return error("unrecognised U parallel move syntax: Same register number expected for Rn, Nn in '(Rn)-Nn')"); + + ea1 |= 0 << 3; + + if (*tok != EOL) + return error("unrecognised U parallel move syntax: expected End-Of-Line after '(Rn)-Nn'"); + } + } + + inst = B16(00100000, 01000000); + inst |= ea1; + return inst; + } + else + return error("extra (unexpected) text found"); - return OK; + return OK; } diff --git a/error.c b/error.c index 6db7ad0..81983b1 100644 --- a/error.c +++ b/error.c @@ -11,18 +11,21 @@ #include "listing.h" #include "token.h" +// Exported variables int errcnt; // Error count char * err_fname; // Name of error message file +// Internal variables static long unused; // For supressing 'write' warnings // // Report error if not at EOL +// // N.B.: Since this should *never* happen, we can feel free to add whatever // diagnostics that will help in tracking down a problem to this function. // -int at_eol(void) +int ErrorIfNotAtEOL(void) { if (*tok != EOL) { @@ -40,9 +43,9 @@ int at_eol(void) // // Cannot create a file // -void cantcreat(const char * fn) +void CantCreateFile(const char * fn) { - printf("cannot create: '%s'\n", fn); + printf("Cannot create file: '%s'\n", fn); exit(1); } @@ -66,7 +69,7 @@ void err_setup(void) err_fname = NULL; if ((err_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0) - cantcreat(fnbuf); + CantCreateFile(fnbuf); err_flag = 1; } diff --git a/error.h b/error.h index be072d5..5dec21e 100644 --- a/error.h +++ b/error.h @@ -22,9 +22,9 @@ int error(const char *, ...); int warn(const char *, ...); int fatal(const char *); int interror(int); -void cantcreat(const char *); +void CantCreateFile(const char *); void err_setup(void); -int at_eol(void); +int ErrorIfNotAtEOL(void); #endif // __ERROR_H__ diff --git a/listing.c b/listing.c index 87956af..3e89ad5 100644 --- a/listing.c +++ b/listing.c @@ -178,7 +178,7 @@ void list_setup(void) list_fname = NULL; if ((list_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0) - cantcreat(fnbuf); + CantCreateFile(fnbuf); } diff --git a/macro.c b/macro.c index 8d5d88e..4d63f2f 100644 --- a/macro.c +++ b/macro.c @@ -172,7 +172,7 @@ int DefineMacro(void) { argno = 0; symlist(defmac2); - at_eol(); + ErrorIfNotAtEOL(); } // Suck in the macro definition; we're looking for an ENDM symbol on a line diff --git a/object.c b/object.c index bee4fd6..29fd8f3 100644 --- a/object.c +++ b/object.c @@ -9,11 +9,13 @@ #include "object.h" #include "6502.h" #include "direct.h" +#include "dsp56k.h" #include "error.h" #include "mark.h" #include "riscasm.h" #include "sect.h" #include "symbol.h" +#include "version.h" //#define DEBUG_ELF @@ -56,6 +58,10 @@ See left. 4 & 5 If these bits are set to 0 (PF_PRIVATE), the processes' - 6-15 Currently unused */ +// Internal function prototypes +static void WriteLOD(void); +static void WriteP56(void); + // // Add entry to symbol table (in ALCYON mode) @@ -351,6 +357,7 @@ int WriteObject(int fd) if (strtable == NULL) { + free(buf); error("cannot allocate string table memory (in BSD mode)"); return ERROR; } @@ -359,6 +366,8 @@ int WriteObject(int fd) // Build object file header chptr = buf; // Base of header (for D_foo macros) + ch_size = 0; + challoc = 0x800000; D_long(0x00000107); // Magic number D_long(sect[TEXT].sloc); // TEXT size D_long(sect[DATA].sloc); // DATA size @@ -440,6 +449,8 @@ int WriteObject(int fd) // Build object file header just before the text+data image chptr = buf; // -> base of header + ch_size = 0; + challoc = HDRSIZE + tds + symbolMaxSize; D_word(0x601A); // 00 - magic number D_long(sect[TEXT].sloc); // 02 - TEXT size D_long(sect[DATA].sloc); // 06 - DATA size @@ -592,6 +603,8 @@ for(int j=0; jELF" Magic Number D_byte(0x01); // 04 - 32 vs 64 (1 = 32, 2 = 64) D_byte(0x02); // 05 - Endianness (1 = LE, 2 = BE) @@ -774,7 +787,174 @@ for(int j=0; j base of header + ch_size = 0; + challoc = 0x600000; + + if (obj_format == LOD) + WriteLOD(); + else + WriteP56(); + + // Write all the things |o/ + ssize_t unused = write(fd, buf, chptr - buf); + + if (buf) + free(buf); + } return 0; } + +static void WriteLOD(void) +{ + D_printf("_START %s 0000 0000 0000 RMAC %01i.%01i.%01i\n\n", firstfname, MAJOR, MINOR, PATCH); + + for(DSP_ORG * l=&dsp_orgmap[0]; lend != l->start) + { + switch (l->memtype) + { + case ORG_P: D_printf("_DATA P %.4X\n", l->orgadr); break; + case ORG_X: D_printf("_DATA X %.4X\n", l->orgadr); break; + case ORG_Y: D_printf("_DATA Y %.4X\n", l->orgadr); break; + case ORG_L: D_printf("_DATA L %.4X\n", l->orgadr); break; + default: + error("Internal error: unknown DSP56001 org'd section"); + return; + } + + CHUNK * cp = l->chunk; + uint8_t * p_chunk = l->start; + uint8_t * p_chunk_end = p_chunk; + uint32_t j = 0; + + while (p_chunk_end != l->end) + { + if (l->end < (cp->chptr + cp->ch_size) && l->end > cp->chptr) + { + // If the end of the section is inside the current chunk, just dump everything and stop + p_chunk_end = l->end; + } + else + { + // If the end of the section is not inside the current chunk, just dump everything from the current chunk and move on to the next + p_chunk_end = cp->chptr + cp->ch_size; + } + + uint32_t count = (uint32_t)(p_chunk_end - p_chunk); + + for(uint32_t i=0; ichnext; // Advance chunk + + if (cp != NULL) + p_chunk = cp->chptr; // Set dump pointer to start of this chunk + } + + if ((j & 7) != 0) + D_printf("\n"); + } + } + + // Dump the symbol table into the buf + DumpLODSymbols(); + + D_printf("\n_END %.4X\n", dsp_orgmap[0].orgadr); +} + + +static void WriteP56(void) +{ + for(DSP_ORG * l=&dsp_orgmap[0]; lend == l->start) + continue; + + if ((l->memtype < ORG_P) || (l->memtype > ORG_L)) + { + error("Internal error: unknown DSP56001 org'd section"); + return; + } + + CHUNK * cp = l->chunk; + uint8_t * p_chunk = l->start; + uint8_t * p_chunk_end = p_chunk; + + // Memory type (P, X, Y or L) + D_dsp(l->memtype); + + // Chunk start address (in DSP words) + D_dsp(l->orgadr); + + // Chunk length (in DSP words) + // We'll fill this field after we write the chunk so we can calculate + // how long it is (so if the chunk is split into different CHUNKs we + // can deal with this during copy) + uint8_t * p_buf_len = chptr; + chptr += 3; + + // The chunk itself + uint32_t chunk_size = 0; + + while (p_chunk_end != l->end) + { + if (l->end < (cp->chptr + cp->ch_size) && l->end > cp->chptr) + { + // If the end of the section is inside the current chunk, just + // dump everything and stop + p_chunk_end = l->end; + } + else + { + // If the end of the section is not inside the current chunk, + // just dump everything from the current chunk and move on to + // the next + p_chunk_end = cp->chptr + cp->ch_size; + } + + uint32_t current_chunk_size = p_chunk_end - p_chunk; + chunk_size += current_chunk_size; + memcpy(chptr, p_chunk, current_chunk_size); + chptr += current_chunk_size; + + cp = cp->chnext; // Advance chunk + + if (cp != NULL) + p_chunk = cp->chptr; // Set dump pointer to start of this chunk + } + + // Now we can mark the chunk's length (DSP word size is 24-bits, so + // the byte count needs to be divided by 3) + SETBE24(p_buf_len, chunk_size / 3); + } +} + diff --git a/op.c b/op.c index 6a78fbc..836f4de 100644 --- a/op.c +++ b/op.c @@ -177,7 +177,7 @@ static int HandleBitmap(void) } } - at_eol(); + ErrorIfNotAtEOL(); uint64_t p1 = 0x00 | ((ypos * 2) << 3) | (iheight << 14) | (linkAddr << 21) | (dataAddr << 40); uint64_t p2 = xpos | (bpp << 12) | (pitch << 15) | (dwidth << 18) | (iwidth << 28) | (index << 38) | (flags << 45) | (firstpix << 49); @@ -302,7 +302,7 @@ static int HandleScaledBitmap(void) } } - at_eol(); + ErrorIfNotAtEOL(); uint64_t p1 = 0x01 | ((ypos * 2) << 3) | (iheight << 14) | (linkAddr << 21) | (dataAddr << 40); uint64_t p2 = xpos | (bpp << 12) | (pitch << 15) | (dwidth << 18) | (iwidth << 28) | (index << 38) | (flags << 45) | (firstpix << 49); @@ -345,7 +345,7 @@ static int HandleGPUObject(void) if (!(eattr & DEFINED)) return error("bad expression in data"); - at_eol(); + ErrorIfNotAtEOL(); uint64_t p1 = 0x02 | ((ypos * 2) << 3) | (eval << 14); @@ -410,7 +410,7 @@ static int HandleBranch(void) if (!(eattr & DEFINED)) AddFixup(FU_QUAD | FU_OBJLINK, sloc, exprbuf); - at_eol(); + ErrorIfNotAtEOL(); uint64_t p1 = 0x03 | (cc << 14) | ((ypos * 2) << 3) | ((eval & 0x3FFFF8) << 21); @@ -468,7 +468,7 @@ static int HandleJump(void) if (!(eattr & DEFINED)) AddFixup(FU_QUAD | FU_OBJLINK, sloc, exprbuf); - at_eol(); + ErrorIfNotAtEOL(); // This is "branch if VC < 2047", which pretty much guarantees the branch. uint64_t p1 = 0x03 | (1 << 14) | (0x7FF << 3) | ((eval & 0x3FFFF8) << 21); diff --git a/procln.c b/procln.c index fe13aa7..8917004 100644 --- a/procln.c +++ b/procln.c @@ -587,7 +587,7 @@ When checking to see if it's already been equated, issue a warning. if (list_flag) // Put value in listing listvalue((uint32_t)eval); - at_eol(); // Must be at EOL now + ErrorIfNotAtEOL(); // Must be at EOL now goto loop; } @@ -782,11 +782,24 @@ When checking to see if it's already been equated, issue a warning. parcode = 0; } +#if 1 while ((dsp_am0 & md->mn0) == 0 || (dsp_am1 & md->mn1) == 0) md = &dsp56k_machtab[md->mncont]; (*md->mnfunc)(md->mninst | (parcode << 8)); goto loop; +#else + for(;;) + { + if ((dsp_am0 & md->mn0) != 0 && (dsp_am1 & md->mn1) != 0) + { + (*md->mnfunc)(md->mninst|(parcode << 8)); + goto loop; + } + + md = &dsp56k_machtab[md->mncont]; + } +#endif } } diff --git a/riscasm.c b/riscasm.c index fea5153..50fecf4 100644 --- a/riscasm.c +++ b/riscasm.c @@ -258,7 +258,7 @@ int GenerateRISCCode(int state) // UNPACK case RI_ONE: reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - at_eol(); + ErrorIfNotAtEOL(); DepositRISCInstructionWord(parm, parm >> 6, reg2); break; @@ -276,7 +276,7 @@ int GenerateRISCCode(int state) altbankok = 1; // MOVETA reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - at_eol(); + ErrorIfNotAtEOL(); DepositRISCInstructionWord(parm, reg1, reg2); break; @@ -338,7 +338,7 @@ int GenerateRISCCode(int state) CHECK_COMMA; reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - at_eol(); + ErrorIfNotAtEOL(); DepositRISCInstructionWord(parm, reg1, reg2); break; @@ -387,7 +387,7 @@ int GenerateRISCCode(int state) CHECK_COMMA; reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - at_eol(); + ErrorIfNotAtEOL(); DepositRISCInstructionWord(parm, 0, reg2); val = WORDSWAP32(eval); @@ -410,7 +410,7 @@ int GenerateRISCCode(int state) CHECK_COMMA; reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - at_eol(); + ErrorIfNotAtEOL(); DepositRISCInstructionWord(parm, reg1, reg2); break; @@ -533,7 +533,7 @@ int GenerateRISCCode(int state) tok++; CHECK_COMMA; reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - at_eol(); + ErrorIfNotAtEOL(); DepositRISCInstructionWord(parm, reg1, reg2); break; @@ -652,7 +652,7 @@ int GenerateRISCCode(int state) return MalformedOpcode(MALF_RPAREN); tok++; - at_eol(); + ErrorIfNotAtEOL(); DepositRISCInstructionWord(parm, reg2, reg1); break; @@ -670,7 +670,7 @@ int GenerateRISCCode(int state) tok++; CHECK_COMMA; reg2 = EvaluateRegisterFromTokenStream(FU_REGTWO); - at_eol(); + ErrorIfNotAtEOL(); DepositRISCInstructionWord(parm, reg1, reg2); break; @@ -689,7 +689,7 @@ int GenerateRISCCode(int state) return MalformedOpcode(MALF_RPAREN); tok++; - at_eol(); + ErrorIfNotAtEOL(); DepositRISCInstructionWord(parm, reg2, reg1); break; @@ -802,7 +802,7 @@ int GenerateRISCCode(int state) return MalformedOpcode(MALF_RPAREN); tok++; - at_eol(); + ErrorIfNotAtEOL(); } DepositRISCInstructionWord(parm, reg2, reg1); diff --git a/rmac.c b/rmac.c index ecc3adc..3f021e7 100644 --- a/rmac.c +++ b/rmac.c @@ -10,6 +10,7 @@ #include "6502.h" #include "debug.h" #include "direct.h" +#include "dsp56k.h" #include "error.h" #include "expr.h" #include "listing.h" @@ -148,6 +149,8 @@ void DisplayHelp(void) " a: ALCYON (use this for ST)\n" " b: BSD (use this for Jaguar)\n" " e: ELF\n" + " p: P56 (use this for DSP56001 only)\n" + " l: LOD (use this for DSP56001 only)\n" " x: com/exe/xex (Atari 800)\n" " -i[path] Directory to search for include files\n" " -l[filename] Create an output listing file\n" @@ -161,6 +164,7 @@ void DisplayHelp(void) " 6502\n" " tom\n" " jerry\n" + " 56001\n" " -n Don't do things behind your back in RISC assembler\n" " -o file Output file name\n" " +o[value] Turn a specific optimisation on\n" @@ -358,6 +362,14 @@ int Process(int argc, char ** argv) case 'E': obj_format = ELF; break; + case 'l': // -fl = LOD + case 'L': + obj_format = LOD; + break; + case 'p': // -fp = P56 + case 'P': + obj_format = P56; + break; case 'x': // -fx = COM/EXE/XEX case 'X': obj_format = XEX; @@ -588,6 +600,7 @@ int Process(int argc, char ** argv) // - "foo.o" for linkable output; // - "foo.prg" for GEMDOS executable (-p flag). SaveSection(); + int temp_section = cursect; for(i=TEXT; i<=BSS; i<<=1) { @@ -613,6 +626,20 @@ int Process(int argc, char ** argv) currentorg += 2; } + // This looks like an awful kludge... !!! FIX !!! + if (temp_section & (M56001P | M56001X | M56001Y)) + { + SwitchSection(temp_section); + + if (chptr != dsp_currentorg->start) + { + dsp_currentorg->end = chptr; + dsp_currentorg++; + } + } + + SwitchSection(TEXT); + if (objfname == NULL) { if (firstfname == NULL) @@ -635,7 +662,7 @@ int Process(int argc, char ** argv) if (errcnt == 0) { if ((fd = open(objfname, _OPEN_FLAGS, _PERM_MODE)) < 0) - cantcreat(objfname); + CantCreateFile(objfname); if (verb_flag) { diff --git a/rmac.h b/rmac.h index 10e7e59..cd7d671 100644 --- a/rmac.h +++ b/rmac.h @@ -137,6 +137,12 @@ { (a)[(r + 0)] = (uint8_t)((v) & 0xFF); \ (a)[(r + 1)] = (uint8_t)((v) >> 8); } +// In DSP56001 mode, this is useful: +#define SETBE24(a, v) \ + { (a)[0] = (uint8_t)(((v) >> 16) & 0xFF); \ + (a)[1] = (uint8_t)(((v) >> 8) & 0xFF); \ + (a)[2] = (uint8_t)((v) & 0xFF); } + // Byteswap crap #define BYTESWAP16(x) ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8)) #define BYTESWAP32(x) ((((x) & 0x000000FF) << 24) | (((x) & 0x0000FF00) << 8) | (((x) & 0x00FF0000) >> 8) | (((x) & 0xFF000000) >> 24)) @@ -218,12 +224,13 @@ PTR #define TEXT 0x0001 // Relative to text #define DATA 0x0002 // Relative to data #define BSS 0x0004 // Relative to BSS +//OK, this is bad, mmkay? These are treated as indices into an array which means that this was never meant to be defined this way--at least if it was, it was a compromise that has come home to bite us all in the ass. !!! FIX !!! #define M6502 0x0008 // 6502/microprocessor (absolute) #define M56001P 0x0010 // DSP 56001 Program RAM #define M56001X 0x0020 // DSP 56001 X RAM #define M56001Y 0x0040 // DSP 56001 Y RAM #define M56001L 0x0080 // DSP 56001 L RAM -#define TDB (TEXT|DATA|BSS) // Mask for text+data+bss +#define TDB (TEXT|DATA|BSS) // Mask for TEXT+DATA+BSS #define M56KPXYL (M56001P|M56001X|M56001Y|M56001L) // Mask for 56K stuff // Sizes diff --git a/sect.c b/sect.c index 9c1a586..49806a0 100644 --- a/sect.c +++ b/sect.c @@ -9,6 +9,7 @@ #include "sect.h" #include "6502.h" #include "direct.h" +#include "dsp56k.h" #include "error.h" #include "expr.h" #include "listing.h" @@ -75,11 +76,14 @@ void InitSection(void) MakeSection(i, 0); // Construct default sections, make TEXT the current section - MakeSection(ABS, SUSED | SABS | SBSS); // ABS - MakeSection(TEXT, SUSED | TEXT ); // TEXT - MakeSection(DATA, SUSED | DATA ); // DATA - MakeSection(BSS, SUSED | BSS | SBSS); // BSS - MakeSection(M6502, SUSED | TEXT ); // 6502 code section + MakeSection(ABS, SUSED | SABS | SBSS); // ABS + MakeSection(TEXT, SUSED | TEXT ); // TEXT + MakeSection(DATA, SUSED | DATA ); // DATA + MakeSection(BSS, SUSED | BSS | SBSS); // BSS + MakeSection(M6502, SUSED | TEXT ); // 6502 code section + MakeSection(M56001P, SUSED | SABS ); // DSP 56001 Program RAM + MakeSection(M56001X, SUSED | SABS ); // DSP 56001 X RAM + MakeSection(M56001Y, SUSED | SABS ); // DSP 56001 Y RAM // Switch to TEXT for starters SwitchSection(TEXT); @@ -128,9 +132,13 @@ void SwitchSection(int sno) // For 6502 mode, add the last org'd address // Why? /* -Because the way this is set up it treats the 6502 assembly space as a single 64K space (+ 16 bytes, for some reason) and just bobbles around inside that space and uses a stack of org "pointers" to show where the data ended up. +Because the way this is set up it treats the 6502 assembly space as a single 64K space (+ 16 bytes, for some unknown reason) and just bobbles around inside that space and uses a stack of org "pointers" to show where the data ended up. -This is a piss poor way to handle things, and for fucks sake, we can do better than this! +This is a shitty way to handle things, and we can do better than this! :-P + +Really, there's no reason to have the 6502 (or DSP56001 for that matter) have their own private sections for this kind of thing, as there's literally *no* chance that it would be mingled with 68K+ code. It should be able to use the TEXT, DATA & BSS sections just like the 68K. + +Or should it? After looking at the code, maybe it's better to keep the 56001 sections segregated from the rest. But we can still make the 6502 stuff better. */ if (m6502) chptr = cp->chptr + orgaddr; @@ -267,7 +275,8 @@ int AddFixup(uint32_t attr, uint32_t loc, TOKEN * fexpr) if (attr & FUMASKDSP) { attr |= FU_56001; - _orgaddr = orgaddr; + // Save the exact spot in this chunk where the fixup should go + _orgaddr = chptr - scode->chptr; } // Allocate space for the fixup + any expression @@ -349,6 +358,9 @@ int ResolveFixups(int sno) // than this. SetFilenameForErrorReporting(); + if ((sno == M56001P) || (sno == M56001X) || (sno == M56001Y) || (sno == M56001L)) + loc = fup->orgaddr; + // Search for chunk containing location to fix up; compute a // pointer to the location (in the chunk). Often we will find the // Fixup is in the "cached" chunk, so the linear-search is seldom @@ -566,16 +578,7 @@ int ResolveFixups(int sno) case FU_WORD: if ((dw & FUMASKRISC) == FU_JR) { -#if 0 - int reg; - - if (fup->orgaddr) - reg = (signed)((eval - (fup->orgaddr + 2)) / 2); - else - reg = (signed)((eval - (loc + 2)) / 2); -#else int reg = (signed)((eval - ((fup->orgaddr ? fup->orgaddr : loc) + 2)) / 2); -#endif if ((reg < -16) || (reg > 15)) { @@ -727,8 +730,8 @@ int ResolveFixups(int sno) uint64_t addr = eval; //Hmm, not sure how this can be set, since it's only set if it's a DSP56001 fixup or a FU_JR... :-/ - if (fup->orgaddr) - addr = fup->orgaddr; +// if (fup->orgaddr) +// addr = fup->orgaddr; eval = (quad & 0xFFFFFC0000FFFFFFLL) | ((addr & 0x3FFFF8) << 21); } @@ -743,8 +746,8 @@ int ResolveFixups(int sno) uint64_t addr = eval; //Hmm, not sure how this can be set, since it's only set if it's a DSP56001 fixup or a FU_JR... :-/ - if (fup->orgaddr) - addr = fup->orgaddr; +// if (fup->orgaddr) +// addr = fup->orgaddr; eval = (quad & 0x000007FFFFFFFFFFLL) | ((addr & 0xFFFFF8) << 40); } @@ -798,7 +801,7 @@ int ResolveFixups(int sno) case FU_DSPADR12: if (eval >= 0x1000) { - error("address out of range ($000-$FFF)"); + error("address out of range ($0-$FFF)"); break; } @@ -809,22 +812,22 @@ int ResolveFixups(int sno) // This is a full DSP word containing Effective Address Extension case FU_DSPADR24: case FU_DSPIMM24: - if (eval >= 0x100000) + if (eval >= 0x1000000) { - error("value out of range ($000-$FFFFFF)"); + error("value out of range ($0-$FFFFFF)"); break; } - *locp++ = (uint32_t)eval >> 16; - *locp++ = ((uint32_t)eval >> 8) & 0xFF; - *locp++ = (uint32_t)eval & 0xFF; + locp[0] = (uint8_t)((eval >> 16) & 0xFF); + locp[1] = (uint8_t)((eval >> 8) & 0xFF); + locp[2] = (uint8_t)(eval & 0xFF); break; // This is a 16bit absolute address into a 24bit field case FU_DSPADR16: if (eval >= 0x10000) { - error("address out of range ($0000-$FFFF)"); + error("address out of range ($0-$FFFF)"); break; } @@ -838,7 +841,7 @@ int ResolveFixups(int sno) case FU_DSPIMM12: if (eval >= 0x1000) { - error("immediate out of range ($000-$FFF)"); + error("immediate out of range ($0-$FFF)"); break; } @@ -851,7 +854,7 @@ int ResolveFixups(int sno) case FU_DSPIMM8: if (eval >= 0x100) { - error("immediate out of range ($00-$FF)"); + error("immediate out of range ($0-$FF)"); break; } @@ -948,6 +951,12 @@ int ResolveAllFixups(void) ResolveFixups(DATA); DEBUG printf("Resolving 6502 sections...\n"); ResolveFixups(M6502); // Fixup 6502 section (if any) + DEBUG printf("Resolving DSP56001 P: sections...\n"); + ResolveFixups(M56001P); // Fixup 56001 P: section (if any) + DEBUG printf("Resolving DSP56001 X: sections...\n"); + ResolveFixups(M56001X); // Fixup 56001 X: section (if any) + DEBUG printf("Resolving DSP56001 Y: sections...\n"); + ResolveFixups(M56001Y); // Fixup 56001 Y: section (if any) return 0; } diff --git a/sect.h b/sect.h index 84ad789..fb1db43 100644 --- a/sect.h +++ b/sect.h @@ -54,7 +54,9 @@ #define D_ZEROFILL(n) {chcheck(n); memset(chptr, 0, n); chptr+=n; sloc+=n; \ ch_size+=n; if (orgactive) orgaddr+=n;} -#define NSECTS 16 // Max. number of sections +//OK, this is bad, mmkay? The constants defined in rmac.h are used as indices into an array which means that this was never meant to be defined this way--at least if it was, it was a compromise that has come home to bite us all in the ass. !!! FIX !!! +//#define NSECTS 16 // Max. number of sections +#define NSECTS 256 // Max. number of sections // Tunable (storage) definitions #define CH_THRESHOLD 32 // Minimum amount of space in code chunk diff --git a/symbol.c b/symbol.c index 84d5e16..c1abfab 100644 --- a/symbol.c +++ b/symbol.c @@ -7,6 +7,7 @@ // #include "symbol.h" +#include "dsp56k.h" #include "error.h" #include "listing.h" #include "object.h" @@ -35,6 +36,9 @@ static uint8_t tdb_text[8] = { 'a', 't', 'd', '!', 'b', SPACE, SPACE, SPACE }; +// Internal function prototypes +static uint16_t WriteLODSection(int, uint16_t); + // // Initialize symbol table @@ -332,6 +336,53 @@ uint32_t sy_assign_ELF(uint8_t * buf, uint8_t *(* construct)()) } +// +// Helper function for dsp_lod_symbols +// +static uint16_t WriteLODSection(int section, uint16_t symbolCount) +{ + for(SYM * sy=sdecl; sy!=NULL; sy=sy->sdecl) + { + // Export vanilla labels (but don't make them global). An exception is + // made for equates, which are not exported unless they are referenced. + if (sy->stype == LABEL && lsym_flag + && (sy->sattr & (DEFINED | REFERENCED)) != 0 + && (*sy->sname != '.') + && (sy->sattr & GLOBAL) == 0 + && (sy->sattr & (section))) + { + sy->senv = symbolCount++; + D_printf("%-19s I %.6" PRIX64 "\n", sy->sname, sy->svalue); + } + } + + return symbolCount; +} + + +// +// Dump LOD style symbols into the passed in buffer +// +void DumpLODSymbols(void) +{ + D_printf("_SYMBOL P\n"); + uint16_t count = WriteLODSection(M56001P, 0); + + D_printf("_SYMBOL X\n"); + count = WriteLODSection(M56001X, count); + + D_printf("_SYMBOL Y\n"); + count = WriteLODSection(M56001Y, count); + + D_printf("_SYMBOL L\n"); + count = WriteLODSection(M56001L, count); + + // TODO: I've seen _SYMBOL N in there but no idea what symbols it needs... + //D_printf("_SYMBOL N\n"); + //WriteLODSection(M56001?, count); +} + + // // Convert string to uppercase // diff --git a/symbol.h b/symbol.h index 47ea3cd..f8391a0 100644 --- a/symbol.h +++ b/symbol.h @@ -51,6 +51,7 @@ void ForceUndefinedSymbolsGlobal(void); int symtable(void); uint32_t sy_assign(uint8_t *, uint8_t *(*)()); uint32_t sy_assign_ELF(uint8_t *, uint8_t *(*)()); +void DumpLODSymbols(void); uint8_t * GetSymbolNameByUID(uint32_t); #endif // __SYMBOL_H__ diff --git a/token.c b/token.c index 564ff0c..cd6b9c6 100644 --- a/token.c +++ b/token.c @@ -1171,7 +1171,7 @@ DEBUG { printf("TokenizeLine: Calling fpop() from SRC_IFILE...\n"); } } // Make j = -1 if user tries to use a RISC register while in 68K mode - if (!(rgpu || rdsp) && ((TOKEN)j >= KW_R0 && (TOKEN)j <= KW_R31)) + if (!(rgpu || rdsp || dsp56001) && ((TOKEN)j >= KW_R0 && (TOKEN)j <= KW_R31)) { j = -1; } diff --git a/version.h b/version.h index 1be65d8..a6184b5 100644 --- a/version.h +++ b/version.h @@ -13,9 +13,9 @@ // Release Information -#define MAJOR 1 // Major version number -#define MINOR 13 // Minor version number -#define PATCH 5 // Patch release number +#define MAJOR 2 // Major version number +#define MINOR 0 // Minor version number +#define PATCH 0 // Patch release number #endif // __VERSION_H__