summaryrefslogtreecommitdiff
path: root/mips/mips_prelude.sail
diff options
context:
space:
mode:
authorRobert Norton2016-05-12 19:19:44 +0100
committerRobert Norton2016-05-12 19:19:44 +0100
commit73cbdc8a34c14a8c6ad1bb1912ad2f1e6b38980c (patch)
tree5178806140614e4c4658dc07f8f42afa95b67527 /mips/mips_prelude.sail
parentf2d1251696941469f9356c7d5a809cf21bda0e24 (diff)
Implement count/compare registers for timer interrupts and rdhwr instruction.
Diffstat (limited to 'mips/mips_prelude.sail')
-rw-r--r--mips/mips_prelude.sail27
1 files changed, 27 insertions, 0 deletions
diff --git a/mips/mips_prelude.sail b/mips/mips_prelude.sail
index a8d3f8d5..28afb156 100644
--- a/mips/mips_prelude.sail
+++ b/mips/mips_prelude.sail
@@ -30,6 +30,10 @@ register (bit[64]) CP0ErrorEPC
register (bit[1]) CP0LLBit
register (bit[64]) CP0LLAddr
register (bit[64]) CP0BadVAddr
+register (bit[32]) CP0Count
+register (bit[32]) CP0Compare
+register (bit[32]) CP0HWREna
+register (bit[64]) CP0UserLocal
typedef StatusReg = register bits [31:0] {
31 .. 28 : CU; (* co-processor enable bits *)
@@ -208,6 +212,29 @@ function AccessLevel getAccessLevel() =
case _ -> User (* behaviour undefined, assume user *)
}
+function unit checkCP0Access () =
+ {
+ let accessLevel = getAccessLevel() in
+ if ((accessLevel != Kernel) & (~((CP0Status.CU)[0]))) then
+ {
+ (CP0Cause.CE) := 0b00;
+ exit (SignalException(CpU));
+ }
+ }
+
+function unit incrementCP0Count() = {
+ CP0Count := (CP0Count + 1);
+ if (CP0Count == CP0Compare) then {
+ ((CP0Cause.IP)[15]) := bitone;
+ };
+ (* XXX Sail does not allow reading fields here :-( *)
+ let (bit[32])status = CP0Status in
+ let (bit[32])cause = CP0Cause in
+ let (bit[8]) ims = (status[15..8]) in
+ let (bit[8]) ips = (cause[15..8]) in
+ if ((CP0Status.IE) & ((ips & ims) != 0x00)) then
+ exit (SignalException(Int));
+}
function (bit[64]) TLBTranslate ((bit[64]) vAddr, (MemAccessType) accessType) =
{