X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=sim%2Fsh%2Fgencode.c;h=77a83d637685066f80a9fb23e8cd80e05e5152b7;hb=f2e1c129f8f0985ec80e6cf775cf3e4afbced6fa;hp=e7b6b4dc548f063b489d6a07c59ed4f4b9600834;hpb=b939d772c1052b510a03d579a6250d23e5b39212;p=deliverable%2Fbinutils-gdb.git diff --git a/sim/sh/gencode.c b/sim/sh/gencode.c index e7b6b4dc54..77a83d6376 100644 --- a/sim/sh/gencode.c +++ b/sim/sh/gencode.c @@ -1,9 +1,10 @@ -/* Simulator/Opcode generator for the Hitachi Super-H architecture. +/* Simulator/Opcode generator for the Renesas + (formerly Hitachi) / SuperH Inc. Super-H architecture. Written by Steve Chamberlain of Cygnus Support. sac@cygnus.com - This file is part of SH sim + This file is part of SH sim. THIS SOFTWARE IS NOT COPYRIGHTED @@ -19,7 +20,7 @@ */ /* This program generates the opcode table for the assembler and - the simulator code + the simulator code. -t prints a pretty table for the assembler manual -s generates the simulator code jump table @@ -29,26 +30,31 @@ */ +#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....", - "R[n] += SEXT(i);", + "R[n] += SEXT (i);", "if (i == 0) {", " UNDEF(n); /* see #ifdef PARANOID */", " break;", @@ -71,7 +77,7 @@ op tab[] = "R[n] = ult;", }, - { "0", "", "and #,R0", "11001001i8*1....", + { "0", "0", "and #,R0", "11001001i8*1....", "R0 &= i;", }, { "n", "nm", "and ,", "0010nnnnmmmm1001", @@ -83,13 +89,15 @@ op tab[] = }, { "", "", "bf ", "10001011i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (!T) {", - " SET_NIP (PC + 4 + (SEXT(i) * 2));", + " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", "}", }, { "", "", "bf.s ", "10001111i8p1....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "if (!T) {", " SET_NIP (PC + 4 + (SEXT (i) * 2));", " cycles += 2;", @@ -97,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;", @@ -117,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;", @@ -124,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;", @@ -151,6 +352,11 @@ op tab[] = "SET_SR_T (0);", }, + /* sh4a */ + { "", "", "clrdmxy", "0000000010001000", + "saved_state.asregs.cregs.named.sr &= ~(SR_MASK_DMX | SR_MASK_DMY);" + }, + { "", "0", "cmp/eq #,R0", "10001000i8*1....", "SET_SR_T (R0 == SEXT (i));", }, @@ -195,16 +401,16 @@ op tab[] = "SET_SR_T (0);", }, - { "", "nm", "div1 ,", "0011nnnnmmmm0100", /* ? MVS */ - "div1 (R, m, n/*, T*/);", + { "n", "nm", "div1 ,", "0011nnnnmmmm0100", + "div1 (&R0, m, n/*, T*/);", }, { "", "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", @@ -228,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 */ @@ -257,7 +469,7 @@ op tab[] = " int i;", " float f;", " } u;", - " u.f = DR(n);", + " u.f = DR (n);", " FPUL = u.i;", "}", }, @@ -274,33 +486,44 @@ op tab[] = " float f;", " } u;", " u.i = FPUL;", - " SET_DR(n, u.f);", + " SET_DR (n, u.f);", "}", }, /* sh2e */ { "", "", "fdiv ,", "1111nnnnmmmm0011", "FP_OP (n, /, m);", - "/* FIXME: check for DP and (n & 1) == 0? */", + "/* FIXME: check for DP and (n & 1) == 0? */", }, /* sh4 */ - { "", "", "fipr ,", "1111nnmm11101101", - "/* FIXME: not implemented */", - "RAISE_EXCEPTION (SIGILL);", - "/* FIXME: check for DP and (n & 1) == 0? */", + { "", "", "fipr ,", "1111vvVV11101101", + "if (FPSCR_PR)", + " RAISE_EXCEPTION (SIGILL);", + "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);", + " fsum += FR (v1+2) * FR (v2+2);", + " fsum += FR (v1+3) * FR (v2+3);", + " SET_FR (v1+3, fsum);", + "}", }, /* sh2e */ { "", "", "fldi0 ", "1111nnnn10001101", - "SET_FR (n, (float)0.0);", - "/* FIXME: check for DP and (n & 1) == 0? */", + "SET_FR (n, (float) 0.0);", + "/* FIXME: check for DP and (n & 1) == 0? */", }, /* sh2e */ { "", "", "fldi1 ", "1111nnnn10011101", - "SET_FR (n, (float)1.0);", - "/* FIXME: check for DP and (n & 1) == 0? */", + "SET_FR (n, (float) 1.0);", + "/* FIXME: check for DP and (n & 1) == 0? */", }, /* sh2e */ @@ -310,7 +533,7 @@ op tab[] = " int i;", " float f;", " } u;", - " u.f = FR(n);", + " u.f = FR (n);", " FPUL = u.i;", }, @@ -318,16 +541,16 @@ op tab[] = { "", "", "float FPUL,", "1111nnnn00101101", /* sh4 */ "if (FPSCR_PR)", - " SET_DR (n, (double)FPUL);", + " SET_DR (n, (double) FPUL);", "else", "{", - " SET_FR (n, (float)FPUL);", + " SET_FR (n, (float) FPUL);", "}", }, /* sh2e */ { "", "", "fmac ,,", "1111nnnnmmmm1110", - "SET_FR (n, FR(m) * FR(0) + FR(n));", + "SET_FR (n, FR (m) * FR (0) + FR (n));", "/* FIXME: check for DP and (n & 1) == 0? */", }, @@ -355,7 +578,7 @@ op tab[] = "else", "{", " MA (1);", - " WLAT (R[n], FI(m));", + " WLAT (R[n], FI (m));", "}", }, /* sh2e */ @@ -368,11 +591,23 @@ op tab[] = "else", "{", " MA (1);", - " SET_FI(n, RLAT(R[m]));", + " 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", "fmov.s @+,", "1111nnnnmmmm1001", + { "m", "m", "fmov.s @+,", "1111nnnnmmmm1001", /* sh4 */ "if (FPSCR_SZ) {", " MA (2);", @@ -398,7 +633,7 @@ op tab[] = "{", " MA (1);", " R[n] -= 4;", - " WLAT (R[n], FI(m));", + " WLAT (R[n], FI (m));", "}", }, /* sh2e */ @@ -411,7 +646,7 @@ op tab[] = "else", "{", " MA (1);", - " SET_FI(n, RLAT(R[0] + R[m]));", + " SET_FI (n, RLAT (R[0] + R[m]));", "}", }, /* sh2e */ @@ -424,56 +659,110 @@ op tab[] = "else", "{", " MA (1);", - " WLAT((R[0]+R[n]), FI(m));", + " WLAT ((R[0]+R[n]), FI (m));", "}", }, - /* sh4: See fmov instructions above for move to/from extended fp registers */ + /* sh4: + See fmov instructions above for move to/from extended fp registers. */ /* sh2e */ { "", "", "fmul ,", "1111nnnnmmmm0010", - "FP_OP(n, *, m);", + "FP_OP (n, *, m);", }, /* 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 */ + { "", "", "fpchg", "1111011111111101", + "SET_FPSCR (GET_FPSCR () ^ FPSCR_MASK_PR);", }, /* sh4 */ { "", "", "frchg", "1111101111111101", - "SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_FR);", + "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);", + }, + + /* sh4 */ + { "", "", "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));", + " SET_FR (n+1, fsca_s (FPUL, &cos));", + " }", }, /* sh4 */ { "", "", "fschg", "1111001111111101", - "SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_SZ);", + "SET_FPSCR (GET_FPSCR () ^ FPSCR_MASK_SZ);", }, /* sh3e */ { "", "", "fsqrt ", "1111nnnn01101101", - "FP_UNARY(n, sqrt);", + "FP_UNARY (n, sqrt);", + }, + + /* sh4 */ + { "", "", "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)));", }, /* sh2e */ { "", "", "fsub ,", "1111nnnnmmmm0001", - "FP_OP(n, -, m);", + "FP_OP (n, -, m);", }, /* sh2e */ { "", "", "ftrc , FPUL", "1111nnnn00111101", /* sh4 */ "if (FPSCR_PR) {", - " if (DR(n) != DR(n)) /* NaN */", + " if (DR (n) != DR (n)) /* NaN */", " FPUL = 0x80000000;", " else", - " FPUL = (int)DR(n);", + " FPUL = (int) DR (n);", "}", "else", - "if (FR(n) != FR(n)) /* NaN */", + "if (FR (n) != FR (n)) /* NaN */", " FPUL = 0x80000000;", "else", - " FPUL = (int)FR(n);", + " FPUL = (int) FR (n);", + }, + + /* sh4 */ + { "", "", "ftrv ", "1111vv0111111101", + "if (FPSCR_PR)", + " 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);", + "}", }, /* sh2e */ @@ -488,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]);", @@ -501,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];", @@ -513,12 +818,24 @@ op tab[] = { "", "n", "ldc ,MOD", "0100nnnn01011110", "SET_MOD (R[n]);", }, -#if 0 { "", "n", "ldc ,DBR", "0100nnnn11111010", - "DBR = R[n];", - "/* FIXME: user mode */", + "if (SR_MD)", + " DBR = R[n]; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", + }, + { "", "n", "ldc ,SGR", "0100nnnn00111010", + "if (SR_MD)", + " SGR = R[n]; /* priv mode */", + "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 */", }, -#endif { "n", "n", "ldc.l @+,", "0100nnnnmmmm0111", "MA (1);", "CREG (m) = RLAT (R[n]);", @@ -536,14 +853,26 @@ op tab[] = "SET_MOD (RLAT (R[n]));", "R[n] += 4;", }, -#if 0 { "n", "n", "ldc.l @+,DBR", "0100nnnn11110110", - "MA (1);", - "DBR = RLAT (R[n]);", - "R[n] += 4;", - "/* FIXME: user mode */", + "if (SR_MD)", + "{ /* priv mode */", + " MA (1);", + " DBR = RLAT (R[n]);", + " R[n] += 4;", + "}", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", + }, + { "n", "n", "ldc.l @+,SGR", "0100nnnn00110110", + "if (SR_MD)", + "{ /* priv mode */", + " MA (1);", + " SGR = RLAT (R[n]);", + " R[n] += 4;", + "}", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, -#endif /* sh-dsp */ { "", "", "ldre @(,PC)", "10001110i8p1....", @@ -553,40 +882,63 @@ op tab[] = "RS = SEXT (i) * 2 + 4 + PH2T (PC);", }, + /* sh4a */ + { "", "n", "ldrc ", "0100nnnn00110100", + "SET_RC (R[n]);", + "loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);", + "CHECK_INSN_PTR (insn_ptr);", + "RE |= 1;", + }, + { "", "", "ldrc #", "10001010i8*1....", + "SET_RC (i);", + "loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);", + "CHECK_INSN_PTR (insn_ptr);", + "RE |= 1;", + }, + { "", "n", "lds ,", "0100nnnnssss1010", "SREG (m) = R[n];", }, { "n", "n", "lds.l @+,", "0100nnnnssss0110", "MA (1);", - "SREG (m) = RLAT(R[n]);", + "SREG (m) = RLAT (R[n]);", "R[n] += 4;", }, /* sh2e / sh-dsp (lds ,DSR) */ { "", "n", "lds ,FPSCR", "0100nnnn01101010", - "SET_FPSCR(R[n]);", + "SET_FPSCR (R[n]);", }, /* sh2e / sh-dsp (lds.l @+,DSR) */ { "n", "n", "lds.l @+,FPSCR", "0100nnnn01100110", "MA (1);", - "SET_FPSCR (RLAT(R[n]));", + "SET_FPSCR (RLAT (R[n]));", "R[n] += 4;", }, { "", "", "ldtlb", "0000000000111000", - "/* FIXME: XXX*/ abort();", + "/* We don't implement cache or tlb, so this is a noop. */", }, { "nm", "nm", "mac.l @+,@+", "0000nnnnmmmm1111", - "trap (255, R0, PC, memory, maskl, maskw, endianw);", - "/* FIXME: mac.l support */", + "macl (&R0, memory, n, m);", }, { "nm", "nm", "mac.w @+,@+", "0100nnnnmmmm1111", - "macw(R0,memory,n,m,endianw);", + "macw (&R0, memory, n, m, endianw);", }, { "n", "", "mov #,", "1110nnnni8*1....", - "R[n] = SEXT(i);", + "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];", @@ -613,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]);", @@ -630,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);", @@ -646,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);", @@ -666,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]);", @@ -684,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);", @@ -699,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);", @@ -719,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]);", @@ -737,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);", @@ -747,6 +1140,7 @@ op tab[] = }, { "0", "", "mova @(,PC),R0", "11000111i8p4....", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "R0 = ((i + 4 + PH2T (PC)) & ~0x3);", }, @@ -756,14 +1150,53 @@ op tab[] = "WLAT (R[n], R[0]);", }, + { "", "n0", "movco.l R0, @", "0000nnnn01110011", + "/* LDST -> T */", + "SET_SR_T (LDST);", + "/* if (T) R0 -> (Rn) */", + "if (T)", + " WLAT (R[n], R[0]);", + "/* 0 -> LDST */", + "SET_LDST (0);", + }, + + { "0", "n", "movli.l @, R0", "0000nnnn01100011", + "/* 1 -> LDST */", + "SET_LDST (1);", + "/* (Rn) -> R0 */", + "R[0] = RLAT (R[n]);", + "/* if (interrupt/exception) 0 -> LDST */", + "/* (we don't simulate asynchronous interrupts/exceptions) */", + }, + { "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 + (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 + (0^e)) << 24) + (RBAT (regn + (1^e)) << 16) + ", + " (RBAT (regn + (2^e)) << 8) + RBAT (regn + (3^e));", + "R[n] += 4;", + "L (0);", + }, { "", "mn", "mul.l ,", "0000nnnnmmmm0111", - "MACL = ((int)R[n]) * ((int)R[m]);", + "MACL = ((int) R[n]) * ((int) R[m]);", }, -#if 0 +#if 0 /* FIXME: The above cast to int is not really portable. + It should be replaced by a SEXT32 macro. */ { "", "nm", "mul.l ,", "0000nnnnmmmm0111", "MACL = R[n] * R[m];", }, @@ -771,13 +1204,13 @@ op tab[] = /* muls.w - see muls */ { "", "mn", "muls ,", "0010nnnnmmmm1111", - "MACL = ((int)(short)R[n]) * ((int)(short)R[m]);", + "MACL = ((int) (short) R[n]) * ((int) (short) R[m]);", }, /* mulu.w - see mulu */ { "", "mn", "mulu ,", "0010nnnnmmmm1110", - "MACL = (((unsigned int)(unsigned short)R[n])", - " * ((unsigned int)(unsigned short)R[m]));", + "MACL = (((unsigned int) (unsigned short) R[n])", + " * ((unsigned int) (unsigned short) R[m]));", }, { "n", "m", "neg ,", "0110nnnnmmmm1011", @@ -799,18 +1232,24 @@ op tab[] = "R[n] = ~R[m];", }, + /* sh4a */ + { "", "n", "icbi @", "0000nnnn11100011", + "/* Except for the effect on the cache - which is not simulated -", + " this is like a nop. */", + }, + { "", "n", "ocbi @", "0000nnnn10010011", - "RSBAT (R[n]); /* Take exceptions like byte load. */", + "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. */", + "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. */", + "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop. */", "/* FIXME: Cache not implemented */", }, @@ -830,6 +1269,18 @@ op tab[] = " this is like a nop. */", }, + /* sh4a */ + { "", "n", "prefi @", "0000nnnn11010011", + "/* Except for the effect on the cache - which is not simulated -", + " this is like a nop. */", + }, + + /* sh4a */ + { "", "", "synco", "0000000010101011", + "/* Except for the effect on the pipeline - which is not simulated -", + " this is like a nop. */", + }, + { "n", "n", "rotcl ", "0100nnnn00100100", "ult = R[n] < 0;", "R[n] = (R[n] << 1) | T;", @@ -864,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;", @@ -872,10 +1324,33 @@ 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;" + }, + + /* sh4a */ + { "", "", "setdmy", "0000000011001000", + "saved_state.asregs.cregs.named.sr |= SR_MASK_DMY;" + "saved_state.asregs.cregs.named.sr &= ~SR_MASK_DMX;" + }, /* sh-dsp */ { "", "n", "setrc ", "0100nnnn00010100", @@ -904,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", @@ -918,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", @@ -952,38 +1427,56 @@ 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", "R[n] = CREG (m);", }, -#if 0 { "n", "", "stc SGR,", "0000nnnn00111010", - "R[n] = SGR;", + "if (SR_MD)", + " R[n] = SGR; /* priv mode */", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, { "n", "", "stc DBR,", "0000nnnn11111010", - "R[n] = DBR;", + "if (SR_MD)", + " R[n] = DBR; /* priv mode */", + "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 */", }, -#endif { "n", "n", "stc.l ,@-", "0100nnnnmmmm0011", "MA (1);", "R[n] -= 4;", "WLAT (R[n], CREG (m));", }, -#if 0 { "n", "n", "stc.l SGR,@-", "0100nnnn00110010", - "MA (1);", - "R[n] -= 4;", - "WLAT (R[n], SGR);", + "if (SR_MD)", + "{ /* priv mode */", + " MA (1);", + " R[n] -= 4;", + " WLAT (R[n], SGR);", + "}", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, { "n", "n", "stc.l DBR,@-", "0100nnnn11110010", - "MA (1);", - "R[n] -= 4;", - "WLAT (R[n], DBR);", + "if (SR_MD)", + "{ /* priv mode */", + " MA (1);", + " R[n] -= 4;", + " WLAT (R[n], DBR);", + "}", + "else", + " RAISE_EXCEPTION (SIGILL); /* user mode */", }, -#endif { "n", "", "sts ,", "0000nnnnssss1010", "R[n] = SREG (m);", @@ -1023,27 +1516,28 @@ op tab[] = { "", "n", "tas.b @", "0100nnnn00011011", "MA (1);", - "ult = RBAT(R[n]);", + "ult = RBAT (R[n]);", "SET_SR_T (ult == 0);", - "WBAT(R[n],ult|0x80);", + "WBAT (R[n],ult|0x80);", }, { "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, R, PC, memory, maskl, maskw,endianw);", + " nip += trap (sd, i, &R0, PC, memory, maskl, maskw, endianw);", #if 0 "else {", /* SH-[12] */ - " R[15]-=4;", - " WLAT (R[15], GET_SR());", - " R[15]-=4;", + " R[15] -= 4;", + " WLAT (R[15], GET_SR ());", + " R[15] -= 4;", " WLAT (R[15], PH2T (PC + 2));", #else "else if (!SR_BL) {", - " SSR = GET_SR();", + " SSR = GET_SR ();", " SPC = PH2T (PC + 2);", - " SET_SR (GET_SR() | SR_MASK_MD | SR_MASK_BL | SR_MASK_RB);", + " SET_SR (GET_SR () | SR_MASK_MD | SR_MASK_BL | SR_MASK_RB);", " /* FIXME: EXPEVT = 0x00000160; */", #endif " SET_NIP (PT2H (RLAT (VBR + (imm<<2))));", @@ -1081,10 +1575,10 @@ op tab[] = #if 0 { "divs.l ,", "0100nnnnmmmm1110", - "divl(0,R[n],R[m]);", + "divl (0, R[n], R[m]);", }, { "divu.l ,", "0100nnnnmmmm1101", - "divl(0,R[n],R[m]);", + "divl (0, R[n], R[m]);", }, #endif @@ -1237,62 +1731,125 @@ op movsxy_tab[] = "WLAT (R[n], SEXT (DSP_R (m)));", "R[n] += R[8];", }, - { "", "n", "movx.w @,", "111100xxXX000100", + { "", "n", "movx.w @,", "111100xyXY0001??", "DSP_R (m) = RSWAT (R[n]) << 16;", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", + }, + { "", "n", "movx.l @,", "111100xyXY010100", + "DSP_R (m) = RLAT (R[n]);", }, - { "n", "n", "movx.w @+,", "111100xxXX001000", + { "n", "n", "movx.w @+,", "111100xyXY0010??", "DSP_R (m) = RSWAT (R[n]) << 16;", "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", + }, + { "n", "n", "movx.l @+,", "111100xyXY011000", + "DSP_R (m) = RLAT (R[n]);", + "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 4;", }, - { "n", "n8","movx.w @+REG_8,", "111100xxXX001000", + { "n", "n8","movx.w @+REG_8,", "111100xyXY0011??", "DSP_R (m) = RSWAT (R[n]) << 16;", "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", + }, + { "n", "n8","movx.l @+REG_8,", "111100xyXY011100", + "DSP_R (m) = RLAT (R[n]);", + "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];", }, - { "", "n", "movx.w ,@", "111100xxaa100100", + { "", "n", "movx.w ,@", "111100xyax1001??", "WWAT (R[n], DSP_R (m) >> 16);", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", }, - { "n", "n", "movx.w ,@+", "111100xxaa101000", + { "", "n", "movx.l ,@", "111100xyax110100", + "WLAT (R[n], DSP_R (m));", + }, + { "n", "n", "movx.w ,@+", "111100xyax1010??", "WWAT (R[n], DSP_R (m) >> 16);", "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", + }, + { "n", "n", "movx.l ,@+", "111100xyax111000", + "WLAT (R[n], DSP_R (m));", + "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 4;", }, - { "n", "n8","movx.w ,@+REG_8","111100xxaa101100", + { "n", "n8","movx.w ,@+REG_8","111100xyax1011??", "WWAT (R[n], DSP_R (m) >> 16);", "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];", - "iword &= 0xfd53; goto top;", + "if (iword & 3)", + " {", + " iword &= 0xfd53; goto top;", + " }", }, - { "", "n", "movy.w @,", "111100yyYY000001", + { "n", "n8","movx.l ,@+REG_8","111100xyax111100", + "WLAT (R[n], DSP_R (m));", + "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];", + }, + { "", "n", "movy.w @,", "111100yxYX000001", "DSP_R (m) = RSWAT (R[n]) << 16;", }, - { "n", "n", "movy.w @+,", "111100yyYY000010", + { "n", "n", "movy.w @+,", "111100yxYX000010", "DSP_R (m) = RSWAT (R[n]) << 16;", "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;", }, - { "n", "n9","movy.w @+REG_9,", "111100yyYY000010", + { "n", "n9","movy.w @+REG_9,", "111100yxYX000011", "DSP_R (m) = RSWAT (R[n]) << 16;", "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];", }, - { "", "n", "movy.w ,@", "111100yyAA010001", + { "", "n", "movy.w ,@", "111100yxAY010001", "WWAT (R[n], DSP_R (m) >> 16);", }, - { "n", "n", "movy.w ,@+", "111100yyAA010010", + { "n", "n", "movy.w ,@+", "111100yxAY010010", "WWAT (R[n], DSP_R (m) >> 16);", "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;", }, - { "n", "n9", "movy.w ,@+REG_9", "111100yyAA010010", + { "n", "n9", "movy.w ,@+REG_9", "111100yxAY010011", "WWAT (R[n], DSP_R (m) >> 16);", "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];", }, + { "", "n", "movy.l @,", "111100yxYX100001", + "DSP_R (m) = RLAT (R[n]);", + }, + { "n", "n", "movy.l @+,", "111100yxYX100010", + "DSP_R (m) = RLAT (R[n]);", + "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 4;", + }, + { "n", "n9","movy.l @+REG_9,", "111100yxYX100011", + "DSP_R (m) = RLAT (R[n]);", + "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];", + }, + { "", "n", "movy.l ,@", "111100yxAY110001", + "WLAT (R[n], DSP_R (m));", + }, + { "n", "n", "movy.l ,@+", "111100yxAY110010", + "WLAT (R[n], DSP_R (m));", + "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 4;", + }, + { "n", "n9", "movy.l ,@+REG_9", "111100yxAY110011", + "WLAT (R[n], DSP_R (m));", + "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];", + }, { "", "", "nopx nopy", "1111000000000000", "/* nop */", }, { "", "", "ppi", "1111100000000000", + "RAISE_EXCEPTION_IF_IN_DELAY_SLOT ();", "ppi_insn (RIAT (nip));", - "nip += 2;", + "SET_NIP (nip + 2);", "iword &= 0xf7ff; goto top;", }, #endif @@ -1303,10 +1860,10 @@ op ppi_tab[] = { "","", "pshl #,dz", "00000iiim16.zzzz", "int Sz = DSP_R (z) & 0xffff0000;", "", - "if (i < 16)", + "if (i <= 16)", " res = Sz << i;", "else if (i >= 128 - 16)", - " res = Sz >> 128 - i;", + " res = (unsigned) Sz >> 128 - i; /* no sign extension */", "else", " {", " RAISE_EXCEPTION (SIGILL);", @@ -1320,7 +1877,7 @@ op ppi_tab[] = "int Sz = DSP_R (z);", "int Sz_grd = GET_DSP_GRD (z);", "", - "if (i < 32)", + "if (i <= 32)", " {", " if (i == 32)", " {", @@ -1359,7 +1916,7 @@ op ppi_tab[] = "greater_equal = 0;", }, { "","", "pmuls Se,Sf,Dg", "0100eeffxxyygguu", - "res = (DSP_R (e)) >> 16 * (DSP_R (f) >> 16) * 2;", + "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;", "if (res == 0x80000000)", " res = 0x7fffffff;", "DSP_R (g) = res;", @@ -1372,7 +1929,7 @@ op ppi_tab[] = "int Sy = DSP_R (y);", "int Sy_grd = SIGN32 (Sy);", "", - "res = (DSP_R (e)) >> 16 * (DSP_R (f) >> 16) * 2;", + "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;", "if (res == 0x80000000)", " res = 0x7fffffff;", "DSP_R (g) = res;", @@ -1391,7 +1948,7 @@ op ppi_tab[] = "int Sy = DSP_R (y);", "int Sy_grd = SIGN32 (Sy);", "", - "res = (DSP_R (e)) >> 16 * (DSP_R (f) >> 16) * 2;", + "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;", "if (res == 0x80000000)", " res = 0x7fffffff;", "DSP_R (g) = res;", @@ -1441,7 +1998,7 @@ op ppi_tab[] = "DSR |= carry;\n", "goto assign_z;\n", }, - { "","", "pcmp Sx,Sy", "10000100xxyy....", + { "","", "pcmp Sx,Sy", "10000100xxyyzzzz", "int Sx = DSP_R (x);", "int Sx_grd = GET_DSP_GRD (x);", "int Sy = DSP_R (y);", @@ -1458,6 +2015,24 @@ op ppi_tab[] = }, { "","", "pwad Sx,Sy,Dz", "10110100xxyyzzzz", }, + { "","", "(if cc) pabs Sx,Dz", "100010ccxx01zzzz", + "/* FIXME: duplicate code pabs. */", + "res = DSP_R (x);", + "res_grd = GET_DSP_GRD (x);", + "if (res >= 0)", + " carry = 0;", + "else", + " {", + " res = -res;", + " carry = (res != 0); /* The manual has a bug here. */", + " res_grd = -res_grd - carry;", + " }", + "COMPUTE_OVERFLOW;", + "/* ??? The re-computing of overflow after", + " saturation processing is specific to pabs. */", + "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;", + "ADD_SUB_GE;", + }, { "","", "pabs Sx,Dz", "10001000xx..zzzz", "res = DSP_R (x);", "res_grd = GET_DSP_GRD (x);", @@ -1475,16 +2050,53 @@ op ppi_tab[] = "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;", "ADD_SUB_GE;", }, + + { "","", "(if cc) prnd Sx,Dz", "100110ccxx01zzzz", + "/* FIXME: duplicate code prnd. */", + "int Sx = DSP_R (x);", + "int Sx_grd = GET_DSP_GRD (x);", + "", + "res = (Sx + 0x8000) & 0xffff0000;", + "carry = (unsigned) res < (unsigned) Sx;", + "res_grd = Sx_grd + carry;", + "COMPUTE_OVERFLOW;", + "ADD_SUB_GE;", + }, { "","", "prnd Sx,Dz", "10011000xx..zzzz", "int Sx = DSP_R (x);", "int Sx_grd = GET_DSP_GRD (x);", "", - "res = Sx + 0x8000;", + "res = (Sx + 0x8000) & 0xffff0000;", "carry = (unsigned) res < (unsigned) Sx;", "res_grd = Sx_grd + carry;", "COMPUTE_OVERFLOW;", "ADD_SUB_GE;", }, + + { "","", "(if cc) pabs Sy,Dz", "101010cc01yyzzzz", + "/* FIXME: duplicate code pabs. */", + "res = DSP_R (y);", + "res_grd = 0;", + "overflow = 0;", + "greater_equal = DSR_MASK_G;", + "if (res >= 0)", + " carry = 0;", + "else", + " {", + " res = -res;", + " carry = 1;", + " if (res < 0)", + " {", + " if (S)", + " res = 0x7fffffff;", + " else", + " {", + " overflow = DSR_MASK_V;", + " greater_equal = 0;", + " }", + " }", + " }", + }, { "","", "pabs Sy,Dz", "10101000..yyzzzz", "res = DSP_R (y);", "res_grd = 0;", @@ -1508,11 +2120,22 @@ op ppi_tab[] = " }", " }", }, + { "","", "(if cc) prnd Sy,Dz", "101110cc01yyzzzz", + "/* FIXME: duplicate code prnd. */", + "int Sy = DSP_R (y);", + "int Sy_grd = SIGN32 (Sy);", + "", + "res = (Sy + 0x8000) & 0xffff0000;", + "carry = (unsigned) res < (unsigned) Sy;", + "res_grd = Sy_grd + carry;", + "COMPUTE_OVERFLOW;", + "ADD_SUB_GE;", + }, { "","", "prnd Sy,Dz", "10111000..yyzzzz", "int Sy = DSP_R (y);", "int Sy_grd = SIGN32 (Sy);", "", - "res = Sy + 0x8000;", + "res = (Sy + 0x8000) & 0xffff0000;", "carry = (unsigned) res < (unsigned) Sy;", "res_grd = Sy_grd + carry;", "COMPUTE_OVERFLOW;", @@ -1522,10 +2145,10 @@ op ppi_tab[] = "int Sx = DSP_R (x) & 0xffff0000;", "int Sy = DSP_R (y) >> 16 & 0x7f;", "", - "if (Sy < 16)", + "if (Sy <= 16)", " res = Sx << Sy;", "else if (Sy >= 128 - 16)", - " res = Sx >> 128 - Sy;", + " res = (unsigned) Sx >> 128 - Sy; /* no sign extension */", "else", " {", " RAISE_EXCEPTION (SIGILL);", @@ -1538,7 +2161,7 @@ op ppi_tab[] = "int Sx_grd = GET_DSP_GRD (x);", "int Sy = DSP_R (y) >> 16 & 0x7f;", "", - "if (Sy < 32)", + "if (Sy <= 32)", " {", " if (Sy == 32)", " {", @@ -1588,6 +2211,18 @@ op ppi_tab[] = "COMPUTE_OVERFLOW;", "ADD_SUB_GE;", }, + { "","", "(if cc) psub Sy,Sx,Dz", "100001ccxxyyzzzz", + "int Sx = DSP_R (x);", + "int Sx_grd = GET_DSP_GRD (x);", + "int Sy = DSP_R (y);", + "int Sy_grd = SIGN32 (Sy);", + "", + "res = Sy - Sx;", + "carry = (unsigned) res > (unsigned) Sy;", + "res_grd = Sy_grd - Sx_grd - carry;", + "COMPUTE_OVERFLOW;", + "ADD_SUB_GE;", + }, { "","", "(if cc) padd Sx,Sy,Dz", "101100ccxxyyzzzz", "int Sx = DSP_R (x);", "int Sx_grd = GET_DSP_GRD (x);", @@ -1677,6 +2312,21 @@ op ppi_tab[] = "overflow = 0;", "greater_equal = 1;", }, + { "","", "pclr Du pmuls Se,Sf,Dg", "0100eeff0001gguu", + "/* Do multiply. */", + "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;", + "if (res == 0x80000000)", + " res = 0x7fffffff;", + "DSP_R (g) = res;", + "DSP_GRD (g) = SIGN32 (res);", + "/* FIXME: update DSR based on results of multiply! */", + "", + "/* Do clr. */", + "z = u;", + "res = 0;", + "res_grd = 0;", + "goto assign_z;", + }, { "","", "(if cc) pdmsb Sx,Dz", "100111ccxx..zzzz", "unsigned Sx = DSP_R (x);", "int Sx_grd = GET_DSP_GRD (x);", @@ -1792,11 +2442,33 @@ op ppi_tab[] = " MACL = DSP_R (z) = res;", "return;", }, + /* sh4a */ + { "","", "(if cc) pswap Sx,Dz", "100111ccxx01zzzz", + "int Sx = DSP_R (x);", + "", + "res = ((Sx & 0xffff) * 65536) + ((Sx >> 16) & 0xffff);", + "res_grd = GET_DSP_GRD (x);", + "carry = 0;", + "overflow = 0;", + "greater_equal = res & 0x80000000 ? 0 : DSR_MASK_G;", + }, + /* sh4a */ + { "","", "(if cc) pswap Sy,Dz", "101111cc01yyzzzz", + "int Sy = DSP_R (y);", + "", + "res = ((Sy & 0xffff) * 65536) + ((Sy >> 16) & 0xffff);", + "res_grd = SIGN32 (Sy);", + "carry = 0;", + "overflow = 0;", + "greater_equal = res & 0x80000000 ? 0 : DSR_MASK_G;", + }, + {0, 0} }; /* 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", @@ -1831,7 +2503,7 @@ static char *nibble_type_list[] = 0 }; static -char *arg_type_list[] = +const char * const arg_type_list[] = { "A_END", "A_BDISP12", @@ -1864,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; @@ -1903,7 +2559,7 @@ qfunc (a, b) } static void -sorttab () +sorttab (void) { op *p = tab; int len = 0; @@ -1917,7 +2573,7 @@ sorttab () } static void -gengastab () +gengastab (void) { op *p; sorttab (); @@ -1925,144 +2581,197 @@ gengastab () { printf ("%s %-30s\n", p->code, p->name); } - - } -/* Convert a string of 4 binary digits into an int */ +static unsigned short table[1 << 16]; -static -int -bton (s) - char *s; +static int warn_conflicts = 0; +static void +conflict_warn (int val, int i) { - int n = 0; - int v = 8; - while (v) - { - if (*s == '1') - n |= v; - v >>= 1; - s++; - } - return n; -} + int ix, key; + int j = table[val]; + + fprintf (stderr, "Warning: opcode table conflict: 0x%04x (idx %d && %d)\n", + val, i, table[val]); -static unsigned char table[1 << 16]; + 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*/ +/* 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 (shift, val, i, s) - int shift; - int val; - int i; - char *s; +expand_opcode (int val, int i, const char *s) { - int j; - if (*s == 0) { + if (warn_conflicts && table[val] != 0) + conflict_warn (val, i); table[val] = i; } else { + int j = 0, m = 0; + switch (s[0]) { - + default: + fprintf (stderr, "expand_opcode: illegal char '%c'\n", s[0]); + exit (1); case '0': case '1': - { - int m, mv; - - val |= bton (s) << shift; - if (s[2] == '0' || s[2] == '1') - expand_opcode (shift - 4, val, i, s + 4); - else if (s[2] == 'N') - for (j = 0; j < 4; j++) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); - else if (s[2] == 'x') - for (j = 0; j < 4; j += 2) - for (m = 0; m < 32; m++) - { - /* Ignore illegal nopy */ - if ((m & 7) == 0 && m != 0) - continue; - mv = m & 3 | (m & 4) << 2 | (m & 8) << 3 | (m & 16) << 4; - expand_opcode (shift - 4, val | mv | (j << shift), i, - s + 4); - } - else if (s[2] == 'y') - for (j = 0; j < 2; j++) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); - break; - } + /* Consume an arbitrary number of ones and zeros. */ + do { + j = (j << 1) + (s[m++] - '0'); + } while (s[m] == '0' || s[m] == '1'); + expand_opcode ((val << m) | j, i, s + m); + break; + case 'N': /* NN -- four-way fork */ + for (j = 0; j < 4; j++) + expand_opcode ((val << 2) | j, i, s + 2); + break; + case 'x': /* xx or xy -- two-way or four-way fork */ + for (j = 0; j < 4; j += (s[1] == 'x' ? 2 : 1)) + expand_opcode ((val << 2) | j, i, s + 2); + break; + case 'y': /* yy or yx -- two-way or four-way fork */ + for (j = 0; j < (s[1] == 'x' ? 4 : 2); j++) + expand_opcode ((val << 2) | j, i, s + 2); + break; + case '?': /* Seven-way "wildcard" fork for movxy */ + expand_opcode ((val << 2), i, s + 2); + for (j = 1; j < 4; j++) + { + expand_opcode ((val << 2) | j, i, s + 2); + expand_opcode ((val << 2) | (j + 16), i, s + 2); + } + break; + case 'i': /* eg. "i8*1" */ + case '.': /* "...." is a wildcard */ case 'n': case 'm': + /* nnnn, mmmm, i#*#, .... -- 16-way fork. */ for (j = 0; j < 16; j++) - { - expand_opcode (shift - 4, val | (j << shift), i, s + 4); - - } + expand_opcode ((val << 4) | j, i, s + 4); + break; + case 'e': + /* eeee -- even numbered register: + 8 way fork. */ + for (j = 0; j < 15; j += 2) + expand_opcode ((val << 4) | j, i, s + 4); break; case 'M': - /* A1, A0,X0,X1,Y0,Y1,M0,A1G,M1,M1G */ - for (j = 5; j < 16; j++) - if (j != 6) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + /* A0, A1, X0, X1, Y0, Y1, M0, M1, A0G, A1G: + MMMM -- 10-way fork */ + expand_opcode ((val << 4) | 5, i, s + 4); + for (j = 7; j < 16; j++) + expand_opcode ((val << 4) | j, i, s + 4); break; case 'G': - /* A1G, A0G: */ + /* A1G, A0G: + GGGG -- two-way fork */ for (j = 13; j <= 15; j +=2) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + expand_opcode ((val << 4) | j, i, s + 4); break; case 's': + /* ssss -- 10-way fork */ /* System registers mach, macl, pr: */ for (j = 0; j < 3; j++) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + expand_opcode ((val << 4) | j, i, s + 4); /* System registers fpul, fpscr/dsr, a0, x0, x1, y0, y1: */ for (j = 5; j < 12; j++) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + expand_opcode ((val << 4) | j, i, s + 4); break; case 'X': + /* XX/XY -- 2/4 way fork. */ + for (j = 0; j < 4; j += (s[1] == 'X' ? 2 : 1)) + expand_opcode ((val << 2) | j, i, s + 2); + break; case 'a': - val |= bton (s) << shift; - for (j = 0; j < 16; j += 8) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + /* aa/ax -- 2/4 way fork. */ + for (j = 0; j < 4; j += (s[1] == 'a' ? 2 : 1)) + expand_opcode ((val << 2) | j, i, s + 2); break; case 'Y': + /* YY/YX -- 2/4 way fork. */ + for (j = 0; j < (s[1] == 'Y' ? 2 : 4); j += 1) + expand_opcode ((val << 2) | j, i, s + 2); + break; case 'A': - val |= bton (s) << shift; - for (j = 0; j < 8; j += 4) - expand_opcode (shift - 4, val | (j << shift), i, s + 4); + /* AA/AY: 2/4 way fork. */ + for (j = 0; j < (s[1] == 'A' ? 2 : 4); j += 1) + expand_opcode ((val << 2) | j, i, s + 2); break; - - default: - for (j = 0; j < (1 << (shift + 4)); j++) + case 'v': + /* vv(VV) -- 4(16) way fork. */ + /* Vector register fv0/4/8/12. */ + if (s[2] == 'V') { - table[val | j] = i; + /* 2 vector registers. */ + for (j = 0; j < 15; j++) + expand_opcode ((val << 4) | j, i, s + 4); } + else + { + /* 1 vector register. */ + for (j = 0; j < 4; j += 1) + expand_opcode ((val << 2) | j, i, s + 2); + } + break; } } } /* Print the jump table used to index an opcode into a switch - statement entry. */ + 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; @@ -2090,8 +2799,7 @@ dumptable (name, size, start) static void -filltable (p) - op *p; +filltable (op *p) { static int index = 1; @@ -2099,16 +2807,16 @@ filltable (p) for (; p->name; p++) { p->index = index++; - expand_opcode (12, 0, p->index, p->code); + expand_opcode (0, p->index, p->code); } } -/* Table already contais all the switch case tags for 16-bit opcode double +/* Table already contains all the switch case tags for 16-bit opcode double data transfer (ddt) insns, and the switch case tag for processing parallel processing insns (ppi) for code 0xf800 (ppi nopx nopy). Copy the latter tag to represent all combinations of ppi with ddt. */ static void -ppi_moves () +expand_ppi_movxy (void) { int i; @@ -2118,8 +2826,7 @@ ppi_moves () } static void -gensim_caselist (p) - op *p; +gensim_caselist (op *p) { for (; p->name; p++) { @@ -2127,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); @@ -2138,10 +2844,23 @@ gensim_caselist (p) { switch (*s) { - fprintf (stderr, "gencode/gensim_caselist: illegal char '%c'\n", - *s); - exit (1); - break; + default: + fprintf (stderr, "gencode/gensim_caselist: illegal char '%c'\n", + *s); + exit (1); + break; + case '?': + /* Wildcard expansion, nothing to do here. */ + s += 2; + break; + case 'v': + printf (" int v1 = ((iword >> 10) & 3) * 4;\n"); + s += 2; + break; + case 'V': + printf (" int v2 = ((iword >> 8) & 3) * 4;\n"); + s += 2; + break; case '0': case '1': s += 2; @@ -2150,7 +2869,8 @@ gensim_caselist (p) s += 4; break; case 'n': - printf (" int n = (iword >>8) & 0xf;\n"); + case 'e': + printf (" int n = (iword >> 8) & 0xf;\n"); needn = 1; s += 4; break; @@ -2159,12 +2879,26 @@ gensim_caselist (p) s += 2; break; case 'x': - printf (" int n = ((iword >> 9) & 1) + 4;\n"); + if (s[1] == 'y') /* xy */ + { + printf (" int n = (iword & 3) ? \n"); + printf (" ((iword >> 9) & 1) + 4 : \n"); + printf (" REG_xy ((iword >> 8) & 3);\n"); + } + else + printf (" int n = ((iword >> 9) & 1) + 4;\n"); needn = 1; s += 2; break; case 'y': - printf (" int n = ((iword >> 8) & 1) + 6;\n"); + if (s[1] == 'x') /* yx */ + { + printf (" int n = (iword & 0xc) ? \n"); + printf (" ((iword >> 8) & 1) + 6 : \n"); + printf (" REG_yx ((iword >> 8) & 3);\n"); + } + else + printf (" int n = ((iword >> 8) & 1) + 6;\n"); needn = 1; s += 2; break; @@ -2173,23 +2907,51 @@ gensim_caselist (p) case 's': case 'M': case 'G': - printf (" int m = (iword >>4) & 0xf;\n"); + printf (" int m = (iword >> 4) & 0xf;\n"); s += 4; break; case 'X': - printf (" int m = ((iword >> 7) & 1) + 8;\n"); + if (s[1] == 'Y') /* XY */ + { + printf (" int m = (iword & 3) ? \n"); + printf (" ((iword >> 7) & 1) + 8 : \n"); + printf (" DSP_xy ((iword >> 6) & 3);\n"); + } + else + printf (" int m = ((iword >> 7) & 1) + 8;\n"); s += 2; break; case 'a': - printf (" int m = 7 - ((iword >> 6) & 2);\n"); + if (s[1] == 'x') /* ax */ + { + printf (" int m = (iword & 3) ? \n"); + printf (" 7 - ((iword >> 6) & 2) : \n"); + printf (" DSP_ax ((iword >> 6) & 3);\n"); + } + else + printf (" int m = 7 - ((iword >> 6) & 2);\n"); s += 2; break; case 'Y': - printf (" int m = ((iword >> 6) & 1) + 10;\n"); + if (s[1] == 'X') /* YX */ + { + printf (" int m = (iword & 0xc) ? \n"); + printf (" ((iword >> 6) & 1) + 10 : \n"); + printf (" DSP_yx ((iword >> 6) & 3);\n"); + } + else + printf (" int m = ((iword >> 6) & 1) + 10;\n"); s += 2; break; case 'A': - printf (" int m = 7 - ((iword >> 5) & 2);\n"); + if (s[1] == 'Y') /* AY */ + { + printf (" int m = (iword & 0xc) ? \n"); + printf (" 7 - ((iword >> 5) & 2) : \n"); + printf (" DSP_ay ((iword >> 6) & 3);\n"); + } + else + printf (" int m = 7 - ((iword >> 5) & 2);\n"); s += 2; break; @@ -2198,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; @@ -2206,7 +2974,6 @@ gensim_caselist (p) break; case '1': sextbit = 12; - printf ("fff"); break; } @@ -2214,13 +2981,21 @@ 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': - printf ("<<1"); + printf (" << 1"); break; case '4': - printf ("<<2"); + printf (" << 2"); break; } printf (";\n"); @@ -2229,27 +3004,46 @@ gensim_caselist (p) } if (sextbit > 0) { - printf (" i = (i ^ (1<<%d))-(1<<%d);\n", + printf (" i = (i ^ (1 << %d)) - (1 << %d);\n", sextbit - 1, sextbit - 1); } if (needm && needn) - printf (" TB(m,n);\n"); + printf (" TB (m,n);\n"); else if (needm) - printf (" TL(m);\n"); + printf (" TL (m);\n"); else if (needn) - printf (" TL(n);\n"); + printf (" TL (n);\n"); { - /* Do the refs */ - char *r; + /* Do the refs. */ + const char *r; for (r = p->refs; *r; r++) { - if (*r == '0') printf(" CREF(0);\n"); - if (*r == '8') printf(" CREF(8);\n"); - if (*r == '9') printf(" CREF(9);\n"); - if (*r == 'n') printf(" CREF(n);\n"); - if (*r == 'm') printf(" CREF(m);\n"); + 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"); + if (*r == 'n') printf (" CREF (n);\n"); + if (*r == 'm') printf (" CREF (m);\n"); } } @@ -2264,13 +3058,32 @@ gensim_caselist (p) printf (" }\n"); { - /* Do the defs */ - char *r; + /* Do the defs. */ + 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"); } } @@ -2280,9 +3093,21 @@ gensim_caselist (p) } static void -gensim () +gensim (void) { printf ("{\n"); + printf ("/* REG_xy = [r4, r5, r0, r1]. */\n"); + printf ("#define REG_xy(R) ((R)==0 ? 4 : (R)==2 ? 5 : (R)==1 ? 0 : 1)\n"); + printf ("/* REG_yx = [r6, r7, r2, r3]. */\n"); + printf ("#define REG_yx(R) ((R)==0 ? 6 : (R)==1 ? 7 : (R)==2 ? 2 : 3)\n"); + printf ("/* DSP_ax = [a0, a1, x0, x1]. */\n"); + printf ("#define DSP_ax(R) ((R)==0 ? 7 : (R)==2 ? 5 : (R)==1 ? 8 : 9)\n"); + printf ("/* DSP_ay = [a0, a1, y0, y1]. */\n"); + printf ("#define DSP_ay(R) ((R)==0 ? 7 : (R)==1 ? 5 : (R)==2 ? 10 : 11)\n"); + printf ("/* DSP_xy = [x0, x1, y0, y1]. */\n"); + printf ("#define DSP_xy(R) ((R)==0 ? 8 : (R)==2 ? 9 : (R)==1 ? 10 : 11)\n"); + printf ("/* DSP_yx = [y0, y1, x0, x1]. */\n"); + printf ("#define DSP_yx(R) ((R)==0 ? 10 : (R)==1 ? 11 : (R)==2 ? 8 : 9)\n"); printf (" switch (jump_table[iword]) {\n"); gensim_caselist (tab); @@ -2297,85 +3122,82 @@ 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); - if (*s == ' ') printf("_"); - if (*s == '@') printf("ind_"); - if (*s == ',') printf("_"); + if (isalpha (*s)) + printf ("%c", tolower (*s)); + if (*s == ' ') + printf ("_"); + if (*s == '@') + printf ("ind_"); + if (*s == ',') + printf ("_"); s++; } - printf(" %d\n",p->index); + printf (" %d\n",p->index); } } static int ppi_index; -/* Take an ppi code, expand all varying fields in it and fill all the - right entries in 'table' with the opcode index. */ +/* Take a ppi code, expand all varying fields in it and fill all the + right entries in 'table' with the opcode 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; - for (;;) + switch (s[0]) { - switch (s[0]) - { - default: - fprintf (stderr, "gencode/expand_ppi_code: Illegal char '%c'\n", - s[0]); - exit (2); - break; - /* The last eight bits are disregarded for the switch table. */ - case 'm': - case 'x': - case '.': - table[val] = i; - return; - case '0': - val += val; - s++; - break; - case '1': - val += val + 1; - s++; - break; - case 'i': - case 'e': case 'f': - val += val; - s++; - expand_ppi_code (val, i, s); - val++; - break; - case 'c': - val <<= 2; - s += 2; - val++; - expand_ppi_code (val, ppi_index++, s); - val++; - expand_ppi_code (val, i, s); - val++; - break; - } + default: + fprintf (stderr, "gencode/expand_ppi_code: Illegal char '%c'\n", s[0]); + exit (2); + 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; + case 'm': + /* Four-bit expansion. */ + for (j = 0; j < 16; j++) + expand_ppi_code ((val << 4) + j, i, s + 4); + break; + case '.': + case '0': + expand_ppi_code ((val << 1), i, s + 1); + break; + case '1': + expand_ppi_code ((val << 1) + 1, i, s + 1); + break; + case 'i': + case 'e': case 'f': + case 'x': case 'y': + expand_ppi_code ((val << 1), i, s + 1); + expand_ppi_code ((val << 1) + 1, i, s + 1); + break; + case 'c': + expand_ppi_code ((val << 2) + 1, ppi_index++, s + 2); + expand_ppi_code ((val << 2) + 2, i, s + 2); + expand_ppi_code ((val << 2) + 3, i, s + 2); + break; } } static void -ppi_filltable () +ppi_filltable (void) { op *p; ppi_index = 1; @@ -2388,7 +3210,7 @@ ppi_filltable () } static void -ppi_gensim () +ppi_gensim (void) { op *p = ppi_tab; @@ -2419,29 +3241,33 @@ 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 (" /* 'ff' = [y0, y1, x0, a1] */\n"); printf (" static char 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 (" /* 'yy' = [y0, y1, m0, m1] */\n"); printf (" static char 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 (" /* 'uu' = [x0, y0, a0, a1] */\n"); printf (" static char u_tab[] = { 8, 10, 7, 5};\n"); printf ("\n"); printf (" int z;\n"); printf (" int res, res_grd;\n"); printf (" int carry, overflow, greater_equal;\n"); printf ("\n"); - printf (" switch (ppi_table[iword >> 8]) {\n"); + printf (" switch (ppi_table[iword >> 4]) {\n"); for (; p->name; p++) { 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); @@ -2469,7 +3295,7 @@ ppi_gensim () break; case 'c': printf (" if ((((iword >> 8) ^ DSR) & 1) == 0)\n"); - printf ("\tbreak;\n"); + printf ("\treturn;\n"); printf (" }\n"); printf (" case %d: \n", p->index + 1); printf (" {\n"); @@ -2533,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"); @@ -2552,28 +3378,30 @@ ppi_gensim () } int -main (ac, av) - int ac; - char **av; +main (int ac, char *av[]) { - /* verify the table before anything else */ + /* Verify the table before anything else. */ { op *p; for (p = tab; p->name; p++) { - /* check that the code field contains 16 bits */ + /* 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 (); } } } - /* now generate the requested data */ + /* 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 (); @@ -2589,12 +3417,12 @@ main (ac, av) memset (table, 0, sizeof table); filltable (movsxy_tab); - ppi_moves (); + expand_ppi_movxy (); dumptable ("sh_dsp_table", 1 << 12, 0xf000); memset (table, 0, sizeof table); ppi_filltable (); - dumptable ("ppi_table", 1 << 8, 0); + dumptable ("ppi_table", 1 << 12, 0); } else if (strcmp (av[1], "-x") == 0) {