diff options
| -rw-r--r-- | rvcontroller.lua | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/rvcontroller.lua b/rvcontroller.lua index a8d8915..d804f75 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_Zimop_Zabha_Zacas_Zalasr_Zawrs_Zcb_Zclsd_Zcmop_Zcmp_Zcmt_Zbkb_Zbkx instruction set, little-endian +Single RISC-V core, RV32IMACBZicntr_Zicond_Zicsr_Zifencei_Zihintpause_Zilsd_Zimop_Zabha_Zacas_Zalasr_Zawrs_Zcb_Zclsd_Zcmop_Zcmp_Zcmt_Zbkb_Zbkx instruction set, switchable endianness (little-endian default) 65536 bytes of RAM (configurable in settings below) starting at base address 0 Intended to be compliant with the following specifications: @@ -262,7 +262,8 @@ local function setreg(reg,val) if reg ~= 0 then mem.registers[reg] = math.floor(val%(2^32)) end end -local function readram(address,bytes) +local function readram(address,bytes,instfetch) + local bigendian = mem.bigendian and not instfetch --Instruction fetches must always be little-endian if address > RAM_SIZE-1 then digiline_send("monitordisp",string.format("Out-of-bounds\nmemory read\nAddress: %08X\nPC: %08X\nSystem halted",address,mem.registers.pc)) mem.running = false @@ -270,7 +271,12 @@ local function readram(address,bytes) end local out = 0 for i=0,bytes-1 do - local offsetaddr = address+i + local offsetaddr + if bigendian then + offsetaddr = address+bytes-1-i + else + offsetaddr = address+i + end local segment = math.floor(offsetaddr/256) local offset = offsetaddr%256 out = out + (string.byte(string.sub(mem.ram[segment],offset+1,offset+1)) or 0) * 2^(8*i) @@ -298,7 +304,12 @@ local function writeram(address,data,bytes) for i=0,bytes-1 do local thisbyte = data % (2^((i+1)*8)) / 2^(i*8) thisbyte = math.floor(thisbyte) % 2^32 - local offsetaddr = address+i + local offsetaddr + if mem.bigendian then + offsetaddr = address+bytes-1-i + else + offsetaddr = address+i + end local segment = math.floor(offsetaddr/256) local offset = offsetaddr%256 mem.ram[segment] = string.sub(mem.ram[segment],0,offset)..string.char(thisbyte)..string.sub(mem.ram[segment],offset+2,-1) @@ -345,8 +356,13 @@ 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 or address == 0x310 then + elseif address == 0xf11 or address == 0xf12 or address == 0xf13 or address == 0xf14 or address == 0xf15 or address == 0x300 or address == 0x301 then --Read-only machine information register, ignore write + elseif address == 0x310 then + --mstatush + local bits = explodebits(data,32) + mem.bigendian = bits[5] + mem.csr[0x310] = mem.bigendian and 0x20 or 0 return end if not mem.csr[address] then @@ -2310,7 +2326,7 @@ local function run(limit) break end first = false - local instruction = readram(mem.registers.pc,4) + local instruction = readram(mem.registers.pc,4,true) if instruction%4 == 3 then local jumped,stop = runinst(instruction) if not jumped then mem.registers.pc = (mem.registers.pc + 4) % 2^32 end @@ -2407,6 +2423,7 @@ if event.type == "program" or event.iid == "reset" then mem.breakpoint = -1 mem.hexloading = false mem.reservationset = nil + mem.bigendian = false elseif event.channel == "reset" then mem.running = false digiline_send("monitordisp","\n\n\n\n\n\n\n") |
