diff --git a/src/main/scala/vexriscv/plugin/CsrPlugin.scala b/src/main/scala/vexriscv/plugin/CsrPlugin.scala index c980fa8..7f4c774 100644 --- a/src/main/scala/vexriscv/plugin/CsrPlugin.scala +++ b/src/main/scala/vexriscv/plugin/CsrPlugin.scala @@ -32,6 +32,14 @@ object CsrAccess { object NONE extends CsrAccess } +object CsrPlugin { + object IS_CSR extends Stageable(Bool) + object CSR_WRITE_OPCODE extends Stageable(Bool) + object CSR_READ_OPCODE extends Stageable(Bool) + object IS_PMP_CFG extends Stageable(Bool) + object IS_PMP_ADDR extends Stageable(Bool) +} + case class ExceptionPortInfo(port : Flow[ExceptionCause],stage : Stage, priority : Int) case class CsrPluginConfig( catchIllegalAccess : Boolean, @@ -399,6 +407,7 @@ trait IWake{ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with ExceptionService with PrivilegeService with InterruptionInhibitor with ExceptionInhibitor with IContextSwitching with CsrInterface with IWake{ import config._ import CsrAccess._ + import CsrPlugin._ assert(!(wfiGenAsNop && wfiGenAsWait)) @@ -440,9 +449,6 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep } object ENV_CTRL extends Stageable(EnvCtrlEnum()) - object IS_CSR extends Stageable(Bool) - object CSR_WRITE_OPCODE extends Stageable(Bool) - object CSR_READ_OPCODE extends Stageable(Bool) object PIPELINED_CSR_READ extends Stageable(Bits(32 bits)) var allowInterrupts : Bool = null @@ -1029,9 +1035,13 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep || (input(INSTRUCTION)(14 downto 13) === B"11" && imm.z === 0) ) insert(CSR_READ_OPCODE) := input(INSTRUCTION)(13 downto 7) =/= B"0100000" + + if (pipeline.serviceExist(classOf[PmpPlugin])) { + insert(IS_PMP_CFG) := input(INSTRUCTION)(31 downto 24) === 0x3a + insert(IS_PMP_ADDR) := input(INSTRUCTION)(31 downto 24) === 0x3b + } } - execute plug new Area{ import execute._ //Manage WFI instructions @@ -1103,25 +1113,27 @@ class CsrPlugin(val config: CsrPluginConfig) extends Plugin[VexRiscv] with Excep True -> Mux(input(INSTRUCTION)(12), readToWriteData & ~writeSrc, readToWriteData | writeSrc) ) - when(arbitration.isValid && input(IS_CSR)) { - if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData - arbitration.haltItself setWhen(blockedBySideEffects) - } - if(pipelineCsrRead){ - insert(PIPELINED_CSR_READ) := readData - when(memory.arbitration.isValid && memory.input(IS_CSR)) { - memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ) + val csrAddress = input(INSTRUCTION)(csrRange) + val pmpAccess = if (pipeline.serviceExist(classOf[PmpPlugin])) { + input(IS_PMP_CFG) | input(IS_PMP_ADDR) + } else False + + when (~pmpAccess) { + when(arbitration.isValid && input(IS_CSR)) { + if(!pipelineCsrRead) output(REGFILE_WRITE_DATA) := readData + arbitration.haltItself setWhen(blockedBySideEffects) } + if(pipelineCsrRead){ + insert(PIPELINED_CSR_READ) := readData + when(memory.arbitration.isValid && memory.input(IS_CSR)) { + memory.output(REGFILE_WRITE_DATA) := memory.input(PIPELINED_CSR_READ) + } + } + }.elsewhen(arbitration.isValid && input(IS_CSR)) { + illegalAccess := False } -// -// Component.current.rework{ -// when(arbitration.isFiring && input(IS_CSR)) { -// memory.input(REGFILE_WRITE_DATA).getDrivingReg := readData -// } -// } //Translation of the csrMapping into real logic - val csrAddress = input(INSTRUCTION)(csrRange) Component.current.afterElaboration{ def doJobs(jobs : ArrayBuffer[Any]): Unit ={ val withWrite = jobs.exists(j => j.isInstanceOf[CsrWrite] || j.isInstanceOf[CsrOnWrite] || j.isInstanceOf[CsrDuringWrite]) diff --git a/src/main/scala/vexriscv/plugin/PmpPlugin.scala b/src/main/scala/vexriscv/plugin/PmpPlugin.scala index e6cb396..357d5b8 100644 --- a/src/main/scala/vexriscv/plugin/PmpPlugin.scala +++ b/src/main/scala/vexriscv/plugin/PmpPlugin.scala @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samuel Lindemer + * Copyright (c) 2021 Samuel Lindemer * * SPDX-License-Identifier: MIT */ @@ -7,9 +7,11 @@ package vexriscv.plugin import vexriscv.{VexRiscv, _} +import vexriscv.plugin.CsrPlugin.{_} +import vexriscv.plugin.MemoryTranslatorPort.{_} import spinal.core._ import spinal.lib._ -import scala.collection.mutable.ArrayBuffer +import spinal.lib.fsm._ /* Each 32-bit pmpcfg# register contains four 8-bit configuration sections. * These section numbers contain flags which apply to regions defined by the @@ -63,104 +65,70 @@ import scala.collection.mutable.ArrayBuffer * register defines a 4-byte wide region. */ -case class PmpRegister(previous : PmpRegister) extends Area { - +trait Pmp { def OFF = 0 def TOR = 1 def NA4 = 2 def NAPOT = 3 - val state = new Area { - val r, w, x = Reg(Bool) - val l = RegInit(False) - val a = Reg(UInt(2 bits)) init(0) - val addr = Reg(UInt(32 bits)) + def xlen = 32 + def rBit = 0 + def wBit = 1 + def xBit = 2 + def aBits = 4 downto 3 + def lBit = 7 +} + +class PmpSetter() extends Component with Pmp { + val io = new Bundle { + val a = in Bits(2 bits) + val addr = in UInt(xlen bits) + val prevHi = in UInt(30 bits) + val boundLo, boundHi = out UInt(30 bits) } - // CSR writes connect to these signals rather than the internal state - // registers. This makes locking and WARL possible. - val csr = new Area { - val r, w, x = Bool - val l = Bool - val a = UInt(2 bits) - val addr = UInt(32 bits) - } + val shifted = io.addr(29 downto 0) + io.boundLo := shifted + io.boundHi := shifted - // Last valid assignment wins; nothing happens if a user-initiated write did - // not occur on this clock cycle. - csr.r := state.r - csr.w := state.w - csr.x := state.x - csr.l := state.l - csr.a := state.a - csr.addr := state.addr - - // Computed PMP region bounds - val region = new Area { - val valid, locked = Bool - val start, end = UInt(32 bits) - } - - when(~state.l) { - state.r := csr.r - state.w := csr.w - state.x := csr.x - state.l := csr.l - state.a := csr.a - state.addr := csr.addr - - if (csr.l == True & csr.a == TOR) { - previous.state.l := True + switch (io.a) { + is (TOR) { + io.boundLo := io.prevHi } - } - - val shifted = state.addr |<< 2 - val mask = state.addr & ~(state.addr + 1) - val masked = (state.addr & ~mask) |<< 2 - - // PMP changes take effect two clock cycles after the initial CSR write (i.e., - // settings propagate from csr -> state -> region). - region.locked := state.l - region.valid := True - - switch(csr.a) { - is(TOR) { - if (previous == null) region.start := 0 - else region.start := previous.region.end - region.end := shifted + is (NA4) { + io.boundHi := shifted + 1 } - is(NA4) { - region.start := shifted - region.end := shifted + 4 - } - is(NAPOT) { - region.start := masked - region.end := masked + ((mask + 1) |<< 3) - } - default { - region.start := 0 - region.end := shifted - region.valid := False + is (NAPOT) { + val mask = io.addr & ~(io.addr + 1) + val boundLo = (io.addr ^ mask)(29 downto 0) + io.boundLo := boundLo + io.boundHi := boundLo + ((mask + 1) |<< 3)(29 downto 0) } } } case class ProtectedMemoryTranslatorPort(bus : MemoryTranslatorBus) -class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator { - - // Each pmpcfg# CSR configures four regions. - assert((regions % 4) == 0) - - val pmps = ArrayBuffer[PmpRegister]() - val portsInfo = ArrayBuffer[ProtectedMemoryTranslatorPort]() +class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] with MemoryTranslator with Pmp { + assert(regions % 4 == 0) + assert(regions <= 16) + var setter : PmpSetter = null + var dPort, iPort : ProtectedMemoryTranslatorPort = null + override def newTranslationPort(priority : Int, args : Any): MemoryTranslatorBus = { val port = ProtectedMemoryTranslatorPort(MemoryTranslatorBus(new MemoryTranslatorBusParameter(0, 0))) - portsInfo += port + priority match { + case PRIORITY_INSTRUCTION => iPort = port + case PRIORITY_DATA => dPort = port + } port.bus } + override def setup(pipeline: VexRiscv): Unit = { + setter = new PmpSetter() + } + override def build(pipeline: VexRiscv): Unit = { import pipeline.config._ import pipeline._ @@ -169,78 +137,201 @@ class PmpPlugin(regions : Int, ioRange : UInt => Bool) extends Plugin[VexRiscv] val csrService = pipeline.service(classOf[CsrInterface]) val privilegeService = pipeline.service(classOf[PrivilegeService]) - val core = pipeline plug new Area { + val pmpaddr = Mem(UInt(xlen bits), regions) + val pmpcfg = Reg(Bits(8 * regions bits)) init(0) + val boundLo, boundHi = Mem(UInt(30 bits), regions) + val cfgRegion = pmpcfg.subdivideIn(8 bits) + val cfgRegister = pmpcfg.subdivideIn(xlen bits) + val lockMask = Reg(Bits(4 bits)) init(B"4'0") - // Instantiate pmpaddr0 ... pmpaddr# CSRs. - for (i <- 0 until regions) { - if (i == 0) { - pmps += PmpRegister(null) - } else { - pmps += PmpRegister(pmps.last) + execute plug new Area { + import execute._ + + val csrAddress = input(INSTRUCTION)(csrRange) + val accessAddr = input(IS_PMP_ADDR) + val accessCfg = input(IS_PMP_CFG) + val pmpWrite = arbitration.isValid && input(IS_CSR) && input(CSR_WRITE_OPCODE) & (accessAddr | accessCfg) + val pmpRead = arbitration.isValid && input(IS_CSR) && input(CSR_READ_OPCODE) & (accessAddr | accessCfg) + val pmpIndex = csrAddress(log2Up(regions) - 1 downto 0).asUInt + val pmpSelect = pmpIndex(log2Up(regions) - 3 downto 0) + + val readAddr = pmpaddr.readAsync(pmpIndex).asBits + val readCfg = cfgRegister(pmpSelect) + val readToWrite = Mux(accessCfg, readCfg, readAddr) + val writeSrc = input(SRC1) + val writeData = input(INSTRUCTION)(13).mux( + False -> writeSrc, + True -> Mux( + input(INSTRUCTION)(12), + readToWrite & ~writeSrc, + readToWrite | writeSrc + ) + ) + + val writer = new Area { + when (accessCfg) { + when (pmpRead) { + output(REGFILE_WRITE_DATA).assignFromBits(readCfg) + } + when (pmpWrite) { + switch(pmpSelect) { + for (i <- 0 until (regions / 4)) { + is(i) { + for (j <- Range(0, xlen, 8)) { + val bitRange = j + xlen * i + lBit downto j + xlen * i + val overwrite = writeData.subdivideIn(8 bits)(j / 8) + val locked = cfgRegister(i).subdivideIn(8 bits)(j / 8)(lBit) + lockMask(j / 8) := locked + when (~locked) { + pmpcfg(bitRange).assignFromBits(overwrite) + if (j != 0 || i != 0) { + when (overwrite(lBit) & overwrite(aBits) === TOR) { + pmpcfg(j + xlen * i - 1) := True + } + } + } + } + } + } + } + } + }.elsewhen (accessAddr) { + when (pmpRead) { + output(REGFILE_WRITE_DATA) := readAddr + } } - csrService.r(0x3b0 + i, pmps(i).state.addr) - csrService.w(0x3b0 + i, pmps(i).csr.addr) + val locked = cfgRegion(pmpIndex)(lBit) + pmpaddr.write(pmpIndex, writeData.asUInt, ~locked & pmpWrite & accessAddr) } - // Instantiate pmpcfg0 ... pmpcfg# CSRs. - for (i <- 0 until (regions / 4)) { - csrService.r(0x3a0 + i, - 31 -> pmps((i * 4) + 3).state.l, 23 -> pmps((i * 4) + 2).state.l, - 15 -> pmps((i * 4) + 1).state.l, 7 -> pmps((i * 4) ).state.l, - 27 -> pmps((i * 4) + 3).state.a, 26 -> pmps((i * 4) + 3).state.x, - 25 -> pmps((i * 4) + 3).state.w, 24 -> pmps((i * 4) + 3).state.r, - 19 -> pmps((i * 4) + 2).state.a, 18 -> pmps((i * 4) + 2).state.x, - 17 -> pmps((i * 4) + 2).state.w, 16 -> pmps((i * 4) + 2).state.r, - 11 -> pmps((i * 4) + 1).state.a, 10 -> pmps((i * 4) + 1).state.x, - 9 -> pmps((i * 4) + 1).state.w, 8 -> pmps((i * 4) + 1).state.r, - 3 -> pmps((i * 4) ).state.a, 2 -> pmps((i * 4) ).state.x, - 1 -> pmps((i * 4) ).state.w, 0 -> pmps((i * 4) ).state.r - ) - csrService.w(0x3a0 + i, - 31 -> pmps((i * 4) + 3).csr.l, 23 -> pmps((i * 4) + 2).csr.l, - 15 -> pmps((i * 4) + 1).csr.l, 7 -> pmps((i * 4) ).csr.l, - 27 -> pmps((i * 4) + 3).csr.a, 26 -> pmps((i * 4) + 3).csr.x, - 25 -> pmps((i * 4) + 3).csr.w, 24 -> pmps((i * 4) + 3).csr.r, - 19 -> pmps((i * 4) + 2).csr.a, 18 -> pmps((i * 4) + 2).csr.x, - 17 -> pmps((i * 4) + 2).csr.w, 16 -> pmps((i * 4) + 2).csr.r, - 11 -> pmps((i * 4) + 1).csr.a, 10 -> pmps((i * 4) + 1).csr.x, - 9 -> pmps((i * 4) + 1).csr.w, 8 -> pmps((i * 4) + 1).csr.r, - 3 -> pmps((i * 4) ).csr.a, 2 -> pmps((i * 4) ).csr.x, - 1 -> pmps((i * 4) ).csr.w, 0 -> pmps((i * 4) ).csr.r - ) - } + val controller = new StateMachine { + val counter = Reg(UInt(log2Up(regions) bits)) init(0) + val enable = RegInit(False) - // Connect memory ports to PMP logic. - val ports = for ((port, portId) <- portsInfo.zipWithIndex) yield new Area { + val stateIdle : State = new State with EntryPoint { + onEntry { + lockMask := B"4'x0" + enable := False + counter := 0 + } + onExit { + enable := True + arbitration.haltItself := True + } + whenIsActive { + when (pmpWrite) { + when (accessCfg) { + goto(stateCfg) + }.elsewhen (accessAddr) { + goto(stateAddr) + } + } + } + } - val address = port.bus.cmd(0).virtualAddress - port.bus.rsp.physicalAddress := address + val stateCfg : State = new State { + onEntry (counter := pmpIndex(log2Up(regions) - 3 downto 0) @@ U"2'00") + whenIsActive { + counter := counter + 1 + when (counter(1 downto 0) === 3) { + goto(stateIdle) + } otherwise { + arbitration.haltItself := True + } + } + } - // Only the first matching PMP region applies. - val hits = pmps.map(pmp => pmp.region.valid & - pmp.region.start <= address & - pmp.region.end > address & - (pmp.region.locked | ~privilegeService.isMachine())) + val stateAddr : State = new State { + onEntry (counter := pmpIndex) + whenIsActive { + counter := counter + 1 + when (counter === (pmpIndex + 1) | counter === 0) { + goto(stateIdle) + } otherwise { + arbitration.haltItself := True + } + } + } - // M-mode has full access by default, others have none. - when(CountOne(hits) === 0) { - port.bus.rsp.allowRead := privilegeService.isMachine() - port.bus.rsp.allowWrite := privilegeService.isMachine() - port.bus.rsp.allowExecute := privilegeService.isMachine() + when (accessCfg) { + setter.io.a := writeData.subdivideIn(8 bits)(counter(1 downto 0))(aBits) + setter.io.addr := pmpaddr(counter) } otherwise { - port.bus.rsp.allowRead := MuxOH(OHMasking.first(hits), pmps.map(_.state.r)) - port.bus.rsp.allowWrite := MuxOH(OHMasking.first(hits), pmps.map(_.state.w)) - port.bus.rsp.allowExecute := MuxOH(OHMasking.first(hits), pmps.map(_.state.x)) + setter.io.a := cfgRegion(counter)(aBits) + when (counter === pmpIndex) { + setter.io.addr := writeData.asUInt + } otherwise { + setter.io.addr := pmpaddr(counter) + } } + + when (counter === 0) { + setter.io.prevHi := 0 + } otherwise { + setter.io.prevHi := boundHi(counter - 1) + } + + when (enable & + ((accessCfg & ~lockMask(counter(1 downto 0))) | + (accessAddr & ~cfgRegion(counter)(lBit)))) { + boundLo(counter) := setter.io.boundLo + boundHi(counter) := setter.io.boundHi + } + } + } - port.bus.rsp.isIoAccess := ioRange(port.bus.rsp.physicalAddress) - port.bus.rsp.isPaging := False - port.bus.rsp.exception := False - port.bus.rsp.refilling := False - port.bus.busy := False + pipeline plug new Area { + def getHits(address : UInt) = { + (0 until regions).map(i => + address >= boundLo(U(i, log2Up(regions) bits)) & + address < boundHi(U(i, log2Up(regions) bits)) & + (cfgRegion(i)(lBit) | ~privilegeService.isMachine()) & + cfgRegion(i)(aBits) =/= 0 + ) + } + val dGuard = new Area { + val address = dPort.bus.cmd(0).virtualAddress + dPort.bus.rsp.physicalAddress := address + dPort.bus.rsp.isIoAccess := ioRange(address) + dPort.bus.rsp.isPaging := False + dPort.bus.rsp.exception := False + dPort.bus.rsp.refilling := False + dPort.bus.rsp.allowExecute := False + dPort.bus.busy := False + + val hits = getHits(address(31 downto 2)) + + when(~hits.orR) { + dPort.bus.rsp.allowRead := privilegeService.isMachine() + dPort.bus.rsp.allowWrite := privilegeService.isMachine() + } otherwise { + val oneHot = OHMasking.first(hits) + dPort.bus.rsp.allowRead := MuxOH(oneHot, cfgRegion.map(cfg => cfg(rBit))) + dPort.bus.rsp.allowWrite := MuxOH(oneHot, cfgRegion.map(cfg => cfg(wBit))) + } + } + + val iGuard = new Area { + val address = iPort.bus.cmd(0).virtualAddress + iPort.bus.rsp.physicalAddress := address + iPort.bus.rsp.isIoAccess := ioRange(address) + iPort.bus.rsp.isPaging := False + iPort.bus.rsp.exception := False + iPort.bus.rsp.refilling := False + iPort.bus.rsp.allowRead := False + iPort.bus.rsp.allowWrite := False + iPort.bus.busy := False + + val hits = getHits(address(31 downto 2)) + + when(~hits.orR) { + iPort.bus.rsp.allowExecute := privilegeService.isMachine() + } otherwise { + val oneHot = OHMasking.first(hits) + iPort.bus.rsp.allowExecute := MuxOH(oneHot, cfgRegion.map(cfg => cfg(xBit))) + } } } } -} - +} \ No newline at end of file diff --git a/src/test/cpp/raw/pmp/build/pmp.asm b/src/test/cpp/raw/pmp/build/pmp.asm index 4508ee6..c1fa1b7 100644 --- a/src/test/cpp/raw/pmp/build/pmp.asm +++ b/src/test/cpp/raw/pmp/build/pmp.asm @@ -17,26 +17,26 @@ Disassembly of section .crt_section: 80000018 : 80000018: 00000e13 li t3,0 8000001c: 00000f17 auipc t5,0x0 -80000020: 27cf0f13 addi t5,t5,636 # 80000298 +80000020: 330f0f13 addi t5,t5,816 # 8000034c 80000024: 800000b7 lui ra,0x80000 80000028: 80008237 lui tp,0x80008 8000002c: deadc137 lui sp,0xdeadc -80000030: eef10113 addi sp,sp,-273 # deadbeef -80000034: 0020a023 sw sp,0(ra) # 80000000 -80000038: 00222023 sw sp,0(tp) # 80008000 +80000030: eef10113 addi sp,sp,-273 # deadbeef +80000034: 0020a023 sw sp,0(ra) # 80000000 +80000038: 00222023 sw sp,0(tp) # 80008000 8000003c: 0000a183 lw gp,0(ra) -80000040: 24311c63 bne sp,gp,80000298 +80000040: 30311663 bne sp,gp,8000034c 80000044: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000048: 24311863 bne sp,gp,80000298 +80000048: 30311263 bne sp,gp,8000034c 8000004c: 071202b7 lui t0,0x7120 80000050: 3a029073 csrw pmpcfg0,t0 80000054: 3a002373 csrr t1,pmpcfg0 -80000058: 24629063 bne t0,t1,80000298 +80000058: 2e629a63 bne t0,t1,8000034c 8000005c: 191f02b7 lui t0,0x191f0 80000060: 30428293 addi t0,t0,772 # 191f0304 <_start-0x66e0fcfc> 80000064: 3a129073 csrw pmpcfg1,t0 -80000068: 000f02b7 lui t0,0xf0 -8000006c: 50628293 addi t0,t0,1286 # f0506 <_start-0x7ff0fafa> +80000068: 000f12b7 lui t0,0xf1 +8000006c: 90a28293 addi t0,t0,-1782 # f090a <_start-0x7ff0f6f6> 80000070: 3a229073 csrw pmpcfg2,t0 80000074: 0f1e22b7 lui t0,0xf1e2 80000078: 90028293 addi t0,t0,-1792 # f1e1900 <_start-0x70e1e700> @@ -44,7 +44,7 @@ Disassembly of section .crt_section: 80000080: 200002b7 lui t0,0x20000 80000084: 3b029073 csrw pmpaddr0,t0 80000088: 3b002373 csrr t1,pmpaddr0 -8000008c: 20629663 bne t0,t1,80000298 +8000008c: 2c629063 bne t0,t1,8000034c 80000090: fff00293 li t0,-1 80000094: 3b129073 csrw pmpaddr1,t0 80000098: 200022b7 lui t0,0x20002 @@ -85,119 +85,166 @@ Disassembly of section .crt_section: 80000124: 0020a023 sw sp,0(ra) 80000128: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> 8000012c: 0000a183 lw gp,0(ra) -80000130: 16311463 bne sp,gp,80000298 +80000130: 20311e63 bne sp,gp,8000034c 80000134: 00000193 li gp,0 80000138: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -8000013c: 14311e63 bne sp,gp,80000298 +8000013c: 20311863 bne sp,gp,8000034c 80000140 : 80000140: 00100e13 li t3,1 80000144: 00000f17 auipc t5,0x0 -80000148: 154f0f13 addi t5,t5,340 # 80000298 +80000148: 208f0f13 addi t5,t5,520 # 8000034c 8000014c: 079212b7 lui t0,0x7921 80000150: 80828293 addi t0,t0,-2040 # 7920808 <_start-0x786df7f8> 80000154: 3a029073 csrw pmpcfg0,t0 80000158: 3a002373 csrr t1,pmpcfg0 -8000015c: 12629e63 bne t0,t1,80000298 +8000015c: 1e629863 bne t0,t1,8000034c 80000160: 800080b7 lui ra,0x80008 80000164: deadc137 lui sp,0xdeadc -80000168: eef10113 addi sp,sp,-273 # deadbeef -8000016c: 0020a023 sw sp,0(ra) # 80008000 +80000168: eef10113 addi sp,sp,-273 # deadbeef +8000016c: 0020a023 sw sp,0(ra) # 80008000 80000170: 00000f17 auipc t5,0x0 80000174: 010f0f13 addi t5,t5,16 # 80000180 80000178: 0000a183 lw gp,0(ra) -8000017c: 11c0006f j 80000298 +8000017c: 1d00006f j 8000034c 80000180 : 80000180: 00200e13 li t3,2 80000184: 00000f17 auipc t5,0x0 -80000188: 114f0f13 addi t5,t5,276 # 80000298 +80000188: 1c8f0f13 addi t5,t5,456 # 8000034c 8000018c: 071202b7 lui t0,0x7120 80000190: 3a029073 csrw pmpcfg0,t0 80000194: 3a002373 csrr t1,pmpcfg0 -80000198: 3b205073 csrwi pmpaddr2,0 -8000019c: 3b202373 csrr t1,pmpaddr2 -800001a0: 0e030c63 beqz t1,80000298 -800001a4: 0e628a63 beq t0,t1,80000298 -800001a8: 800080b7 lui ra,0x80008 -800001ac: deadc137 lui sp,0xdeadc -800001b0: eef10113 addi sp,sp,-273 # deadbeef -800001b4: 0020a023 sw sp,0(ra) # 80008000 -800001b8: 00000f17 auipc t5,0x0 -800001bc: 010f0f13 addi t5,t5,16 # 800001c8 -800001c0: 0000a183 lw gp,0(ra) -800001c4: 0d40006f j 80000298 +80000198: 1a628a63 beq t0,t1,8000034c +8000019c: 200042b7 lui t0,0x20004 +800001a0: fff28293 addi t0,t0,-1 # 20003fff <_start-0x5fffc001> +800001a4: 3b305073 csrwi pmpaddr3,0 +800001a8: 3b302373 csrr t1,pmpaddr3 +800001ac: 1a031063 bnez t1,8000034c +800001b0: 18628e63 beq t0,t1,8000034c +800001b4: 200022b7 lui t0,0x20002 +800001b8: 3b205073 csrwi pmpaddr2,0 +800001bc: 3b202373 csrr t1,pmpaddr2 +800001c0: 18030663 beqz t1,8000034c +800001c4: 18629463 bne t0,t1,8000034c +800001c8: 800080b7 lui ra,0x80008 +800001cc: deadc137 lui sp,0xdeadc +800001d0: eef10113 addi sp,sp,-273 # deadbeef +800001d4: 0020a023 sw sp,0(ra) # 80008000 +800001d8: 00000f17 auipc t5,0x0 +800001dc: 010f0f13 addi t5,t5,16 # 800001e8 +800001e0: 0000a183 lw gp,0(ra) +800001e4: 1680006f j 8000034c -800001c8 : -800001c8: 00300e13 li t3,3 -800001cc: 00000f17 auipc t5,0x0 -800001d0: 0ccf0f13 addi t5,t5,204 # 80000298 -800001d4: 00000117 auipc sp,0x0 -800001d8: 01010113 addi sp,sp,16 # 800001e4 -800001dc: 34111073 csrw mepc,sp -800001e0: 30200073 mret +800001e8 : +800001e8: 00300e13 li t3,3 +800001ec: 00000f17 auipc t5,0x0 +800001f0: 160f0f13 addi t5,t5,352 # 8000034c +800001f4: 00ff02b7 lui t0,0xff0 +800001f8: 3b32a073 csrs pmpaddr3,t0 +800001fc: 3b302373 csrr t1,pmpaddr3 +80000200: 14629663 bne t0,t1,8000034c +80000204: 0ff00293 li t0,255 +80000208: 3b32a073 csrs pmpaddr3,t0 +8000020c: 3b302373 csrr t1,pmpaddr3 +80000210: 00ff02b7 lui t0,0xff0 +80000214: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +80000218: 12629a63 bne t0,t1,8000034c +8000021c: 00ff02b7 lui t0,0xff0 +80000220: 3b32b073 csrc pmpaddr3,t0 +80000224: 3b302373 csrr t1,pmpaddr3 +80000228: 0ff00293 li t0,255 +8000022c: 12629063 bne t0,t1,8000034c +80000230: 00ff02b7 lui t0,0xff0 +80000234: 0ff28293 addi t0,t0,255 # ff00ff <_start-0x7f00ff01> +80000238: 3a02b073 csrc pmpcfg0,t0 +8000023c: 3a002373 csrr t1,pmpcfg0 +80000240: 079202b7 lui t0,0x7920 +80000244: 10629463 bne t0,t1,8000034c +80000248: 00ff02b7 lui t0,0xff0 +8000024c: 70728293 addi t0,t0,1799 # ff0707 <_start-0x7f00f8f9> +80000250: 3a02a073 csrs pmpcfg0,t0 +80000254: 3a002373 csrr t1,pmpcfg0 +80000258: 079202b7 lui t0,0x7920 +8000025c: 70728293 addi t0,t0,1799 # 7920707 <_start-0x786df8f9> +80000260: 0e629663 bne t0,t1,8000034c -800001e4 : -800001e4: 00400e13 li t3,4 -800001e8: 00000f17 auipc t5,0x0 -800001ec: 0b0f0f13 addi t5,t5,176 # 80000298 -800001f0: deadc137 lui sp,0xdeadc -800001f4: eef10113 addi sp,sp,-273 # deadbeef -800001f8: 800080b7 lui ra,0x80008 -800001fc: 0020a023 sw sp,0(ra) # 80008000 -80000200: 00000f17 auipc t5,0x0 -80000204: 010f0f13 addi t5,t5,16 # 80000210 -80000208: 0000a183 lw gp,0(ra) -8000020c: 08c0006f j 80000298 - -80000210 : -80000210: 00500e13 li t3,5 -80000214: deadc137 lui sp,0xdeadc -80000218: eef10113 addi sp,sp,-273 # deadbeef -8000021c: 800000b7 lui ra,0x80000 -80000220: 0020a023 sw sp,0(ra) # 80000000 -80000224: 0000a183 lw gp,0(ra) -80000228: 06311863 bne sp,gp,80000298 - -8000022c : -8000022c: 00600e13 li t3,6 -80000230: 800100b7 lui ra,0x80010 -80000234: 0000a183 lw gp,0(ra) # 80010000 -80000238: 00000f17 auipc t5,0x0 -8000023c: 06cf0f13 addi t5,t5,108 # 800002a4 -80000240: 0030a023 sw gp,0(ra) -80000244: 0540006f j 80000298 - -80000248 : -80000248: 00700e13 li t3,7 -8000024c: 00000f17 auipc t5,0x0 -80000250: 04cf0f13 addi t5,t5,76 # 80000298 -80000254: deadc137 lui sp,0xdeadc -80000258: eef10113 addi sp,sp,-273 # deadbeef -8000025c: 800300b7 lui ra,0x80030 -80000260: ff808093 addi ra,ra,-8 # 8002fff8 -80000264: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> +80000264 : +80000264: 00400e13 li t3,4 80000268: 00000f17 auipc t5,0x0 -8000026c: fa8f0f13 addi t5,t5,-88 # 80000210 -80000270: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> -80000274: 0240006f j 80000298 +8000026c: 0e4f0f13 addi t5,t5,228 # 8000034c +80000270: 00000117 auipc sp,0x0 +80000274: 01010113 addi sp,sp,16 # 80000280 +80000278: 34111073 csrw mepc,sp +8000027c: 30200073 mret -80000278 : -80000278: 00800e13 li t3,8 -8000027c: 800400b7 lui ra,0x80040 -80000280: ff808093 addi ra,ra,-8 # 8003fff8 -80000284: 0000a183 lw gp,0(ra) -80000288: 00000f17 auipc t5,0x0 -8000028c: 01cf0f13 addi t5,t5,28 # 800002a4 -80000290: 0030a023 sw gp,0(ra) -80000294: 0040006f j 80000298 +80000280 : +80000280: 00500e13 li t3,5 +80000284: 00000f17 auipc t5,0x0 +80000288: 0c8f0f13 addi t5,t5,200 # 8000034c +8000028c: deadc137 lui sp,0xdeadc +80000290: eef10113 addi sp,sp,-273 # deadbeef +80000294: 800080b7 lui ra,0x80008 +80000298: 0020a023 sw sp,0(ra) # 80008000 +8000029c: 00000f17 auipc t5,0x0 +800002a0: 010f0f13 addi t5,t5,16 # 800002ac +800002a4: 0000a183 lw gp,0(ra) +800002a8: 0a40006f j 8000034c -80000298 : -80000298: f0100137 lui sp,0xf0100 -8000029c: f2410113 addi sp,sp,-220 # f00fff24 -800002a0: 01c12023 sw t3,0(sp) +800002ac : +800002ac: 00600e13 li t3,6 +800002b0: 00000f17 auipc t5,0x0 +800002b4: 09cf0f13 addi t5,t5,156 # 8000034c +800002b8: deadc137 lui sp,0xdeadc +800002bc: eef10113 addi sp,sp,-273 # deadbeef +800002c0: 800000b7 lui ra,0x80000 +800002c4: 0020a023 sw sp,0(ra) # 80000000 +800002c8: 0000a183 lw gp,0(ra) +800002cc: 08311063 bne sp,gp,8000034c -800002a4 : -800002a4: f0100137 lui sp,0xf0100 -800002a8: f2010113 addi sp,sp,-224 # f00fff20 -800002ac: 00012023 sw zero,0(sp) +800002d0 : +800002d0: 00700e13 li t3,7 +800002d4: 00000f17 auipc t5,0x0 +800002d8: 078f0f13 addi t5,t5,120 # 8000034c +800002dc: 800400b7 lui ra,0x80040 +800002e0: 0000a183 lw gp,0(ra) # 80040000 +800002e4: 00000f17 auipc t5,0x0 +800002e8: 074f0f13 addi t5,t5,116 # 80000358 +800002ec: 0030a023 sw gp,0(ra) +800002f0: 05c0006f j 8000034c + +800002f4 : +800002f4: 00800e13 li t3,8 +800002f8: 00000f17 auipc t5,0x0 +800002fc: 054f0f13 addi t5,t5,84 # 8000034c +80000300: deadc137 lui sp,0xdeadc +80000304: eef10113 addi sp,sp,-273 # deadbeef +80000308: 800300b7 lui ra,0x80030 +8000030c: ff808093 addi ra,ra,-8 # 8002fff8 +80000310: 00222023 sw sp,0(tp) # 0 <_start-0x80000000> +80000314: 00000f17 auipc t5,0x0 +80000318: 010f0f13 addi t5,t5,16 # 80000324 +8000031c: 00022183 lw gp,0(tp) # 0 <_start-0x80000000> +80000320: 02c0006f j 8000034c + +80000324 : +80000324: 00900e13 li t3,9 +80000328: 00000f17 auipc t5,0x0 +8000032c: 024f0f13 addi t5,t5,36 # 8000034c +80000330: 800400b7 lui ra,0x80040 +80000334: ff808093 addi ra,ra,-8 # 8003fff8 +80000338: 0000a183 lw gp,0(ra) +8000033c: 00000f17 auipc t5,0x0 +80000340: 01cf0f13 addi t5,t5,28 # 80000358 +80000344: 0030a023 sw gp,0(ra) +80000348: 0040006f j 8000034c + +8000034c : +8000034c: f0100137 lui sp,0xf0100 +80000350: f2410113 addi sp,sp,-220 # f00fff24 +80000354: 01c12023 sw t3,0(sp) + +80000358 : +80000358: f0100137 lui sp,0xf0100 +8000035c: f2010113 addi sp,sp,-224 # f00fff20 +80000360: 00012023 sw zero,0(sp) diff --git a/src/test/cpp/raw/pmp/build/pmp.elf b/src/test/cpp/raw/pmp/build/pmp.elf index b844a20..68e30ea 100755 Binary files a/src/test/cpp/raw/pmp/build/pmp.elf and b/src/test/cpp/raw/pmp/build/pmp.elf differ diff --git a/src/test/cpp/raw/pmp/build/pmp.hex b/src/test/cpp/raw/pmp/build/pmp.hex index 8197935..5dc92f6 100644 --- a/src/test/cpp/raw/pmp/build/pmp.hex +++ b/src/test/cpp/raw/pmp/build/pmp.hex @@ -1,13 +1,13 @@ :0200000480007A :100000009700000093800001739050306F00C00093 :1000100073101F3473002030130E0000170F000000 -:10002000130FCF27B70000803782008037C1ADDEC5 +:10002000130F0F33B70000803782008037C1ADDE79 :100030001301F1EE23A020002320220083A1000061 -:10004000631C31248321020063183124B702120794 -:100050007390023A7323003A63906224B7021F1927 -:10006000938242307390123AB7020F00938262502B +:10004000631631308321020063123130B702120788 +:100050007390023A7323003A639A622EB7021F1913 +:10006000938242307390123AB7120F009382A2909B :100070007390223AB7221E0F938202907390323A05 -:10008000B70200207390023B7323003B639662200B +:10008000B70200207390023B7323003B6390622C05 :100090009302F0FF7390123BB72200207390223B33 :1000A000B74200209382F2FF7390323BB7420020A8 :1000B0009382F2FF7390423BB74200209382F2FF9B @@ -18,29 +18,41 @@ :100100007390C23B930200007390D23B93020000B5 :100110007390E23B930200007390F23B3701C10001 :100120001301E1FE23A020002320220083A1000070 -:10013000631431169301000083210200631E311401 -:10014000130E1000170F0000130F4F15B712920770 -:10015000938282807390023A7323003A639E621204 +:10013000631E3120930100008321020063183120E7 +:10014000130E1000170F0000130F8F20B712920725 +:10015000938282807390023A7323003A6398621EFE :10016000B780008037C1ADDE1301F1EE23A020007F -:10017000170F0000130F0F0183A100006F00C011C3 -:10018000130E2000170F0000130F4F11B7021207B4 -:100190007390023A7323003A7350203B7323203B41 -:1001A000630C030E638A620EB780008037C1ADDE38 -:1001B0001301F1EE23A02000170F0000130F0F0111 -:1001C00083A100006F00400D130E3000170F0000D8 -:1001D000130FCF0C1701000013010101731011342C -:1001E00073002030130E4000170F0000130F0F0B89 -:1001F00037C1ADDE1301F1EEB780008023A02000EF -:10020000170F0000130F0F0183A100006F00C0083B -:10021000130E500037C1ADDE1301F1EEB7000080C0 -:1002200023A0200083A1000063183106130E600094 -:10023000B700018083A10000170F0000130FCF0645 -:1002400023A030006F004005130E7000170F000050 -:10025000130FCF0437C1ADDE1301F1EEB7000380F9 -:10026000938080FF23202200170F0000130F8FFAC6 -:10027000832102006F004002130E8000B70004804B -:10028000938080FF83A10000170F0000130FCF01A0 -:1002900023A030006F004000370110F0130141F23D -:1002A0002320C101370110F0130101F223200100C6 +:10017000170F0000130F0F0183A100006F00001D77 +:10018000130E2000170F0000130F8F1CB702120769 +:100190007390023A7323003A638A621AB7420020CE +:1001A0009382F2FF7350303B7323303B6310031A8A +:1001B000638E6218B72200207350203B7323203BCC +:1001C0006306031863946218B780008037C1ADDE00 +:1001D0001301F1EE23A02000170F0000130F0F01F1 +:1001E00083A100006F008016130E3000170F00006F +:1001F000130F0F16B702FF0073A0323B7323303B7F +:10020000639662149302F00F73A0323B7323303B6A +:10021000B702FF009382F20F639A6212B702FF00E7 +:1002200073B0323B7323303B9302F00F6390621242 +:10023000B702FF009382F20F73B0023A7323003AC1 +:10024000B702920763946210B702FF009382727044 +:1002500073A0023A7323003AB70292079382727036 +:100260006396620E130E4000170F0000130F4F0E1F +:1002700017010000130101017310113473002030C5 +:10028000130E5000170F0000130F8F0C37C1ADDE97 +:100290001301F1EEB780008023A02000170F0000AB +:1002A000130F0F0183A100006F00400A130E6000BE +:1002B000170F0000130FCF0937C1ADDE1301F1EEA8 +:1002C000B700008023A0200083A100006310310844 +:1002D000130E7000170F0000130F8F07B700048074 +:1002E00083A10000170F0000130F4F0723A0300059 +:1002F0006F00C005130E8000170F0000130F4F058D +:1003000037C1ADDE1301F1EEB7000380938080FFAB +:1003100023202200170F0000130F0F01832102007A +:100320006F00C002130E9000170F0000130F4F0252 +:10033000B7000480938080FF83A10000170F0000A6 +:10034000130FCF0123A030006F004000370110F0E1 +:10035000130141F22320C101370110F0130101F212 +:040360002320010055 :040000058000000077 :00000001FF diff --git a/src/test/cpp/raw/pmp/build/pmp.map b/src/test/cpp/raw/pmp/build/pmp.map index 2a01820..f2e88d8 100644 --- a/src/test/cpp/raw/pmp/build/pmp.map +++ b/src/test/cpp/raw/pmp/build/pmp.map @@ -8,28 +8,28 @@ onChipRam 0x0000000080000000 0x0000000000020000 w !xr Linker script and memory map LOAD build/src/crt.o -LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a +LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/rv32i/ilp32/libgcc.a START GROUP -LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/lib/libc.a -LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/../../../../riscv64-unknown-elf/lib/libgloss.a +LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/lib/rv32i/ilp32/libc.a +LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/lib/rv32i/ilp32/libgloss.a END GROUP -LOAD /opt/riscv/lib/gcc/riscv64-unknown-elf/10.2.0/libgcc.a +LOAD /opt/riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/rv32i/ilp32/libgcc.a -.crt_section 0x0000000080000000 0x2b0 +.crt_section 0x0000000080000000 0x364 0x0000000080000000 . = ALIGN (0x4) *crt.o(.text) - .text 0x0000000080000000 0x2b0 build/src/crt.o + .text 0x0000000080000000 0x364 build/src/crt.o 0x0000000080000000 _start 0x0000000080000010 trap OUTPUT(build/pmp.elf elf32-littleriscv) -.data 0x00000000800002b0 0x0 - .data 0x00000000800002b0 0x0 build/src/crt.o +.data 0x0000000080000364 0x0 + .data 0x0000000080000364 0x0 build/src/crt.o -.bss 0x00000000800002b0 0x0 - .bss 0x00000000800002b0 0x0 build/src/crt.o +.bss 0x0000000080000364 0x0 + .bss 0x0000000080000364 0x0 build/src/crt.o .riscv.attributes - 0x0000000000000000 0x1e + 0x0000000000000000 0x1a .riscv.attributes - 0x0000000000000000 0x1e build/src/crt.o + 0x0000000000000000 0x1a build/src/crt.o diff --git a/src/test/cpp/raw/pmp/src/crt.S b/src/test/cpp/raw/pmp/src/crt.S index 76ee02f..089500a 100644 --- a/src/test/cpp/raw/pmp/src/crt.S +++ b/src/test/cpp/raw/pmp/src/crt.S @@ -8,15 +8,15 @@ #define TRAP_RA x30 #define PMPCFG0 0x07120000 -#define PMPCFG0_ 0x07920808 // locked +#define PMPCFG0_ 0x07920808 #define PMPCFG1 0x191f0304 -#define PMPCFG2 0x000f0506 +#define PMPCFG2 0x000f090a #define PMPCFG3 0x0f1e1900 -#define PMPADDR0 0x20000000 // OFF -#define PMPADDR1 0xffffffff // OFF +#define PMPADDR0 0x20000000 // OFF (test0) -> TOR (test1) -> OFF (test2) +#define PMPADDR1 0xffffffff // OFF (test0) -> TOR (test1) -> OFF (test2) #define PMPADDR2 0x20002000 // NA4 W -#define PMPADDR3 0x20003fff // OFF RWX +#define PMPADDR3 0x20003fff // OFF RWX -> 0x00000000 OFF RWX (test2) #define PMPADDR4 0x20003fff // OFF X #define PMPADDR5 0x20003fff // OFF RW #define PMPADDR6 0x20001fff // NAPOT RWX @@ -132,10 +132,17 @@ test2: li x5, PMPCFG0 csrw pmpcfg0, x5 // "unlock" region 2 csrr x6, pmpcfg0 + beq x5, x6, fail + li x5, PMPADDR3 + csrwi pmpaddr3, 0x0 + csrr x6, pmpaddr3 + bnez x6, fail + beq x5, x6, fail + li x5, PMPADDR2 csrwi pmpaddr2, 0x0 csrr x6, pmpaddr2 - beqz x6, fail - beq x5, x6, fail + beqz x6, fail + bne x5, x6, fail li x1, 0x80008000 li x2, 0xdeadbeef sw x2, 0x0(x1) // should still be OK (write 0x80008000) @@ -143,54 +150,86 @@ test2: lw x3, 0x0(x1) // should still fault (read 0x80008000) j fail -// jump into user mode +// verify masked CSR read/write operations test3: li TEST_ID, 3 la TRAP_RA, fail - la x2, test4 + li x5, 0x00ff0000 + csrs pmpaddr3, x5 + csrr x6, pmpaddr3 + bne x5, x6, fail + li x5, 0x000000ff + csrs pmpaddr3, x5 + csrr x6, pmpaddr3 + li x5, 0x00ff00ff + bne x5, x6, fail + li x5, 0x00ff0000 + csrc pmpaddr3, x5 + csrr x6, pmpaddr3 + li x5, 0x000000ff + bne x5, x6, fail + li x5, 0x00ff00ff + csrc pmpcfg0, x5 + csrr x6, pmpcfg0 + li x5, 0x07920000 + bne x5, x6, fail + li x5, 0x00ff0707 + csrs pmpcfg0, x5 + csrr x6, pmpcfg0 + li x5, 0x07920707 + bne x5, x6, fail + +// jump into user mode +test4: + li TEST_ID, 4 + la TRAP_RA, fail + la x2, test5 csrw mepc, x2 mret // attempt to read/write region 2 from user mode -test4: - li TEST_ID, 4 +test5: + li TEST_ID, 5 la TRAP_RA, fail li x2, 0xdeadbeef li x1, 0x80008000 sw x2, 0x0(x1) // should be OK (write 0x80008000) - la TRAP_RA, test5 + la TRAP_RA, test6 lw x3, 0x0(x1) // should fault (read 0x80008000) j fail // attempt to read/write other regions from user mode -test5: - li TEST_ID, 5 +test6: + li TEST_ID, 6 + la TRAP_RA, fail li x2, 0xdeadbeef li x1, 0x80000000 sw x2, 0x0(x1) lw x3, 0x0(x1) bne x2, x3, fail // should be OK (read/write 0x80000000) -test6: - li TEST_ID, 6 - li x1, 0x80010000 - lw x3, 0x0(x1) // should be OK (read 0x80010000) - la TRAP_RA, pass - sw x3, 0x0(x1) // should fault (write 0x80010000) - j fail - test7: li TEST_ID, 7 + la TRAP_RA, fail + li x1, 0x80040000 + lw x3, 0x0(x1) // should be OK (read 0x80040000) + la TRAP_RA, pass + sw x3, 0x0(x1) // should fault (write 0x80040000) + j fail + +test8: + li TEST_ID, 8 la TRAP_RA, fail li x2, 0xdeadbeef li x1, 0x8002fff8 sw x2, 0x0(x4) // should be OK (write 0x8002fff8) - la TRAP_RA, test5 + la TRAP_RA, test9 lw x3, 0x0(x4) // should fault (read 0x8002fff8) j fail -test8: - li TEST_ID, 8 +test9: + li TEST_ID, 9 + la TRAP_RA, fail li x1, 0x8003fff8 lw x3, 0x0(x1) // should be OK (read 0x8003fff8) la TRAP_RA, pass