From 0c1a6fee8042bbb51fb3109c0df8f2f5317e6180 Mon Sep 17 00:00:00 2001 From: Tommy Thorn Date: Mon, 23 Jun 2008 23:57:45 -0700 Subject: [PATCH] YARISIM: add a register-use decode map This isn't useful for the simulator but is for the implementation and it's easier to prepare and test in the simulator. --- yarisim/mips32.h | 6 +-- yarisim/run_simple.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++- yarisim/runmips.h | 1 + yarisim/sim.c | 1 + yarisim/support.c | 2 +- 5 files changed, 110 insertions(+), 5 deletions(-) diff --git a/yarisim/mips32.h b/yarisim/mips32.h index fb362de..6afac74 100644 --- a/yarisim/mips32.h +++ b/yarisim/mips32.h @@ -42,12 +42,12 @@ Regimm map: instr[20:16] (5 bit) typedef enum root_map { SPECIAL =0x00, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, ADDI=0x08, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, - CP0 =0x10, CP1, CP2, CP3, BEQL, BNEL, BLEZL, BGTZL, + CP0 =0x10, CP1, CP2, CP1X, BEQL, BNEL, BLEZL, BGTZL, RDHWR = 0x1f, LB =0x20, LH, LWL, LW, LBU, LHU, LWR, SB =0x28, SH, SWL, SW, SWR =0x2e, CACHE, - LL =0x30, LWC1, LWC2, PREF, LDC1=0x35, LCD2, - SC =0x38, SWC1, SWC2, SDC1=0x3d, SCD2, + LL =0x30, LWC1, LWC2, PREF, LDC1=0x35, LDC2, + SC =0x38, SWC1, SWC2, SDC1=0x3d, SDC2, } root_map_t; typedef enum reg_map { diff --git a/yarisim/run_simple.c b/yarisim/run_simple.c index 6d1629a..406a16a 100644 --- a/yarisim/run_simple.c +++ b/yarisim/run_simple.c @@ -57,6 +57,100 @@ char *inst_name[64+64+32] = { }; +/* + * Create a decode map showing which instructions use which + * fields. This is needed for an implementation to get a more precise + * load interlock. Simply assuming all instructions use both the rs + * (25:21) and rt (20:16) field leads to too many false interlocks. + * Developing and testing the map in the simulator is easier than in + * the actual implementation. + * + * We use the same compressed encoding as above. It may not be enough + * to cover all instructions. + * + * USE_RT_LATE marks instructions that use rt, but does so in a later + * stage. This matters as we _can_ forward load results to these + * instructions. + */ +enum { USE_RS = 1, + USE_RT = 2, + USE_RT_LATE = 4, +}; +unsigned char reg_use_map[64+64+128]; + +void init_reg_use_map(void) +{ + int i; + memset(reg_use_map, USE_RS | USE_RT, sizeof reg_use_map); + + // Deal with SPECIAL instructions + reg_use_map[64 + SYSCALL] = 0; + reg_use_map[64 + BREAK] = 0; + + // Deal with REGIMM instructions + for (i = 0; i < 32; ++i) + reg_use_map[128 + i] = USE_RS; + + // The main opcodes + reg_use_map[J] = 0; + reg_use_map[JAL] = 0; + reg_use_map[ADDI] = USE_RS; + reg_use_map[ADDIU] = USE_RS; + reg_use_map[SLTI] = USE_RS; + reg_use_map[SLTIU] = USE_RS; + reg_use_map[ANDI] = USE_RS; + reg_use_map[ORI] = USE_RS; + reg_use_map[XORI] = USE_RS; + reg_use_map[LUI] = 0; + + reg_use_map[CP0] = USE_RT; // Not all CP0 instruction use rt, but this is close enough + reg_use_map[CP1] = USE_RT; // Not all CP1 instruction use rt, but this is close enough + reg_use_map[CP2] = USE_RT; // Not all CP2 instruction use rt, but this is close enough + reg_use_map[CP1X] = USE_RT; // Not all CP1X instruction use rt, but this is close enough + // XXX alnv.ps uses rs, but we don't implement that + //reg_use_map[LDL] = USE_RS; + //reg_use_map[LDR] = USE_RS; + //reg_use_map[SDBBP] = 0; + //reg_use_map[JALX] = 0; + + reg_use_map[LB] = USE_RS; + reg_use_map[LH] = USE_RS; + reg_use_map[LWL] = USE_RS | USE_RT_LATE; + reg_use_map[LW] = USE_RS; + reg_use_map[LBU] = USE_RS; + reg_use_map[LHU] = USE_RS; + reg_use_map[LWR] = USE_RS | USE_RT_LATE; + //reg_use_map[LWU] = USE_RS; + + reg_use_map[SB] = USE_RS | USE_RT_LATE; + reg_use_map[SH] = USE_RS | USE_RT_LATE; + reg_use_map[SWL] = USE_RS | USE_RT_LATE; + reg_use_map[SW] = USE_RS | USE_RT_LATE; + //reg_use_map[SDL] = USE_RS | USE_RT_LATE; + //reg_use_map[SDR] = USE_RS | USE_RT_LATE; + reg_use_map[SWR] = USE_RS | USE_RT_LATE; + + reg_use_map[CACHE] = USE_RS; + reg_use_map[LL] = USE_RS; + reg_use_map[LWC1] = USE_RS; // AKA L_S + reg_use_map[LWC2] = USE_RS; + reg_use_map[PREF] = USE_RS; + //reg_use_map[LLD] = USE_RS; + //reg_use_map[L_D] = USE_RS; + reg_use_map[LDC1] = USE_RS; // AKA L_D + reg_use_map[LDC2] = USE_RS; + + reg_use_map[SC] = USE_RS | USE_RT_LATE; + reg_use_map[SWC1] = USE_RS | USE_RT_LATE; // AKA S_S + reg_use_map[SWC2] = USE_RS | USE_RT_LATE; + //reg_use_map[59??] = ??; + //reg_use_map[SCD] = USE_RS | USE_RT_LATE; + reg_use_map[SDC1] = USE_RS | USE_RT_LATE; // AKA S_D + reg_use_map[SDC2] = USE_RS | USE_RT_LATE; + //reg_use_map[SD] = USE_RS | USE_RT_LATE; +} + + #define UNTESTED() ({ if (tested[__LINE__]++ == 0) printf(__FILE__ ":%d: not tested\n", __LINE__); }) #define TESTED() @@ -345,6 +439,15 @@ void run_simple(MIPS_state_t *state) s = state->r[i.r.rs]; t = state->r[i.r.rt]; + + unsigned reg_use = reg_use_map[i.j.opcode == SPECIAL? 64 + i.r.funct : + i.j.opcode == REGIMM ? 128 + i.r.rt : + /* */ i.j.opcode]; + if (!(reg_use & USE_RS)) + s = 0xDEAD1111; + if (!(reg_use & (USE_RT | USE_RT_LATE))) + t = 0xDEAD2222; + wbr = i.r.rt; wbv = 0xDEADBEEF; // Never used, but have to shut up gcc. unsigned address = s + i.i.imm; @@ -761,7 +864,7 @@ void run_simple(MIPS_state_t *state) fatal("%08x:%08x, opcode CP1 rs=0x%x not handled\n", pc_prev, i.raw, i.r.rs); } - case CP3: fatal("%08x:%08x, opcode CP3 not handled\n", pc_prev, i.raw); + case CP1X: fatal("%08x:%08x, opcode CP1X not handled\n", pc_prev, i.raw); case BEQL: fatal("%08x:%08x, opcode BEQL not handled\n", pc_prev, i.raw); case BNEL: fatal("%08x:%08x, opcode BEQL not handled\n", pc_prev, i.raw); case LWC1: // XXX how are we going to cosimulate this? Extend the wbr address space? diff --git a/yarisim/runmips.h b/yarisim/runmips.h index 36dc485..ba52626 100644 --- a/yarisim/runmips.h +++ b/yarisim/runmips.h @@ -123,6 +123,7 @@ unsigned load(unsigned a, int c, int fetch); void store(unsigned a, unsigned v, int c); void disass(unsigned pc, inst_t i); +void init_reg_use_map(void); void run_simple(MIPS_state_t *s); void dump(char); void dump_tinymon(void); diff --git a/yarisim/sim.c b/yarisim/sim.c index 5988e07..1f9b97f 100644 --- a/yarisim/sim.c +++ b/yarisim/sim.c @@ -222,6 +222,7 @@ int main(int argc, char **argv) atexit(print_stats); signal(SIGINT, exit); mips_state.pc = program_entry; + init_reg_use_map(); run_simple(&mips_state); break; diff --git a/yarisim/support.c b/yarisim/support.c index adcc219..e6e959c 100644 --- a/yarisim/support.c +++ b/yarisim/support.c @@ -439,7 +439,7 @@ void disass(unsigned pc, inst_t i) i.r.rs); } break; - case CP3: sprintf(buf,"%-6s", "cp3"); break; + case CP1X: sprintf(buf,"%-6s", "cp1x"); break; case BEQL: sprintf(buf,"%-6s","bbql"); break; case RDHWR: if (i.r.funct == 59) { -- 2.11.4.GIT