[rx sim] add decode cache

DJ Delorie dj@redhat.com
Thu Jul 29 18:42:00 GMT 2010


This patch is a performance improvement for the RX simulator.  It
stores the opcode decode information from libopcodes so that any given
opcode need not be decoded more than once.  This, and some
optimizations in the previous patch, results in the simulator taking
about 60% of the time it used to take to run a given program.  On a
3.2GHz desktop, I get an effective 12.5MHz simulated time with full
cycle stats, 14.5MHz with just cycle tracking, and 16MHz without cycle
tracking.

Committed.

[include/opcode]

	* rx.h (RX_Operand_Type): Add TwoReg.
	(RX_Opcode_ID): Remove ediv and ediv2.

[opcodes]

	* rx-decode.opc (SRR): New.
	(rx_decode_opcode): Use it for movbi and movbir.  Decode NOP2 (mov
	r0,r0) and NOP3 (max r0,r0) special cases.
	* rx-decode.c: Regenerate.
	
[sim/rx]

	* rx.c (decode_cache_base): New.
	(id_names): Remove ediv and edivu.
	(optype_names): Add TwoReg.
	(maybe_get_mem_page): New.
	(rx_get_byte): Call it.
	(get_op): Add TwoReg support.
	(put_op): Likewise.
	(PD, PS, PS2, GD, GS, GS2, DSZ, SSZ, S2SZ, US1, US2, OM): "opcode"
	is a pointer now.
	(DO_RETURN): New.  We use longjmp to return an exception result.
	(decode_opcode): Make opcode a pointer to the decode cache.  Save
	decoded opcode information and re-use.  Call DO_RETURN instead of
	return throughout.  Remove ediv and edivu.
	* mem.c (ptdc): New.  Adds decode cache.
	(rx_mem_ptr): Support it.
	(rx_mem_decode_cache): New.
	* mem.h (enum mem_ptr_action): add MPA_DECODE_CACHE.
	(rx_mem_decode_cache): Declare.
	* gdb-if.c (sim_resume): Add decode_opcode's setjmp logic here...
	* main.c (main): ...and here.  Use a fast loop if neither trace
	nor disassemble is given.
	* cpu.h (RX_MAKE_STEPPED, RX_MAKE_HIT_BREAK, RX_MAKE_EXITED,
	RX_MAKE_STOPPED, RX_EXITED, RX_STOPPED): Adjust so that 0 is not a
	valid code for anything.

Index: include/opcode/rx.h
===================================================================
RCS file: /cvs/src/src/include/opcode/rx.h,v
retrieving revision 1.4
diff -p -U3 -r1.4 rx.h
--- include/opcode/rx.h	28 Jul 2010 21:58:22 -0000	1.4
+++ include/opcode/rx.h	29 Jul 2010 18:35:03 -0000
@@ -47,6 +47,7 @@ typedef enum
   RX_Operand_Predec,	/* [-Rn] */
   RX_Operand_Condition,	/* eq, gtu, etc */
   RX_Operand_Flag,	/* [UIOSZC] */
+  RX_Operand_TwoReg,	/* [Rn + scale*R2] */
 } RX_Operand_Type;
 
 typedef enum
@@ -82,8 +83,6 @@ typedef enum
   RXO_min,	/* d = min(d,s) */
   RXO_emul,	/* d:64 = d:32 * s */
   RXO_emulu,	/* d:64 = d:32 * s (unsigned) */
-  RXO_ediv,	/* d:64 / s; d = quot, d+1 = rem */
-  RXO_edivu,	/* d:64 / s; d = quot, d+1 = rem */
 
   RXO_rolc,	/* d <<= 1 through carry */
   RXO_rorc,	/* d >>= 1 through carry*/
Index: opcodes/rx-decode.opc
===================================================================
RCS file: /cvs/src/src/opcodes/rx-decode.opc,v
retrieving revision 1.4
diff -p -U3 -r1.4 rx-decode.opc
--- opcodes/rx-decode.opc	28 Jul 2010 00:36:46 -0000	1.4
+++ opcodes/rx-decode.opc	29 Jul 2010 18:35:03 -0000
@@ -89,6 +89,7 @@ static int dsp3map[] = { 8, 9, 10, 3, 4,
 
 #define SC(i)       OP (1, RX_Operand_Immediate, 0, i)
 #define SR(r)       OP (1, RX_Operand_Register,  r, 0)
+#define SRR(r)      OP (1, RX_Operand_TwoReg,  r, 0)
 #define SI(r,a)     OP (1, RX_Operand_Indirect,  r, a)
 #define SIs(r,a,s)  OP (1, RX_Operand_Indirect,  r, (a) * SCALE[s])
 #define SD(t,r,s)   rx_disp (1, t, r, bwl[s], ld);
@@ -270,14 +271,21 @@ rx_decode_opcode (unsigned long pc AU,
   ID(mov); sBWL (sz); DIs(dst, d*16+sppp, sz); SC(IMM(1)); F_____;
 
 /** 11sz sd ss rsrc rdst	mov%s	%1, %0 */
-  ID(mov); sBWL(sz); F_____;
-  if ((ss == 3) && (sd != 3))
+  if (ss == 3 && sz == 2 && rsrc == 0 && rdst == 0)
     {
-      SD(ss, rdst, sz); DD(sd, rsrc, sz);
+      ID(nop2);
     }
   else
     {
-      SD(ss, rsrc, sz); DD(sd, rdst, sz);
+      ID(mov); sBWL(sz); F_____;
+      if ((ss == 3) && (sd != 3))
+	{
+	  SD(ss, rdst, sz); DD(sd, rsrc, sz);
+	}
+      else
+	{
+	  SD(ss, rsrc, sz); DD(sd, rdst, sz);
+	}
     }
 
 /** 10sz 1dsp a src b dst	mov%s	%1, %0 */
@@ -287,13 +295,13 @@ rx_decode_opcode (unsigned long pc AU,
   ID(mov); sBWL(sz); DIs(dst, dsp*4+a*2+b, sz); SR(src); F_____;
 
 /** 1111 1110 01sz isrc bsrc rdst	mov%s	[%1, %2], %0 */
-  ID(movbi); sBWL(sz); DR(rdst); SR(isrc); S2R(bsrc); F_____;
+  ID(movbi); sBWL(sz); DR(rdst); SRR(isrc); S2R(bsrc); F_____;
 
 /** 1111 1110 00sz isrc bsrc rdst	mov%s	%0, [%1, %2] */
-  ID(movbir); sBWL(sz); DR(rdst); SR(isrc); S2R(bsrc); F_____;
+  ID(movbir); sBWL(sz); DR(rdst); SRR(isrc); S2R(bsrc); F_____;
 
 /** 1111 1110 11sz isrc bsrc rdst	movu%s	[%1, %2], %0 */
-  ID(movbi); uBWL(sz); DR(rdst); SR(isrc); S2R(bsrc); F_____;
+  ID(movbi); uBWL(sz); DR(rdst); SRR(isrc); S2R(bsrc); F_____;
 
 /** 1111 1101 0010 0p sz rdst rsrc	mov%s	%1, %0 */
   ID(mov); sBWL (sz); SR(rsrc); F_____;
@@ -525,7 +533,14 @@ rx_decode_opcode (unsigned long pc AU,
   ID(max); DR(rdst); SC(IMMex(im));
 
 /** 1111 1100 0001 00ss rsrc rdst	max	%1%S1, %0 */
-  ID(max); SP(ss, rsrc); DR(rdst);
+  if (ss == 3 && rsrc == 0 && rdst == 0)
+    {
+      ID(nop3);
+    }
+  else
+    {
+      ID(max); SP(ss, rsrc); DR(rdst);
+    }
 
 /** 0000 0110 mx10 00ss 0000 0100 rsrc rdst	max	%1%S1, %0 */
   ID(max); SPm(ss, rsrc, mx); DR(rdst);
@@ -681,23 +696,23 @@ rx_decode_opcode (unsigned long pc AU,
 
 
 /** 0000 1dsp			bra.s	%a0 */
-  ID(branch); Scc(RXC_always); DC(pc + dsp3map[dsp]);
+  ID(branch); DC(pc + dsp3map[dsp]);
 
 /** 0010 1110			bra.b	%a0 */
-  ID(branch); Scc(RXC_always); DC(pc + IMMex(1));
+  ID(branch); DC(pc + IMMex(1));
 
 /** 0011 1000			bra.w	%a0 */
-  ID(branch); Scc(RXC_always); DC(pc + IMMex(2));
+  ID(branch); DC(pc + IMMex(2));
 
 /** 0000 0100			bra.a	%a0 */
-  ID(branch); Scc(RXC_always); DC(pc + IMMex(3));
+  ID(branch); DC(pc + IMMex(3));
 
 /** 0111 1111 0100 rsrc		bra.l	%0 */
-  ID(branchrel); Scc(RXC_always); DR(rsrc);
+  ID(branchrel); DR(rsrc);
 
 
 /** 0111 1111 0000 rsrc		jmp	%0 */
-  ID(branch); Scc(RXC_always); DR(rsrc);
+  ID(branch); DR(rsrc);
 
 /** 0111 1111 0001 rsrc		jsr	%0 */
   ID(jsr); DR(rsrc);
Index: sim/rx/cpu.h
===================================================================
RCS file: /cvs/src/src/sim/rx/cpu.h,v
retrieving revision 1.3
diff -p -U3 -r1.3 cpu.h
--- sim/rx/cpu.h	28 Jul 2010 21:58:22 -0000	1.3
+++ sim/rx/cpu.h	29 Jul 2010 18:35:03 -0000
@@ -211,16 +211,16 @@ int condition_true (int cond_id);
    - RX_MAKE_HIT_BREAK is the return code for hitting a breakpoint.
    - RX_MAKE_EXITED (C) is the return code for exiting with status C.
    - RX_MAKE_STOPPED (S) is the return code for stopping on signal S.  */
-#define RX_MAKE_STEPPED()   (0)
-#define RX_MAKE_HIT_BREAK() (1)
-#define RX_MAKE_EXITED(c)   (((int) (c) << 8) + 2)
-#define RX_MAKE_STOPPED(s)  (((int) (s) << 8) + 3)
+#define RX_MAKE_STEPPED()   (1)
+#define RX_MAKE_HIT_BREAK() (2)
+#define RX_MAKE_EXITED(c)   (((int) (c) << 8) + 3)
+#define RX_MAKE_STOPPED(s)  (((int) (s) << 8) + 4)
 
 #define RX_STEPPED(r)       ((r) == RX_MAKE_STEPPED ())
 #define RX_HIT_BREAK(r)     ((r) == RX_MAKE_HIT_BREAK ())
-#define RX_EXITED(r)        (((r) & 0xff) == 2)
+#define RX_EXITED(r)        (((r) & 0xff) == 3)
 #define RX_EXIT_STATUS(r)   ((r) >> 8)
-#define RX_STOPPED(r)       (((r) & 0xff) == 3)
+#define RX_STOPPED(r)       (((r) & 0xff) == 4)
 #define RX_STOP_SIG(r)      ((r) >> 8)
 
 /* The step result for the current step.  Global to allow
Index: sim/rx/gdb-if.c
===================================================================
RCS file: /cvs/src/src/sim/rx/gdb-if.c,v
retrieving revision 1.7
diff -p -U3 -r1.7 gdb-if.c
--- sim/rx/gdb-if.c	7 Jul 2010 23:22:43 -0000	1.7
+++ sim/rx/gdb-if.c	29 Jul 2010 18:35:03 -0000
@@ -733,6 +733,8 @@ handle_step (int rc)
 void
 sim_resume (SIM_DESC sd, int step, int sig_to_deliver)
 {
+  int rc;
+
   check_desc (sd);
 
   if (sig_to_deliver != 0)
@@ -745,7 +747,12 @@ sim_resume (SIM_DESC sd, int step, int s
   execution_error_clear_last_error ();
 
   if (step)
-    handle_step (decode_opcode ());
+    {
+      rc = setjmp (decode_jmp_buf);
+      if (rc == 0)
+	rc = decode_opcode ();
+      handle_step (rc);
+    }
   else
     {
       /* We don't clear 'stop' here, because then we would miss
@@ -762,7 +769,9 @@ sim_resume (SIM_DESC sd, int step, int s
 	      break;
 	    }
 
-	  int rc = decode_opcode ();
+	  rc = setjmp (decode_jmp_buf);
+	  if (rc == 0)
+	    rc = decode_opcode ();
 
 	  if (execution_error_get_last_error () != SIM_ERR_NONE)
 	    {
Index: sim/rx/main.c
===================================================================
RCS file: /cvs/src/src/sim/rx/main.c,v
retrieving revision 1.4
diff -p -U3 -r1.4 main.c
--- sim/rx/main.c	28 Jul 2010 21:58:22 -0000	1.4
+++ sim/rx/main.c	29 Jul 2010 18:35:03 -0000
@@ -94,6 +94,7 @@ main (int argc, char **argv)
   int o;
   int save_trace;
   bfd *prog;
+  int rc;
 
   /* By default, we exit when an execution error occurs.  */
   execution_error_init_standalone ();
@@ -178,33 +179,50 @@ main (int argc, char **argv)
 
   sim_disasm_init (prog);
 
-  while (1)
-    {
-      int rc;
-
-      if (trace)
-	printf ("\n");
+  enable_counting = verbose;
 
-      if (disassemble)
-	sim_disasm_one ();
+  rc = setjmp (decode_jmp_buf);
 
-      enable_counting = verbose;
-      rc = decode_opcode ();
-      enable_counting = 0;
-
-      if (RX_HIT_BREAK (rc))
-	done (1);
-      else if (RX_EXITED (rc))
-	done (RX_EXIT_STATUS (rc));
-      else if (RX_STOPPED (rc))
+  if (rc == 0)
+    {
+      if (!trace && !disassemble)
 	{
-	  if (verbose)
-	    printf("Stopped on signal %d\n", RX_STOP_SIG (rc));
-	  exit(1);
+	  /* This will longjmp to the above if an exception
+	     happens.  */
+	  for (;;)
+	    decode_opcode ();
 	}
       else
-	assert (RX_STEPPED (rc));
+	while (1)
+	  {
+
+	    if (trace)
+	      printf ("\n");
+
+	    if (disassemble)
+	      {
+		enable_counting = 0;
+		sim_disasm_one ();
+		enable_counting = verbose;
+	      }
 
-      trace_register_changes ();
+	    rc = decode_opcode ();
+
+	    if (trace)
+	      trace_register_changes ();
+	  }
+    }
+
+  if (RX_HIT_BREAK (rc))
+    done (1);
+  else if (RX_EXITED (rc))
+    done (RX_EXIT_STATUS (rc));
+  else if (RX_STOPPED (rc))
+    {
+      if (verbose)
+	printf("Stopped on signal %d\n", RX_STOP_SIG (rc));
+      exit(1);
     }
+  done (0);
+  exit (0);
 }
Index: sim/rx/mem.c
===================================================================
RCS file: /cvs/src/src/sim/rx/mem.c,v
retrieving revision 1.3
diff -p -U3 -r1.3 mem.c
--- sim/rx/mem.c	28 Jul 2010 21:58:22 -0000	1.3
+++ sim/rx/mem.c	29 Jul 2010 18:35:03 -0000
@@ -30,6 +30,7 @@ along with this program.  If not, see <h
 #include <stdlib.h>
 #include <string.h>
 
+#include "opcode/rx.h"
 #include "mem.h"
 #include "cpu.h"
 #include "syscalls.h"
@@ -46,6 +47,7 @@ along with this program.  If not, see <h
 
 static unsigned char **pt[L1_LEN];
 static unsigned char **ptr[L1_LEN];
+static RX_Opcode_Decoded ***ptdc[L1_LEN];
 
 /* [ get=0/put=1 ][ byte size ] */
 static unsigned int mem_counters[2][5];
@@ -85,16 +87,16 @@ rx_mem_ptr (unsigned long address, enum 
     {
       pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
       ptr[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
+      ptdc[pt1] = (RX_Opcode_Decoded ***) calloc (L2_LEN, sizeof (RX_Opcode_Decoded ***));
     }
   if (pt[pt1][pt2] == 0)
     {
       if (action == MPA_READING)
 	execution_error (SIM_ERR_READ_UNWRITTEN_PAGES, address);
 
-      pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN);
-      memset (pt[pt1][pt2], 0, OFF_LEN);
-      ptr[pt1][pt2] = (unsigned char *) malloc (OFF_LEN);
-      memset (ptr[pt1][pt2], MC_UNINIT, OFF_LEN);
+      pt[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1);
+      ptr[pt1][pt2] = (unsigned char *) calloc (OFF_LEN, 1);
+      ptdc[pt1][pt2] = (RX_Opcode_Decoded **) calloc (OFF_LEN, sizeof(RX_Opcode_Decoded *));
     }
   else if (action == MPA_READING
 	   && ptr[pt1][pt2][pto] == MC_UNINIT)
@@ -105,14 +107,28 @@ rx_mem_ptr (unsigned long address, enum 
       if (ptr[pt1][pt2][pto] == MC_PUSHED_PC)
 	execution_error (SIM_ERR_CORRUPT_STACK, address);
       ptr[pt1][pt2][pto] = MC_DATA;
+      if (ptdc[pt1][pt2][pto])
+	{
+	  free (ptdc[pt1][pt2][pto]);
+	  ptdc[pt1][pt2][pto] = NULL;
+	}
     }
 
   if (action == MPA_CONTENT_TYPE)
-    return ptr[pt1][pt2] + pto;
+    return (unsigned char *) (ptr[pt1][pt2] + pto);
+
+  if (action == MPA_DECODE_CACHE)
+    return (unsigned char *) (ptdc[pt1][pt2] + pto);
 
   return pt[pt1][pt2] + pto;
 }
 
+RX_Opcode_Decoded **
+rx_mem_decode_cache (unsigned long address)
+{
+  return (RX_Opcode_Decoded **) rx_mem_ptr (address, MPA_DECODE_CACHE);
+}
+
 static inline int
 is_reserved_address (unsigned int address)
 {
@@ -335,7 +351,9 @@ mem_put_qi (int address, unsigned char v
   COUNT (1, 1);
 }
 
+#ifdef CYCLE_ACCURATE
 static int tpu_base;
+#endif
 
 void
 mem_put_hi (int address, unsigned short value)
Index: sim/rx/mem.h
===================================================================
RCS file: /cvs/src/src/sim/rx/mem.h,v
retrieving revision 1.3
diff -p -U3 -r1.3 mem.h
--- sim/rx/mem.h	28 Jul 2010 21:58:22 -0000	1.3
+++ sim/rx/mem.h	29 Jul 2010 18:35:03 -0000
@@ -29,7 +29,8 @@ enum mem_ptr_action
 {
   MPA_WRITING,
   MPA_READING,
-  MPA_CONTENT_TYPE
+  MPA_CONTENT_TYPE,
+  MPA_DECODE_CACHE
 };
 
 void init_mem (void);
@@ -43,6 +44,9 @@ unsigned long mem_usage_cycles (void);
 #define NONPAGE_MASK (~(PAGE_SIZE-1))
 
 unsigned char *rx_mem_ptr (unsigned long address, enum mem_ptr_action action);
+#ifdef RXC_never
+RX_Opcode_Decoded **rx_mem_decode_cache (unsigned long address);
+#endif
 
 void mem_put_qi (int address, unsigned char value);
 void mem_put_hi (int address, unsigned short value);
Index: sim/rx/rx.c
===================================================================
RCS file: /cvs/src/src/sim/rx/rx.c,v
retrieving revision 1.5
diff -p -U3 -r1.5 rx.c
--- sim/rx/rx.c	28 Jul 2010 21:58:22 -0000	1.5
+++ sim/rx/rx.c	29 Jul 2010 18:35:03 -0000
@@ -65,8 +65,6 @@ static const char * id_names[] = {
   "RXO_min",	/* d = min(d,s) */
   "RXO_emul",	/* d:64 = d:32 * s */
   "RXO_emulu",	/* d:64 = d:32 * s (unsigned) */
-  "RXO_ediv",	/* d:64 / s; d = quot, d+1 = rem */
-  "RXO_edivu",	/* d:64 / s; d = quot, d+1 = rem */
 
   "RXO_rolc",	/* d <<= 1 through carry */
   "RXO_rorc",	/* d >>= 1 through carry*/
@@ -145,7 +143,8 @@ static const char * optype_names[] = {
   "Ps++",	/* [Rn+] */
   "--Pr",	/* [-Rn] */
   " cc ",	/* eq, gtu, etc */
-  "Flag"	/* [UIOSZC] */
+  "Flag",	/* [UIOSZC] */
+  "RbRi"	/* [Rb + scale * Ri] */
 };
 
 #define N_RXO (sizeof(id_names)/sizeof(id_names[0]))
@@ -296,8 +295,20 @@ _rx_abort (const char *file, int line)
 }
 
 static unsigned char *get_byte_base;
+static RX_Opcode_Decoded **decode_cache_base;
 static SI get_byte_page;
 
+static inline void
+maybe_get_mem_page (SI tpc)
+{
+  if (((tpc ^ get_byte_page) & NONPAGE_MASK) || enable_counting)
+    {
+      get_byte_page = tpc & NONPAGE_MASK;
+      get_byte_base = rx_mem_ptr (get_byte_page, MPA_READING) - get_byte_page;
+      decode_cache_base = rx_mem_decode_cache (get_byte_page) - get_byte_page;
+    }
+}
+
 /* This gets called a *lot* so optimize it.  */
 static int
 rx_get_byte (void *vdata)
@@ -309,20 +320,16 @@ rx_get_byte (void *vdata)
   if (rx_big_endian)
     tpc ^= 3;
 
-  if (((tpc ^ get_byte_page) & NONPAGE_MASK) || enable_counting)
-    {
-      get_byte_page = tpc & NONPAGE_MASK;
-      get_byte_base = rx_mem_ptr (get_byte_page, MPA_READING) - get_byte_page;
-    }
+  maybe_get_mem_page (tpc);
 
   rx_data->dpc ++;
   return get_byte_base [tpc];
 }
 
 static int
-get_op (RX_Opcode_Decoded *rd, int i)
+get_op (const RX_Opcode_Decoded *rd, int i)
 {
-  RX_Opcode_Operand *o = rd->op + i;
+  const RX_Opcode_Operand *o = rd->op + i;
   int addr, rv = 0;
 
   switch (o->type)
@@ -343,8 +350,11 @@ get_op (RX_Opcode_Decoded *rd, int i)
       /* fall through */
     case RX_Operand_Postinc:	/* [Rn+] */
     case RX_Operand_Indirect:	/* [Rn + addend] */
+    case RX_Operand_TwoReg:	/* [Rn + scale * R2] */
 #ifdef CYCLE_ACCURATE
       RL (o->reg);
+      if (o->type == RX_Operand_TwoReg)
+	RL (rd->op[2].reg);
       regs.rt = -1;
       if (regs.m2m == M2M_BOTH)
 	{
@@ -359,7 +369,11 @@ get_op (RX_Opcode_Decoded *rd, int i)
       memory_source = 1;
 #endif
 
-      addr = get_reg (o->reg) + o->addend;
+      if (o->type == RX_Operand_TwoReg)
+	addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
+      else
+	addr = get_reg (o->reg) + o->addend;
+
       switch (o->size)
 	{
 	case RX_AnySize:
@@ -440,9 +454,9 @@ get_op (RX_Opcode_Decoded *rd, int i)
 }
 
 static void
-put_op (RX_Opcode_Decoded *rd, int i, int v)
+put_op (const RX_Opcode_Decoded *rd, int i, int v)
 {
-  RX_Opcode_Operand *o = rd->op + i;
+  const RX_Opcode_Operand *o = rd->op + i;
   int addr;
 
   switch (o->size)
@@ -504,6 +518,7 @@ put_op (RX_Opcode_Decoded *rd, int i, in
       /* fall through */
     case RX_Operand_Postinc:	/* [Rn+] */
     case RX_Operand_Indirect:	/* [Rn + addend] */
+    case RX_Operand_TwoReg:	/* [Rn + scale * R2] */
 
 #ifdef CYCLE_ACCURATE
       if (regs.m2m == M2M_BOTH)
@@ -518,7 +533,11 @@ put_op (RX_Opcode_Decoded *rd, int i, in
       memory_dest = 1;
 #endif
 
-      addr = get_reg (o->reg) + o->addend;
+      if (o->type == RX_Operand_TwoReg)
+	addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
+      else
+	addr = get_reg (o->reg) + o->addend;
+
       switch (o->size)
 	{
 	case RX_AnySize:
@@ -559,19 +578,19 @@ put_op (RX_Opcode_Decoded *rd, int i, in
     }
 }
 
-#define PD(x) put_op (&opcode, 0, x)
-#define PS(x) put_op (&opcode, 1, x)
-#define PS2(x) put_op (&opcode, 2, x)
-#define GD() get_op (&opcode, 0)
-#define GS() get_op (&opcode, 1)
-#define GS2() get_op (&opcode, 2)
-#define DSZ() size2bytes[opcode.op[0].size]
-#define SSZ() size2bytes[opcode.op[0].size]
-#define S2SZ() size2bytes[opcode.op[0].size]
+#define PD(x) put_op (opcode, 0, x)
+#define PS(x) put_op (opcode, 1, x)
+#define PS2(x) put_op (opcode, 2, x)
+#define GD() get_op (opcode, 0)
+#define GS() get_op (opcode, 1)
+#define GS2() get_op (opcode, 2)
+#define DSZ() size2bytes[opcode->op[0].size]
+#define SSZ() size2bytes[opcode->op[0].size]
+#define S2SZ() size2bytes[opcode->op[0].size]
 
 /* "Universal" sources.  */
-#define US1() ((opcode.op[2].type == RX_Operand_None) ? GD() : GS())
-#define US2() ((opcode.op[2].type == RX_Operand_None) ? GS() : GS2())
+#define US1() ((opcode->op[2].type == RX_Operand_None) ? GD() : GS())
+#define US2() ((opcode->op[2].type == RX_Operand_None) ? GS() : GS2())
 
 static void
 push(int val)
@@ -828,7 +847,7 @@ do_fp_exception (unsigned long opcode_pc
 }
 
 static int
-op_is_memory (RX_Opcode_Decoded *rd, int i)
+op_is_memory (const RX_Opcode_Decoded *rd, int i)
 {
   switch (rd->op[i].type)
     {
@@ -840,7 +859,9 @@ op_is_memory (RX_Opcode_Decoded *rd, int
       return 0;
     }
 }
-#define OM(i) op_is_memory (&opcode, i)
+#define OM(i) op_is_memory (opcode, i)
+
+#define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
 
 int
 decode_opcode ()
@@ -852,8 +873,7 @@ decode_opcode ()
   long long sll;
   unsigned long opcode_pc;
   RX_Data rx_data;
-  RX_Opcode_Decoded opcode;
-  int rv;
+  const RX_Opcode_Decoded *opcode;
 #ifdef CYCLE_STATS
   unsigned long long prev_cycle_count;
 #endif
@@ -861,9 +881,6 @@ decode_opcode ()
   int tx;
 #endif
 
-  if ((rv = setjmp (decode_jmp_buf)))
-    return rv;
-
 #ifdef CYCLE_STATS
   prev_cycle_count = regs.cycle_count;
 #endif
@@ -875,9 +892,25 @@ decode_opcode ()
 
   rx_cycles ++;
 
-  rx_data.dpc = opcode_pc = regs.r_pc;
-  memset (&opcode, 0, sizeof(opcode));
-  opcode_size = rx_decode_opcode (opcode_pc, &opcode, rx_get_byte, &rx_data);
+  maybe_get_mem_page (regs.r_pc);
+
+  opcode_pc = regs.r_pc;
+
+  /* Note that we don't word-swap this point, there's no point.  */
+  if (decode_cache_base[opcode_pc] == NULL)
+    {
+      RX_Opcode_Decoded *opcode_w;
+      rx_data.dpc = opcode_pc;
+      opcode_w = decode_cache_base[opcode_pc] = calloc (1, sizeof (RX_Opcode_Decoded));
+      opcode_size = rx_decode_opcode (opcode_pc, opcode_w,
+				      rx_get_byte, &rx_data);
+      opcode = opcode_w;
+    }
+  else
+    {
+      opcode = decode_cache_base[opcode_pc];
+      opcode_size = opcode->n_bytes;
+    }
 
 #ifdef CYCLE_ACCURATE
   if (branch_alignment_penalty)
@@ -896,11 +929,11 @@ decode_opcode ()
 
   regs.r_pc += opcode_size;
 
-  rx_flagmask = opcode.flags_s;
-  rx_flagand = ~(int)opcode.flags_0;
-  rx_flagor = opcode.flags_1;
+  rx_flagmask = opcode->flags_s;
+  rx_flagand = ~(int)opcode->flags_0;
+  rx_flagor = opcode->flags_1;
 
-  switch (opcode.id)
+  switch (opcode->id)
     {
     case RXO_abs:
       sll = GS ();
@@ -928,7 +961,7 @@ decode_opcode ()
     case RXO_bclr:
       ma = GD ();
       mb = GS ();
-      if (opcode.op[0].type == RX_Operand_Register)
+      if (opcode->op[0].type == RX_Operand_Register)
 	mb &= 0x1f;
       else
 	mb &= 0x07;
@@ -940,7 +973,7 @@ decode_opcode ()
     case RXO_bmcc:
       ma = GD ();
       mb = GS ();
-      if (opcode.op[0].type == RX_Operand_Register)
+      if (opcode->op[0].type == RX_Operand_Register)
 	mb &= 0x1f;
       else
 	mb &= 0x07;
@@ -955,7 +988,7 @@ decode_opcode ()
     case RXO_bnot:
       ma = GD ();
       mb = GS ();
-      if (opcode.op[0].type == RX_Operand_Register)
+      if (opcode->op[0].type == RX_Operand_Register)
 	mb &= 0x1f;
       else
 	mb &= 0x07;
@@ -965,7 +998,7 @@ decode_opcode ()
       break;
 
     case RXO_branch:
-      if (GS())
+      if (opcode->op[1].type == RX_Operand_None || GS())
 	{
 #ifdef CYCLE_ACCURATE
 	  SI old_pc = regs.r_pc;
@@ -987,9 +1020,6 @@ decode_opcode ()
 	    }
 #ifdef CYCLE_STATS
 	  branch_stalls ++;
-	  /* This is just for statistics */
-	  if (opcode.op[1].reg == 14)
-	    opcode.op[1].type = RX_Operand_None;
 #endif
 #endif
 	}
@@ -1032,11 +1062,11 @@ decode_opcode ()
       {
 	int old_psw = regs.r_psw;
 	if (rx_in_gdb)
-	  return RX_MAKE_HIT_BREAK ();
+	  DO_RETURN (RX_MAKE_HIT_BREAK ());
 	if (regs.r_intb == 0)
 	  {
 	    tprintf("BREAK hit, no vector table.\n");
-	    return RX_MAKE_EXITED(1);
+	    DO_RETURN (RX_MAKE_EXITED(1));
 	  }
 	regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
 	pushpc (old_psw);
@@ -1049,7 +1079,7 @@ decode_opcode ()
     case RXO_bset:
       ma = GD ();
       mb = GS ();
-      if (opcode.op[0].type == RX_Operand_Register)
+      if (opcode->op[0].type == RX_Operand_Register)
 	mb &= 0x1f;
       else
 	mb &= 0x07;
@@ -1061,7 +1091,7 @@ decode_opcode ()
     case RXO_btst:
       ma = GS ();
       mb = GS2 ();
-      if (opcode.op[1].type == RX_Operand_Register)
+      if (opcode->op[1].type == RX_Operand_Register)
 	mb &= 0x1f;
       else
 	mb &= 0x07;
@@ -1071,7 +1101,7 @@ decode_opcode ()
       break;
 
     case RXO_clrpsw:
-      v = 1 << opcode.op[0].reg;
+      v = 1 << opcode->op[0].reg;
       if (FLAG_PM
 	  && (v == FLAGBIT_I
 	      || v == FLAGBIT_U))
@@ -1120,60 +1150,13 @@ decode_opcode ()
       cycles (20);
       break;
 
-    case RXO_ediv:
-      ma = GS();
-      mb = GD();
-      tprintf("%d / %d = ", mb, ma);
-      if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
-	{
-	  tprintf("#NAN\n");
-	  set_flags (FLAGBIT_O, FLAGBIT_O);
-	}
-      else
-	{
-	  v = mb/ma;
-	  mb = mb%ma;
-	  tprintf("%d, rem %d\n", v, mb);
-	  set_flags (FLAGBIT_O, 0);
-	  PD (v);
-	  opcode.op[0].reg ++;
-	  PD (mb);
-	}
-      /* Note: spec says 3 to 22 cycles, we are pessimistic.  */
-      cycles (22);
-      break;
-
-    case RXO_edivu:
-      uma = GS();
-      umb = GD();
-      tprintf("%u / %u = ", umb, uma);
-      if (uma == 0)
-	{
-	  tprintf("#NAN\n");
-	  set_flags (FLAGBIT_O, FLAGBIT_O);
-	}
-      else
-	{
-	  v = umb/uma;
-	  umb = umb%uma;
-	  tprintf("%u, rem %u\n", v, umb);
-	  set_flags (FLAGBIT_O, 0);
-	  PD (v);
-	  opcode.op[0].reg ++;
-	  PD (umb);
-	}
-      /* Note: spec says 2 to 20 cycles, we are pessimistic.  */
-      cycles (20);
-      break;
-
     case RXO_emul:
       ma = GD ();
       mb = GS ();
       sll = (long long)ma * (long long)mb;
       tprintf("%d * %d = %lld\n", ma, mb, sll);
-      PD (sll);
-      opcode.op[0].reg ++;
-      PD (sll >> 32);
+      put_reg (opcode->op[0].reg, sll);
+      put_reg (opcode->op[0].reg + 1, sll >> 32);
       E2;
       break;
 
@@ -1182,9 +1165,8 @@ decode_opcode ()
       umb = GS ();
       ll = (long long)uma * (long long)umb;
       tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
-      PD (ll);
-      opcode.op[0].reg ++;
-      PD (ll >> 32);
+      put_reg (opcode->op[0].reg, ll);
+      put_reg (opcode->op[0].reg + 1, ll >> 32);
       E2;
       break;
 
@@ -1242,7 +1224,7 @@ decode_opcode ()
       v = GS ();
       if (v == 255)
 	{
-	  return rx_syscall (regs.r[5]);
+	  DO_RETURN (rx_syscall (regs.r[5]));
 	}
       else
 	{
@@ -1278,7 +1260,7 @@ decode_opcode ()
 	regs.link_register = regs.r_pc;
 #endif
 	pushpc (get_reg (pc));
-	if (opcode.id == RXO_jsrrel)
+	if (opcode->id == RXO_jsrrel)
 	  v += regs.r_pc;
 #ifdef CYCLE_ACCURATE
 	delta = v - regs.r_pc;
@@ -1323,12 +1305,6 @@ decode_opcode ()
       else
 	PD (mb);
       E (1);
-#ifdef CYCLE_STATS
-      if (opcode.op[0].type == RX_Operand_Register
-	  && opcode.op[1].type == RX_Operand_Register
-	  && opcode.op[0].reg == opcode.op[1].reg)
-	opcode.id = RXO_nop3;
-#endif
       break;
 
     case RXO_min:
@@ -1344,8 +1320,8 @@ decode_opcode ()
     case RXO_mov:
       v = GS ();
 
-      if (opcode.op[0].type == RX_Operand_Register
-	  && opcode.op[0].reg == 16 /* PSW */)
+      if (opcode->op[0].type == RX_Operand_Register
+	  && opcode->op[0].reg == 16 /* PSW */)
 	{
 	  /* Special case, LDC and POPC can't ever modify PM.  */
 	  int pm = regs.r_psw & FLAGBIT_PM;
@@ -1360,16 +1336,16 @@ decode_opcode ()
       if (FLAG_PM)
 	{
 	  /* various things can't be changed in user mode.  */
-	  if (opcode.op[0].type == RX_Operand_Register)
-	    if (opcode.op[0].reg == 32)
+	  if (opcode->op[0].type == RX_Operand_Register)
+	    if (opcode->op[0].reg == 32)
 	      {
 		v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
 		v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
 	      }
-	  if (opcode.op[0].reg == 34 /* ISP */
-	      || opcode.op[0].reg == 37 /* BPSW */
-	      || opcode.op[0].reg == 39 /* INTB */
-	      || opcode.op[0].reg == 38 /* VCT */)
+	  if (opcode->op[0].reg == 34 /* ISP */
+	      || opcode->op[0].reg == 37 /* BPSW */
+	      || opcode->op[0].reg == 39 /* INTB */
+	      || opcode->op[0].reg == 38 /* VCT */)
 	    /* These are ignored.  */
 	    break;
 	}
@@ -1381,10 +1357,10 @@ decode_opcode ()
       PD (v);
 
 #ifdef CYCLE_ACCURATE
-      if ((opcode.op[0].type == RX_Operand_Predec
-	   && opcode.op[1].type == RX_Operand_Register)
-	  || (opcode.op[0].type == RX_Operand_Postinc
-	      && opcode.op[1].type == RX_Operand_Register))
+      if ((opcode->op[0].type == RX_Operand_Predec
+	   && opcode->op[1].type == RX_Operand_Register)
+	  || (opcode->op[0].type == RX_Operand_Postinc
+	      && opcode->op[1].type == RX_Operand_Register))
 	{
 	  /* Special case: push reg doesn't cause a memory stall.  */
 	  memory_dest = 0;
@@ -1393,32 +1369,14 @@ decode_opcode ()
 #endif
 
       set_sz (v, DSZ());
-#ifdef CYCLE_STATS
-      if (opcode.op[0].type == RX_Operand_Register
-	  && opcode.op[1].type == RX_Operand_Register
-	  && opcode.op[0].reg == opcode.op[1].reg)
-	opcode.id = RXO_nop2;
-#endif
       break;
 
     case RXO_movbi:
-      /* We cheat to save on code duplication. */
-      regs.r_temp = (get_reg (opcode.op[1].reg) * size2bytes[opcode.size]
-		     + get_reg (opcode.op[2].reg));
-      opcode.op[1].reg = r_temp_idx;
-      opcode.op[1].type = RX_Operand_Indirect;
-      opcode.op[1].addend = 0;
       PD (GS ());
       cycles (1);
       break;
 
     case RXO_movbir:
-      /* We cheat to save on code duplication. */
-      regs.r_temp = (get_reg (opcode.op[1].reg) * size2bytes[opcode.size]
-		     + get_reg (opcode.op[2].reg));
-      opcode.op[1].reg = r_temp_idx;
-      opcode.op[1].type = RX_Operand_Indirect;
-      opcode.op[1].addend = 0;
       PS (GD ());
       cycles (1);
       break;
@@ -1478,6 +1436,8 @@ decode_opcode ()
       break;
 
     case RXO_nop:
+    case RXO_nop2:
+    case RXO_nop3:
       E1;
       break;
 
@@ -1487,14 +1447,14 @@ decode_opcode ()
 
     case RXO_popm:
       /* POPM cannot pop R0 (sp).  */
-      if (opcode.op[1].reg == 0 || opcode.op[2].reg == 0)
+      if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
 	EXCEPTION (EX_UNDEFINED);
-      if (opcode.op[1].reg >= opcode.op[2].reg)
+      if (opcode->op[1].reg >= opcode->op[2].reg)
 	{
 	  regs.r_pc = opcode_pc;
-	  return RX_MAKE_STOPPED (SIGILL);
+	  DO_RETURN (RX_MAKE_STOPPED (SIGILL));
 	}
-      for (v = opcode.op[1].reg; v <= opcode.op[2].reg; v++)
+      for (v = opcode->op[1].reg; v <= opcode->op[2].reg; v++)
 	{
 	  cycles (1);
 	  RLD (v);
@@ -1504,19 +1464,19 @@ decode_opcode ()
 
     case RXO_pushm:
       /* PUSHM cannot push R0 (sp).  */
-      if (opcode.op[1].reg == 0 || opcode.op[2].reg == 0)
+      if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
 	EXCEPTION (EX_UNDEFINED);
-      if (opcode.op[1].reg >= opcode.op[2].reg)
+      if (opcode->op[1].reg >= opcode->op[2].reg)
 	{
 	  regs.r_pc = opcode_pc;
 	  return RX_MAKE_STOPPED (SIGILL);
 	}
-      for (v = opcode.op[2].reg; v >= opcode.op[1].reg; v--)
+      for (v = opcode->op[2].reg; v >= opcode->op[1].reg; v--)
 	{
 	  RL (v);
 	  push (get_reg (v));
 	}
-      cycles (opcode.op[2].reg - opcode.op[1].reg + 1);
+      cycles (opcode->op[2].reg - opcode->op[1].reg + 1);
       break;
 
     case RXO_racw:
@@ -1573,7 +1533,7 @@ decode_opcode ()
 	{
 	  long long tmp;
 
-	  switch (opcode.size)
+	  switch (opcode->size)
 	    {
 	    case RX_Long:
 	      ma = mem_get_si (regs.r[1]);
@@ -1627,7 +1587,7 @@ decode_opcode ()
       else
 	set_flags (FLAGBIT_O|FLAGBIT_S, ma);
 #ifdef CYCLE_ACCURATE
-      switch (opcode.size)
+      switch (opcode->size)
 	{
 	case RX_Long:
 	  cycles (6 + 4 * tx);
@@ -1725,17 +1685,17 @@ decode_opcode ()
       break;
 
     case RXO_rtsd:
-      if (opcode.op[2].type == RX_Operand_Register)
+      if (opcode->op[2].type == RX_Operand_Register)
 	{
 	  int i;
 	  /* RTSD cannot pop R0 (sp).  */
-	  put_reg (0, get_reg (0) + GS() - (opcode.op[0].reg-opcode.op[2].reg+1)*4);
-	  if (opcode.op[2].reg == 0)
+	  put_reg (0, get_reg (0) + GS() - (opcode->op[0].reg-opcode->op[2].reg+1)*4);
+	  if (opcode->op[2].reg == 0)
 	    EXCEPTION (EX_UNDEFINED);
 #ifdef CYCLE_ACCURATE
-	  tx = opcode.op[0].reg - opcode.op[2].reg + 1;
+	  tx = opcode->op[0].reg - opcode->op[2].reg + 1;
 #endif
-	  for (i = opcode.op[2].reg; i <= opcode.op[0].reg; i ++)
+	  for (i = opcode->op[2].reg; i <= opcode->op[0].reg; i ++)
 	    {
 	      RLD (i);
 	      put_reg (i, pop ());
@@ -1807,7 +1767,7 @@ decode_opcode ()
       break;
 
     case RXO_setpsw:
-      v = 1 << opcode.op[0].reg;
+      v = 1 << opcode->op[0].reg;
       if (FLAG_PM
 	  && (v == FLAGBIT_I
 	      || v == FLAGBIT_U))
@@ -1880,7 +1840,7 @@ decode_opcode ()
 #ifdef CYCLE_ACCURATE
       tx = regs.r[3];
 #endif
-      switch (opcode.size)
+      switch (opcode->size)
 	{
 	case RX_Long:
 	  while (regs.r[3] != 0)
@@ -1923,7 +1883,7 @@ decode_opcode ()
     case RXO_stop:
       PRIVILEDGED ();
       regs.r_psw |= FLAGBIT_I;
-      return RX_MAKE_STOPPED(0);
+      DO_RETURN (RX_MAKE_STOPPED(0));
 
     case RXO_sub:
       MATH_OP (-, 0);
@@ -1939,7 +1899,7 @@ decode_opcode ()
 	  cycles (3);
 	  break;
 	}
-      switch (opcode.size)
+      switch (opcode->size)
 	{
 	case RX_Long:
 	  uma = get_reg (2);
@@ -1993,7 +1953,7 @@ decode_opcode ()
 #endif
       if (regs.r[3] == 0)
 	break;
-      switch (opcode.size)
+      switch (opcode->size)
 	{
 	case RX_Long:
 	  uma = get_reg (2);
@@ -2043,7 +2003,7 @@ decode_opcode ()
     case RXO_wait:
       PRIVILEDGED ();
       regs.r_psw |= FLAGBIT_I;
-      return RX_MAKE_STOPPED(0);
+      DO_RETURN (RX_MAKE_STOPPED(0));
 
     case RXO_xchg:
 #ifdef CYCLE_ACCURATE
@@ -2082,7 +2042,7 @@ decode_opcode ()
 #ifdef CYCLE_STATS
   if (prev_cycle_count == regs.cycle_count)
     {
-      printf("Cycle count not updated! id %s\n", id_names[opcode.id]);
+      printf("Cycle count not updated! id %s\n", id_names[opcode->id]);
       abort ();
     }
 #endif
@@ -2090,15 +2050,15 @@ decode_opcode ()
 #ifdef CYCLE_STATS
   if (running_benchmark)
     {
-      int omap = op_lookup (opcode.op[0].type, opcode.op[1].type, opcode.op[2].type);
+      int omap = op_lookup (opcode->op[0].type, opcode->op[1].type, opcode->op[2].type);
 
 
-      cycles_per_id[opcode.id][omap] += regs.cycle_count - prev_cycle_count;
-      times_per_id[opcode.id][omap] ++;
+      cycles_per_id[opcode->id][omap] += regs.cycle_count - prev_cycle_count;
+      times_per_id[opcode->id][omap] ++;
 
-      times_per_pair[prev_opcode_id][po0][opcode.id][omap] ++;
+      times_per_pair[prev_opcode_id][po0][opcode->id][omap] ++;
 
-      prev_opcode_id = opcode.id;
+      prev_opcode_id = opcode->id;
       po0 = omap;
     }
 #endif



More information about the Gdb-patches mailing list