summaryrefslogtreecommitdiff
path: root/rvcontroller.lua
diff options
context:
space:
mode:
authorcheapie <cheapiephp@gmail.com>2026-05-29 19:38:40 -0500
committercheapie <cheapiephp@gmail.com>2026-05-29 19:43:27 -0500
commit94c5a7930e5bff6cb18492392d5eea32306885e1 (patch)
treea842d2a1d4186638b98af68145d902bf22c1d9ff /rvcontroller.lua
parentbaa99d7688127a06e407edcadded63fb6efe2dc1 (diff)
downloadrvcontroller-94c5a7930e5bff6cb18492392d5eea32306885e1.tar
rvcontroller-94c5a7930e5bff6cb18492392d5eea32306885e1.tar.gz
rvcontroller-94c5a7930e5bff6cb18492392d5eea32306885e1.tar.bz2
rvcontroller-94c5a7930e5bff6cb18492392d5eea32306885e1.tar.xz
rvcontroller-94c5a7930e5bff6cb18492392d5eea32306885e1.zip
Add mutable ISA support via writing to misa
Diffstat (limited to 'rvcontroller.lua')
-rw-r--r--rvcontroller.lua120
1 files changed, 80 insertions, 40 deletions
diff --git a/rvcontroller.lua b/rvcontroller.lua
index ca1d2da..64be2ab 100644
--- a/rvcontroller.lua
+++ b/rvcontroller.lua
@@ -104,6 +104,11 @@ Shows information on a monitor command, or a list of commands if none is specifi
ecall operations:
+NOTE: When in RV32E mode, replace a7 with a5. a5 can also be used in place of a7 in I mode if a7 is 0.
+
+a7 = 0
+Run the operation from the a5 register instead, unless a5 is also 0 in which case no operation occurs
+
a7 = 1
Prints the integer value from register a0
@@ -254,10 +259,18 @@ local function mul64(a,b,asigned,bsigned)
end
local function getreg(reg)
+ if reg > 15 and not mem.isa.i then
+ digiline_send("monitordisp",string.format("Attempted read from\nregister x%d\nin E mode\nPC: %08X",reg,mem.registers.pc))
+ return 0
+ end
return reg == 0 and 0 or mem.registers[reg]
end
local function setreg(reg,val)
+ if reg > 15 and not mem.isa.i then
+ digiline_send("monitordisp",string.format("Attempted write to\nregister x%d\nin E mode\nPC: %08X",reg,mem.registers.pc))
+ return
+ end
if val < 0 then val = val + (2^32) end
if reg ~= 0 then mem.registers[reg] = math.floor(val%(2^32)) end
end
@@ -356,7 +369,7 @@ local function writecsr(address,data)
elseif address == 0xc00 or address == 0xc01 or address == 0xc02 or address == 0xc80 or address == 0xc81 or address == 0xc82 then
--One of the read-only CSRs from Zicntr, just ignore the write
return
- elseif address == 0xf11 or address == 0xf12 or address == 0xf13 or address == 0xf14 or address == 0xf15 or address == 0x300 or address == 0x301 then
+ elseif address == 0xf11 or address == 0xf12 or address == 0xf13 or address == 0xf14 or address == 0xf15 or address == 0x300 then
--Read-only machine information register, ignore write
elseif address == 0x310 then
--mstatush
@@ -364,6 +377,20 @@ local function writecsr(address,data)
mem.bigendian = bits[5]
mem.csr[0x310] = mem.bigendian and 0x20 or 0
return
+ elseif address == 0x301 then
+ --misa
+ local bits = explodebits(data,32)
+ if mem.registers.pc % 4 == 2 and not bits[2] then
+ digiline_send("monitordisp",string.format("Attempted to disable\nC extension but\ninstruction would be\nmisaligned,\nwrite ignored\nPC: %08X",mem.registers.pc))
+ end
+ mem.isa.a = bits[0]
+ mem.isa.b = bits[1]
+ mem.isa.c = bits[2]
+ mem.isa.i = bits[8]
+ mem.isa.m = bits[12]
+ local newbits = {[0] = mem.isa.a,mem.isa.b,mem.isa.c,[4] = not mem.isa.i,[8] = mem.isa.i,[12] = mem.isa.m}
+ mem.csr[0x301] = implodebits(newbits,32)
+ return
end
if not mem.csr[address] then
digiline_send("monitordisp",string.format("W: Attempted write\nto unknown\nCSR 0x%03X\nPC: %08X",address,mem.registers.pc))
@@ -686,7 +713,8 @@ local operations = {
writeram(address+(mem.bigendian and 0 or 4),getreg(rs2+1),4)
end,
ecall = function()
- local func = getreg(17)
+ local func = mem.isa.i and getreg(17) or getreg(15)
+ if mem.isa.i and func == 0 then func = getreg(15) end
local param1 = getreg(10)
local param2 = getreg(11)
if func == 1 then
@@ -1603,33 +1631,33 @@ local function runinst(instruction)
operations.slt(rd,rs1,rs2)
elseif f3 == 0x3 and f7 == 0x0 then
operations.sltu(rd,rs1,rs2)
- elseif f3 == 0x0 and f7 == 0x1 then
+ elseif f3 == 0x0 and f7 == 0x1 and mem.isa.m then
operations.mul(rd,rs1,rs2)
- elseif f3 == 0x1 and f7 == 0x1 then
+ elseif f3 == 0x1 and f7 == 0x1 and mem.isa.m then
operations.mulh(rd,rs1,rs2)
- elseif f3 == 0x2 and f7 == 0x1 then
+ elseif f3 == 0x2 and f7 == 0x1 and mem.isa.m then
operations.mulsu(rd,rs1,rs2)
- elseif f3 == 0x3 and f7 == 0x1 then
+ elseif f3 == 0x3 and f7 == 0x1 and mem.isa.m then
operations.mulu(rd,rs1,rs2)
- elseif f3 == 0x4 and f7 == 0x1 then
+ elseif f3 == 0x4 and f7 == 0x1 and mem.isa.m then
operations.div(rd,rs1,rs2)
- elseif f3 == 0x5 and f7 == 0x1 then
+ elseif f3 == 0x5 and f7 == 0x1 and mem.isa.m then
operations.divu(rd,rs1,rs2)
- elseif f3 == 0x6 and f7 == 0x1 then
+ elseif f3 == 0x6 and f7 == 0x1 and mem.isa.m then
operations.rem(rd,rs1,rs2)
- elseif f3 == 0x7 and f7 == 0x1 then
+ elseif f3 == 0x7 and f7 == 0x1 and mem.isa.m then
operations.remu(rd,rs1,rs2)
- elseif f3 == 0x2 and f7 == 0x10 then
+ elseif f3 == 0x2 and f7 == 0x10 and mem.isa.b then
operations.sh1add(rd,rs1,rs2)
- elseif f3 == 0x4 and f7 == 0x10 then
+ elseif f3 == 0x4 and f7 == 0x10 and mem.isa.b then
operations.sh2add(rd,rs1,rs2)
- elseif f3 == 0x6 and f7 == 0x10 then
+ elseif f3 == 0x6 and f7 == 0x10 and mem.isa.b then
operations.sh3add(rd,rs1,rs2)
- elseif f3 == 0x7 and f7 == 0x20 then
+ elseif f3 == 0x7 and f7 == 0x20 and mem.isa.b then
operations.andn(rd,rs1,rs2)
- elseif f3 == 0x6 and f7 == 0x20 then
+ elseif f3 == 0x6 and f7 == 0x20 and mem.isa.b then
operations.orn(rd,rs1,rs2)
- elseif f3 == 0x4 and f7 == 0x20 then
+ elseif f3 == 0x4 and f7 == 0x20 and mem.isa.b then
operations.xnor(rd,rs1,rs2)
elseif f3 == 0x6 and f7 == 0x5 then
operations.max(rd,rs1,rs2)
@@ -1639,23 +1667,23 @@ local function runinst(instruction)
operations.min(rd,rs1,rs2)
elseif f3 == 0x5 and f7 == 0x5 then
operations.minu(rd,rs1,rs2)
- elseif f3 == 0x4 and f7 == 0x4 and rs2 == 0x0 then
+ elseif f3 == 0x4 and f7 == 0x4 and rs2 == 0x0 and mem.isa.b then
operations.zexth(rd,rs1)
- elseif f3 == 0x1 and f7 == 0x30 then
+ elseif f3 == 0x1 and f7 == 0x30 and mem.isa.b then
operations.rol(rd,rs1,rs2)
- elseif f3 == 0x5 and f7 == 0x30 then
+ elseif f3 == 0x5 and f7 == 0x30 and mem.isa.b then
operations.ror(rd,rs1,rs2)
- elseif f3 == 0x1 and f7 == 0x24 then
+ elseif f3 == 0x1 and f7 == 0x24 and mem.isa.b then
operations.bclr(rd,rs1,rs2)
- elseif f3 == 0x5 and f7 == 0x24 then
+ elseif f3 == 0x5 and f7 == 0x24 and mem.isa.b then
operations.bext(rd,rs1,rs2)
- elseif f3 == 0x1 and f7 == 0x34 then
+ elseif f3 == 0x1 and f7 == 0x34 and mem.isa.b then
operations.binv(rd,rs1,rs2)
- elseif f3 == 0x1 and f7 == 0x14 then
+ elseif f3 == 0x1 and f7 == 0x14 and mem.isa.b then
operations.bset(rd,rs1,rs2)
- elseif f3 == 0x2 and f7 == 0x14 then
+ elseif f3 == 0x2 and f7 == 0x14 and mem.isa.b then
operations.xperm4(rd,rs1,rs2)
- elseif f3 == 0x4 and f7 == 0x14 then
+ elseif f3 == 0x4 and f7 == 0x14 and mem.isa.b then
operations.xperm8(rd,rs1,rs2)
elseif f3 == 0x4 and f7 == 0x4 then
operations.pack(rd,rs1,rs2)
@@ -1695,21 +1723,21 @@ local function runinst(instruction)
operations.slti(rd,rs1,imm)
elseif f3 == 0x3 then
operations.sltiu(rd,rs1,imm)
- elseif f3 == 0x1 and imm == 0x600 then
+ elseif f3 == 0x1 and imm == 0x600 and mem.isa.b then
operations.clz(rd,rs1)
- elseif f3 == 0x1 and imm == 0x601 then
+ elseif f3 == 0x1 and imm == 0x601 and mem.isa.b then
operations.ctz(rd,rs1)
- elseif f3 == 0x1 and imm == 0x602 then
+ elseif f3 == 0x1 and imm == 0x602 and mem.isa.b then
operations.cpop(rd,rs1)
- elseif f3 == 0x1 and imm == 0x604 then
+ elseif f3 == 0x1 and imm == 0x604 and mem.isa.b then
operations.sextb(rd,rs1)
- elseif f3 == 0x1 and imm == 0x605 then
+ elseif f3 == 0x1 and imm == 0x605 and mem.isa.b then
operations.sexth(rd,rs1)
elseif f3 == 0x5 and math.floor(imm/2^5) == 0x30 then
operations.rori(rd,rs1,imm)
- elseif f3 == 0x5 and imm == 0x287 then
+ elseif f3 == 0x5 and imm == 0x287 and mem.isa.b then
operations.orcb(rd,rs1)
- elseif f3 == 0x5 and imm == 0x698 then
+ elseif f3 == 0x5 and imm == 0x698 and mem.isa.b then
operations.rev8(rd,rs1)
elseif f3 == 0x1 and math.floor(imm/2^5) == 0x24 then
operations.bclri(rd,rs1,imm)
@@ -1750,9 +1778,9 @@ local function runinst(instruction)
operations.ecall()
elseif imm == 0x1 then
operations.ebreak()
- elseif rs1 == 0 and rd == 0 and imm == 0x0d then
+ elseif rs1 == 0 and rd == 0 and imm == 0x0d and mem.isa.a then
return operations.wrsnto()
- elseif rs1 == 0 and rd == 0 and imm == 0x1d then
+ elseif rs1 == 0 and rd == 0 and imm == 0x1d and mem.isa.a then
return operations.wrssto()
end
elseif f3 == 0x1 then
@@ -1837,7 +1865,7 @@ local function runinst(instruction)
local immbits = {[0] = false,bits[21],bits[22],bits[23],bits[24],bits[25],bits[26],bits[27],bits[28],bits[29],bits[30],bits[20],bits[12],bits[13],bits[14],bits[15],bits[16],bits[17],bits[18],bits[19],bits[31]}
local imm = implodebits(immbits,21)
return operations.jal(rd,imm)
- elseif opcode == 0x2f then
+ elseif opcode == 0x2f and mem.isa.a then
--Atomic memory operation
local f5 = math.floor(instruction/2^27)
local f3 = implodebits({[0] = bits[12],bits[13],bits[14]},3)
@@ -2198,15 +2226,15 @@ local function runcinst(instruction)
--c.zext.b
local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8
operations.andi(rd,rd,0xff)
- elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[2] and not (bits[3] or bits[4]) then
+ elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[2] and mem.isa.b and not (bits[3] or bits[4]) then
--c.sext.b
local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8
operations.sextb(rd,rd)
- elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[3] and not (bits[2] or bits[4]) then
+ elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[3] and mem.isa.b and not (bits[2] or bits[4]) then
--c.zext.h
local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8
operations.zexth(rd,rd)
- elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[2] and bits[3] and not bits[4] then
+ elseif opcode == 1 and f6 == 0x27 and bits[5] and bits[6] and bits[2] and bits[3] and mem.isa.b and not bits[4] then
--c.sext.h
local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8
operations.sexth(rd,rd)
@@ -2214,7 +2242,7 @@ local function runcinst(instruction)
--c.not
local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8
operations.xori(rd,rd,0xffffffff)
- elseif opcode == 1 and f6 == 0x27 and bits[6] and not bits[5] then
+ elseif opcode == 1 and f6 == 0x27 and bits[6] and mem.isa.m and not bits[5] then
--c.mul
local rd = implodebits({[0] = bits[7],bits[8],bits[9]},3)+8
local rs2 = implodebits({[0] = bits[2],bits[3],bits[4]},3)+8
@@ -2327,7 +2355,12 @@ local function run(limit)
end
first = false
local instruction = readram(mem.registers.pc,4,true)
- if instruction%4 == 3 then
+ if instruction%4 == 3 or not mem.isa.c then
+ if mem.registers.pc%4 ~= 0 and not mem.isa.c then
+ digiline_send("monitordisp",string.format("Misaligned\ninstruction fetch,\nSystem halted\nPC: %08X",mem.registers.pc))
+ mem.running = false
+ break
+ end
local jumped,stop = runinst(instruction)
if not jumped then mem.registers.pc = (mem.registers.pc + 4) % 2^32 end
if stop then break end
@@ -2424,6 +2457,13 @@ if event.type == "program" or event.iid == "reset" then
mem.hexloading = false
mem.reservationset = nil
mem.bigendian = false
+ mem.isa = {
+ a = true,
+ b = true,
+ c = true,
+ i = true,
+ m = true,
+ }
elseif event.channel == "reset" then
mem.running = false
digiline_send("monitordisp","\n\n\n\n\n\n\n")