X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=sim%2Fsh%2Fgencode.c;h=5eb7caf258936972082a6c9c84e99b3fe47a3141;hb=5bab16fdf1775c8abd16376458c5843fbe1d4314;hp=9769d7391c00f14eeb5e4a73d71b86e1e8c8161b;hpb=0145ab2e522710ce9b87652c2afdcc44cf51ac8b;p=binutils-gdb.git diff --git a/sim/sh/gencode.c b/sim/sh/gencode.c index 9769d7391c0..5eb7caf2589 100644 --- a/sim/sh/gencode.c +++ b/sim/sh/gencode.c @@ -30,22 +30,27 @@ */ +#include #include +#include +#include +#include +#include "libiberty.h" #define MAX_NR_STUFF 42 typedef struct { - char *defs; - char *refs; - char *name; - char *code; - char *stuff[MAX_NR_STUFF]; + const char *defs; + const char *refs; + const char *name; + const char *code; + const char * const stuff[MAX_NR_STUFF]; int index; } op; -op tab[] = +static op tab[] = { { "n", "", "add #,", "0111nnnni8*1....", @@ -84,6 +89,7 @@ op tab[] = }, { "", "", "bf ", "10001011i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (!T) {", " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", @@ -91,6 +97,7 @@ op tab[] = }, { "", "", "bf.s ", "10001111i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (!T) {", " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", @@ -98,19 +105,35 @@ op tab[] = "}", }, + { "", "n", "bit32 #imm3,@(disp12,)", "0011nnnni8*11001", + "/* 32-bit logical bit-manipulation instructions. */", + "int word2 = RIAT (nip);", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "i >>= 4; /* BOGUS: Using only three bits of 'i'. */", + "/* MSB of 'i' must be zero. */", + "if (i > 7)", + " RAISE_EXCEPTION (SIGILL);", + "MA (1);", + "do_blog_insn (1 << i, (word2 & 0xfff) + R[n], ", + " (word2 >> 12) & 0xf, memory, maskb);", + "SET_NIP (nip + 2); /* Consume 2 more bytes. */", + }, { "", "", "bra ", "1010i12.........", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_NIP (PC + 4 + (SEXT12 (i) * 2));", "cycles += 2;", "Delay_Slot (PC + 2);", }, { "", "n", "braf ", "0000nnnn00100011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_NIP (PC + 4 + R[n]);", "cycles += 2;", "Delay_Slot (PC + 2);", }, { "", "", "bsr ", "1011i12.........", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "PR = PH2T (PC + 4);", "SET_NIP (PC + 4 + (SEXT12 (i) * 2));", "cycles += 2;", @@ -118,6 +141,7 @@ op tab[] = }, { "", "n", "bsrf ", "0000nnnn00000011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "PR = PH2T (PC) + 4;", "SET_NIP (PC + 4 + R[n]);", "cycles += 2;", @@ -125,13 +149,189 @@ op tab[] = }, { "", "", "bt ", "10001001i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (T) {", " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", "}", }, + + { "", "m", "bld/st #, ", "10000111mmmmi4*1", + "/* MSB of 'i' is true for load, false for store. */", + "if (i <= 7)", + " if (T)", + " R[m] |= (1 << i);", + " else", + " R[m] &= ~(1 << i);", + "else", + " SET_SR_T ((R[m] & (1 << (i - 8))) != 0);", + }, + { "m", "m", "bset/clr #, ", "10000110mmmmi4*1", + "/* MSB of 'i' is true for set, false for clear. */", + "if (i <= 7)", + " R[m] &= ~(1 << i);", + "else", + " R[m] |= (1 << (i - 8));", + }, + { "n", "n", "clips.b ", "0100nnnn10010001", + "if (R[n] < -128 || R[n] > 127) {", + " L (n);", + " SET_SR_CS (1);", + " if (R[n] > 127)", + " R[n] = 127;", + " else if (R[n] < -128)", + " R[n] = -128;", + "}", + }, + { "n", "n", "clips.w ", "0100nnnn10010101", + "if (R[n] < -32768 || R[n] > 32767) {", + " L (n);", + " SET_SR_CS (1);", + " if (R[n] > 32767)", + " R[n] = 32767;", + " else if (R[n] < -32768)", + " R[n] = -32768;", + "}", + }, + { "n", "n", "clipu.b ", "0100nnnn10000001", + "if (R[n] < -256 || R[n] > 255) {", + " L (n);", + " SET_SR_CS (1);", + " R[n] = 255;", + "}", + }, + { "n", "n", "clipu.w ", "0100nnnn10000101", + "if (R[n] < -65536 || R[n] > 65535) {", + " L (n);", + " SET_SR_CS (1);", + " R[n] = 65535;", + "}", + }, + { "n", "0n", "divs R0,", "0100nnnn10010100", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "if (R0 == 0)", + " R[n] = 0x7fffffff;", + "else if (R0 == -1 && R[n] == 0x80000000)", + " R[n] = 0x7fffffff;", + "else R[n] /= R0;", + "L (n);", + }, + { "n", "0n", "divu R0,", "0100nnnn10000100", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "if (R0 == 0)", + " R[n] = 0xffffffff;", + "/* FIXME: The result may be implementation-defined if it is outside */", + "/* the range of signed int (i.e. if R[n] was negative and R0 == 1). */", + "else R[n] = R[n] / (unsigned int) R0;", + "L (n);", + }, + { "n", "0n", "mulr R0,", "0100nnnn10000000", + "R[n] = (R[n] * R0) & 0xffffffff;", + "L (n);", + }, + { "0", "n", "ldbank @,R0", "0100nnnn11100101", + "int regn = (R[n] >> 2) & 0x1f;", + "int bankn = (R[n] >> 7) & 0x1ff;", + "if (regn > 19)", + " regn = 19; /* FIXME what should happen? */", + "R0 = saved_state.asregs.regstack[bankn].regs[regn];", + "L (0);", + }, + { "", "0n", "stbank R0,@", "0100nnnn11100001", + "int regn = (R[n] >> 2) & 0x1f;", + "int bankn = (R[n] >> 7) & 0x1ff;", + "if (regn > 19)", + " regn = 19; /* FIXME what should happen? */", + "saved_state.asregs.regstack[bankn].regs[regn] = R0;", + }, + { "", "", "resbank", "0000000001011011", + "int i;", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + /* FIXME: cdef all */ + "if (BO) { /* Bank Overflow */", + /* FIXME: how do we know when to reset BO? */ + " for (i = 0; i <= 14; i++) {", + " R[i] = RLAT (R[15]);", + " MA (1);", + " R[15] += 4;", + " }", + " PR = RLAT (R[15]);", + " R[15] += 4;", + " MA (1);", + " GBR = RLAT (R[15]);", + " R[15] += 4;", + " MA (1);", + " MACH = RLAT (R[15]);", + " R[15] += 4;", + " MA (1);", + " MACL = RLAT (R[15]);", + " R[15] += 4;", + " MA (1);", + "}", + "else if (BANKN == 0) /* Bank Underflow */", + " RAISE_EXCEPTION (SIGILL);", /* FIXME: what exception? */ + "else {", + " SET_BANKN (BANKN - 1);", + " for (i = 0; i <= 14; i++)", + " R[i] = saved_state.asregs.regstack[BANKN].regs[i];", + " MACH = saved_state.asregs.regstack[BANKN].regs[15];", + " PR = saved_state.asregs.regstack[BANKN].regs[17];", + " GBR = saved_state.asregs.regstack[BANKN].regs[18];", + " MACL = saved_state.asregs.regstack[BANKN].regs[19];", + "}", + }, + { "f", "f-", "movml.l ,@-R15", "0100nnnn11110001", + "/* Push Rn...R0 (if n==15, push pr and R14...R0). */", + "do {", + " MA (1);", + " R[15] -= 4;", + " if (n == 15)", + " WLAT (R[15], PR);", + " else", + " WLAT (R[15], R[n]);", + "} while (n-- > 0);", + }, + { "f", "f+", "movml.l @R15+,", "0100nnnn11110101", + "/* Pop R0...Rn (if n==15, pop R0...R14 and pr). */", + "int i = 0;\n", + "do {", + " MA (1);", + " if (i == 15)", + " PR = RLAT (R[15]);", + " else", + " R[i] = RLAT (R[15]);", + " R[15] += 4;", + "} while (i++ < n);", + }, + { "f", "f-", "movmu.l ,@-R15", "0100nnnn11110000", + "/* Push pr, R14...Rn (if n==15, push pr). */", /* FIXME */ + "int i = 15;\n", + "do {", + " MA (1);", + " R[15] -= 4;", + " if (i == 15)", + " WLAT (R[15], PR);", + " else", + " WLAT (R[15], R[i]);", + "} while (i-- > n);", + }, + { "f", "f+", "movmu.l @R15+,", "0100nnnn11110100", + "/* Pop Rn...R14, pr (if n==15, pop pr). */", /* FIXME */ + "do {", + " MA (1);", + " if (n == 15)", + " PR = RLAT (R[15]);", + " else", + " R[n] = RLAT (R[15]);", + " R[15] += 4;", + "} while (n++ < 15);", + }, + { "", "", "nott", "0000000001101000", + "SET_SR_T (T == 0);", + }, { "", "", "bt.s ", "10001101i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (T) {", " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", @@ -154,7 +354,7 @@ op tab[] = /* sh4a */ { "", "", "clrdmxy", "0000000010001000", - "saved_state.asregs.cregs.named.sr &= ~(SR_MASK_DMX | SR_MASK_DMY);" + "saved_state.asregs.sr &= ~(SR_MASK_DMX | SR_MASK_DMY);" }, { "", "0", "cmp/eq #,R0", "10001000i8*1....", @@ -206,11 +406,11 @@ op tab[] = }, { "", "nm", "dmuls.l ,", "0011nnnnmmmm1101", - "dmul (1/*signed*/, R[n], R[m]);", + "dmul_s (R[n], R[m]);", }, { "", "nm", "dmulu.l ,", "0011nnnnmmmm0101", - "dmul (0/*unsigned*/, R[n], R[m]);", + "dmul_u (R[n], R[m]);", }, { "n", "n", "dt ", "0100nnnn00010000", @@ -234,8 +434,14 @@ op tab[] = /* sh2e */ { "", "", "fabs ", "1111nnnn01011101", - "FP_UNARY (n, fabs);", - "/* FIXME: FR (n) &= 0x7fffffff; */", + " union", + " {", + " unsigned int i;", + " float f;", + " } u;", + " u.f = FR (n);", + " u.i &= 0x7fffffff;", + " SET_FR (n, u.f);", }, /* sh2e */ @@ -297,6 +503,8 @@ op tab[] = "else", "{", " double fsum = 0;", + " if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", " /* FIXME: check for nans and infinities. */", " fsum += FR (v1+0) * FR (v2+0);", " fsum += FR (v1+1) * FR (v2+1);", @@ -386,6 +594,18 @@ op tab[] = " SET_FI (n, RLAT (R[m]));", "}", }, + /* sh2a */ + { "", "n", "fmov.s @(disp12,), ", "0011nnnnmmmm0001", + "/* and fmov.s , @(disp12,)", + " and mov.bwl , @(disp12,)", + " and mov.bwl @(disp12,),", + " and movu.bw @(disp12,),. */", + "int word2 = RIAT (nip);", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "SET_NIP (nip + 2); /* Consume 2 more bytes. */", + "MA (1);", + "do_long_move_insn (word2 & 0xf000, word2 & 0x0fff, m, n, &thislock);", + }, /* sh2e */ { "m", "m", "fmov.s @+,", "1111nnnnmmmm1001", /* sh4 */ @@ -453,7 +673,14 @@ op tab[] = /* sh2e */ { "", "", "fneg ", "1111nnnn01001101", - "FP_UNARY (n, -);", + " union", + " {", + " unsigned int i;", + " float f;", + " } u;", + " u.f = FR (n);", + " u.i ^= 0x80000000;", + " SET_FR (n, u.f);", }, /* sh4a */ @@ -465,6 +692,8 @@ op tab[] = { "", "", "frchg", "1111101111111101", "if (FPSCR_PR)", " RAISE_EXCEPTION (SIGILL);", + "else if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", "else", " SET_FPSCR (GET_FPSCR () ^ FPSCR_MASK_FR);", }, @@ -473,6 +702,8 @@ op tab[] = { "", "", "fsca", "1111eeee11111101", "if (FPSCR_PR)", " RAISE_EXCEPTION (SIGILL);", + "else if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", "else", " {", " SET_FR (n, fsca_s (FPUL, &sin));", @@ -494,6 +725,8 @@ op tab[] = { "", "", "fsrra ", "1111nnnn01111101", "if (FPSCR_PR)", " RAISE_EXCEPTION (SIGILL);", + "else if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", "else", " SET_FR (n, fsrra_s (FR (n)));", }, @@ -525,6 +758,8 @@ op tab[] = " RAISE_EXCEPTION (SIGILL);", "else", "{", + " if (saved_state.asregs.bfd_mach == bfd_mach_sh2a)", + " RAISE_EXCEPTION (SIGILL);", " /* FIXME not implemented. */", " printf (\"ftrv xmtrx, FV%d\\n\", v1);", "}", @@ -542,12 +777,14 @@ op tab[] = }, { "", "n", "jmp @", "0100nnnn00101011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_NIP (PT2H (R[n]));", "cycles += 2;", "Delay_Slot (PC + 2);", }, { "", "n", "jsr @", "0100nnnn00001011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "PR = PH2T (PC + 4);", "if (~doprofile)", " gotcall (PR, R[n]);", @@ -555,6 +792,20 @@ op tab[] = "cycles += 2;", "Delay_Slot (PC + 2);", }, + { "", "n", "jsr/n @", "0100nnnn01001011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "PR = PH2T (PC + 2);", + "if (~doprofile)", + " gotcall (PR, R[n]);", + "SET_NIP (PT2H (R[n]));", + }, + { "", "", "jsr/n @@(,TBR)", "10000011i8p4....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "PR = PH2T (PC + 2);", + "if (~doprofile)", + " gotcall (PR, i + TBR);", + "SET_NIP (PT2H (i + TBR));", + }, { "", "n", "ldc ,", "0100nnnnmmmm1110", "CREG (m) = R[n];", @@ -579,6 +830,12 @@ op tab[] = "else", " RAISE_EXCEPTION (SIGILL); /* user mode */", }, + { "", "n", "ldc ,TBR", "0100nnnn01001010", + "if (SR_MD)", /* FIXME? */ + " TBR = R[n]; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", + }, { "n", "n", "ldc.l @+,", "0100nnnnmmmm0111", "MA (1);", "CREG (m) = RLAT (R[n]);", @@ -673,6 +930,16 @@ op tab[] = { "n", "", "mov #,", "1110nnnni8*1....", "R[n] = SEXT (i);", }, + { "n", "", "movi20 #,", "0000nnnni8*10000", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "R[n] = ((i << 24) >> 12) | RIAT (nip);", + "SET_NIP (nip + 2); /* Consume 2 more bytes. */", + }, + { "n", "", "movi20s #,", "0000nnnni8*10001", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "R[n] = ((((i & 0xf0) << 24) >> 12) | RIAT (nip)) << 8;", + "SET_NIP (nip + 2); /* Consume 2 more bytes. */", + }, { "n", "m", "mov ,", "0110nnnnmmmm0011", "R[n] = R[m];", }, @@ -698,6 +965,12 @@ op tab[] = "R[m] += 1;", "L (n);", }, + { "0n", "n", "mov.b @-,R0", "0100nnnn11001011", + "MA (1);", + "R[n] -= 1;", + "R0 = RSBAT (R[n]);", + "L (0);", + }, { "", "mn", "mov.b ,@", "0010nnnnmmmm0000", "MA (1);", "WBAT (R[n], R[m]);", @@ -715,9 +988,16 @@ op tab[] = "WBAT (R[n] + R0, R[m]);", }, { "n", "nm", "mov.b ,@-", "0010nnnnmmmm0100", + /* Allow for the case where m == n. */ + "int t = R[m];", "MA (1);", "R[n] -= 1;", - "WBAT (R[n], R[m]);", + "WBAT (R[n], t);", + }, + { "n", "n0", "mov.b R0,@+", "0100nnnn10001011", + "MA (1);", + "WBAT (R[n], R0);", + "R[n] += 1;", }, { "n", "m", "mov.b @,", "0110nnnnmmmm0000", "MA (1);", @@ -731,6 +1011,7 @@ op tab[] = "L (0);", }, { "n", "", "mov.l @(,PC),", "1101nnnni8p4....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "MA (1);", "R[n] = RLAT ((PH2T (PC) & ~3) + 4 + i);", "L (n);", @@ -751,6 +1032,12 @@ op tab[] = "R[m] += 4;", "L (n);", }, + { "0n", "n", "mov.l @-,R0", "0100nnnn11101011", + "MA (1);", + "R[n] -= 4;", + "R0 = RLAT (R[n]);", + "L (0);", + }, { "n", "m", "mov.l @,", "0110nnnnmmmm0010", "MA (1);", "R[n] = RLAT (R[m]);", @@ -769,9 +1056,16 @@ op tab[] = "WLAT (R0 + R[n], R[m]);", }, { "n", "nm", "mov.l ,@-", "0010nnnnmmmm0110", + /* Allow for the case where m == n. */ + "int t = R[m];", "MA (1) ;", "R[n] -= 4;", - "WLAT (R[n], R[m]);", + "WLAT (R[n], t);", + }, + { "n", "n0", "mov.l R0,@+", "0100nnnn10101011", + "MA (1) ;", + "WLAT (R[n], R0);", + "R[n] += 4;", }, { "", "nm", "mov.l ,@", "0010nnnnmmmm0010", "MA (1);", @@ -784,6 +1078,7 @@ op tab[] = "L (0);", }, { "n", "", "mov.w @(,PC),", "1001nnnni8p2....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "MA (1);", "R[n] = RSWAT (PH2T (PC + 4 + i));", "L (n);", @@ -804,6 +1099,12 @@ op tab[] = "R[m] += 2;", "L (n);", }, + { "0n", "n", "mov.w @-,R0", "0100nnnn11011011", + "MA (1);", + "R[n] -= 2;", + "R0 = RSWAT (R[n]);", + "L (0);", + }, { "n", "m", "mov.w @,", "0110nnnnmmmm0001", "MA (1);", "R[n] = RSWAT (R[m]);", @@ -822,9 +1123,16 @@ op tab[] = "WWAT (R0 + R[n], R[m]);", }, { "n", "mn", "mov.w ,@-", "0010nnnnmmmm0101", + /* Allow for the case where m == n. */ + "int t = R[m];", "MA (1);", "R[n] -= 2;", - "WWAT (R[n], R[m]);", + "WWAT (R[n], t);", + }, + { "n", "0n", "mov.w R0,@+", "0100nnnn10011011", + "MA (1);", + "WWAT (R[n], R0);", + "R[n] += 2;", }, { "", "nm", "mov.w ,@", "0010nnnnmmmm0001", "MA (1);", @@ -832,6 +1140,7 @@ op tab[] = }, { "0", "", "mova @(,PC),R0", "11000111i8p4....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "R0 = ((i + 4 + PH2T (PC)) & ~0x3);", }, @@ -863,21 +1172,25 @@ op tab[] = { "n", "", "movt ", "0000nnnn00101001", "R[n] = T;", }, - + { "", "", "movrt ", "0000nnnn00111001", + "R[n] = (T == 0);", + }, { "0", "n", "movua.l @,R0", "0100nnnn10101001", "int regn = R[n];", + "int e = target_little_endian ? 3 : 0;", "MA (1);", - "R[0] = (RBAT (regn) << 24) + (RBAT (regn + 1) << 16) + ", - " (RBAT (regn + 2) << 8) + RBAT (regn + 3);", - "L (n);", + "R[0] = (RBAT (regn + (0^e)) << 24) + (RBAT (regn + (1^e)) << 16) + ", + " (RBAT (regn + (2^e)) << 8) + RBAT (regn + (3^e));", + "L (0);", }, { "0n", "n", "movua.l @+,R0", "0100nnnn11101001", "int regn = R[n];", + "int e = target_little_endian ? 3 : 0;", "MA (1);", - "R[0] = (RBAT (regn) << 24) + (RBAT (regn + 1) << 16) + ", - " (RBAT (regn + 2) << 8) + RBAT (regn + 3);", + "R[0] = (RBAT (regn + (0^e)) << 24) + (RBAT (regn + (1^e)) << 16) + ", + " (RBAT (regn + (2^e)) << 8) + RBAT (regn + (3^e));", "R[n] += 4;", - "L (n);", + "L (0);", }, { "", "mn", "mul.l ,", "0000nnnnmmmm0111", "MACL = ((int) R[n]) * ((int) R[m]);", @@ -926,17 +1239,17 @@ op tab[] = }, { "", "n", "ocbi @", "0000nnnn10010011", - "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop. */", + "(void) RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop. */", "/* FIXME: Cache not implemented */", }, { "", "n", "ocbp @", "0000nnnn10100011", - "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop. */", + "(void) RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop. */", "/* FIXME: Cache not implemented */", }, { "", "n", "ocbwb @", "0000nnnn10110011", - "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop. */", + "(void) RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop. */", "/* FIXME: Cache not implemented */", }, @@ -1002,6 +1315,7 @@ op tab[] = "R[15] += 4;", "Delay_Slot (PC + 2);", #else + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_SR (SSR);", "SET_NIP (PT2H (SPC));", "cycles += 2;", @@ -1010,21 +1324,32 @@ op tab[] = }, { "", "", "rts", "0000000000001011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "SET_NIP (PT2H (PR));", "cycles += 2;", "Delay_Slot (PC + 2);", }, + { "", "", "rts/n", "0000000001101011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "SET_NIP (PT2H (PR));", + }, + { "0", "n", "rtv/n ", "0000nnnn01111011", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", + "R0 = R[n];", + "L (0);", + "SET_NIP (PT2H (PR));", + }, /* sh4a */ { "", "", "setdmx", "0000000010011000", - "saved_state.asregs.cregs.named.sr |= SR_MASK_DMX;" - "saved_state.asregs.cregs.named.sr &= ~SR_MASK_DMY;" + "saved_state.asregs.sr |= SR_MASK_DMX;" + "saved_state.asregs.sr &= ~SR_MASK_DMY;" }, /* sh4a */ { "", "", "setdmy", "0000000011001000", - "saved_state.asregs.cregs.named.sr |= SR_MASK_DMY;" - "saved_state.asregs.cregs.named.sr &= ~SR_MASK_DMX;" + "saved_state.asregs.sr |= SR_MASK_DMY;" + "saved_state.asregs.sr &= ~SR_MASK_DMX;" }, /* sh-dsp */ @@ -1054,7 +1379,7 @@ op tab[] = }, { "n", "mn", "shad ,", "0100nnnnmmmm1100", - "R[n] = (R[m] < 0) ? (R[n] >> ((-R[m])&0x1f)) : (R[n] << (R[m] & 0x1f));", + "R[n] = (R[m] < 0) ? (R[m]&0x1f ? R[n] >> ((-R[m])&0x1f) : R[n] >> 31) : (R[n] << (R[m] & 0x1f));", }, { "n", "n", "shal ", "0100nnnn00100000", @@ -1068,7 +1393,7 @@ op tab[] = }, { "n", "mn", "shld ,", "0100nnnnmmmm1101", - "R[n] = (R[m] < 0) ? (UR[n] >> ((-R[m])&0x1f)): (R[n] << (R[m] & 0x1f));", + "R[n] = (R[m] < 0) ? (R[m]&0x1f ? UR[n] >> ((-R[m])&0x1f) : 0): (R[n] << (R[m] & 0x1f));", }, { "n", "n", "shll ", "0100nnnn00000000", @@ -1102,7 +1427,7 @@ op tab[] = }, { "", "", "sleep", "0000000000011011", - "nip += trap (0xc3, &R0, PC, memory, maskl, maskw, endianw);", + "nip += trap (sd, 0xc3, &R0, PC, memory, maskl, maskw, endianw);", }, { "n", "", "stc ,", "0000nnnnmmmm0010", @@ -1121,6 +1446,12 @@ op tab[] = "else", " RAISE_EXCEPTION (SIGILL); /* user mode */", }, + { "n", "", "stc TBR,", "0000nnnn01001010", + "if (SR_MD)", /* FIXME? */ + " R[n] = TBR; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", + }, { "n", "n", "stc.l ,@-", "0100nnnnmmmm0011", "MA (1);", "R[n] -= 4;", @@ -1192,8 +1523,9 @@ op tab[] = { "0", "", "trapa #", "11000011i8*1....", "long imm = 0xff & i;", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (i < 20 || i == 33 || i == 34 || i == 0xc3)", - " nip += trap (i, &R0, PC, memory, maskl, maskw, endianw);", + " nip += trap (sd, i, &R0, PC, memory, maskl, maskw, endianw);", #if 0 "else {", /* SH-[12] */ @@ -1515,8 +1847,9 @@ op movsxy_tab[] = "/* nop */", }, { "", "", "ppi", "1111100000000000", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "ppi_insn (RIAT (nip));", - "nip += 2;", + "SET_NIP (nip + 2);", "iword &= 0xf7ff; goto top;", }, #endif @@ -1530,7 +1863,7 @@ op ppi_tab[] = "if (i <= 16)", " res = Sz << i;", "else if (i >= 128 - 16)", - " res = (unsigned) Sz >> 128 - i; /* no sign extension */", + " res = (unsigned) Sz >> (128 - i); /* no sign extension */", "else", " {", " RAISE_EXCEPTION (SIGILL);", @@ -1554,7 +1887,7 @@ op ppi_tab[] = " else", " {", " res = Sz << i;", - " res_grd = Sz_grd << i | (unsigned) Sz >> 32 - i;", + " res_grd = Sz_grd << i | (unsigned) Sz >> (32 - i);", " }", " res_grd = SEXT (res_grd);", " carry = res_grd & 1;", @@ -1569,7 +1902,7 @@ op ppi_tab[] = " }", " else", " {", - " res = Sz >> i | Sz_grd << 32 - i;", + " res = Sz >> i | Sz_grd << (32 - i);", " res_grd = Sz_grd >> i;", " }", " carry = Sz >> (i - 1) & 1;", @@ -1640,7 +1973,7 @@ op ppi_tab[] = "ADD_SUB_GE;", "DSR &= ~0xf1;\n", "if (res || res_grd)\n", - " DSR |= greater_equal | res_grd >> 2 & DSR_MASK_N | overflow;\n", + " DSR |= greater_equal | (res_grd >> 2 & DSR_MASK_N) | overflow;\n", "else\n", " DSR |= DSR_MASK_Z | overflow;\n", "DSR |= carry;\n", @@ -1659,7 +1992,7 @@ op ppi_tab[] = "ADD_SUB_GE;", "DSR &= ~0xf1;\n", "if (res || res_grd)\n", - " DSR |= greater_equal | res_grd >> 2 & DSR_MASK_N | overflow;\n", + " DSR |= greater_equal | (res_grd >> 2 & DSR_MASK_N) | overflow;\n", "else\n", " DSR |= DSR_MASK_Z | overflow;\n", "DSR |= carry;\n", @@ -1815,7 +2148,7 @@ op ppi_tab[] = "if (Sy <= 16)", " res = Sx << Sy;", "else if (Sy >= 128 - 16)", - " res = (unsigned) Sx >> 128 - Sy; /* no sign extension */", + " res = (unsigned) Sx >> (128 - Sy); /* no sign extension */", "else", " {", " RAISE_EXCEPTION (SIGILL);", @@ -1838,7 +2171,7 @@ op ppi_tab[] = " else", " {", " res = Sx << Sy;", - " res_grd = Sx_grd << Sy | (unsigned) Sx >> 32 - Sy;", + " res_grd = Sx_grd << Sy | (unsigned) Sx >> (32 - Sy);", " }", " res_grd = SEXT (res_grd);", " carry = res_grd & 1;", @@ -1853,7 +2186,7 @@ op ppi_tab[] = " }", " else", " {", - " res = Sx >> Sy | Sx_grd << 32 - Sy;", + " res = Sx >> Sy | Sx_grd << (32 - Sy);", " res_grd = Sx_grd >> Sy;", " }", " carry = Sx >> (Sy - 1) & 1;", @@ -1933,7 +2266,7 @@ op ppi_tab[] = "int Sx_grd = GET_DSP_GRD (x);", "", "res = Sx - 0x10000;", - "carry = res > Sx;", + "carry = Sx < (INT_MIN + 0x10000);", "res_grd = Sx_grd - carry;", "COMPUTE_OVERFLOW;", "ADD_SUB_GE;", @@ -1944,7 +2277,7 @@ op ppi_tab[] = "int Sx_grd = GET_DSP_GRD (x);", "", "res = Sx + 0x10000;", - "carry = res < Sx;", + "carry = Sx > (INT_MAX - 0x10000);", "res_grd = Sx_grd + carry;", "COMPUTE_OVERFLOW;", "ADD_SUB_GE;", @@ -1955,7 +2288,7 @@ op ppi_tab[] = "int Sy_grd = SIGN32 (Sy);", "", "res = Sy - 0x10000;", - "carry = res > Sy;", + "carry = Sy < (INT_MIN + 0x10000);", "res_grd = Sy_grd - carry;", "COMPUTE_OVERFLOW;", "ADD_SUB_GE;", @@ -1966,7 +2299,7 @@ op ppi_tab[] = "int Sy_grd = SIGN32 (Sy);", "", "res = Sy + 0x10000;", - "carry = res < Sy;", + "carry = Sy > (INT_MAX - 0x10000);", "res_grd = Sy_grd + carry;", "COMPUTE_OVERFLOW;", "ADD_SUB_GE;", @@ -2030,7 +2363,7 @@ op ppi_tab[] = }, { "","", "(if cc) pdmsb Sy,Dz", "101111cc..yyzzzz", "unsigned Sy = DSP_R (y);", - "int i;", + "int i = 16;", "", "if (Sy < 0)", " Sy = ~Sy;", @@ -2134,7 +2467,8 @@ op ppi_tab[] = }; /* Tables of things to put into enums for sh-opc.h */ -static char *nibble_type_list[] = +static +const char * const nibble_type_list[] = { "HEX_0", "HEX_1", @@ -2169,7 +2503,7 @@ static char *nibble_type_list[] = 0 }; static -char *arg_type_list[] = +const char * const arg_type_list[] = { "A_END", "A_BDISP12", @@ -2202,27 +2536,11 @@ char *arg_type_list[] = 0, }; -static void -make_enum_list (name, s) - char *name; - char **s; -{ - int i = 1; - printf ("typedef enum {\n"); - while (*s) - { - printf ("\t%s,\n", *s); - s++; - i++; - } - printf ("} %s;\n", name); -} - static int -qfunc (a, b) - op *a; - op *b; +qfunc (const void *va, const void *vb) { + const op *a = va; + const op *b = vb; char bufa[9]; char bufb[9]; int diff; @@ -2241,7 +2559,7 @@ qfunc (a, b) } static void -sorttab () +sorttab (void) { op *p = tab; int len = 0; @@ -2255,7 +2573,7 @@ sorttab () } static void -gengastab () +gengastab (void) { op *p; sorttab (); @@ -2265,19 +2583,68 @@ gengastab () } } -static unsigned char table[1 << 16]; +static unsigned short table[1 << 16]; + +static int warn_conflicts = 0; + +static void +conflict_warn (int val, int i) +{ + int ix, key; + int j = table[val]; + + fprintf (stderr, "Warning: opcode table conflict: 0x%04x (idx %d && %d)\n", + val, i, table[val]); + + for (ix = ARRAY_SIZE (tab); ix >= 0; ix--) + if (tab[ix].index == i || tab[ix].index == j) + { + key = ((tab[ix].code[0] - '0') << 3) + + ((tab[ix].code[1] - '0') << 2) + + ((tab[ix].code[2] - '0') << 1) + + ((tab[ix].code[3] - '0')); + + if (val >> 12 == key) + fprintf (stderr, " %s -- %s\n", tab[ix].code, tab[ix].name); + } + + for (ix = ARRAY_SIZE (movsxy_tab); ix >= 0; ix--) + if (movsxy_tab[ix].index == i || movsxy_tab[ix].index == j) + { + key = ((movsxy_tab[ix].code[0] - '0') << 3) + + ((movsxy_tab[ix].code[1] - '0') << 2) + + ((movsxy_tab[ix].code[2] - '0') << 1) + + ((movsxy_tab[ix].code[3] - '0')); + + if (val >> 12 == key) + fprintf (stderr, " %s -- %s\n", + movsxy_tab[ix].code, movsxy_tab[ix].name); + } + + for (ix = ARRAY_SIZE (ppi_tab); ix >= 0; ix--) + if (ppi_tab[ix].index == i || ppi_tab[ix].index == j) + { + key = ((ppi_tab[ix].code[0] - '0') << 3) + + ((ppi_tab[ix].code[1] - '0') << 2) + + ((ppi_tab[ix].code[2] - '0') << 1) + + ((ppi_tab[ix].code[3] - '0')); + + if (val >> 12 == key) + fprintf (stderr, " %s -- %s\n", + ppi_tab[ix].code, ppi_tab[ix].name); + } +} /* Take an opcode, expand all varying fields in it out and fill all the right entries in 'table' with the opcode index. */ static void -expand_opcode (val, i, s) - int val; - int i; - char *s; +expand_opcode (int val, int i, const char *s) { if (*s == 0) { + if (warn_conflicts && table[val] != 0) + conflict_warn (val, i); table[val] = i; } else @@ -2397,17 +2764,14 @@ expand_opcode (val, i, s) statement entry. */ static void -dumptable (name, size, start) - char *name; - int size; - int start; +dumptable (const char *name, int size, int start) { int lump = 256; int online = 16; int i = start; - printf ("unsigned char %s[%d]={\n", name, size); + printf ("unsigned short %s[%d]={\n", name, size); while (i < start + size) { int j = 0; @@ -2435,8 +2799,7 @@ dumptable (name, size, start) static void -filltable (p) - op *p; +filltable (op *p) { static int index = 1; @@ -2453,7 +2816,7 @@ filltable (p) processing insns (ppi) for code 0xf800 (ppi nopx nopy). Copy the latter tag to represent all combinations of ppi with ddt. */ static void -expand_ppi_movxy () +expand_ppi_movxy (void) { int i; @@ -2463,8 +2826,7 @@ expand_ppi_movxy () } static void -gensim_caselist (p) - op *p; +gensim_caselist (op *p) { for (; p->name; p++) { @@ -2472,8 +2834,7 @@ gensim_caselist (p) int sextbit = -1; int needm = 0; int needn = 0; - - char *s = p->code; + const char *s = p->code; printf (" /* %s %s */\n", p->name, p->code); printf (" case %d: \n", p->index); @@ -2599,6 +2960,12 @@ gensim_caselist (p) switch (s[1]) { + default: + fprintf (stderr, + "gensim_caselist: Unknown char '%c' in %s\n", + s[1], s); + exit (1); + break; case '4': printf ("f"); break; @@ -2607,7 +2974,6 @@ gensim_caselist (p) break; case '1': sextbit = 12; - printf ("fff"); break; } @@ -2615,6 +2981,14 @@ gensim_caselist (p) switch (s[3]) { + default: + fprintf (stderr, + "gensim_caselist: Unknown char '%c' in %s\n", + s[3], s); + exit (1); + break; + case '.': /* eg. "i12." */ + break; case '1': break; case '2': @@ -2643,9 +3017,28 @@ gensim_caselist (p) { /* Do the refs. */ - char *r; + const char *r; for (r = p->refs; *r; r++) { + if (*r == 'f') printf (" CREF (15);\n"); + if (*r == '-') + { + printf (" {\n"); + printf (" int i = n;\n"); + printf (" do {\n"); + printf (" CREF (i);\n"); + printf (" } while (i-- > 0);\n"); + printf (" }\n"); + } + if (*r == '+') + { + printf (" {\n"); + printf (" int i = n;\n"); + printf (" do {\n"); + printf (" CREF (i);\n"); + printf (" } while (i++ < 14);\n"); + printf (" }\n"); + } if (*r == '0') printf (" CREF (0);\n"); if (*r == '8') printf (" CREF (8);\n"); if (*r == '9') printf (" CREF (9);\n"); @@ -2666,12 +3059,31 @@ gensim_caselist (p) { /* Do the defs. */ - char *r; + const char *r; for (r = p->defs; *r; r++) { - if (*r == '0') printf(" CDEF (0);\n"); - if (*r == 'n') printf(" CDEF (n);\n"); - if (*r == 'm') printf(" CDEF (m);\n"); + if (*r == 'f') printf (" CDEF (15);\n"); + if (*r == '-') + { + printf (" {\n"); + printf (" int i = n;\n"); + printf (" do {\n"); + printf (" CDEF (i);\n"); + printf (" } while (i-- > 0);\n"); + printf (" }\n"); + } + if (*r == '+') + { + printf (" {\n"); + printf (" int i = n;\n"); + printf (" do {\n"); + printf (" CDEF (i);\n"); + printf (" } while (i++ < 14);\n"); + printf (" }\n"); + } + if (*r == '0') printf (" CDEF (0);\n"); + if (*r == 'n') printf (" CDEF (n);\n"); + if (*r == 'm') printf (" CDEF (m);\n"); } } @@ -2681,7 +3093,7 @@ gensim_caselist (p) } static void -gensim () +gensim (void) { printf ("{\n"); printf ("/* REG_xy = [r4, r5, r0, r1]. */\n"); @@ -2710,19 +3122,17 @@ gensim () } static void -gendefines () +gendefines (void) { op *p; filltable (tab); for (p = tab; p->name; p++) { - char *s = p->name; + const char *s = p->name; printf ("#define OPC_"); while (*s) { - if (isupper (*s)) - *s = tolower (*s); if (isalpha (*s)) - printf ("%c", *s); + printf ("%c", tolower (*s)); if (*s == ' ') printf ("_"); if (*s == '@') @@ -2742,10 +3152,7 @@ static int ppi_index; NOTE: tail recursion optimization removed for simplicity. */ static void -expand_ppi_code (val, i, s) - int val; - int i; - char *s; +expand_ppi_code (int val, int i, const char *s) { int j; @@ -2757,6 +3164,9 @@ expand_ppi_code (val, i, s) break; case 'g': case 'z': + if (warn_conflicts && table[val] != 0) + conflict_warn (val, i); + /* The last four bits are disregarded for the switch table. */ table[val] = i; return; @@ -2787,7 +3197,7 @@ expand_ppi_code (val, i, s) } static void -ppi_filltable () +ppi_filltable (void) { op *p; ppi_index = 1; @@ -2800,7 +3210,7 @@ ppi_filltable () } static void -ppi_gensim () +ppi_gensim (void) { op *p = ppi_tab; @@ -2831,21 +3241,20 @@ ppi_gensim () printf (" (greater_equal = ~(overflow << 3 & res_grd) & DSR_MASK_G)\n"); printf ("\n"); printf ("static void\n"); - printf ("ppi_insn (iword)\n"); - printf (" int iword;\n"); + printf ("ppi_insn (int iword)\n"); printf ("{\n"); printf (" /* 'ee' = [x0, x1, y0, a1] */\n"); - printf (" static char e_tab[] = { 8, 9, 10, 5};\n"); + printf (" static char const e_tab[] = { 8, 9, 10, 5};\n"); printf (" /* 'ff' = [y0, y1, x0, a1] */\n"); - printf (" static char f_tab[] = {10, 11, 8, 5};\n"); + printf (" static char const f_tab[] = {10, 11, 8, 5};\n"); printf (" /* 'xx' = [x0, x1, a0, a1] */\n"); - printf (" static char x_tab[] = { 8, 9, 7, 5};\n"); + printf (" static char const x_tab[] = { 8, 9, 7, 5};\n"); printf (" /* 'yy' = [y0, y1, m0, m1] */\n"); - printf (" static char y_tab[] = {10, 11, 12, 14};\n"); + printf (" static char const y_tab[] = {10, 11, 12, 14};\n"); printf (" /* 'gg' = [m0, m1, a0, a1] */\n"); - printf (" static char g_tab[] = {12, 14, 7, 5};\n"); + printf (" static char const g_tab[] = {12, 14, 7, 5};\n"); printf (" /* 'uu' = [x0, y0, a0, a1] */\n"); - printf (" static char u_tab[] = { 8, 10, 7, 5};\n"); + printf (" static char const u_tab[] = { 8, 10, 7, 5};\n"); printf ("\n"); printf (" int z;\n"); printf (" int res, res_grd;\n"); @@ -2858,8 +3267,7 @@ ppi_gensim () int shift, j; int cond = 0; int havedecl = 0; - - char *s = p->code; + const char *s = p->code; printf (" /* %s %s */\n", p->name, p->code); printf (" case %d: \n", p->index); @@ -2939,7 +3347,7 @@ ppi_gensim () printf (" }\n"); printf (" DSR &= ~0xf1;\n"); printf (" if (res || res_grd)\n"); - printf (" DSR |= greater_equal | res_grd >> 2 & DSR_MASK_N | overflow;\n"); + printf (" DSR |= greater_equal | (res_grd >> 2 & DSR_MASK_N) | overflow;\n"); printf (" else\n"); printf (" DSR |= DSR_MASK_Z | overflow;\n"); printf (" assign_dc:\n"); @@ -2951,11 +3359,11 @@ ppi_gensim () printf (" DSR |= res_grd >> 7 & 1;\n"); printf (" case 2: /* Zero Value Mode */\n"); printf (" DSR |= DSR >> 6 & 1;\n"); - printf (" case 3: /* Overflow mode\n"); + printf (" case 3: /* Overflow mode */\n"); printf (" DSR |= overflow >> 4;\n"); printf (" case 4: /* Signed Greater Than Mode */\n"); printf (" DSR |= DSR >> 7 & 1;\n"); - printf (" case 4: /* Signed Greater Than Or Equal Mode */\n"); + printf (" case 5: /* Signed Greater Than Or Equal Mode */\n"); printf (" DSR |= greater_equal >> 7;\n"); printf (" }\n"); printf (" assign_z:\n"); @@ -2970,9 +3378,7 @@ ppi_gensim () } int -main (ac, av) - int ac; - char **av; +main (int ac, char *av[]) { /* Verify the table before anything else. */ { @@ -2982,7 +3388,7 @@ main (ac, av) /* Check that the code field contains 16 bits. */ if (strlen (p->code) != 16) { - fprintf (stderr, "Code `%s' length wrong (%d) for `%s'\n", + fprintf (stderr, "Code `%s' length wrong (%zu) for `%s'\n", p->code, strlen (p->code), p->name); abort (); } @@ -2992,6 +3398,10 @@ main (ac, av) /* Now generate the requested data. */ if (ac > 1) { + if (ac > 2 && strcmp (av[2], "-w") == 0) + { + warn_conflicts = 1; + } if (strcmp (av[1], "-t") == 0) { gengastab ();