summaryrefslogtreecommitdiff
path: root/rvcontroller.lua
diff options
context:
space:
mode:
authorcheapie <no-email-for-you@example.com>2026-05-25 10:09:12 -0500
committercheapie <no-email-for-you@example.com>2026-05-25 10:09:12 -0500
commitb319dda192819bf079d314441469787908d97606 (patch)
tree84da47a1a30f9dda02dc846c0654f00abdb6c259 /rvcontroller.lua
parent28f10c35bdeddacdb2e10b0e84819f9c6ef67256 (diff)
downloadrvcontroller-b319dda192819bf079d314441469787908d97606.tar
rvcontroller-b319dda192819bf079d314441469787908d97606.tar.gz
rvcontroller-b319dda192819bf079d314441469787908d97606.tar.bz2
rvcontroller-b319dda192819bf079d314441469787908d97606.tar.xz
rvcontroller-b319dda192819bf079d314441469787908d97606.zip
Add Zimop, Zcmop, Zalasr, and Zawrs
Diffstat (limited to 'rvcontroller.lua')
-rw-r--r--rvcontroller.lua73
1 files changed, 71 insertions, 2 deletions
diff --git a/rvcontroller.lua b/rvcontroller.lua
index 25e66f9..a8d8915 100644
--- a/rvcontroller.lua
+++ b/rvcontroller.lua
@@ -7,7 +7,7 @@
Emulated system specifications:
-Single RISC-V core, RV32IMACB_Zicntr_Zicond_Zicsr_Zifencei_Zihintpause_Zilsd_Zabha_Zacas_Zcb_Zclsd_Zcmp_Zcmt_Zbkb_Zbkx instruction set, little-endian
+Single RISC-V core, RV32IMACB_Zicntr_Zicond_Zicsr_Zifencei_Zihintpause_Zilsd_Zimop_Zabha_Zacas_Zalasr_Zawrs_Zcb_Zclsd_Zcmop_Zcmp_Zcmt_Zbkb_Zbkx instruction set, little-endian
65536 bytes of RAM (configurable in settings below) starting at base address 0
Intended to be compliant with the following specifications:
@@ -17,6 +17,7 @@ Intended to be compliant with the following specifications:
* "Zicsr" Extension for Control and Status Register (CSR) Instructions, Version 2.0
* "Zicond" Extension for Integer Conditional Operations, Version 1.0.0
* "Zicntr" Extension for Counters, Version 2.0
+* "Zimop" Extension for May-Be-Operations, Version 1.0
* "M" Extension for Integer Multiplication and Division, Version 2.0
- Note: This implies the following:
- * Zmmul Extension, Version 1.0
@@ -31,6 +32,7 @@ Intended to be compliant with the following specifications:
- Note: This implies the following:
- * "Zca" Extension for Code Size Reduction, Version 1.0.0
* Zcb: Extension for Code Size Reduction, Version 1.0.0
+* "Zcmop" Compressed May-Be-Operations Extension, Version 1.0
* Zcmp: Extension for Code Size Reduction, Version 1.0.0
* Zcmt: Extension for Code Size Reduction, Version 1.0.0
* "B" Extension for Bit Manipulation, Version 1.0.0
@@ -42,6 +44,8 @@ Intended to be compliant with the following specifications:
* Zilsd, Zclsd: Extensions for Load/Store pair for RV32, Version 1.0
* "Zabha" Extension for Byte and Halfword Atomic Memory Operations, Version 1.0
* "Zacas" Extension for Atomic Compare-and-Swap (CAS) Instructions, Version 1.0.0
+* "Zalasr" Atomic Load-Acquire and Store-Release Instructions, Version 1.0
+* "Zawrs" Extension for Wait-on-Reservation-Set instructions, Version 1.01
* Zbkb: Extension for Bit-manipulation for Cryptography, Version 1.0.0
* Zbkx: Extension for Crossbar permutations, Version 1.0.0
@@ -283,6 +287,12 @@ local function writeram(address,data,bytes)
if mem.reservationset then
if mem.reservationset + 4 >= address and mem.reservationset <= address+bytes-1 then
mem.reservationset = nil
+ if mem.rswaiting then
+ if mem.rswaiting == "nto" then digiline_send("monitordisp","CPU started") end
+ mem.rswaiting = false
+ mem.running = true
+ interrupt(0,"tick")
+ end
end
end
for i=0,bytes-1 do
@@ -1518,6 +1528,25 @@ local operations = {
setreg(rd,getreg(rs1))
end
end,
+ mopr = function(rd,rs1,imm)
+ setreg(rd,0)
+ end,
+ moprr = function(rd,rs1,rs2,imm)
+ setreg(rd,0)
+ end,
+ cmop = function(rd,imm)
+ --Does nothing until/unless redefined by another extension
+ end,
+ wrsnto = function(rd,rs1)
+ mem.rswaiting = "nto"
+ mem.running = false
+ digiline_send("monitordisp","Waiting for\nreservation set")
+ return false,true
+ end,
+ wrssto = function(rd,rs1)
+ mem.rswaiting = "sto"
+ return false,true
+ end,
}
local function runinst(instruction)
@@ -1705,6 +1734,10 @@ local function runinst(instruction)
operations.ecall()
elseif imm == 0x1 then
operations.ebreak()
+ elseif rs1 == 0 and rd == 0 and imm == 0x0d then
+ return operations.wrsnto()
+ elseif rs1 == 0 and rd == 0 and imm == 0x1d then
+ return operations.wrssto()
end
elseif f3 == 0x1 then
operations.csrrw(rd,rs1,imm)
@@ -1712,6 +1745,12 @@ local function runinst(instruction)
operations.csrrs(rd,rs1,imm)
elseif f3 == 0x3 then
operations.csrrc(rd,rs1,imm)
+ elseif f3 == 0x4 and bits[31] and bits[24] and bits[23] and bits[22] and not (bits[29] or bits[28] or bits[25]) then
+ local immbits = implodebits({[0] = bits[20],bits[21],bits[26],bits[27],bits[30]},5)
+ operations.mopr(rd,rs1,imm)
+ elseif f3 == 0x4 and bits[31] and bits[25] and not (bits[28] or bits[29]) then
+ local immbits = implodebits({[0] = bits[26],bits[27],bits[30]},3)
+ operations.moprr(rd,rs1,rs2,imm)
elseif f3 == 0x5 then
operations.csrrwi(rd,rs1,imm)
elseif f3 == 0x6 then
@@ -1827,6 +1866,14 @@ local function runinst(instruction)
elseif f5 == 5 then
--amocas.w
operations.amocasw(rd,rs1,rs2)
+ elseif f5 == 6 and rs2 == 0 then
+ --lw.aq/lw.aqrl
+ --The normal lw instruction implementation already meets these requirements
+ operations.lw(rd,rs1,0)
+ elseif f5 == 7 and rd == 0 then
+ --sw.rl/sw.aqrl
+ --The normal sw instruction implementation already meets these requirements
+ operations.sw(rs1,rs2,0)
end
elseif f3 == 3 then
if f5 == 5 then
@@ -1864,6 +1911,14 @@ local function runinst(instruction)
elseif f5 == 5 then
--amocas.b
operations.amocasb(rd,rs1,rs2)
+ elseif f5 == 6 and rs2 == 0 then
+ --lb.aq/lb.aqrl
+ --The normal lb instruction implementation already meets these requirements
+ operations.lb(rd,rs1,0)
+ elseif f5 == 7 and rd == 0 then
+ --sb.rl/sb.aqrl
+ --The normal sb instruction implementation already meets these requirements
+ operations.sb(rs1,rs2,0)
end
elseif f3 == 1 then
if f5 == 1 then
@@ -1896,6 +1951,14 @@ local function runinst(instruction)
elseif f5 == 5 then
--amocas.h
operations.amocash(rd,rs1,rs2)
+ elseif f5 == 6 and rs2 == 0 then
+ --lh.aq/lh.aqrl
+ --The normal lh instruction implementation already meets these requirements
+ operations.lh(rd,rs1,0)
+ elseif f5 == 7 and rd == 0 then
+ --sh.rl/sh.aqrl
+ --The normal sh instruction implementation already meets these requirements
+ operations.sh(rs1,rs2,0)
end
end
elseif opcode == 0x0f then
@@ -2011,18 +2074,22 @@ local function runcinst(instruction)
operations.addi(rd,0,imm)
elseif opcode == 1 and f3 == 3 then
local immbits = {[0] = bits[2],bits[3],bits[4],bits[5],bits[6],bits[12]}
+ local imm = implodebits(immbits,6)
local rd = implodebits({[0] = bits[7],bits[8],bits[9],bits[10],bits[11]},5)
if rd == 2 then
--c.addi16sp (CI)
--For whatever reason this has a completely different immediate format than c.lui
imm = implodebits({[0] = false,false,false,false,bits[6],bits[2],bits[5],bits[3],bits[4],bits[12]},10,true)
operations.addi(2,2,imm)
- else
+ elseif imm ~= 0 then
--c.lui (CI)
signextend(immbits,6,20)
local imm = implodebits(immbits,20)
imm = imm*2^12
operations.lui(rd,imm)
+ elseif rd%2 == 1 and rd <= 15 then
+ --c.mop
+ operations.cmop(rd,imm)
end
elseif opcode == 1 and f3 == 0 then
--c.addi (CI)
@@ -2311,6 +2378,7 @@ if event.type == "program" or event.iid == "reset" then
mem.registers.pc = 0
mem.running = false
mem.inputwaiting = false
+ mem.rswaiting = false
mem.stdout = {}
mem.starttime = os.time()
mem.csr = {
@@ -2454,6 +2522,7 @@ elseif event.channel == "monitorkb" then
elseif argv[1] == "stop" then
mem.running = false
mem.inputwaiting = false
+ mem.rswaiting = false
digiline_send("monitordisp","Stopped by user")
elseif argv[1] == "h" then
--Easter egg