This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch RFC] SH: Use FRAME_GROWS_DOWNWARD


Kaz Kojima wrote:



I see. Do you have any idea of another experimentaions?


Well, you could run a benchmark.
Unless there are actually significant performance differences, hardware
would probably not be much use - the differences are likely to be in the
noise. sh-elf-run can give you an approximate cycle count, for something that
is more or less the SH2 or SH3 pipeline, I think. It doesn't emulate caches,
which is actually good for our purposes, since random alignments cause
extra noise.


I also made a patch to the simulator some time ago to support approximate
cycle counting for the SH4 pipeline. It does slow down the general operation
of the simulator slightly, though. I thought I had sent it, but unfortunately,
I couldn't find it with a web search - which might or might not be due to a
hole in the archives. If I have sent it to a relevant FSF mainling list,
it's Copyright FSF, otherwise, it is Copyright STM / Renesas. At any
rate, you can use it under the GPL.


2003-10-24 J"orn Rennecke <joern.rennecke@superh.com>

       * interp.c (ready_s): New struct.
       (saved_state_type): Make prevlock and thislock pointers.
       Add new fields sh4_group and ready.
       (L_SH4, SH4_GROUP_USE, SH4_MT, SH4_EX, SH4_BR, SH4_LS): New macros.
       (SH4_FE, SH4_CO SH4, BRANCH_TAKEN): New macros.
       (sh4_units): New enum.
       (FP_OP, FP_UNARY, FP_CMP, Delay_Slot, L, TL, TB, MA,
       * gencode.c (op): Add new field sh4_group.
       (tab): Add initializers for new field.  Complete def / ref
       information.  Add code for latency / cycle count special cases.
       (movsxy_tab, ppi_tab): Add initializers for new field.
       * (gensim_caselist, sim_resume): Add code for SH4 timings.

       * interp.c (fsca_s, fsrra_s): New functions.
       * gencode.c (tab): Add entries for fsca and fsrra.
       (expand_opcode): Allow variable length n / m fields.

? sim-031023
Index: gencode.c
===================================================================
RCS file: /cvs/src/src/sim/sh/gencode.c,v
retrieving revision 1.20
diff -p -r1.20 gencode.c
*** gencode.c	11 Aug 2003 19:28:05 -0000	1.20
--- gencode.c	24 Oct 2003 19:55:30 -0000
***************
*** 36,41 ****
--- 36,42 ----
  typedef struct
  {
    char *defs;
+   char *sh4_group;
    char *refs;
    char *name;
    char *code;
*************** typedef struct
*** 47,181 ****
  op tab[] =
  {
  
!   { "n", "", "add #<imm>,<REG_N>", "0111nnnni8*1....",
      "R[n] += SEXT(i);",
      "if (i == 0) {",
!     "  UNDEF(n); /* see #ifdef PARANOID */",
      "  break;",
      "}",
    },
!   { "n", "mn", "add <REG_M>,<REG_N>", "0011nnnnmmmm1100",
      "R[n] += R[m];",
    },
  
!   { "n", "mn", "addc <REG_M>,<REG_N>", "0011nnnnmmmm1110",
      "ult = R[n] + T;",
      "SET_SR_T (ult < R[n]);",
      "R[n] = ult + R[m];",
      "SET_SR_T (T || (R[n] < ult));",
    },
  
!   { "n", "mn", "addv <REG_M>,<REG_N>", "0011nnnnmmmm1111",
      "ult = R[n] + R[m];",
      "SET_SR_T ((~(R[n] ^ R[m]) & (ult ^ R[n])) >> 31);",
      "R[n] = ult;",
    },
  
!   { "0", "", "and #<imm>,R0", "11001001i8*1....",
      "R0 &= i;",
    },
!   { "n", "nm", "and <REG_M>,<REG_N>", "0010nnnnmmmm1001",
      "R[n] &= R[m];",
    },
!   { "", "0", "and.b #<imm>,@(R0,GBR)", "11001101i8*1....",
      "MA (1);",
      "WBAT (GBR + R0, RBAT (GBR + R0) & i);",
    },
  
!   { "", "", "bf <bdisp8>", "10001011i8p1....",
      "if (!T) {",
!     "  SET_NIP (PC + 4 + (SEXT(i) * 2));",
!     "  cycles += 2;",
      "}",
    },
  
!   { "", "", "bf.s <bdisp8>", "10001111i8p1....",
      "if (!T) {",
!     "  SET_NIP (PC + 4 + (SEXT (i) * 2));",
!     "  cycles += 2;",
      "  Delay_Slot (PC + 2);",
      "}",
    },
  
!   { "", "", "bra <bdisp12>", "1010i12.........",
!     "SET_NIP (PC + 4 + (SEXT12 (i) * 2));",
!     "cycles += 2;",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "n", "braf <REG_N>", "0000nnnn00100011",
!     "SET_NIP (PC + 4 + R[n]);",
!     "cycles += 2;",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "", "bsr <bdisp12>", "1011i12.........",
      "PR = PH2T (PC + 4);",
!     "SET_NIP (PC + 4 + (SEXT12 (i) * 2));",
!     "cycles += 2;",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "n", "bsrf <REG_N>", "0000nnnn00000011",
      "PR = PH2T (PC) + 4;",
!     "SET_NIP (PC + 4 + R[n]);",
!     "cycles += 2;",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "", "bt <bdisp8>", "10001001i8p1....",
      "if (T) {",
!     "  SET_NIP (PC + 4 + (SEXT (i) * 2));",
!     "  cycles += 2;",
      "}",
    },
  
!   { "", "", "bt.s <bdisp8>", "10001101i8p1....",
      "if (T) {",
!     "  SET_NIP (PC + 4 + (SEXT (i) * 2));",
!     "  cycles += 2;",
      "  Delay_Slot (PC + 2);",
      "}",
    },
  
!   { "", "", "clrmac", "0000000000101000",
      "MACH = 0;",
      "MACL = 0;",
    },
  
!   { "", "", "clrs", "0000000001001000",
      "SET_SR_S (0);",
    },
  
!   { "", "", "clrt", "0000000000001000",
      "SET_SR_T (0);",
    },
  
!   { "", "0", "cmp/eq #<imm>,R0", "10001000i8*1....",
      "SET_SR_T (R0 == SEXT (i));",
    },
!   { "", "mn", "cmp/eq <REG_M>,<REG_N>", "0011nnnnmmmm0000",
      "SET_SR_T (R[n] == R[m]);",
    },
!   { "", "mn", "cmp/ge <REG_M>,<REG_N>", "0011nnnnmmmm0011",
      "SET_SR_T (R[n] >= R[m]);",
    },
!   { "", "mn", "cmp/gt <REG_M>,<REG_N>", "0011nnnnmmmm0111",
      "SET_SR_T (R[n] > R[m]);",
    },
!   { "", "mn", "cmp/hi <REG_M>,<REG_N>", "0011nnnnmmmm0110",
      "SET_SR_T (UR[n] > UR[m]);",
    },
!   { "", "mn", "cmp/hs <REG_M>,<REG_N>", "0011nnnnmmmm0010",
      "SET_SR_T (UR[n] >= UR[m]);",
    },
!   { "", "n", "cmp/pl <REG_N>", "0100nnnn00010101",
      "SET_SR_T (R[n] > 0);",
    },
!   { "", "n", "cmp/pz <REG_N>", "0100nnnn00010001",
      "SET_SR_T (R[n] >= 0);",
    },
!   { "", "mn", "cmp/str <REG_M>,<REG_N>", "0010nnnnmmmm1100",
      "ult = R[n] ^ R[m];",
      "SET_SR_T (((ult & 0xff000000) == 0)",
      "          | ((ult & 0xff0000) == 0)",
--- 48,181 ----
  op tab[] =
  {
  
!   { "n", "ex", "", "add #<imm>,<REG_N>", "0111nnnni8*1....",
      "R[n] += SEXT(i);",
+     "#ifdef PARANOID",
      "if (i == 0) {",
!     "  UNDEF(n);",
      "  break;",
      "}",
+     "#endif /* PARANOID */",
    },
!   { "n", "ex", "mn", "add <REG_M>,<REG_N>", "0011nnnnmmmm1100",
      "R[n] += R[m];",
    },
  
!   { "nt", "ex", "mnt", "addc <REG_M>,<REG_N>", "0011nnnnmmmm1110",
      "ult = R[n] + T;",
      "SET_SR_T (ult < R[n]);",
      "R[n] = ult + R[m];",
      "SET_SR_T (T || (R[n] < ult));",
    },
  
!   { "nt", "ex", "mn", "addv <REG_M>,<REG_N>", "0011nnnnmmmm1111",
      "ult = R[n] + R[m];",
      "SET_SR_T ((~(R[n] ^ R[m]) & (ult ^ R[n])) >> 31);",
      "R[n] = ult;",
    },
  
!   { "0", "ex", "", "and #<imm>,R0", "11001001i8*1....",
      "R0 &= i;",
    },
!   { "n", "ex", "nm", "and <REG_M>,<REG_N>", "0010nnnnmmmm1001",
      "R[n] &= R[m];",
    },
!   { "", "co", "0", "and.b #<imm>,@(R0,GBR)", "11001101i8*1....",
      "MA (1);",
+     "cycles += 3;",
      "WBAT (GBR + R0, RBAT (GBR + R0) & i);",
    },
  
!   { "", "br", "t", "bf <bdisp8>", "10001011i8p1....",
      "if (!T) {",
!     "  BRANCH_TAKEN (PC + 4 + (SEXT(i) * 2));",
      "}",
    },
  
!   { "", "br", "t", "bf.s <bdisp8>", "10001111i8p1....",
      "if (!T) {",
!     "  BRANCH_TAKEN (PC + 4 + (SEXT (i) * 2));",
      "  Delay_Slot (PC + 2);",
      "}",
    },
  
!   { "", "br", "", "bra <bdisp12>", "1010i12.........",
!     "BRANCH_TAKEN (PC + 4 + (SEXT12 (i) * 2));",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "co", "n", "braf <REG_N>", "0000nnnn00100011",
!     "BRANCH_TAKEN (PC + 4 + R[n]);",
!     "cycles++;",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "br", "", "bsr <bdisp12>", "1011i12.........",
      "PR = PH2T (PC + 4);",
!     "BRANCH_TAKEN (PC + 4 + (SEXT12 (i) * 2));",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "co", "n", "bsrf <REG_N>", "0000nnnn00000011",
      "PR = PH2T (PC) + 4;",
!     "BRANCH_TAKEN (PC + 4 + R[n]);",
!     "cycles++;",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "br", "t", "bt <bdisp8>", "10001001i8p1....",
      "if (T) {",
!     "  BRANCH_TAKEN (PC + 4 + (SEXT (i) * 2));",
      "}",
    },
  
!   { "", "br", "t", "bt.s <bdisp8>", "10001101i8p1....",
      "if (T) {",
!     "  BRANCH_TAKEN (PC + 4 + (SEXT (i) * 2));",
      "  Delay_Slot (PC + 2);",
      "}",
    },
  
!   { "", "co", "", "clrmac", "0000000000101000",
!     "L_SH4 (mach, 3);",
!     "L_SH4 (macl, 3);",
      "MACH = 0;",
      "MACL = 0;",
    },
  
!   { "", "co", "", "clrs", "0000000001001000",
      "SET_SR_S (0);",
    },
  
!   { "t", "mt", "", "clrt", "0000000000001000",
      "SET_SR_T (0);",
    },
  
!   { "t", "mt", "0", "cmp/eq #<imm>,R0", "10001000i8*1....",
      "SET_SR_T (R0 == SEXT (i));",
    },
!   { "t", "mt", "mn", "cmp/eq <REG_M>,<REG_N>", "0011nnnnmmmm0000",
      "SET_SR_T (R[n] == R[m]);",
    },
!   { "t", "mt", "mn", "cmp/ge <REG_M>,<REG_N>", "0011nnnnmmmm0011",
      "SET_SR_T (R[n] >= R[m]);",
    },
!   { "t", "mt", "mn", "cmp/gt <REG_M>,<REG_N>", "0011nnnnmmmm0111",
      "SET_SR_T (R[n] > R[m]);",
    },
!   { "t", "mt", "mn", "cmp/hi <REG_M>,<REG_N>", "0011nnnnmmmm0110",
      "SET_SR_T (UR[n] > UR[m]);",
    },
!   { "t", "mt", "mn", "cmp/hs <REG_M>,<REG_N>", "0011nnnnmmmm0010",
      "SET_SR_T (UR[n] >= UR[m]);",
    },
!   { "t", "mt", "n", "cmp/pl <REG_N>", "0100nnnn00010101",
      "SET_SR_T (R[n] > 0);",
    },
!   { "t", "mt", "n", "cmp/pz <REG_N>", "0100nnnn00010001",
      "SET_SR_T (R[n] >= 0);",
    },
!   { "t", "mt", "mn", "cmp/str <REG_M>,<REG_N>", "0010nnnnmmmm1100",
      "ult = R[n] ^ R[m];",
      "SET_SR_T (((ult & 0xff000000) == 0)",
      "          | ((ult & 0xff0000) == 0)",
*************** op tab[] =
*** 183,253 ****
      "          | ((ult & 0xff) == 0));",
    },
  
!   { "", "mn", "div0s <REG_M>,<REG_N>", "0010nnnnmmmm0111",
      "SET_SR_Q ((R[n] & sbit) != 0);",
      "SET_SR_M ((R[m] & sbit) != 0);",
      "SET_SR_T (M != Q);",
    },
  
!   { "", "", "div0u", "0000000000011001",
      "SET_SR_M (0);",
      "SET_SR_Q (0);",
      "SET_SR_T (0);",
    },
  
!   { "", "nm", "div1 <REG_M>,<REG_N>", "0011nnnnmmmm0100", /* ? MVS */
      "div1 (R, m, n/*, T*/);",
    },
  
!   { "", "nm", "dmuls.l <REG_M>,<REG_N>", "0011nnnnmmmm1101",
      "dmul (1/*signed*/, R[n], R[m]);",
    },
  
!   { "", "nm", "dmulu.l <REG_M>,<REG_N>", "0011nnnnmmmm0101",
      "dmul (0/*unsigned*/, R[n], R[m]);",
    },
  
!   { "n", "n", "dt <REG_N>", "0100nnnn00010000",
      "R[n]--;",
      "SET_SR_T (R[n] == 0);",
    },
  
!   { "n", "m", "exts.b <REG_M>,<REG_N>", "0110nnnnmmmm1110",
      "R[n] = SEXT (R[m]);",
    },
!   { "n", "m", "exts.w <REG_M>,<REG_N>", "0110nnnnmmmm1111",
      "R[n] = SEXTW (R[m]);",
    },
  
!   { "n", "m", "extu.b <REG_M>,<REG_N>", "0110nnnnmmmm1100",
      "R[n] = (R[m] & 0xff);",
    },
!   { "n", "m", "extu.w <REG_M>,<REG_N>", "0110nnnnmmmm1101",
      "R[n] = (R[m] & 0xffff);",
    },
  
    /* sh2e */
!   { "", "", "fabs <FREG_N>", "1111nnnn01011101",
!     "FP_UNARY (n, fabs);",
      "/* FIXME: FR(n) &= 0x7fffffff; */",
    },
  
    /* sh2e */
!   { "", "", "fadd <FREG_M>,<FREG_N>", "1111nnnnmmmm0000",
!     "FP_OP (n, +, m);",
    },
  
    /* sh2e */
!   { "", "", "fcmp/eq <FREG_M>,<FREG_N>", "1111nnnnmmmm0100",
      "FP_CMP (n, ==, m);",
    },
    /* sh2e */
!   { "", "", "fcmp/gt <FREG_M>,<FREG_N>", "1111nnnnmmmm0101",
      "FP_CMP (n, >, m);",
    },
  
    /* sh4 */
!   { "", "", "fcnvds <DR_N>,FPUL", "1111nnnn10111101",
      "if (! FPSCR_PR || n & 1)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
--- 183,260 ----
      "          | ((ult & 0xff) == 0));",
    },
  
!   { "t", "ex", "mn", "div0s <REG_M>,<REG_N>", "0010nnnnmmmm0111",
      "SET_SR_Q ((R[n] & sbit) != 0);",
      "SET_SR_M ((R[m] & sbit) != 0);",
      "SET_SR_T (M != Q);",
    },
  
!   { "t", "ex", "", "div0u", "0000000000011001",
      "SET_SR_M (0);",
      "SET_SR_Q (0);",
      "SET_SR_T (0);",
    },
  
!   { "nt", "ex", "nmt", "div1 <REG_M>,<REG_N>", "0011nnnnmmmm0100",
      "div1 (R, m, n/*, T*/);",
    },
  
!   { "", "co", "nm", "dmuls.l <REG_M>,<REG_N>", "0011nnnnmmmm1101",
!     "L_SH4 (macl, 4);",
!     "L_SH4 (mach, 4);",
!     "cycles++;",
      "dmul (1/*signed*/, R[n], R[m]);",
    },
  
!   { "", "co", "nm", "dmulu.l <REG_M>,<REG_N>", "0011nnnnmmmm0101",
!     "L_SH4 (macl, 4);",
!     "L_SH4 (mach, 4);",
!     "cycles++;",
      "dmul (0/*unsigned*/, R[n], R[m]);",
    },
  
!   { "nt", "ex", "n", "dt <REG_N>", "0100nnnn00010000",
      "R[n]--;",
      "SET_SR_T (R[n] == 0);",
    },
  
!   { "n", "ex", "m", "exts.b <REG_M>,<REG_N>", "0110nnnnmmmm1110",
      "R[n] = SEXT (R[m]);",
    },
!   { "n", "ex", "m", "exts.w <REG_M>,<REG_N>", "0110nnnnmmmm1111",
      "R[n] = SEXTW (R[m]);",
    },
  
!   { "n", "ex", "m", "extu.b <REG_M>,<REG_N>", "0110nnnnmmmm1100",
      "R[n] = (R[m] & 0xff);",
    },
!   { "n", "ex", "m", "extu.w <REG_M>,<REG_N>", "0110nnnnmmmm1101",
      "R[n] = (R[m] & 0xffff);",
    },
  
    /* sh2e */
!   { "", "ls", "", "fabs <FREG_N>", "1111nnnn01011101",
!     "FP_UNARY (n, fabs, 0, 0);",
      "/* FIXME: FR(n) &= 0x7fffffff; */",
    },
  
    /* sh2e */
!   { "", "fe", "c", "fadd <FREG_M>,<FREG_N>", "1111nnnnmmmm0000",
!     "SH4_FE;",
!     "FP_OP (n, +, m, 3, 8);",
    },
  
    /* sh2e */
!   { "", "", "c", "fcmp/eq <FREG_M>,<FREG_N>", "1111nnnnmmmm0100",
      "FP_CMP (n, ==, m);",
    },
    /* sh2e */
!   { "", "", "c", "fcmp/gt <FREG_M>,<FREG_N>", "1111nnnnmmmm0101",
      "FP_CMP (n, >, m);",
    },
  
    /* sh4 */
!   { "", "fe", "c", "fcnvds <DR_N>,FPUL", "1111nnnn10111101",
      "if (! FPSCR_PR || n & 1)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
*************** op tab[] =
*** 259,269 ****
      "  } u;",
      "  u.f = DR(n);",
      "  FPUL = u.i;",
      "}",
    },
  
    /* sh4 */
!   { "", "", "fcnvsd FPUL,<DR_N>", "1111nnnn10101101",
      "if (! FPSCR_PR || n & 1)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
--- 266,277 ----
      "  } u;",
      "  u.f = DR(n);",
      "  FPUL = u.i;",
+     "  L_SH4 (fpul, 4);",
      "}",
    },
  
    /* sh4 */
!   { "", "fe", "c", "fcnvsd FPUL,<DR_N>", "1111nnnn10101101",
      "if (! FPSCR_PR || n & 1)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
*************** op tab[] =
*** 275,310 ****
      "  } u;",
      "  u.i = FPUL;",
      "  SET_DR(n, u.f);",
      "}",
    },
  
    /* sh2e */
!   { "", "", "fdiv <FREG_M>,<FREG_N>", "1111nnnnmmmm0011",
!     "FP_OP (n, /, m);",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh4 */
!   { "", "", "fipr <FV_M>,<FV_N>", "1111nnmm11101101",
      "/* FIXME: not implemented */",
      "RAISE_EXCEPTION (SIGILL);",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh2e */
!   { "", "", "fldi0 <FREG_N>", "1111nnnn10001101",
      "SET_FR (n, (float)0.0);",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh2e */
!   { "", "", "fldi1 <FREG_N>", "1111nnnn10011101",
      "SET_FR (n, (float)1.0);",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh2e */
!   { "", "", "flds <FREG_N>,FPUL", "1111nnnn00011101",
      "  union",
      "  {",
      "    int i;",
--- 283,319 ----
      "  } u;",
      "  u.i = FPUL;",
      "  SET_DR(n, u.f);",
+     "  L_SH4 (FR[n], 4);",
      "}",
    },
  
    /* sh2e */
!   { "", "fe", "c", "fdiv <FREG_M>,<FREG_N>", "1111nnnnmmmm0011",
!     "FP_OP (n, /, m, 12, 25);",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh4 */
!   { "", "fe", "c", "fipr <FV_M>,<FV_N>", "1111nnmm11101101",
      "/* FIXME: not implemented */",
      "RAISE_EXCEPTION (SIGILL);",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh2e */
!   { "", "ls", "", "fldi0 <FREG_N>", "1111nnnn10001101",
      "SET_FR (n, (float)0.0);",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh2e */
!   { "", "ls", "", "fldi1 <FREG_N>", "1111nnnn10011101",
      "SET_FR (n, (float)1.0);",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh2e */
!   { "", "ls", "", "flds <FREG_N>,FPUL", "1111nnnn00011101",
      "  union",
      "  {",
      "    int i;",
*************** op tab[] =
*** 315,338 ****
    },
  
    /* sh2e */
!   { "", "", "float FPUL,<FREG_N>", "1111nnnn00101101",
      /* sh4 */
      "if (FPSCR_PR)",
!     "  SET_DR (n, (double)FPUL);",
      "else",
!     "{",
!     "  SET_FR (n, (float)FPUL);",
!     "}",
    },
  
    /* sh2e */
!   { "", "", "fmac <FREG_0>,<FREG_M>,<FREG_N>", "1111nnnnmmmm1110",
      "SET_FR (n, FR(m) * FR(0) + FR(n));",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh2e */
!   { "", "", "fmov <FREG_M>,<FREG_N>", "1111nnnnmmmm1100",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  int ni = XD_TO_XF (n);",
--- 324,352 ----
    },
  
    /* sh2e */
!   { "", "fe", "c", "float FPUL,<FREG_N>", "1111nnnn00101101",
      /* sh4 */
      "if (FPSCR_PR)",
!     "  {",
!     "    L_SH4 (FR[n], 4);",
!     "    SET_DR (n, (double)FPUL);",
!     "  }",
      "else",
!     "  {",
!     "    L_SH4 (FR[n], 3);",
!     "    SET_FR (n, (float)FPUL);",
!     "  }",
    },
  
    /* sh2e */
!   { "", "fe", "", "fmac <FREG_0>,<FREG_M>,<FREG_N>", "1111nnnnmmmm1110",
!     "    L_SH4 (FR[n], 3);",
      "SET_FR (n, FR(m) * FR(0) + FR(n));",
      "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh2e */
!   { "", "ls", "c", "fmov <FREG_M>,<FREG_N>", "1111nnnnmmmm1100",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  int ni = XD_TO_XF (n);",
*************** op tab[] =
*** 346,352 ****
      "}",
    },
    /* sh2e */
!   { "", "n", "fmov.s <FREG_M>,@<REG_N>", "1111nnnnmmmm1010",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
--- 360,366 ----
      "}",
    },
    /* sh2e */
!   { "", "ls", "nc", "fmov.s <FREG_M>,@<REG_N>", "1111nnnnmmmm1010",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
*************** op tab[] =
*** 359,365 ****
      "}",
    },
    /* sh2e */
!   { "", "m", "fmov.s @<REG_M>,<FREG_N>", "1111nnnnmmmm1000",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
--- 373,379 ----
      "}",
    },
    /* sh2e */
!   { "f", "ld", "mc", "fmov.s @<REG_M>,<FREG_N>", "1111nnnnmmmm1000",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
*************** op tab[] =
*** 372,378 ****
      "}",
    },
    /* sh2e */
!   { "m", "m", "fmov.s @<REG_M>+,<FREG_N>", "1111nnnnmmmm1001",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
--- 386,392 ----
      "}",
    },
    /* sh2e */
!   { "mf", "ld", "mc", "fmov.s @<REG_M>+,<FREG_N>", "1111nnnnmmmm1001",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
*************** op tab[] =
*** 387,393 ****
      "}",
    },
    /* sh2e */
!   { "n", "n", "fmov.s <FREG_M>,@-<REG_N>", "1111nnnnmmmm1011",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
--- 401,407 ----
      "}",
    },
    /* sh2e */
!   { "n", "ls", "nc", "fmov.s <FREG_M>,@-<REG_N>", "1111nnnnmmmm1011",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
*************** op tab[] =
*** 402,408 ****
      "}",
    },
    /* sh2e */
!   { "", "0m", "fmov.s @(R0,<REG_M>),<FREG_N>", "1111nnnnmmmm0110",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
--- 416,422 ----
      "}",
    },
    /* sh2e */
!   { "f", "ld", "0mc", "fmov.s @(R0,<REG_M>),<FREG_N>", "1111nnnnmmmm0110",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
*************** op tab[] =
*** 415,421 ****
      "}",
    },
    /* sh2e */
!   { "", "0n", "fmov.s <FREG_M>,@(R0,<REG_N>)", "1111nnnnmmmm0111",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
--- 429,435 ----
      "}",
    },
    /* sh2e */
!   { "", "ls", "0nc", "fmov.s <FREG_M>,@(R0,<REG_N>)", "1111nnnnmmmm0111",
      /* sh4 */
      "if (FPSCR_SZ) {",
      "  MA (2);",
*************** op tab[] =
*** 431,447 ****
    /* sh4: See fmov instructions above for move to/from extended fp registers */
  
    /* sh2e */
!   { "", "", "fmul <FREG_M>,<FREG_N>", "1111nnnnmmmm0010",
!     "FP_OP(n, *, m);",
    },
  
    /* sh2e */
!   { "", "", "fneg <FREG_N>", "1111nnnn01001101",
!     "FP_UNARY(n, -);",
    },
  
    /* sh4 */
!   { "", "", "frchg", "1111101111111101",
      "if (FPSCR_PR)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
--- 445,461 ----
    /* sh4: See fmov instructions above for move to/from extended fp registers */
  
    /* sh2e */
!   { "", "fe", "c", "fmul <FREG_M>,<FREG_N>", "1111nnnnmmmm0010",
!     "FP_OP(n, *, m, 3, 8);",
    },
  
    /* sh2e */
!   { "", "ls", "", "fneg <FREG_N>", "1111nnnn01001101",
!     "FP_UNARY(n, -, 0, 0);",
    },
  
    /* sh4 */
!   { "", "fe", "", "frchg", "1111101111111101",
      "if (FPSCR_PR)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
*************** op tab[] =
*** 449,486 ****
    },
  
    /* sh4 */
!   { "", "", "fschg", "1111001111111101",
      "SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_SZ);",
    },
  
    /* sh3e */
!   { "", "", "fsqrt <FREG_N>", "1111nnnn01101101",
!     "FP_UNARY(n, sqrt);",
    },
  
    /* sh2e */
!   { "", "", "fsub <FREG_M>,<FREG_N>", "1111nnnnmmmm0001",
!     "FP_OP(n, -, m);",
    },
  
    /* sh2e */
!   { "", "", "ftrc <FREG_N>, FPUL", "1111nnnn00111101",
      /* sh4 */
      "if (FPSCR_PR) {",
      "  if (DR(n) != DR(n)) /* NaN */",
      "    FPUL = 0x80000000;",
      "  else",
      "    FPUL =  (int)DR(n);",
      "}",
      "else",
!     "if (FR(n) != FR(n)) /* NaN */",
!     "  FPUL = 0x80000000;",
!     "else",
!     "  FPUL = (int)FR(n);",
    },
  
    /* sh2e */
!   { "", "", "fsts FPUL,<FREG_N>", "1111nnnn00001101",
      "  union",
      "  {",
      "    int i;",
--- 463,528 ----
    },
  
    /* sh4 */
!   { "", "fe", "c", "fsca", "1111nnn011111101",
!     "if (FPSCR_PR)",
!     "  RAISE_EXCEPTION (SIGILL);",
!     "else",
!     "  {",
!     "    L_SH4 (FR[n], 11);",
!     "    L_SH4 (FR[n+1], 11);",
!     "    SET_FR (n, fsca_s (FPUL, &sin));",
!     "    SET_FR (n+1, fsca_s (FPUL, &cos));",
!     "  }",
!   },
! 
!   /* sh4 */
!   { "", "fe", "", "fschg", "1111001111111101",
      "SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_SZ);",
    },
  
    /* sh3e */
!   { "", "fe", "c", "fsqrt <FREG_N>", "1111nnnn01101101",
!     "FP_UNARY(n, sqrt, 11, 24);",
!   },
! 
!   /* sh4 */
!   { "", "fe", "c", "fsrra", "1111nnnn01111101",
!     "if (FPSCR_PR)",
!     "  RAISE_EXCEPTION (SIGILL);",
!     "else",
!     "  {",
!     "    L_SH4 (FR[n], 11);",
!     "    SET_FR (n, fsrra_s (FR (n)));",
!     "  }",
    },
  
    /* sh2e */
!   { "", "fe", "c", "fsub <FREG_M>,<FREG_N>", "1111nnnnmmmm0001",
!     "FP_OP(n, -, m, 3, 8);",
    },
  
    /* sh2e */
!   { "", "fe", "c", "ftrc <FREG_N>, FPUL", "1111nnnn00111101",
      /* sh4 */
      "if (FPSCR_PR) {",
      "  if (DR(n) != DR(n)) /* NaN */",
      "    FPUL = 0x80000000;",
      "  else",
      "    FPUL =  (int)DR(n);",
+     "  L_SH4 (fpul, 4);",
      "}",
      "else",
!     "  {",
!     "    if (FR(n) != FR(n)) /* NaN */",
!     "      FPUL = 0x80000000;",
!     "    else",
!     "      FPUL = (int)FR(n);",
!     "    L_SH4 (fpul, 3);",
!     "  }",
    },
  
    /* sh2e */
!   { "", "ls", "", "fsts FPUL,<FREG_N>", "1111nnnn00001101",
      "  union",
      "  {",
      "    int i;",
*************** op tab[] =
*** 490,502 ****
      "  SET_FR (n, u.f);",
    },
  
!   { "", "n", "jmp @<REG_N>", "0100nnnn00101011",
      "SET_NIP (PT2H (R[n]));",
      "cycles += 2;",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "n", "jsr @<REG_N>", "0100nnnn00001011",
      "PR = PH2T (PC + 4);",
      "if (~doprofile)",
      "  gotcall (PR, R[n]);",
--- 532,544 ----
      "  SET_FR (n, u.f);",
    },
  
!   { "", "co", "n", "jmp @<REG_N>", "0100nnnn00101011",
      "SET_NIP (PT2H (R[n]));",
      "cycles += 2;",
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "co", "n", "jsr @<REG_N>", "0100nnnn00001011",
      "PR = PH2T (PC + 4);",
      "if (~doprofile)",
      "  gotcall (PR, R[n]);",
*************** op tab[] =
*** 505,546 ****
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "n", "ldc <REG_N>,<CREG_M>", "0100nnnnmmmm1110",
      "CREG (m) = R[n];",
      "/* FIXME: user mode */",
    },
!   { "", "n", "ldc <REG_N>,SR", "0100nnnn00001110",
      "SET_SR (R[n]);",
      "/* FIXME: user mode */",
    },
!   { "", "n", "ldc <REG_N>,MOD", "0100nnnn01011110",
      "SET_MOD (R[n]);",
    },
  #if 0
!   { "", "n", "ldc <REG_N>,DBR", "0100nnnn11111010",
      "DBR = R[n];",
      "/* FIXME: user mode */",
    },
  #endif
!   { "n", "n", "ldc.l @<REG_N>+,<CREG_M>", "0100nnnnmmmm0111",
      "MA (1);",
      "CREG (m) = RLAT (R[n]);",
      "R[n] += 4;",
      "/* FIXME: user mode */",
    },
!   { "n", "n", "ldc.l @<REG_N>+,SR", "0100nnnn00000111",
      "MA (1);",
      "SET_SR (RLAT (R[n]));",
      "R[n] += 4;",
      "/* FIXME: user mode */",
    },
!   { "n", "n", "ldc.l @<REG_N>+,MOD", "0100nnnn01010111",
      "MA (1);",
      "SET_MOD (RLAT (R[n]));",
      "R[n] += 4;",
    },
  #if 0
!   { "n", "n", "ldc.l @<REG_N>+,DBR", "0100nnnn11110110",
      "MA (1);",
      "DBR = RLAT (R[n]);",
      "R[n] += 4;",
--- 547,590 ----
      "Delay_Slot (PC + 2);",
    },
  
!   { "", "co", "n", "ldc <REG_N>,<CREG_M>", "0100nnnnmmmm1110",
      "CREG (m) = R[n];",
      "/* FIXME: user mode */",
    },
!   { "", "co", "n", "ldc <REG_N>,SR", "0100nnnn00001110",
!     "cycles += 3;",
      "SET_SR (R[n]);",
      "/* FIXME: user mode */",
    },
!   { "", "co", "n", "ldc <REG_N>,MOD", "0100nnnn01011110",
      "SET_MOD (R[n]);",
    },
  #if 0
!   { "", "co", "n", "ldc <REG_N>,DBR", "0100nnnn11111010",
      "DBR = R[n];",
      "/* FIXME: user mode */",
    },
  #endif
!   { "n", "co", "n", "ldc.l @<REG_N>+,<CREG_M>", "0100nnnnmmmm0111",
      "MA (1);",
      "CREG (m) = RLAT (R[n]);",
      "R[n] += 4;",
      "/* FIXME: user mode */",
    },
!   { "n", "co", "n", "ldc.l @<REG_N>+,SR", "0100nnnn00000111",
      "MA (1);",
+     "cycles += 3;",
      "SET_SR (RLAT (R[n]));",
      "R[n] += 4;",
      "/* FIXME: user mode */",
    },
!   { "n", "co", "n", "ldc.l @<REG_N>+,MOD", "0100nnnn01010111",
      "MA (1);",
      "SET_MOD (RLAT (R[n]));",
      "R[n] += 4;",
    },
  #if 0
!   { "n", "co", "n", "ldc.l @<REG_N>+,DBR", "0100nnnn11110110",
      "MA (1);",
      "DBR = RLAT (R[n]);",
      "R[n] += 4;",
*************** op tab[] =
*** 549,862 ****
  #endif
  
    /* sh-dsp */
!   { "", "", "ldre @(<disp>,PC)", "10001110i8p1....",
      "RE = SEXT (i) * 2 + 4 + PH2T (PC);",
    },
!   { "", "", "ldrs @(<disp>,PC)", "10001100i8p1....",
      "RS = SEXT (i) * 2 + 4 + PH2T (PC);",
    },
  
!   { "", "n", "lds <REG_N>,<SREG_M>", "0100nnnnssss1010",
      "SREG (m) = R[n];",
    },
!   { "n", "n", "lds.l @<REG_N>+,<SREG_M>", "0100nnnnssss0110",
      "MA (1);",
      "SREG (m) = RLAT(R[n]);",
      "R[n] += 4;",
    },
    /* sh2e / sh-dsp (lds <REG_N>,DSR) */
!   { "", "n", "lds <REG_N>,FPSCR", "0100nnnn01101010",
      "SET_FPSCR(R[n]);",
    },
    /* sh2e / sh-dsp (lds.l @<REG_N>+,DSR) */
!   { "n", "n", "lds.l @<REG_N>+,FPSCR", "0100nnnn01100110",
      "MA (1);",
      "SET_FPSCR (RLAT(R[n]));",
      "R[n] += 4;",
    },
  
!   { "", "", "ldtlb", "0000000000111000",
      "/* We don't implement cache or tlb, so this is a noop.  */",
    },
! 
!   { "nm", "nm", "mac.l @<REG_M>+,@<REG_N>+", "0000nnnnmmmm1111",
      "macl(&R0,memory,n,m);",
    },
  
!   { "nm", "nm", "mac.w @<REG_M>+,@<REG_N>+", "0100nnnnmmmm1111",
      "macw(&R0,memory,n,m,endianw);",
    },
  
!   { "n", "", "mov #<imm>,<REG_N>", "1110nnnni8*1....",
      "R[n] = SEXT(i);",
    },
!   { "n", "m", "mov <REG_M>,<REG_N>", "0110nnnnmmmm0011",
      "R[n] = R[m];",
    },
  
!   { "0", "", "mov.b @(<disp>,GBR),R0", "11000100i8*1....",
      "MA (1);",
      "R0 = RSBAT (i + GBR);",
!     "L (0);",
    },
!   { "0", "m", "mov.b @(<disp>,<REG_M>),R0", "10000100mmmmi4*1",
      "MA (1);",
      "R0 = RSBAT (i + R[m]);",
!     "L (0);",
    },
!   { "n", "0m", "mov.b @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1100",
      "MA (1);",
      "R[n] = RSBAT (R0 + R[m]);",
!     "L (n);",
    },
!   { "nm", "m", "mov.b @<REG_M>+,<REG_N>", "0110nnnnmmmm0100",
      "MA (1);",
      "R[n] = RSBAT (R[m]);",
      "R[m] += 1;",
!     "L (n);",
    },
!   { "", "mn", "mov.b <REG_M>,@<REG_N>", "0010nnnnmmmm0000",
      "MA (1);",
      "WBAT (R[n], R[m]);",
    },
!   { "", "0", "mov.b R0,@(<disp>,GBR)", "11000000i8*1....",
      "MA (1);",
      "WBAT (i + GBR, R0);",
    },
!   { "", "m0", "mov.b R0,@(<disp>,<REG_M>)", "10000000mmmmi4*1",
      "MA (1);",
      "WBAT (i + R[m], R0);",
    },
!   { "", "mn0", "mov.b <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0100",
      "MA (1);",
      "WBAT (R[n] + R0, R[m]);",
    },
!   { "n", "nm", "mov.b <REG_M>,@-<REG_N>", "0010nnnnmmmm0100",
      "MA (1);",
      "R[n] -= 1;",
      "WBAT (R[n], R[m]);",
    },
!   { "n", "m", "mov.b @<REG_M>,<REG_N>", "0110nnnnmmmm0000",
      "MA (1);",
      "R[n] = RSBAT (R[m]);",
!     "L (n);",
    },
  
!   { "0", "", "mov.l @(<disp>,GBR),R0", "11000110i8*4....",
      "MA (1);",
      "R0 = RLAT (i + GBR);",
!     "L (0);",
    },
!   { "n", "", "mov.l @(<disp>,PC),<REG_N>", "1101nnnni8p4....",
      "MA (1);",
      "R[n] = RLAT ((PH2T (PC) & ~3) + 4 + i);",
!     "L (n);",
    },
!   { "n", "m", "mov.l @(<disp>,<REG_M>),<REG_N>", "0101nnnnmmmmi4*4",
      "MA (1);",
      "R[n] = RLAT (i + R[m]);",
!     "L (n);",
    },
!   { "n", "m0", "mov.l @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1110",
      "MA (1);",
      "R[n] = RLAT (R0 + R[m]);",
!     "L (n);",
    },
!   { "nm", "m", "mov.l @<REG_M>+,<REG_N>", "0110nnnnmmmm0110",
      "MA (1);",
      "R[n] = RLAT (R[m]);",
      "R[m] += 4;",
!     "L (n);",
    },
!   { "n", "m", "mov.l @<REG_M>,<REG_N>", "0110nnnnmmmm0010",
      "MA (1);",
      "R[n] = RLAT (R[m]);",
!     "L (n);",
    },
!   { "", "0", "mov.l R0,@(<disp>,GBR)", "11000010i8*4....",
      "MA (1);",
      "WLAT (i + GBR, R0);",
    },
!   { "", "nm", "mov.l <REG_M>,@(<disp>,<REG_N>)", "0001nnnnmmmmi4*4",
      "MA (1);",
      "WLAT (i + R[n], R[m]);",
    },
!   { "", "nm0", "mov.l <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0110",
      "MA (1);",
      "WLAT (R0 + R[n], R[m]);",
    },
!   { "n", "nm", "mov.l <REG_M>,@-<REG_N>", "0010nnnnmmmm0110",
      "MA (1) ;",
      "R[n] -= 4;",
      "WLAT (R[n], R[m]);",
    },
!   { "", "nm", "mov.l <REG_M>,@<REG_N>", "0010nnnnmmmm0010",
      "MA (1);",
      "WLAT (R[n], R[m]);",
    },
  
!   { "0", "", "mov.w @(<disp>,GBR),R0", "11000101i8*2....",
      "MA (1);",
      "R0 = RSWAT (i + GBR);",
!     "L (0);",
    },
!   { "n", "", "mov.w @(<disp>,PC),<REG_N>", "1001nnnni8p2....",
      "MA (1);",
      "R[n] = RSWAT (PH2T (PC + 4 + i));",
!     "L (n);",
    },
!   { "0", "m", "mov.w @(<disp>,<REG_M>),R0", "10000101mmmmi4*2",
      "MA (1);",
      "R0 = RSWAT (i + R[m]);",
!     "L (0);",
    },
!   { "n", "m0", "mov.w @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1101",
      "MA (1);",
      "R[n] = RSWAT (R0 + R[m]);",
!     "L (n);",
    },
!   { "nm", "n", "mov.w @<REG_M>+,<REG_N>", "0110nnnnmmmm0101",
      "MA (1);",
      "R[n] = RSWAT (R[m]);",
      "R[m] += 2;",
!     "L (n);",
    },
!   { "n", "m", "mov.w @<REG_M>,<REG_N>", "0110nnnnmmmm0001",
      "MA (1);",
      "R[n] = RSWAT (R[m]);",
!     "L (n);",
    },
!   { "", "0", "mov.w R0,@(<disp>,GBR)", "11000001i8*2....",
      "MA (1);",
      "WWAT (i + GBR, R0);",
    },
!   { "", "0m", "mov.w R0,@(<disp>,<REG_M>)", "10000001mmmmi4*2",
      "MA (1);",
      "WWAT (i + R[m], R0);",
    },
!   { "", "m0n", "mov.w <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0101",
      "MA (1);",
      "WWAT (R0 + R[n], R[m]);",
    },
!   { "n", "mn", "mov.w <REG_M>,@-<REG_N>", "0010nnnnmmmm0101",
      "MA (1);",
      "R[n] -= 2;",
      "WWAT (R[n], R[m]);",
    },
!   { "", "nm", "mov.w <REG_M>,@<REG_N>", "0010nnnnmmmm0001",
      "MA (1);",
      "WWAT (R[n], R[m]);",
    },
  
!   { "0", "", "mova @(<disp>,PC),R0", "11000111i8p4....",
      "R0 = ((i + 4 + PH2T (PC)) & ~0x3);",
    },
  
!   { "", "n0", "movca.l R0, @<REG_N>", "0000nnnn11000011",
      "/* We don't simulate cache, so this insn is identical to mov.  */",
      "MA (1);",
      "WLAT (R[n], R[0]);",
    },
  
!   { "n", "", "movt <REG_N>", "0000nnnn00101001",
      "R[n] = T;",
    },
  
!   { "", "mn", "mul.l <REG_M>,<REG_N>", "0000nnnnmmmm0111",
      "MACL = ((int)R[n]) * ((int)R[m]);",
    },
  #if 0
!   { "", "nm", "mul.l <REG_M>,<REG_N>", "0000nnnnmmmm0111",
      "MACL = R[n] * R[m];",
    },
  #endif
  
    /* muls.w - see muls */
!   { "", "mn", "muls <REG_M>,<REG_N>", "0010nnnnmmmm1111",
      "MACL = ((int)(short)R[n]) * ((int)(short)R[m]);",
    },
  
    /* mulu.w - see mulu */
!   { "", "mn", "mulu <REG_M>,<REG_N>", "0010nnnnmmmm1110",
      "MACL = (((unsigned int)(unsigned short)R[n])",
      "        * ((unsigned int)(unsigned short)R[m]));",
    },
  
!   { "n", "m", "neg <REG_M>,<REG_N>", "0110nnnnmmmm1011",
      "R[n] = - R[m];",
    },
  
!   { "n", "m", "negc <REG_M>,<REG_N>", "0110nnnnmmmm1010",
      "ult = -T;",
      "SET_SR_T (ult > 0);",
      "R[n] = ult - R[m];",
      "SET_SR_T (T || (R[n] > ult));",
    },
  
!   { "", "", "nop", "0000000000001001",
      "/* nop */",
    },
  
!   { "n", "m", "not <REG_M>,<REG_N>", "0110nnnnmmmm0111",
      "R[n] = ~R[m];",
    },
  
!   { "", "n", "ocbi @<REG_N>", "0000nnnn10010011",
      "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop.  */",
      "/* FIXME: Cache not implemented */",
    },
  
!   { "", "n", "ocbp @<REG_N>", "0000nnnn10100011",
      "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop.  */",
      "/* FIXME: Cache not implemented */",
    },
  
!   { "", "n", "ocbwb @<REG_N>", "0000nnnn10110011",
      "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop.  */",
      "/* FIXME: Cache not implemented */",
    },
  
!   { "0", "", "or #<imm>,R0", "11001011i8*1....",
      "R0 |= i;",
    },
!   { "n", "m", "or <REG_M>,<REG_N>", "0010nnnnmmmm1011",
      "R[n] |= R[m];",
    },
!   { "", "0", "or.b #<imm>,@(R0,GBR)", "11001111i8*1....",
      "MA (1);",
      "WBAT (R0 + GBR, (RBAT (R0 + GBR) | i));",
    },
  
!   { "", "n", "pref @<REG_N>", "0000nnnn10000011",
      "/* Except for the effect on the cache - which is not simulated -",
      "   this is like a nop.  */",
    },
  
!   { "n", "n", "rotcl <REG_N>", "0100nnnn00100100",
      "ult = R[n] < 0;",
      "R[n] = (R[n] << 1) | T;",
      "SET_SR_T (ult);",
    },
  
!   { "n", "n", "rotcr <REG_N>", "0100nnnn00100101",
      "ult = R[n] & 1;",
      "R[n] = (UR[n] >> 1) | (T << 31);",
      "SET_SR_T (ult);",
    },
  
!   { "n", "n", "rotl <REG_N>", "0100nnnn00000100",
      "SET_SR_T (R[n] < 0);",
      "R[n] <<= 1;",
      "R[n] |= T;",
    },
  
!   { "n", "n", "rotr <REG_N>", "0100nnnn00000101",
      "SET_SR_T (R[n] & 1);",
      "R[n] = UR[n] >> 1;",
      "R[n] |= (T << 31);",
    },
  
!   { "", "", "rte", "0000000000101011", 
  #if 0
      /* SH-[12] */
      "int tmp = PC;",
--- 593,916 ----
  #endif
  
    /* sh-dsp */
!   { "", "", "", "ldre @(<disp>,PC)", "10001110i8p1....",
      "RE = SEXT (i) * 2 + 4 + PH2T (PC);",
    },
!   { "", "", "", "ldrs @(<disp>,PC)", "10001100i8p1....",
      "RS = SEXT (i) * 2 + 4 + PH2T (PC);",
    },
  
!   { "", "co", "n", "lds <REG_N>,<SREG_M>", "0100nnnnssss1010",
      "SREG (m) = R[n];",
    },
!   { "n", "co", "n", "lds.l @<REG_N>+,<SREG_M>", "0100nnnnssss0110",
      "MA (1);",
      "SREG (m) = RLAT(R[n]);",
      "R[n] += 4;",
    },
    /* sh2e / sh-dsp (lds <REG_N>,DSR) */
!   { "", "co", "n", "lds <REG_N>,FPSCR", "0100nnnn01101010",
      "SET_FPSCR(R[n]);",
    },
    /* sh2e / sh-dsp (lds.l @<REG_N>+,DSR) */
!   { "n", "co", "n", "lds.l @<REG_N>+,FPSCR", "0100nnnn01100110",
!     "L_SH4 (fpscr, 4);",
      "MA (1);",
      "SET_FPSCR (RLAT(R[n]));",
      "R[n] += 4;",
    },
  
!   { "", "", "", "ldtlb", "0000000000111000",
      "/* We don't implement cache or tlb, so this is a noop.  */",
    },
!   /* mac / mac doesn't incur an extra latency penalty.  */
!   { "nm", "co", "nm", "mac.l @<REG_M>+,@<REG_N>+", "0000nnnnmmmm1111",
!     "cycles++;",
      "macl(&R0,memory,n,m);",
    },
  
!   { "nm", "co", "nm", "mac.w @<REG_M>+,@<REG_N>+", "0100nnnnmmmm1111",
!     "cycles++;",
      "macw(&R0,memory,n,m,endianw);",
    },
  
!   { "n", "ex", "", "mov #<imm>,<REG_N>", "1110nnnni8*1....",
      "R[n] = SEXT(i);",
    },
!   { "n", "mt", "m", "mov <REG_M>,<REG_N>", "0110nnnnmmmm0011",
      "R[n] = R[m];",
    },
  
!   { "0", "ld", "", "mov.b @(<disp>,GBR),R0", "11000100i8*1....",
      "MA (1);",
      "R0 = RSBAT (i + GBR);",
!     "L (R[0]);",
    },
!   { "0", "ld", "m", "mov.b @(<disp>,<REG_M>),R0", "10000100mmmmi4*1",
      "MA (1);",
      "R0 = RSBAT (i + R[m]);",
!     "L (R[0]);",
    },
!   { "n", "ld", "0m", "mov.b @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1100",
      "MA (1);",
      "R[n] = RSBAT (R0 + R[m]);",
!     "L (R[n]);",
    },
!   { "nm", "ld", "m", "mov.b @<REG_M>+,<REG_N>", "0110nnnnmmmm0100",
      "MA (1);",
      "R[n] = RSBAT (R[m]);",
      "R[m] += 1;",
!     "L (R[n]);",
    },
!   { "", "ls", "mn", "mov.b <REG_M>,@<REG_N>", "0010nnnnmmmm0000",
      "MA (1);",
      "WBAT (R[n], R[m]);",
    },
!   { "", "ls", "0", "mov.b R0,@(<disp>,GBR)", "11000000i8*1....",
      "MA (1);",
      "WBAT (i + GBR, R0);",
    },
!   { "", "ls", "m0", "mov.b R0,@(<disp>,<REG_M>)", "10000000mmmmi4*1",
      "MA (1);",
      "WBAT (i + R[m], R0);",
    },
!   { "", "ls", "mn0", "mov.b <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0100",
      "MA (1);",
      "WBAT (R[n] + R0, R[m]);",
    },
!   { "n", "ls", "nm", "mov.b <REG_M>,@-<REG_N>", "0010nnnnmmmm0100",
      "MA (1);",
      "R[n] -= 1;",
      "WBAT (R[n], R[m]);",
    },
!   { "n", "ld", "m", "mov.b @<REG_M>,<REG_N>", "0110nnnnmmmm0000",
      "MA (1);",
      "R[n] = RSBAT (R[m]);",
!     "L (R[n]);",
    },
  
!   { "0", "ld", "", "mov.l @(<disp>,GBR),R0", "11000110i8*4....",
      "MA (1);",
      "R0 = RLAT (i + GBR);",
!     "L (R[0]);",
    },
!   { "n", "ld", "", "mov.l @(<disp>,PC),<REG_N>", "1101nnnni8p4....",
      "MA (1);",
      "R[n] = RLAT ((PH2T (PC) & ~3) + 4 + i);",
!     "L (R[n]);",
    },
!   { "n", "ld", "m", "mov.l @(<disp>,<REG_M>),<REG_N>", "0101nnnnmmmmi4*4",
      "MA (1);",
      "R[n] = RLAT (i + R[m]);",
!     "L (R[n]);",
    },
!   { "n", "ld", "m0", "mov.l @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1110",
      "MA (1);",
      "R[n] = RLAT (R0 + R[m]);",
!     "L (R[n]);",
    },
!   { "nm", "ld", "m", "mov.l @<REG_M>+,<REG_N>", "0110nnnnmmmm0110",
      "MA (1);",
      "R[n] = RLAT (R[m]);",
      "R[m] += 4;",
!     "L (R[n]);",
    },
!   { "n", "ld", "m", "mov.l @<REG_M>,<REG_N>", "0110nnnnmmmm0010",
      "MA (1);",
      "R[n] = RLAT (R[m]);",
!     "L (R[n]);",
    },
!   { "", "ls", "0", "mov.l R0,@(<disp>,GBR)", "11000010i8*4....",
      "MA (1);",
      "WLAT (i + GBR, R0);",
    },
!   { "", "ls", "nm", "mov.l <REG_M>,@(<disp>,<REG_N>)", "0001nnnnmmmmi4*4",
      "MA (1);",
      "WLAT (i + R[n], R[m]);",
    },
!   { "", "ls", "nm0", "mov.l <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0110",
      "MA (1);",
      "WLAT (R0 + R[n], R[m]);",
    },
!   { "n", "ls", "nm", "mov.l <REG_M>,@-<REG_N>", "0010nnnnmmmm0110",
      "MA (1) ;",
      "R[n] -= 4;",
      "WLAT (R[n], R[m]);",
    },
!   { "", "ls", "nm", "mov.l <REG_M>,@<REG_N>", "0010nnnnmmmm0010",
      "MA (1);",
      "WLAT (R[n], R[m]);",
    },
  
!   { "0", "ld", "", "mov.w @(<disp>,GBR),R0", "11000101i8*2....",
      "MA (1);",
      "R0 = RSWAT (i + GBR);",
!     "L (R[0]);",
    },
!   { "n", "ld", "", "mov.w @(<disp>,PC),<REG_N>", "1001nnnni8p2....",
      "MA (1);",
      "R[n] = RSWAT (PH2T (PC + 4 + i));",
!     "L (R[n]);",
    },
!   { "0", "ld", "m", "mov.w @(<disp>,<REG_M>),R0", "10000101mmmmi4*2",
      "MA (1);",
      "R0 = RSWAT (i + R[m]);",
!     "L (R[0]);",
    },
!   { "n", "ld", "m0", "mov.w @(R0,<REG_M>),<REG_N>", "0000nnnnmmmm1101",
      "MA (1);",
      "R[n] = RSWAT (R0 + R[m]);",
!     "L (R[n]);",
    },
!   { "nm", "ld", "n", "mov.w @<REG_M>+,<REG_N>", "0110nnnnmmmm0101",
      "MA (1);",
      "R[n] = RSWAT (R[m]);",
      "R[m] += 2;",
!     "L (R[n]);",
    },
!   { "n", "ld", "m", "mov.w @<REG_M>,<REG_N>", "0110nnnnmmmm0001",
      "MA (1);",
      "R[n] = RSWAT (R[m]);",
!     "L (R[n]);",
    },
!   { "", "ls", "0", "mov.w R0,@(<disp>,GBR)", "11000001i8*2....",
      "MA (1);",
      "WWAT (i + GBR, R0);",
    },
!   { "", "ls", "0m", "mov.w R0,@(<disp>,<REG_M>)", "10000001mmmmi4*2",
      "MA (1);",
      "WWAT (i + R[m], R0);",
    },
!   { "", "ls", "m0n", "mov.w <REG_M>,@(R0,<REG_N>)", "0000nnnnmmmm0101",
      "MA (1);",
      "WWAT (R0 + R[n], R[m]);",
    },
!   { "n", "ls", "mn", "mov.w <REG_M>,@-<REG_N>", "0010nnnnmmmm0101",
      "MA (1);",
      "R[n] -= 2;",
      "WWAT (R[n], R[m]);",
    },
!   { "", "ls", "nm", "mov.w <REG_M>,@<REG_N>", "0010nnnnmmmm0001",
      "MA (1);",
      "WWAT (R[n], R[m]);",
    },
  
!   { "0", "ex", "", "mova @(<disp>,PC),R0", "11000111i8p4....",
      "R0 = ((i + 4 + PH2T (PC)) & ~0x3);",
    },
  
!   { "", "ls", "n0", "movca.l R0, @<REG_N>", "0000nnnn11000011",
      "/* We don't simulate cache, so this insn is identical to mov.  */",
      "MA (1);",
      "WLAT (R[n], R[0]);",
    },
  
!   { "n", "ex", "", "movt <REG_N>", "0000nnnn00101001",
      "R[n] = T;",
    },
  
!   { "", "co", "mn", "mul.l <REG_M>,<REG_N>", "0000nnnnmmmm0111",
!     "L_SH4 (macl, 4);",
!     "cycles++;",
      "MACL = ((int)R[n]) * ((int)R[m]);",
    },
  #if 0
!   { "", "co", "nm", "mul.l <REG_M>,<REG_N>", "0000nnnnmmmm0111",
      "MACL = R[n] * R[m];",
    },
  #endif
  
    /* muls.w - see muls */
!   { "", "co", "mn", "muls <REG_M>,<REG_N>", "0010nnnnmmmm1111",
!     "L_SH4 (macl, 4);",
!     "cycles++;",
      "MACL = ((int)(short)R[n]) * ((int)(short)R[m]);",
    },
  
    /* mulu.w - see mulu */
!   { "", "co", "mn", "mulu <REG_M>,<REG_N>", "0010nnnnmmmm1110",
!     "L_SH4 (macl, 4);",
!     "cycles++;",
      "MACL = (((unsigned int)(unsigned short)R[n])",
      "        * ((unsigned int)(unsigned short)R[m]));",
    },
  
!   { "n", "ex", "m", "neg <REG_M>,<REG_N>", "0110nnnnmmmm1011",
      "R[n] = - R[m];",
    },
  
!   { "nt", "ex", "mt", "negc <REG_M>,<REG_N>", "0110nnnnmmmm1010",
      "ult = -T;",
      "SET_SR_T (ult > 0);",
      "R[n] = ult - R[m];",
      "SET_SR_T (T || (R[n] > ult));",
    },
  
!   { "", "mt", "", "nop", "0000000000001001",
      "/* nop */",
    },
  
!   { "n", "ex", "m", "not <REG_M>,<REG_N>", "0110nnnnmmmm0111",
      "R[n] = ~R[m];",
    },
  
!   { "", "ls", "n", "ocbi @<REG_N>", "0000nnnn10010011",
      "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop.  */",
      "/* FIXME: Cache not implemented */",
    },
  
!   { "", "ls", "n", "ocbp @<REG_N>", "0000nnnn10100011",
      "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop.  */",
      "/* FIXME: Cache not implemented */",
    },
  
!   { "", "ls", "n", "ocbwb @<REG_N>", "0000nnnn10110011",
      "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop.  */",
      "/* FIXME: Cache not implemented */",
    },
  
!   { "0", "ex", "", "or #<imm>,R0", "11001011i8*1....",
      "R0 |= i;",
    },
!   { "n", "ex", "m", "or <REG_M>,<REG_N>", "0010nnnnmmmm1011",
      "R[n] |= R[m];",
    },
!   { "", "co", "0", "or.b #<imm>,@(R0,GBR)", "11001111i8*1....",
      "MA (1);",
+     "cycles += 3;",
      "WBAT (R0 + GBR, (RBAT (R0 + GBR) | i));",
    },
  
!   { "", "ls", "n", "pref @<REG_N>", "0000nnnn10000011",
      "/* Except for the effect on the cache - which is not simulated -",
      "   this is like a nop.  */",
    },
  
!   { "nt", "ex", "nt", "rotcl <REG_N>", "0100nnnn00100100",
      "ult = R[n] < 0;",
      "R[n] = (R[n] << 1) | T;",
      "SET_SR_T (ult);",
    },
  
!   { "nt", "ex", "nt", "rotcr <REG_N>", "0100nnnn00100101",
      "ult = R[n] & 1;",
      "R[n] = (UR[n] >> 1) | (T << 31);",
      "SET_SR_T (ult);",
    },
  
!   { "nt", "ex", "n", "rotl <REG_N>", "0100nnnn00000100",
      "SET_SR_T (R[n] < 0);",
      "R[n] <<= 1;",
      "R[n] |= T;",
    },
  
!   { "nt", "ex", "n", "rotr <REG_N>", "0100nnnn00000101",
      "SET_SR_T (R[n] & 1);",
      "R[n] = UR[n] >> 1;",
      "R[n] |= (T << 31);",
    },
  
!   { "", "co", "", "rte", "0000000000101011", 
  #if 0
      /* SH-[12] */
      "int tmp = PC;",
*************** op tab[] =
*** 868,889 ****
  #else
      "SET_SR (SSR);",
      "SET_NIP (PT2H (SPC));",
!     "cycles += 2;",
      "Delay_Slot (PC + 2);",
  #endif
    },
  
!   { "", "", "rts", "0000000000001011",
      "SET_NIP (PT2H (PR));",
      "cycles += 2;",
      "Delay_Slot (PC + 2);",
    },
  
    /* sh-dsp */
!   { "", "n", "setrc <REG_N>", "0100nnnn00010100",
      "SET_RC (R[n]);",
    },
!   { "", "", "setrc #<imm>", "10000010i8*1....",
      /* It would be more realistic to let loop_start point to some static
         memory that contains an illegal opcode and then give a bus error when
         the loop is eventually encountered, but it seems not only simpler,
--- 922,943 ----
  #else
      "SET_SR (SSR);",
      "SET_NIP (PT2H (SPC));",
!     "cycles += 4;",
      "Delay_Slot (PC + 2);",
  #endif
    },
  
!   { "", "co", "", "rts", "0000000000001011",
      "SET_NIP (PT2H (PR));",
      "cycles += 2;",
      "Delay_Slot (PC + 2);",
    },
  
    /* sh-dsp */
!   { "", "", "n", "setrc <REG_N>", "0100nnnn00010100",
      "SET_RC (R[n]);",
    },
!   { "", "", "", "setrc #<imm>", "10000010i8*1....",
      /* It would be more realistic to let loop_start point to some static
         memory that contains an illegal opcode and then give a bus error when
         the loop is eventually encountered, but it seems not only simpler,
*************** op tab[] =
*** 897,1037 ****
      "}",
    },
  
!   { "", "", "sets", "0000000001011000",
      "SET_SR_S (1);",
    },
  
!   { "", "", "sett", "0000000000011000",
      "SET_SR_T (1);",
    },
  
!   { "n", "mn", "shad <REG_M>,<REG_N>", "0100nnnnmmmm1100",
      "R[n] = (R[m] < 0) ? (R[n] >> ((-R[m])&0x1f)) : (R[n] << (R[m] & 0x1f));",
    },
  
!   { "n", "n", "shal <REG_N>", "0100nnnn00100000",
      "SET_SR_T (R[n] < 0);",
      "R[n] <<= 1;",
    },
  
!   { "n", "n", "shar <REG_N>", "0100nnnn00100001",
      "SET_SR_T (R[n] & 1);",
      "R[n] = R[n] >> 1;",
    },
  
!   { "n", "mn", "shld <REG_M>,<REG_N>", "0100nnnnmmmm1101",
      "R[n] = (R[m] < 0) ? (UR[n] >> ((-R[m])&0x1f)): (R[n] << (R[m] & 0x1f));",
    },
  
!   { "n", "n", "shll <REG_N>", "0100nnnn00000000",
      "SET_SR_T (R[n] < 0);",
      "R[n] <<= 1;",
    },
  
!   { "n", "n", "shll2 <REG_N>", "0100nnnn00001000",
      "R[n] <<= 2;",
    },
!   { "n", "n", "shll8 <REG_N>", "0100nnnn00011000",
      "R[n] <<= 8;",
    },
!   { "n", "n", "shll16 <REG_N>", "0100nnnn00101000",
      "R[n] <<= 16;",
    },
  
!   { "n", "n", "shlr <REG_N>", "0100nnnn00000001",
      "SET_SR_T (R[n] & 1);",
      "R[n] = UR[n] >> 1;",
    },
  
!   { "n", "n", "shlr2 <REG_N>", "0100nnnn00001001",
      "R[n] = UR[n] >> 2;",
    },
!   { "n", "n", "shlr8 <REG_N>", "0100nnnn00011001",
      "R[n] = UR[n] >> 8;",
    },
!   { "n", "n", "shlr16 <REG_N>", "0100nnnn00101001",
      "R[n] = UR[n] >> 16;",
    },
  
!   { "", "", "sleep", "0000000000011011",
      "nip += trap (0xc3, R0, PC, memory, maskl, maskw, endianw);",
    },
  
!   { "n", "", "stc <CREG_M>,<REG_N>", "0000nnnnmmmm0010",
      "R[n] = CREG (m);",
    },
  
  #if 0
!   { "n", "", "stc SGR,<REG_N>", "0000nnnn00111010",
      "R[n] = SGR;",
    },
!   { "n", "", "stc DBR,<REG_N>", "0000nnnn11111010",
      "R[n] = DBR;",
    },
  #endif
!   { "n", "n", "stc.l <CREG_M>,@-<REG_N>", "0100nnnnmmmm0011",
      "MA (1);",
      "R[n] -= 4;",
      "WLAT (R[n], CREG (m));",
    },
  #if 0
!   { "n", "n", "stc.l SGR,@-<REG_N>", "0100nnnn00110010",
      "MA (1);",
      "R[n] -= 4;",
      "WLAT (R[n], SGR);",
    },
!   { "n", "n", "stc.l DBR,@-<REG_N>", "0100nnnn11110010",
      "MA (1);",
      "R[n] -= 4;",
      "WLAT (R[n], DBR);",
    },
  #endif
  
!   { "n", "", "sts <SREG_M>,<REG_N>", "0000nnnnssss1010",
      "R[n] = SREG (m);",
    },
!   { "n", "n", "sts.l <SREG_M>,@-<REG_N>", "0100nnnnssss0010",
      "MA (1);",
      "R[n] -= 4;",
      "WLAT (R[n], SREG (m));",
    },
  
!   { "n", "nm", "sub <REG_M>,<REG_N>", "0011nnnnmmmm1000",
      "R[n] -= R[m];",
    },
  
!   { "n", "nm", "subc <REG_M>,<REG_N>", "0011nnnnmmmm1010",
      "ult = R[n] - T;",
      "SET_SR_T (ult > R[n]);",
      "R[n] = ult - R[m];",
      "SET_SR_T (T || (R[n] > ult));",
    },
  
!   { "n", "nm", "subv <REG_M>,<REG_N>", "0011nnnnmmmm1011",
      "ult = R[n] - R[m];",
      "SET_SR_T (((R[n] ^ R[m]) & (ult ^ R[n])) >> 31);",
      "R[n] = ult;",
    },
  
!   { "n", "nm", "swap.b <REG_M>,<REG_N>", "0110nnnnmmmm1000",
      "R[n] = ((R[m] & 0xffff0000)",
      "        | ((R[m] << 8) & 0xff00)",
      "        | ((R[m] >> 8) & 0x00ff));",
    },
!   { "n", "nm", "swap.w <REG_M>,<REG_N>", "0110nnnnmmmm1001",
      "R[n] = (((R[m] << 16) & 0xffff0000)",
      "        | ((R[m] >> 16) & 0x00ffff));",
    },
  
!   { "", "n", "tas.b @<REG_N>", "0100nnnn00011011",
      "MA (1);",
      "ult = RBAT(R[n]);",
      "SET_SR_T (ult == 0);",
      "WBAT(R[n],ult|0x80);",
    },
  
!   { "0", "", "trapa #<imm>", "11000011i8*1....", 
      "long imm = 0xff & i;",
      "if (i < 20 || i == 33 || i == 34 || i == 0xc3)",
      "  nip += trap (i, R, PC, memory, maskl, maskw,endianw);",
  #if 0
--- 951,1102 ----
      "}",
    },
  
!   { "", "co", "", "sets", "0000000001011000",
      "SET_SR_S (1);",
    },
  
!   { "t", "mt", "", "sett", "0000000000011000",
      "SET_SR_T (1);",
    },
  
!   { "n", "ex", "mn", "shad <REG_M>,<REG_N>", "0100nnnnmmmm1100",
      "R[n] = (R[m] < 0) ? (R[n] >> ((-R[m])&0x1f)) : (R[n] << (R[m] & 0x1f));",
    },
  
!   { "nt", "ex", "n", "shal <REG_N>", "0100nnnn00100000",
      "SET_SR_T (R[n] < 0);",
      "R[n] <<= 1;",
    },
  
!   { "nt", "ex", "n", "shar <REG_N>", "0100nnnn00100001",
      "SET_SR_T (R[n] & 1);",
      "R[n] = R[n] >> 1;",
    },
  
!   { "n", "ex", "mn", "shld <REG_M>,<REG_N>", "0100nnnnmmmm1101",
      "R[n] = (R[m] < 0) ? (UR[n] >> ((-R[m])&0x1f)): (R[n] << (R[m] & 0x1f));",
    },
  
!   { "nt", "ex", "n", "shll <REG_N>", "0100nnnn00000000",
      "SET_SR_T (R[n] < 0);",
      "R[n] <<= 1;",
    },
  
!   { "n", "ex", "n", "shll2 <REG_N>", "0100nnnn00001000",
      "R[n] <<= 2;",
    },
!   { "n", "ex", "n", "shll8 <REG_N>", "0100nnnn00011000",
      "R[n] <<= 8;",
    },
!   { "n", "ex", "n", "shll16 <REG_N>", "0100nnnn00101000",
      "R[n] <<= 16;",
    },
  
!   { "nt", "ex", "n", "shlr <REG_N>", "0100nnnn00000001",
      "SET_SR_T (R[n] & 1);",
      "R[n] = UR[n] >> 1;",
    },
  
!   { "n", "ex", "n", "shlr2 <REG_N>", "0100nnnn00001001",
      "R[n] = UR[n] >> 2;",
    },
!   { "n", "ex", "n", "shlr8 <REG_N>", "0100nnnn00011001",
      "R[n] = UR[n] >> 8;",
    },
!   { "n", "ex", "n", "shlr16 <REG_N>", "0100nnnn00101001",
      "R[n] = UR[n] >> 16;",
    },
  
!   { "", "co", "", "sleep", "0000000000011011",
!     "cycles += 3;",
      "nip += trap (0xc3, R0, PC, memory, maskl, maskw, endianw);",
    },
  
!   { "n", "co", "", "stc <CREG_M>,<REG_N>", "0000nnnnmmmm0010",
!     "cycles++;",
      "R[n] = CREG (m);",
    },
  
  #if 0
!   { "n", "co", "", "stc SGR,<REG_N>", "0000nnnn00111010",
!     "cycles += 2;",
      "R[n] = SGR;",
    },
!   { "n", "co", "", "stc DBR,<REG_N>", "0000nnnn11111010",
!     "cycles++;",
      "R[n] = DBR;",
    },
  #endif
!   { "n", "co", "n", "stc.l <CREG_M>,@-<REG_N>", "0100nnnnmmmm0011",
      "MA (1);",
+     "cycles++;",
      "R[n] -= 4;",
      "WLAT (R[n], CREG (m));",
    },
  #if 0
!   { "n", "co", "n", "stc.l SGR,@-<REG_N>", "0100nnnn00110010",
      "MA (1);",
+     "cycles += 2;",
      "R[n] -= 4;",
      "WLAT (R[n], SGR);",
    },
!   { "n", "co", "n", "stc.l DBR,@-<REG_N>", "0100nnnn11110010",
      "MA (1);",
+     "cycles++;",
      "R[n] -= 4;",
      "WLAT (R[n], DBR);",
    },
  #endif
  
!   { "n", "co", "", "sts <SREG_M>,<REG_N>", "0000nnnnssss1010",
!     "L_SH4 (R[n], 3);", /* This is the mach / macl timing.  */
      "R[n] = SREG (m);",
    },
!   { "n", "co", "n", "sts.l <SREG_M>,@-<REG_N>", "0100nnnnssss0010",
      "MA (1);",
+     "cycles++;", /* This is the PR timing.  */
      "R[n] -= 4;",
      "WLAT (R[n], SREG (m));",
    },
  
!   { "n", "ex", "nm", "sub <REG_M>,<REG_N>", "0011nnnnmmmm1000",
      "R[n] -= R[m];",
    },
  
!   { "nt", "ex", "nmt", "subc <REG_M>,<REG_N>", "0011nnnnmmmm1010",
      "ult = R[n] - T;",
      "SET_SR_T (ult > R[n]);",
      "R[n] = ult - R[m];",
      "SET_SR_T (T || (R[n] > ult));",
    },
  
!   { "nt", "ex", "nm", "subv <REG_M>,<REG_N>", "0011nnnnmmmm1011",
      "ult = R[n] - R[m];",
      "SET_SR_T (((R[n] ^ R[m]) & (ult ^ R[n])) >> 31);",
      "R[n] = ult;",
    },
  
!   { "n", "ex", "nm", "swap.b <REG_M>,<REG_N>", "0110nnnnmmmm1000",
      "R[n] = ((R[m] & 0xffff0000)",
      "        | ((R[m] << 8) & 0xff00)",
      "        | ((R[m] >> 8) & 0x00ff));",
    },
!   { "n", "ex", "nm", "swap.w <REG_M>,<REG_N>", "0110nnnnmmmm1001",
      "R[n] = (((R[m] << 16) & 0xffff0000)",
      "        | ((R[m] >> 16) & 0x00ffff));",
    },
  
!   { "", "co", "n", "tas.b @<REG_N>", "0100nnnn00011011",
      "MA (1);",
+     "cycles += 4;",
      "ult = RBAT(R[n]);",
      "SET_SR_T (ult == 0);",
      "WBAT(R[n],ult|0x80);",
    },
  
!   { "0", "co", "", "trapa #<imm>", "11000011i8*1....", 
      "long imm = 0xff & i;",
+     "cycles += 6;",
      "if (i < 20 || i == 33 || i == 34 || i == 0xc3)",
      "  nip += trap (i, R, PC, memory, maskl, maskw,endianw);",
  #if 0
*************** op tab[] =
*** 1052,1082 ****
      "}",
    },
  
!   { "", "mn", "tst <REG_M>,<REG_N>", "0010nnnnmmmm1000",
      "SET_SR_T ((R[n] & R[m]) == 0);",
    },
!   { "", "0", "tst #<imm>,R0", "11001000i8*1....",
      "SET_SR_T ((R0 & i) == 0);",
    },
!   { "", "0", "tst.b #<imm>,@(R0,GBR)", "11001100i8*1....",
      "MA (1);",
      "SET_SR_T ((RBAT (GBR+R0) & i) == 0);",
    },
  
!   { "", "0", "xor #<imm>,R0", "11001010i8*1....",
      "R0 ^= i;",
    },
!   { "n", "mn", "xor <REG_M>,<REG_N>", "0010nnnnmmmm1010",
      "R[n] ^= R[m];",
    },
!   { "", "0", "xor.b #<imm>,@(R0,GBR)", "11001110i8*1....",
      "MA (1);",
      "ult = RBAT (GBR+R0);",
      "ult ^= i;",
      "WBAT (GBR + R0, ult);",
    },
  
!   { "n", "nm", "xtrct <REG_M>,<REG_N>", "0010nnnnmmmm1101",
      "R[n] = (((R[n] >> 16) & 0xffff)",
      "        | ((R[m] << 16) & 0xffff0000));",
    },
--- 1117,1148 ----
      "}",
    },
  
!   { "t", "mt", "mn", "tst <REG_M>,<REG_N>", "0010nnnnmmmm1000",
      "SET_SR_T ((R[n] & R[m]) == 0);",
    },
!   { "t", "mt", "0", "tst #<imm>,R0", "11001000i8*1....",
      "SET_SR_T ((R0 & i) == 0);",
    },
!   { "t", "mt", "0", "tst.b #<imm>,@(R0,GBR)", "11001100i8*1....",
      "MA (1);",
      "SET_SR_T ((RBAT (GBR+R0) & i) == 0);",
    },
  
!   { "0", "ex", "0", "xor #<imm>,R0", "11001010i8*1....",
      "R0 ^= i;",
    },
!   { "n", "ex", "mn", "xor <REG_M>,<REG_N>", "0010nnnnmmmm1010",
      "R[n] ^= R[m];",
    },
!   { "", "co", "0", "xor.b #<imm>,@(R0,GBR)", "11001110i8*1....",
      "MA (1);",
+     "cycles += 3;",
      "ult = RBAT (GBR+R0);",
      "ult ^= i;",
      "WBAT (GBR + R0, ult);",
    },
  
!   { "n", "ex", "nm", "xtrct <REG_M>,<REG_N>", "0010nnnnmmmm1101",
      "R[n] = (((R[n] >> 16) & 0xffff)",
      "        | ((R[m] << 16) & 0xffff0000));",
    },
*************** op movsxy_tab[] =
*** 1098,1298 ****
     450 MHz PIII - 9% with ACE_FAST.
     Maybe we should have separate simulator loops?  */
  #if 1
!   { "n", "n", "movs.w @-<REG_N>,<DSP_REG_M>", "111101NNMMMM0000",
      "MA (1);",
      "R[n] -= 2;",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
    },
!   { "", "n",  "movs.w @<REG_N>,<DSP_REG_M>",  "111101NNMMMM0100",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
    },
!   { "n", "n", "movs.w @<REG_N>+,<DSP_REG_M>", "111101NNMMMM1000",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
      "R[n] += 2;",
    },
!   { "n", "n8","movs.w @<REG_N>+REG_8,<DSP_REG_M>", "111101NNMMMM1100",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
      "R[n] += R[8];",
    },
!   { "n", "n", "movs.w @-<REG_N>,<DSP_GRD_M>", "111101NNGGGG0000",
      "MA (1);",
      "R[n] -= 2;",
      "DSP_R (m) = RSWAT (R[n]);",
    },
!   { "", "n",  "movs.w @<REG_N>,<DSP_GRD_M>",  "111101NNGGGG0100",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]);",
    },
!   { "n", "n", "movs.w @<REG_N>+,<DSP_GRD_M>", "111101NNGGGG1000",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]);",
      "R[n] += 2;",
    },
!   { "n", "n8","movs.w @<REG_N>+REG_8,<DSP_GRD_M>", "111101NNGGGG1100",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]);",
      "R[n] += R[8];",
    },
!   { "n", "n", "movs.w <DSP_REG_M>,@-<REG_N>", "111101NNMMMM0001",
      "MA (1);",
      "R[n] -= 2;",
      "WWAT (R[n], DSP_R (m) >> 16);",
    },
!   { "", "n",  "movs.w <DSP_REG_M>,@<REG_N>",  "111101NNMMMM0101",
      "MA (1);",
      "WWAT (R[n], DSP_R (m) >> 16);",
    },
!   { "n", "n", "movs.w <DSP_REG_M>,@<REG_N>+", "111101NNMMMM1001",
      "MA (1);",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += 2;",
    },
!   { "n", "n8","movs.w <DSP_REG_M>,@<REG_N>+REG_8", "111101NNMMMM1101",
      "MA (1);",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += R[8];",
    },
!   { "n", "n", "movs.w <DSP_GRD_M>,@-<REG_N>", "111101NNGGGG0001",
      "MA (1);",
      "R[n] -= 2;",
      "WWAT (R[n], SEXT (DSP_R (m)));",
    },
!   { "", "n",  "movs.w <DSP_GRD_M>,@<REG_N>",  "111101NNGGGG0101",
      "MA (1);",
      "WWAT (R[n], SEXT (DSP_R (m)));",
    },
!   { "n", "n", "movs.w <DSP_GRD_M>,@<REG_N>+", "111101NNGGGG1001",
      "MA (1);",
      "WWAT (R[n], SEXT (DSP_R (m)));",
      "R[n] += 2;",
    },
!   { "n", "n8","movs.w <DSP_GRD_M>,@<REG_N>+REG_8", "111101NNGGGG1101",
      "MA (1);",
      "WWAT (R[n], SEXT (DSP_R (m)));",
      "R[n] += R[8];",
    },
!   { "n", "n", "movs.l @-<REG_N>,<DSP_REG_M>", "111101NNMMMM0010",
      "MA (1);",
      "R[n] -= 4;",
      "DSP_R (m) = RLAT (R[n]);",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
    },
!   { "", "n",  "movs.l @<REG_N>,<DSP_REG_M>",  "111101NNMMMM0110",
      "MA (1);",
      "DSP_R (m) = RLAT (R[n]);",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
    },
!   { "n", "n", "movs.l @<REG_N>+,<DSP_REG_M>", "111101NNMMMM1010",
      "MA (1);",
      "DSP_R (m) = RLAT (R[n]);",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
      "R[n] += 4;",
    },
!   { "n", "n8","movs.l @<REG_N>+REG_8,<DSP_REG_M>", "111101NNMMMM1110",
      "MA (1);",
      "DSP_R (m) = RLAT (R[n]);",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
      "R[n] += R[8];",
    },
!   { "n", "n", "movs.l <DSP_REG_M>,@-<REG_N>", "111101NNMMMM0011",
      "MA (1);",
      "R[n] -= 4;",
      "WLAT (R[n], DSP_R (m));",
    },
!   { "", "n",  "movs.l <DSP_REG_M>,@<REG_N>",  "111101NNMMMM0111",
      "MA (1);",
      "WLAT (R[n], DSP_R (m));",
    },
!   { "n", "n", "movs.l <DSP_REG_M>,@<REG_N>+", "111101NNMMMM1011",
      "MA (1);",
      "WLAT (R[n], DSP_R (m));",
      "R[n] += 4;",
    },
!   { "n", "n8","movs.l <DSP_REG_M>,@<REG_N>+REG_8", "111101NNMMMM1111",
      "MA (1);",
      "WLAT (R[n], DSP_R (m));",
      "R[n] += R[8];",
    },
!   { "n", "n", "movs.l <DSP_GRD_M>,@-<REG_N>", "111101NNGGGG0011",
      "MA (1);",
      "R[n] -= 4;",
      "WLAT (R[n], SEXT (DSP_R (m)));",
    },
!   { "", "n",  "movs.l <DSP_GRD_M>,@<REG_N>",  "111101NNGGGG0111",
      "MA (1);",
      "WLAT (R[n], SEXT (DSP_R (m)));",
    },
!   { "n", "n", "movs.l <DSP_GRD_M>,@<REG_N>+", "111101NNGGGG1011",
      "MA (1);",
      "WLAT (R[n], SEXT (DSP_R (m)));",
      "R[n] += 4;",
    },
!   { "n", "n8","movs.l <DSP_GRD_M>,@<REG_N>+REG_8", "111101NNGGGG1111",
      "MA (1);",
      "WLAT (R[n], SEXT (DSP_R (m)));",
      "R[n] += R[8];",
    },
!   { "", "n", "movx.w @<REG_x>,<DSP_XX>",   "111100xxXX000100",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "iword &= 0xfd53; goto top;",
    },
!   { "n", "n", "movx.w @<REG_x>+,<DSP_XX>", "111100xxXX001000",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;",
      "iword &= 0xfd53; goto top;",
    },
!   { "n", "n8","movx.w @<REG_x>+REG_8,<DSP_XX>", "111100xxXX001100",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
      "iword &= 0xfd53; goto top;",
    },
!   { "", "n", "movx.w <DSP_Aa>,@<REG_x>",   "111100xxaa100100",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "iword &= 0xfd53; goto top;",
    },
!   { "n", "n", "movx.w <DSP_Aa>,@<REG_x>+", "111100xxaa101000",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;",
      "iword &= 0xfd53; goto top;",
    },
!   { "n", "n8","movx.w <DSP_Aa>,@<REG_x>+REG_8","111100xxaa101100",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
      "iword &= 0xfd53; goto top;",
    },
!   { "", "n", "movy.w @<REG_y>,<DSP_YY>",   "111100yyYY000001",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
    },
!   { "n", "n", "movy.w @<REG_y>+,<DSP_YY>", "111100yyYY000010",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;",
    },
!   { "n", "n9","movy.w @<REG_y>+REG_9,<DSP_YY>", "111100yyYY000011",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
    },
!   { "", "n", "movy.w <DSP_Aa>,@<REG_y>",   "111100yyAA010001",
      "WWAT (R[n], DSP_R (m) >> 16);",
    },
!   { "n", "n", "movy.w <DSP_Aa>,@<REG_y>+", "111100yyAA010010",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;",
    },
!   { "n", "n9", "movy.w <DSP_Aa>,@<REG_y>+REG_9", "111100yyAA010011",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
    },
!   { "", "", "nopx nopy", "1111000000000000",
      "/* nop */",
    },
!   { "", "", "ppi", "1111100000000000",
      "ppi_insn (RIAT (nip));",
      "nip += 2;",
      "iword &= 0xf7ff; goto top;",
--- 1164,1364 ----
     450 MHz PIII - 9% with ACE_FAST.
     Maybe we should have separate simulator loops?  */
  #if 1
!   { "n", "", "n", "movs.w @-<REG_N>,<DSP_REG_M>", "111101NNMMMM0000",
      "MA (1);",
      "R[n] -= 2;",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
    },
!   { "", "", "n",  "movs.w @<REG_N>,<DSP_REG_M>",  "111101NNMMMM0100",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
    },
!   { "n", "", "n", "movs.w @<REG_N>+,<DSP_REG_M>", "111101NNMMMM1000",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
      "R[n] += 2;",
    },
!   { "n", "", "n8","movs.w @<REG_N>+REG_8,<DSP_REG_M>", "111101NNMMMM1100",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
      "R[n] += R[8];",
    },
!   { "n", "", "n", "movs.w @-<REG_N>,<DSP_GRD_M>", "111101NNGGGG0000",
      "MA (1);",
      "R[n] -= 2;",
      "DSP_R (m) = RSWAT (R[n]);",
    },
!   { "", "", "n",  "movs.w @<REG_N>,<DSP_GRD_M>",  "111101NNGGGG0100",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]);",
    },
!   { "n", "", "n", "movs.w @<REG_N>+,<DSP_GRD_M>", "111101NNGGGG1000",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]);",
      "R[n] += 2;",
    },
!   { "n", "", "n8","movs.w @<REG_N>+REG_8,<DSP_GRD_M>", "111101NNGGGG1100",
      "MA (1);",
      "DSP_R (m) = RSWAT (R[n]);",
      "R[n] += R[8];",
    },
!   { "n", "", "n", "movs.w <DSP_REG_M>,@-<REG_N>", "111101NNMMMM0001",
      "MA (1);",
      "R[n] -= 2;",
      "WWAT (R[n], DSP_R (m) >> 16);",
    },
!   { "", "", "n",  "movs.w <DSP_REG_M>,@<REG_N>",  "111101NNMMMM0101",
      "MA (1);",
      "WWAT (R[n], DSP_R (m) >> 16);",
    },
!   { "n", "", "n", "movs.w <DSP_REG_M>,@<REG_N>+", "111101NNMMMM1001",
      "MA (1);",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += 2;",
    },
!   { "n", "", "n8","movs.w <DSP_REG_M>,@<REG_N>+REG_8", "111101NNMMMM1101",
      "MA (1);",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += R[8];",
    },
!   { "n", "", "n", "movs.w <DSP_GRD_M>,@-<REG_N>", "111101NNGGGG0001",
      "MA (1);",
      "R[n] -= 2;",
      "WWAT (R[n], SEXT (DSP_R (m)));",
    },
!   { "", "", "n",  "movs.w <DSP_GRD_M>,@<REG_N>",  "111101NNGGGG0101",
      "MA (1);",
      "WWAT (R[n], SEXT (DSP_R (m)));",
    },
!   { "n", "", "n", "movs.w <DSP_GRD_M>,@<REG_N>+", "111101NNGGGG1001",
      "MA (1);",
      "WWAT (R[n], SEXT (DSP_R (m)));",
      "R[n] += 2;",
    },
!   { "n", "", "n8","movs.w <DSP_GRD_M>,@<REG_N>+REG_8", "111101NNGGGG1101",
      "MA (1);",
      "WWAT (R[n], SEXT (DSP_R (m)));",
      "R[n] += R[8];",
    },
!   { "n", "", "n", "movs.l @-<REG_N>,<DSP_REG_M>", "111101NNMMMM0010",
      "MA (1);",
      "R[n] -= 4;",
      "DSP_R (m) = RLAT (R[n]);",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
    },
!   { "", "", "n",  "movs.l @<REG_N>,<DSP_REG_M>",  "111101NNMMMM0110",
      "MA (1);",
      "DSP_R (m) = RLAT (R[n]);",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
    },
!   { "n", "", "n", "movs.l @<REG_N>+,<DSP_REG_M>", "111101NNMMMM1010",
      "MA (1);",
      "DSP_R (m) = RLAT (R[n]);",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
      "R[n] += 4;",
    },
!   { "n", "", "n8","movs.l @<REG_N>+REG_8,<DSP_REG_M>", "111101NNMMMM1110",
      "MA (1);",
      "DSP_R (m) = RLAT (R[n]);",
      "DSP_GRD (m) = SIGN32 (DSP_R (m));",
      "R[n] += R[8];",
    },
!   { "n", "", "n", "movs.l <DSP_REG_M>,@-<REG_N>", "111101NNMMMM0011",
      "MA (1);",
      "R[n] -= 4;",
      "WLAT (R[n], DSP_R (m));",
    },
!   { "", "", "n",  "movs.l <DSP_REG_M>,@<REG_N>",  "111101NNMMMM0111",
      "MA (1);",
      "WLAT (R[n], DSP_R (m));",
    },
!   { "n", "", "n", "movs.l <DSP_REG_M>,@<REG_N>+", "111101NNMMMM1011",
      "MA (1);",
      "WLAT (R[n], DSP_R (m));",
      "R[n] += 4;",
    },
!   { "n", "", "n8","movs.l <DSP_REG_M>,@<REG_N>+REG_8", "111101NNMMMM1111",
      "MA (1);",
      "WLAT (R[n], DSP_R (m));",
      "R[n] += R[8];",
    },
!   { "n", "", "n", "movs.l <DSP_GRD_M>,@-<REG_N>", "111101NNGGGG0011",
      "MA (1);",
      "R[n] -= 4;",
      "WLAT (R[n], SEXT (DSP_R (m)));",
    },
!   { "", "", "n",  "movs.l <DSP_GRD_M>,@<REG_N>",  "111101NNGGGG0111",
      "MA (1);",
      "WLAT (R[n], SEXT (DSP_R (m)));",
    },
!   { "n", "", "n", "movs.l <DSP_GRD_M>,@<REG_N>+", "111101NNGGGG1011",
      "MA (1);",
      "WLAT (R[n], SEXT (DSP_R (m)));",
      "R[n] += 4;",
    },
!   { "n", "", "n8","movs.l <DSP_GRD_M>,@<REG_N>+REG_8", "111101NNGGGG1111",
      "MA (1);",
      "WLAT (R[n], SEXT (DSP_R (m)));",
      "R[n] += R[8];",
    },
!   { "", "", "n", "movx.w @<REG_x>,<DSP_XX>",   "111100xxXX000100",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "iword &= 0xfd53; goto top;",
    },
!   { "n", "", "n", "movx.w @<REG_x>+,<DSP_XX>", "111100xxXX001000",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;",
      "iword &= 0xfd53; goto top;",
    },
!   { "n", "", "n8","movx.w @<REG_x>+REG_8,<DSP_XX>", "111100xxXX001100",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
      "iword &= 0xfd53; goto top;",
    },
!   { "", "", "n", "movx.w <DSP_Aa>,@<REG_x>",   "111100xxaa100100",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "iword &= 0xfd53; goto top;",
    },
!   { "n", "", "n", "movx.w <DSP_Aa>,@<REG_x>+", "111100xxaa101000",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;",
      "iword &= 0xfd53; goto top;",
    },
!   { "n", "", "n8","movx.w <DSP_Aa>,@<REG_x>+REG_8","111100xxaa101100",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
      "iword &= 0xfd53; goto top;",
    },
!   { "", "", "n", "movy.w @<REG_y>,<DSP_YY>",   "111100yyYY000001",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
    },
!   { "n", "", "n", "movy.w @<REG_y>+,<DSP_YY>", "111100yyYY000010",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;",
    },
!   { "n", "", "n9","movy.w @<REG_y>+REG_9,<DSP_YY>", "111100yyYY000011",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
    },
!   { "", "", "n", "movy.w <DSP_Aa>,@<REG_y>",   "111100yyAA010001",
      "WWAT (R[n], DSP_R (m) >> 16);",
    },
!   { "n", "", "n", "movy.w <DSP_Aa>,@<REG_y>+", "111100yyAA010010",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;",
    },
!   { "n", "", "n9", "movy.w <DSP_Aa>,@<REG_y>+REG_9", "111100yyAA010011",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
    },
!   { "", "", "", "nopx nopy", "1111000000000000",
      "/* nop */",
    },
!   { "", "", "", "ppi", "1111100000000000",
      "ppi_insn (RIAT (nip));",
      "nip += 2;",
      "iword &= 0xf7ff; goto top;",
*************** op movsxy_tab[] =
*** 1302,1308 ****
  
  op ppi_tab[] =
  {
!   { "","", "pshl #<imm>,dz",	"00000iiim16.zzzz",
      "int Sz = DSP_R (z) & 0xffff0000;",
      "",
      "if (i <= 16)",
--- 1368,1374 ----
  
  op ppi_tab[] =
  {
!   { "", "","", "pshl #<imm>,dz",	"00000iiim16.zzzz",
      "int Sz = DSP_R (z) & 0xffff0000;",
      "",
      "if (i <= 16)",
*************** op ppi_tab[] =
*** 1318,1324 ****
      "res_grd = 0;",
      "goto logical;",
    },
!   { "","", "psha #<imm>,dz",	"00010iiim32.zzzz",
      "int Sz = DSP_R (z);",
      "int Sz_grd = GET_DSP_GRD (z);",
      "",
--- 1384,1390 ----
      "res_grd = 0;",
      "goto logical;",
    },
!   { "", "","", "psha #<imm>,dz",	"00010iiim32.zzzz",
      "int Sz = DSP_R (z);",
      "int Sz_grd = GET_DSP_GRD (z);",
      "",
*************** op ppi_tab[] =
*** 1360,1366 ****
      "COMPUTE_OVERFLOW;",
      "greater_equal = 0;",
    },
!   { "","", "pmuls Se,Sf,Dg",	"0100eeffxxyygguu",
      "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;",
      "if (res == 0x80000000)",
      "  res = 0x7fffffff;",
--- 1426,1432 ----
      "COMPUTE_OVERFLOW;",
      "greater_equal = 0;",
    },
!   { "", "","", "pmuls Se,Sf,Dg",	"0100eeffxxyygguu",
      "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;",
      "if (res == 0x80000000)",
      "  res = 0x7fffffff;",
*************** op ppi_tab[] =
*** 1368,1374 ****
      "DSP_GRD (g) = SIGN32 (res);",
      "return;",
    },
!   { "","", "psub Sx,Sy,Du pmuls Se,Sf,Dg",	"0110eeffxxyygguu",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
--- 1434,1440 ----
      "DSP_GRD (g) = SIGN32 (res);",
      "return;",
    },
!   { "", "","", "psub Sx,Sy,Du pmuls Se,Sf,Dg",	"0110eeffxxyygguu",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
*************** op ppi_tab[] =
*** 1387,1393 ****
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "padd Sx,Sy,Du pmuls Se,Sf,Dg",	"0111eeffxxyygguu",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
--- 1453,1459 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "padd Sx,Sy,Du pmuls Se,Sf,Dg",	"0111eeffxxyygguu",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
*************** op ppi_tab[] =
*** 1405,1411 ****
      "res_grd = Sx_grd + Sy_grd + carry;",
      "COMPUTE_OVERFLOW;",
    },
!   { "","", "psubc Sx,Sy,Dz",		"10100000xxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
--- 1471,1477 ----
      "res_grd = Sx_grd + Sy_grd + carry;",
      "COMPUTE_OVERFLOW;",
    },
!   { "", "","", "psubc Sx,Sy,Dz",	"10100000xxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
*************** op ppi_tab[] =
*** 1424,1430 ****
      "DSR |= carry;\n",
      "goto assign_z;\n",
    },
!   { "","", "paddc Sx,Sy,Dz",	"10110000xxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
--- 1490,1496 ----
      "DSR |= carry;\n",
      "goto assign_z;\n",
    },
!   { "", "","", "paddc Sx,Sy,Dz",	"10110000xxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
*************** op ppi_tab[] =
*** 1443,1449 ****
      "DSR |= carry;\n",
      "goto assign_z;\n",
    },
!   { "","", "pcmp Sx,Sy",	"10000100xxyy....",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
--- 1509,1515 ----
      "DSR |= carry;\n",
      "goto assign_z;\n",
    },
!   { "", "","", "pcmp Sx,Sy",	"10000100xxyy....",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
*************** op ppi_tab[] =
*** 1456,1466 ****
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "pwsb Sx,Sy,Dz",	"10100100xxyyzzzz",
    },
!   { "","", "pwad Sx,Sy,Dz",	"10110100xxyyzzzz",
    },
!   { "","", "pabs Sx,Dz",	"10001000xx..zzzz",
      "res = DSP_R (x);",
      "res_grd = GET_DSP_GRD (x);",
      "if (res >= 0)",
--- 1522,1532 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "pwsb Sx,Sy,Dz",	"10100100xxyyzzzz",
    },
!   { "", "","", "pwad Sx,Sy,Dz",	"10110100xxyyzzzz",
    },
!   { "", "","", "pabs Sx,Dz",	"10001000xx..zzzz",
      "res = DSP_R (x);",
      "res_grd = GET_DSP_GRD (x);",
      "if (res >= 0)",
*************** op ppi_tab[] =
*** 1477,1483 ****
      "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;",
      "ADD_SUB_GE;",
    },
!   { "","", "prnd Sx,Dz",	"10011000xx..zzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "",
--- 1543,1549 ----
      "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "prnd Sx,Dz",	"10011000xx..zzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "",
*************** op ppi_tab[] =
*** 1487,1493 ****
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "pabs Sy,Dz",	"10101000..yyzzzz",
      "res = DSP_R (y);",
      "res_grd = 0;",
      "overflow = 0;",
--- 1553,1559 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "pabs Sy,Dz",	"10101000..yyzzzz",
      "res = DSP_R (y);",
      "res_grd = 0;",
      "overflow = 0;",
*************** op ppi_tab[] =
*** 1510,1516 ****
      "      }",
      "  }",
    },
!   { "","", "prnd Sy,Dz",	"10111000..yyzzzz",
      "int Sy = DSP_R (y);",
      "int Sy_grd = SIGN32 (Sy);",
      "",
--- 1576,1582 ----
      "      }",
      "  }",
    },
!   { "", "","", "prnd Sy,Dz",	"10111000..yyzzzz",
      "int Sy = DSP_R (y);",
      "int Sy_grd = SIGN32 (Sy);",
      "",
*************** op ppi_tab[] =
*** 1520,1526 ****
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "(if cc) pshl Sx,Sy,Dz",	"100000ccxxyyzzzz",
      "int Sx = DSP_R (x) & 0xffff0000;",
      "int Sy = DSP_R (y) >> 16 & 0x7f;",
      "",
--- 1586,1592 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "(if cc) pshl Sx,Sy,Dz",	"100000ccxxyyzzzz",
      "int Sx = DSP_R (x) & 0xffff0000;",
      "int Sy = DSP_R (y) >> 16 & 0x7f;",
      "",
*************** op ppi_tab[] =
*** 1535,1541 ****
      "  }",
      "goto cond_logical;",
    },
!   { "","", "(if cc) psha Sx,Sy,Dz",	"100100ccxxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y) >> 16 & 0x7f;",
--- 1601,1607 ----
      "  }",
      "goto cond_logical;",
    },
!   { "", "","", "(if cc) psha Sx,Sy,Dz",	"100100ccxxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y) >> 16 & 0x7f;",
*************** op ppi_tab[] =
*** 1578,1584 ****
      "COMPUTE_OVERFLOW;",
      "greater_equal = 0;",
    },
!   { "","", "(if cc) psub Sx,Sy,Dz",	"101000ccxxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
--- 1644,1650 ----
      "COMPUTE_OVERFLOW;",
      "greater_equal = 0;",
    },
!   { "", "","", "(if cc) psub Sx,Sy,Dz",	"101000ccxxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
*************** op ppi_tab[] =
*** 1590,1596 ****
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "(if cc) padd Sx,Sy,Dz",	"101100ccxxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
--- 1656,1662 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "(if cc) padd Sx,Sy,Dz",	"101100ccxxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
*************** op ppi_tab[] =
*** 1602,1608 ****
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "(if cc) pand Sx,Sy,Dz",	"100101ccxxyyzzzz",
      "res = DSP_R (x) & DSP_R (y);",
    "cond_logical:",
      "res &= 0xffff0000;",
--- 1668,1674 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "(if cc) pand Sx,Sy,Dz",	"100101ccxxyyzzzz",
      "res = DSP_R (x) & DSP_R (y);",
    "cond_logical:",
      "res &= 0xffff0000;",
*************** op ppi_tab[] =
*** 1620,1634 ****
      "  DSR |= DSR_MASK_Z;\n",
      "goto assign_dc;\n",
    },
!   { "","", "(if cc) pxor Sx,Sy,Dz",	"101001ccxxyyzzzz",
      "res = DSP_R (x) ^ DSP_R (y);",
      "goto cond_logical;",
    },
!   { "","", "(if cc) por Sx,Sy,Dz",	"101101ccxxyyzzzz",
      "res = DSP_R (x) | DSP_R (y);",
      "goto cond_logical;",
    },
!   { "","", "(if cc) pdec Sx,Dz",	"100010ccxx..zzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "",
--- 1686,1700 ----
      "  DSR |= DSR_MASK_Z;\n",
      "goto assign_dc;\n",
    },
!   { "", "","", "(if cc) pxor Sx,Sy,Dz",	"101001ccxxyyzzzz",
      "res = DSP_R (x) ^ DSP_R (y);",
      "goto cond_logical;",
    },
!   { "", "","", "(if cc) por Sx,Sy,Dz",	"101101ccxxyyzzzz",
      "res = DSP_R (x) | DSP_R (y);",
      "goto cond_logical;",
    },
!   { "", "","", "(if cc) pdec Sx,Dz",	"100010ccxx..zzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "",
*************** op ppi_tab[] =
*** 1639,1645 ****
      "ADD_SUB_GE;",
      "res &= 0xffff0000;",
    },
!   { "","", "(if cc) pinc Sx,Dz",	"100110ccxx..zzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "",
--- 1705,1711 ----
      "ADD_SUB_GE;",
      "res &= 0xffff0000;",
    },
!   { "", "","", "(if cc) pinc Sx,Dz",	"100110ccxx..zzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "",
*************** op ppi_tab[] =
*** 1650,1656 ****
      "ADD_SUB_GE;",
      "res &= 0xffff0000;",
    },
!   { "","", "(if cc) pdec Sy,Dz",	"101010cc..yyzzzz",
      "int Sy = DSP_R (y);",
      "int Sy_grd = SIGN32 (Sy);",
      "",
--- 1716,1722 ----
      "ADD_SUB_GE;",
      "res &= 0xffff0000;",
    },
!   { "", "","", "(if cc) pdec Sy,Dz",	"101010cc..yyzzzz",
      "int Sy = DSP_R (y);",
      "int Sy_grd = SIGN32 (Sy);",
      "",
*************** op ppi_tab[] =
*** 1661,1667 ****
      "ADD_SUB_GE;",
      "res &= 0xffff0000;",
    },
!   { "","", "(if cc) pinc Sy,Dz",	"101110cc..yyzzzz",
      "int Sy = DSP_R (y);",
      "int Sy_grd = SIGN32 (Sy);",
      "",
--- 1727,1733 ----
      "ADD_SUB_GE;",
      "res &= 0xffff0000;",
    },
!   { "", "","", "(if cc) pinc Sy,Dz",	"101110cc..yyzzzz",
      "int Sy = DSP_R (y);",
      "int Sy_grd = SIGN32 (Sy);",
      "",
*************** op ppi_tab[] =
*** 1672,1685 ****
      "ADD_SUB_GE;",
      "res &= 0xffff0000;",
    },
!   { "","", "(if cc) pclr Dz",		"100011cc....zzzz",
      "res = 0;",
      "res_grd = 0;",
      "carry = 0;",
      "overflow = 0;",
      "greater_equal = 1;",
    },
!   { "","", "(if cc) pdmsb Sx,Dz",	"100111ccxx..zzzz",
      "unsigned Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int i = 16;",
--- 1738,1751 ----
      "ADD_SUB_GE;",
      "res &= 0xffff0000;",
    },
!   { "", "","", "(if cc) pclr Dz",	"100011cc....zzzz",
      "res = 0;",
      "res_grd = 0;",
      "carry = 0;",
      "overflow = 0;",
      "greater_equal = 1;",
    },
!   { "", "","", "(if cc) pdmsb Sx,Dz",	"100111ccxx..zzzz",
      "unsigned Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int i = 16;",
*************** op ppi_tab[] =
*** 1713,1719 ****
      "overflow = 0;",
      "ADD_SUB_GE;",
    },
!   { "","", "(if cc) pdmsb Sy,Dz",	"101111cc..yyzzzz",
      "unsigned Sy = DSP_R (y);",
      "int i;",
      "",
--- 1779,1785 ----
      "overflow = 0;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "(if cc) pdmsb Sy,Dz",	"101111cc..yyzzzz",
      "unsigned Sy = DSP_R (y);",
      "int i;",
      "",
*************** op ppi_tab[] =
*** 1736,1742 ****
      "overflow = 0;",
      "ADD_SUB_GE;",
    },
!   { "","", "(if cc) pneg Sx,Dz",	"110010ccxx..zzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "",
--- 1802,1808 ----
      "overflow = 0;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "(if cc) pneg Sx,Dz",	"110010ccxx..zzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "",
*************** op ppi_tab[] =
*** 1746,1759 ****
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "(if cc) pcopy Sx,Dz",	"110110ccxx..zzzz",
      "res = DSP_R (x);",
      "res_grd = GET_DSP_GRD (x);",
      "carry = 0;",
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "(if cc) pneg Sy,Dz",	"111010cc..yyzzzz",
      "int Sy = DSP_R (y);",
      "int Sy_grd = SIGN32 (Sy);",
      "",
--- 1812,1825 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "(if cc) pcopy Sx,Dz",	"110110ccxx..zzzz",
      "res = DSP_R (x);",
      "res_grd = GET_DSP_GRD (x);",
      "carry = 0;",
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "(if cc) pneg Sy,Dz",	"111010cc..yyzzzz",
      "int Sy = DSP_R (y);",
      "int Sy_grd = SIGN32 (Sy);",
      "",
*************** op ppi_tab[] =
*** 1763,1793 ****
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "(if cc) pcopy Sy,Dz",	"111110cc..yyzzzz",
      "res = DSP_R (y);",
      "res_grd = SIGN32 (res);",
      "carry = 0;",
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "","", "(if cc) psts MACH,Dz",	"110011cc....zzzz",
      "res = MACH;",
      "res_grd = SIGN32 (res);",
      "goto assign_z;",
    },
!   { "","", "(if cc) psts MACL,Dz",	"110111cc....zzzz",
      "res = MACL;",
      "res_grd = SIGN32 (res);",
      "goto assign_z;",
    },
!   { "","", "(if cc) plds Dz,MACH",	"111011cc....zzzz",
      "if (0xa05f >> z & 1)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
      "  MACH = DSP_R (z);",
      "return;",
    },
!   { "","", "(if cc) plds Dz,MACL",	"111111cc....zzzz",
      "if (0xa05f >> z & 1)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
--- 1829,1859 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "(if cc) pcopy Sy,Dz",	"111110cc..yyzzzz",
      "res = DSP_R (y);",
      "res_grd = SIGN32 (res);",
      "carry = 0;",
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
!   { "", "","", "(if cc) psts MACH,Dz",	"110011cc....zzzz",
      "res = MACH;",
      "res_grd = SIGN32 (res);",
      "goto assign_z;",
    },
!   { "", "","", "(if cc) psts MACL,Dz",	"110111cc....zzzz",
      "res = MACL;",
      "res_grd = SIGN32 (res);",
      "goto assign_z;",
    },
!   { "", "","", "(if cc) plds Dz,MACH",	"111011cc....zzzz",
      "if (0xa05f >> z & 1)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
      "  MACH = DSP_R (z);",
      "return;",
    },
!   { "", "","", "(if cc) plds Dz,MACL",	"111111cc....zzzz",
      "if (0xa05f >> z & 1)",
      "  RAISE_EXCEPTION (SIGILL);",
      "else",
*************** expand_opcode (shift, val, i, s)
*** 1979,1984 ****
--- 2045,2052 ----
  	  {
  	    int m, mv;
  
+ 	    if (s[1] - '0' > 1U || !s[2] || ! s[3])
+ 	      expand_opcode (shift - 1, val + s[0] - '0', i, s + 1);
  	    val |= bton (s) << shift;
  	    if (s[2] == '0' || s[2] == '1')
  	      expand_opcode (shift - 4, val, i, s + 4);
*************** expand_opcode (shift, val, i, s)
*** 2003,2014 ****
  	  }
  	case 'n':
  	case 'm':
! 	  for (j = 0; j < 16; j++)
! 	    {
! 	      expand_opcode (shift - 4, val | (j << shift), i, s + 4);
! 
! 	    }
! 	  break;
  	case 'M':
  	  /* A1, A0,X0,X1,Y0,Y1,M0,A1G,M1,M1G */
  	  for (j = 5; j < 16; j++)
--- 2071,2087 ----
  	  }
  	case 'n':
  	case 'm':
! 	  {
! 	    int digits = 1;
! 	    while (s[digits] == s[0])
! 	      digits++;
! 	    for (j = 0; j < (1 << digits); j++)
! 	      {
! 		expand_opcode (shift - digits, val | (j << shift), i,
! 			       s + digits);
! 	      }
! 	    break;
! 	  }
  	case 'M':
  	  /* A1, A0,X0,X1,Y0,Y1,M0,A1G,M1,M1G */
  	  for (j = 5; j < 16; j++)
*************** gensim_caselist (p)
*** 2129,2137 ****
--- 2202,2217 ----
        int sextbit = -1;
        int needm = 0;
        int needn = 0;
+       int needm_int = 0;
+       int needn_int = 0;
        
        char *s = p->code;
+       char *fp_pref = "R";
+       int latency = 1;
  
+ #ifdef SH4_TIMINGS
+       fp_pref = strncmp (p->code, "1111", 4) == 0 ? "FR" : "R";
+ #endif
        printf ("  /* %s %s */\n", p->name, p->code);
        printf ("  case %d:      \n", p->index);
  
*************** gensim_caselist (p)
*** 2141,2148 ****
  	  switch (*s)
  	    {
  	    default:
! 	      fprintf (stderr, "gencode/gensim_caselist: illegal char '%c'\n",
! 		       *s);
  	      exit (1);
  	      break;
  	    case '0':
--- 2221,2229 ----
  	  switch (*s)
  	    {
  	    default:
! 	      fprintf (stderr,
! 		       "gencode/gensim_caselist: illegal char '%c' in %s\n",
! 		       *s, p->name);
  	      exit (1);
  	      break;
  	    case '0':
*************** gensim_caselist (p)
*** 2236,2258 ****
  		  sextbit - 1, sextbit - 1);
  	}
  
-       if (needm && needn)
- 	printf ("      TB(m,n);\n");  
-       else if (needm)
- 	printf ("      TL(m);\n");
-       else if (needn)
- 	printf ("      TL(n);\n");
- 
        {
  	/* Do the refs */
  	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"); 
  	  }
        }
  
--- 2317,2369 ----
  		  sextbit - 1, sextbit - 1);
  	}
  
        {
  	/* Do the refs */
  	char *r;
  	for (r = p->refs; *r; r++)
  	  {
! 	    if (*r == '0') printf("      CREF(0);\n      TL(R[0]);\n"); 
  	    if (*r == '8') printf("      CREF(8);\n"); 
  	    if (*r == '9') printf("      CREF(9);\n"); 
! 	    if (*r == 'n') printf("      CREF(n);\n"), needn_int = 1; 
! 	    if (*r == 'm') printf("      CREF(m);\n"), needm_int = 1; 
! #if SH4_TIMINGS
! 	    if (*r == 't') printf("      TL(t);\n"); 
! 	    if (*r == 'c') printf("      TL(fpscr);\n"); 
! #endif
! 	  }
!       }
!       if (needm && needn)
! 	printf ("      TB(%s[m],%s[n]);\n",
! 		needm_int ? "R" : fp_pref, needn_int ? "R" : fp_pref);  
!       else if (needm)
! 	printf ("      TL(%s[m]);\n", needm_int ? "R" : fp_pref);
!       else if (needn)
! 	printf ("      TL(%s[n]);\n", needn_int ? "R" : fp_pref);
! 
!       if (*p->sh4_group)
! 	{
! 	  if (strcmp (p->sh4_group, "ld") == 0)
! 	    {
! 	      printf ("SH4_LS;\n");
! 	      latency = 2;
! 	    }
! 	  else
! 	    printf ("SH4_%c%c;\n",
! 		    toupper (p->sh4_group[0]), toupper (p->sh4_group[1]));
! 	}
! 
!       if (strcmp (p->sh4_group, "co") != 0) {
! 	/* Do the def latencies */
! 	char *r;
! 	for (r = p->defs; *r; r++) 
! 	  {
! 	    if (*r == '0') printf("      L_SH4 (R[0], %d);\n", latency); 
! 	    if (*r == 'n' && strcmp (p->sh4_group, "mt") != 0)
! 			   printf("      L_SH4 (R[n], %d);\n", latency); 
! 	    if (*r == 'm') printf("      L_SH4 (R[m], 1);\n"); 
! 	    if (*r == 'f') printf("      L_SH4 (FR[n], %d);\n", latency); 
! 	    if (*r == 't') printf("      L_SH4 (t, 1);\n"); 
  	  }
        }
  
*************** gensim_caselist (p)
*** 2274,2279 ****
--- 2385,2391 ----
  	    if (*r == '0') printf("      CDEF(0);\n"); 
  	    if (*r == 'n') printf("      CDEF(n);\n"); 
  	    if (*r == 'm') printf("      CDEF(m);\n"); 
+ 	    if (*r == 't') printf("      L_SH4(t, 1);\n"); 
  	  }
        }
  
Index: interp.c
===================================================================
RCS file: /cvs/src/src/sim/sh/interp.c,v
retrieving revision 1.11
diff -p -r1.11 interp.c
*** interp.c	15 Oct 2003 12:30:47 -0000	1.11
--- interp.c	24 Oct 2003 19:55:30 -0000
*************** int sim_write (SIM_DESC sd, SIM_ADDR add
*** 65,70 ****
--- 65,78 ----
     for a quit. */
  #define POLL_QUIT_INTERVAL 0x60000
  
+ struct ready_s {
+   int R[16];
+   int FR[16];
+   int macl, mach;
+   int t;
+   int fpscr, fpul;
+ };
+ 
  typedef union
  {
  
*************** typedef union
*** 132,139 ****
      int cycles;
      int insts;
  
!     int prevlock;
!     int thislock;
      int exception;
  
      int end_of_registers;
--- 140,149 ----
      int cycles;
      int insts;
  
!     int *prevlock;
!     int *thislock;
!     int sh4_group;
!     struct ready_s ready;
      int exception;
  
      int end_of_registers;
*************** do { \
*** 398,403 ****
--- 408,415 ----
     #define PARANOID
  */
  
+ #define SH4_TIMINGS
+ 
  #ifdef PARANOID
  int valid[16];
  #define CREF(x)  if(!valid[x]) fail();
*************** set_dr (n, exp)
*** 510,552 ****
  #define MOD_ME DSP_GRD (17)
  #define MOD_DELTA DSP_GRD (18)
  
! #define FP_OP(n, OP, m) \
  { \
    if (FPSCR_PR) \
      { \
        if (((n) & 1) || ((m) & 1)) \
  	RAISE_EXCEPTION (SIGILL); \
        else \
! 	SET_DR(n, (DR(n) OP DR(m))); \
      } \
    else \
!     SET_FR(n, (FR(n) OP FR(m))); \
  } while (0)
  
! #define FP_UNARY(n, OP) \
  { \
    if (FPSCR_PR) \
      { \
        if ((n) & 1) \
  	RAISE_EXCEPTION (SIGILL); \
        else \
! 	SET_DR(n, (OP (DR(n)))); \
      } \
    else \
!     SET_FR(n, (OP (FR(n)))); \
  } while (0)
  
  #define FP_CMP(n, OP, m) \
  { \
    if (FPSCR_PR) \
      { \
        if (((n) & 1) || ((m) & 1)) \
  	RAISE_EXCEPTION (SIGILL); \
        else \
  	SET_SR_T (DR(n) OP DR(m)); \
      } \
    else \
!     SET_SR_T (FR(n) OP FR(m)); \
  } while (0)
  
  static void
--- 522,584 ----
  #define MOD_ME DSP_GRD (17)
  #define MOD_DELTA DSP_GRD (18)
  
! #define FP_OP(n, OP, m, s_latency, d_latency) \
  { \
    if (FPSCR_PR) \
      { \
        if (((n) & 1) || ((m) & 1)) \
  	RAISE_EXCEPTION (SIGILL); \
        else \
! 	{ \
! 	  SET_DR(n, (DR(n) OP DR(m))); \
! 	  L_SH4 (FR[n], d_latency); \
! 	} \
      } \
    else \
!     { \
!       SET_FR(n, (FR(n) OP FR(m))); \
!       L_SH4 (FR[n], s_latency); \
!     } \
  } while (0)
  
! #define FP_UNARY(n, OP, s_latency, d_latency) \
  { \
    if (FPSCR_PR) \
      { \
        if ((n) & 1) \
  	RAISE_EXCEPTION (SIGILL); \
        else \
! 	{ \
! 	  SET_DR(n, (OP (DR(n)))); \
! 	  if (d_latency) \
! 	    L_SH4 (FR[n], d_latency); \
! 	} \
      } \
    else \
!     { \
!       SET_FR(n, (OP (FR(n)))); \
!       if (s_latency) \
! 	L_SH4 (FR[n], s_latency); \
!     } \
  } while (0)
  
  #define FP_CMP(n, OP, m) \
  { \
    if (FPSCR_PR) \
      { \
+       SH4_CO; \
+       cycles++; \
        if (((n) & 1) || ((m) & 1)) \
  	RAISE_EXCEPTION (SIGILL); \
        else \
  	SET_SR_T (DR(n) OP DR(m)); \
      } \
    else \
!     { \
!       SH4_FE; \
!       SET_SR_T (FR(n) OP FR(m)); \
!     } \
!   L_SH4 (t, 2); \
  } while (0)
  
  static void
*************** process_rbat_addr (addr)
*** 775,782 ****
  
  #define SET_NIP(x) nip = (x); CHECK_INSN_PTR (nip);
  
- #define Delay_Slot(TEMPPC)  	iword = RIAT (TEMPPC); goto top;
- 
  #define CHECK_INSN_PTR(p) \
  do { \
    if (saved_state.asregs.exception || PH2T (p) & maskw) \
--- 807,812 ----
*************** do { \
*** 794,808 ****
  #define TL(x)
  #define TB(x)
  
! #else
  
  #define MA(n) \
    do { memstalls += ((((int) PC & 3) != 0) ? (n) : ((n) - 1)); } while (0)
  
! #define L(x)   thislock = x;
! #define TL(x)  if ((x) == prevlock) stalls++;
! #define TB(x,y)  if ((x) == prevlock || (y)==prevlock) stalls++;
  
  #endif
  
  #if defined(__GO32__) || defined(_WIN32)
--- 824,881 ----
  #define TL(x)
  #define TB(x)
  
! #elif ! defined (SH4_TIMINGS)
  
  #define MA(n) \
    do { memstalls += ((((int) PC & 3) != 0) ? (n) : ((n) - 1)); } while (0)
  
! /* instead of x / y use R[x] / R[y] */
! #define L(x)   thislock = &(x);
! #define L_SH4(x,n)
! #define TL(x)  if (&(x) == prevlock) stalls++;
! #define TB(x,y)  if (&(x) == prevlock || &(y)==prevlock) stalls++;
! 
! #endif
! 
! #ifdef SH4_TIMINGS
! enum
! {
!   sh4_mt = 1, sh4_ex = 2, sh4_br = 4, sh4_ls = 8, sh4_fe = 16, sh4_issue = 32
! } sh4_units;
! 
! #define MA(n)
! #define L(x) ready->x = cycles + 2
! #define L_SH4(x,n) ready->x = cycles + (n)
! #define TL(x) \
!   if (ready->x > cycles) cycles = ready->x - 1, sh4_group = sh4_issue
! #define TB (x,y) \
!   if (ready->x > cycles || ready->y > cycles) \
!     cycles = (ready->x >= ready->y ? ready->x : ready->y) - 1, \
!     sh4_group = sh4_issue
! 
! #define SH4_GROUP_USE(gt, gs) \
!   if (sh4_group & (sh4_issue | (gt))) \
!     cycles++, sh4_group = gs; \
!   else \
!     sh4_group = sh4_issue;
  
+ #define SH4_MT SH4_GROUP_USE (0,      sh4_mt)
+ #define SH4_EX SH4_GROUP_USE (sh4_ex, sh4_ex)
+ #define SH4_BR SH4_GROUP_USE (sh4_br, sh4_br)
+ #define SH4_LS SH4_GROUP_USE (sh4_ls, sh4_ls)
+ #define SH4_FE SH4_GROUP_USE (sh4_fe, sh4_fe)
+ #define SH4_CO SH4_GROUP_USE (sh4_mt|sh4_ex|sh4_br|sh4_ls|sh4_fe, sh4_issue)
+ #define BRANCH_TAKEN(addr) SET_NIP (addr); cycles += 1; sh4_group = sh4_issue
+ #define Delay_Slot(TEMPPC)  	sh4_group = 0, iword = RIAT (TEMPPC); goto top;
+ #else
+ #define SH4_MT
+ #define SH4_EX
+ #define SH4_BR
+ #define SH4_LS
+ #define SH4_FE
+ #define SH4_CO
+ #define BRANCH_TAKEN(addr) SET_NIP (addr); cycles += 2
+ #define Delay_Slot(TEMPPC)  	iword = RIAT (TEMPPC); goto top;
  #endif
  
  #if defined(__GO32__) || defined(_WIN32)
*************** macl (regs, memory, n, m)
*** 1411,1416 ****
--- 1484,1538 ----
    MACH = mach;
  }
  
+ float
+ fsca_s (int in, double (*f) (double))
+ {
+   double rad = ldexp ((in & 0xffff), -15) * 3.141592653589793238462643383;
+   double result = (*f) (rad);
+   double error, upper, lower, frac;
+   int exp;
+ 
+   /* Search the value with the maximum error that is still within the
+      architectural spec.  */
+   error = ldexp (1., -21);
+   /* compensate for calculation inaccuracy by reducing error.  */
+   error = error - ldexp (1., -50);
+   upper = result + error;
+   frac = frexp (upper, &exp);
+   upper = ldexp (floor (ldexp (frac, 24)), exp - 24);
+   lower = result - error;
+   frac = frexp (lower, &exp);
+   lower = ldexp (ceil (ldexp (frac, 24)), exp - 24);
+   return abs (upper - result) >= abs (lower - result) ? upper : lower;
+ }
+ 
+ float
+ fsrra_s (float in)
+ {
+   double result = 1. / sqrt (in);
+   int exp;
+   double frac, upper, lower, error, eps;
+ 
+   /* refine result */
+   result = result - (result * result * in - 1) * 0.5 * result;
+   /* Search the value with the maximum error that is still within the
+      architectural spec.  */
+   frac = frexp (result, &exp);
+   frac = ldexp (frac, 24);
+   error = 4.; /* 1 << 24-1-21 */
+   /* use eps to compensate for possible 1 ulp error in our 'exact' result.  */
+   eps = ldexp (1., -29);
+   upper = floor (frac + error - eps);
+   if (upper > 16777216.)
+     upper = floor ((frac + error - eps) * 0.5) * 2.;
+   lower = ceil ((frac - error + eps) * 2) * .5;
+   if (lower > 8388608.)
+     lower = ceil (frac - error + eps);
+   upper = ldexp (upper, exp - 24);
+   lower = ldexp (lower, exp - 24);
+   return upper - result >= result - lower ? upper : lower;
+ }
+ 
  static struct loop_bounds
  get_loop_bounds (rs, re, memory, mem_end, maskw, endianw)
       int rs, re;
*************** sim_resume (sd, step, siggnal)
*** 1656,1663 ****
    register int stalls = 0;
    register int memstalls = 0;
    register int insts = 0;
!   register int prevlock;
!   register int thislock;
    register unsigned int doprofile;
    register int pollcount = 0;
    /* endianw is used for every insn fetch, hence it makes sense to cache it.
--- 1778,1787 ----
    register int stalls = 0;
    register int memstalls = 0;
    register int insts = 0;
!   register int *prevlock;
!   register int *thislock;
!   struct ready_s *ready;
!   int sh4_group;
    register unsigned int doprofile;
    register int pollcount = 0;
    /* endianw is used for every insn fetch, hence it makes sense to cache it.
*************** sim_resume (sd, step, siggnal)
*** 1701,1706 ****
--- 1825,1832 ----
    /*T = GET_SR () & SR_MASK_T;*/
    prevlock = saved_state.asregs.prevlock;
    thislock = saved_state.asregs.thislock;
+   ready = &saved_state.asregs.ready;
+   sh4_group = saved_state.asregs.sh4_group;
    doprofile = saved_state.asregs.profile;
  
    /* If profiling not enabled, disable it by asking for
*************** sim_resume (sd, step, siggnal)
*** 1749,1761 ****
  	}
  
  #ifndef ACE_FAST
        prevlock = thislock;
!       thislock = 30;
        cycles++;
  
        if (cycles >= doprofile)
  	{
  
  	  saved_state.asregs.cycles += doprofile;
  	  cycles -= doprofile;
  	  if (saved_state.asregs.profile_hist)
--- 1875,1899 ----
  	}
  
  #ifndef ACE_FAST
+ #ifndef SH4_TIMINGS
        prevlock = thislock;
!       thislock = NULL;
        cycles++;
+ #endif
  
        if (cycles >= doprofile)
  	{
  
+ #ifdef SH4_TIMINGS
+ 	  {
+ 	    int i;
+ 	    for (i = 0; i < 16; i++)
+ 	      {
+ 		ready->R[i] -= doprofile;
+ 		ready->FR[i] -= doprofile;
+ 	      }
+ 	  }
+ #endif /* SH4_TIMINGS */
  	  saved_state.asregs.cycles += doprofile;
  	  cycles -= doprofile;
  	  if (saved_state.asregs.profile_hist)
*************** sim_resume (sd, step, siggnal)
*** 1806,1811 ****
--- 1944,1950 ----
  
    saved_state.asregs.prevlock = prevlock;
    saved_state.asregs.thislock = thislock;
+   saved_state.asregs.sh4_group = sh4_group;
  
    if (profile_file)
      {
*************** sim_create_inferior (sd, prog_bfd, argv,
*** 2309,2314 ****
--- 2448,2454 ----
    /* Clear the registers. */
    memset (&saved_state, 0,
  	  (char*)&saved_state.asregs.end_of_registers - (char*)&saved_state);
+   saved_state.asregs.sh4_group = sh4_issue;
  
    /* Set the PC.  */
    if (prog_bfd != NULL)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]