| // Copyright 2024 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // RiscV 32 bit G instruction decoder. |
| decoder RiscV32G { |
| namespace mpact::sim::riscv::encoding; |
| opcode_enum = "isa32::OpcodeEnum"; |
| includes { |
| #include "riscv/riscv32g_decoder.h" |
| } |
| RiscVGInst32; |
| RiscVCInst16; |
| }; |
| |
| #include "riscv_format32.bin_fmt" |
| #include "riscv_format16.bin_fmt" |
| |
| instruction group RiscVGInst32 = {RiscVGInstBase32, RiscVGHints32}; |
| |
| instruction group RiscVGInstBase32[32] : Inst32Format { |
| lui : UType : opcode == 0b011'0111, rd != 0; |
| auipc : UType : opcode == 0b001'0111, rd != 0; |
| jal : JType : rd != 0, opcode == 0b110'1111; |
| j : JType : rd == 0, opcode == 0b110'1111; |
| jalr : IType : rd != 0, func3 == 0b000, opcode == 0b110'0111; |
| jr : IType : rd == 0, func3 == 0b000, opcode == 0b110'0111; |
| beq : BType : func3 == 0b000, opcode == 0b110'0011; |
| bne : BType : func3 == 0b001, opcode == 0b110'0011; |
| blt : BType : func3 == 0b100, opcode == 0b110'0011; |
| bge : BType : func3 == 0b101, opcode == 0b110'0011; |
| bltu : BType : func3 == 0b110, opcode == 0b110'0011; |
| bgeu : BType : func3 == 0b111, opcode == 0b110'0011; |
| lb : BType : func3 == 0b000, opcode == 0b000'0011; |
| lh : BType : func3 == 0b001, opcode == 0b000'0011; |
| lw : BType : func3 == 0b010, opcode == 0b000'0011; |
| lbu : BType : func3 == 0b100, opcode == 0b000'0011; |
| lhu : BType : func3 == 0b101, opcode == 0b000'0011; |
| sb : SType : func3 == 0b000, opcode == 0b010'0011; |
| sh : SType : func3 == 0b001, opcode == 0b010'0011; |
| sw : SType : func3 == 0b010, opcode == 0b010'0011; |
| addi : IType : func3 == 0b000, opcode == 0b001'0011, rd != 0; |
| nop : IType : func3 == 0b000, opcode == 0b001'0011, rd == 0, imm12 == 0, rs1 == 0; |
| slti : IType : func3 == 0b010, opcode == 0b001'0011, rd != 0; |
| sltiu : IType : func3 == 0b011, opcode == 0b001'0011, rd != 0; |
| xori : IType : func3 == 0b100, rd != 0, opcode == 0b001'0011; |
| ori : IType : func3 == 0b110, rd != 0b00000, opcode == 0b001'0011; |
| andi : IType : func3 == 0b111, opcode == 0b001'0011, rd != 0; |
| slli : RType : func7 == 0b000'0000, func3==0b001, opcode == 0b001'0011; |
| srli : RType : func7 == 0b000'0000, func3==0b101, rd != 0, opcode == 0b001'0011; |
| srai : RType : func7 == 0b010'0000, func3==0b101, opcode == 0b001'0011; |
| add : RType : func7 == 0b000'0000, func3==0b000, rd != 0, opcode == 0b011'0011; |
| sub : RType : func7 == 0b010'0000, func3==0b000, rd != 0, opcode == 0b011'0011; |
| sll : RType : func7 == 0b000'0000, func3==0b001, rd != 0, opcode == 0b011'0011; |
| slt : RType : func7 == 0b000'0000, func3==0b010, rd != 0, opcode == 0b011'0011; |
| sltu : RType : func7 == 0b000'0000, func3==0b011, rd != 0, opcode == 0b011'0011; |
| xor : RType : func7 == 0b000'0000, func3==0b100, rd != 0, opcode == 0b011'0011; |
| srl : RType : func7 == 0b000'0000, func3==0b101, rd != 0, opcode == 0b011'0011; |
| sra : RType : func7 == 0b010'0000, func3==0b101, rd != 0, opcode == 0b011'0011; |
| or : RType : func7 == 0b000'0000, func3==0b110, rd != 0, opcode == 0b011'0011; |
| and : RType : func7 == 0b000'0000, func3==0b111, rd != 0, opcode == 0b011'0011; |
| fence : Fence : fm == 0b0000, succ != 0b0000, func3 == 0b000, opcode == 0b000'1111; |
| fence_tso : Fence : fm == 0b1000, pred == 0b0011, succ == 0b0011, func3 == 0b000, opcode == 0b000'1111; |
| ecall : Inst32Format : bits == 0b0000'0000'0000'00000'000'00000, opcode == 0b111'0011; |
| ebreak : Inst32Format : bits == 0b0000'0000'0001'00000'000'00000, opcode == 0b111'0011; |
| // RiscV32 Instruction fence. |
| fencei : IType : func3 == 001, opcode == 0b000'1111; |
| // RiscV32 multiply divide. |
| mul : RType : func7 == 0b000'0001, func3 == 0b000, opcode == 0b011'0011; |
| mulh : RType : func7 == 0b000'0001, func3 == 0b001, opcode == 0b011'0011; |
| mulhsu : RType : func7 == 0b000'0001, func3 == 0b010, opcode == 0b011'0011; |
| mulhu : RType : func7 == 0b000'0001, func3 == 0b011, opcode == 0b011'0011; |
| div : RType : func7 == 0b000'0001, func3 == 0b100, opcode == 0b011'0011; |
| divu : RType : func7 == 0b000'0001, func3 == 0b101, opcode == 0b011'0011; |
| rem : RType : func7 == 0b000'0001, func3 == 0b110, opcode == 0b011'0011; |
| remu : RType : func7 == 0b000'0001, func3 == 0b111, opcode == 0b011'0011; |
| // RiscV32 atomic instructions. |
| lrw : AType : func5 == 0b0'0010, rs2 == 0, func3 == 0b010, opcode == 0b010'1111; |
| scw : AType : func5 == 0b0'0011, func3 == 0b010, opcode == 0b010'1111; |
| amoswapw : AType : func5 == 0b0'0001, func3 == 0b010, opcode == 0b010'1111; |
| amoaddw : AType : func5 == 0b0'0000, func3 == 0b010, opcode == 0b010'1111; |
| amoxorw : AType : func5 == 0b0'0100, func3 == 0b010, opcode == 0b010'1111; |
| amoandw : AType : func5 == 0b0'1100, func3 == 0b010, opcode == 0b010'1111; |
| amoorw : AType : func5 == 0b0'1000, func3 == 0b010, opcode == 0b010'1111; |
| amominw : AType : func5 == 0b1'0000, func3 == 0b010, opcode == 0b010'1111; |
| amomaxw : AType : func5 == 0b1'0100, func3 == 0b010, opcode == 0b010'1111; |
| amominuw : AType : func5 == 0b1'1000, func3 == 0b010, opcode == 0b010'1111; |
| amomaxuw : AType : func5 == 0b1'1100, func3 == 0b010, opcode == 0b010'1111; |
| // RiscV32 single precision floating point instructions. |
| flw : IType : func3 == 0b010, opcode == 0b000'0111; |
| fsw : SType : func3 == 0b010, opcode == 0b010'0111; |
| fmadd_s : R4Type : func2 == 0b00, opcode == 0b100'0011; |
| fmsub_s : R4Type : func2 == 0b00, opcode == 0b100'0111; |
| fnmsub_s : R4Type : func2 == 0b00, opcode == 0b100'1011; |
| fnmadd_s : R4Type : func2 == 0b00, opcode == 0b100'1111; |
| fadd_s : RType : func7 == 0b000'0000, opcode == 0b101'0011; |
| fsub_s : RType : func7 == 0b000'0100, opcode == 0b101'0011; |
| fmul_s : RType : func7 == 0b000'1000, opcode == 0b101'0011; |
| fdiv_s : RType : func7 == 0b000'1100, opcode == 0b101'0011; |
| fsqrt_s : RType : func7 == 0b010'1100, rs2 == 0, opcode == 0b101'0011; |
| fsgnj_s : RType : func7 == 0b001'0000, func3 == 0b000, opcode == 0b101'0011; |
| fsgnjn_s : RType : func7 == 0b001'0000, func3 == 0b001, opcode == 0b101'0011; |
| fsgnjx_s : RType : func7 == 0b001'0000, func3 == 0b010, opcode == 0b101'0011; |
| fmin_s : RType : func7 == 0b001'0100, func3 == 0b000, opcode == 0b101'0011; |
| fmax_s : RType : func7 == 0b001'0100, func3 == 0b001, opcode == 0b101'0011; |
| fcvt_ws : RType : func7 == 0b110'0000, rs2 == 0, opcode == 0b101'0011; |
| fcvt_wus : RType : func7 == 0b110'0000, rs2 == 1, opcode == 0b101'0011; |
| fmv_xw : RType : func7 == 0b111'0000, rs2 == 0, func3 == 0b000, opcode == 0b101'0011; |
| fcmpeq_s : RType : func7 == 0b101'0000, func3 == 0b010, opcode == 0b101'0011; |
| fcmplt_s : RType : func7 == 0b101'0000, func3 == 0b001, opcode == 0b101'0011; |
| fcmple_s : RType : func7 == 0b101'0000, func3 == 0b000, opcode == 0b101'0011; |
| fclass_s : RType : func7 == 0b111'0000, rs2 == 0, func3 == 0b001, opcode == 0b101'0011; |
| fcvt_sw : RType : func7 == 0b110'1000, rs2 == 0, opcode == 0b101'0011; |
| fcvt_swu : RType : func7 == 0b110'1000, rs2 == 1, opcode == 0b101'0011; |
| fmv_wx : RType : func7 == 0b111'1000, rs2 == 0, func3 == 0b000, opcode == 0b101'0011; |
| // RiscV32 double precision floating point instructions. |
| fld : IType : func3 == 0b011, opcode == 0b000'0111; |
| fsd : SType : func3 == 0b011, opcode == 0b010'0111; |
| fmadd_d : R4Type : func2 == 0b01, opcode == 0b100'0011; |
| fmsub_d : R4Type : func2 == 0b01, opcode == 0b100'0111; |
| fnmsub_d : R4Type : func2 == 0b01, opcode == 0b100'1011; |
| fnmadd_d : R4Type : func2 == 0b01, opcode == 0b100'1111; |
| fadd_d : RType : func7 == 0b000'0001, opcode == 0b101'0011; |
| fsub_d : RType : func7 == 0b000'0101, opcode == 0b101'0011; |
| fmul_d : RType : func7 == 0b000'1001, opcode == 0b101'0011; |
| fdiv_d : RType : func7 == 0b000'1101, opcode == 0b101'0011; |
| fsqrt_d : RType : func7 == 0b010'1101, rs2 == 0, opcode == 0b101'0011; |
| fsgnj_d : RType : func7 == 0b001'0001, func3 == 0b000, opcode == 0b101'0011; |
| fsgnjn_d : RType : func7 == 0b001'0001, func3 == 0b001, opcode == 0b101'0011; |
| fsgnjx_d : RType : func7 == 0b001'0001, func3 == 0b010, opcode == 0b101'0011; |
| fmin_d : RType : func7 == 0b001'0101, func3 == 0b000, opcode == 0b101'0011; |
| fmax_d : RType : func7 == 0b001'0101, func3 == 0b001, opcode == 0b101'0011; |
| fcvt_sd : RType : func7 == 0b010'0000, rs2 == 1, opcode == 0b101'0011; |
| fcvt_ds : RType : func7 == 0b010'0001, rs2 == 0, opcode == 0b101'0011; |
| fcmpeq_d : RType : func7 == 0b101'0001, func3 == 0b010, opcode == 0b101'0011; |
| fcmplt_d : RType : func7 == 0b101'0001, func3 == 0b001, opcode == 0b101'0011; |
| fcmple_d : RType : func7 == 0b101'0001, func3 == 0b000, opcode == 0b101'0011; |
| fclass_d : RType : func7 == 0b111'0001, rs2 == 0, func3 == 0b001, opcode == 0b101'0011; |
| fcvt_wd : RType : func7 == 0b110'0001, rs2 == 0, opcode == 0b101'0011; |
| fcvt_wud : RType : func7 == 0b110'0001, rs2 == 1, opcode == 0b101'0011; |
| fcvt_dw : RType : func7 == 0b110'1001, rs2 == 0, opcode == 0b101'0011; |
| fcvt_dwu : RType : func7 == 0b110'1001, rs2 == 1, opcode == 0b101'0011; |
| // RiscV32 CSR manipulation instructions. |
| csrrw : IType : func3 == 0b001, u_imm12 != 0b1100'0000'0000, rd != 0, opcode == 0b111'0011; |
| csrrs : IType : func3 == 0b010, rs1 != 0, rd != 0, opcode == 0b111'0011; |
| csrrc : IType : func3 == 0b011, rs1 != 0, rd != 0, opcode == 0b111'0011; |
| csrrs_nr : IType : func3 == 0b010, rs1 != 0, rd == 0, opcode == 0b111'0011; |
| csrrc_nr : IType : func3 == 0b011, rs1 != 0, rd == 0, opcode == 0b111'0011; |
| csrrw_nr : IType : func3 == 0b001, u_imm12 != 0b1100'0000'0000, rd == 0, opcode == 0b111'0011; |
| csrrs_nw : IType : func3 == 0b010, rs1 == 0, opcode == 0b111'0011; |
| csrrc_nw : IType : func3 == 0b011, rs1 == 0, opcode == 0b111'0011; |
| csrrwi : IType : func3 == 0b101, rd != 0, opcode == 0b111'0011; |
| csrrsi : IType : func3 == 0b110, rs1 != 0, rd != 0, opcode == 0b111'0011; |
| csrrci : IType : func3 == 0b111, rs1 != 0, rd != 0, opcode == 0b111'0011; |
| csrrsi_nr: IType : func3 == 0b110, rs1 != 0, rd == 0, opcode == 0b111'0011; |
| csrrci_nr: IType : func3 == 0b111, rs1 != 0, rd == 0, opcode == 0b111'0011; |
| csrrwi_nr: IType : func3 == 0b101, rd == 0, opcode == 0b111'0011; |
| csrrsi_nw: IType : func3 == 0b110, rs1 == 0, opcode == 0b111'0011; |
| csrrci_nw: IType : func3 == 0b111, rs1 == 0, opcode == 0b111'0011; |
| unimp : IType : func3 == 0b001, u_imm12 == 0b1100'0000'0000, rs1 == 0, rd == 0, opcode == 0b111'0011; |
| // RiscV32 Privileged instructions. |
| uret : Inst32Format : bits == 0b000'0000'00010'00000'000'00000, opcode == 0b111'0011; |
| sret : Inst32Format : bits == 0b000'1000'00010'00000'000'00000, opcode == 0b111'0011; |
| mret : Inst32Format : bits == 0b001'1000'00010'00000'000'00000, opcode == 0b111'0011; |
| wfi : Inst32Format : bits == 0b000'1000'00101'00000'000'00000, opcode == 0b111'0011; |
| sfence_vma_zz : RType : func7 == 0b000'1001, rs2 == 0, rs1 == 0, func3 == 0, rd == 0, opcode == 0b111'0011; |
| sfence_vma_zn : RType : func7 == 0b000'1001, rs2 != 0, rs1 == 0, func3 == 0, rd == 0, opcode == 0b111'0011; |
| sfence_vma_nz : RType : func7 == 0b000'1001, rs2 == 0, rs1 != 0, func3 == 0, rd == 0, opcode == 0b111'0011; |
| sfence_vma_nn : RType : func7 == 0b000'1001, rs2 != 0, rs1 != 0, func3 == 0, rd == 0, opcode == 0b111'0011; |
| }; |
| |
| // Encoding for RiscV hint instructions. |
| instruction group RiscVGHints32[32] : Inst32Format { |
| lui_hint: UType : opcode == 0b011'0111, rd == 0; |
| auipc_hint: UType : opcode == 0b001'0111, rd == 0; |
| addi_hint1: IType : func3 == 0b000, opcode == 0b001'0011, rd == 0, rs1 != 0; |
| addi_hint2: IType : func3 == 0b000, opcode == 0b001'0011, rd == 0, imm12 != 0; |
| slti_hint : IType : func3 == 0b010, opcode == 0b001'0011, rd == 0; |
| sltiu_hint: IType : func3 == 0b011, opcode == 0b001'0011, rd == 0; |
| xori_hint: IType : func3 == 0b100, rd == 0, opcode == 0b001'0011; |
| ori_hint: IType : func3 == 0b110, rd == 0b00000, opcode == 0b001'0011; |
| andi_hint: IType : func3 == 0b111, opcode == 0b001'0011, rd == 0; |
| srli_hint: RType : func7 == 0b000'0000, func3==0b101, rd == 0, opcode == 0b001'0011; |
| slt_hint: RType : func7 == 0b000'0000, func3==0b010, rd == 0, opcode == 0b011'0011; |
| slli_semihost: RType : func7 == 0b000'0000, func3==0b001, rd == 0, rs1 == 0, r_uimm5 == 31, opcode == 0b001'0011; |
| slli_hint1: RType : func7 == 0b000'0000, func3==0b001, rd == 0, rs1 != 0, opcode == 0b001'0011; |
| slli_hint2: RType : func7 == 0b000'0000, func3==0b001, rd == 0, r_uimm5 != 31, opcode == 0b001'0011; |
| srai_semihost: RType : func7 == 0b010'0000, func3==0b101, rd == 0, rs1 == 0, r_uimm5 == 7, opcode == 0b001'0011; |
| srai_hint1: RType : func7 == 0b010'0000, func3==0b101, rd == 0, rs1 != 0, opcode == 0b001'0011; |
| srai_hint2: RType : func7 == 0b010'0000, func3==0b101, rd == 0, r_uimm5 != 7, opcode == 0b001'0011; |
| add_hint1: RType : func7 == 0b000'0000, func3==0b000, rd == 0, rs1 != 0, opcode == 0b011'0011; |
| add_hint2: RType : func7 == 0b000'0000, func3==0b000, rd == 0, rs1 == 0, rs2 > 5, opcode == 0b011'0011; |
| add_hint3: RType : func7 == 0b000'0000, func3==0b000, rd == 0, rs1 == 0, rs2 < 2, opcode == 0b011'0011; |
| sub_hint: RType : func7 == 0b010'0000, func3==0b000, rd == 0, opcode == 0b011'0011; |
| sll_hint: RType : func7 == 0b000'0000, func3==0b001, rd == 0, opcode == 0b011'0011; |
| sltu_hint: RType : func7 == 0b000'0000, func3==0b011, rd == 0, opcode == 0b011'0011; |
| xor_hint: RType : func7 == 0b000'0000, func3==0b100, rd == 0, opcode == 0b011'0011; |
| srl_hint: RType : func7 == 0b000'0000, func3==0b101, rd == 0, opcode == 0b011'0011; |
| sra_hint: RType : func7 == 0b010'0000, func3==0b101, rd == 0, opcode == 0b011'0011; |
| or_hint : RType : func7 == 0b000'0000, func3==0b110, rd == 0, opcode == 0b011'0011; |
| and_hint: RType : func7 == 0b000'0000, func3==0b111, rd == 0, opcode == 0b011'0011; |
| fence_hint1: Fence : func3==0b000, rd == 0, rs1 != 0, fm == 0, pred == 0, opcode == 0b000'1111; |
| fence_hint2: Fence : func3==0b000, rd == 0, rs1 != 0, fm == 0, succ == 0, opcode == 0b000'1111; |
| fence_hint3: Fence : func3==0b000, rd != 0, rs1 == 0, fm == 0, pred == 0, opcode == 0b000'1111; |
| fence_hint4: Fence : func3==0b000, rd != 0, rs1 == 0, fm == 0, succ == 0, opcode == 0b000'1111; |
| fence_hint5: Fence : func3==0b000, rd == 0, rs1 == 0, fm == 0, pred == 0, succ != 0, opcode == 0b000'1111; |
| fence_hint6: Fence : func3==0b000, rd == 0, rs1 == 0, fm == 0, succ == 0, opcode == 0b000'1111; |
| fence_hint7: Fence : func3==0b000, rd != 0, rs1 == 0, fm == 0, pred != 1, succ == 0, opcode == 0b000'1111; |
| }; |
| |
| instruction group RiscVCInst16 = {RiscVCInstBase16, RiscVCHints16}; |
| |
| // Compact instruction encodings. |
| instruction group RiscVCInstBase16[16] : Inst16Format { |
| caddi4spn : CIW: func3 == 0b000, op == 0b00, imm8 != 0; |
| cfld : CL : func3 == 0b001, op == 0b00; |
| clw : CL : func3 == 0b010, op == 0b00; |
| cflw : CL : func3 == 0b011, op == 0b00; |
| cfsd : CS : func3 == 0b101, op == 0b00; |
| csw : CS : func3 == 0b110, op == 0b00; |
| cfsw : CS : func3 == 0b111, op == 0b00; |
| cnop : CI : func3 == 0b000, imm1 == 0, rs1 == 0, imm5 == 0, op == 0b01; |
| caddi : CI : func3 == 0b000, imm6 != 0, rd != 0, op == 0b01; |
| cjal : CJ : func3 == 0b001, op == 0b01; |
| cli : CI : func3 == 0b010, rd != 0, op == 0b01; |
| caddi16sp : CI : func3 == 0b011, rd == 2, op == 0b01; |
| clui : CI : func3 == 0b011, rd != 0, rd != 2, op == 0b01; |
| csrli : CB : func3 == 0b100, imm3 == 0b000, op == 0b01; |
| csrai : CB : func3 == 0b100, imm3 == 0b001, op == 0b01; |
| candi : CB : func3 == 0b100, func2 == 0b10, op == 0b01; |
| csub : CA : func6 == 0b100'011, func2 == 0b00, op == 0b01; |
| cxor : CA : func6 == 0b100'011, func2 == 0b01, op == 0b01; |
| cor : CA : func6 == 0b100'011, func2 == 0b10, op == 0b01; |
| cand : CA : func6 == 0b100'011, func2 == 0b11, op == 0b01; |
| cj : CJ : func3 == 0b101, op == 0b01; |
| cbeqz : CB : func3 == 0b110, op == 0b01; |
| cbnez : CB : func3 == 0b111, op == 0b01; |
| cslli : CI : func3 == 0b000, imm1 == 0, rs1 != 0, op == 0b10; |
| cfldsp : CI : func3 == 0b001, op == 0b10; |
| clwsp : CI : func3 == 0b010, rd != 0, op == 0b10; |
| cflwsp : CI : func3 == 0b011, op == 0b10; |
| cjr : CR : func4 == 0b1000, rs1 != 0, rs2 == 0, op == 0b10; |
| cmv : CR : func4 == 0b1000, rs1 != 0, rs2 != 0, op == 0b10; |
| cebreak : CR : func4 == 0b1001, rs1 == 0, rs2 == 0, op == 0b10; |
| cjalr : CR : func4 == 0b1001, rs1 != 0, rs2 == 0, op == 0b10; |
| cadd : CR : func4 == 0b1001, rs1 != 0, rs2 != 0, op == 0b10; |
| cfsdsp : CSS: func3 == 0b101, op == 0b10; |
| cswsp : CSS: func3 == 0b110, op == 0b10; |
| cfswsp : CSS: func3 == 0b111, op == 0b10; |
| cunimp : Inst16Format : func3 == 0b000, bits == 0b000'0000'0000, op == 0b00; |
| }; |
| |
| instruction group RiscVCHints16[16] : Inst16Format { |
| cnop_hint : CI : func3 == 0b000, imm6 != 0, rs1 == 0, op == 0b01; |
| caddi_hint: CI : func3 == 0b000, imm6 == 0, rd != 0, op == 0b01; |
| cli_hint : CI : func3 == 0b010, rd == 0, op == 0b01; |
| clui_hint : CI : func3 == 0b011, rd == 0, imm6 != 0, op == 0b01; |
| cmv_hint : CR : func4 == 0b1000, rs1 == 0, rs2 != 0, op == 0b10; |
| cslli_hint: CI : func3 == 0b000, imm6 != 0, rd == 0, op == 0b10; |
| cadd_hint : CR : func4 == 0b1001, rs1 == 0, rs2 != 0, rs2 != 2, rs2 != 3, rs2 != 4, rs2 != 5, op == 0b10; |
| }; |