| // 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. |
| |
| // This file refactors the original "C" extension into the new set of Zc* |
| // extensions. These should be preferred for new simulator targets. |
| |
| // Compact instruction formats. |
| |
| format Inst16Format[16] { |
| fields: |
| unsigned func3[3]; |
| unsigned bits[11]; |
| unsigned op[2]; |
| }; |
| |
| format CA[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned rs1p[3]; |
| unsigned func2[2]; |
| unsigned fs2p[3]; |
| unsigned op[2]; |
| overlays: |
| unsigned uimm2[2] = func2; |
| unsigned uimm1[1] = func2[0]; |
| unsigned func5[5] = func2, fs2p; |
| unsigned rs1[5] = 0b01, rs1p; |
| unsigned rs2[5] = 0b01, fs2p; |
| unsigned rd[5] = 0b01, rs1p; |
| }; |
| |
| format CB[16] : Inst16Format { |
| fields: |
| unsigned func3[3]; |
| unsigned imm3[3]; |
| unsigned rs1p[3]; |
| unsigned imm5[5]; |
| unsigned op[2]; |
| overlays: |
| unsigned func2[2] = [11, 10]; |
| unsigned func5[5] = [12..10, 6..5]; |
| unsigned shamt[6] = [12, 6..2]; |
| unsigned rs2p[3] = [4..2]; |
| unsigned rs2[5] = 0b10, [4..2]; |
| signed bimm[9] = imm3[2], imm5[4..3, 0], imm3[1..0], imm5[2..1], 0b0; |
| }; |
| |
| format CI[16] : Inst16Format { |
| fields: |
| unsigned func3[3]; |
| unsigned imm1[1]; |
| unsigned rs1[5]; |
| unsigned imm5[5]; |
| unsigned op[2]; |
| overlays: |
| unsigned rd[5] = rs1; |
| signed imm6[6] = imm1, imm5; |
| unsigned uimm6[6] = imm1, imm5; |
| signed imm18[18] = imm1, imm5, 0b0000'0000'0000; |
| signed ci_imm10[10] = imm1, imm5[2..1, 3, 0, 4], 0b0000; |
| unsigned ci_imm_w[8] = imm5[1..0], imm1, imm5[4..2], 0b00; |
| unsigned ci_imm_d[9] = imm5[2..0], imm1, imm5[4..3], 0b000; |
| }; |
| |
| format CIW[16] : Inst16Format { |
| fields: |
| unsigned func3[3]; |
| unsigned imm8[8]; |
| unsigned rdp[3]; |
| unsigned op[2]; |
| overlays: |
| unsigned rd[5] = 0b01, rdp; |
| unsigned ciw_imm10[10] = imm8[5..2, 7..6, 0, 1], 0b00; |
| }; |
| |
| format CJ[16] : Inst16Format { |
| fields: |
| unsigned func3[3]; |
| unsigned imm11[11]; |
| unsigned op[2]; |
| overlays: |
| signed jimm[12] = imm11[10, 6, 8..7, 4, 5, 0, 9, 3..1], 0b0; |
| }; |
| |
| format CL[16] : Inst16Format { |
| fields: |
| unsigned func3[3]; |
| unsigned imm3[3]; |
| unsigned rs1p[3]; |
| unsigned imm2[2]; |
| unsigned rdp[3]; |
| unsigned op[2]; |
| overlays: |
| unsigned cl_rs1[5] = 0b01, rs1p; |
| unsigned cl_rd[5] = 0b01, rdp; |
| unsigned cl_imm_w[7] = imm2[0], imm3, imm2[1], 0b00; |
| unsigned cl_imm_d[8] = imm2, imm3, 0b000; |
| }; |
| |
| format CLB[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned rs1p[3]; |
| unsigned uimm2[2]; |
| unsigned rdp[3]; |
| unsigned op[2]; |
| overlays: |
| unsigned rs1[5] = 0b01, rs1p; |
| unsigned rd[5] = 0b01, rdp; |
| }; |
| |
| format CLH[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned rs1p[3]; |
| unsigned func1[1]; |
| unsigned uimm1[1]; |
| unsigned rdp[3]; |
| unsigned op[2]; |
| overlays: |
| unsigned rs1[5] = 0b01, rs1p; |
| unsigned rd[5] = 0b01, rdp; |
| unsigned uimm2[2] = uimm1, 0b0; |
| }; |
| |
| format CMJT[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned index[8]; |
| unsigned op[2]; |
| overlays: |
| }; |
| |
| format CMMV[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned rs1p[3]; |
| unsigned func2[2]; |
| unsigned rs2p[3]; |
| unsigned op[2]; |
| overlays: |
| unsigned rs1[5] = 0b01, rs1p; |
| unsigned rs2[5] = 0b01, rs2p; |
| }; |
| |
| format CMPP[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned func2[2]; |
| unsigned rlist[4]; |
| unsigned spimm[2]; |
| unsigned op[2]; |
| }; |
| |
| format CR[16] : Inst16Format { |
| fields: |
| unsigned func4[4]; |
| unsigned rs1[5]; |
| unsigned rs2[5]; |
| unsigned op[2]; |
| }; |
| |
| format CS[16] : Inst16Format { |
| fields: |
| unsigned func3[3]; |
| unsigned imm3[3]; |
| unsigned rs1p[3]; |
| unsigned imm2[2]; |
| unsigned rs2p[3]; |
| unsigned op[2]; |
| overlays: |
| unsigned cs_rs1[5] = 0b01, rs1p; |
| unsigned cs_rs2[5] = 0b01, rs2p; |
| unsigned cs_imm_w[7] = imm2[0], imm3, imm2[1], 0b00; |
| unsigned cs_imm_d[8] = imm2, imm3, 0b000; |
| }; |
| |
| format CSB[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned rs1p[3]; |
| unsigned uimm2[2]; |
| unsigned rs2p[3]; |
| unsigned op[2]; |
| overlays: |
| unsigned rs1[5] = 0b01, rs1p; |
| unsigned rs2[5] = 0b01, rs2p; |
| }; |
| |
| format CSH[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned rs1p[3]; |
| unsigned func1[1]; |
| unsigned uimm1[1]; |
| unsigned rs2p[3]; |
| unsigned op[2]; |
| overlays: |
| unsigned rs1[5] = 0b01, rs1p; |
| unsigned rs2[5] = 0b01, rs2p; |
| unsigned uimm2[2] = uimm1, 0b0; |
| }; |
| |
| format CSS[16] : Inst16Format { |
| fields: |
| unsigned func3[3]; |
| unsigned imm6[6]; |
| unsigned rs2[5]; |
| unsigned op[2]; |
| overlays: |
| unsigned css_imm_w[8] = imm6[1..0], imm6[5..2], 0b00; |
| unsigned css_imm_d[9] = imm6[2..0], imm6[5..3], 0b000; |
| }; |
| |
| format CU[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned rs1p[3]; |
| unsigned func5[5]; |
| unsigned op[2]; |
| overlays: |
| unsigned rs1[5] = 0b01, rs1p; |
| unsigned rd[5] = 0b01, rs1p; |
| }; |
| |
| // Non floating point compact instructions from "C". |
| instruction group RiscVZca[16] : Inst16Format { |
| caddi4spn : CIW: func3 == 0b000, op == 0b00, imm8 != 0; |
| clw : CL : func3 == 0b010, op == 0b00; |
| csw : CS : func3 == 0b110, 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; |
| clwsp : CI : func3 == 0b010, rd != 0, 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; |
| cswsp : CSS: func3 == 0b110, op == 0b10; |
| } |
| |
| // Single-precision floating point compact instructions from "C". |
| instruction group RiscVZcf[16] : Inst16Format { |
| cflw : CL : func3 == 0b011, op == 0b00; |
| cfsw : CS : func3 == 0b111, op == 0b00; |
| cflwsp : CI : func3 == 0b011, op == 0b10; |
| cfswsp : CSS: func3 == 0b111, op == 0b10; |
| } |
| |
| // Double-precision floating point compact instructions from "C". |
| instruction group RiscVZcd[16] : Inst16Format { |
| cfld : CL : func3 == 0b001, op == 0b00; |
| cfldsp : CI : func3 == 0b001, op == 0b10; |
| cfsd : CS : func3 == 0b101, op == 0b00; |
| cfsdsp : CSS: func3 == 0b101, op == 0b10; |
| } |
| |
| // Simple code-size saving instructions that are easy to implement on all CPUs. |
| instruction group RiscVZcb32[16] : Inst16Format { |
| c_lbu : CLB : func6 == 0b100'000, op == 0b00; |
| c_lhu : CLH : func6 == 0b100'001, func2[1] == 0b0, op == 0b00; |
| c_lh : CLH : func6 == 0b100'001, func2[1] == 0b1, op == 0b00; |
| c_sb : CSB : func6 == 0b100'010, op2 == 0b00; |
| c_sh : CSH : func6 == 0b100'011, func2[1] == 0b0, op == 0b00; |
| c_zext_b : CU : func6 == 0b100'111, func5 == 0b11000, op = 0b01; |
| c_sext_b : CU : func6 == 0b100'111, func5 == 0b11001, op == 0b01; |
| c_zext_h : CU : func6 == 0b100'111, func5 == 0b11010, op == 0b01; |
| c_sext_h : CU : func6 == 0b100'111, func5 == 0b11011, op == 0b01; |
| c_not : CU : func6 == 0b100'111, func5 == 0b11101, op == 0b01;; |
| c_mul : CA : func6 == 0b100'111, func2 == 0b10, op == 0b01; |
| } |
| |
| // For 64 bit CPUs the zext_w instruction is added. |
| instruction group RiscV64Zcb64[64] : Inst16Format { |
| c_zext_w : CU : func6 == 0b100'111, func5 = 0b11100, op == 0b01; |
| } |
| |
| // Push/pop/register move instructions. Incompatible with Zcf and Zcd. |
| instruction group RiscVZcmp[16] : Inst16Format { |
| cm_push : CMPP : func8 == 0b101'11000, rlist > 3, op == 0b10; |
| cm_pop : CMPP : func8 == 0b101'11010, rlist > 3,op == 0b10; |
| cm_popret : CMPP : func8 == 0b101'11110, rlist > 3,op == 0b10; |
| cm_popretz : CMPP : func8 == 0b101'11100, rlist > 3, op == 0b10; |
| cm_mvsa01 : CMMV : func6 == 0b101'011, func2 == 0b01, rs1p != rs2p, op == 0b10; |
| cm_mva01s : CMMV : func6 == 0b101'011, func2 == 0b11, op == 0b10; |
| } |
| |
| format CMJT[16] : Inst16Format { |
| fields: |
| unsigned func6[6]; |
| unsigned index[8]; |
| unsigned op[2]; |
| } |
| |
| // Jump table instructions. |
| instruction group RiscVZcmt[16] : Inst16Format { |
| cm_jt : CMJT : func6 == 0b101'000, index < 32, op == 0b10; |
| cm_jalt : CMJT : func6 == 0b101'000, index >= 32,op == 0b10; |
| } |