From 0151a2ca3dfd929ef1737bc4116609503a33d08c Mon Sep 17 00:00:00 2001 From: Albert Yosher Date: Tue, 12 Nov 2024 18:23:46 +0200 Subject: [PATCH] Add C extension --- arch/ext/C.yaml | 6 ++++ arch/inst/C/c.add.yaml | 36 ++++++++++++++++++++ arch/inst/C/c.addi.yaml | 35 ++++++++++++++++++++ arch/inst/C/c.addi16sp.yaml | 33 +++++++++++++++++++ arch/inst/C/c.addi4spn.yaml | 35 ++++++++++++++++++++ arch/inst/C/c.addiw.yaml | 35 ++++++++++++++++++++ arch/inst/C/c.addw.yaml | 45 +++++++++++++++++++++++++ arch/inst/C/c.and.yaml | 55 +++++++++++++++++++++++++++++++ arch/inst/C/c.andi.yaml | 44 +++++++++++++++++++++++++ arch/inst/C/c.beqz.yaml | 65 +++++++++++++++++++++++++++++++++++++ arch/inst/C/c.bnez.yaml | 65 +++++++++++++++++++++++++++++++++++++ arch/inst/C/c.ebreak.yaml | 44 +++++++++++++++++++++++++ arch/inst/C/c.fld.yaml | 37 +++++++++++++++++++++ arch/inst/C/c.fldsp.yaml | 38 ++++++++++++++++++++++ arch/inst/C/c.flw.yaml | 37 +++++++++++++++++++++ arch/inst/C/c.flwsp.yaml | 38 ++++++++++++++++++++++ arch/inst/C/c.fsd.yaml | 37 +++++++++++++++++++++ arch/inst/C/c.fsdsp.yaml | 38 ++++++++++++++++++++++ arch/inst/C/c.fsw.yaml | 37 +++++++++++++++++++++ arch/inst/C/c.fswsp.yaml | 38 ++++++++++++++++++++++ arch/inst/C/c.j.yaml | 30 +++++++++++++++++ arch/inst/C/c.jal.yaml | 34 +++++++++++++++++++ arch/inst/C/c.jalr.yaml | 32 ++++++++++++++++++ arch/inst/C/c.jr.yaml | 29 +++++++++++++++++ arch/inst/C/c.ld.yaml | 65 +++++++++++++++++++++++++++++++++++++ arch/inst/C/c.ldsp.yaml | 39 ++++++++++++++++++++++ arch/inst/C/c.li.yaml | 33 +++++++++++++++++++ arch/inst/C/c.lq.yaml | 37 +++++++++++++++++++++ arch/inst/C/c.lqsp.yaml | 38 ++++++++++++++++++++++ arch/inst/C/c.lui.yaml | 36 ++++++++++++++++++++ arch/inst/C/c.lw.yaml | 65 +++++++++++++++++++++++++++++++++++++ arch/inst/C/c.lwsp.yaml | 37 +++++++++++++++++++++ arch/inst/C/c.mv.yaml | 39 ++++++++++++++++++++++ arch/inst/C/c.nop.yaml | 27 +++++++++++++++ arch/inst/C/c.or.yaml | 55 +++++++++++++++++++++++++++++++ arch/inst/C/c.sd.yaml | 37 +++++++++++++++++++++ arch/inst/C/c.sdsp.yaml | 36 ++++++++++++++++++++ arch/inst/C/c.slli.yaml | 51 +++++++++++++++++++++++++++++ arch/inst/C/c.sq.yaml | 37 +++++++++++++++++++++ arch/inst/C/c.sqsp.yaml | 36 ++++++++++++++++++++ arch/inst/C/c.srai.yaml | 47 +++++++++++++++++++++++++++ arch/inst/C/c.srli.yaml | 51 +++++++++++++++++++++++++++++ arch/inst/C/c.sub.yaml | 55 +++++++++++++++++++++++++++++++ arch/inst/C/c.subw.yaml | 45 +++++++++++++++++++++++++ arch/inst/C/c.sw.yaml | 37 +++++++++++++++++++++ arch/inst/C/c.swsp.yaml | 35 ++++++++++++++++++++ arch/inst/C/c.xor.yaml | 55 +++++++++++++++++++++++++++++++ 47 files changed, 1916 insertions(+) create mode 100644 arch/inst/C/c.add.yaml create mode 100644 arch/inst/C/c.addi.yaml create mode 100644 arch/inst/C/c.addi16sp.yaml create mode 100644 arch/inst/C/c.addi4spn.yaml create mode 100644 arch/inst/C/c.addiw.yaml create mode 100644 arch/inst/C/c.addw.yaml create mode 100644 arch/inst/C/c.and.yaml create mode 100644 arch/inst/C/c.andi.yaml create mode 100644 arch/inst/C/c.beqz.yaml create mode 100644 arch/inst/C/c.bnez.yaml create mode 100644 arch/inst/C/c.ebreak.yaml create mode 100644 arch/inst/C/c.fld.yaml create mode 100644 arch/inst/C/c.fldsp.yaml create mode 100644 arch/inst/C/c.flw.yaml create mode 100644 arch/inst/C/c.flwsp.yaml create mode 100644 arch/inst/C/c.fsd.yaml create mode 100644 arch/inst/C/c.fsdsp.yaml create mode 100644 arch/inst/C/c.fsw.yaml create mode 100644 arch/inst/C/c.fswsp.yaml create mode 100644 arch/inst/C/c.j.yaml create mode 100644 arch/inst/C/c.jal.yaml create mode 100644 arch/inst/C/c.jalr.yaml create mode 100644 arch/inst/C/c.jr.yaml create mode 100644 arch/inst/C/c.ld.yaml create mode 100644 arch/inst/C/c.ldsp.yaml create mode 100644 arch/inst/C/c.li.yaml create mode 100644 arch/inst/C/c.lq.yaml create mode 100644 arch/inst/C/c.lqsp.yaml create mode 100644 arch/inst/C/c.lui.yaml create mode 100644 arch/inst/C/c.lw.yaml create mode 100644 arch/inst/C/c.lwsp.yaml create mode 100644 arch/inst/C/c.mv.yaml create mode 100644 arch/inst/C/c.nop.yaml create mode 100644 arch/inst/C/c.or.yaml create mode 100644 arch/inst/C/c.sd.yaml create mode 100644 arch/inst/C/c.sdsp.yaml create mode 100644 arch/inst/C/c.slli.yaml create mode 100644 arch/inst/C/c.sq.yaml create mode 100644 arch/inst/C/c.sqsp.yaml create mode 100644 arch/inst/C/c.srai.yaml create mode 100644 arch/inst/C/c.srli.yaml create mode 100644 arch/inst/C/c.sub.yaml create mode 100644 arch/inst/C/c.subw.yaml create mode 100644 arch/inst/C/c.sw.yaml create mode 100644 arch/inst/C/c.swsp.yaml create mode 100644 arch/inst/C/c.xor.yaml diff --git a/arch/ext/C.yaml b/arch/ext/C.yaml index 8b74dda4d..3ec544064 100644 --- a/arch/ext/C.yaml +++ b/arch/ext/C.yaml @@ -3,6 +3,12 @@ C: type: unprivileged long_name: Compressed instructions + company: + name: RISC-V International + url: https://riscv.org + doc_license: + name: Creative Commons Attribution 4.0 International License + url: https://creativecommons.org/licenses/by/4.0/ versions: - version: "2.2.0" state: ratified diff --git a/arch/inst/C/c.add.yaml b/arch/inst/C/c.add.yaml new file mode 100644 index 000000000..5aca02cb2 --- /dev/null +++ b/arch/inst/C/c.add.yaml @@ -0,0 +1,36 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.add: + long_name: Add + description: | + Add the value in rs2 to rd, and store the result in rd. + C.ADD expands into `add rd, rd, rs2`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, rs2 + encoding: + match: 1001----------10 + variables: + - name: rs2 + location: 6-2 + - name: rd + location: 11-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg t0 = X[rd]; + XReg t1 = X[rs2]; + X[rd] = t0 + t1; + + sail(): | + { + let rs1_val = X(rd); + let rs2_val = X(rs2); + X(rd) = rs1_val + rs2_val; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.addi.yaml b/arch/inst/C/c.addi.yaml new file mode 100644 index 000000000..f227a49e0 --- /dev/null +++ b/arch/inst/C/c.addi.yaml @@ -0,0 +1,35 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.addi: + long_name: Add a sign-extended non-zero immediate + description: | + C.ADDI adds the non-zero sign-extended 6-bit immediate to the value in register rd then writes the result to rd. + C.ADDI expands into `addi rd, rd, imm`. + C.ADDI is only valid when rd≠x0 and imm≠0. + The code points with rd=x0 encode the C.NOP instruction; the remaining code points with imm=0 encode HINTs. + definedBy: + anyOf: + - C + - Zca + assembly: xd, imm + encoding: + match: 000-----------01 + variables: + - name: imm + location: 12|6-2 + not: 0 + - name: rd + location: 11-7 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rd] + imm; + diff --git a/arch/inst/C/c.addi16sp.yaml b/arch/inst/C/c.addi16sp.yaml new file mode 100644 index 000000000..20a079162 --- /dev/null +++ b/arch/inst/C/c.addi16sp.yaml @@ -0,0 +1,33 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.addi16sp: + long_name: Add a sign-extended non-zero immediate + description: | + C.ADDI16SP adds the non-zero sign-extended 6-bit immediate to the value in the stack pointer (sp=x2), where the immediate is scaled to represent multiples of 16 in the range (-512,496). + C.ADDI16SP is used to adjust the stack pointer in procedure prologues and epilogues. + It expands into `addi x2, x2, nzimm[9:4]`. + C.ADDI16SP is only valid when nzimm≠0; the code point with nzimm=0 is reserved. + definedBy: + anyOf: + - C + - Zca + assembly: imm + encoding: + match: 011-00010-----01 + variables: + - name: imm + location: 12|4-3|5|2|6 + left_shift: 4 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[2] = X[2] + imm; + diff --git a/arch/inst/C/c.addi4spn.yaml b/arch/inst/C/c.addi4spn.yaml new file mode 100644 index 000000000..ca9d016d7 --- /dev/null +++ b/arch/inst/C/c.addi4spn.yaml @@ -0,0 +1,35 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.addi4spn: + long_name: Add a zero-extended non-zero immediate, scaled by 4, to the stack pointer + description: | + Adds a zero-extended non-zero immediate, scaled by 4, to the stack pointer, x2, and writes the result to rd′. + This instruction is used to generate pointers to stack-allocated variables. + It expands to `addi rd′, x2, nzuimm[9:2]`. + C.ADDI4SPN is only valid when nzuimm≠0; the code points with nzuimm=0 are reserved. + definedBy: + anyOf: + - C + - Zca + assembly: xd, imm + encoding: + match: 000-----------00 + variables: + - name: imm + location: 10-7|12-11|5|6 + left_shift: 2 + not: 0 + - name: rd + location: 4-2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd+8] = X[2] + imm; + diff --git a/arch/inst/C/c.addiw.yaml b/arch/inst/C/c.addiw.yaml new file mode 100644 index 000000000..db1db4cfe --- /dev/null +++ b/arch/inst/C/c.addiw.yaml @@ -0,0 +1,35 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.addiw: + long_name: Add a sign-extended non-zero immediate + description: | + C.ADDIW is an RV64C/RV128C-only instruction that performs the same computation as C.ADDI but produces a 32-bit result, then sign-extends result to 64 bits. + C.ADDIW expands into `addiw rd, rd, imm`. + The immediate can be zero for C.ADDIW, where this corresponds to `sext.w rd`. + C.ADDIW is only valid when rd≠x0; the code points with rd=x0 are reserved. + definedBy: + anyOf: + - C + - Zca + base: 64 + assembly: xd, imm + encoding: + match: 001-----------01 + variables: + - name: imm + location: 12|6-2 + - name: rd + location: 11-7 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = sext((X[rd] + imm), 32); + diff --git a/arch/inst/C/c.addw.yaml b/arch/inst/C/c.addw.yaml new file mode 100644 index 000000000..6a93e314d --- /dev/null +++ b/arch/inst/C/c.addw.yaml @@ -0,0 +1,45 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.addw: + long_name: Add word + description: | + Add the 32-bit values in rs2 from rd, and store the result in rd. + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.ADDW expands into `addw rd, rd, rs2`. + definedBy: + anyOf: + - C + - Zca + base: 64 + assembly: xd, rs2 + encoding: + match: 100111---01---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + Bits<32> t0 = X[rd+8][31:0]; + Bits<32> t1 = X[rs2+8][31:0]; + X[rd+8] = sext(t0 + t1, 31); + + sail(): | + { + let rs1_val = (X(rd+8))[31..0]; + let rs2_val = (X(rs2+8))[31..0]; + let result : bits(32) = match op { + RISCV_ADDW => rs1_val + rs2_val, + RISCV_SUBW => rs1_val - rs2_val, + RISCV_SLLW => rs1_val << (rs2_val[4..0]), + RISCV_SRLW => rs1_val >> (rs2_val[4..0]), + RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) + }; + X(rd+8) = sign_extend(result); + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.and.yaml b/arch/inst/C/c.and.yaml new file mode 100644 index 000000000..4e031c40b --- /dev/null +++ b/arch/inst/C/c.and.yaml @@ -0,0 +1,55 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.and: + long_name: And + description: | + And rd with rs2, and store the result in rd + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.AND expands into `and rd, rd, rs2`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, rs2 + encoding: + match: 100011---11---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg t0 = X[rd+8]; + XReg t1 = X[rs2+8]; + X[rd+8] = t0 & t1; + + sail(): | + { + let rs1_val = X(rd+8); + let rs2_val = X(rs2+8); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.andi.yaml b/arch/inst/C/c.andi.yaml new file mode 100644 index 000000000..746e1c981 --- /dev/null +++ b/arch/inst/C/c.andi.yaml @@ -0,0 +1,44 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.andi: + long_name: And immediate + description: | + And an immediate to the value in rd, and store the result in rd. + The rd register index should be used as rd+8 (registers x8-x15). + C.ANDI expands into `andi rd, rd, imm`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, imm + encoding: + match: 100-10--------01 + variables: + - name: imm + location: 12|6-2 + - name: rd + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + # shamt is between 0-63 + X[rd+8] = X[rd+8] & imm; + + sail(): | + { + let rd_val = X(rd+8); + let immext : xlenbits = sign_extend(imm); + let result : xlenbits = match op { + RISCV_ADDI => rd_val + immext, + RISCV_SLTI => zero_extend(bool_to_bits(rd_val <_s immext)), + RISCV_SLTIU => zero_extend(bool_to_bits(rd_val <_u immext)), + RISCV_ANDI => rd_val & immext, + RISCV_ORI => rd_val | immext, + RISCV_XORI => rd_val ^ immext + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.beqz.yaml b/arch/inst/C/c.beqz.yaml new file mode 100644 index 000000000..7b664efa1 --- /dev/null +++ b/arch/inst/C/c.beqz.yaml @@ -0,0 +1,65 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.beqz: + long_name: Branch if Equal Zero + description: | + C.BEQZ performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. It can therefore target a ±256 B range. C.BEQZ takes the branch if the value in register rs1′ is zero. + It expands to `beq` `rs1, x0, offset`. + definedBy: + anyOf: + - C + - Zca + assembly: xs1, imm + encoding: + match: 110-----------01 + variables: + - name: imm + location: 12|6-5|2|11-10|4-3 + left_shift: 0 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (X[rs1] != 0) { + jump($pc + imm); + } + + sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(0); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS + } + } + } + } else RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.bnez.yaml b/arch/inst/C/c.bnez.yaml new file mode 100644 index 000000000..fb70ea199 --- /dev/null +++ b/arch/inst/C/c.bnez.yaml @@ -0,0 +1,65 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.bnez: + long_name: Branch if NOT Equal Zero + description: | + C.BEQZ performs conditional control transfers. The offset is sign-extended and added to the pc to form the branch target address. It can therefore target a ±256 B range. C.BEQZ takes the branch if the value in register rs1′ is NOT zero. + It expands to `beq` `rs1, x0, offset`. + definedBy: + anyOf: + - C + - Zca + assembly: xs1, imm + encoding: + match: 111-----------01 + variables: + - name: imm + location: 12|6-5|2|11-10|4-3 + left_shift: 0 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (X[rs1] != 0) { + jump($pc + imm); + } + + sail(): | + { + let rs1_val = X(rs1); + let rs2_val = X(0); + let taken : bool = match op { + RISCV_BEQ => rs1_val == rs2_val, + RISCV_BNE => rs1_val != rs2_val, + RISCV_BLT => rs1_val <_s rs2_val, + RISCV_BGE => rs1_val >=_s rs2_val, + RISCV_BLTU => rs1_val <_u rs2_val, + RISCV_BGEU => rs1_val >=_u rs2_val + }; + let t : xlenbits = PC + sign_extend(imm); + if taken then { + /* Extensions get the first checks on the prospective target address. */ + match ext_control_check_pc(t) { + Ext_ControlAddr_Error(e) => { + ext_handle_control_check_error(e); + RETIRE_FAIL + }, + Ext_ControlAddr_OK(target) => { + if bit_to_bool(target[1]) & not(extension("C")) then { + handle_mem_exception(target, E_Fetch_Addr_Align()); + RETIRE_FAIL; + } else { + set_next_pc(target); + RETIRE_SUCCESS + } + } + } + } else RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.ebreak.yaml b/arch/inst/C/c.ebreak.yaml new file mode 100644 index 000000000..a50e09d3f --- /dev/null +++ b/arch/inst/C/c.ebreak.yaml @@ -0,0 +1,44 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.ebreak: + long_name: Breakpoint exception. + description: | + The C.EBREAK instruction is used by debuggers to cause control to be transferred back to + a debugging environment. Unless overridden by an external debug environment, + C.EBREAK raises a breakpoint exception and performs no other operation. + + [NOTE] + As described in the `C` Standard Extension for Compressed Instructions, the `c.ebreak` + instruction performs the same operation as the EBREAK instruction. + + EBREAK causes the receiving privilege mode's epc register to be set to the address of + the EBREAK instruction itself, not the address of the following instruction. + As EBREAK causes a synchronous exception, it is not considered to retire, + and should not increment the `minstret` CSR. + definedBy: + anyOf: + - C + - Zca + assembly: " " + encoding: + match: "1001000000000010" + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (TRAP_ON_EBREAK) { + raise_precise(ExceptionCode::Breakpoint, mode(), $pc); + } else { + eei_ebreak(); + } + + sail(): | + { + handle_mem_exception(PC, E_Breakpoint()); + RETIRE_FAIL + } diff --git a/arch/inst/C/c.fld.yaml b/arch/inst/C/c.fld.yaml new file mode 100644 index 000000000..02df88e9b --- /dev/null +++ b/arch/inst/C/c.fld.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.fld: + long_name: Load double-precision + description: | + Loads a double precision floating-point value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the base address in register rs1. + It expands to `fld` `rd, offset(rs1)`. + definedBy: + allOf: + - C + - D + assembly: xd, imm(xs1) + encoding: + match: 001-----------00 + variables: + - name: imm + location: 6-5|12-10 + left_shift: 3 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + X[rd] = sext(read_memory<64>(virtual_address, $encoding), 64); diff --git a/arch/inst/C/c.fldsp.yaml b/arch/inst/C/c.fldsp.yaml new file mode 100644 index 000000000..e9151667a --- /dev/null +++ b/arch/inst/C/c.fldsp.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.fldsp: + long_name: Load doubleword into floating-point register from stack + description: | + Loads a double-precision floating-point value from memory into floating-point register rd. + It computes its effective address by adding the zero-extended offset, scaled by 8, + to the stack pointer, x2. + It expands to `fld` `rd, offset(x2)`. + definedBy: + allOf: + - C + - D + assembly: fd, imm(sp) + encoding: + match: 001-----------10 + variables: + - name: imm + location: 4-2|12|6-5 + left_shift: 3 + - name: rd + location: 11-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (implemented?(ExtensionName::D) && (CSR[misa].D == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + f[rd] = read_memory<64>(virtual_address, $encoding); diff --git a/arch/inst/C/c.flw.yaml b/arch/inst/C/c.flw.yaml new file mode 100644 index 000000000..179fce179 --- /dev/null +++ b/arch/inst/C/c.flw.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.flw: + long_name: Load single-precision + description: | + Loads a single precision floating-point value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the base address in register rs1. + It expands to `flw` `rd, offset(rs1)`. + definedBy: + allOf: + - C + - F + assembly: xd, imm(xs1) + encoding: + match: 011-----------00 + variables: + - name: imm + location: 5|12-10|6 + left_shift: 2 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + X[rd] = sext(read_memory<32>(virtual_address, $encoding), 32); diff --git a/arch/inst/C/c.flwsp.yaml b/arch/inst/C/c.flwsp.yaml new file mode 100644 index 000000000..aff898dfe --- /dev/null +++ b/arch/inst/C/c.flwsp.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.flwsp: + long_name: Load word into floating-point register from stack + description: | + Loads a single-precision floating-point value from memory into floating-point register rd. + It computes its effective address by adding the zero-extended offset, scaled by 4, + to the stack pointer, x2. + It expands to `flw` `rd, offset(x2)`. + definedBy: + allOf: + - C + - F + assembly: fd, imm(sp) + encoding: + match: 011-----------10 + variables: + - name: imm + location: 3-2|12|6-4 + left_shift: 2 + - name: rd + location: 11-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (implemented?(ExtensionName::F) && (CSR[misa].F == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + f[rd] = read_memory<32>(virtual_address, $encoding); diff --git a/arch/inst/C/c.fsd.yaml b/arch/inst/C/c.fsd.yaml new file mode 100644 index 000000000..6a3ed3f69 --- /dev/null +++ b/arch/inst/C/c.fsd.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.fsd: + long_name: Store double-precision + description: | + Stores a double precision floating-point value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the base address in register rs1. + It expands to `fsd` `rs2, offset(rs1)`. + definedBy: + allOf: + - C + - D + assembly: xs2, imm(xs1) + encoding: + match: 101-----------00 + variables: + - name: imm + location: 6-5|12-10 + left_shift: 3 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + write_memory<64>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.fsdsp.yaml b/arch/inst/C/c.fsdsp.yaml new file mode 100644 index 000000000..960e920f1 --- /dev/null +++ b/arch/inst/C/c.fsdsp.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.fsdsp: + long_name: Store double-precision value to stack + description: | + Stores a double-precision floating-point value in floating-point register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the stack pointer, x2. + It expands to `fsd` `rs2, offset(x2)`. + definedBy: + allOf: + - C + - D + assembly: fs2, imm(sp) + encoding: + match: 101-----------10 + variables: + - name: imm + location: 9-7|12-10 + left_shift: 3 + - name: rs2 + location: 6-2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (implemented?(ExtensionName::D) && (CSR[misa].D == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + write_memory<64>(virtual_address, f[rs2][63:0], $encoding); diff --git a/arch/inst/C/c.fsw.yaml b/arch/inst/C/c.fsw.yaml new file mode 100644 index 000000000..0ae02e595 --- /dev/null +++ b/arch/inst/C/c.fsw.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.fsw: + long_name: Store single-precision + description: | + Stores a single precision floating-point value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the base address in register rs1. + It expands to `fsw` `rs2, offset(rs1)`. + definedBy: + allOf: + - C + - F + assembly: xs2, imm(xs1) + encoding: + match: 111-----------00 + variables: + - name: imm + location: 5|12-10|6 + left_shift: 2 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + write_memory<32>(virtual_address, X[rs2][31:0], $encoding); diff --git a/arch/inst/C/c.fswsp.yaml b/arch/inst/C/c.fswsp.yaml new file mode 100644 index 000000000..837f182ec --- /dev/null +++ b/arch/inst/C/c.fswsp.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.fswsp: + long_name: Store single-precision value to stack + description: | + Stores a single-precision floating-point value in floating-point register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the stack pointer, x2. + It expands to `fsw` `rs2, offset(x2)`. + definedBy: + allOf: + - C + - F + assembly: fs2, imm(sp) + encoding: + match: 111-----------10 + variables: + - name: imm + location: 8-7|12-9 + left_shift: 2 + - name: rs2 + location: 6-2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + if (implemented?(ExtensionName::F) && (CSR[misa].F == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + write_memory<32>(virtual_address, f[rs2][31:0], $encoding); diff --git a/arch/inst/C/c.j.yaml b/arch/inst/C/c.j.yaml new file mode 100644 index 000000000..e965e7b40 --- /dev/null +++ b/arch/inst/C/c.j.yaml @@ -0,0 +1,30 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.j: + long_name: Jump + description: | + C.J performs an unconditional control transfer. The offset is sign-extended and added to the pc to form the jump target address. C.J can therefore target a ±2 KiB range. + It expands to `jal` `x0, offset`. + definedBy: + anyOf: + - C + - Zca + assembly: imm + encoding: + match: 101-----------01 + variables: + - name: imm + location: 12|8|10-9|6|7|2|11|5-3 + left_shift: 1 + sign_extend: true + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + jump($pc + imm); diff --git a/arch/inst/C/c.jal.yaml b/arch/inst/C/c.jal.yaml new file mode 100644 index 000000000..83d0f054b --- /dev/null +++ b/arch/inst/C/c.jal.yaml @@ -0,0 +1,34 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.jal: + long_name: Jump and Link + description: | + C.JAL is an RV32C-only instruction that performs the same operation as C.J, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1. + It expands to `jal` `x1, offset`. + definedBy: + anyOf: + - C + - Zca + base: 32 + assembly: imm + encoding: + match: 001-----------01 + variables: + - name: imm + location: 12|8|10-9|6|7|2|11|5-3 + left_shift: 1 + sign_extend: true + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg retrun_addr = $pc + 2; + + jump_halfword($pc + imm); + X[1] = retrun_addr; diff --git a/arch/inst/C/c.jalr.yaml b/arch/inst/C/c.jalr.yaml new file mode 100644 index 000000000..3b67f974a --- /dev/null +++ b/arch/inst/C/c.jalr.yaml @@ -0,0 +1,32 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.jalr: + long_name: Jump and Link Register. + description: | + C.JALR (jump and link register) performs the same operation as C.JR, but additionally writes the address of the instruction following the jump (pc+2) to the link register, x1. + C.JALR expands to jalr x1, 0(rs1). + definedBy: + anyOf: + - C + - Zca + assembly: xs1 + encoding: + match: 1001-----0000010 + variables: + - name: rs1 + location: 11-7 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + XReg returnaddr; + returnaddr = $pc + 2; + + jump(X[rs1]); + X[1] = returnaddr; diff --git a/arch/inst/C/c.jr.yaml b/arch/inst/C/c.jr.yaml new file mode 100644 index 000000000..7fd3a0861 --- /dev/null +++ b/arch/inst/C/c.jr.yaml @@ -0,0 +1,29 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.jr: + long_name: Jump Register + description: | + C.JR (jump register) performs an unconditional control transfer to the address in register rs1. + C.JR expands to jalr x0, 0(rs1). + definedBy: + anyOf: + - C + - Zca + assembly: xs1 + encoding: + match: 1000-----0000010 + variables: + - name: rs1 + location: 11-7 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + jump(X[rs1]); diff --git a/arch/inst/C/c.ld.yaml b/arch/inst/C/c.ld.yaml new file mode 100644 index 000000000..f2c37603c --- /dev/null +++ b/arch/inst/C/c.ld.yaml @@ -0,0 +1,65 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.ld: + long_name: Load double + description: | + Loads a 64-bit value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the base address in register rs1. + It expands to `ld` `rd, offset(rs1)`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, imm(xs1) + encoding: + match: 011-----------00 + variables: + - name: imm + location: 6-5|12-10 + left_shift: 3 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + X[rd] = sext(read_memory<64>(virtual_address, $encoding), 64); + + sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } + } + } diff --git a/arch/inst/C/c.ldsp.yaml b/arch/inst/C/c.ldsp.yaml new file mode 100644 index 000000000..76ef48189 --- /dev/null +++ b/arch/inst/C/c.ldsp.yaml @@ -0,0 +1,39 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.ldsp: + long_name: Load doubleword from stack pointer + description: | + C.LDSP is an RV64C/RV128C-only instruction that loads a 64-bit value from memory + into register rd. + It computes its effective address by adding the zero-extended offset, scaled by 8, + to the stack pointer, x2. + It expands to `ld` `rd, offset(x2)`. + C.LDSP is only valid when rd ≠ x0 the code points with rd=x0 are reserved. + definedBy: + anyOf: + - C + - Zca + base: 64 + assembly: xd, imm(sp) + encoding: + match: 011-----------10 + variables: + - name: imm + location: 4-2|12|6-5 + left_shift: 3 + - name: rd + location: 11-7 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + X[rd] = read_memory<64>(virtual_address, $encoding); diff --git a/arch/inst/C/c.li.yaml b/arch/inst/C/c.li.yaml new file mode 100644 index 000000000..d31cca35c --- /dev/null +++ b/arch/inst/C/c.li.yaml @@ -0,0 +1,33 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.li: + long_name: Load the sign-extended 6-bit immediate + description: | + C.LI loads the sign-extended 6-bit immediate, imm, into register rd. + C.LI expands into `addi rd, x0, imm`. + C.LI is only valid when rd≠x0; the code points with rd=x0 encode HINTs. + definedBy: + anyOf: + - C + - Zca + assembly: xd, imm + encoding: + match: 010-----------01 + variables: + - name: imm + location: 12|6-2 + - name: rd + location: 11-7 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = imm; + diff --git a/arch/inst/C/c.lq.yaml b/arch/inst/C/c.lq.yaml new file mode 100644 index 000000000..548805342 --- /dev/null +++ b/arch/inst/C/c.lq.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.lq: + long_name: Load quadruple + description: | + Loads a 128-bit value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 16, + to the base address in register rs1. + It expands to `lq` `rd, offset(rs1)`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, imm(xs1) + encoding: + match: 001-----------00 + variables: + - name: imm + location: 12-11|6-5|10 + left_shift: 4 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + X[rd] = sext(read_memory<128>(virtual_address, $encoding), 128); diff --git a/arch/inst/C/c.lqsp.yaml b/arch/inst/C/c.lqsp.yaml new file mode 100644 index 000000000..ba1eb3ba2 --- /dev/null +++ b/arch/inst/C/c.lqsp.yaml @@ -0,0 +1,38 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.lqsp: + long_name: Load quadruple word from stack pointer + description: | + C.LQSP is an RV128C-only instruction that loads a 128-bit value from memory into register rd. + It computes its effective address by adding the zero-extended offset, scaled by 16, + to the stack pointer, x2. + It expands to `lq` `rd, offset(x2)`. + C.LQSP is only valid when rd ≠ x0 the code points with rd=x0 are reserved. + definedBy: + anyOf: + - C + - Zca + base: 64 + assembly: xd, imm(sp) + encoding: + match: 001-----------10 + variables: + - name: imm + location: 5-2|12|6 + left_shift: 4 + - name: rd + location: 11-7 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + X[rd] = read_memory<128>(virtual_address, $encoding); diff --git a/arch/inst/C/c.lui.yaml b/arch/inst/C/c.lui.yaml new file mode 100644 index 000000000..ffba4e470 --- /dev/null +++ b/arch/inst/C/c.lui.yaml @@ -0,0 +1,36 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.lui: + long_name: Load the non-zero 6-bit immediate field into bits 17–12 of the destination register + description: | + C.LUI loads the non-zero 6-bit immediate field into bits 17–12 of the destination register, clears the bottom 12 bits, and sign-extends bit 17 into all higher bits of the destination. + C.LUI expands into `lui rd, imm`. + C.LUI is only valid when rd≠x0 and rd≠x2, and when the immediate is not equal to zero. + The code points with imm=0 are reserved; the remaining code points with rd=x0 are HINTs; and the remaining code points with rd=x2 correspond to the C.ADDI16SP instruction + definedBy: + anyOf: + - C + - Zca + assembly: xd, imm + encoding: + match: 011-----------01 + variables: + - name: imm + location: 12|6-2 + left_shift: 12 + - name: rd + location: 11-7 + not: 0 + not: 2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = imm; + diff --git a/arch/inst/C/c.lw.yaml b/arch/inst/C/c.lw.yaml new file mode 100644 index 000000000..60cef3383 --- /dev/null +++ b/arch/inst/C/c.lw.yaml @@ -0,0 +1,65 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.lw: + long_name: Load word + description: | + Loads a 32-bit value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the base address in register rs1. + It expands to `lw` `rd, offset(rs1)`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, imm(xs1) + encoding: + match: 010-----------00 + variables: + - name: imm + location: 5|12-10|6 + left_shift: 2 + - name: rd + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + X[rd] = sext(read_memory<32>(virtual_address, $encoding), 32); + + sail(): | + { + let offset : xlenbits = sign_extend(imm); + /* Get the address, X(rs1) + offset. + Some extensions perform additional checks on address validity. */ + match ext_data_get_addr(rs1, offset, Read(Data), width) { + Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, + Ext_DataAddr_OK(vaddr) => + if check_misaligned(vaddr, width) + then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } + else match translateAddr(vaddr, Read(Data)) { + TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, + TR_Address(paddr, _) => + match (width) { + BYTE => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 1, aq, rl, false), is_unsigned), + HALF => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 2, aq, rl, false), is_unsigned), + WORD => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 4, aq, rl, false), is_unsigned), + DOUBLE if sizeof(xlen) >= 64 => + process_load(rd, vaddr, mem_read(Read(Data), paddr, 8, aq, rl, false), is_unsigned), + _ => report_invalid_width(__FILE__, __LINE__, width, "load") + } + } + } + } diff --git a/arch/inst/C/c.lwsp.yaml b/arch/inst/C/c.lwsp.yaml new file mode 100644 index 000000000..c07559e17 --- /dev/null +++ b/arch/inst/C/c.lwsp.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.lwsp: + long_name: Load word from stack pointer + description: | + Loads a 32-bit value from memory into register rd. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the stack pointer, x2. + It expands to `lw` `rd, offset(x2)`. + C.LWSP is only valid when rd ≠ x0. The code points with rd=x0 are reserved. + definedBy: + anyOf: + - C + - Zca + assembly: xd, imm(sp) + encoding: + match: 010-----------10 + variables: + - name: imm + location: 3-2|12|6-4 + left_shift: 2 + - name: rd + location: 11-7 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + X[rd] = sext(read_memory<32>(virtual_address, $encoding), 32); diff --git a/arch/inst/C/c.mv.yaml b/arch/inst/C/c.mv.yaml new file mode 100644 index 000000000..e721f3efd --- /dev/null +++ b/arch/inst/C/c.mv.yaml @@ -0,0 +1,39 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.mv: + long_name: Move Register + description: | + C.MV (move register) performs copy of the data in register rs2 to register rd + C.MV expands to addi rd, x0, rs2. + definedBy: + anyOf: + - C + - Zca + assembly: xd, xs2 + encoding: + match: 1000----------10 + variables: + - name: rd + location: 11-7 + not: 0 + - name: rs2 + location: 6-2 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + X[rd] = X[rs2]; + + sail(): | + { + let rs2_val = X(rs2); + X(rs) = rs2_val + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.nop.yaml b/arch/inst/C/c.nop.yaml new file mode 100644 index 000000000..9ad6df0f0 --- /dev/null +++ b/arch/inst/C/c.nop.yaml @@ -0,0 +1,27 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.nop: + long_name: Non-operation + description: | + C.NOP expands into `addi x0, x0, imm`. + definedBy: + anyOf: + - C + - Zca + assembly: imm + encoding: + match: 000-00000-----01 + variables: + - name: imm + location: 12|6-2 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + diff --git a/arch/inst/C/c.or.yaml b/arch/inst/C/c.or.yaml new file mode 100644 index 000000000..cd6241325 --- /dev/null +++ b/arch/inst/C/c.or.yaml @@ -0,0 +1,55 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.or: + long_name: Or + description: | + Or rd with rs2, and store the result in rd + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.OR expands into `or rd, rd, rs2`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, rs2 + encoding: + match: 100011---10---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg t0 = X[rd+8]; + XReg t1 = X[rs2+8]; + X[rd+8] = t0 | t1; + + sail(): | + { + let rs1_val = X(rd+8); + let rs2_val = X(rs2+8); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.sd.yaml b/arch/inst/C/c.sd.yaml new file mode 100644 index 000000000..38bc4c4c0 --- /dev/null +++ b/arch/inst/C/c.sd.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.sd: + long_name: Store double + description: | + Stores a 64-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the base address in register rs1. + It expands to `sd` `rs2, offset(rs1)`. + definedBy: + anyOf: + - C + - Zca + assembly: xs2, imm(xs1) + encoding: + match: 111-----------00 + variables: + - name: imm + location: 6-5|12-10 + left_shift: 3 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + write_memory<64>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.sdsp.yaml b/arch/inst/C/c.sdsp.yaml new file mode 100644 index 000000000..6547c765c --- /dev/null +++ b/arch/inst/C/c.sdsp.yaml @@ -0,0 +1,36 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.sdsp: + long_name: Store doubleword to stack + description: | + Stores a 64-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 8, + to the stack pointer, x2. + It expands to `sd` `rs2, offset(x2)`. + definedBy: + anyOf: + - C + - Zca + base: 64 + assembly: xs2, imm(sp) + encoding: + match: 111-----------10 + variables: + - name: imm + location: 9-7|12-10 + left_shift: 3 + - name: rs2 + location: 6-2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + write_memory<64>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.slli.yaml b/arch/inst/C/c.slli.yaml new file mode 100644 index 000000000..89806a62e --- /dev/null +++ b/arch/inst/C/c.slli.yaml @@ -0,0 +1,51 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.slli: + long_name: Shift left logical immediate + description: | + Shift the value in rd left by shamt, and store the result back in rd. + C.SLLI expands into `slli rd, rd, shamt`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, shamt + encoding: + match: 000-----------10 + variables: + - name: shamt + location: 12|6-2 + - name: rd + location: 11-7 + not: 0 + access: + s: always + u: always + vs: always + vu: always + operation(): | + # shamt is between 0-63 + X[rd] = X[rd] << shamt; + + sail(): | + { + let rd_val = X(rd); + /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ + let result : xlenbits = match op { + RISCV_SLLI => if sizeof(xlen) == 32 + then rd_val << shamt[4..0] + else rd_val << shamt, + RISCV_SRLI => if sizeof(xlen) == 32 + then rd_val >> shamt[4..0] + else rd_val >> shamt, + RISCV_SRAI => if sizeof(xlen) == 32 + then shift_right_arith32(rd_val, shamt[4..0]) + else shift_right_arith64(rd_val, shamt) + }; + X(rd) = result; + RETIRE_SUCCESS + } + + + + diff --git a/arch/inst/C/c.sq.yaml b/arch/inst/C/c.sq.yaml new file mode 100644 index 000000000..d7ba2c99d --- /dev/null +++ b/arch/inst/C/c.sq.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.sq: + long_name: Store quadruple + description: | + Stores a 128-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 16, + to the base address in register rs1. + It expands to `sq` `rs2, offset(rs1)`. + definedBy: + anyOf: + - C + - Zca + assembly: xs2, imm(xs1) + encoding: + match: 101-----------00 + variables: + - name: imm + location: 12-11|6-5|10 + left_shift: 4 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + write_memory<128>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.sqsp.yaml b/arch/inst/C/c.sqsp.yaml new file mode 100644 index 000000000..0213866d1 --- /dev/null +++ b/arch/inst/C/c.sqsp.yaml @@ -0,0 +1,36 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.sqsp: + long_name: Store quadruple word to stack + description: | + Stores a 128-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 16, + to the stack pointer, x2. + It expands to `sq` `rs2, offset(x2)`. + definedBy: + anyOf: + - C + - Zca + base: 64 + assembly: xs2, imm(sp) + encoding: + match: 101-----------10 + variables: + - name: imm + location: 10-7|12-11 + left_shift: 4 + - name: rs2 + location: 6-2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + write_memory<128>(virtual_address, X[rs2], $encoding); diff --git a/arch/inst/C/c.srai.yaml b/arch/inst/C/c.srai.yaml new file mode 100644 index 000000000..bca00015b --- /dev/null +++ b/arch/inst/C/c.srai.yaml @@ -0,0 +1,47 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.srai: + long_name: Shift right arithmetical immediate + description: | + Arithmetic shift (the original sign bit is copied into the vacated upper bits) the value in rd right by shamt, and store the result in rd. + The rd register index should be used as rd+8 (registers x8-x15). + C.SRAI expands into `srai rd, rd, shamt`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, shamt + encoding: + match: 100-01--------01 + variables: + - name: shamt + location: 12|6-2 + - name: rd + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + # shamt is between 0-63 + X[rd+8] = X[rd+8] >>> shamt; + + sail(): | + { + let rd_val = X(rd+8); + /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ + let result : xlenbits = match op { + RISCV_SLLI => if sizeof(xlen) == 32 + then rd_val << shamt[4..0] + else rd_val << shamt, + RISCV_SRLI => if sizeof(xlen) == 32 + then rd_val >> shamt[4..0] + else rd_val >> shamt, + RISCV_SRAI => if sizeof(xlen) == 32 + then shift_right_arith32(rd_val, shamt[4..0]) + else shift_right_arith64(rd_val, shamt) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.srli.yaml b/arch/inst/C/c.srli.yaml new file mode 100644 index 000000000..c8032af87 --- /dev/null +++ b/arch/inst/C/c.srli.yaml @@ -0,0 +1,51 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.srli: + long_name: Shift right logical immediate + description: | + Shift the value in rd right by shamt, and store the result back in rd. + The rd register index should be used as rd+8 (registers x8-x15). + C.SRLI expands into `srli rd, rd, shamt`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, shamt + encoding: + match: 100-00--------01 + variables: + - name: shamt + location: 12|6-2 + - name: rd + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + # shamt is between 0-63 + X[rd+8] = X[rd+8] >> shamt; + + sail(): | + { + let rd_val = X(rd+8); + /* the decoder guard should ensure that shamt[5] = 0 for RV32 */ + let result : xlenbits = match op { + RISCV_SLLI => if sizeof(xlen) == 32 + then rd_val << shamt[4..0] + else rd_val << shamt, + RISCV_SRLI => if sizeof(xlen) == 32 + then rd_val >> shamt[4..0] + else rd_val >> shamt, + RISCV_SRAI => if sizeof(xlen) == 32 + then shift_right_arith32(rd_val, shamt[4..0]) + else shift_right_arith64(rd_val, shamt) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } + + + + diff --git a/arch/inst/C/c.sub.yaml b/arch/inst/C/c.sub.yaml new file mode 100644 index 000000000..e853bf4cc --- /dev/null +++ b/arch/inst/C/c.sub.yaml @@ -0,0 +1,55 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.sub: + long_name: Subtract + description: | + Subtract the value in rs2 from rd, and store the result in rd. + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.SUB expands into `sub rd, rd, rs2`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, rs2 + encoding: + match: 100011---00---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg t0 = X[rd+8]; + XReg t1 = X[rs2+8]; + X[rd+8] = t0 - t1; + + sail(): | + { + let rs1_val = X(rd+8); + let rs2_val = X(rs2+8); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd+8) = result; + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.subw.yaml b/arch/inst/C/c.subw.yaml new file mode 100644 index 000000000..10b008446 --- /dev/null +++ b/arch/inst/C/c.subw.yaml @@ -0,0 +1,45 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.subw: + long_name: Subtract word + description: | + Subtract the 32-bit values in rs2 from rd, and store the result in rd. + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.SUBW expands into `subw rd, rd, rs2`. + definedBy: + anyOf: + - C + - Zca + base: 64 + assembly: xd, rs2 + encoding: + match: 100111---00---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + Bits<32> t0 = X[rd+8][31:0]; + Bits<32> t1 = X[rs2+8][31:0]; + X[rd+8] = sext(t0 - t1, 31); + + sail(): | + { + let rs1_val = (X(rd+8))[31..0]; + let rs2_val = (X(rs2+8))[31..0]; + let result : bits(32) = match op { + RISCV_ADDW => rs1_val + rs2_val, + RISCV_SUBW => rs1_val - rs2_val, + RISCV_SLLW => rs1_val << (rs2_val[4..0]), + RISCV_SRLW => rs1_val >> (rs2_val[4..0]), + RISCV_SRAW => shift_right_arith32(rs1_val, rs2_val[4..0]) + }; + X(rd+8) = sign_extend(result); + RETIRE_SUCCESS + } diff --git a/arch/inst/C/c.sw.yaml b/arch/inst/C/c.sw.yaml new file mode 100644 index 000000000..8010aa2fb --- /dev/null +++ b/arch/inst/C/c.sw.yaml @@ -0,0 +1,37 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.sw: + long_name: Store word + description: | + Stores a 32-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the base address in register rs1. + It expands to `sw` `rs2, offset(rs1)`. + definedBy: + anyOf: + - C + - Zca + assembly: xs2, imm(xs1) + encoding: + match: 110-----------00 + variables: + - name: imm + location: 5|12-10|6 + left_shift: 2 + - name: rs2 + location: 4-2 + - name: rs1 + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[rs1] + imm; + + write_memory<32>(virtual_address, X[rs2][31:0], $encoding); diff --git a/arch/inst/C/c.swsp.yaml b/arch/inst/C/c.swsp.yaml new file mode 100644 index 000000000..e0a0db87c --- /dev/null +++ b/arch/inst/C/c.swsp.yaml @@ -0,0 +1,35 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.swsp: + long_name: Store word to stack + description: | + Stores a 32-bit value in register rs2 to memory. + It computes an effective address by adding the zero-extended offset, scaled by 4, + to the stack pointer, x2. + It expands to `sw` `rs2, offset(x2)`. + definedBy: + anyOf: + - C + - Zca + assembly: xs2, imm(sp) + encoding: + match: 110-----------10 + variables: + - name: imm + location: 8-7|12-9 + left_shift: 2 + - name: rs2 + location: 6-2 + access: + s: always + u: always + vs: always + vu: always + operation(): | + if (implemented?(ExtensionName::C) && (CSR[misa].C == 1'b0)) { + raise(ExceptionCode::IllegalInstruction, mode(), $encoding); + } + + XReg virtual_address = X[2] + imm; + + write_memory<32>(virtual_address, X[rs2][31:0], $encoding); diff --git a/arch/inst/C/c.xor.yaml b/arch/inst/C/c.xor.yaml new file mode 100644 index 000000000..a5bebb2db --- /dev/null +++ b/arch/inst/C/c.xor.yaml @@ -0,0 +1,55 @@ +# yaml-language-server: $schema=../../../schemas/inst_schema.json + +c.xor: + long_name: Exclusive Or + description: | + Exclusive or rd with rs2, and store the result in rd + The rd and rs2 register indexes should be used as rd+8 and rs2+8 (registers x8-x15). + C.XOR expands into `xor rd, rd, rs2`. + definedBy: + anyOf: + - C + - Zca + assembly: xd, rs2 + encoding: + match: 100011---01---01 + variables: + - name: rs2 + location: 4-2 + - name: rd + location: 9-7 + access: + s: always + u: always + vs: always + vu: always + operation(): | + XReg t0 = X[rd+8]; + XReg t1 = X[rs2+8]; + X[rd+8] = t0 ^ t1; + + sail(): | + { + let rs1_val = X(rd+8); + let rs2_val = X(rs2+8); + let result : xlenbits = match op { + RISCV_ADD => rs1_val + rs2_val, + RISCV_SLT => zero_extend(bool_to_bits(rs1_val <_s rs2_val)), + RISCV_SLTU => zero_extend(bool_to_bits(rs1_val <_u rs2_val)), + RISCV_AND => rs1_val & rs2_val, + RISCV_OR => rs1_val | rs2_val, + RISCV_XOR => rs1_val ^ rs2_val, + RISCV_SLL => if sizeof(xlen) == 32 + then rs1_val << (rs2_val[4..0]) + else rs1_val << (rs2_val[5..0]), + RISCV_SRL => if sizeof(xlen) == 32 + then rs1_val >> (rs2_val[4..0]) + else rs1_val >> (rs2_val[5..0]), + RISCV_SUB => rs1_val - rs2_val, + RISCV_SRA => if sizeof(xlen) == 32 + then shift_right_arith32(rs1_val, rs2_val[4..0]) + else shift_right_arith64(rs1_val, rs2_val[5..0]) + }; + X(rd+8) = result; + RETIRE_SUCCESS + }