diff --git a/backends/instructions_appendix/all_instructions.golden.adoc b/backends/instructions_appendix/all_instructions.golden.adoc index 8aab83aa5..7357633dd 100644 --- a/backends/instructions_appendix/all_instructions.golden.adoc +++ b/backends/instructions_appendix/all_instructions.golden.adoc @@ -11513,6 +11513,78 @@ Included in:: |=== +[#udb:doc:inst:cm_jalt] +== cm.jalt + +Synopsis:: +Jump Via Table with Optional Link + +Assembly:: +cm.jalt index + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":2,"name": 0x2,"type":2},{"bits":8,"name": "index != {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}","type":4},{"bits":6,"name": 0x28,"type":2}]} +.... + +Description:: +Read an address from the Jump Vector Table and jump to it, linking to `ra`. + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|index |$encoding[9:2] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zcmt* | ~> 1.0.0 + +|=== + + +[#udb:doc:inst:cm_jt] +== cm.jt + +Synopsis:: +Jump Via Table + +Assembly:: +cm.jt index + +Encoding:: +[wavedrom, ,svg,subs='attributes',width="100%"] +.... +{"reg":[{"bits":2,"name": 0x2,"type":2},{"bits":5,"name": "index","type":4},{"bits":9,"name": 0x140,"type":2}]} +.... + +Description:: +Read an address from the Jump Vector Table and jump to it. + + +Decode Variables:: +[width="100%", cols="1,2", options="header"] +|=== +|Variable Name |Location +|index |$encoding[6:2] +|=== + +Included in:: +[options="autowrap,autowidth"] +|=== +| Extension | Version + +| *Zcmt* | ~> 1.0.0 + +|=== + + [#udb:doc:inst:cm_mva01s] == cm.mva01s diff --git a/spec/std/isa/csr/jvt.yaml b/spec/std/isa/csr/jvt.yaml index 890bdfc06..fbbc7c0c6 100644 --- a/spec/std/isa/csr/jvt.yaml +++ b/spec/std/isa/csr/jvt.yaml @@ -46,25 +46,19 @@ fields: } reset_value: UNDEFINED_LEGAL sw_write(csr_value): | - if ((mode() != PrivilegeMode::M) && implemented?(ExtensionName::Smstateen)) { - if (CSR[mstateen0].JVT == 1'b0) { - unimplemented_csr($encoding); - } - } - else if ((mode() == PrivilegeMode::U) && implemented?(ExtensionName::Ssstateen)) { - if (CSR[sstateen0].JVT == 1'b0) { - unimplemented_csr($encoding); - } - } - else if ((mode() == PrivilegeMode::VS) && implemented?(ExtensionName::Ssstateen)) { - if (CSR[hstateen0].JVT == 1'b0) { - unimplemented_csr($encoding); - } - } - else if ((mode() == PrivilegeMode::VU) && implemented?(ExtensionName::Ssstateen)) { - if ((CSR[sstateen0].JVT == 1'b0) || (CSR[hstateen0].JVT == 1'b0)) { - unimplemented_csr($encoding); - } + if (( mode() != PrivilegeMode::M && implemented?(ExtensionName::Smstateen) + && CSR[mstateen0].JVT == 1'b0 ) + || + ( mode() == PrivilegeMode::U && implemented?(ExtensionName::Ssstateen) + && CSR[sstateen0].JVT == 1'b0 ) + || + ( mode() == PrivilegeMode::VS && implemented?(ExtensionName::Ssstateen) + && CSR[hstateen0].JVT == 1'b0 ) + || + ( mode() == PrivilegeMode::VU && implemented?(ExtensionName::Ssstateen) + && (CSR[sstateen0].JVT == 1'b0 || CSR[hstateen0].JVT == 1'b0) )) { + + unimplemented_csr($encoding); } else { if (JVT_BASE_TYPE == "custom") { @@ -94,28 +88,4 @@ fields: } return 0; sw_read(): | - # If the Smstateen extension is implemented, then bit 2 in `mstateen0`, `sstateen0`, and `hstateen0` is - # implemented. If bit 2 of a controlling `stateen0` CSR is zero, then access to the `jvt` CSR and execution - # of a `cm.jalt` or `cm.jt` instruction by a lower privilege level results in an illegal-instruction trap (or, if - # appropriate, a virtual-instruction trap). - - if ((mode() != PrivilegeMode::M) && implemented?(ExtensionName::Smstateen)) { - if (CSR[mstateen0].JVT == 1'b0) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } - } - else if ((mode() == PrivilegeMode::U) && implemented?(ExtensionName::Ssstateen)) { - if (CSR[sstateen0].JVT == 1'b0) { - raise(ExceptionCode::IllegalInstruction, mode(), $encoding); - } - } - else if ((mode() == PrivilegeMode::VS) && implemented?(ExtensionName::Ssstateen)) { - if (CSR[hstateen0].JVT == 1'b0) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } - } - else if ((mode() == PrivilegeMode::VU) && implemented?(ExtensionName::Ssstateen)) { - if ((CSR[sstateen0].JVT == 1'b0) || (CSR[hstateen0].JVT == 1'b0)) { - raise(ExceptionCode::VirtualInstruction, mode(), $encoding); - } - } + check_zcmt_enabled($encoding); diff --git a/spec/std/isa/inst/Zcmt/cm.jalt.yaml b/spec/std/isa/inst/Zcmt/cm.jalt.yaml new file mode 100644 index 000000000..770901013 --- /dev/null +++ b/spec/std/isa/inst/Zcmt/cm.jalt.yaml @@ -0,0 +1,63 @@ +# Copyright (c) Ventana Micro Systems +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: cm.jalt +long_name: Jump Via Table with Optional Link +description: | + Read an address from the Jump Vector Table and jump to it, linking to `ra`. +definedBy: Zcmt +assembly: index +encoding: + match: 101000--------10 + variables: + - name: index + location: 9-2 + # prettier-ignore + not: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 ] +access: + s: always + u: always + vs: always + vu: always +operation(): | + # Ensure JVT readable + check_zcmt_enabled($encoding); + + if (CSR[jvt].MODE != 0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + # Skip over _this_ 16-bit instruction + XReg return_addr = $pc + 2; + X[1] = return_addr; + + XReg jump_table_base = { CSR[jvt].BASE, 6'b000000 }; + XReg virtual_address = jump_table_base + index `* (xlen() / 8); + XReg addr; + TranslationResult result; + + # TODO: Correct this check when we figure out what MISA can do + if (CSR[misa].S == 1) { + result = translate(virtual_address, MemoryOperation::Fetch, mode(), $encoding); + } else { + result.paddr = virtual_address; + } + + # may raise an exception + access_check(result.paddr, xlen(), $pc, MemoryOperation::Fetch, ExceptionCode::InstructionAccessFault, mode()); + + if (xlen() == 32) { + addr = read_physical_memory<32>(result.paddr); + } else { + addr = read_physical_memory<64>(result.paddr); + } # Ensure low-order bit is clear + + addr = addr & $signed(2'b10); + + jump(addr); + +sail(): | diff --git a/spec/std/isa/inst/Zcmt/cm.jt.yaml b/spec/std/isa/inst/Zcmt/cm.jt.yaml new file mode 100644 index 000000000..4fb59de7e --- /dev/null +++ b/spec/std/isa/inst/Zcmt/cm.jt.yaml @@ -0,0 +1,58 @@ +# Copyright (c) Ventana Micro Systems +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../../../schemas/inst_schema.json + +$schema: "inst_schema.json#" +kind: instruction +name: cm.jt +long_name: Jump Via Table +description: | + Read an address from the Jump Vector Table and jump to it. +definedBy: Zcmt +assembly: index +encoding: + match: 101000000-----10 + variables: + - name: index + location: 6-2 +access: + s: always + u: always + vs: always + vu: always +operation(): | + # Ensure JVT readable + check_zcmt_enabled($encoding); + + if (CSR[jvt].MODE != 0) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg jump_table_base = { CSR[jvt].BASE, 6'b000000 }; + XReg virtual_address = jump_table_base + index `* (xlen() / 8); + XReg addr; + TranslationResult result; + + # TODO: Correct this check when we figure out what MISA can do + if (CSR[misa].S == 1) { + result = translate(virtual_address, MemoryOperation::Fetch, mode(), $encoding); + } else { + result.paddr = virtual_address; + } + + # may raise an exception + access_check(result.paddr, xlen(), $pc, MemoryOperation::Fetch, ExceptionCode::InstructionAccessFault, mode()); + + if (xlen() == 32) { + addr = read_physical_memory<32>(result.paddr); + } else { + addr = read_physical_memory<64>(result.paddr); + } + + # Ensure low-order bit is clear + addr = addr & $signed(2'b10); + + jump(addr); + +sail(): | diff --git a/spec/std/isa/isa/globals.isa b/spec/std/isa/isa/globals.isa index 9afd483a5..e08e1cd1a 100644 --- a/spec/std/isa/isa/globals.isa +++ b/spec/std/isa/isa/globals.isa @@ -3062,3 +3062,33 @@ function mstatus_sd_reset_value return ((fs_value == 3) || (vs_value == 3)) ? 1 : 0; } } + +function check_zcmt_enabled { + arguments + Bits encoding + description { + If the Smstateen extension is implemented, then bit 2 in `mstateen0`, `sstateen0`, and `hstateen0` is + implemented. If bit 2 of a controlling `stateen0` CSR is zero, then access to the `jvt` CSR and execution + of a `cm.jalt` or `cm.jt` instruction by a lower privilege level results in an illegal-instruction trap (or, if + appropriate, a virtual-instruction trap). + } + body { + if (( mode() != PrivilegeMode::M && implemented?(ExtensionName::Smstateen) + && CSR[mstateen0].JVT == 1'b0 ) + || + ( mode() == PrivilegeMode::U && implemented?(ExtensionName::Ssstateen) + && CSR[sstateen0].JVT == 1'b0 )) { + + raise(ExceptionCode::IllegalInstruction, mode(), encoding); + } + else + if (( mode() == PrivilegeMode::VS && implemented?(ExtensionName::Ssstateen) + && CSR[hstateen0].JVT == 1'b0 ) + || + ( mode() == PrivilegeMode::VU && implemented?(ExtensionName::Ssstateen) + && (CSR[sstateen0].JVT == 1'b0 || CSR[hstateen0].JVT == 1'b0) )) { + + raise(ExceptionCode::VirtualInstruction, mode(), encoding); + } + } +}