diff options
| author | cheapie <cheapiephp@gmail.com> | 2026-05-29 19:38:40 -0500 |
|---|---|---|
| committer | cheapie <cheapiephp@gmail.com> | 2026-05-29 19:43:27 -0500 |
| commit | 94c5a7930e5bff6cb18492392d5eea32306885e1 (patch) | |
| tree | a842d2a1d4186638b98af68145d902bf22c1d9ff /rvcontroller.lua | |
| parent | baa99d7688127a06e407edcadded63fb6efe2dc1 (diff) | |
| download | rvcontroller-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.lua | 120 |
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") |
