diff options
Diffstat (limited to 'mips/mips_insts.sail')
| -rw-r--r-- | mips/mips_insts.sail | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/mips/mips_insts.sail b/mips/mips_insts.sail index 722e3d00..d8a45730 100644 --- a/mips/mips_insts.sail +++ b/mips/mips_insts.sail @@ -1286,8 +1286,8 @@ function clause execute(SDR(base, rt, offset)) = union ast member regregimm16 CACHE function clause decode (0b101111 : (regno) base : (regno) op : (imm16) imm) = Some(CACHE(base, op, imm)) -function clause execute (CACHE(base, op, imm)) = - () (* XXX NOP *) +function clause execute (CACHE(base, op, imm)) = + checkCP0Access () (* pretty much a NOP because no caches *) (* PREF - prefetching into (non-existent) caches *) @@ -1317,7 +1317,8 @@ function clause decode (0b010000 : 0b00000 : (regno) rt : (regno) rd : 0b0000000 Some(MFC0(rt, rd, sel, false)) (* MFC0 *) function clause decode (0b010000 : 0b00001 : (regno) rt : (regno) rd : 0b00000000 : (bit[3]) sel) = Some(MFC0(rt, rd, sel, true)) (* DMFC0 *) -function clause execute (MFC0(rt, rd, sel, double)) = +function clause execute (MFC0(rt, rd, sel, double)) = { + checkCP0Access(); let (bit[64]) result = switch (rd, sel) { case (0b00000,0b000) -> 0 (* 0, TLB Index *) @@ -1327,10 +1328,10 @@ function clause execute (MFC0(rt, rd, sel, double)) = case (0b00100,0b000) -> 0 (* 4, TLB Context *) case (0b00101,0b000) -> 0 (* 5, TLB PageMask *) case (0b00110,0b000) -> 0 (* 6, TLB Wired *) - case (0b00111,0b000) -> 0 (* 6, HWREna *) + case (0b00111,0b000) -> EXTZ(CP0HWREna) (* 6, HWREna *) case (0b01000,0b000) -> CP0BadVAddr (* 8, BadVAddr reg *) case (0b01000,0b001) -> 0 (* 8, BadInstr reg XXX TODO *) - case (0b01001,0b000) -> 0 (* 9, Count reg XXX TODO *) + case (0b01001,0b000) -> EXTZ(CP0Count) (* 9, Count reg *) case (0b01010,0b000) -> 0 (* 10, TLB EntryHi *) case (0b01011,0b000) -> EXTZ(CP0Compare) (* 11, Compare reg *) case (0b01100,0b000) -> EXTZ(CP0Status) (* 12, Status reg *) @@ -1356,20 +1357,24 @@ function clause execute (MFC0(rt, rd, sel, double)) = case _ -> {exit (SignalException(ResI)); 0} } in wGPR(rt) := if (double) then result else EXTS(result[31..0]) - +} union ast member (regno, regno, bit[3], bool) MTC0 function clause decode (0b010000 : 0b00100 : (regno) rt : (regno) rd : 0b00000000 : (bit[3]) sel) = Some(MTC0(rt, rd, sel, false)) (* MTC0 *) function clause decode (0b010000 : 0b00101 : (regno) rt : (regno) rd : 0b00000000 : (bit[3]) sel) = Some(MTC0(rt, rd, sel, true)) (* DMTC0 *) -function clause execute (MTC0(rt, rd, sel, double)) = +function clause execute (MTC0(rt, rd, sel, double)) = { + checkCP0Access(); let reg_val = (rGPR(rt)) in switch (rd, sel) { + case (0b00100,0b010) -> CP0UserLocal := reg_val + case (0b00111,0b000) -> CP0HWREna := (reg_val[31..30] : 0b00000000000000000000000000 : reg_val[4..0]) + case (0b01001,0b000) -> CP0Count := reg_val[31..0] case (0b01011,0b000) -> { (* 11, sel 0: Compare reg *) CP0Compare := reg_val[31..0]; - (CP0Cause.IP)[8] := 0 + (CP0Cause.IP)[15] := 0 } case (0b01100,0b000) -> { (* 12 Status *) (CP0Status.CU) := reg_val[31..28]; @@ -1391,12 +1396,31 @@ function clause execute (MTC0(rt, rd, sel, double)) = case (0b11110,0b000) -> CP0ErrorEPC := reg_val (* 30, ErrorEPC *) case _ -> exit (SignalException(ResI)) } +} + +union ast member (regno, regno) RDHWR +function clause decode (0b011111 : 0b00000 : (regno) rt : (regno) rd : 0b00000 : 0b111011) = Some(RDHWR(rt, rd)) +function clause execute (RDHWR(rt, rd)) = { + let accessLevel = getAccessLevel() in + if ((accessLevel != Kernel) & (~((CP0Status.CU)[0])) & ~(CP0HWREna[rd])) then + exit (SignalException(ResI)); + let (bit[64]) temp = switch (rd) { + case 0b00000 -> EXTZ([bitzero]) (* CPUNum *) + case 0b00001 -> EXTZ([bitzero]) (* SYNCI_step *) + case 0b00010 -> EXTZ(CP0Count) (* Count *) + case 0b00011 -> EXTZ([bitone]) (* Count resolution *) + case 0b11101 -> CP0UserLocal (* User local register *) + case _ -> exit (SignalException(ResI)) + } in + wGPR(rt) := temp; +} union ast member unit ERET function clause decode (0b010000 : 0b1 : 0b0000000000000000000 : 0b011000) = Some(ERET) function clause execute (ERET) = { + checkCP0Access(); ERETHook(); CP0LLBit := 0b0; if (CP0Status.ERL == bitone) then |
