This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB 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: [RFA] Add sh4a to sh-sim (2nd iteration)


Joern Rennecke wrote:

According to the sh2-dsp manual that is still at the Renesas web site,
the xx / yy fields are still present in the pmuls instruction.

Hmm, well, are they used for anything? I think I took them out to resolve a conflict with another insn (but I don't remember for sure). Since there's no corresponding register parameter, and the code does not use them -- is there any harm? If the other patterns are not used now, they probably will be someday.


According to the manual, because of the ignored x,y,u operands, there are
64 valid pmuls opcodes for each e,f,g combination.  I can't find anything
in the manual that says that any one of these opcodes is preferred.
If there is a conflict, it appears that the sh4a-dsp is not actually
backward compatible with the sh3-dsp, and we'll need another opcode table
modification depending on bfd_get_mach.  OTOH I seem to remember that we
were asked to zero unused fields in the assembler, but that might be just
to get reproducible results.  You should probably ask Renesas for
clarification.

OK, I'll restore the xxyy for now, just to get it committed, and address it either as it comes up or as clarification obtains.


What are these FIXMEs supposed to mean?

I did this work 4 months ago. Probably I thought the comment was wrong, and that the actual set of registers was as shown. Your second opinion would be appreciated.


The first part of the comments is right, the FIXMEs are wrong.  The
registers are numbered like in the movs instruction which is the same
as in the the Dz parameter, with A1G / A0G having a number 8 higher
than A1 / A0.  See also the macros in interp.c after DSR_R.

OK, removing the fixme comments. Committing with changes as attached below:

2004-01-07  Michael Snyder  <msnyder@redhat.com>

	* gencode.c: Replace 'Hitachi' with 'Renesas'.
	(op tab): Add new instructions for sh4a, DBR, SBR.
	(expand_opcode): Add handling for new movxy combinations.
	(gensym_caselist): Ditto.
	(expand_ppi_movxy): Remove movx/movy expansions, 
	now handled in expand_opcode.
	(gensym): Add some helpful macros.
	(expand_ppi_code): Flatten loop for simplicity, tweak for 12-bit
	instead of 8-bit table (some insns are ambiguous to 8 bits).
	(ppi_gensim, main): Generate 12-bit instead of 8-bit ppi table.

	* interp.c: Replace 'Hitachi' with 'Renesas'.
	(union saved_state_type): Add dbr, sgr, ldst.
	(get_loop_bounds_ext): New function.
	(init_dsp): Add bfd_mach_sh4al_dsp.
	(sim_resume): Handle extended loop bounds.	

Index: gencode.c
===================================================================
RCS file: /cvs/src/src/sim/sh/gencode.c,v
retrieving revision 1.22
diff -p -r1.22 gencode.c
*** gencode.c	6 Jan 2004 01:05:02 -0000	1.22
--- gencode.c	9 Jan 2004 19:33:38 -0000
***************
*** 1,4 ****
! /* Simulator/Opcode generator for the Hitachi Super-H architecture.
  
     Written by Steve Chamberlain of Cygnus Support.
     sac@cygnus.com
--- 1,5 ----
! /* Simulator/Opcode generator for the Renesas
!    (formerly Hitachi) / SuperH Inc. Super-H architecture.
  
     Written by Steve Chamberlain of Cygnus Support.
     sac@cygnus.com
*************** op tab[] =
*** 151,156 ****
--- 152,162 ----
      "SET_SR_T (0);",
    },
  
+   /* sh4a */
+   { "", "", "clrdmxy", "0000000010001000",
+     "saved_state.asregs.cregs.named.sr &= ~(SR_MASK_DMX | SR_MASK_DMY);"
+   },
+ 
    { "", "0", "cmp/eq #<imm>,R0", "10001000i8*1....",
      "SET_SR_T (R0 == SEXT (i));",
    },
*************** op tab[] =
*** 195,201 ****
      "SET_SR_T (0);",
    },
  
!   { "", "nm", "div1 <REG_M>,<REG_N>", "0011nnnnmmmm0100", /* ? MVS */
      "div1 (R, m, n/*, T*/);",
    },
  
--- 201,207 ----
      "SET_SR_T (0);",
    },
  
!   { "", "nm", "div1 <REG_M>,<REG_N>", "0011nnnnmmmm0100",
      "div1 (R, m, n/*, T*/);",
    },
  
*************** op tab[] =
*** 285,294 ****
    },
  
    /* sh4 */
!   { "", "", "fipr <FV_M>,<FV_N>", "1111nnmm11101101",
!     "/* FIXME: not implemented */",
!     "RAISE_EXCEPTION (SIGILL);",
!     "/* FIXME: check for DP and (n & 1) == 0? */",
    },
  
    /* sh2e */
--- 291,309 ----
    },
  
    /* sh4 */
!   { "", "", "fipr <FV_M>,<FV_N>", "1111vvVV11101101",
!     "if (FPSCR_PR)", 
!     "  RAISE_EXCEPTION (SIGILL);",
!     "else",
!     "{",
!     "  double fsum = 0;",
!     "  /* FIXME: check for nans and infinities.  */",
!     "  fsum += FR (v1+0) * FR (v2+0);",
!     "  fsum += FR (v1+1) * FR (v2+1);",
!     "  fsum += FR (v1+2) * FR (v2+2);",
!     "  fsum += FR (v1+3) * FR (v2+3);",
!     "  SET_FR (v1+3, fsum);",
!     "}",
    },
  
    /* sh2e */
*************** op tab[] =
*** 440,445 ****
--- 455,465 ----
      "FP_UNARY(n, -);",
    },
  
+   /* sh4a */
+   { "", "", "fpchg", "1111011111111101",
+     "SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_PR);",
+   },
+ 
    /* sh4 */
    { "", "", "frchg", "1111101111111101",
      "if (FPSCR_PR)",
*************** op tab[] =
*** 498,503 ****
--- 518,534 ----
      "  FPUL = (int)FR(n);",
    },
  
+   /* sh4 */
+   { "", "", "ftrv <FV_N>", "1111vv0111111101",
+     "if (FPSCR_PR)",
+     "  RAISE_EXCEPTION (SIGILL);",
+     "else",
+     "{", 
+     "  /* FIXME not implemented.  */",
+     "  printf (\"ftrv xmtrx, FV%d\\n\", v1);",
+     "}", 
+   },
+ 
    /* sh2e */
    { "", "", "fsts FPUL,<FREG_N>", "1111nnnn00001101",
      "  union",
*************** op tab[] =
*** 535,546 ****
    { "", "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]);",
--- 566,583 ----
    { "", "n", "ldc <REG_N>,MOD", "0100nnnn01011110",
      "SET_MOD (R[n]);",
    },
    { "", "n", "ldc <REG_N>,DBR", "0100nnnn11111010",
!     "if (SR_MD)",
!     "  DBR = R[n]; /* priv mode */",
!     "else",
!     "  RAISE_EXCEPTION (SIGILL); /* user mode */",
!   },
!   { "", "n", "ldc <REG_N>,SGR", "0100nnnn00111010",
!     "if (SR_MD)",
!     "  SGR = R[n]; /* priv mode */",
!     "else",
!     "  RAISE_EXCEPTION (SIGILL); /* user mode */",
    },
    { "n", "n", "ldc.l @<REG_N>+,<CREG_M>", "0100nnnnmmmm0111",
      "MA (1);",
      "CREG (m) = RLAT (R[n]);",
*************** op tab[] =
*** 558,571 ****
      "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;",
!     "/* FIXME: user mode */",
    },
- #endif
  
    /* sh-dsp */
    { "", "", "ldre @(<disp>,PC)", "10001110i8p1....",
--- 595,620 ----
      "SET_MOD (RLAT (R[n]));",
      "R[n] += 4;",
    },
    { "n", "n", "ldc.l @<REG_N>+,DBR", "0100nnnn11110110",
!     "if (SR_MD)",
!     "{ /* priv mode */",
!     "  MA (1);",
!     "  DBR = RLAT (R[n]);",
!     "  R[n] += 4;",
!     "}",
!     "else",
!     "  RAISE_EXCEPTION (SIGILL); /* user mode */",
!   },
!   { "n", "n", "ldc.l @<REG_N>+,SGR", "0100nnnn00110110",
!     "if (SR_MD)",
!     "{ /* priv mode */",
!     "  MA (1);",
!     "  SGR = RLAT (R[n]);",
!     "  R[n] += 4;",
!     "}",
!     "else",
!     "  RAISE_EXCEPTION (SIGILL); /* user mode */",
    },
  
    /* sh-dsp */
    { "", "", "ldre @(<disp>,PC)", "10001110i8p1....",
*************** op tab[] =
*** 575,580 ****
--- 624,643 ----
      "RS = SEXT (i) * 2 + 4 + PH2T (PC);",
    },
  
+   /* sh4a */
+   { "", "n", "ldrc <REG_N>", "0100nnnn00110100",
+     "SET_RC (R[n]);",
+     "loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);",
+     "CHECK_INSN_PTR (insn_ptr);",
+     "RE |= 1;",
+   },
+   { "", "", "ldrc #<imm>", "10001010i8*1....",
+     "SET_RC (i);",
+     "loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);",
+     "CHECK_INSN_PTR (insn_ptr);",
+     "RE |= 1;",
+   },
+ 
    { "", "n", "lds <REG_N>,<SREG_M>", "0100nnnnssss1010",
      "SREG (m) = R[n];",
    },
*************** op tab[] =
*** 777,790 ****
      "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];",
    },
--- 840,888 ----
      "WLAT (R[n], R[0]);",
    },
  
+   { "n", "0", "movco.l R0, @<REG_N>", "0000nnnn01110011", 
+     "/* LDST -> T */",
+     "SET_SR_T (LDST);",
+     "/* if (T) R0 -> (Rn) */",
+     "if (T)",
+     "  WLAT (R[n], R[0]);",
+     "/* 0 -> LDST */",
+     "SET_LDST (0);",
+   },
+ 
+   { "0", "n", "movli.l @<REG_N>, R0", "0000nnnn01100011", 
+     "/* 1 -> LDST */",
+     "SET_LDST (1);",
+     "/* (Rn) -> R0 */",
+     "R[0] = RLAT (R[n]);",
+     "/* if (interrupt/exception) 0 -> LDST */",
+     "/* (we don't simulate asynchronous interrupts/exceptions) */",
+   },
+ 
    { "n", "", "movt <REG_N>", "0000nnnn00101001",
      "R[n] = T;",
    },
  
+   { "0", "n", "movua.l @<REG_N>,R0", "0100nnnn10101001",
+     "int regn = R[n];",
+     "MA (1);",
+     "R[0] = (RBAT (regn) << 24) + (RBAT (regn + 1) << 16) + ",
+     "  (RBAT (regn + 2) << 8) + RBAT (regn + 3);",
+     "L (n);",
+   },
+   { "0n", "n", "movua.l @<REG_N>+,R0", "0100nnnn11101001",
+     "int regn = R[n];",
+     "MA (1);",
+     "R[0] = (RBAT (regn) << 24) + (RBAT (regn + 1) << 16) + ",
+     "  (RBAT (regn + 2) << 8) + RBAT (regn + 3);",
+     "R[n] += 4;",
+     "L (n);",
+   },
    { "", "mn", "mul.l <REG_M>,<REG_N>", "0000nnnnmmmm0111",
!     "MACL = ((int) R[n]) * ((int) R[m]);",
    },
! #if 0  /* FIXME: The above cast to int is not really portable.
! 	  It should be replaced by a SEXT32 macro.  */
    { "", "nm", "mul.l <REG_M>,<REG_N>", "0000nnnnmmmm0111",
      "MACL = R[n] * R[m];",
    },
*************** op tab[] =
*** 820,825 ****
--- 918,929 ----
      "R[n] = ~R[m];",
    },
  
+   /* sh4a */
+   { "", "n", "icbi @<REG_N>", "0000nnnn11100011",
+     "/* Except for the effect on the cache - which is not simulated -",
+     "   this is like a nop.  */",
+   },
+ 
    { "", "n", "ocbi @<REG_N>", "0000nnnn10010011",
      "RSBAT (R[n]); /* Take exceptions like byte load, otherwise noop.  */",
      "/* FIXME: Cache not implemented */",
*************** op tab[] =
*** 851,856 ****
--- 955,972 ----
      "   this is like a nop.  */",
    },
  
+   /* sh4a */
+   { "", "n", "prefi @<REG_N>", "0000nnnn11010011",
+     "/* Except for the effect on the cache - which is not simulated -",
+     "   this is like a nop.  */",
+   },
+ 
+   /* sh4a */
+   { "", "", "synco", "0000000010101011", 
+     "/* Except for the effect on the pipeline - which is not simulated -", 
+     "   this is like a nop.  */",
+   },
+ 
    { "n", "n", "rotcl <REG_N>", "0100nnnn00100100",
      "ult = R[n] < 0;",
      "R[n] = (R[n] << 1) | T;",
*************** op tab[] =
*** 898,903 ****
--- 1014,1031 ----
      "Delay_Slot (PC + 2);",
    },
  
+   /* sh4a */
+   { "", "", "setdmx", "0000000010011000",
+     "saved_state.asregs.cregs.named.sr |=  SR_MASK_DMX;"
+     "saved_state.asregs.cregs.named.sr &= ~SR_MASK_DMY;"
+   },
+ 
+   /* sh4a */
+   { "", "", "setdmy", "0000000011001000",
+     "saved_state.asregs.cregs.named.sr |=  SR_MASK_DMY;"
+     "saved_state.asregs.cregs.named.sr &= ~SR_MASK_DMX;"
+   },
+ 
    /* sh-dsp */
    { "", "n", "setrc <REG_N>", "0100nnnn00010100",
      "SET_RC (R[n]);",
*************** op tab[] =
*** 980,1010 ****
      "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);",
--- 1108,1150 ----
      "R[n] = CREG (m);",
    },
  
    { "n", "", "stc SGR,<REG_N>", "0000nnnn00111010",
!     "if (SR_MD)",
!     "  R[n] = SGR; /* priv mode */",
!     "else",
!     "  RAISE_EXCEPTION (SIGILL); /* user mode */",
    },
    { "n", "", "stc DBR,<REG_N>", "0000nnnn11111010",
!     "if (SR_MD)",
!     "  R[n] = DBR; /* priv mode */",
!     "else",
!     "  RAISE_EXCEPTION (SIGILL); /* user mode */",
    },
    { "n", "n", "stc.l <CREG_M>,@-<REG_N>", "0100nnnnmmmm0011",
      "MA (1);",
      "R[n] -= 4;",
      "WLAT (R[n], CREG (m));",
    },
    { "n", "n", "stc.l SGR,@-<REG_N>", "0100nnnn00110010",
!     "if (SR_MD)",
!     "{ /* priv mode */",
!     "  MA (1);",
!     "  R[n] -= 4;",
!     "  WLAT (R[n], SGR);",
!     "}",
!     "else",
!     "  RAISE_EXCEPTION (SIGILL); /* user mode */",
    },
    { "n", "n", "stc.l DBR,@-<REG_N>", "0100nnnn11110010",
!     "if (SR_MD)",
!     "{ /* priv mode */",
!     "  MA (1);",
!     "  R[n] -= 4;",
!     "  WLAT (R[n], DBR);",
!     "}",
!     "else",
!     "  RAISE_EXCEPTION (SIGILL); /* user mode */",
    },
  
    { "n", "", "sts <SREG_M>,<REG_N>", "0000nnnnssss1010",
      "R[n] = SREG (m);",
*************** op movsxy_tab[] =
*** 1258,1313 ****
      "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 */",
    },
--- 1398,1515 ----
      "WLAT (R[n], SEXT (DSP_R (m)));",
      "R[n] += R[8];",
    },
!   { "", "n", "movx.w @<REG_xy>,<DSP_XY>",   "111100xyXY0001??",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
!     "if (iword & 3)",
!     "  {",
!     "    iword &= 0xfd53; goto top;",
!     "  }",
!   },
!   { "", "n", "movx.l @<REG_xy>,<DSP_XY>",   "111100xyXY010100",
!     "DSP_R (m) = RLAT (R[n]);",
    },
!   { "n", "n", "movx.w @<REG_xy>+,<DSP_XY>", "111100xyXY0010??",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;",
!     "if (iword & 3)",
!     "  {",
!     "    iword &= 0xfd53; goto top;",
!     "  }",
!   },
!   { "n", "n", "movx.l @<REG_xy>+,<DSP_XY>", "111100xyXY011000",
!     "DSP_R (m) = RLAT (R[n]);",
!     "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 4;",
    },
!   { "n", "n8","movx.w @<REG_xy>+REG_8,<DSP_XY>", "111100xyXY0011??",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
!     "if (iword & 3)",
!     "  {",
!     "    iword &= 0xfd53; goto top;",
!     "  }",
!   },
!   { "n", "n8","movx.l @<REG_xy>+REG_8,<DSP_XY>", "111100xyXY011100",
!     "DSP_R (m) = RLAT (R[n]);",
!     "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
    },
!   { "", "n", "movx.w <DSP_Ax>,@<REG_xy>",   "111100xyax1001??",
      "WWAT (R[n], DSP_R (m) >> 16);",
!     "if (iword & 3)",
!     "  {",
!     "    iword &= 0xfd53; goto top;",
!     "  }",
!   },
!   { "", "n", "movx.l <DSP_Ax>,@<REG_xy>",   "111100xyax110100",
!     "WLAT (R[n], DSP_R (m));",
    },
!   { "n", "n", "movx.w <DSP_Ax>,@<REG_xy>+", "111100xyax1010??",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 2;",
!     "if (iword & 3)",
!     "  {",
!     "    iword &= 0xfd53; goto top;",
!     "  }",
    },
!   { "n", "n", "movx.l <DSP_Ax>,@<REG_xy>+", "111100xyax111000",
!     "WLAT (R[n], DSP_R (m));",
!     "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : 4;",
!   },
!   { "n", "n8","movx.w <DSP_Ax>,@<REG_xy>+REG_8","111100xyax1011??",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
!     "if (iword & 3)",
!     "  {",
!     "    iword &= 0xfd53; goto top;",
!     "  }",
!   },
!   { "n", "n8","movx.l <DSP_Ax>,@<REG_xy>+REG_8","111100xyax111100",
!     "WLAT (R[n], DSP_R (m));",
!     "R[n] += ((R[n] & 0xffff) == MOD_ME) ? MOD_DELTA : R[8];",
    },
!   { "", "n", "movy.w @<REG_yx>,<DSP_YX>",   "111100yxYX000001",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
    },
!   { "n", "n", "movy.w @<REG_yx>+,<DSP_YX>", "111100yxYX000010",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;",
    },
!   { "n", "n9","movy.w @<REG_yx>+REG_9,<DSP_YX>", "111100yxYX000011",
      "DSP_R (m) = RSWAT (R[n]) << 16;",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
    },
!   { "", "n", "movy.w <DSP_Ay>,@<REG_yx>",   "111100yxAY010001",
      "WWAT (R[n], DSP_R (m) >> 16);",
    },
!   { "n", "n", "movy.w <DSP_Ay>,@<REG_yx>+", "111100yxAY010010",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 2;",
    },
!   { "n", "n9", "movy.w <DSP_Ay>,@<REG_yx>+REG_9", "111100yxAY010011",
      "WWAT (R[n], DSP_R (m) >> 16);",
      "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
    },
+   { "", "n", "movy.l @<REG_yx>,<DSP_YX>",   "111100yxYX100001",
+     "DSP_R (m) = RLAT (R[n]);",
+   },
+   { "n", "n", "movy.l @<REG_yx>+,<DSP_YX>", "111100yxYX100010",
+     "DSP_R (m) = RLAT (R[n]);",
+     "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 4;",
+   },
+   { "n", "n9","movy.l @<REG_yx>+REG_9,<DSP_YX>", "111100yxYX100011",
+     "DSP_R (m) = RLAT (R[n]);",
+     "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
+   },
+   { "", "n", "movy.l <DSP_Ay>,@<REG_yx>",   "111100yxAY110001",
+     "WLAT (R[n], DSP_R (m));",
+   },
+   { "n", "n", "movy.l <DSP_Ay>,@<REG_yx>+", "111100yxAY110010",
+     "WLAT (R[n], DSP_R (m));",
+     "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : 4;",
+   },
+   { "n", "n9", "movy.l <DSP_Ay>,@<REG_yx>+REG_9", "111100yxAY110011",
+     "WLAT (R[n], DSP_R (m));",
+     "R[n] += ((R[n] | ~0xffff) == MOD_ME) ? MOD_DELTA : R[9];",
+   },
    { "", "", "nopx nopy", "1111000000000000",
      "/* nop */",
    },
*************** op ppi_tab[] =
*** 1462,1468 ****
      "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);",
--- 1664,1670 ----
      "DSR |= carry;\n",
      "goto assign_z;\n",
    },
!   { "","", "pcmp Sx,Sy",	"10000100xxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
      "int Sy = DSP_R (y);",
*************** op ppi_tab[] =
*** 1479,1484 ****
--- 1681,1704 ----
    },
    { "","", "pwad Sx,Sy,Dz",	"10110100xxyyzzzz",
    },
+   { "","", "(if cc) pabs Sx,Dz",	"100010ccxx01zzzz",
+     "/* FIXME: duplicate code pabs.  */",
+     "res = DSP_R (x);",
+     "res_grd = GET_DSP_GRD (x);",
+     "if (res >= 0)",
+     "  carry = 0;",
+     "else",
+     "  {",
+     "    res = -res;",
+     "    carry = (res != 0); /* The manual has a bug here.  */", 
+     "    res_grd = -res_grd - carry;", 
+     "  }",
+     "COMPUTE_OVERFLOW;",
+     "/* ??? The re-computing of overflow after",
+     "   saturation processing is specific to pabs.  */",
+     "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;",
+     "ADD_SUB_GE;",
+   },
    { "","", "pabs Sx,Dz",	"10001000xx..zzzz",
      "res = DSP_R (x);",
      "res_grd = GET_DSP_GRD (x);",
*************** op ppi_tab[] =
*** 1496,1501 ****
--- 1716,1733 ----
      "overflow = res_grd != SIGN32 (res) ? DSR_MASK_V : 0;",
      "ADD_SUB_GE;",
    },
+ 
+   { "","", "(if cc) prnd Sx,Dz",	"100110ccxx01zzzz",
+     "/* FIXME: duplicate code prnd.  */",
+     "int Sx = DSP_R (x);",
+     "int Sx_grd = GET_DSP_GRD (x);",
+     "",
+     "res = (Sx + 0x8000) & 0xffff0000;",
+     "carry = (unsigned) res < (unsigned) Sx;",
+     "res_grd = Sx_grd + carry;",
+     "COMPUTE_OVERFLOW;",
+     "ADD_SUB_GE;",
+   },
    { "","", "prnd Sx,Dz",	"10011000xx..zzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
*************** op ppi_tab[] =
*** 1506,1511 ****
--- 1738,1768 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
+ 
+   { "","", "(if cc) pabs Sy,Dz",	"101010cc01yyzzzz",
+     "/* FIXME: duplicate code pabs.  */",
+     "res = DSP_R (y);",
+     "res_grd = 0;",
+     "overflow = 0;",
+     "greater_equal = DSR_MASK_G;",
+     "if (res >= 0)",
+     "  carry = 0;",
+     "else",
+     "  {",
+     "    res = -res;",
+     "    carry = 1;",
+     "    if (res < 0)",
+     "      {",
+     "        if (S)",
+     "          res = 0x7fffffff;",
+     "        else",
+     "          {",
+     "            overflow = DSR_MASK_V;",
+     "            greater_equal = 0;",
+     "          }",
+     "      }",
+     "  }",
+   },
    { "","", "pabs Sy,Dz",	"10101000..yyzzzz",
      "res = DSP_R (y);",
      "res_grd = 0;",
*************** op ppi_tab[] =
*** 1529,1534 ****
--- 1786,1802 ----
      "      }",
      "  }",
    },
+   { "","", "(if cc) prnd Sy,Dz",	"101110cc01yyzzzz",
+     "/* FIXME: duplicate code prnd.  */",
+     "int Sy = DSP_R (y);",
+     "int Sy_grd = SIGN32 (Sy);",
+     "",
+     "res = (Sy + 0x8000) & 0xffff0000;",
+     "carry = (unsigned) res < (unsigned) Sy;",
+     "res_grd = Sy_grd + carry;",
+     "COMPUTE_OVERFLOW;",
+     "ADD_SUB_GE;",
+   },
    { "","", "prnd Sy,Dz",	"10111000..yyzzzz",
      "int Sy = DSP_R (y);",
      "int Sy_grd = SIGN32 (Sy);",
*************** op ppi_tab[] =
*** 1609,1614 ****
--- 1877,1894 ----
      "COMPUTE_OVERFLOW;",
      "ADD_SUB_GE;",
    },
+   { "","", "(if cc) psub Sy,Sx,Dz",	"100001ccxxyyzzzz",
+     "int Sx = DSP_R (x);",
+     "int Sx_grd = GET_DSP_GRD (x);",
+     "int Sy = DSP_R (y);",
+     "int Sy_grd = SIGN32 (Sy);",
+     "",
+     "res = Sy - Sx;",
+     "carry = (unsigned) res > (unsigned) Sy;",
+     "res_grd = Sy_grd - Sx_grd - carry;",
+     "COMPUTE_OVERFLOW;",
+     "ADD_SUB_GE;",
+   },
    { "","", "(if cc) padd Sx,Sy,Dz",	"101100ccxxyyzzzz",
      "int Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
*************** op ppi_tab[] =
*** 1698,1703 ****
--- 1978,1998 ----
      "overflow = 0;",
      "greater_equal = 1;",
    },
+   { "","", "pclr Du pmuls Se,Sf,Dg",	"0100eeff0001gguu",
+     "/* Do multiply.  */",
+     "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;",
+     "if (res == 0x80000000)",
+     "  res = 0x7fffffff;",
+     "DSP_R (g) = res;",
+     "DSP_GRD (g) = SIGN32 (res);",
+     "/* FIXME: update DSR based on results of multiply!  */",
+     "",
+     "/* Do clr.  */",
+     "z = u;",
+     "res = 0;",
+     "res_grd = 0;",
+     "goto assign_z;",
+   },
    { "","", "(if cc) pdmsb Sx,Dz",	"100111ccxx..zzzz",
      "unsigned Sx = DSP_R (x);",
      "int Sx_grd = GET_DSP_GRD (x);",
*************** op ppi_tab[] =
*** 1813,1818 ****
--- 2108,2134 ----
      "  MACL = DSP_R (z) = res;",
      "return;",
    },
+   /* sh4a */
+   { "","", "(if cc) pswap Sx,Dz",	"100111ccxx01zzzz",
+     "int Sx = DSP_R (x);",
+     "",
+     "res = ((Sx & 0xffff) * 65536) + ((Sx >> 16) & 0xffff);",
+     "res_grd = GET_DSP_GRD (x);",
+     "carry = 0;",
+     "overflow = 0;",
+     "greater_equal = res & 0x80000000 ? 0 : DSR_MASK_G;",
+   },
+   /* sh4a */
+   { "","", "(if cc) pswap Sy,Dz",	"101111cc01yyzzzz",
+     "int Sy = DSP_R (y);",
+     "",
+     "res = ((Sy & 0xffff) * 65536) + ((Sy >> 16) & 0xffff);",
+     "res_grd = SIGN32 (Sy);",
+     "carry = 0;",
+     "overflow = 0;",
+     "greater_equal = res & 0x80000000 ? 0 : DSR_MASK_G;",
+   },
+ 
    {0, 0}
  };
  
*************** expand_opcode (val, i, s)
*** 1976,2001 ****
  	  exit (1);
  	case '0':
  	case '1':
! 	    /* Consume an arbitrary number of ones and zeros.  */
! 	    do {
! 	      j = (j << 1) + (s[m++] - '0');
! 	    } while (s[m] == '0' || s[m] == '1');
! 	    expand_opcode ((val << m) | j, i, s + m);
! 	    break;
! 
  	case 'N':	/* NN -- four-way fork */
  	  for (j = 0; j < 4; j++)
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
! 	case 'x':	/* xx -- 2-way fork */
! 	  /* Cross-breeding with movy moved to separate function.  */
! 	  for (j = 0; j < 4; j += 2)
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
! 	case 'y':	/* yy -- two-way fork */
! 	  for (j = 0; j < 2; j++)
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
  	case 'i':	/* eg. "i8*1" */
  	case '.':	/* "...." is a wildcard */
  	case 'n':
--- 2292,2323 ----
  	  exit (1);
  	case '0':
  	case '1':
! 	  /* Consume an arbitrary number of ones and zeros.  */
! 	  do {
! 	    j = (j << 1) + (s[m++] - '0');
! 	  } while (s[m] == '0' || s[m] == '1');
! 	  expand_opcode ((val << m) | j, i, s + m);
! 	  break;
  	case 'N':	/* NN -- four-way fork */
  	  for (j = 0; j < 4; j++)
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
! 	case 'x':	/* xx or xy -- two-way or four-way fork */
! 	  for (j = 0; j < 4; j += (s[1] == 'x' ? 2 : 1))
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
! 	case 'y':	/* yy or yx -- two-way or four-way fork */
! 	  for (j = 0; j < (s[1] == 'x' ? 4 : 2); j++)
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
+ 	case '?':	/* Seven-way "wildcard" fork for movxy */
+ 	  expand_opcode ((val << 2), i, s + 2);
+ 	  for (j = 1; j < 4; j++)
+ 	    {
+ 	      expand_opcode ((val << 2) | j, i, s + 2);
+ 	      expand_opcode ((val << 2) | (j + 16), i, s + 2);
+ 	    }
+ 	  break;
  	case 'i':	/* eg. "i8*1" */
  	case '.':	/* "...." is a wildcard */
  	case 'n':
*************** expand_opcode (val, i, s)
*** 2033,2049 ****
  	    expand_opcode ((val << 4) | j, i, s + 4);
  	  break;
  	case 'X':
  	case 'a':
! 	  /* XX, aa -- two-way fork */
! 	  for (j = 0; j < 4; j += 2)
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
  	case 'Y':
  	case 'A':
! 	  /* YY, AA -- two-way fork */
! 	  for (j = 0; j < 2; j++)
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
  	}
      }
  }
--- 2355,2395 ----
  	    expand_opcode ((val << 4) | j, i, s + 4);
  	  break;
  	case 'X':
+ 	  /* XX/XY -- 2/4 way fork.  */
+ 	  for (j = 0; j < 4; j += (s[1] == 'X' ? 2 : 1))
+ 	    expand_opcode ((val << 2) | j, i, s + 2);
+ 	  break;
  	case 'a':
! 	  /* aa/ax -- 2/4 way fork.  */
! 	  for (j = 0; j < 4; j += (s[1] == 'a' ? 2 : 1))
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
  	case 'Y':
+ 	  /* YY/YX -- 2/4 way fork.  */
+ 	  for (j = 0; j < (s[1] == 'Y' ? 2 : 4); j += 1)
+ 	    expand_opcode ((val << 2) | j, i, s + 2);
+ 	  break;
  	case 'A':
! 	  /* AA/AY: 2/4 way fork.  */
! 	  for (j = 0; j < (s[1] == 'A' ? 2 : 4); j += 1)
  	    expand_opcode ((val << 2) | j, i, s + 2);
  	  break;
+ 	case 'v':
+ 	  /* vv(VV) -- 4(16) way fork.  */
+ 	  /* Vector register fv0/4/8/12.  */
+ 	  if (s[2] == 'V')
+ 	    {
+ 	      /* 2 vector registers.  */
+ 	      for (j = 0; j < 15; j++)
+ 		expand_opcode ((val << 4) | j, i, s + 4);
+ 	    }
+ 	  else
+ 	    {
+ 	      /* 1 vector register.  */
+ 	      for (j = 0; j < 4; j += 1)
+ 		expand_opcode ((val << 2) | j, i, s + 2);
+ 	    }
+ 	  break;
  	}
      }
  }
*************** expand_ppi_movxy ()
*** 2113,2136 ****
    int i;
  
    for (i = 0xf000; i < 0xf400; i++)
-     if ((i & 3) == 0 && (i & 12) != 0 && table[i] != 0)
-       {
- 	/* A movx insn, which needs to be filled out with the 
- 	   corresponding movy insns.  This used to be done in
- 	   expand_opcode.  */
- 	int m, mv;
- 
- 	for (m = 0; m < 32; m++)
- 	  {
- 	    /* Ignore illegal nopy */
- 	    if ((m & 7) == 0 && m != 0)
- 	      continue;
- 	    mv = m & 3 | (m & 4) << 2 | (m & 8) << 3 | (m & 16) << 4;
- 	    table [i | mv] = table [i];
- 	  }
-       }
- 
-   for (i = 0xf000; i < 0xf400; i++)
      if (table[i])
        table[i + 0x800] = table[0xf800];
  }
--- 2459,2464 ----
*************** gensim_caselist (p)
*** 2161,2166 ****
--- 2489,2506 ----
  		       *s);
  	      exit (1);
  	      break;
+ 	    case '?':
+ 	      /* Wildcard expansion, nothing to do here.  */
+ 	      s += 2;
+ 	      break;
+ 	    case 'v':
+ 	      printf ("      int v1 = ((iword >> 10) & 3) * 4;\n");
+ 	      s += 2;
+ 	      break;
+ 	    case 'V':
+ 	      printf ("      int v2 = ((iword >> 8)  & 3) * 4;\n");
+ 	      s += 2;
+ 	      break;
  	    case '0':
  	    case '1':
  	      s += 2;
*************** gensim_caselist (p)
*** 2179,2190 ****
  	      s += 2;
  	      break;
  	    case 'x':
! 	      printf ("      int n = ((iword >> 9) & 1) + 4;\n");
  	      needn = 1;
  	      s += 2;
  	      break;
  	    case 'y':
! 	      printf ("      int n = ((iword >> 8) & 1) + 6;\n");
  	      needn = 1;
  	      s += 2;
  	      break;
--- 2519,2544 ----
  	      s += 2;
  	      break;
  	    case 'x':
! 	      if (s[1] == 'y')	/* xy */
! 		{
! 		  printf ("      int n = (iword & 3) ? \n");
! 		  printf ("              ((iword >> 9) & 1) + 4 : \n");
! 		  printf ("              REG_xy ((iword >> 8) & 3);\n");
! 		}
! 	      else
! 		printf ("      int n = ((iword >> 9) & 1) + 4;\n");
  	      needn = 1;
  	      s += 2;
  	      break;
  	    case 'y':
! 	      if (s[1] == 'x')	/* yx */
! 		{
! 		  printf ("      int n = (iword & 0xc) ? \n");
! 		  printf ("              ((iword >> 8) & 1) + 6 : \n");
! 		  printf ("              REG_yx ((iword >> 8) & 3);\n");
! 		}
! 	      else
! 		printf ("      int n = ((iword >> 8) & 1) + 6;\n");
  	      needn = 1;
  	      s += 2;
  	      break;
*************** gensim_caselist (p)
*** 2197,2215 ****
  	      s += 4;
  	      break;
  	    case 'X':
! 	      printf ("      int m = ((iword >> 7) & 1) + 8;\n");
  	      s += 2;
  	      break;
  	    case 'a':
! 	      printf ("      int m = 7 - ((iword >> 6) & 2);\n");
  	      s += 2;
  	      break;
  	    case 'Y':
! 	      printf ("      int m = ((iword >> 6) & 1) + 10;\n");
  	      s += 2;
  	      break;
  	    case 'A':
! 	      printf ("      int m = 7 - ((iword >> 5) & 2);\n");
  	      s += 2;
  	      break;
  
--- 2551,2597 ----
  	      s += 4;
  	      break;
  	    case 'X':
! 	      if (s[1] == 'Y')	/* XY */
! 		{
! 		  printf ("      int m = (iword & 3) ? \n");
! 		  printf ("              ((iword >> 7) & 1) + 8 : \n");
! 		  printf ("              DSP_xy ((iword >> 6) & 3);\n");
! 		}
! 	      else
! 		printf ("      int m = ((iword >> 7) & 1) + 8;\n");
  	      s += 2;
  	      break;
  	    case 'a':
! 	      if (s[1] == 'x')	/* ax */
! 		{
! 		  printf ("      int m = (iword & 3) ? \n");
! 		  printf ("              7 - ((iword >> 6) & 2) : \n");
! 		  printf ("              DSP_ax ((iword >> 6) & 3);\n");
! 		}
! 	      else
! 		printf ("      int m = 7 - ((iword >> 6) & 2);\n");
  	      s += 2;
  	      break;
  	    case 'Y':
! 	      if (s[1] == 'X')	/* YX */
! 		{
! 		  printf ("      int m = (iword & 0xc) ? \n");
! 		  printf ("              ((iword >> 6) & 1) + 10 : \n");
! 		  printf ("              DSP_yx ((iword >> 6) & 3);\n");
! 		}
! 	      else
! 		printf ("      int m = ((iword >> 6) & 1) + 10;\n");
  	      s += 2;
  	      break;
  	    case 'A':
! 	      if (s[1] == 'Y')	/* AY */
! 		{
! 		  printf ("      int m = (iword & 0xc) ? \n");
! 		  printf ("              7 - ((iword >> 5) & 2) : \n");
! 		  printf ("              DSP_ay ((iword >> 6) & 3);\n");
! 		}
! 	      else
! 		printf ("      int m = 7 - ((iword >> 5) & 2);\n");
  	      s += 2;
  	      break;
  
*************** static void
*** 2303,2308 ****
--- 2685,2702 ----
  gensim ()
  {
    printf ("{\n");
+   printf ("/* REG_xy = [r4, r5, r0, r1].  */\n");
+   printf ("#define REG_xy(R) ((R)==0 ? 4 : (R)==2 ? 5 : (R)==1 ?  0 :  1)\n");
+   printf ("/* REG_yx = [r6, r7, r2, r3].  */\n");
+   printf ("#define REG_yx(R) ((R)==0 ? 6 : (R)==1 ? 7 : (R)==2 ?  2 :  3)\n");
+   printf ("/* DSP_ax = [a0, a1, x0, x1].  */\n");
+   printf ("#define DSP_ax(R) ((R)==0 ? 7 : (R)==2 ? 5 : (R)==1 ?  8 :  9)\n");
+   printf ("/* DSP_ay = [a0, a1, y0, y1].  */\n");
+   printf ("#define DSP_ay(R) ((R)==0 ? 7 : (R)==1 ? 5 : (R)==2 ? 10 : 11)\n");
+   printf ("/* DSP_xy = [x0, x1, y0, y1].  */\n");
+   printf ("#define DSP_xy(R) ((R)==0 ? 8 : (R)==2 ? 9 : (R)==1 ? 10 : 11)\n");
+   printf ("/* DSP_yx = [y0, y1, x0, x1].  */\n");
+   printf ("#define DSP_yx(R) ((R)==0 ? 10 : (R)==1 ? 11 : (R)==2 ? 8 : 9)\n");
    printf ("  switch (jump_table[iword]) {\n");
  
    gensim_caselist (tab);
*************** gendefines ()
*** 2341,2347 ****
  static int ppi_index;
  
  /* Take a ppi code, expand all varying fields in it and fill all the
!    right entries in 'table' with the opcode index.  */
  
  static void
  expand_ppi_code (val, i, s)
--- 2735,2742 ----
  static int ppi_index;
  
  /* Take a ppi code, expand all varying fields in it and fill all the
!    right entries in 'table' with the opcode index.  
!    NOTE: tail recursion optimization removed for simplicity.  */
  
  static void
  expand_ppi_code (val, i, s)
*************** expand_ppi_code (val, i, s)
*** 2351,2396 ****
  {
    int j;
  
!   for (;;)
      {
!       switch (s[0])
! 	{
! 	default:
! 	  fprintf (stderr, "gencode/expand_ppi_code: Illegal char '%c'\n",
! 		   s[0]);
! 	  exit (2);
! 	  break;
! 	/* The last eight bits are disregarded for the switch table.  */
! 	case 'm':
! 	case 'x':
! 	case '.':
! 	  table[val] = i;
! 	  return;
! 	case '0':
! 	  val += val;
! 	  s++;
! 	  break;
! 	case '1':
! 	  val += val + 1;
! 	  s++;
! 	  break;
! 	case 'i':
! 	case 'e': case 'f':
! 	  val += val;
! 	  s++;
! 	  expand_ppi_code (val, i, s);
! 	  val++;
! 	  break;
! 	case 'c':
! 	  val <<= 2;
! 	  s += 2;
! 	  val++;
! 	  expand_ppi_code (val, ppi_index++, s);
! 	  val++;
! 	  expand_ppi_code (val, i, s);
! 	  val++;
! 	  break;
! 	}
      }
  }
  
--- 2746,2785 ----
  {
    int j;
  
!   switch (s[0])
      {
!     default:
!       fprintf (stderr, "gencode/expand_ppi_code: Illegal char '%c'\n", s[0]);
!       exit (2);
!       break;
!     case 'g':
!     case 'z':
!       /* The last four bits are disregarded for the switch table.  */
!       table[val] = i;
!       return;
!     case 'm':
!       /* Four-bit expansion.  */
!       for (j = 0; j < 16; j++)
! 	expand_ppi_code ((val << 4) + j, i, s + 4);
!       break;
!     case '.':
!     case '0':
!       expand_ppi_code ((val << 1), i, s + 1);
!       break;
!     case '1':
!       expand_ppi_code ((val << 1) + 1, i, s + 1);
!       break;
!     case 'i':
!     case 'e': case 'f':
!     case 'x': case 'y':
!       expand_ppi_code ((val << 1), i, s + 1);
!       expand_ppi_code ((val << 1) + 1, i, s + 1);
!       break;
!     case 'c':
!       expand_ppi_code ((val << 2) + 1, ppi_index++, s + 2);
!       expand_ppi_code ((val << 2) + 2, i, s + 2);
!       expand_ppi_code ((val << 2) + 3, i, s + 2);
!       break;
      }
  }
  
*************** ppi_gensim ()
*** 2442,2459 ****
    printf ("ppi_insn (iword)\n");
    printf ("     int iword;\n");
    printf ("{\n");
    printf ("  static char e_tab[] = { 8,  9, 10,  5};\n");
    printf ("  static char f_tab[] = {10, 11,  8,  5};\n");
    printf ("  static char x_tab[] = { 8,  9,  7,  5};\n");
    printf ("  static char y_tab[] = {10, 11, 12, 14};\n");
    printf ("  static char g_tab[] = {12, 14,  7,  5};\n");
    printf ("  static char u_tab[] = { 8, 10,  7,  5};\n");
    printf ("\n");
    printf ("  int z;\n");
    printf ("  int res, res_grd;\n");
    printf ("  int carry, overflow, greater_equal;\n");
    printf ("\n");
!   printf ("  switch (ppi_table[iword >> 8]) {\n");
  
    for (; p->name; p++)
      {
--- 2831,2854 ----
    printf ("ppi_insn (iword)\n");
    printf ("     int iword;\n");
    printf ("{\n");
+   printf ("  /* 'ee' = [x0, x1, y0, a1] */\n");
    printf ("  static char e_tab[] = { 8,  9, 10,  5};\n");
+   printf ("  /* 'ff' = [y0, y1, x0, a1] */\n");
    printf ("  static char f_tab[] = {10, 11,  8,  5};\n");
+   printf ("  /* 'xx' = [x0, x1, a0, a1]  */\n");
    printf ("  static char x_tab[] = { 8,  9,  7,  5};\n");
+   printf ("  /* 'yy' = [y0, y1, m0, m1]  */\n");
    printf ("  static char y_tab[] = {10, 11, 12, 14};\n");
+   printf ("  /* 'gg' = [m0, m1, a0, a1]  */\n");
    printf ("  static char g_tab[] = {12, 14,  7,  5};\n");
+   printf ("  /* 'uu' = [x0, y0, a0, a1]  */\n");
    printf ("  static char u_tab[] = { 8, 10,  7,  5};\n");
    printf ("\n");
    printf ("  int z;\n");
    printf ("  int res, res_grd;\n");
    printf ("  int carry, overflow, greater_equal;\n");
    printf ("\n");
!   printf ("  switch (ppi_table[iword >> 4]) {\n");
  
    for (; p->name; p++)
      {
*************** main (ac, av)
*** 2614,2620 ****
  
  	  memset (table, 0, sizeof table);
  	  ppi_filltable ();
! 	  dumptable ("ppi_table", 1 << 8, 0);
  	}
        else if (strcmp (av[1], "-x") == 0)
  	{
--- 3009,3015 ----
  
  	  memset (table, 0, sizeof table);
  	  ppi_filltable ();
! 	  dumptable ("ppi_table", 1 << 12, 0);
  	}
        else if (strcmp (av[1], "-x") == 0)
  	{
Index: interp.c
===================================================================
RCS file: /cvs/src/src/sim/sh/interp.c,v
retrieving revision 1.12
diff -p -r1.12 interp.c
*** interp.c	3 Nov 2003 14:14:15 -0000	1.12
--- interp.c	9 Jan 2004 19:33:38 -0000
***************
*** 1,4 ****
! /* Simulator for the Hitachi SH architecture.
  
     Written by Steve Chamberlain of Cygnus Support.
     sac@cygnus.com
--- 1,4 ----
! /* Simulator for the Renesas (formerly Hitachi) / SuperH Inc. SH architecture.
  
     Written by Steve Chamberlain of Cygnus Support.
     sac@cygnus.com
*************** typedef union
*** 120,125 ****
--- 120,128 ----
  	    int re;
  	    /* sh3 */
  	    int bank[8];
+ 	    int dbr;		/* debug base register */
+ 	    int sgr;		/* saved gr15 */
+ 	    int ldst;		/* load/store flag (boolean) */
  	  } named;
  	int i[16];
        } cregs;
*************** static int target_dsp;
*** 167,176 ****
  static int host_little_endian;
  static char **prog_argv;
  
- #if 1
  static int maskw = 0;
  static int maskl = 0;
- #endif
  
  static SIM_OPEN_KIND sim_kind;
  static char *myname;
--- 170,177 ----
*************** static char *myname;
*** 189,196 ****
--- 190,199 ----
  #define CREG(n)	(saved_state.asregs.cregs.i[(n)])
  #define GBR 	saved_state.asregs.cregs.named.gbr
  #define VBR 	saved_state.asregs.cregs.named.vbr
+ #define DBR 	saved_state.asregs.cregs.named.dbr
  #define SSR	saved_state.asregs.cregs.named.ssr
  #define SPC	saved_state.asregs.cregs.named.spc
+ #define SGR 	saved_state.asregs.cregs.named.sgr
  #define SREG(n)	(saved_state.asregs.sregs.i[(n)])
  #define MACH 	saved_state.asregs.sregs.named.mach
  #define MACL 	saved_state.asregs.sregs.named.macl
*************** static char *myname;
*** 228,233 ****
--- 231,237 ----
  #define Q 	((saved_state.asregs.cregs.named.sr & SR_MASK_Q) != 0)
  #define S 	((saved_state.asregs.cregs.named.sr & SR_MASK_S) != 0)
  #define T 	((saved_state.asregs.cregs.named.sr & SR_MASK_T) != 0)
+ #define LDST	((saved_state.asregs.cregs.named.ldst) != 0)
  
  #define SR_BL ((saved_state.asregs.cregs.named.sr & SR_MASK_BL) != 0)
  #define SR_RB ((saved_state.asregs.cregs.named.sr & SR_MASK_RB) != 0)
*************** do { \
*** 249,254 ****
--- 253,259 ----
  #define SET_SR_Q(EXP) SET_SR_BIT ((EXP), SR_MASK_Q)
  #define SET_SR_S(EXP) SET_SR_BIT ((EXP), SR_MASK_S)
  #define SET_SR_T(EXP) SET_SR_BIT ((EXP), SR_MASK_T)
+ #define SET_LDST(EXP) (saved_state.asregs.cregs.named.ldst = ((EXP) != 0))
  
  /* stc currently relies on being able to read SR without modifications.  */
  #define GET_SR() (saved_state.asregs.cregs.named.sr - 0)
*************** macl (regs, memory, n, m)
*** 1411,1416 ****
--- 1416,1447 ----
    MACH = mach;
  }
  
+ 
+ /* GET_LOOP_BOUNDS {EXTENDED}
+    These two functions compute the actual starting and ending point
+    of the repeat loop, based on the RS and RE registers (repeat start, 
+    repeat stop).  The extended version is called for LDRC, and the
+    regular version is called for SETRC.  The difference is that for
+    LDRC, the loop start and end instructions are literally the ones
+    pointed to by RS and RE -- for SETRC, they're not (see docs).  */
+ 
+ static struct loop_bounds
+ get_loop_bounds_ext (rs, re, memory, mem_end, maskw, endianw)
+      int rs, re;
+      unsigned char *memory, *mem_end;
+      int maskw, endianw;
+ {
+   struct loop_bounds loop;
+ 
+   /* FIXME: should I verify RS < RE?  */
+   loop.start = PT2H (RS);	/* FIXME not using the params?  */
+   loop.end   = PT2H (RE & ~1);	/* Ignore bit 0 of RE.  */
+   SKIP_INSN (loop.end);
+   if (loop.end >= mem_end)
+     loop.end = PT2H (0);
+   return loop;
+ }
+ 
  float
  fsca_s (int in, double (*f) (double))
  {
*************** init_dsp (abfd)
*** 1541,1547 ****
    int was_dsp = target_dsp;
    unsigned long mach = bfd_get_mach (abfd);
  
!   if (mach == bfd_mach_sh_dsp || mach == bfd_mach_sh3_dsp)
      {
        int ram_area_size, xram_start, yram_start;
        int new_select;
--- 1572,1580 ----
    int was_dsp = target_dsp;
    unsigned long mach = bfd_get_mach (abfd);
  
!   if (mach == bfd_mach_sh_dsp  || 
!       mach == bfd_mach_sh4al_dsp ||
!       mach == bfd_mach_sh3_dsp)
      {
        int ram_area_size, xram_start, yram_start;
        int new_select;
*************** init_dsp (abfd)
*** 1556,1562 ****
  	  xram_start = 0x0800f000;
  	  ram_area_size = 0x1000;
  	}
!       if (mach == bfd_mach_sh3_dsp)
  	{
  	  /* SH7612:
  	     8KB each for X & Y memory;
--- 1589,1595 ----
  	  xram_start = 0x0800f000;
  	  ram_area_size = 0x1000;
  	}
!       if (mach == bfd_mach_sh3_dsp || mach == bfd_mach_sh4al_dsp)
  	{
  	  /* SH7612:
  	     8KB each for X & Y memory;
*************** sim_resume (sd, step, siggnal)
*** 1740,1746 ****
    memory = saved_state.asregs.memory;
    mem_end = memory + saved_state.asregs.msize;
  
!   loop = get_loop_bounds (RS, RE, memory, mem_end, maskw, endianw);
    insn_ptr = PT2H (saved_state.asregs.pc);
    CHECK_INSN_PTR (insn_ptr);
  
--- 1773,1783 ----
    memory = saved_state.asregs.memory;
    mem_end = memory + saved_state.asregs.msize;
  
!   if (RE & 1)
!     loop = get_loop_bounds_ext (RS, RE, memory, mem_end, maskw, endianw);
!   else
!     loop = get_loop_bounds     (RS, RE, memory, mem_end, maskw, endianw);
! 
    insn_ptr = PT2H (saved_state.asregs.pc);
    CHECK_INSN_PTR (insn_ptr);
  

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