From bf793486173623416e8133df59c532bd7c2955e6 Mon Sep 17 00:00:00 2001 From: ggn Date: Mon, 25 Dec 2023 10:42:29 +0200 Subject: [PATCH] Fix for multiple 56k illegal combinations of parallel moves --- Vs2015/rmac/rmac.vcxproj | 1 - dsp56k.mch | 10 +++--- dsp56k_amode.c | 66 +++++++++++++++++++++++++++++----------- dsp56k_amode.h | 6 ++-- procln.c | 33 ++++++++++++++++++-- 5 files changed, 87 insertions(+), 29 deletions(-) diff --git a/Vs2015/rmac/rmac.vcxproj b/Vs2015/rmac/rmac.vcxproj index 3b2a6b4..0ac267f 100644 --- a/Vs2015/rmac/rmac.vcxproj +++ b/Vs2015/rmac/rmac.vcxproj @@ -49,7 +49,6 @@ - diff --git a/dsp56k.mch b/dsp56k.mch index c73ecaf..94e6ac6 100644 --- a/dsp56k.mch +++ b/dsp56k.mch @@ -9,10 +9,10 @@ addl M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0001d010 dsp_baab addr M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d010 dsp_baab d=(b,a=0, a,b=1) add M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0001d000 dsp_baab + d=(a=0, b=1) - M_ALL48 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0jjjd000 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1) -cmp M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d101 dsp_baab + d=(a=0, b=1) -- M_ALU24 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0jjjd101 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1) -cmpm M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d111 dsp_baab + d=(a=0, b=1) -- M_ALU24 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0jjjd111 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1) +cmp M_ACC56 M_ACC56 PARTEST %mmmmmmmmmmmmmmmm0000d101 dsp_baab + d=(a=0, b=1) +- M_ALU24 M_ACC56 PARTEST %mmmmmmmmmmmmmmmm0jjjd101 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1) +cmpm M_ACC56 M_ACC56 PARTEST %mmmmmmmmmmmmmmmm0000d111 dsp_baab + d=(a=0, b=1) +- M_ALU24 M_ACC56 PARTEST %mmmmmmmmmmmmmmmm0jjjd111 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1) sub M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0001d100 dsp_baab + d=(a=0, b=1) - M_ALL48 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0jjjd100 dsp_acc48 jjj=(x=2, y=3, x0=4, y0=5, x1=6, y1=7), d=(a=0, b=1) tfr M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d001 dsp_baab + d=(a=0, b=1) @@ -22,7 +22,7 @@ rol M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0011d111 dsp_ab ror M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0010d111 dsp_ab d=(a=0, b=1) subl M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0001d110 dsp_baab d=(b,a=0, a,b=1) subr M_ACC56 M_ACC56 PARMOVE %mmmmmmmmmmmmmmmm0000d110 dsp_baab d=(b,a=0, a,b=1) -tst M_ACC56 M_AM_NONE PARMOVE %mmmmmmmmmmmmmmmm0000d011 dsp_ab d=(a=0, b=1) +tst M_ACC56 M_AM_NONE PARTEST %mmmmmmmmmmmmmmmm0000d011 dsp_ab d=(a=0, b=1) enddo M_AM_NONE M_AM_NONE NOPARMO %000000000000000010001100 dsp_self illegal M_AM_NONE M_AM_NONE NOPARMO %000000000000000000000101 dsp_self nop M_AM_NONE M_AM_NONE NOPARMO %000000000000000000000000 dsp_self diff --git a/dsp56k_amode.c b/dsp56k_amode.c index 664c533..c293284 100644 --- a/dsp56k_amode.c +++ b/dsp56k_amode.c @@ -888,7 +888,7 @@ static inline int SDreg(int reg) { if (reg >= REG56_X0 && reg <= REG56_N7) return reg & 0xFF; - else if (reg >= REG56_A0&® <= REG56_A2) + else if (reg >= REG56_A0 && reg <= REG56_A2) return (8 >> (reg & 7)) | 8; else //if (reg>=REG56_R0&®<=REG56_R7) return reg - REG56_R0 + 16; @@ -899,9 +899,9 @@ static inline int SDreg(int reg) // x1 | 261 | 5 // y0 | 262 | 6 // y1 | 263 | 7 - // b0 | 265 | 8 - // b2 | 267 | 9 - // b1 | 269 | 10 + // b0 | 265 | 9 + // b2 | 267 | 11 + // b1 | 269 | 13 // a | 270 | 14 // b | 271 | 15 // n0 | 280 | 24 @@ -912,9 +912,9 @@ static inline int SDreg(int reg) // n5 | 285 | 29 // n6 | 286 | 30 // n7 | 287 | 31 - // a0 | 136 | 0 - // a1 | 137 | 1 - // a2 | 138 | 2 + // a0 | 136 | 8 + // a1 | 137 | 9 + // a2 | 138 | 10 // r0 | 151 | 16 // r1 | 152 | 17 // r2 | 153 | 18 @@ -1168,7 +1168,7 @@ static inline LONG check_x_y(LONG ea1, LONG S1) // // 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) +static inline LONG parse_x(const int W, LONG inst, const LONG S1, const int check_for_x_y, WORD dest) { int immreg; // Immediate register destination LONG S2, D1, D2; // Source and Destinations @@ -1207,6 +1207,9 @@ x_checkea_right: if (S1 != 14) return error("unrecognised X:R parallel move syntax: S1 can only be a in 'a,X:ea x0,a'"); + if (S1 == 14 && ea1 == DSP_EA_ABS) + return error("unrecognised X:R parallel move syntax: absolute address not allowed 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'"); @@ -1219,12 +1222,18 @@ x_checkea_right: else if (*tok == REG56_X0 && tok[1] == ',' && tok[2] == REG56_B) { // 'B,X:ea X0,B' + if (dest == REG56_B) + return error("illegal X:R parallel move syntax: base instruction's destination register cannot be b in '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 (S1 == 15 && ea1 == DSP_EA_ABS) + return error("unrecognised X:R parallel move syntax: absolute address not allowed 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'"); @@ -1579,7 +1588,7 @@ x_gotea1: // then it won't be used anyway ea1 = DSP_EA_ABS; - if (!(dspImmedEXATTR&DEFINED)) + if (!(dspImmedEXATTR & DEFINED)) { force_imm = NUM_FORCE_LONG; deposit_extra_ea = DEPOSIT_EXTRA_WORD; @@ -1653,7 +1662,7 @@ x_gotea1: // // Parse Y: addressing space parallel moves // -static inline LONG parse_y(LONG inst, LONG S1, LONG D1, LONG S2) +static inline LONG parse_y(LONG inst, LONG S1, LONG D1, LONG S2, WORD dest) { int immreg; // Immediate register destination LONG D2; // Destination @@ -1861,6 +1870,13 @@ static inline LONG parse_y(LONG inst, LONG S1, LONG D1, LONG S2) { //'Y:ea,D' D1 = SDreg(*tok++); + + if (dest && dest == REG56_A && (D1 == 14 || D1 == 0 || D1 == 1 || D1 == 2)) + return error("illegal R:Y parallel move syntax: cannot have base instruction's destination register to be a and D in 'Y:ea,D' to be a, a0, a1 or a2"); + + if (dest && dest == REG56_B && (D1 == 15 || D1 == 8 || D1 == 9 || D1 == 10)) + return error("illegal R:Y parallel move syntax: cannot have base instruction's destination register to be a and D in 'Y:ea,D' to be a, a0, a1 or a2"); + inst |= 0b0000000001000000; inst |= ea1; inst |= ((D1 & 0x18) << (12 - 3)) + ((D1 & 7) << 8); @@ -2495,7 +2511,8 @@ LONG checkea_full(const uint32_t termchar, const int strings) // It's quite complex so it's split into a few procedures (in fact most of the // above ones). A big effort was made so this can be managable and not too // hacky, however one look at the 56001 manual regarding parallel moves and -// you'll know that this is not an easy // problem to deal with! +// you'll know that this is not an easy +// problem to deal with! // dest=destination register from the main opcode. This must not be the same // as D1 or D2 and that even goes for stuff like dest=A, D1=A0/1/2!!! // @@ -2539,10 +2556,20 @@ LONG parmoves(WORD dest) if (!((*tok >= REG56_X0 && *tok <= REG56_N7) || (*tok >= REG56_R0 && *tok <= REG56_R7) || (*tok >= REG56_A0 && *tok <= REG56_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++); + D1 = *tok++; + immreg = SDreg(D1); if (*tok == EOL) { + if (dest == REG56_A && (D1 == REG56_A || D1 == REG56_A0 || D1 == REG56_A1 || D1 == REG56_A2)) + { + return error("illegal #xxxxxx,D parallel move syntax: instruction's destination register cannot be a and D in '#xxxxxx,D' be a, a0, a1 or a2"); + } + if (dest == REG56_B && (D1 == REG56_B || D1 == REG56_B0 || D1 == REG56_B1 || D1 == REG56_B2)) + { + return error("illegal #xxxxxx,D parallel move syntax: instruction's destination register cannot be b and D in '#xxxxxx,D' be b, b0, b1 or b2"); + } + if (!(dspImmedEXATTR & FLOAT)) { if (dspImmedEXATTR & DEFINED) @@ -2759,7 +2786,7 @@ deposit_immediate_short_with_register: 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, 0b0100000000000000, 0, 1); + return parse_x(1, 0b0100000000000000, 0, 1, dest); } else if (*tok == REG56_Y) { @@ -2773,7 +2800,7 @@ deposit_immediate_short_with_register: return error("expected ':' after 'Y' in parallel move (i.e. Y:)"); // 'Y:ea,D' or 'Y:aa,D' - return parse_y(0b0100100010000000, 0, 0, 0); + return parse_y(0b0100100010000000, 0, 0, 0, dest); } else if (*tok == REG56_L) { @@ -2791,7 +2818,7 @@ deposit_immediate_short_with_register: // 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' + // 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,B B,Y:ea' // L: 'S,L:ea' 'S,L:aa' LONG L_S1; parse_everything_else: @@ -2810,7 +2837,7 @@ parse_everything_else: if (*tok++ != ':') return error("unrecognised X: parallel move syntax: expected ':' after 'S,X'"); - return parse_x(0, 0b0100000000000000, S1, 1); + return parse_x(0, 0b0100000000000000, S1, 1, dest); } else if (*tok == REG56_Y) { @@ -2820,7 +2847,7 @@ parse_everything_else: if (*tok++ != ':') return error("unrecognised Y: parallel move syntax: expected ':' after 'S,Y'"); - return parse_y(0b000000000000000, S1, 0, 0); + return parse_y(0b000000000000000, S1, 0, 0, dest); } else if (*tok == REG56_L) { @@ -2852,7 +2879,7 @@ parse_everything_else: tok++; if (*tok++ != ':') return error("expected ':' after 'Y' in parallel move (i.e. Y:)"); - return parse_y(0b0001000001000000, S1, D1, 0); + return parse_y(0b0001000001000000, S1, D1, 0, dest); } else if (*tok == REG56_A || *tok == REG56_B || *tok == REG56_Y0 || *tok == REG56_Y1) @@ -2874,6 +2901,9 @@ parse_everything_else: ea1 = checkea_full(EOL, Y_ERRORS); + if (ea1 == DSP_EA_ABS) + return error("unrecognised X:R parallel move syntax: absolute address not allowed in 'y0,a a,y:ea'"); + if (ea1 == ERROR) return ERROR; diff --git a/dsp56k_amode.h b/dsp56k_amode.h index 5f2d53f..f9c5b7d 100644 --- a/dsp56k_amode.h +++ b/dsp56k_amode.h @@ -68,8 +68,10 @@ // B10 Accumulator B= B1:B0 (48 bits) // Attribute masks -#define PARMOVE 0x00000001L -#define NOPARMO 0x00000000L +#define PARMOVE 0x00000001L +#define NOPARMO 0x00000000L +#define PARNOWRITE 0x00000002L // Instruction does not write to a destination (CMP and TST mostly) +#define PARTEST (PARMOVE|PARNOWRITE) // DSP EA modes diff --git a/procln.c b/procln.c index 463ed1d..df6df2d 100644 --- a/procln.c +++ b/procln.c @@ -685,9 +685,10 @@ When checking to see if it's already been equated, issue a warning. if (state >= 2000) { LONG parcode; - int operands; + int operands = 0; MNTABDSP * md = &dsp56k_machtab[state - 2000]; deposit_extra_ea = 0; // Assume no extra word needed + dsp_a1reg = 0; if (md->mnfunc == dsp_mult) { @@ -698,7 +699,7 @@ When checking to see if it's already been equated, issue a warning. } else if ((md->mnattr & PARMOVE) && md->mn0 != M_AM_NONE) { - if (dsp_amode(2) == ERROR) + if ((operands = dsp_amode(2)) == ERROR) goto loop; } else if ((md->mnattr & PARMOVE) && md->mn0 == M_AM_NONE) @@ -725,7 +726,33 @@ When checking to see if it's already been equated, issue a warning. if (md->mnattr & PARMOVE) { // Check for parallel moves - if ((parcode = parmoves(dsp_a1reg)) == ERROR) + // We need to pass the information of which destination + // register (if any) is in the main opcode to the parallel + // moves routine. This is a bit more nuanced than originally + // expected: for starters, different variables hold the + // destination register depending on the amount of operands + // (dsp_a1reg, etc). Then some instructions with parallel moves + // simply do not alter any register (cmp and tst mostly). There + // are also cases of the instruction not containing any register + // (example: move with only a X:R field). + int destination_register = dsp_a1reg; + if (md->mnattr & PARNOWRITE) + { + destination_register = 0; + } + else if (operands == 3) + { + destination_register = dsp_a2reg; + } + else if (operands == 4) + { + // No parallel moves + } + else if (operands == 0) + { + destination_register = 0; + } + if ((parcode = parmoves(destination_register)) == ERROR) goto loop; } else -- 2.40.1.windows.1