summaryrefslogtreecommitdiff
path: root/mips_new_tc
diff options
context:
space:
mode:
authorAlasdair Armstrong2017-07-06 19:01:09 +0100
committerAlasdair Armstrong2017-07-06 19:01:09 +0100
commit205e09e36baaf8cf2aa794e84d8e13daf8c4c4b7 (patch)
tree55a04a38c4e932f17a12621e9d96b6f2d0a0a6e9 /mips_new_tc
parent4bb28c48b92a469b8a7eeae5ae6e32418c8936ae (diff)
Testing new typechecker on MIPS spec
Also: - Added support for foreach loops - Started work on type unions - Flow typing can now generate constraints, in addition to restricting range-typed variables - Various bugfixes - Better unification for nexps with multiplication
Diffstat (limited to 'mips_new_tc')
-rw-r--r--mips_new_tc/mips_epilogue.sail41
-rw-r--r--mips_new_tc/mips_insts.sail1675
-rw-r--r--mips_new_tc/mips_prelude.sail610
-rw-r--r--mips_new_tc/mips_regfp.sail455
-rw-r--r--mips_new_tc/mips_ri.sail42
-rw-r--r--mips_new_tc/mips_tlb.sail134
-rw-r--r--mips_new_tc/mips_tlb_stub.sail40
-rw-r--r--mips_new_tc/mips_wrappers.sail70
8 files changed, 3067 insertions, 0 deletions
diff --git a/mips_new_tc/mips_epilogue.sail b/mips_new_tc/mips_epilogue.sail
new file mode 100644
index 00000000..50993949
--- /dev/null
+++ b/mips_new_tc/mips_epilogue.sail
@@ -0,0 +1,41 @@
+(*========================================================================*)
+(* *)
+(* Copyright (c) 2015-2017 Robert M. Norton *)
+(* Copyright (c) 2015-2017 Kathyrn Gray *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+(* mips_epilogue.sail: end of decode, execute and AST definitions. *)
+
+end decode
+end execute
+end ast
+
+function option<ast> supported_instructions (instr) = Some(instr)
diff --git a/mips_new_tc/mips_insts.sail b/mips_new_tc/mips_insts.sail
new file mode 100644
index 00000000..d127f6db
--- /dev/null
+++ b/mips_new_tc/mips_insts.sail
@@ -0,0 +1,1675 @@
+(*========================================================================*)
+(* *)
+(* Copyright (c) 2015-2017 Robert M. Norton *)
+(* Copyright (c) 2015-2017 Kathyrn Gray *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+(* misp_insts.sail: mips instruction decode and execute clauses and AST node
+ declarations *)
+
+scattered function unit execute
+scattered typedef ast = const union
+
+val bit[32] -> option<ast> effect pure decode
+scattered function option<ast> decode
+
+(**************************************************************************************)
+(* [D]ADD[I][U] various forms of ADD *)
+(**************************************************************************************)
+
+(* DADDIU Doubleword Add Immediate Unsigned --
+ the simplest possible instruction, no undefined behaviour or exceptions
+ reg, reg, immediate *)
+
+union ast member regregimm16 DADDIU
+
+function clause decode (0b011001 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(DADDIU(rs, rt, imm))
+
+function clause execute (DADDIU (rs, rt, imm)) =
+ {
+ wGPR(rt) := rGPR(rs) + EXTS(imm)
+ }
+
+(* DADDU Doubleword Add Unsigned -- another very simple instruction,
+ reg, reg, reg *)
+
+union ast member regregreg DADDU
+
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b101101) =
+ Some(DADDU(rs, rt, rd))
+
+function clause execute (DADDU (rs, rt, rd)) =
+ {
+ wGPR(rd) := rGPR(rs) + rGPR(rt)
+ }
+
+(* DADDI Doubleword Add Immediate
+ reg, reg, imm with possible exception *)
+
+union ast member regregimm16 DADDI
+
+function clause decode (0b011000 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(DADDI(rs, rt, imm))
+
+function clause execute (DADDI (rs, rt, imm)) =
+ {
+ let (bit[65]) sum65 = (EXTS(rGPR(rs)) + EXTS(imm)) in
+ {
+ if (sum65[64] != sum65[63]) then
+ (SignalException(Ov))
+ else
+ wGPR(rt) := sum65[63..0]
+ }
+ }
+
+(* DADD Doubleword Add
+ reg, reg, reg with possible exception *)
+
+union ast member regregreg DADD
+
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b101100) =
+ Some(DADD(rs, rt, rd))
+
+function clause execute (DADD (rs, rt, rd)) =
+ {
+ let (bit[65]) sum65 = (EXTS(rGPR(rs)) + EXTS(rGPR(rt))) in
+ {
+ if sum65[64] != sum65[63] then
+ (SignalException(Ov))
+ else
+ wGPR(rd) := sum65[63..0]
+ }
+ }
+
+(* ADD 32-bit add -- reg, reg, reg with possible undefined behaviour or exception *)
+
+union ast member regregreg ADD
+
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b100000) =
+ Some(ADD(rs, rt, rd))
+
+function clause execute (ADD(rs, rt, rd)) =
+ {
+ (bit[64]) opA := rGPR(rs);
+ (bit[64]) opB := rGPR(rt);
+ if NotWordVal(opA) | NotWordVal(opB) then
+ wGPR(rd) := undefined (* XXX could exit instead *)
+ else
+ let (bit[33]) sum33 = (EXTS(opA[31 .. 0]) + EXTS(opB[31 .. 0])) in
+ if sum33[32] != sum33[31] then
+ (SignalException(Ov))
+ else
+ wGPR(rd) := EXTS(sum33[31..0])
+ }
+
+(* ADDI 32-bit add immediate -- reg, reg, imm with possible undefined behaviour or exception *)
+
+union ast member regregimm16 ADDI
+
+function clause decode (0b001000 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(ADDI(rs, rt, imm))
+
+function clause execute (ADDI(rs, rt, imm)) =
+ {
+ (bit[64]) opA := rGPR(rs);
+ if NotWordVal(opA) then
+ wGPR(rt) := undefined (* XXX could exit instead *)
+ else
+ let (bit[33]) sum33 = (EXTS(opA[31 .. 0]) + EXTS(imm)) in
+ if sum33[32] != sum33[31] then
+ (SignalException(Ov))
+ else
+ wGPR(rt) := EXTS(sum33[31..0])
+ }
+
+(* ADDU 32-bit add immediate -- reg, reg, reg with possible undefined behaviour *)
+
+union ast member regregreg ADDU
+
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b100001) =
+ Some(ADDU(rs, rt, rd))
+
+function clause execute (ADDU(rs, rt, rd)) =
+ {
+ (bit[64]) opA := rGPR(rs);
+ (bit[64]) opB := rGPR(rt);
+ if NotWordVal(opA) | NotWordVal(opB) then
+ wGPR(rd) := undefined
+ else
+ wGPR(rd) := EXTS(opA[31..0] + opB[31..0])
+ }
+
+
+(* ADDIU 32-bit add immediate -- reg, reg, imm with possible undefined behaviour *)
+
+union ast member regregimm16 ADDIU
+
+function clause decode (0b001001 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(ADDIU(rs, rt, imm))
+
+function clause execute (ADDIU(rs, rt, imm)) =
+ {
+ (bit[64]) opA := rGPR(rs);
+ if NotWordVal(opA) then
+ wGPR(rt) := undefined (* XXX could exit instead *)
+ else
+ wGPR(rt) := EXTS((opA[31 .. 0]) + EXTS(imm))
+ }
+
+(**************************************************************************************)
+(* [D]SUB[U] various forms of SUB *)
+(**************************************************************************************)
+
+(* DSUBU doubleword subtract 'unsigned' reg, reg, reg *)
+
+union ast member regregreg DSUBU
+
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b101111) =
+ Some(DSUBU(rs, rt, rd))
+
+function clause execute (DSUBU (rs, rt, rd)) =
+ {
+ wGPR(rd) := rGPR(rs) - rGPR(rt)
+ }
+
+(* DSUB reg, reg, reg with possible exception *)
+
+union ast member regregreg DSUB
+
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b101110) =
+ Some(DSUB(rs, rt, rd))
+
+function clause execute (DSUB (rs, rt, rd)) =
+ {
+ let (bit[65]) temp65 = (EXTS(rGPR(rs)) - EXTS(rGPR(rt))) in
+ {
+ if temp65[64] != temp65[63] then
+ (SignalException(Ov))
+ else
+ wGPR(rd) := temp65[63..0]
+ }
+ }
+
+(* SUB 32-bit sub -- reg, reg, reg with possible undefined behaviour or exception *)
+
+union ast member regregreg SUB
+
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b100010) =
+ Some(SUB(rs, rt, rd))
+
+function clause execute (SUB(rs, rt, rd)) =
+ {
+ (bit[64]) opA := rGPR(rs);
+ (bit[64]) opB := rGPR(rt);
+ if NotWordVal(opA) | NotWordVal(opB) then
+ wGPR(rd) := undefined (* XXX could instead *)
+ else
+ let (bit[33]) temp33 = (EXTS(opA[31..0]) - EXTS(opB[31..0])) in
+ if temp33[32] != temp33[31] then
+ (SignalException(Ov))
+ else
+ wGPR(rd) := EXTS(temp33[31..0])
+ }
+
+(* SUBU 32-bit 'unsigned' sub -- reg, reg, reg with possible undefined behaviour *)
+
+union ast member regregreg SUBU
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b100011) =
+ Some(SUBU(rs, rt, rd))
+
+function clause execute (SUBU(rs, rt, rd)) =
+ {
+ (bit[64]) opA := rGPR(rs);
+ (bit[64]) opB := rGPR(rt);
+ if NotWordVal(opA) | NotWordVal(opB) then
+ wGPR(rd) := undefined
+ else
+ wGPR(rd) := EXTS(opA[31..0] - opB[31..0])
+ }
+
+(**************************************************************************************)
+(* Logical bitwise operations *)
+(**************************************************************************************)
+
+(* AND reg, reg, reg *)
+
+union ast member regregreg AND
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b100100) =
+ Some(AND(rs, rt, rd))
+
+function clause execute (AND (rs, rt, rd)) =
+ {
+ wGPR(rd) := (rGPR(rs) & rGPR(rt))
+ }
+
+(* ANDI reg, reg, imm *)
+
+union ast member regregimm16 ANDI
+function clause decode (0b001100 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(ANDI(rs, rt, imm))
+function clause execute (ANDI (rs, rt, imm)) =
+ {
+ wGPR(rt) := (rGPR(rs) & EXTZ(imm))
+ }
+
+(* OR reg, reg, reg *)
+
+union ast member regregreg OR
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b100101) =
+ Some(OR(rs, rt, rd))
+function clause execute (OR (rs, rt, rd)) =
+ {
+ wGPR(rd) := (rGPR(rs) | rGPR(rt))
+ }
+
+(* ORI reg, reg, imm *)
+
+union ast member regregimm16 ORI
+function clause decode (0b001101 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(ORI(rs, rt, imm))
+function clause execute (ORI (rs, rt, imm)) =
+ {
+ wGPR(rt) := (rGPR(rs) | EXTZ(imm))
+ }
+
+(* NOR reg, reg, reg *)
+
+union ast member regregreg NOR
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b100111) =
+ Some(NOR(rs, rt, rd))
+function clause execute (NOR (rs, rt, rd)) =
+ {
+ wGPR(rd) := ~(rGPR(rs) | rGPR(rt))
+ }
+
+(* XOR reg, reg, reg *)
+
+union ast member regregreg XOR
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b100110) =
+ Some(XOR(rs, rt, rd))
+function clause execute (XOR (rs, rt, rd)) =
+ {
+ wGPR(rd) := (rGPR(rs) ^ rGPR(rt))
+ }
+
+(* XORI reg, reg, imm *)
+union ast member regregimm16 XORI
+function clause decode (0b001110 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(XORI(rs, rt, imm))
+function clause execute (XORI (rs, rt, imm)) =
+ {
+ wGPR(rt) := (rGPR(rs) ^ EXTZ(imm))
+ }
+
+(* LUI reg, imm 32-bit load immediate into upper 16 bits *)
+union ast member (regno, imm16) LUI
+function clause decode (0b001111 : 0b00000 : (regno) rt : (imm16) imm) =
+ Some(LUI(rt, imm))
+function clause execute (LUI (rt, imm)) =
+ {
+ wGPR(rt) := EXTS(imm : 0x0000)
+ }
+
+(**************************************************************************************)
+(* 64-bit shift operations *)
+(**************************************************************************************)
+
+(* DSLL reg, reg, imm5 *)
+
+union ast member regregreg DSLL
+function clause decode (0b000000 : 0b00000 : (regno) rt : (regno) rd : (bit[5]) sa : 0b111000) =
+ Some(DSLL(rt, rd, sa))
+function clause execute (DSLL (rt, rd, sa)) =
+ {
+
+ wGPR(rd) := (rGPR(rt) << sa) (* make tuareg mode less blue >> *)
+ }
+
+(* DSLL32 reg, reg, imm5 *)
+
+union ast member regregreg DSLL32
+function clause decode (0b000000 : 0b00000 : (regno) rt : (regno) rd : (bit[5]) sa : 0b111100) =
+ Some(DSLL32(rt, rd, sa))
+function clause execute (DSLL32 (rt, rd, sa)) =
+ {
+ wGPR(rd) := (rGPR(rt) << (0b1 : sa)) (* make tuareg mode less blue >> *)
+ }
+
+(* DSLLV reg, reg, reg *)
+
+union ast member regregreg DSLLV
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b010100) =
+ Some(DSLLV(rs, rt, rd))
+function clause execute (DSLLV (rs, rt, rd)) =
+ {
+ wGPR(rd) := (rGPR(rt) << ((rGPR(rs))[5 .. 0])) (* make tuareg mode less blue >> *)
+ (* alternative slicing based version of above
+ sa := (rGPR(rt))[5 .. 0];
+ v := rGPR(rs);
+ wGPR(rd) := v[(63-sa) .. 0] : (0b0 ^^ sa) *)
+ }
+
+(* DSRA arithmetic shift duplicating sign bit - reg, reg, imm5 *)
+
+union ast member regregreg DSRA
+function clause decode (0b000000 : 0b00000 : (regno) rt : (regno) rd : (bit[5]) sa : 0b111011) =
+ Some(DSRA(rt, rd, sa))
+function clause execute (DSRA (rt, rd, sa)) =
+ {
+ temp := rGPR(rt);
+ wGPR(rd) := ((temp[63] ^^ sa) : (temp[63 .. sa]))
+ }
+
+(* DSRA32 reg, reg, imm5 *)
+
+union ast member regregreg DSRA32
+function clause decode (0b000000 : 0b00000 : (regno) rt : (regno) rd : (bit[5]) sa : 0b111111) =
+ Some(DSRA32(rt, rd, sa))
+function clause execute (DSRA32 (rt, rd, sa)) =
+ {
+ temp := rGPR(rt);
+ sa32 := (0b1 : sa); (* sa+32 *)
+ wGPR(rd) := ((temp[63] ^^ sa32) : (temp[63 .. sa32]))
+ }
+
+(* DSRAV reg, reg, reg *)
+union ast member regregreg DSRAV
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b010111) =
+ Some(DSRAV(rs, rt, rd))
+function clause execute (DSRAV (rs, rt, rd)) =
+ {
+ temp := rGPR(rt);
+ sa := (rGPR(rs)) [5..0];
+ wGPR(rd) := ((temp[63] ^^ sa) : temp[63 .. sa])
+ }
+
+(* DSRL shift right logical - reg, reg, imm5 *)
+
+union ast member regregreg DSRL
+function clause decode (0b000000 : 0b00000 : (regno) rt : (regno) rd : (bit[5]) sa : 0b111010) =
+ Some(DSRL(rt, rd, sa))
+function clause execute (DSRL (rt, rd, sa)) =
+ {
+ temp := rGPR(rt);
+ wGPR(rd) := ((bitzero ^^ sa) : (temp[63 .. sa]))
+ }
+
+(* DSRL32 reg, reg, imm5 *)
+
+union ast member regregreg DSRL32
+function clause decode (0b000000 : 0b00000 : (regno) rt : (regno) rd : (bit[5]) sa : 0b111110) =
+ Some(DSRL32(rt, rd, sa))
+function clause execute (DSRL32 (rt, rd, sa)) =
+ {
+ temp := rGPR(rt);
+ sa32 := (0b1 : sa); (* sa+32 *)
+ wGPR(rd) := ((bitzero ^^ sa32) : (temp[63 .. sa32]))
+ }
+
+(* DSRLV reg, reg, reg *)
+
+union ast member regregreg DSRLV
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b010110) =
+ Some(DSRLV(rs, rt, rd))
+function clause execute (DSRLV (rs, rt, rd)) =
+ {
+ temp := rGPR(rt);
+ sa := (rGPR(rs)) [5..0];
+ wGPR(rd) := ((bitzero ^^ sa) : temp[63 .. sa])
+ }
+
+(**************************************************************************************)
+(* 32-bit shift operations *)
+(**************************************************************************************)
+
+(* SLL 32-bit shift left *)
+
+union ast member regregreg SLL
+function clause decode (0b000000 : 0b00000 : (regno) rt : (regno) rd : (regno) sa : 0b000000) =
+ Some(SLL(rt, rd, sa))
+function clause execute (SLL(rt, rd, sa)) =
+ {
+ wGPR(rd) := EXTS((rGPR(rt)) [(31-sa)..0] : (bitzero ^^ sa))
+ }
+
+(* SLLV 32-bit shift left variable *)
+
+union ast member regregreg SLLV
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b000100) =
+ Some(SLLV(rs, rt, rd))
+function clause execute (SLLV(rs, rt, rd)) =
+ {
+ sa := (rGPR(rs))[4..0];
+ wGPR(rd) := EXTS((rGPR(rt)) [(31-sa)..0] : (bitzero ^^ sa))
+ }
+
+(* SRA 32-bit arithmetic shift right *)
+
+union ast member regregreg SRA
+function clause decode (0b000000 : 0b00000 : (regno) rt : (regno) rd : (regno) sa : 0b000011) =
+ Some(SRA(rt, rd, sa))
+function clause execute (SRA(rt, rd, sa)) =
+ {
+ temp := rGPR(rt);
+ if (NotWordVal(temp)) then
+ wGPR(rd) := undefined
+ else
+ wGPR(rd) := (temp[31] ^^ (sa+32)) : temp [31..sa]
+ }
+
+(* SRAV 32-bit arithmetic shift right variable *)
+
+union ast member regregreg SRAV
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b000111) =
+ Some(SRAV(rs, rt, rd))
+function clause execute (SRAV(rs, rt, rd)) =
+ {
+ temp := rGPR(rt);
+ sa := (rGPR(rs))[4..0];
+ if (NotWordVal(temp)) then
+ wGPR(rd) := undefined
+ else
+ wGPR(rd) := (temp[31] ^^ (sa+32)) : temp [31..sa]
+ }
+
+(* SRL 32-bit shift right *)
+
+union ast member regregreg SRL
+function clause decode (0b000000 : 0b00000 : (regno) rt : (regno) rd : (regno) sa : 0b000010) =
+ Some(SRL(rt, rd, sa))
+function clause execute (SRL(rt, rd, sa)) =
+ {
+ temp := rGPR(rt);
+ if (NotWordVal(temp)) then
+ wGPR(rd) := undefined
+ else
+ wGPR(rd) := EXTS((bitzero ^^ sa) : (temp [31..sa]))
+ }
+
+(* SRLV 32-bit shift right variable *)
+
+union ast member regregreg SRLV
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b000110) =
+ Some(SRLV(rs, rt, rd))
+function clause execute (SRLV(rs, rt, rd)) =
+ {
+ temp := rGPR(rt);
+ sa := (rGPR(rs))[4..0];
+ if (NotWordVal(temp)) then
+ wGPR(rd) := undefined
+ else
+ wGPR(rd) := EXTS((bitzero ^^ sa) : (temp [31..sa]))
+ }
+
+(**************************************************************************************)
+(* set less than / conditional move *)
+(**************************************************************************************)
+
+(* SLT set if less than (signed) *)
+
+union ast member regregreg SLT
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b101010) =
+ Some(SLT(rs, rt, rd))
+function clause execute (SLT(rs, rt, rd)) =
+ {
+ wGPR(rd) := if (rGPR(rs) <_s rGPR(rt)) then 1 else 0
+ }
+
+(* SLT set if less than immediate (signed) *)
+
+union ast member regregimm16 SLTI
+function clause decode (0b001010 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(SLTI(rs, rt, imm))
+function clause execute (SLTI(rs, rt, imm)) =
+ {
+ let imm_val = signed(imm) in
+ let rs_val = signed(rGPR(rs)) in
+ wGPR(rt) := if (rs_val < imm_val) then 0x0000000000000001 else 0x0000000000000000
+ }
+
+(* SLTU set if less than unsigned *)
+
+union ast member regregreg SLTU
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b101011) =
+ Some(SLTU(rs, rt, rd))
+function clause execute (SLTU(rs, rt, rd)) =
+ {
+ let rs_val = (0b0 : (rGPR(rs))) in
+ let rt_val = (0b0 : (rGPR(rt))) in
+ wGPR(rd) := (if (rs_val < rt_val) then 1 else 0)
+ }
+
+(* SLTIU set if less than immediate unsigned *)
+
+union ast member regregimm16 SLTIU
+function clause decode (0b001011 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(SLTIU(rs, rt, imm))
+function clause execute (SLTIU(rs, rt, imm)) =
+ {
+ let rs_val = (0b0 : (rGPR(rs))) in
+ let imm_val = (0b0 : ((bit[64])(EXTS(imm)))) in
+ wGPR(rt) := (if (rs_val < imm_val) then 1 else 0)
+ }
+
+(* MOVN move if non-zero *)
+
+union ast member regregreg MOVN
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b001011) =
+ Some(MOVN(rs, rt, rd))
+function clause execute (MOVN(rs, rt, rd)) =
+ {
+ if (rGPR(rt) != 0x0000000000000000) then
+ wGPR(rd) := rGPR(rs)
+ }
+
+(* MOVZ move if zero *)
+
+union ast member regregreg MOVZ
+function clause decode (0b000000 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b001010) =
+ Some(MOVZ(rs, rt, rd))
+function clause execute (MOVZ(rs, rt, rd)) =
+ {
+ if (rGPR(rt) == 0x0000000000000000) then
+ wGPR(rd) := rGPR(rs)
+ }
+
+(******************************************************************************)
+(* MUL/DIV instructions *)
+(******************************************************************************)
+
+(* MFHI move from HI register *)
+union ast member regno MFHI
+function clause decode (0b000000 : 0b0000000000 : (regno) rd : 0b00000 : 0b010000) =
+ Some(MFHI(rd))
+function clause execute (MFHI(rd)) =
+ {
+ wGPR(rd) := HI
+ }
+
+(* MFLO move from LO register *)
+union ast member regno MFLO
+function clause decode (0b000000 : 0b0000000000 : (regno) rd : 0b00000 : 0b010010) =
+ Some(MFLO(rd))
+function clause execute (MFLO(rd)) =
+ {
+ wGPR(rd) := LO
+ }
+
+(* MTHI move to HI register *)
+union ast member regno MTHI
+function clause decode (0b000000 : (regno) rs : 0b000000000000000 : 0b010001) =
+ Some(MTHI(rs))
+function clause execute (MTHI(rs)) =
+ {
+ HI := rGPR(rs)
+ }
+
+(* MTLO move to LO register *)
+union ast member regno MTLO
+function clause decode (0b000000 : (regno) rs : 0b000000000000000 : 0b010011) =
+ Some(MTLO(rs))
+function clause execute (MTLO(rs)) =
+ {
+ LO := rGPR(rs)
+ }
+
+(* MUL 32-bit multiply into GPR *)
+union ast member regregreg MUL
+function clause decode (0b011100 : (regno) rs : (regno) rt : (regno) rd : 0b00000 : 0b000010) =
+ Some(MUL(rs, rt, rd))
+function clause execute (MUL(rs, rt, rd)) =
+ {
+ rsVal := rGPR(rs);
+ rtVal := rGPR(rt);
+ (bit[64]) result := (rsVal[31..0]) *_s (rtVal[31..0]);
+ wGPR(rd) := if (NotWordVal(rsVal) | NotWordVal(rtVal)) then
+ undefined
+ else
+ EXTS(result[31..0]);
+ (* HI and LO are technically undefined after MUL, but this causes problems with tests and
+ (potentially) context switch so just leave them alone
+ HI := undefined;
+ LO := undefined;
+ *)
+ }
+
+(* MULT 32-bit multiply into HI/LO *)
+union ast member (regno, regno) MULT
+function clause decode (0b000000 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b011000) =
+ Some(MULT(rs, rt))
+function clause execute (MULT(rs, rt)) =
+ {
+ rsVal := rGPR(rs);
+ rtVal := rGPR(rt);
+ (bit[64]) result := if (NotWordVal(rsVal) | NotWordVal(rtVal)) then
+ undefined
+ else
+ (rsVal[31..0]) *_s (rtVal[31..0]);
+ HI := EXTS(result[63..32]);
+ LO := EXTS(result[31..0]);
+ }
+
+(* MULTU 32-bit unsignedm rultiply into HI/LO *)
+union ast member (regno, regno) MULTU
+function clause decode (0b000000 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b011001) =
+ Some(MULTU(rs, rt))
+function clause execute (MULTU(rs, rt)) =
+ {
+ rsVal := rGPR(rs);
+ rtVal := rGPR(rt);
+ (bit[64]) result := if (NotWordVal(rsVal) | NotWordVal(rtVal)) then
+ undefined
+ else
+ (rsVal[31..0]) * (rtVal[31..0]);
+ HI := EXTS(result[63..32]);
+ LO := EXTS(result[31..0]);
+ }
+
+(* DMULT 64-bit multiply into HI/LO *)
+union ast member (regno, regno) DMULT
+function clause decode (0b000000 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b011100) =
+ Some(DMULT(rs, rt))
+function clause execute (DMULT(rs, rt)) =
+ {
+ (bit[128]) result := (rGPR(rs)) *_s (rGPR(rt));
+ HI := (result[127..64]);
+ LO := (result[63..0]);
+ }
+
+(* DMULTU 64-bit unsigned multiply into HI/LO *)
+union ast member (regno, regno) DMULTU
+function clause decode (0b000000 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b011101) =
+ Some(DMULTU(rs, rt))
+function clause execute (DMULTU(rs, rt)) =
+ {
+ (bit[128]) result := (rGPR(rs)) * (rGPR(rt));
+ HI := (result[127..64]);
+ LO := (result[63..0]);
+ }
+
+(* MADD 32-bit signed multiply and add into HI/LO *)
+union ast member (regno, regno) MADD
+function clause decode (0b011100 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b000000) =
+ Some(MADD(rs, rt))
+function clause execute (MADD(rs, rt)) =
+ {
+ rsVal := rGPR(rs);
+ rtVal := rGPR(rt);
+ (bit[64]) mul_result := if (NotWordVal(rsVal) | NotWordVal(rtVal)) then
+ undefined
+ else
+ ((rsVal[31..0]) *_s (rtVal[31..0]));
+ (bit[64]) result := mul_result + (HI[31..0] : LO[31..0]);
+ HI := EXTS(result[63..32]);
+ LO := EXTS(result[31..0]);
+ }
+
+(* MADDU 32-bit unsigned multiply and add into HI/LO *)
+union ast member (regno, regno) MADDU
+function clause decode (0b011100 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b000001) =
+ Some(MADDU(rs, rt))
+function clause execute (MADDU(rs, rt)) =
+ {
+ rsVal := rGPR(rs);
+ rtVal := rGPR(rt);
+ (bit[64]) mul_result := if (NotWordVal(rsVal) | NotWordVal(rtVal)) then
+ undefined
+ else
+ ((rsVal[31..0]) * (rtVal[31..0]));
+ (bit[64]) result := mul_result + (HI[31..0] : LO[31..0]);
+ HI := EXTS(result[63..32]);
+ LO := EXTS(result[31..0]);
+ }
+
+(* MSUB 32-bit signed multiply and sub from HI/LO *)
+union ast member (regno, regno) MSUB
+function clause decode (0b011100 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b000100) =
+ Some(MSUB(rs, rt))
+function clause execute (MSUB(rs, rt)) =
+ {
+ rsVal := rGPR(rs);
+ rtVal := rGPR(rt);
+ (bit[64]) mul_result := if (NotWordVal(rsVal) | NotWordVal(rtVal)) then
+ undefined
+ else
+ ((rsVal[31..0]) *_s (rtVal[31..0]));
+ (bit[64]) result := (HI[31..0] : LO[31..0]) - mul_result;
+ HI := EXTS(result[63..32]);
+ LO := EXTS(result[31..0]);
+ }
+
+(* MSUBU 32-bit unsigned multiply and sub from HI/LO *)
+union ast member (regno, regno) MSUBU
+function clause decode (0b011100 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b000101) =
+ Some(MSUBU(rs, rt))
+function clause execute (MSUBU(rs, rt)) =
+ {
+ rsVal := rGPR(rs);
+ rtVal := rGPR(rt);
+ (bit[64]) mul_result := if (NotWordVal(rsVal) | NotWordVal(rtVal)) then
+ undefined
+ else
+ ((rsVal[31..0]) * (rtVal[31..0]));
+ (bit[64]) result := (HI[31..0] : LO[31..0]) - mul_result;
+ HI := EXTS(result[63..32]);
+ LO := EXTS(result[31..0]);
+ }
+
+(* DIV 32-bit divide into HI/LO *)
+union ast member (regno, regno) DIV
+function clause decode (0b000000 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b011010) =
+ Some(DIV(rs, rt))
+function clause execute (DIV(rs, rt)) =
+ {
+ rsVal := rGPR(rs);
+ rtVal := rGPR(rt);
+ let ((bit[32]) q, (bit[32])r) = (
+ if (NotWordVal(rsVal) | NotWordVal(rtVal) | (rtVal == 0)) then
+ (undefined, undefined)
+ else
+ let si = (signed((rsVal[31..0]))) in
+ let ti = (signed((rtVal[31..0]))) in
+ let qi = (si quot ti) in
+ let ri = (si - (ti*qi)) in
+ ((bit[32]) qi, (bit[32]) ri))
+ in
+ {
+ HI := EXTS(r);
+ LO := EXTS(q);
+ }
+ }
+
+(* DIVU 32-bit unsigned divide into HI/LO *)
+union ast member (regno, regno) DIVU
+function clause decode (0b000000 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b011011) =
+ Some(DIVU(rs, rt))
+function clause execute (DIVU(rs, rt)) =
+ {
+ rsVal := rGPR(rs);
+ rtVal := rGPR(rt);
+ let ((bit[32]) q, (bit[32])r) = (
+ if (NotWordVal(rsVal) | NotWordVal(rtVal) | rtVal == 0) then
+ (undefined, undefined)
+ else
+ let si = unsigned(rsVal[31..0]) in
+ let ti = unsigned(rtVal[31..0]) in
+ let qi = (si quot ti) in
+ let ri = (si mod ti) in
+ ((bit[32]) qi, (bit[32]) ri))
+ in
+ {
+ HI := EXTS(r);
+ LO := EXTS(q);
+ }
+ }
+
+(* DDIV 64-bit divide into HI/LO *)
+union ast member (regno, regno) DDIV
+function clause decode (0b000000 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b011110) =
+ Some(DDIV(rs, rt))
+function clause execute (DDIV(rs, rt)) =
+ {
+ rsVal := signed(rGPR(rs));
+ rtVal := signed(rGPR(rt));
+ let ((bit[64])q, (bit[64])r) = (if (rtVal == 0)
+ then (undefined, undefined)
+ else
+ let qi = (rsVal quot rtVal) in
+ let ri = (rsVal - (qi * rtVal)) in
+ ((bit[64]) qi, (bit[64]) ri)) in
+ {
+ LO := q;
+ HI := r;
+ }
+ }
+
+(* DDIV 64-bit divide into HI/LO *)
+union ast member (regno, regno) DDIVU
+function clause decode (0b000000 : (regno) rs : (regno) rt : 0b00000 : 0b00000 : 0b011111) =
+ Some(DDIVU(rs, rt))
+function clause execute (DDIVU(rs, rt)) =
+ {
+ (int) rsVal := rGPR(rs);
+ (int) rtVal := rGPR(rt);
+ let ((bit[64])q, (bit[64])r) = (if (rtVal == 0)
+ then (undefined, undefined)
+ else let qi = (rsVal quot rtVal) in
+ let ri = (rsVal mod rtVal) in
+ ((bit[64]) qi, (bit[64]) ri)) in
+ {
+ LO := q;
+ HI := r;
+ }
+ }
+
+(**************************************************************************************)
+(* Jump instructions -- unconditional branches *)
+(**************************************************************************************)
+
+(* J - jump, the simplest control flow instruction, with branch delay slot *)
+union ast member (bit[26]) J
+function clause decode (0b000010 : (bit[26]) offset) =
+ Some(J(offset))
+function clause execute (J(offset)) =
+ {
+ delayedPC := (PC + 4)[63..28] : offset : 0b00;
+ branchPending := 1
+ }
+
+(* JAL - jump and link *)
+union ast member (bit[26]) JAL
+function clause decode (0b000011 : (bit[26]) offset) =
+ Some(JAL(offset))
+function clause execute (JAL(offset)) =
+ {
+ delayedPC := (PC + 4)[63..28] : offset : 0b00;
+ branchPending := 1;
+ wGPR(31) := PC + 8;
+ }
+
+(* JR -- jump via register *)
+union ast member regno JR
+function clause decode (0b000000 : (regno) rs : 0b00000 : 0b00000 : (regno) hint : 0b001000) =
+ Some(JR(rs)) (* hint is ignored *)
+function clause execute (JR(rs)) =
+ {
+ delayedPC := rGPR(rs);
+ branchPending := 1;
+ }
+
+(* JALR -- jump via register with link *)
+union ast member (regno, regno) JALR
+function clause decode (0b000000 : (regno) rs : 0b00000 : (regno) rd : (regno) hint : 0b001001) =
+ Some(JALR(rs, rd)) (* hint is ignored *)
+function clause execute (JALR(rs, rd)) =
+ {
+ delayedPC := rGPR(rs);
+ branchPending := 1;
+ wGPR(rd) := PC + 8;
+ }
+
+(**************************************************************************************)
+(* B[N]EQ[L] - branch on (not) equal (likely) *)
+(* Conditional branch instructions with two register operands *)
+(**************************************************************************************)
+
+union ast member (regno, regno, imm16, bool, bool) BEQ
+function clause decode (0b000100 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(BEQ(rs, rt, imm, false, false)) (* BEQ *)
+function clause decode (0b010100 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(BEQ(rs, rt, imm, false, true)) (* BEQL *)
+function clause decode (0b000101 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(BEQ(rs, rt, imm, true , false)) (* BNE *)
+function clause decode (0b010101 : (regno) rs : (regno) rt : (imm16) imm) =
+ Some(BEQ(rs, rt, imm, true , true)) (* BNEL *)
+function clause execute (BEQ(rs, rd, imm, ne, likely)) =
+ {
+ if ((rGPR(rs) == rGPR(rd)) ^ ne) then
+ {
+ let (bit[64]) offset = (EXTS(imm : 0b00) + 4) in
+ delayedPC := PC + offset;
+ branchPending := 1;
+ }
+ else
+ {
+ if (likely) then
+ nextPC := PC + 8; (* skip branch delay *)
+ }
+ }
+
+(*
+
+ Branches comparing with zero (single register operand, possible link in r31)
+*)
+
+(**************************************************************************************)
+(* BGEZ[AL][L] - branch on comparison with zero (possibly link, likely) *)
+(* Conditional branch instructions with single register operand *)
+(**************************************************************************************)
+
+union ast member (regno, imm16, Comparison, bool, bool) BCMPZ
+function clause decode (0b000001 : (regno) rs : 0b00000 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, LT, false, false)) (* BLTZ *)
+function clause decode (0b000001 : (regno) rs : 0b10000 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, LT, true, false)) (* BLTZAL *)
+function clause decode (0b000001 : (regno) rs : 0b00010 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, LT, false, true)) (* BLTZL *)
+function clause decode (0b000001 : (regno) rs : 0b10010 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, LT, true, true)) (* BLTZALL *)
+
+function clause decode (0b000001 : (regno) rs : 0b00001 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, GE, false, false)) (* BGEZ *)
+function clause decode (0b000001 : (regno) rs : 0b10001 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, GE, true, false)) (* BGEZAL *)
+function clause decode (0b000001 : (regno) rs : 0b00011 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, GE, false, true)) (* BGEZL *)
+function clause decode (0b000001 : (regno) rs : 0b10011 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, GE, true, true)) (* BGEZALL *)
+
+function clause decode (0b000111 : (regno) rs : 0b00000 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, GT, false, false)) (* BGTZ *)
+function clause decode (0b010111 : (regno) rs : 0b00000 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, GT, false, true)) (* BGTZL *)
+
+function clause decode (0b000110 : (regno) rs : 0b00000 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, LE, false, false)) (* BLEZ *)
+function clause decode (0b010110 : (regno) rs : 0b00000 : (imm16) imm) =
+ Some(BCMPZ(rs, imm, LE, false, true)) (* BLEZL *)
+
+function clause execute (BCMPZ(rs, imm, cmp, link, likely)) =
+ {
+ (bit[64]) linkVal := PC + 8;
+ regVal := rGPR(rs);
+ condition := compare(cmp, regVal, 0);
+ if (condition) then
+ {
+ let (bit[64]) offset = (EXTS(imm : 0b00) + 4) in
+ delayedPC := PC + offset;
+ branchPending := 1;
+ }
+ else if (likely) then
+ {
+ nextPC := PC + 8 (* skip branch delay *)
+ };
+ if (link) then
+ wGPR(31) := linkVal
+ }
+
+(**************************************************************************************)
+(* SYSCALL/BREAK/WAIT/Trap *)
+(**************************************************************************************)
+
+(* Co-opt syscall 0xfffff for use as thread start in pccmem *)
+union ast member unit SYSCALL_THREAD_START
+function clause decode (0b000000 : 0xfffff : 0b001100) =
+ Some(SYSCALL_THREAD_START)
+function clause execute (SYSCALL_THREAD_START) = ()
+
+
+(* fake stop fetching instruction for ppcmem, execute doesn't do anything,
+ decode never produces it *)
+
+union ast member unit ImplementationDefinedStopFetching
+function clause execute (ImplementationDefinedStopFetching) = ()
+
+
+union ast member unit SYSCALL
+function clause decode (0b000000 : (bit[20]) code : 0b001100) =
+ Some(SYSCALL) (* code is ignored *)
+function clause execute (SYSCALL) =
+ {
+ (SignalException(Sys))
+ }
+
+(* BREAK is identical to SYSCALL exception for the exception raised *)
+union ast member unit BREAK
+function clause decode (0b000000 : (bit[20]) code : 0b001101) =
+ Some(BREAK) (* code is ignored *)
+function clause execute (BREAK) =
+ {
+ (SignalException(Bp))
+ }
+
+(* Accept WAIT as a NOP *)
+union ast member unit WAIT
+function clause decode (0b010000 : 0x80000 : 0b100000) =
+ Some(WAIT) (* we only accept code == 0 *)
+function clause execute (WAIT) = {
+ nextPC := PC;
+}
+
+(* Trap instructions with two register operands *)
+union ast member (regno, regno, Comparison) TRAPREG
+function clause decode (0b000000 : (regno) rs : (regno) rt : (bit[10]) code : 0b110000) =
+ Some(TRAPREG(rs, rt, GE)) (* TGE *)
+function clause decode (0b000000 : (regno) rs : (regno) rt : (bit[10]) code : 0b110001) =
+ Some(TRAPREG(rs, rt, GEU)) (* TGEU *)
+function clause decode (0b000000 : (regno) rs : (regno) rt : (bit[10]) code : 0b110010) =
+ Some(TRAPREG(rs, rt, LT)) (* TLT *)
+function clause decode (0b000000 : (regno) rs : (regno) rt : (bit[10]) code : 0b110011) =
+ Some(TRAPREG(rs, rt, LTU)) (* TLTU *)
+function clause decode (0b000000 : (regno) rs : (regno) rt : (bit[10]) code : 0b110100) =
+ Some(TRAPREG(rs, rt, EQ)) (* TEQ *)
+function clause decode (0b000000 : (regno) rs : (regno) rt : (bit[10]) code : 0b110110) =
+ Some(TRAPREG(rs, rt, NE)) (* TNE *)
+function clause execute (TRAPREG(rs, rt, cmp)) =
+ {
+ rs_val := rGPR(rs);
+ rt_val := rGPR(rt);
+ condition := compare(cmp, rs_val, rt_val);
+ if (condition) then
+ (SignalException(Tr))
+ }
+
+
+(* Trap instructions with one register and one immediate operand *)
+union ast member (regno, imm16, Comparison) TRAPIMM
+function clause decode (0b000001 : (regno) rs : 0b01100 : (imm16) imm) =
+ Some(TRAPIMM(rs, imm, EQ)) (* TEQI *)
+function clause decode (0b000001 : (regno) rs : 0b01110 : (imm16) imm) =
+ Some(TRAPIMM(rs, imm, NE)) (* TNEI *)
+function clause decode (0b000001 : (regno) rs : 0b01000 : (imm16) imm) =
+ Some(TRAPIMM(rs, imm, GE)) (* TGEI *)
+function clause decode (0b000001 : (regno) rs : 0b01001 : (imm16) imm) =
+ Some(TRAPIMM(rs, imm, GEU)) (* TGEIU *)
+function clause decode (0b000001 : (regno) rs : 0b01010 : (imm16) imm) =
+ Some(TRAPIMM(rs, imm, LT)) (* TLTI *)
+function clause decode (0b000001 : (regno) rs : 0b01011 : (imm16) imm) =
+ Some(TRAPIMM(rs, imm, LTU)) (* TLTIU *)
+function clause execute (TRAPIMM(rs, imm, cmp)) =
+ {
+ rs_val := rGPR(rs);
+ imm_val := EXTS(imm);
+ condition := compare(cmp, rs_val, imm_val);
+ if (condition) then
+ (SignalException(Tr))
+ }
+
+(**************************************************************************************)
+(* Load instructions -- various width/signs *)
+(**************************************************************************************)
+
+union ast member (WordType, bool, bool, regno, regno, imm16) Load
+function clause decode (0b100000 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Load(B, true, false, base, rt, offset)) (* LB *)
+function clause decode (0b100100 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Load(B, false, false, base, rt, offset)) (* LBU *)
+function clause decode (0b100001 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Load(H, true, false, base, rt, offset)) (* LH *)
+function clause decode (0b100101 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Load(H, false, false, base, rt, offset)) (* LHU *)
+function clause decode (0b100011 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Load(W, true, false, base, rt, offset)) (* LW *)
+function clause decode (0b100111 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Load(W, false, false, base, rt, offset)) (* LWU *)
+function clause decode (0b110111 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Load(D, false, false, base, rt, offset)) (* LD *)
+function clause decode (0b110000 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Load(W, true, true, base, rt, offset)) (* LL *)
+function clause decode (0b110100 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Load(D, false, true, base, rt, offset)) (* LLD *)
+function clause execute (Load(width, signed, linked, base, rt, offset)) =
+ {
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), LoadData, width);
+ if ~ (isAddressAligned(vAddr, width)) then
+ (SignalExceptionBadAddr(AdEL, vAddr)) (* unaligned access *)
+ else
+ let pAddr = (TLBTranslate(vAddr, LoadData)) in
+ {
+ memResult := if (linked) then
+ {
+ CP0LLBit := 0b1;
+ CP0LLAddr := pAddr;
+ MEMr_reserve_wrapper(pAddr, wordWidthBytes(width));
+ }
+ else
+ MEMr_wrapper(pAddr, wordWidthBytes(width));
+ if (signed) then
+ wGPR(rt) := EXTS(memResult)
+ else
+ wGPR(rt) := EXTZ(memResult)
+ }
+ }
+
+(**************************************************************************************)
+(* Store instructions -- various widths *)
+(**************************************************************************************)
+
+union ast member (WordType, bool, regno, regno, imm16) Store
+function clause decode (0b101000 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Store(B, false, base, rt, offset)) (* SB *)
+function clause decode (0b101001 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Store(H, false, base, rt, offset)) (* SH *)
+function clause decode (0b101011 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Store(W, false, base, rt, offset)) (* SW *)
+function clause decode (0b111111 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Store(D, false, base, rt, offset)) (* SD *)
+function clause decode (0b111000 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Store(W, true, base, rt, offset)) (* SC *)
+function clause decode (0b111100 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(Store(D, true, base, rt, offset)) (* SCD *)
+function clause execute (Store(width, conditional, base, rt, offset)) =
+ {
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), StoreData, width);
+ (bit[64]) rt_val := rGPR(rt);
+ if ~ (isAddressAligned(vAddr, width)) then
+ (SignalExceptionBadAddr(AdES, vAddr)) (* unaligned access *)
+ else
+ let pAddr = (TLBTranslate(vAddr, StoreData)) in
+ {
+ if (conditional) then
+ {
+ success := if (CP0LLBit[0]) then switch(width)
+ {
+ case B -> MEMw_conditional_wrapper(pAddr, 1, rt_val[7..0])
+ case H -> MEMw_conditional_wrapper(pAddr, 2, rt_val[15..0])
+ case W -> MEMw_conditional_wrapper(pAddr, 4, rt_val[31..0])
+ case D -> MEMw_conditional_wrapper(pAddr, 8, rt_val)
+ } else false;
+ wGPR(rt) := EXTZ([success])
+ }
+ else
+ switch(width)
+ {
+ case B -> MEMw_wrapper(pAddr, 1) := rt_val[7..0]
+ case H -> MEMw_wrapper(pAddr, 2) := rt_val[15..0]
+ case W -> MEMw_wrapper(pAddr, 4) := rt_val[31..0]
+ case D -> MEMw_wrapper(pAddr, 8) := rt_val
+ }
+ }
+ }
+
+(* LWL - Load word left (big-endian only) *)
+
+union ast member regregimm16 LWL
+function clause decode(0b100010 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(LWL(base, rt, offset))
+function clause execute(LWL(base, rt, offset)) =
+ {
+ (* XXX length check not quite right, but conservative *)
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), LoadData, W);
+ let pAddr = (TLBTranslate(vAddr, LoadData)) in
+ {
+ mem_val := MEMr_wrapper (pAddr[63..2] : 0b00, 4); (* read word of interest *)
+ reg_val := rGPR(rt);
+ wGPR(rt) := EXTS(switch(vAddr[1..0])
+ {
+ case 0b00 -> mem_val
+ case 0b01 -> mem_val[23..0] : reg_val[07..0]
+ case 0b10 -> mem_val[15..0] : reg_val[15..0]
+ case 0b11 -> mem_val[07..0] : reg_val[23..0]
+ });
+ }
+ }
+union ast member regregimm16 LWR
+function clause decode(0b100110 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(LWR(base, rt, offset))
+function clause execute(LWR(base, rt, offset)) =
+ {
+ (* XXX length check not quite right, but conservative *)
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), LoadData, W);
+ let pAddr = (TLBTranslate(vAddr, LoadData)) in
+ {
+ mem_val := MEMr_wrapper (pAddr[63..2] : 0b00, 4); (* read word of interest *)
+ reg_val := rGPR(rt);
+ wGPR(rt) := EXTS(switch(vAddr[1..0]) (* it is acceptable to sign extend in all cases *)
+ {
+ case 0b00 -> reg_val[31..8] : mem_val[31..24]
+ case 0b01 -> reg_val[31..16] : mem_val[31..16]
+ case 0b10 -> reg_val[31..24] : mem_val[31..8]
+ case 0b11 -> mem_val
+ });
+ }
+ }
+
+(* SWL - Store word left *)
+union ast member regregimm16 SWL
+function clause decode(0b101010 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(SWL(base, rt, offset))
+function clause execute(SWL(base, rt, offset)) =
+ {
+ (* XXX length check not quite right, but conservative *)
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), StoreData, W);
+ let pAddr = (TLBTranslate(vAddr, StoreData)) in
+ {
+ reg_val := rGPR(rt);
+ switch (vAddr[1..0])
+ {
+ case 0b00 -> (MEMw_wrapper(pAddr, 4) := reg_val[31..0])
+ case 0b01 -> (MEMw_wrapper(pAddr, 3) := reg_val[31..8])
+ case 0b10 -> (MEMw_wrapper(pAddr, 2) := reg_val[31..16])
+ case 0b11 -> (MEMw_wrapper(pAddr, 1) := reg_val[31..24])
+ }
+ }
+ }
+
+union ast member regregimm16 SWR
+function clause decode(0b101110 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(SWR(base, rt, offset))
+function clause execute(SWR(base, rt, offset)) =
+ {
+ (* XXX length check not quite right, but conservative *)
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), StoreData, W);
+ let (pAddr) = (TLBTranslate(vAddr, StoreData)) in
+ {
+ wordAddr := pAddr[63..2] : 0b00;
+ reg_val := rGPR(rt);
+ switch (vAddr[1..0])
+ {
+ case 0b00 -> (MEMw_wrapper(wordAddr, 1) := reg_val[7..0])
+ case 0b01 -> (MEMw_wrapper(wordAddr, 2) := reg_val[15..0])
+ case 0b10 -> (MEMw_wrapper(wordAddr, 3) := reg_val[23..0])
+ case 0b11 -> (MEMw_wrapper(wordAddr, 4) := reg_val[31..0])
+ }
+ }
+ }
+
+(* Load double-word left *)
+union ast member regregimm16 LDL
+function clause decode(0b011010 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(LDL(base, rt, offset))
+function clause execute(LDL(base, rt, offset)) =
+ {
+ (* XXX length check not quite right, but conservative *)
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), LoadData, D);
+ let pAddr = (TLBTranslate(vAddr, StoreData)) in
+ {
+ mem_val := MEMr_wrapper (pAddr[63..3] : 0b000, 8); (* read double of interest *)
+ reg_val := rGPR(rt);
+ wGPR(rt) := switch(vAddr[2..0])
+ {
+ case 0b000 -> mem_val
+ case 0b001 -> mem_val[55..0] : reg_val[7..0]
+ case 0b010 -> mem_val[47..0] : reg_val[15..0]
+ case 0b011 -> mem_val[39..0] : reg_val[23..0]
+ case 0b100 -> mem_val[31..0] : reg_val[31..0]
+ case 0b101 -> mem_val[23..0] : reg_val[39..0]
+ case 0b110 -> mem_val[15..0] : reg_val[47..0]
+ case 0b111 -> mem_val[07..0] : reg_val[55..0]
+ };
+ }
+ }
+
+(* Load double-word right *)
+union ast member regregimm16 LDR
+function clause decode(0b011011 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(LDR(base, rt, offset))
+function clause execute(LDR(base, rt, offset)) =
+ {
+ (* XXX length check not quite right, but conservative *)
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), LoadData, D);
+ let pAddr = (TLBTranslate(vAddr, StoreData)) in
+ {
+ mem_val := MEMr_wrapper (pAddr[63..3] : 0b000, 8); (* read double of interest *)
+ reg_val := rGPR(rt);
+ wGPR(rt) := switch(vAddr[2..0])
+ {
+ case 0b000 -> reg_val[63..08] : mem_val[63..56]
+ case 0b001 -> reg_val[63..16] : mem_val[63..48]
+ case 0b010 -> reg_val[63..24] : mem_val[63..40]
+ case 0b011 -> reg_val[63..32] : mem_val[63..32]
+ case 0b100 -> reg_val[63..40] : mem_val[63..24]
+ case 0b101 -> reg_val[63..48] : mem_val[63..16]
+ case 0b110 -> reg_val[63..56] : mem_val[63..08]
+ case 0b111 -> mem_val
+ };
+ }
+ }
+
+(* SDL - Store double-word left *)
+union ast member regregimm16 SDL
+function clause decode(0b101100 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(SDL(base, rt, offset))
+function clause execute(SDL(base, rt, offset)) =
+ {
+ (* XXX length check not quite right, but conservative *)
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), StoreData, D);
+ let pAddr = (TLBTranslate(vAddr, StoreData)) in
+ {
+ reg_val := rGPR(rt);
+ switch (vAddr[2..0])
+ {
+ case 0b000 -> (MEMw_wrapper(pAddr, 8) := reg_val[63..00])
+ case 0b001 -> (MEMw_wrapper(pAddr, 7) := reg_val[63..08])
+ case 0b010 -> (MEMw_wrapper(pAddr, 6) := reg_val[63..16])
+ case 0b011 -> (MEMw_wrapper(pAddr, 5) := reg_val[63..24])
+ case 0b100 -> (MEMw_wrapper(pAddr, 4) := reg_val[63..32])
+ case 0b101 -> (MEMw_wrapper(pAddr, 3) := reg_val[63..40])
+ case 0b110 -> (MEMw_wrapper(pAddr, 2) := reg_val[63..48])
+ case 0b111 -> (MEMw_wrapper(pAddr, 1) := reg_val[63..56])
+ }
+ }
+ }
+
+
+(* SDR - Store double-word right *)
+union ast member regregimm16 SDR
+function clause decode(0b101101 : (regno) base : (regno) rt : (imm16) offset) =
+ Some(SDR(base, rt, offset))
+function clause execute(SDR(base, rt, offset)) =
+ {
+ (* XXX length check not quite right, but conservative *)
+ (bit[64]) vAddr := addrWrapper(EXTS(offset) + rGPR(base), StoreData, D);
+ let pAddr = (TLBTranslate(vAddr, StoreData)) in
+ {
+ reg_val := rGPR(rt);
+ wordAddr := pAddr[63..3] : 0b000;
+ switch (vAddr[2..0])
+ {
+ case 0b000 -> (MEMw_wrapper(wordAddr, 1) := reg_val[07..0])
+ case 0b001 -> (MEMw_wrapper(wordAddr, 2) := reg_val[15..0])
+ case 0b010 -> (MEMw_wrapper(wordAddr, 3) := reg_val[23..0])
+ case 0b011 -> (MEMw_wrapper(wordAddr, 4) := reg_val[31..0])
+ case 0b100 -> (MEMw_wrapper(wordAddr, 5) := reg_val[39..0])
+ case 0b101 -> (MEMw_wrapper(wordAddr, 6) := reg_val[47..0])
+ case 0b110 -> (MEMw_wrapper(wordAddr, 7) := reg_val[55..0])
+ case 0b111 -> (MEMw_wrapper(wordAddr, 8) := reg_val[63..0])
+ }
+ }
+ }
+
+(* CACHE - manipulate (non-existent) caches *)
+
+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)) =
+ checkCP0Access () (* pretty much a NOP because no caches *)
+
+(* PREF - prefetching into (non-existent) caches *)
+
+union ast member regregimm16 PREF
+function clause decode (0b110011 : (regno) base : (regno) op : (imm16) imm) =
+ Some(PREF(base, op, imm))
+function clause execute (PREF(base, op, imm)) =
+ () (* XXX NOP *)
+
+
+(* SYNC - Memory barrier *)
+union ast member unit SYNC
+function clause decode (0b000000 : 0b00000 : 0b00000 : 0b00000 : (regno) stype : 0b001111) =
+ Some(SYNC()) (* stype is currently ignored *)
+function clause execute(SYNC) =
+ MEM_sync()
+
+union ast member (regno, regno, bit[3], bool) MFC0
+function clause decode (0b010000 : 0b00000 : (regno) rt : (regno) rd : 0b00000000 : (bit[3]) sel) =
+ 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)) = {
+ checkCP0Access();
+ let (bit[64]) result = switch (rd, sel)
+ {
+ case (0b00000,0b000) -> let (bit[31]) idx = EXTZ(TLBIndex) in
+ (0x00000000 : [TLBProbe] : idx) (* 0, TLB Index *)
+ case (0b00001,0b000) -> EXTZ(TLBRandom) (* 1, TLB Random *)
+ case (0b00010,0b000) -> TLBEntryLo0 (* 2, TLB EntryLo0 *)
+ case (0b00011,0b000) -> TLBEntryLo1 (* 3, TLB EntryLo1 *)
+ case (0b00100,0b000) -> TLBContext (* 4, TLB Context *)
+ case (0b00101,0b000) -> EXTZ(TLBPageMask : 0x000) (* 5, TLB PageMask *)
+ case (0b00110,0b000) -> EXTZ(TLBWired) (* 6, TLB Wired *)
+ case (0b00111,0b000) -> EXTZ(CP0HWREna) (* 7, HWREna *)
+ case (0b01000,0b000) -> CP0BadVAddr (* 8, BadVAddr reg *)
+ case (0b01000,0b001) -> 0 (* 8, BadInstr reg XXX TODO *)
+ case (0b01001,0b000) -> EXTZ(CP0Count) (* 9, Count reg *)
+ case (0b01010,0b000) -> TLBEntryHi (* 10, TLB EntryHi *)
+ case (0b01011,0b000) -> EXTZ(CP0Compare) (* 11, Compare reg *)
+ case (0b01100,0b000) -> EXTZ(CP0Status) (* 12, Status reg *)
+ case (0b01101,0b000) -> EXTZ(CP0Cause) (* 13, Cause reg *)
+ case (0b01110,0b000) -> CP0EPC (* 14, EPC *)
+ case (0b01111,0b000) -> EXTZ(0x00000400) (* 15, sel 0: PrID processor ID *)
+ case (0b01111,0b110) -> 0 (* 15, sel 6: CHERI core ID *)
+ case (0b01111,0b111) -> 0 (* 15, sel 7: CHERI thread ID *)
+ case (0b10000,0b000) -> EXTZ(0b1 (* M *) (* 16, sel 0: Config0 *)
+ : 0b000000000000000 (* Impl *)
+ : 0b1 (* BE *)
+ : 0b10 (* AT *)
+ : 0b000 (* AR *)
+ : 0b001 (* MT standard TLB *)
+ : 0b0000 (* zero *)
+ : 0b000)
+ case (0b10000,0b001) -> EXTZ( (* 16, sel 1: Config1 *)
+ 0b1 (* M *)
+ : TLBIndexMax (* MMU size-1 *)
+ : 0b000 (* IS icache sets *)
+ : 0b000 (* IL icache lines *)
+ : 0b000 (* IA icache assoc. *)
+ : 0b000 (* DS dcache sets *)
+ : 0b000 (* DL dcache lines *)
+ : 0b000 (* DA dcache assoc. *)
+ : [have_cp2] (* C2 CP2 presence *)
+ : 0b0 (* MD MDMX implemented *)
+ : 0b0 (* PC performance counters *)
+ : 0b0 (* WR watch registers *)
+ : 0b0 (* CA 16e code compression *)
+ : 0b0 (* EP EJTAG *)
+ : 0b0) (* FP FPU present *)
+ case (0b10000,0b010) -> EXTZ( (* 16, sel 2: Config2 *)
+ 0b1 (* M *)
+ : 0b000 (* TU L3 control *)
+ : 0b0000 (* TS L3 sets *)
+ : 0b0000 (* TL L3 lines *)
+ : 0b0000 (* TA L3 assoc. *)
+ : 0b0000 (* SU L2 control *)
+ : 0b0000 (* SS L2 sets *)
+ : 0b0000 (* SL L2 lines *)
+ : 0b0000) (* SA L2 assoc. *)
+ case (0b10000,0b011) -> 0x0000000000002000 (* 16, sel 3: Config3 zero except for bit 13 == ulri *)
+ case (0b10000,0b101) -> 0x0000000000000000 (* 16, sel 5: Config5 beri specific -- no extended TLB *)
+ case (0b10001,0b000) -> CP0LLAddr (* 17, sel 0: LLAddr *)
+ case (0b10010,0b000) -> 0 (* 18, WatchLo *)
+ case (0b10011,0b000) -> 0 (* 19, WatchHi *)
+ case (0b10100,0b000) -> TLBXContext (* 20, XContext *)
+ case (0b11110,0b000) -> CP0ErrorEPC (* 30, ErrorEPC *)
+ case _ -> (SignalException(ResI))
+ } in
+ wGPR(rt) := if (double) then result else EXTS(result[31..0])
+}
+
+(* simulator halt instruction "MTC0 rt, r23" (cheri specific behaviour) *)
+union ast member unit HCF
+function clause decode (0b010000 : 0b00100 : (regno) rt : 0b10111 : 0b00000000000) =
+ Some(HCF())
+
+function clause decode (0b010000 : 0b00100 : (regno) rt : 0b11010 : 0b00000000000) =
+ Some(HCF())
+
+function clause execute (HCF) =
+ () (* halt instruction actually executed by interpreter framework *)
+
+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)) = {
+ checkCP0Access();
+ let reg_val = (rGPR(rt)) in
+ switch (rd, sel)
+ {
+ case (0b00000,0b000) -> TLBIndex := mask(reg_val) (* NB no write to TLBProbe *)
+ case (0b00001,0b000) -> () (* TLBRandom is read only *)
+ case (0b00010,0b000) -> TLBEntryLo0 := reg_val
+ case (0b00011,0b000) -> TLBEntryLo1 := reg_val
+ case (0b00100,0b000) -> (TLBContext.PTEBase) := (reg_val[63..23])
+ case (0b00100,0b010) -> CP0UserLocal := reg_val
+ case (0b00101,0b000) -> TLBPageMask := (reg_val[28..13])
+ case (0b00110,0b000) -> {
+ TLBWired := mask(reg_val);
+ TLBRandom := TLBIndexMax;
+ }
+ case (0b00111,0b000) -> CP0HWREna := (reg_val[31..29] : 0b0000000000000000000000000 : reg_val[3..0])
+ case (0b01000,0b000) -> () (* BadVAddr read only *)
+ case (0b01001,0b000) -> CP0Count := reg_val[31..0]
+ case (0b01010,0b000) -> {
+ (TLBEntryHi.R) := (reg_val[63..62]);
+ (TLBEntryHi.VPN2) := (reg_val[39..13]);
+ (TLBEntryHi.ASID) := (reg_val[7..0]);
+ }
+ case (0b01011,0b000) -> { (* 11, sel 0: Compare reg *)
+ CP0Compare := reg_val[31..0];
+ (CP0Cause[15]) := bitzero;
+ }
+ case (0b01100,0b000) -> { (* 12 Status *)
+ (CP0Status.CU) := reg_val[31..28];
+ (CP0Status.BEV) := reg_val[22];
+ (CP0Status.IM) := reg_val[15..8];
+ (CP0Status.KX) := reg_val[7];
+ (CP0Status.SX) := reg_val[6];
+ (CP0Status.UX) := reg_val[5];
+ (CP0Status.KSU) := reg_val[4..3];
+ (CP0Status.ERL) := reg_val[2];
+ (CP0Status.EXL) := reg_val[1];
+ (CP0Status.IE) := reg_val[0];
+ }
+ case (0b01101,0b000) -> { (* 13 Cause *)
+ CP0Cause.IV := reg_val[23]; (* TODO special interrupt vector not implemeneted *)
+ let ip = (bit[8]) (CP0Cause.IP) in
+ CP0Cause.IP := ((ip[7..2]) : (reg_val[9..8]));
+ }
+ case (0b01110,0b000) -> CP0EPC := reg_val (* 14, EPC *)
+ case (0b10000,0b000) -> () (* XXX ignore K0 cache config 16: Config0 *)
+ case (0b10100,0b000) -> (TLBXContext.PTEBase) := (reg_val[63..33])
+ case (0b11110,0b000) -> CP0ErrorEPC := reg_val (* 30, ErrorEPC *)
+ case _ -> (SignalException(ResI))
+ }
+}
+
+function unit TLBWriteEntry((TLBIndexT) idx) = {
+ pagemask := EXTZ(TLBPageMask); (* XXX EXTZ here forces register read in ocaml shallow embedding *)
+ switch(pagemask) {
+ case 0x0000 -> ()
+ case 0x0003 -> ()
+ case 0x000f -> ()
+ case 0x003f -> ()
+ case 0x00ff -> ()
+ case 0x03ff -> ()
+ case 0x0fff -> ()
+ case 0x3fff -> ()
+ case 0xffff -> ()
+ case _ -> (SignalException(MCheck))
+ };
+ ((TLBEntries[idx]).pagemask) := pagemask;
+ ((TLBEntries[idx]).r ) := TLBEntryHi.R;
+ ((TLBEntries[idx]).vpn2 ) := TLBEntryHi.VPN2;
+ ((TLBEntries[idx]).asid ) := TLBEntryHi.ASID;
+ ((TLBEntries[idx]).g ) := ((TLBEntryLo0.G) & (TLBEntryLo1.G));
+ ((TLBEntries[idx]).valid ) := bitone;
+ ((TLBEntries[idx]).caps0 ) := TLBEntryLo0.CapS;
+ ((TLBEntries[idx]).capl0 ) := TLBEntryLo0.CapL;
+ ((TLBEntries[idx]).pfn0 ) := TLBEntryLo0.PFN;
+ ((TLBEntries[idx]).c0 ) := TLBEntryLo0.C;
+ ((TLBEntries[idx]).d0 ) := TLBEntryLo0.D;
+ ((TLBEntries[idx]).v0 ) := TLBEntryLo0.V;
+ ((TLBEntries[idx]).caps1 ) := TLBEntryLo1.CapS;
+ ((TLBEntries[idx]).capl1 ) := TLBEntryLo1.CapL;
+ ((TLBEntries[idx]).pfn1 ) := TLBEntryLo1.PFN;
+ ((TLBEntries[idx]).c1 ) := TLBEntryLo1.C;
+ ((TLBEntries[idx]).d1 ) := TLBEntryLo1.D;
+ ((TLBEntries[idx]).v1 ) := TLBEntryLo1.V;
+}
+
+union ast member TLBWI
+function clause decode (0b010000 : 0b10000000000000000000 : 0b000010) = Some(TLBWI)
+function clause execute (TLBWI) = {
+ checkCP0Access();
+ TLBWriteEntry(TLBIndex);
+}
+
+union ast member TLBWR
+function clause decode (0b010000 : 0b10000000000000000000 : 0b000110) = Some(TLBWR)
+function clause execute (TLBWR) = {
+ checkCP0Access();
+ TLBWriteEntry(TLBRandom);
+}
+
+union ast member TLBR
+function clause decode (0b010000 : 0b10000000000000000000 : 0b000001) = Some(TLBR)
+function clause execute (TLBR) = {
+ checkCP0Access();
+ let entry = TLBEntries[TLBIndex] in {
+ TLBPageMask := entry.pagemask;
+ TLBEntryHi.R := entry.r;
+ TLBEntryHi.VPN2 := entry.vpn2;
+ TLBEntryHi.ASID := entry.asid;
+ TLBEntryLo0.CapS:= entry.caps0;
+ TLBEntryLo0.CapL:= entry.capl0;
+ TLBEntryLo0.PFN := entry.pfn0;
+ TLBEntryLo0.C := entry.c0;
+ TLBEntryLo0.D := entry.d0;
+ TLBEntryLo0.V := entry.v0;
+ TLBEntryLo0.G := entry.g;
+ TLBEntryLo1.CapS:= entry.caps1;
+ TLBEntryLo1.CapL:= entry.capl1;
+ TLBEntryLo1.PFN := entry.pfn1;
+ TLBEntryLo1.C := entry.c1;
+ TLBEntryLo1.D := entry.d1;
+ TLBEntryLo1.V := entry.v1;
+ TLBEntryLo1.G := entry.g;
+ }
+}
+
+union ast member TLBP
+function clause decode (0b010000 : 0b10000000000000000000 : 0b001000) = Some(TLBP)
+function clause execute ((TLBP)) = {
+ checkCP0Access();
+ let result = tlbSearch(TLBEntryHi) in
+ switch(result) {
+ case (Some(idx)) -> {
+ TLBProbe := [bitzero];
+ TLBIndex := idx;
+ }
+ case None -> {
+ TLBProbe := [bitone];
+ TLBIndex := 0;
+ }
+ }
+}
+
+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
+ (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 _ -> (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
+ {
+ nextPC := CP0ErrorEPC;
+ CP0Status.ERL := 0;
+ }
+ else
+ {
+ nextPC := CP0EPC;
+ CP0Status.EXL := 0;
+ }
+ }
diff --git a/mips_new_tc/mips_prelude.sail b/mips_new_tc/mips_prelude.sail
new file mode 100644
index 00000000..dca78b12
--- /dev/null
+++ b/mips_new_tc/mips_prelude.sail
@@ -0,0 +1,610 @@
+(*========================================================================*)
+(* *)
+(* Copyright (c) 2015-2017 Robert M. Norton *)
+(* Copyright (c) 2015-2017 Kathyrn Gray *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+(* mips_prelude.sail: declarations of mips registers, and functions common
+ to mips instructions (e.g. address translation) *)
+
+(* bit vectors have indices decreasing from left i.e. msb is highest index *)
+default Order dec
+
+register (bit[64]) PC
+register (bit[64]) nextPC
+
+(* CP0 Registers *)
+
+typedef CauseReg = register bits [ 31 : 0 ] {
+ 31 : BD; (* branch delay *)
+ (*30 : Z0;*)
+ 29 .. 28 : CE; (* for coprocessor enable exception *)
+ (*27 .. 24 : Z1;*)
+ 23 : IV; (* special interrupt vector not supported *)
+ 22 : WP; (* watchpoint exception occurred *)
+ (*21 .. 16 : Z2; *)
+ 15 .. 8 : IP; (* interrupt pending bits *)
+ (*7 : Z3;*)
+ 6 .. 2 : ExcCode; (* code of last exception *)
+ (*1 .. 0 : Z4;*)
+}
+
+typedef TLBEntryLoReg = register bits [63 : 0] {
+ 63 : CapS;
+ 62 : CapL;
+ 29 .. 6 : PFN;
+ 5 .. 3 : C;
+ 2 : D;
+ 1 : V;
+ 0 : G;
+}
+
+typedef TLBEntryHiReg = register bits [63 : 0] {
+ 63 .. 62 : R;
+ 39 .. 13 : VPN2;
+ 7 .. 0 : ASID;
+}
+
+typedef ContextReg = register bits [63 : 0] {
+ 63 .. 23 : PTEBase;
+ 22 .. 4 : BadVPN2;
+ (*3 .. 0 : ZR;*)
+}
+
+typedef XContextReg = register bits [63 : 0] {
+ 63 .. 33: PTEBase;
+ 32 .. 31: R;
+ 30 .. 4: BadVPN2;
+}
+
+let ([:64:]) TLBNumEntries = 64
+typedef TLBIndexT = (bit[6])
+let (TLBIndexT) TLBIndexMax = 0b111111
+
+let MAX_U64 = unsigned(0xffffffffffffffff)
+let MAX_VA = unsigned(0xffffffffff)
+let MAX_PA = unsigned(0xfffffffff)
+
+typedef TLBEntry = register bits [116 : 0] {
+ 116 .. 101: pagemask;
+ 100 .. 99 : r ;
+ 98 .. 72 : vpn2 ;
+ 71 .. 64 : asid ;
+ 63 : g ;
+ 62 : valid ;
+ 61 : caps1 ;
+ 60 : capl1 ;
+ 59 .. 36 : pfn1 ;
+ 35 .. 33 : c1 ;
+ 32 : d1 ;
+ 31 : v1 ;
+ 30 : caps0 ;
+ 29 : capl0 ;
+ 28 .. 5 : pfn0 ;
+ 4 .. 2 : c0 ;
+ 1 : d0 ;
+ 0 : v0 ;
+}
+
+register (bit[1]) TLBProbe
+register (TLBIndexT) TLBIndex
+register (TLBIndexT) TLBRandom
+register (TLBEntryLoReg) TLBEntryLo0
+register (TLBEntryLoReg) TLBEntryLo1
+register (ContextReg) TLBContext
+register (bit[16]) TLBPageMask
+register (TLBIndexT) TLBWired
+register (TLBEntryHiReg) TLBEntryHi
+register (XContextReg) TLBXContext
+
+register (TLBEntry) TLBEntry00
+register (TLBEntry) TLBEntry01
+register (TLBEntry) TLBEntry02
+register (TLBEntry) TLBEntry03
+register (TLBEntry) TLBEntry04
+register (TLBEntry) TLBEntry05
+register (TLBEntry) TLBEntry06
+register (TLBEntry) TLBEntry07
+register (TLBEntry) TLBEntry08
+register (TLBEntry) TLBEntry09
+register (TLBEntry) TLBEntry10
+register (TLBEntry) TLBEntry11
+register (TLBEntry) TLBEntry12
+register (TLBEntry) TLBEntry13
+register (TLBEntry) TLBEntry14
+register (TLBEntry) TLBEntry15
+register (TLBEntry) TLBEntry16
+register (TLBEntry) TLBEntry17
+register (TLBEntry) TLBEntry18
+register (TLBEntry) TLBEntry19
+register (TLBEntry) TLBEntry20
+register (TLBEntry) TLBEntry21
+register (TLBEntry) TLBEntry22
+register (TLBEntry) TLBEntry23
+register (TLBEntry) TLBEntry24
+register (TLBEntry) TLBEntry25
+register (TLBEntry) TLBEntry26
+register (TLBEntry) TLBEntry27
+register (TLBEntry) TLBEntry28
+register (TLBEntry) TLBEntry29
+register (TLBEntry) TLBEntry30
+register (TLBEntry) TLBEntry31
+register (TLBEntry) TLBEntry32
+register (TLBEntry) TLBEntry33
+register (TLBEntry) TLBEntry34
+register (TLBEntry) TLBEntry35
+register (TLBEntry) TLBEntry36
+register (TLBEntry) TLBEntry37
+register (TLBEntry) TLBEntry38
+register (TLBEntry) TLBEntry39
+register (TLBEntry) TLBEntry40
+register (TLBEntry) TLBEntry41
+register (TLBEntry) TLBEntry42
+register (TLBEntry) TLBEntry43
+register (TLBEntry) TLBEntry44
+register (TLBEntry) TLBEntry45
+register (TLBEntry) TLBEntry46
+register (TLBEntry) TLBEntry47
+register (TLBEntry) TLBEntry48
+register (TLBEntry) TLBEntry49
+register (TLBEntry) TLBEntry50
+register (TLBEntry) TLBEntry51
+register (TLBEntry) TLBEntry52
+register (TLBEntry) TLBEntry53
+register (TLBEntry) TLBEntry54
+register (TLBEntry) TLBEntry55
+register (TLBEntry) TLBEntry56
+register (TLBEntry) TLBEntry57
+register (TLBEntry) TLBEntry58
+register (TLBEntry) TLBEntry59
+register (TLBEntry) TLBEntry60
+register (TLBEntry) TLBEntry61
+register (TLBEntry) TLBEntry62
+register (TLBEntry) TLBEntry63
+
+let (vector <0, 64, inc, (TLBEntry)>) TLBEntries = [
+TLBEntry00,
+TLBEntry01,
+TLBEntry02,
+TLBEntry03,
+TLBEntry04,
+TLBEntry05,
+TLBEntry06,
+TLBEntry07,
+TLBEntry08,
+TLBEntry09,
+TLBEntry10,
+TLBEntry11,
+TLBEntry12,
+TLBEntry13,
+TLBEntry14,
+TLBEntry15,
+TLBEntry16,
+TLBEntry17,
+TLBEntry18,
+TLBEntry19,
+TLBEntry20,
+TLBEntry21,
+TLBEntry22,
+TLBEntry23,
+TLBEntry24,
+TLBEntry25,
+TLBEntry26,
+TLBEntry27,
+TLBEntry28,
+TLBEntry29,
+TLBEntry30,
+TLBEntry31,
+TLBEntry32,
+TLBEntry33,
+TLBEntry34,
+TLBEntry35,
+TLBEntry36,
+TLBEntry37,
+TLBEntry38,
+TLBEntry39,
+TLBEntry40,
+TLBEntry41,
+TLBEntry42,
+TLBEntry43,
+TLBEntry44,
+TLBEntry45,
+TLBEntry46,
+TLBEntry47,
+TLBEntry48,
+TLBEntry49,
+TLBEntry50,
+TLBEntry51,
+TLBEntry52,
+TLBEntry53,
+TLBEntry54,
+TLBEntry55,
+TLBEntry56,
+TLBEntry57,
+TLBEntry58,
+TLBEntry59,
+TLBEntry60,
+TLBEntry61,
+TLBEntry62,
+TLBEntry63
+]
+
+register (bit[32]) CP0Compare
+register (CauseReg) CP0Cause
+register (bit[64]) CP0EPC
+register (bit[64]) CP0ErrorEPC
+register (bit[1]) CP0LLBit
+register (bit[64]) CP0LLAddr
+register (bit[64]) CP0BadVAddr
+register (bit[32]) CP0Count
+register (bit[32]) CP0HWREna
+register (bit[64]) CP0UserLocal
+
+typedef StatusReg = register bits [31:0] {
+ 31 .. 28 : CU; (* co-processor enable bits *)
+ (* RP/FR/RE/MX/PX not implemented *)
+ 22 : BEV; (* use boot exception vectors (initialised to one) *)
+ (* TS/SR/NMI not implemented *)
+ 15 .. 8 : IM; (* Interrupt mask *)
+ 7 : KX; (* kernel 64-bit enable *)
+ 6 : SX; (* supervisor 64-bit enable *)
+ 5 : UX; (* user 64-bit enable *)
+ 4 .. 3 : KSU; (* Processor mode *)
+ 2 : ERL; (* error level (should be initialised to one, but BERI is different) *)
+ 1 : EXL; (* exception level *)
+ 0 : IE; (* interrupt enable *)
+}
+register (StatusReg) CP0Status
+
+(* Implementation registers -- not ISA defined *)
+register (bit[1]) branchPending (* Set by branch instructions to implement branch delay *)
+register (bit[1]) inBranchDelay (* Needs to be set by outside world when in branch delay slot *)
+register (bit[64]) delayedPC (* Set by branch instructions to implement branch delay *)
+
+(* General purpose registers *)
+
+register (bit[64]) GPR00 (* should never be read or written *)
+register (bit[64]) GPR01
+register (bit[64]) GPR02
+register (bit[64]) GPR03
+register (bit[64]) GPR04
+register (bit[64]) GPR05
+register (bit[64]) GPR06
+register (bit[64]) GPR07
+register (bit[64]) GPR08
+register (bit[64]) GPR09
+register (bit[64]) GPR10
+register (bit[64]) GPR11
+register (bit[64]) GPR12
+register (bit[64]) GPR13
+register (bit[64]) GPR14
+register (bit[64]) GPR15
+register (bit[64]) GPR16
+register (bit[64]) GPR17
+register (bit[64]) GPR18
+register (bit[64]) GPR19
+register (bit[64]) GPR20
+register (bit[64]) GPR21
+register (bit[64]) GPR22
+register (bit[64]) GPR23
+register (bit[64]) GPR24
+register (bit[64]) GPR25
+register (bit[64]) GPR26
+register (bit[64]) GPR27
+register (bit[64]) GPR28
+register (bit[64]) GPR29
+register (bit[64]) GPR30
+register (bit[64]) GPR31
+
+(* Special registers For MUL/DIV *)
+register (bit[64]) HI
+register (bit[64]) LO
+
+let (vector <0, 32, inc, (register<(bit[64])>) >) GPR =
+ [ GPR00, GPR01, GPR02, GPR03, GPR04, GPR05, GPR06, GPR07, GPR08, GPR09, GPR10,
+ GPR11, GPR12, GPR13, GPR14, GPR15, GPR16, GPR17, GPR18, GPR19, GPR20,
+ GPR21, GPR22, GPR23, GPR24, GPR25, GPR26, GPR27, GPR28, GPR29, GPR30, GPR31
+ ]
+
+(* JTAG Uart registers *)
+
+register (bit[8]) UART_WDATA
+register (bit[1]) UART_WRITTEN
+register (bit[8]) UART_RDATA
+register (bit[1]) UART_RVALID
+
+(* Check whether a given 64-bit vector is a properly sign extended 32-bit word *)
+val bit[64] -> bool effect pure NotWordVal
+function bool NotWordVal (word) =
+ (word[31] ^^ 32) != word[63..32]
+
+(* Read numbered GP reg. (r0 is always zero) *)
+val bit[5] -> bit[64] effect {rreg} rGPR
+function bit[64] rGPR idx = {
+ if idx == 0 then 0 else GPR[idx]
+}
+
+(* Write numbered GP reg. (writes to r0 ignored) *)
+val (bit[5], bit[64]) -> unit effect {wreg} wGPR
+function unit wGPR (idx, v) = {
+ if idx == 0 then () else GPR[idx] := v
+}
+
+val extern forall Nat 'n. ( bit[64] , [|'n|] ) -> (bit[8 * 'n]) effect { rmem } MEMr
+val extern forall Nat 'n. ( bit[64] , [|'n|] ) -> (bit[8 * 'n]) effect { rmem } MEMr_reserve
+val extern unit -> unit effect { barr } MEM_sync
+
+val extern forall Nat 'n. ( bit[64] , [|'n|]) -> unit effect { eamem } MEMea
+val extern forall Nat 'n. ( bit[64] , [|'n|]) -> unit effect { eamem } MEMea_conditional
+val extern forall Nat 'n. ( bit[64] , [|'n|] , bit[8*'n]) -> unit effect { wmv } MEMval
+val extern forall Nat 'n. ( bit[64] , [|'n|] , bit[8*'n]) -> bool effect { wmv } MEMval_conditional
+
+typedef Exception = enumerate
+{
+ Int; TLBMod; TLBL; TLBS; AdEL; AdES; Sys; Bp; ResI; CpU; Ov; Tr; C2E; C2Trap;
+ XTLBRefillL; XTLBRefillS; XTLBInvL; XTLBInvS; MCheck
+}
+
+(* Return the ISA defined code for an exception condition *)
+function (bit[5]) ExceptionCode ((Exception) ex) =
+ switch (ex)
+ {
+ case Int -> mask(0x00) (* Interrupt *)
+ case TLBMod -> mask(0x01) (* TLB modification exception *)
+ case TLBL -> mask(0x02) (* TLB exception (load or fetch) *)
+ case TLBS -> mask(0x03) (* TLB exception (store) *)
+ case AdEL -> mask(0x04) (* Address error (load or fetch) *)
+ case AdES -> mask(0x05) (* Address error (store) *)
+ case Sys -> mask(0x08) (* Syscall *)
+ case Bp -> mask(0x09) (* Breakpoint *)
+ case ResI -> mask(0x0a) (* Reserved instruction *)
+ case CpU -> mask(0x0b) (* Coprocessor Unusable *)
+ case Ov -> mask(0x0c) (* Arithmetic overflow *)
+ case Tr -> mask(0x0d) (* Trap *)
+ case C2E -> mask(0x12) (* C2E coprocessor 2 exception *)
+ case C2Trap -> mask(0x12) (* C2Trap maps to same exception code, different vector *)
+ case XTLBRefillL -> mask(0x02)
+ case XTLBRefillS -> mask(0x03)
+ case XTLBInvL -> mask(0x02)
+ case XTLBInvS -> mask(0x03)
+ case MCheck -> mask(0x18)
+ }
+
+
+
+function forall Type 'o. 'o SignalExceptionMIPS ((Exception) ex, (bit[64]) kccBase) =
+ {
+ (* Only update EPC and BD if not already in EXL mode *)
+ if (~ (CP0Status.EXL)) then
+ {
+ if (inBranchDelay[0]) then
+ {
+ CP0EPC := PC - 4;
+ CP0Cause.BD := 1;
+ }
+ else
+ {
+ CP0EPC := PC;
+ CP0Cause.BD := 0;
+ }
+ };
+
+ (* choose an exception vector to branch to. Some are not supported
+ e.g. Reset *)
+ vectorOffset :=
+ if (CP0Status.EXL) then
+ 0x180 (* Always use common vector if in exception mode already *)
+ else if ((ex == XTLBRefillL) | (ex == XTLBRefillS)) then
+ 0x080
+ else if (ex == C2Trap) then
+ 0x280 (* Special vector for CHERI traps *)
+ else
+ 0x180; (* Common vector *)
+ (bit[64]) vectorBase := if CP0Status.BEV then
+ 0xFFFFFFFFBFC00200
+ else
+ 0xFFFFFFFF80000000;
+ (* On CHERI we have to subtract KCC.base so that we end up at the
+ right absolute vector address after indirecting via new PCC *)
+ nextPC := ((bit[64])(vectorBase + (bit[64]) (EXTS(vectorOffset)))) - kccBase;
+ CP0Cause.ExcCode := ExceptionCode(ex);
+ CP0Status.EXL := 1;
+ exit ();
+ }
+
+val forall Type 'o . Exception -> 'o effect {escape, rreg, wreg} SignalException
+
+function forall Type 'o. 'o SignalExceptionBadAddr((Exception) ex, (bit[64]) badAddr) =
+ {
+ CP0BadVAddr := badAddr;
+ SignalException(ex);
+ }
+
+function forall Type 'o. 'o SignalExceptionTLB((Exception) ex, (bit[64]) badAddr) = {
+ CP0BadVAddr := badAddr;
+ (TLBContext.BadVPN2) := (badAddr[31..13]);
+ (TLBXContext.BadVPN2):= (badAddr[39..13]);
+ (TLBXContext.R) := (badAddr[63..62]);
+ (TLBEntryHi.R) := (badAddr[63..62]);
+ (TLBEntryHi.VPN2) := (badAddr[39..13]);
+ SignalException(ex);
+}
+
+typedef MemAccessType = enumerate {Instruction; LoadData; StoreData}
+typedef AccessLevel = enumerate {User; Supervisor; Kernel}
+
+function AccessLevel getAccessLevel() =
+ if ((CP0Status.EXL) | (CP0Status.ERL)) then
+ Kernel
+ else switch (bit[2]) (CP0Status.KSU)
+ {
+ case 0b00 -> Kernel
+ case 0b01 -> Supervisor
+ case 0b10 -> User
+ case _ -> User (* behaviour undefined, assume user *)
+ }
+
+function unit checkCP0Access () =
+ {
+ let accessLevel = getAccessLevel() in
+ if ((accessLevel != Kernel) & (~(CP0Status[28] (*CU0*)))) then
+ {
+ (CP0Cause.CE) := 0b00;
+ SignalException(CpU);
+ }
+ }
+
+function unit incrementCP0Count() = {
+ TLBRandom := (if (TLBRandom == TLBWired)
+ then (TLBIndexMax) else (TLBRandom - 1));
+
+ CP0Count := (CP0Count + 1);
+ if (CP0Count == CP0Compare) then {
+ (CP0Cause[15]) := bitone; (* XXX indexing IP field here doesn't seem to work *)
+ };
+
+ let ims = (bit[8]) (CP0Status.IM) in
+ let ips = (bit[8]) (CP0Cause.IP) in
+ let ie = CP0Status.IE in
+ let exl = CP0Status.EXL in
+ let erl = CP0Status.ERL in
+ if ((~(exl)) & (~(erl)) & ie & ((ips & ims) != 0x00)) then
+ SignalException(Int);
+}
+
+typedef regno = bit[5] (* a register number *)
+typedef imm16 = bit[16] (* 16-bit immediate *)
+(* a commonly used instruction format with three register operands *)
+typedef regregreg = (regno, regno, regno)
+(* a commonly used instruction format with two register operands and 16-bit immediate *)
+typedef regregimm16 = (regno, regno, imm16)
+
+typedef decode_failure = enumerate {
+ no_matching_pattern;
+ unsupported_instruction;
+ illegal_instruction;
+ internal_error
+}
+
+(* Used by branch and trap instructions *)
+typedef Comparison = enumerate {
+ EQ; (* equal *)
+ NE; (* not equal *)
+ GE; (* signed greater than or equal *)
+ GEU;(* unsigned greater than or equal *)
+ GT; (* signed strictly greater than *)
+ LE; (* signed less than or equal *)
+ LT; (* signed strictly less than *)
+ LTU;(* unsigned less than or qual *)
+}
+function bool compare ((Comparison)cmp, (bit[64]) valA, (bit[64]) valB) =
+ (* sail comparisons are signed so extend to 65 bits for unsigned comparisons *)
+ let valA65 = (0b0 : valA) in
+ let valB65 = (0b0 : valB) in
+ switch(cmp) {
+ case EQ -> valA == valB
+ case NE -> valA != valB
+ case GE -> valA >= valB
+ case GEU -> valA65 >= valB65
+ case GT -> valA > valB
+ case LE -> valA <= valB
+ case LT -> valA < valB
+ case LTU -> valA65 < valB65
+ }
+typedef WordType = enumerate { B; H; W; D}
+
+function [|1:8|] wordWidthBytes((WordType) w) =
+ switch(w) {
+ case B -> 1
+ case H -> 2
+ case W -> 4
+ case D -> 8
+ }
+
+(* This function checks that memory accesses are naturally aligned
+ -- it is disabled in favour of BERI specific behaviour below.
+function bool isAddressAligned(addr, (WordType) wordType) =
+ switch (wordType) {
+ case B -> true
+ case H -> (addr[0] == 0)
+ case W -> (addr[1..0] == 0b00)
+ case D -> (addr[2..0] == 0b000)
+ }
+*)
+
+(* BERI relaxes the natural alignment requirement for loads and stores
+ but still throws an exception if an access spans a cache line
+ boundary. Here we assume this is 32 bytes so that we don't have to
+ worry about clearing multiple tags when an access spans more than
+ one capability. Capability load/stores are still naturally
+ aligned. Provided this is a factor of smallest supported page size
+ (4k) we don't need to worry about accesses spanning page boundaries
+ either.
+*)
+let alignment_width = 16
+function (bool) isAddressAligned ((bit[64]) addr, (WordType) wordType) =
+ let a = unsigned(addr) in
+ ((a quot alignment_width) == (a + wordWidthBytes(wordType) - 1) quot alignment_width)
+
+val forall Nat 'W, 'W >= 1. ([:'W:], bit[8 * 'W]) -> bit[8 * 'W] effect pure reverse_endianness'
+
+function rec forall Nat 'W, 'W >= 1. bit[8 * 'W] reverse_endianness' (w, value) =
+{
+ ([:8 * 'W:]) width := length(value);
+ if width <= 8
+ then value
+ else value[7..0] : reverse_endianness'(w - 1, value[(width - 1) .. 8])
+}
+
+val forall Nat 'W, 'W >= 1. bit[8 * 'W] -> bit[8 * 'W] effect pure reverse_endianness
+
+function rec forall Nat 'W, 'W >= 1. bit[8 * 'W] reverse_endianness ((bit[8 * 'W]) value) =
+{
+ reverse_endianness'(sizeof 'W, value)
+}
+
+function forall Nat 'n, 1 <= 'n, 'n <= 8. (bit[8 * 'n]) effect { rmem } MEMr_wrapper ((bit[64]) addr, ([:'n:]) size) =
+ if (addr == 0x000000007f000000) then
+ {
+ let rvalid = (bit[1]) UART_RVALID in
+ let rdata = (bit[8 * 'n]) (mask(0x00000000 : UART_RDATA : rvalid : 0b0000000 : 0x0000)) in
+ {
+ UART_RVALID := [bitzero];
+ rdata
+ }
+ }
+ else if (addr == 0x000000007f000004) then
+ mask(0x000000000004ffff) (* Always plenty of write space available and jtag activity *)
+ else
+ reverse_endianness(MEMr(addr, size)) (* MEMr assumes little endian *)
+
+function forall Nat 'n, 'n >= 1. (bit[8 * 'n]) effect { rmem } MEMr_reserve_wrapper ((bit[64]) addr , ([:'n:]) size) =
+ reverse_endianness(MEMr_reserve(addr, size))
diff --git a/mips_new_tc/mips_regfp.sail b/mips_new_tc/mips_regfp.sail
new file mode 100644
index 00000000..36750583
--- /dev/null
+++ b/mips_new_tc/mips_regfp.sail
@@ -0,0 +1,455 @@
+(*========================================================================*)
+(* *)
+(* Copyright (c) 2015-2017 Robert M. Norton *)
+(* Copyright (c) 2015-2017 Kathyrn Gray *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+let (vector <0, 32, inc, string >) GPRs =
+ [ "GPR00", "GPR01", "GPR02", "GPR03", "GPR04", "GPR05", "GPR06", "GPR07", "GPR08", "GPR09", "GPR10",
+ "GPR11", "GPR12", "GPR13", "GPR14", "GPR15", "GPR16", "GPR17", "GPR18", "GPR19", "GPR20",
+ "GPR21", "GPR22", "GPR23", "GPR24", "GPR25", "GPR26", "GPR27", "GPR28", "GPR29", "GPR30", "GPR31"
+ ]
+
+let CIA_fp = RFull("CIA")
+let NIA_fp = RFull("NIA")
+
+function (regfps,regfps,regfps,niafps,diafp,instruction_kind) initial_analysis (instr) = {
+ iR := [|| ||];
+ oR := [|| ||];
+ aR := [|| ||];
+ ik := IK_simple;
+ Nias := [|| ||];
+ Dia := DIAFP_none;
+
+ switch instr {
+ case (DADDIU (rs, rt, imm)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (DADDU (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DADDI (rs, rt, imm)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (DADD (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (ADD(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (ADDI(rs, rt, imm)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (ADDU(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (ADDIU(rs, rt, imm)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (DSUBU (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DSUB (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SUB(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SUBU(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (AND (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (ANDI (rs, rt, imm)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (OR (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (ORI (rs, rt, imm)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (NOR (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (XOR (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (XORI (rs, rt, imm)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (LUI (rt, imm)) -> {
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (DSLL (rt, rd, sa)) -> {
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DSLL32 (rt, rd, sa)) -> {
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DSLLV (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DSRA (rt, rd, sa)) -> {
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DSRA32 (rt, rd, sa)) -> {
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DSRAV (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DSRL (rt, rd, sa)) -> {
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DSRL32 (rt, rd, sa)) -> {
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (DSRLV (rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SLL(rt, rd, sa)) -> {
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SLLV(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SRA(rt, rd, sa)) -> {
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SRAV(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SRL(rt, rd, sa)) -> {
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SRLV(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SLT(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SLTI(rs, rt, imm)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (SLTU(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (SLTIU(rs, rt, imm)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (MOVN(rs, rt, rd)) -> {
+ (* XXX don't always write rd *)
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (MOVZ(rs, rt, rd)) -> {
+ (* XXX don't always write rd *)
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (MFHI(rd)) -> {
+ iR := RFull("HI") :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (MFLO(rd)) -> {
+ iR := RFull("LO") :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (MTHI(rs)) -> {
+ oR := RFull("HI") :: oR;
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ }
+ case (MTLO(rs)) -> {
+ oR := RFull("LO") :: oR;
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ }
+ case (MUL(rs, rt, rd)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ if rd == 0 then () else oR := RFull(GPRs[rd]) :: oR;
+ }
+ case (MULT(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (MULTU(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (DMULT(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (DMULTU(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (MADD(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ iR := RFull("HI") :: RFull ("LO") :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (MADDU(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ iR := RFull("HI") :: RFull ("LO") :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (MSUB(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ iR := RFull("HI") :: RFull ("LO") :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (MSUBU(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ iR := RFull("HI") :: RFull ("LO") :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (DIV(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (DIVU(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (DDIV(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (DDIVU(rs, rt)) -> {
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ oR := RFull("HI") :: RFull ("LO") :: oR;
+ }
+ case (J(offset)) -> {
+ (* XXX actually unconditional jump *)
+ (*ik := IK_cond_branch;*)
+ Dia := DIAFP_concrete((PC + 4)[63..28] : offset : 0b00);
+ }
+ case (JAL(offset)) -> {
+ (* XXX actually unconditional jump *)
+ (*ik := IK_cond_branch;*)
+ oR := RFull("GPR31") :: oR;
+ Dia := DIAFP_concrete((PC + 4)[63..28] : offset : 0b00);
+ }
+ case (JR(rs)) -> {
+ (* XXX actually unconditional jump *)
+ (*ik := IK_cond_branch;*)
+ iR := RFull(GPRs[rs]) :: iR;
+ Dia := DIAFP_reg(RFull(GPRs[rs]));
+ }
+ case (JALR(rs, rd)) -> {
+ (* XXX actually unconditional jump *)
+ (*ik := IK_cond_branch;*)
+ iR := RFull(GPRs[rs]) :: iR;
+ oR := RFull("GPR31") :: oR;
+ Dia := DIAFP_reg(RFull(GPRs[rs]));
+ }
+ case (BEQ(rs, rd, imm, ne, likely)) -> {
+ ik := IK_cond_branch;
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if rd == 0 then () else iR := RFull(GPRs[rd]) :: iR;
+ let (bit[64]) offset = (EXTS(imm : 0b00) + 4) in
+ Dia := DIAFP_concrete (PC + offset);
+ }
+ case (BCMPZ(rs, imm, cmp, link, likely)) -> {
+ ik := IK_cond_branch;
+ if rs == 0 then () else iR := RFull(GPRs[rs]) :: iR;
+ if link then
+ oR := RFull("GPR31") :: oR;
+ let (bit[64]) offset = (EXTS(imm : 0b00) + 4) in
+ Dia := DIAFP_concrete (PC + offset);
+ }
+ case (SYSCALL_THREAD_START) -> ()
+(*
+
+ case (SYSCALL) =
+ case (BREAK) =
+ case (WAIT) = {
+ case (TRAPREG(rs, rt, cmp)) =
+ case (TRAPIMM(rs, imm, cmp)) =
+*)
+ case (Load(width, signed, linked, base, rt, offset)) -> {
+ ik := IK_mem_read (if linked then Read_reserve else Read_plain);
+ if linked then oR := RFull("CP0LLBit")::RFull("CP0LLAddr")::oR else ();
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (Store(width, conditional, base, rt, offset)) -> {
+ ik := IK_mem_write(if conditional then Write_conditional else Write_plain);
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if conditional then iR := RFull("CP0LLBit")::iR else ();
+ if (conditional & (rt != 0)) then oR := RFull(GPRs[rt])::oR else ();
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ }
+ case (LWL(base, rt, offset)) -> {
+ ik := IK_mem_read(Read_plain);
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (LWR(base, rt, offset)) -> {
+ ik := IK_mem_read(Read_plain);
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (SWL(base, rt, offset)) -> {
+ ik := IK_mem_write(Write_plain);
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ }
+ case (SWR(base, rt, offset)) -> {
+ ik := IK_mem_write(Write_plain);
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ }
+ case (LDL(base, rt, offset)) -> {
+ ik := IK_mem_read(Read_plain);
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (LDR(base, rt, offset)) -> {
+ ik := IK_mem_read(Read_plain);
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if rt == 0 then () else oR := RFull(GPRs[rt]) :: oR;
+ }
+ case (SDL(base, rt, offset)) -> {
+ ik := IK_mem_write(Write_plain);
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ }
+ case (SDR(base, rt, offset)) -> {
+ ik := IK_mem_write(Write_plain);
+ if base == 0 then () else aR := RFull(GPRs[base]) :: aR;
+ iR := aR;
+ if rt == 0 then () else iR := RFull(GPRs[rt]) :: iR;
+ }
+(*
+ case (CACHE(base, op, imm)) =
+ case (PREF(base, op, imm)) =
+*)
+ case (SYNC) -> {
+ iK := IK_barrier(Barrier_MIPS_SYNC);
+ }
+(*
+ case (MFC0(rt, rd, sel, double))
+ case (HCF)
+ case (MTC0(rt, rd, sel, double))
+ case (TLBWI)
+ case (TLBWR)
+ case (TLBR)
+ case ((TLBP))
+ case (RDHWR(rt, rd))
+ case (ERET)
+*)
+ };
+ (iR,oR,aR,Nias,Dia,ik)
+}
diff --git a/mips_new_tc/mips_ri.sail b/mips_new_tc/mips_ri.sail
new file mode 100644
index 00000000..3f368111
--- /dev/null
+++ b/mips_new_tc/mips_ri.sail
@@ -0,0 +1,42 @@
+(*========================================================================*)
+(* *)
+(* Copyright (c) 2015-2017 Robert M. Norton *)
+(* Copyright (c) 2015-2017 Kathyrn Gray *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+(* mips_ri.sail: only use if want unknown instructions to throw
+ exception (like real hardware) instead of die (convenient for ppcmem) *)
+
+union ast member unit RI
+function clause decode _ = Some(RI)
+function clause execute (RI) =
+ SignalException (ResI)
+
diff --git a/mips_new_tc/mips_tlb.sail b/mips_new_tc/mips_tlb.sail
new file mode 100644
index 00000000..6a0cddd6
--- /dev/null
+++ b/mips_new_tc/mips_tlb.sail
@@ -0,0 +1,134 @@
+(*========================================================================*)
+(* *)
+(* Copyright (c) 2015-2017 Robert M. Norton *)
+(* Copyright (c) 2015-2017 Kathyrn Gray *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+val (bit[2], bit[27], bit[8], TLBEntry) -> bool effect pure tlbEntryMatch
+
+function bool tlbEntryMatch(r, vpn2, asid, (TLBEntry) entry) =
+ let entryValid = entry.valid in
+ let entryR = entry.r in
+ let entryMask = entry.pagemask in
+ let entryVPN = entry.vpn2 in
+ let entryASID = entry.asid in
+ let entryG = entry.g in
+ (entryValid &
+ (r == entryR) &
+ ((vpn2 & ~((bit[27]) (EXTZ(entryMask)))) == ((entryVPN) & ~((bit[27]) (EXTZ(entryMask))))) &
+ ((asid == (entryASID)) | (entryG)))
+
+val forall Type 'a. 'a -> option<'a> effect pure Some
+
+val forall Type 'a. unit -> option<'a> effect pure None
+
+function option<TLBIndexT> tlbSearch((bit[64]) VAddr) =
+ let r = (VAddr[63..62]) in
+ let vpn2 = (VAddr[39..13]) in
+ let asid = TLBEntryHi.ASID in {
+ foreach (idx from 0 to 63) {
+ if(tlbEntryMatch(r, vpn2, asid, (TLBEntries[idx]))) then
+ return (Some ((TLBIndexT) (to_vec(idx))))
+ };
+ None()
+ }
+
+function (bit[64], bool) TLBTranslate2 ((bit[64]) vAddr, (MemAccessType) accessType) = {
+ let idx = tlbSearch(vAddr) in
+ switch(idx) {
+ case (Some(idx)) ->
+ let entry = (TLBEntries[idx]) in
+ let entryMask = entry.pagemask in
+
+ let evenOddBit = switch(entryMask) {
+ case 0x0000 -> 12
+ case 0x0003 -> 14
+ case 0x000f -> 16
+ case 0x003f -> 18
+ case 0x00ff -> 20
+ case 0x03ff -> 22
+ case 0x0fff -> 24
+ case 0x3fff -> 26
+ case 0xffff -> 28
+ case _ -> undefined
+ } in
+ let isOdd = (vAddr[evenOddBit]) in
+ let (caps, capl, (bit[24])pfn, d, v) = if (isOdd) then
+ (entry.caps1, entry.capl1, entry.pfn1, entry.d1, entry.v1)
+ else
+ (entry.caps0, entry.capl0, entry.pfn0, entry.d0, entry.v0) in
+ if (~(v)) then
+ (SignalExceptionTLB(if (accessType == StoreData) then XTLBInvS else XTLBInvL, vAddr))
+ else if ((accessType == StoreData) & ~(d)) then
+ (SignalExceptionTLB(TLBMod, vAddr))
+ else
+ (EXTZ(pfn[23..((evenOddBit)-(12))] : vAddr[((evenOddBit)-(1)) .. 0]),
+ if (accessType == StoreData) then caps else capl)
+ case None -> (SignalExceptionTLB(
+ if (accessType == StoreData) then XTLBRefillS else XTLBRefillL, vAddr))
+ }
+}
+
+(* perform TLB translation. bool is CHERI specific TLB bits noStoreCap/suppressTag *)
+function (bit[64], bool) TLBTranslateC ((bit[64]) vAddr, (MemAccessType) accessType) =
+ {
+ let currentAccessLevel = getAccessLevel() in
+ let compat32 = (vAddr[61..31] == 0b1111111111111111111111111111111) in
+ let (requiredLevel, addr) = switch(vAddr[63..62]) {
+ case 0b11 -> switch(compat32, vAddr[30..29]) { (* xkseg *)
+ case (true, 0b11) -> (Kernel, None) (* kseg3 mapped 32-bit compat *)
+ case (true, 0b10) -> (Supervisor, None) (* sseg mapped 32-bit compat *)
+ case (true, 0b01) -> (Kernel, Some(EXTZ(vAddr[28..0]))) (* kseg1 unmapped uncached 32-bit compat *)
+ case (true, 0b00) -> (Kernel, Some(EXTZ(vAddr[28..0]))) (* kseg0 unmapped cached 32-bit compat *)
+ case (_, _) -> (Kernel, None) (* xkseg mapped *)
+ }
+ case 0b10 -> (Kernel, Some(EXTZ(vAddr[58..0]))) (* xkphys bits 61-59 are cache mode (ignored) *)
+ case 0b01 -> (Supervisor, None) (* xsseg - supervisor mapped *)
+ case 0b00 -> (User, None) (* xuseg - user mapped *)
+ } in
+ if (((nat)currentAccessLevel) < ((nat)requiredLevel)) then
+ (SignalExceptionBadAddr(if (accessType == StoreData) then AdES else AdEL, vAddr))
+ else
+ let (pa, c) = switch(addr) {
+ case (Some(a)) -> (a, false)
+ case None -> if ((~(compat32)) & (unsigned(vAddr[61..0]) > MAX_VA)) then
+ (SignalExceptionBadAddr(if (accessType == StoreData) then AdES else AdEL, vAddr))
+ else
+ TLBTranslate2(vAddr, accessType)
+ }
+ in if (unsigned(pa) > MAX_PA) then
+ (SignalExceptionBadAddr(if (accessType == StoreData) then AdES else AdEL, vAddr))
+ else
+ (pa, c)
+ }
+
+function (bit[64]) TLBTranslate ((bit[64]) vAddr, (MemAccessType) accessType) =
+ let (addr, c) = TLBTranslateC(vAddr, accessType) in addr
diff --git a/mips_new_tc/mips_tlb_stub.sail b/mips_new_tc/mips_tlb_stub.sail
new file mode 100644
index 00000000..a9970a4e
--- /dev/null
+++ b/mips_new_tc/mips_tlb_stub.sail
@@ -0,0 +1,40 @@
+(*========================================================================*)
+(* *)
+(* Copyright (c) 2015-2017 Robert M. Norton *)
+(* Copyright (c) 2015-2017 Kathyrn Gray *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+function option<TLBIndexT> tlbSearch((bit[64]) VAddr) = None
+
+function (bit[64]) TLBTranslate ((bit[64]) vAddr, (MemAccessType) accessType) =
+ vAddr
+
+function (bit[64], bool) TLBTranslateC ((bit[64]) vAddr, (MemAccessType) accessType) = (vAddr, false)
diff --git a/mips_new_tc/mips_wrappers.sail b/mips_new_tc/mips_wrappers.sail
new file mode 100644
index 00000000..cdb4316c
--- /dev/null
+++ b/mips_new_tc/mips_wrappers.sail
@@ -0,0 +1,70 @@
+(*========================================================================*)
+(* *)
+(* Copyright (c) 2015-2017 Robert M. Norton *)
+(* Copyright (c) 2015-2017 Kathyrn Gray *)
+(* All rights reserved. *)
+(* *)
+(* This software was developed by the University of Cambridge Computer *)
+(* Laboratory as part of the Rigorous Engineering of Mainstream Systems *)
+(* (REMS) project, funded by EPSRC grant EP/K008528/1. *)
+(* *)
+(* Redistribution and use in source and binary forms, with or without *)
+(* modification, are permitted provided that the following conditions *)
+(* are met: *)
+(* 1. Redistributions of source code must retain the above copyright *)
+(* notice, this list of conditions and the following disclaimer. *)
+(* 2. Redistributions in binary form must reproduce the above copyright *)
+(* notice, this list of conditions and the following disclaimer in *)
+(* the documentation and/or other materials provided with the *)
+(* distribution. *)
+(* *)
+(* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' *)
+(* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *)
+(* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *)
+(* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR *)
+(* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *)
+(* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *)
+(* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *)
+(* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *)
+(* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *)
+(* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *)
+(* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *)
+(* SUCH DAMAGE. *)
+(*========================================================================*)
+
+(* mips_wrappers.sail: wrappers functions and hooks for CHERI extensibility
+ (mostly identity functions here) *)
+
+function unit effect {wmem} MEMw_wrapper((bit[64]) addr, ([:8:]) size, (bit[64]) data) =
+ let ledata = reverse_endianness'(8, data) in
+ if (addr == 0x000000007f000000) then
+ {
+ UART_WDATA := ledata[7..0];
+ UART_WRITTEN := (bit[1]) 1;
+ } else {
+ MEMea(addr, size);
+ MEMval(addr, size, ledata);
+ }
+
+function bool effect {wmem} MEMw_conditional_wrapper((bit[64]) addr, ([:8:]) size, (bit[64]) data) =
+ {
+ MEMea_conditional(addr, size);
+ MEMval_conditional(addr, size, reverse_endianness'(8, data))
+ }
+
+function bit[64] addrWrapper((bit[64]) addr, (MemAccessType) accessType, (WordType) width) =
+ addr
+
+function (bit[64]) TranslatePC ((bit[64]) vAddr) = {
+ incrementCP0Count();
+ if (vAddr[1..0] != 0b00) then (* bad PC alignment *)
+ (SignalExceptionBadAddr(AdEL, vAddr))
+ else
+ TLBTranslate(vAddr, Instruction)
+}
+
+let have_cp2 = false
+
+function unit SignalException ((Exception) ex) = SignalExceptionMIPS(ex, 0x0000000000000000)
+
+function unit ERETHook() = ()