From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27914 invoked by alias); 29 Jul 2010 18:42:03 -0000 Received: (qmail 27877 invoked by uid 22791); 29 Jul 2010 18:41:55 -0000 X-SWARE-Spam-Status: No, hits=-4.5 required=5.0 tests=AWL,BAYES_50,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_GJ,TW_OV,TW_TJ,TW_VB,T_LOTS_OF_MONEY,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 29 Jul 2010 18:41:43 +0000 Received: from int-mx04.intmail.prod.int.phx2.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.17]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o6TIffUY009662 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 29 Jul 2010 14:41:41 -0400 Received: from greed.delorie.com ([10.3.112.10]) by int-mx04.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o6TIfd1q019050 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 29 Jul 2010 14:41:40 -0400 Received: from greed.delorie.com (greed.delorie.com [127.0.0.1] (may be forged)) by greed.delorie.com (8.14.3/8.14.3) with ESMTP id o6TIfcsd017025 for ; Thu, 29 Jul 2010 14:41:38 -0400 Received: (from dj@localhost) by greed.delorie.com (8.14.3/8.14.3/Submit) id o6TIfcgn017022; Thu, 29 Jul 2010 14:41:38 -0400 Date: Thu, 29 Jul 2010 18:42:00 -0000 Message-Id: <201007291841.o6TIfcgn017022@greed.delorie.com> From: DJ Delorie To: gdb-patches@sourceware.org Subject: [rx sim] add decode cache X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-07/txt/msg00547.txt.bz2 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 #include +#include "opcode/rx.h" #include "mem.h" #include "cpu.h" #include "syscalls.h" @@ -46,6 +47,7 @@ along with this program. If not, see >= 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