// Copyright (c) 2013-2019 Bluespec, Inc. All Rights Reserved

// ================================================================
// This is an 'include' file, not a separate BSV package
//
// Contains RISC-V ISA defs for the 'C' ("compressed") extension
// i.e., 16-bit instructions
//
// ================================================================
// Instruction field encodings

typedef  Bit #(16)  Instr_C;

Bit #(2) opcode_C0 = 2'b00;
Bit #(2) opcode_C1 = 2'b01;
Bit #(2) opcode_C2 = 2'b10;

Bit #(3) funct3_C_LWSP               = 3'b_010;
Bit #(3) funct3_C_LDSP               = 3'b_011;     // RV64 and RV128
Bit #(3) funct3_C_LQSP               = 3'b_001;     // RV128
Bit #(3) funct3_C_FLWSP              = 3'b_011;     // RV32FC
Bit #(3) funct3_C_FLDSP              = 3'b_001;     // RV32DC, RV64DC

Bit #(3) funct3_C_SWSP               = 3'b_110;

Bit #(3) funct3_C_SQSP               = 3'b_101;     // RV128
Bit #(3) funct3_C_FSDSP              = 3'b_101;     // RV32DC, RV64DC

Bit #(3) funct3_C_SDSP               = 3'b_111;     // RV64 and RV128
Bit #(3) funct3_C_FSWSP              = 3'b_111;     // RV32FC

Bit #(3) funct3_C_LQ                 = 3'b_001;     // RV128
Bit #(3) funct3_C_FLD                = 3'b_001;     // RV32DC, RV64DC

Bit #(3) funct3_C_LW                 = 3'b_010;

Bit #(3) funct3_C_LD                 = 3'b_011;     // RV64 and RV128
Bit #(3) funct3_C_FLW                = 3'b_011;     // RV32FC

Bit #(3) funct3_C_FSD                = 3'b_101;     // RV32DC, RV64DC
Bit #(3) funct3_C_SQ                 = 3'b_101;     // RV128

Bit #(3) funct3_C_SW                 = 3'b_110;

Bit #(3) funct3_C_SD                 = 3'b_111;     // RV64 and RV128
Bit #(3) funct3_C_FSW                = 3'b_111;     // RV32FC

Bit #(3) funct3_C_JAL                = 3'b_001;     // RV32
Bit #(3) funct3_C_J                  = 3'b_101;
Bit #(3) funct3_C_BEQZ               = 3'b_110;
Bit #(3) funct3_C_BNEZ               = 3'b_111;

Bit #(4) funct4_C_JR                 = 4'b_1000;
Bit #(4) funct4_C_JALR               = 4'b_1001;

Bit #(3) funct3_C_LI                 = 3'b_010;
Bit #(3) funct3_C_LUI                = 3'b_011;     // RV64 and RV128

Bit #(3) funct3_C_NOP                = 3'b_000;
Bit #(3) funct3_C_ADDI               = 3'b_000;
Bit #(3) funct3_C_ADDIW              = 3'b_001;
Bit #(3) funct3_C_ADDI16SP           = 3'b_011;
Bit #(3) funct3_C_CIncOffsetImm16CSP = 3'b_011;
Bit #(3) funct3_C_ADDI4SPN           = 3'b_000;
Bit #(3) funct3_C_CIncOffsetImm4CSPN = 3'b_000;
Bit #(3) funct3_C_SLLI               = 3'b_000;

Bit #(3) funct3_C_SRLI               = 3'b_100;
Bit #(2) funct2_C_SRLI               = 2'b_00;

Bit #(3) funct3_C_SRAI               = 3'b_100;
Bit #(2) funct2_C_SRAI               = 2'b_01;

Bit #(3) funct3_C_ANDI               = 3'b_100;
Bit #(2) funct2_C_ANDI               = 2'b_10;

Bit #(4) funct4_C_MV                 = 4'b_1000;
Bit #(4) funct4_C_ADD                = 4'b_1001;

Bit #(6) funct6_C_AND                = 6'b_100_0_11;
Bit #(2) funct2_C_AND                = 2'b_11;

Bit #(6) funct6_C_OR                 = 6'b_100_0_11;
Bit #(2) funct2_C_OR                 = 2'b_10;

Bit #(6) funct6_C_XOR                = 6'b_100_0_11;
Bit #(2) funct2_C_XOR                = 2'b_01;

Bit #(6) funct6_C_SUB                = 6'b_100_0_11;
Bit #(2) funct2_C_SUB                = 2'b_00;

Bit #(6) funct6_C_ADDW               = 6'b_100_1_11;
Bit #(2) funct2_C_ADDW               = 2'b_01;

Bit #(6) funct6_C_SUBW               = 6'b_100_1_11;
Bit #(2) funct2_C_SUBW               = 2'b_00;

Bit #(4) funct4_C_EBREAK             = 4'b_1001;

// ================================================================
// Functions to extract instruction fields from 'C' (compressed) instructions

function Tuple4 #(Bit #(4), RegName, RegName, Bit #(2))  fv_ifields_CR_type (Instr_C  instr);
   let funct4 = instr [15:12];
   let rd_rs1 = instr [11: 7];
   let rs2    = instr [ 6: 2];
   let op     = instr [ 1: 0];
   return tuple4 (funct4, rd_rs1, rs2, op);
endfunction

function Tuple5 #(Bit #(3), Bit #(1), Bit #(5), Bit #(5), Bit #(2))  fv_ifields_CI_type (Instr_C  instr);
   let funct3     = instr [15:13];
   let imm_at_12  = instr [12:12];
   let rd_rs1     = instr [11: 7];
   let imm_at_6_2 = instr [ 6: 2];
   let op         = instr [ 1: 0];
   return tuple5 (funct3, imm_at_12, rd_rs1, imm_at_6_2, op);
endfunction

function Tuple4 #(Bit #(3), Bit #(6), RegName, Bit #(2))  fv_ifields_CSS_type (Instr_C  instr);
   let funct3      = instr [15:13];
   let imm_at_12_7 = instr [12: 7];
   let rs2         = instr [ 6: 2];
   let op          = instr [ 1: 0];
   return tuple4 (funct3, imm_at_12_7, rs2, op);
endfunction

function Tuple4 #(Bit #(3), Bit #(8), RegName, Bit #(2))  fv_ifields_CIW_type (Instr_C  instr);
   let funct3      = instr [15:13];
   let imm_at_12_5 = instr [12: 5];
   let rd          = {2'b01, instr [4:2]};
   let op          = instr [ 1: 0];
   return tuple4 (funct3, imm_at_12_5, rd, op);
endfunction

function Tuple6 #(Bit #(3), Bit #(3), RegName, Bit #(2), RegName, Bit #(2))  fv_ifields_CL_type (Instr_C  instr);
   let funct3       = instr [15:13];
   let imm_at_12_10 = instr [12:10];
   let rs1          = {2'b01, instr [9:7]};
   let imm_at_6_5   = instr [ 6: 5];
   let rd           = {2'b01, instr [4:2]};
   let op           = instr [ 1: 0];
   return tuple6 (funct3, imm_at_12_10, rs1, imm_at_6_5, rd, op);
endfunction

function Tuple6 #(Bit #(3), Bit #(3), RegName, Bit #(2), RegName, Bit #(2))  fv_ifields_CS_type (Instr_C  instr);
   let funct3       = instr [15:13];
   let imm_at_12_10 = instr [12:10];
   let rs1          = {2'b01, instr [9:7]};
   let imm_at_6_5   = instr [ 6: 5];
   let rs2          = {2'b01, instr [4:2]};
   let op           = instr [ 1: 0];
   return tuple6 (funct3, imm_at_12_10, rs1, imm_at_6_5, rs2, op);
endfunction

function Tuple5 #(Bit #(6), RegName, Bit #(2), RegName, Bit #(2))  fv_ifields_CA_type (Instr_C  instr);
   let funct6       = instr [15:10];
   let rd_rs1       = {2'b01, instr [9:7]};
   let funct2       = instr [ 6: 5];
   let rs2          = {2'b01, instr [4:2]};
   let op           = instr [ 1: 0];
   return tuple5 (funct6, rd_rs1, funct2, rs2, op);
endfunction

function Tuple5 #(Bit #(3), Bit #(3), RegName, Bit #(5), Bit #(2))  fv_ifields_CB_type (Instr_C  instr);
   let funct3       = instr [15:13];
   let imm_at_12_10 = instr [12:10];
   let rs1          = {2'b01, instr [9:7]};
   let imm_at_6_2   = instr [ 6: 2];
   let op           = instr [ 1: 0];
   return tuple5 (funct3, imm_at_12_10, rs1, imm_at_6_2, op);
endfunction

function Tuple3 #(Bit #(3), Bit #(11), Bit #(2))  fv_ifields_CJ_type (Instr_C  instr);
   let funct3       = instr [15:13];
   let imm_at_12_2  = instr [12: 2];
   let op           = instr [ 1: 0];
   return tuple3 (funct3, imm_at_12_2, op);
endfunction

// ================================================================
