* [RFA] SH4A contribution for sim
@ 2003-12-05 2:38 Michael Snyder
2003-12-12 2:40 ` Michael Snyder
0 siblings, 1 reply; 5+ messages in thread
From: Michael Snyder @ 2003-12-05 2:38 UTC (permalink / raw)
To: gdb-patches, joern.rennecke, Nick Clifton, andrew.stubbs
[-- Attachment #1: Type: text/plain, Size: 56 bytes --]
Here are my changes to support simulation of the sh4a.
[-- Attachment #2: sh4a.sim --]
[-- Type: text/plain, Size: 44187 bytes --]
2003-12-04 Michael Snyder <msnyder@redhat.com>
* gencode.c: Add support for sh4a.
* interp.c: Ditto.
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 5 Dec 2003 02:32:05 -0000
*************** 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: gencode.c
===================================================================
RCS file: /cvs/src/src/sim/sh/gencode.c,v
retrieving revision 1.21
diff -p -r1.21 gencode.c
*** gencode.c 3 Nov 2003 14:14:15 -0000 1.21
--- gencode.c 5 Dec 2003 02:32:05 -0000
*************** op tab[] =
*** 151,156 ****
--- 151,160 ----
"SET_SR_T (0);",
},
+ { "", "", "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*/);",
},
--- 199,205 ----
"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 */
--- 289,307 ----
},
/* 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 ****
--- 453,463 ----
"FP_UNARY(n, -);",
},
+ /* sh4a */
+ { "", "", "fpchg", "1111011111111101",
+ "SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_PR);",
+ },
+
/* sh4 */
{ "", "", "frchg", "1111101111111101",
"if (FPSCR_PR)",
*************** op tab[] =
*** 449,455 ****
},
/* sh4 */
! { "", "", "fsca", "1111nnn011111101",
"if (FPSCR_PR)",
" RAISE_EXCEPTION (SIGILL);",
"else",
--- 467,473 ----
},
/* sh4 */
! { "", "", "fsca", "1111ddd011111101",
"if (FPSCR_PR)",
" RAISE_EXCEPTION (SIGILL);",
"else",
*************** op tab[] =
*** 498,503 ****
--- 516,531 ----
" FPUL = (int)FR(n);",
},
+ /* sh4a */
+ { "", "", "ftrv <FV_N>", "1111vv0111111101",
+ "if (FPSCR_PR)",
+ " RAISE_EXCEPTION (SIGILL);",
+ "else",
+ "{",
+ " /* FIXME not implemented. */",
+ "}",
+ },
+
/* 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]);",
--- 563,581 ----
{ "", "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....",
--- 593,618 ----
"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 ****
--- 622,641 ----
"RS = SEXT (i) * 2 + 4 + PH2T (PC);",
},
+ /* sh4a-dsp */
+ { "", "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,786 ****
--- 838,881 ----
"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]);",
},
*************** op tab[] =
*** 820,825 ****
--- 915,926 ----
"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 ****
--- 952,969 ----
" 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 ****
--- 1011,1026 ----
"Delay_Slot (PC + 2);",
},
+ { "", "", "setdmx", "0000000010011000",
+ "saved_state.asregs.cregs.named.sr |= SR_MASK_DMX;"
+ "saved_state.asregs.cregs.named.sr &= ~SR_MASK_DMY;"
+ },
+
+ { "", "", "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);",
--- 1103,1146 ----
"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 */",
},
--- 1394,1512 ----
"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[] =
*** 1379,1385 ****
"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;",
--- 1578,1584 ----
"COMPUTE_OVERFLOW;",
"greater_equal = 0;",
},
! { "","", "pmuls Se,Sf,Dg", "0100eeff0000gguu",
"res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;",
"if (res == 0x80000000)",
" res = 0x7fffffff;",
*************** 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);",
--- 1661,1667 ----
"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[] =
*** 1476,1483 ****
--- 1675,1702 ----
"ADD_SUB_GE;",
},
{ "","", "pwsb Sx,Sy,Dz", "10100100xxyyzzzz",
+ "/* FIXME not implemented? */",
},
{ "","", "pwad Sx,Sy,Dz", "10110100xxyyzzzz",
+ "/* FIXME not implemented? */",
+ },
+ { "","", "(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);",
*************** op ppi_tab[] =
*** 1496,1501 ****
--- 1715,1732 ----
"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 ****
--- 1737,1767 ----
"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 ****
--- 1785,1801 ----
" }",
" }",
},
+ { "","", "(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 ****
--- 1876,1893 ----
"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 ****
--- 1977,1997 ----
"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 ****
--- 2107,2131 ----
" MACL = DSP_R (z) = res;",
"return;",
},
+ { "","", "(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;",
+ },
+ { "","", "(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}
};
*************** bton (s)
*** 1973,1979 ****
static unsigned char table[1 << 16];
/* Take an opcode expand all varying fields in it out and fill all the
! right entries in 'table' with the opcode index*/
static void
expand_opcode (shift, val, i, s)
--- 2286,2292 ----
static unsigned char table[1 << 16];
/* Take an opcode expand all varying fields in it out and fill all the
! right entries in 'table' with the opcode index. */
static void
expand_opcode (shift, val, i, s)
*************** expand_opcode (shift, val, i, s)
*** 1998,2022 ****
{
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);
else if (s[2] == 'N')
for (j = 0; j < 4; j++)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
else if (s[2] == 'x')
for (j = 0; j < 4; j += 2)
for (m = 0; m < 32; m++)
{
/* Ignore illegal nopy */
! if ((m & 7) == 0 && m != 0)
continue;
mv = m & 3 | (m & 4) << 2 | (m & 8) << 3 | (m & 16) << 4;
expand_opcode (shift - 4, val | mv | (j << shift), i,
s + 4);
}
else if (s[2] == 'y')
for (j = 0; j < 2; j++)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
--- 2311,2361 ----
{
int m, mv;
+ /* J"orn Rennecke: "Allow variable length n / m fields".
+ I'm not sure if I understand these two lines. MVS */
if (s[1] - '0' > 1U || !s[2] || ! s[3])
expand_opcode (shift - 1, val + s[0] - '0', i, s + 1);
+
val |= bton (s) << shift;
+ /* 0101 -- pass literal value down (once). */
if (s[2] == '0' || s[2] == '1')
expand_opcode (shift - 4, val, i, s + 4);
+ /* 01NN -- do a 4-way fork. */
else if (s[2] == 'N')
for (j = 0; j < 4; j++)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
+ /* 01?? -- 4 way 'wildcard' fork. */
+ else if (s[2] == '?')
+ for (m = 0; m < 4; m++)
+ {
+ expand_opcode (shift - 4, val | m, i, s + 4);
+ if (m != 0)
+ expand_opcode (shift - 4, val | (m + 16), i, s + 4);
+ }
+ /* 01xy -- 4 way fork across xy. */
+ else if (s[2] == 'x' && s[3] == 'y')
+ for (j = 0; j < 4; j++)
+ expand_opcode (shift - 4, val | m | (j << shift), i, s + 4);
+ /* 01xx -- 2x32 fork across x0 and nopy. */
else if (s[2] == 'x')
for (j = 0; j < 4; j += 2)
for (m = 0; m < 32; m++)
{
/* Ignore illegal nopy */
! /* Skip all possible illegal nopy, else you will
! overwrite new instructions. */
! if ((m & 3) == 0 && m != 0)
continue;
+
mv = m & 3 | (m & 4) << 2 | (m & 8) << 3 | (m & 16) << 4;
expand_opcode (shift - 4, val | mv | (j << shift), i,
s + 4);
}
+ /* 01yx -- 4-way fork across yx. */
+ else if (s[2] == 'y' && s[3] == 'x')
+ for (j = 0; j < 4; j++)
+ expand_opcode (shift - 4, val | (j << shift), i, s + 4);
+ /* 01yy -- 2-way fork across 0y. */
else if (s[2] == 'y')
for (j = 0; j < 2; j++)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
*************** expand_opcode (shift, val, i, s)
*** 2024,2029 ****
--- 2363,2370 ----
}
case 'n':
case 'm':
+ /* nnnn, mmmm -- 16-way fork.
+ Or, per J"orn Rennecke, a variable-length mmmm/nnnn field. */
{
int digits = 1;
while (s[digits] == s[0])
*************** expand_opcode (shift, val, i, s)
*** 2037,2053 ****
--- 2378,2399 ----
}
case 'M':
/* A1, A0,X0,X1,Y0,Y1,M0,A1G,M1,M1G */
+ /* MMMM -- A[01], M[01], X[01], Y[01], A[01]G -- 10-way fork.
+ (FIXME: note mistake above, no problem below). */
for (j = 5; j < 16; j++)
if (j != 6)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
break;
case 'G':
/* A1G, A0G: */
+ /* GGGG -- A0G, A1G (guard registers). 2-way fork. */
for (j = 13; j <= 15; j +=2)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
break;
case 's':
/* System registers mach, macl, pr: */
+ /* ssss -- 3-way fork (see above), plus
+ 7-way fork (see below). */
for (j = 0; j < 3; j++)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
/* System registers fpul, fpscr/dsr, a0, x0, x1, y0, y1: */
*************** expand_opcode (shift, val, i, s)
*** 2055,2072 ****
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
break;
case 'X':
case 'a':
val |= bton (s) << shift;
! for (j = 0; j < 16; j += 8)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
break;
case 'Y':
case 'A':
val |= bton (s) << shift;
! for (j = 0; j < 8; j += 4)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
break;
default:
for (j = 0; j < (1 << (shift + 4)); j++)
{
--- 2401,2459 ----
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
break;
case 'X':
+ /* XX/XY -- 2/4 way fork. */
+ val |= bton (s) << shift;
+ for (j = 0; j < 16; j += (s[1] == 'Y' ? 4 : 8))
+ expand_opcode (shift - 4, val | (j << shift), i, s + 4);
+ break;
case 'a':
+ /* aa/ax -- 2/4 way fork. */
val |= bton (s) << shift;
!
! for (j = 0; j < 16; j += (s[1] == 'x' ? 4 : 8))
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
+
break;
case 'Y':
+ /* YY/YX -- 2/4 way fork. */
+ val |= bton (s) << shift;
+ for (j = 0; j < (s[1] == 'X' ? 16 : 8); j += 4)
+ expand_opcode (shift - 4, val | (j << shift), i, s + 4);
+ break;
case 'A':
+ /* AA/AY: 2/4 way fork. */
val |= bton (s) << shift;
!
! for (j = 0; j < (s[1] == 'Y' ? 16 : 8); j += 4)
expand_opcode (shift - 4, val | (j << shift), i, s + 4);
+
break;
+ case 'v':
+ /* vv(VV) -- 4(16) way fork. */
+ /* Vector register fv0/4/8/12. */
+ val |= bton (s) << shift;
+ if (s[2] == 'V')
+ {
+ /* 2 vector registers. */
+ for (j = 0; j < 15; j++)
+ expand_opcode (shift - 4, val | (j << shift), i, s + 4);
+ }
+ else
+ {
+ /* 1 vector register. */
+ for (j = 0; j < 15; j += 4)
+ expand_opcode (shift - 4, val | (j << shift), i, s + 4);
+ }
+ break;
+ case 'd':
+ /* Double register dr0-dr14 (even numbers only). */
+ /* ddd0 -- 8 way fork. */
+ val |= bton (s) << shift;
+ for (j = 0; j < 15; j += 2)
+ expand_opcode (shift - 4, val | (j << shift), i, s + 4);
+ break;
+ /* Default -- 16 way fork. */
default:
for (j = 0; j < (1 << (shift + 4)); j++)
{
*************** gensim_caselist (p)
*** 2171,2176 ****
--- 2558,2582 ----
*s);
exit (1);
break;
+ case '?':
+ /* Wildcard expansion, nothing to do here. */
+ s += 2;
+ break;
+ case 'd':
+ printf (" int n = (iword >> 8) & 0xf;\n");
+ printf (" if (n & 1)\n");
+ printf (" RAISE_EXCEPTION (SIGILL);\n");
+ needn = 1;
+ s += 4;
+ 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)
*** 2188,2199 ****
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;
--- 2594,2620 ----
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)
*** 2206,2223 ****
--- 2627,2672 ----
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
*** 2312,2317 ****
--- 2761,2778 ----
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 ()
*** 2350,2356 ****
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)
--- 2811,2819 ----
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 eliminated to make code more understandable.
! MVS 2003. */
static void
expand_ppi_code (val, i, s)
*************** expand_ppi_code (val, i, s)
*** 2360,2405 ****
{
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;
! }
}
}
--- 2823,2876 ----
{
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. */
! s += 4;
! val <<= 4;
! for (j = 0; j < 16; j++)
! expand_ppi_code (val + j, i, s);
! break;
! case '.':
! case '0':
! val += val;
! s++;
! expand_ppi_code (val, i, s);
! break;
! case '1':
! val += val + 1;
! s++;
! expand_ppi_code (val, i, s);
! break;
! case 'i':
! case 'e': case 'f':
! case 'x': case 'y':
! val += val;
! s++;
! expand_ppi_code (val, i, s);
! val++;
! expand_ppi_code (val, i, s);
! break;
! case 'c':
! val <<= 2;
! s += 2;
! val++;
! expand_ppi_code (val, ppi_index++, s);
! val++;
! expand_ppi_code (val, i, s);
! val++;
! expand_ppi_code (val, i, s);
! break;
}
}
*************** ppi_gensim ()
*** 2451,2468 ****
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++)
{
--- 2922,2945 ----
printf ("ppi_insn (iword)\n");
printf (" int iword;\n");
printf ("{\n");
+ printf (" /* 'ee' = [x0, x1, y0, a1] (FIXME [x0, x1, a1, m1]) */\n");
printf (" static char e_tab[] = { 8, 9, 10, 5};\n");
+ printf (" /* 'ff' = [y0, y1, x0, a1] (FIXME [y0, y1, a1, m1]) */\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] (FIXME [m1, x1, 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)
*** 2623,2629 ****
memset (table, 0, sizeof table);
ppi_filltable ();
! dumptable ("ppi_table", 1 << 8, 0);
}
else if (strcmp (av[1], "-x") == 0)
{
--- 3100,3106 ----
memset (table, 0, sizeof table);
ppi_filltable ();
! dumptable ("ppi_table", 1 << 12, 0); /* 12 */
}
else if (strcmp (av[1], "-x") == 0)
{
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFA] SH4A contribution for sim
2003-12-05 2:38 [RFA] SH4A contribution for sim Michael Snyder
@ 2003-12-12 2:40 ` Michael Snyder
2003-12-15 19:03 ` Joern Rennecke
0 siblings, 1 reply; 5+ messages in thread
From: Michael Snyder @ 2003-12-12 2:40 UTC (permalink / raw)
To: Michael Snyder; +Cc: gdb-patches, joern.rennecke, andrew.stubbs
Michael Snyder wrote:
> Here are my changes to support simulation of the sh4a.
J"oern? Any comment?
>
>
> ------------------------------------------------------------------------
>
> 2003-12-04 Michael Snyder <msnyder@redhat.com>
>
> * gencode.c: Add support for sh4a.
> * interp.c: Ditto.
>
> 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 5 Dec 2003 02:32:05 -0000
> *************** 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: gencode.c
> ===================================================================
> RCS file: /cvs/src/src/sim/sh/gencode.c,v
> retrieving revision 1.21
> diff -p -r1.21 gencode.c
> *** gencode.c 3 Nov 2003 14:14:15 -0000 1.21
> --- gencode.c 5 Dec 2003 02:32:05 -0000
> *************** op tab[] =
> *** 151,156 ****
> --- 151,160 ----
> "SET_SR_T (0);",
> },
>
> + { "", "", "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*/);",
> },
>
> --- 199,205 ----
> "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 */
> --- 289,307 ----
> },
>
> /* 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 ****
> --- 453,463 ----
> "FP_UNARY(n, -);",
> },
>
> + /* sh4a */
> + { "", "", "fpchg", "1111011111111101",
> + "SET_FPSCR (GET_FPSCR() ^ FPSCR_MASK_PR);",
> + },
> +
> /* sh4 */
> { "", "", "frchg", "1111101111111101",
> "if (FPSCR_PR)",
> *************** op tab[] =
> *** 449,455 ****
> },
>
> /* sh4 */
> ! { "", "", "fsca", "1111nnn011111101",
> "if (FPSCR_PR)",
> " RAISE_EXCEPTION (SIGILL);",
> "else",
> --- 467,473 ----
> },
>
> /* sh4 */
> ! { "", "", "fsca", "1111ddd011111101",
> "if (FPSCR_PR)",
> " RAISE_EXCEPTION (SIGILL);",
> "else",
> *************** op tab[] =
> *** 498,503 ****
> --- 516,531 ----
> " FPUL = (int)FR(n);",
> },
>
> + /* sh4a */
> + { "", "", "ftrv <FV_N>", "1111vv0111111101",
> + "if (FPSCR_PR)",
> + " RAISE_EXCEPTION (SIGILL);",
> + "else",
> + "{",
> + " /* FIXME not implemented. */",
> + "}",
> + },
> +
> /* 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]);",
> --- 563,581 ----
> { "", "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....",
> --- 593,618 ----
> "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 ****
> --- 622,641 ----
> "RS = SEXT (i) * 2 + 4 + PH2T (PC);",
> },
>
> + /* sh4a-dsp */
> + { "", "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,786 ****
> --- 838,881 ----
> "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]);",
> },
> *************** op tab[] =
> *** 820,825 ****
> --- 915,926 ----
> "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 ****
> --- 952,969 ----
> " 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 ****
> --- 1011,1026 ----
> "Delay_Slot (PC + 2);",
> },
>
> + { "", "", "setdmx", "0000000010011000",
> + "saved_state.asregs.cregs.named.sr |= SR_MASK_DMX;"
> + "saved_state.asregs.cregs.named.sr &= ~SR_MASK_DMY;"
> + },
> +
> + { "", "", "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);",
> --- 1103,1146 ----
> "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 */",
> },
> --- 1394,1512 ----
> "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[] =
> *** 1379,1385 ****
> "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;",
> --- 1578,1584 ----
> "COMPUTE_OVERFLOW;",
> "greater_equal = 0;",
> },
> ! { "","", "pmuls Se,Sf,Dg", "0100eeff0000gguu",
> "res = (DSP_R (e) >> 16) * (DSP_R (f) >> 16) * 2;",
> "if (res == 0x80000000)",
> " res = 0x7fffffff;",
> *************** 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);",
> --- 1661,1667 ----
> "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[] =
> *** 1476,1483 ****
> --- 1675,1702 ----
> "ADD_SUB_GE;",
> },
> { "","", "pwsb Sx,Sy,Dz", "10100100xxyyzzzz",
> + "/* FIXME not implemented? */",
> },
> { "","", "pwad Sx,Sy,Dz", "10110100xxyyzzzz",
> + "/* FIXME not implemented? */",
> + },
> + { "","", "(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);",
> *************** op ppi_tab[] =
> *** 1496,1501 ****
> --- 1715,1732 ----
> "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 ****
> --- 1737,1767 ----
> "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 ****
> --- 1785,1801 ----
> " }",
> " }",
> },
> + { "","", "(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 ****
> --- 1876,1893 ----
> "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 ****
> --- 1977,1997 ----
> "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 ****
> --- 2107,2131 ----
> " MACL = DSP_R (z) = res;",
> "return;",
> },
> + { "","", "(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;",
> + },
> + { "","", "(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}
> };
>
> *************** bton (s)
> *** 1973,1979 ****
> static unsigned char table[1 << 16];
>
> /* Take an opcode expand all varying fields in it out and fill all the
> ! right entries in 'table' with the opcode index*/
>
> static void
> expand_opcode (shift, val, i, s)
> --- 2286,2292 ----
> static unsigned char table[1 << 16];
>
> /* Take an opcode expand all varying fields in it out and fill all the
> ! right entries in 'table' with the opcode index. */
>
> static void
> expand_opcode (shift, val, i, s)
> *************** expand_opcode (shift, val, i, s)
> *** 1998,2022 ****
> {
> 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);
> else if (s[2] == 'N')
> for (j = 0; j < 4; j++)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> else if (s[2] == 'x')
> for (j = 0; j < 4; j += 2)
> for (m = 0; m < 32; m++)
> {
> /* Ignore illegal nopy */
> ! if ((m & 7) == 0 && m != 0)
> continue;
> mv = m & 3 | (m & 4) << 2 | (m & 8) << 3 | (m & 16) << 4;
> expand_opcode (shift - 4, val | mv | (j << shift), i,
> s + 4);
> }
> else if (s[2] == 'y')
> for (j = 0; j < 2; j++)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> --- 2311,2361 ----
> {
> int m, mv;
>
> + /* J"orn Rennecke: "Allow variable length n / m fields".
> + I'm not sure if I understand these two lines. MVS */
> if (s[1] - '0' > 1U || !s[2] || ! s[3])
> expand_opcode (shift - 1, val + s[0] - '0', i, s + 1);
> +
> val |= bton (s) << shift;
> + /* 0101 -- pass literal value down (once). */
> if (s[2] == '0' || s[2] == '1')
> expand_opcode (shift - 4, val, i, s + 4);
> + /* 01NN -- do a 4-way fork. */
> else if (s[2] == 'N')
> for (j = 0; j < 4; j++)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> + /* 01?? -- 4 way 'wildcard' fork. */
> + else if (s[2] == '?')
> + for (m = 0; m < 4; m++)
> + {
> + expand_opcode (shift - 4, val | m, i, s + 4);
> + if (m != 0)
> + expand_opcode (shift - 4, val | (m + 16), i, s + 4);
> + }
> + /* 01xy -- 4 way fork across xy. */
> + else if (s[2] == 'x' && s[3] == 'y')
> + for (j = 0; j < 4; j++)
> + expand_opcode (shift - 4, val | m | (j << shift), i, s + 4);
> + /* 01xx -- 2x32 fork across x0 and nopy. */
> else if (s[2] == 'x')
> for (j = 0; j < 4; j += 2)
> for (m = 0; m < 32; m++)
> {
> /* Ignore illegal nopy */
> ! /* Skip all possible illegal nopy, else you will
> ! overwrite new instructions. */
> ! if ((m & 3) == 0 && m != 0)
> continue;
> +
> mv = m & 3 | (m & 4) << 2 | (m & 8) << 3 | (m & 16) << 4;
> expand_opcode (shift - 4, val | mv | (j << shift), i,
> s + 4);
> }
> + /* 01yx -- 4-way fork across yx. */
> + else if (s[2] == 'y' && s[3] == 'x')
> + for (j = 0; j < 4; j++)
> + expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> + /* 01yy -- 2-way fork across 0y. */
> else if (s[2] == 'y')
> for (j = 0; j < 2; j++)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> *************** expand_opcode (shift, val, i, s)
> *** 2024,2029 ****
> --- 2363,2370 ----
> }
> case 'n':
> case 'm':
> + /* nnnn, mmmm -- 16-way fork.
> + Or, per J"orn Rennecke, a variable-length mmmm/nnnn field. */
> {
> int digits = 1;
> while (s[digits] == s[0])
> *************** expand_opcode (shift, val, i, s)
> *** 2037,2053 ****
> --- 2378,2399 ----
> }
> case 'M':
> /* A1, A0,X0,X1,Y0,Y1,M0,A1G,M1,M1G */
> + /* MMMM -- A[01], M[01], X[01], Y[01], A[01]G -- 10-way fork.
> + (FIXME: note mistake above, no problem below). */
> for (j = 5; j < 16; j++)
> if (j != 6)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> break;
> case 'G':
> /* A1G, A0G: */
> + /* GGGG -- A0G, A1G (guard registers). 2-way fork. */
> for (j = 13; j <= 15; j +=2)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> break;
> case 's':
> /* System registers mach, macl, pr: */
> + /* ssss -- 3-way fork (see above), plus
> + 7-way fork (see below). */
> for (j = 0; j < 3; j++)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> /* System registers fpul, fpscr/dsr, a0, x0, x1, y0, y1: */
> *************** expand_opcode (shift, val, i, s)
> *** 2055,2072 ****
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> break;
> case 'X':
> case 'a':
> val |= bton (s) << shift;
> ! for (j = 0; j < 16; j += 8)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> break;
> case 'Y':
> case 'A':
> val |= bton (s) << shift;
> ! for (j = 0; j < 8; j += 4)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> break;
>
> default:
> for (j = 0; j < (1 << (shift + 4)); j++)
> {
> --- 2401,2459 ----
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> break;
> case 'X':
> + /* XX/XY -- 2/4 way fork. */
> + val |= bton (s) << shift;
> + for (j = 0; j < 16; j += (s[1] == 'Y' ? 4 : 8))
> + expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> + break;
> case 'a':
> + /* aa/ax -- 2/4 way fork. */
> val |= bton (s) << shift;
> !
> ! for (j = 0; j < 16; j += (s[1] == 'x' ? 4 : 8))
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> +
> break;
> case 'Y':
> + /* YY/YX -- 2/4 way fork. */
> + val |= bton (s) << shift;
> + for (j = 0; j < (s[1] == 'X' ? 16 : 8); j += 4)
> + expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> + break;
> case 'A':
> + /* AA/AY: 2/4 way fork. */
> val |= bton (s) << shift;
> !
> ! for (j = 0; j < (s[1] == 'Y' ? 16 : 8); j += 4)
> expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> +
> break;
>
> + case 'v':
> + /* vv(VV) -- 4(16) way fork. */
> + /* Vector register fv0/4/8/12. */
> + val |= bton (s) << shift;
> + if (s[2] == 'V')
> + {
> + /* 2 vector registers. */
> + for (j = 0; j < 15; j++)
> + expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> + }
> + else
> + {
> + /* 1 vector register. */
> + for (j = 0; j < 15; j += 4)
> + expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> + }
> + break;
> + case 'd':
> + /* Double register dr0-dr14 (even numbers only). */
> + /* ddd0 -- 8 way fork. */
> + val |= bton (s) << shift;
> + for (j = 0; j < 15; j += 2)
> + expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> + break;
> + /* Default -- 16 way fork. */
> default:
> for (j = 0; j < (1 << (shift + 4)); j++)
> {
> *************** gensim_caselist (p)
> *** 2171,2176 ****
> --- 2558,2582 ----
> *s);
> exit (1);
> break;
> + case '?':
> + /* Wildcard expansion, nothing to do here. */
> + s += 2;
> + break;
> + case 'd':
> + printf (" int n = (iword >> 8) & 0xf;\n");
> + printf (" if (n & 1)\n");
> + printf (" RAISE_EXCEPTION (SIGILL);\n");
> + needn = 1;
> + s += 4;
> + 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)
> *** 2188,2199 ****
> 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;
> --- 2594,2620 ----
> 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)
> *** 2206,2223 ****
> --- 2627,2672 ----
> 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
> *** 2312,2317 ****
> --- 2761,2778 ----
> 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 ()
> *** 2350,2356 ****
> 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)
> --- 2811,2819 ----
> 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 eliminated to make code more understandable.
> ! MVS 2003. */
>
> static void
> expand_ppi_code (val, i, s)
> *************** expand_ppi_code (val, i, s)
> *** 2360,2405 ****
> {
> 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;
> ! }
> }
> }
>
> --- 2823,2876 ----
> {
> 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. */
> ! s += 4;
> ! val <<= 4;
> ! for (j = 0; j < 16; j++)
> ! expand_ppi_code (val + j, i, s);
> ! break;
> ! case '.':
> ! case '0':
> ! val += val;
> ! s++;
> ! expand_ppi_code (val, i, s);
> ! break;
> ! case '1':
> ! val += val + 1;
> ! s++;
> ! expand_ppi_code (val, i, s);
> ! break;
> ! case 'i':
> ! case 'e': case 'f':
> ! case 'x': case 'y':
> ! val += val;
> ! s++;
> ! expand_ppi_code (val, i, s);
> ! val++;
> ! expand_ppi_code (val, i, s);
> ! break;
> ! case 'c':
> ! val <<= 2;
> ! s += 2;
> ! val++;
> ! expand_ppi_code (val, ppi_index++, s);
> ! val++;
> ! expand_ppi_code (val, i, s);
> ! val++;
> ! expand_ppi_code (val, i, s);
> ! break;
> }
> }
>
> *************** ppi_gensim ()
> *** 2451,2468 ****
> 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++)
> {
> --- 2922,2945 ----
> printf ("ppi_insn (iword)\n");
> printf (" int iword;\n");
> printf ("{\n");
> + printf (" /* 'ee' = [x0, x1, y0, a1] (FIXME [x0, x1, a1, m1]) */\n");
> printf (" static char e_tab[] = { 8, 9, 10, 5};\n");
> + printf (" /* 'ff' = [y0, y1, x0, a1] (FIXME [y0, y1, a1, m1]) */\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] (FIXME [m1, x1, 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)
> *** 2623,2629 ****
>
> memset (table, 0, sizeof table);
> ppi_filltable ();
> ! dumptable ("ppi_table", 1 << 8, 0);
> }
> else if (strcmp (av[1], "-x") == 0)
> {
> --- 3100,3106 ----
>
> memset (table, 0, sizeof table);
> ppi_filltable ();
> ! dumptable ("ppi_table", 1 << 12, 0); /* 12 */
> }
> else if (strcmp (av[1], "-x") == 0)
> {
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFA] SH4A contribution for sim
2003-12-12 2:40 ` Michael Snyder
@ 2003-12-15 19:03 ` Joern Rennecke
2003-12-17 21:49 ` Michael Snyder
0 siblings, 1 reply; 5+ messages in thread
From: Joern Rennecke @ 2003-12-15 19:03 UTC (permalink / raw)
To: Michael Snyder
Cc: Michael Snyder, gdb-patches, joern.rennecke, andrew.stubbs, amylaar
>
> Michael Snyder wrote:
> > Here are my changes to support simulation of the sh4a.
>
> J"oern? Any comment?
> > {
> > int m, mv;
> >
> > + /* J"orn Rennecke: "Allow variable length n / m fields".
> > + I'm not sure if I understand these two lines. MVS */
> > if (s[1] - '0' > 1U || !s[2] || ! s[3])
> > expand_opcode (shift - 1, val + s[0] - '0', i, s + 1);
> > +
The code above handles a single binary digit if it appears as
one of the last three characters, or in front of a non-binary character
(e.g. the 'i' in 'i8*1....'). This is because handling the three 'n's in
'nnn0' leaves one extra binary digit. E.g. for fsca, after 'nnn', the
nibbles 0111 and 1110 are processed, leaving '1'.
I didn't want to process single bits all the time because that requires
some changes in patterns that recognize binary/letter combinations.
On the other hand, you seem to be doing that right now anyway. And
expanding these combinations is making this code ever harder to maintain.
I think the only sane way forward is to handle variable-length binary fields
- i.e. make a loop to see how much we got and build up the number as we go.
The position dependent template fragments where the 'xx' and 'yy' for
movx/movy, which you changed to 'xy' and 'yx'.
We can use this chage to xy/yx to make the detection position-independent,
or check the shift parameter. rather, that should be a count
of bits that remain to be processed - subtracting 4 at the start doesn't
make much sense if you don't process nibbles all the time.
> > + /* 01xy -- 4 way fork across xy. */
> > + else if (s[2] == 'x' && s[3] == 'y')
> > + for (j = 0; j < 4; j++)
> > + expand_opcode (shift - 4, val | m | (j << shift), i, s + 4);
> > + /* 01xx -- 2x32 fork across x0 and nopy. */
This does not just go across nopy (that would be pointless), but across
nopy and movy.
By replacing all the 'xx' in movx templates with 'xy' and doing a vanilla
expansion for 'xy' above, you disable generation of case labels for
movx/movy combinations. Then you made tons of other changes to compensate
for this. I see not point in these changes.
> > + case 'd':
> > + /* Double register dr0-dr14 (even numbers only). */
> > + /* ddd0 -- 8 way fork. */
> > + val |= bton (s) << shift;
> > + for (j = 0; j < 15; j += 2)
> > + expand_opcode (shift - 4, val | (j << shift), i, s + 4);
> > + break;
What is that for? I don't see why we should have a separate ddd0 pattern,
where nnn0 works just fine and also makes it much clearer where the number
ends up. It's also more efficient when the simulator doesn't do any
unnecessary runtime checks on the opcodes. The even-numbered registers
generate legal instruction encodings. The odd-numbered ones are left
over for the default case. If you want to make sure that they raise a
SIGILL exception, you can do this by initializing table accordingly.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFA] SH4A contribution for sim
2003-12-15 19:03 ` Joern Rennecke
@ 2003-12-17 21:49 ` Michael Snyder
0 siblings, 0 replies; 5+ messages in thread
From: Michael Snyder @ 2003-12-17 21:49 UTC (permalink / raw)
To: Joern Rennecke; +Cc: gdb-patches, joern.rennecke, andrew.stubbs, amylaar
Joern Rennecke wrote:
>>Michael Snyder wrote:
>>
>>>Here are my changes to support simulation of the sh4a.
>>
>>J"oern? Any comment?
>
>
>>> {
>>> int m, mv;
>>>
>>>+ /* J"orn Rennecke: "Allow variable length n / m fields".
>>>+ I'm not sure if I understand these two lines. MVS */
>>> if (s[1] - '0' > 1U || !s[2] || ! s[3])
>>> expand_opcode (shift - 1, val + s[0] - '0', i, s + 1);
>>>+
>
>
> The code above handles a single binary digit if it appears as
> one of the last three characters, or in front of a non-binary character
> (e.g. the 'i' in 'i8*1....'). This is because handling the three 'n's in
> 'nnn0' leaves one extra binary digit. E.g. for fsca, after 'nnn', the
> nibbles 0111 and 1110 are processed, leaving '1'.
Ah, thanks, I see. So you're basically solving the same problem here
that I did by introducing the "ddd0" pattern.
Wouldn't it be safer to handle the extra '0' immediately?
What if you had a pattern that was like "nnn0GGGG", (for instance)?
You'd wind up parsing it as "nnn" plus "0GGG" plus "G".
> I didn't want to process single bits all the time because that requires
> some changes in patterns that recognize binary/letter combinations.
Yeah, that could be ugly.
>
> On the other hand, you seem to be doing that right now anyway.
Processing single bits? Not that I'm aware....
> And
> expanding these combinations is making this code ever harder to maintain.
> I think the only sane way forward is to handle variable-length binary fields
> - i.e. make a loop to see how much we got and build up the number as we go.
> The position dependent template fragments where the 'xx' and 'yy' for
> movx/movy, which you changed to 'xy' and 'yx'.
As a less extreme measure, what if we break some combinations
into two-byte fields instead of four? I'm still thinking it
through, but I'm thinking that, for instance, "01NN" could be
handled in two passes: take the "01" first, then recurse and
let the "NN" be handled in the outer switch statement. This
might also apply to 01xy and XY01.
> We can use this chage to xy/yx to make the detection position-independent,
> or check the shift parameter. rather, that should be a count
> of bits that remain to be processed - subtracting 4 at the start doesn't
> make much sense if you don't process nibbles all the time.
>
>
>>>+ /* 01xy -- 4 way fork across xy. */
>>>+ else if (s[2] == 'x' && s[3] == 'y')
>>>+ for (j = 0; j < 4; j++)
>>>+ expand_opcode (shift - 4, val | m | (j << shift), i, s + 4);
>>>+ /* 01xx -- 2x32 fork across x0 and nopy. */
>
>
> This does not just go across nopy (that would be pointless), but across
> nopy and movy.
> By replacing all the 'xx' in movx templates with 'xy' and doing a vanilla
> expansion for 'xy' above, you disable generation of case labels for
> movx/movy combinations. Then you made tons of other changes to compensate
> for this. I see not point in these changes.
Please say more. I found this part of the work difficult,
and I'm by no means sure that my solution was optimal.
Unfortunately I did the work several months ago, and my
memory is not fresh (appologies for not getting around to
submitting it sooner).
>>>+ case 'd':
>>>+ /* Double register dr0-dr14 (even numbers only). */
>>>+ /* ddd0 -- 8 way fork. */
>>>+ val |= bton (s) << shift;
>>>+ for (j = 0; j < 15; j += 2)
>>>+ expand_opcode (shift - 4, val | (j << shift), i, s + 4);
>>>+ break;
>
>
> What is that for? I don't see why we should have a separate ddd0 pattern,
> where nnn0 works just fine and also makes it much clearer where the number
> ends up. It's also more efficient when the simulator doesn't do any
> unnecessary runtime checks on the opcodes. The even-numbered registers
> generate legal instruction encodings. The odd-numbered ones are left
> over for the default case. If you want to make sure that they raise a
> SIGILL exception, you can do this by initializing table accordingly.
OK, but there's precident -- MMMM, ssss, and GGGG all stand for
specific subsets of register numbers. I'm willing to go with your
way, but consider that if we do use ddd0, then the problem of
handling a single nybble goes away. The nnnn / mmmm code becomes
simpler again.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFA] SH4A contribution for sim
[not found] <200312180144.hBI1iosK001449@meolyon.local>
@ 2003-12-18 2:37 ` Michael Snyder
0 siblings, 0 replies; 5+ messages in thread
From: Michael Snyder @ 2003-12-18 2:37 UTC (permalink / raw)
To: Joern Rennecke; +Cc: gdb-patches, joern.rennecke, andrew.stubbs
Joern Rennecke wrote:
>>[...] This is why I say that when we are making big changes anyway, we
> should also introduce variable length [01]* bitstring parsing.
> [...]
>
>>through, but I'm thinking that, for instance, "01NN" could be
>>handled in two passes: take the "01" first, then recurse and
>>let the "NN" be handled in the outer switch statement. This
>>might also apply to 01xy and XY01.
>
>
> Yes, that is how I'd like to see this pattern handled. But the '01' can
> bhe handled by code that processes arbitrary length constant bitstrings.
> There is no need to process only specific length of these.
OK, I withdraw this patch, and I will submit a new one that
[only] changes expand_opcode along the lines we have been
discussing. Then I'll submit the rest of this patch separately
(perhaps after further discussion of the movx/movy patterns).
[...]
> I made the movx expansion generate all the combinations of movx with movy
> as well as with nopy. That is this inner loop:
>
> 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;
Yes but the h8sx has a bunch of new ones.
We can continue this conversation, I'll separate this change
from the revamp of expand_opcode.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2003-12-18 2:37 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-12-05 2:38 [RFA] SH4A contribution for sim Michael Snyder
2003-12-12 2:40 ` Michael Snyder
2003-12-15 19:03 ` Joern Rennecke
2003-12-17 21:49 ` Michael Snyder
[not found] <200312180144.hBI1iosK001449@meolyon.local>
2003-12-18 2:37 ` Michael Snyder
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox