/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matt Thomas of 3am Software Foundry.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _RISCV_INSN_H_
#define _RISCV_INSN_H_
/*
* I have corrected and updated this, but it's the wrong way to do it.
* It's still used by ddb_machdep.c but that code should be fixed to
* use the newer stuff below. - dholland
*/
union riscv_insn {
uint32_t val;
/* register ops */
struct {
unsigned int r_opcode : 7;
unsigned int r_rd : 5;
unsigned int r_funct3 : 3;
unsigned int r_rs1 : 5;
unsigned int r_rs2 : 5;
unsigned int r_funct7 : 7;
} type_r;
/* 32-bit shifts */
struct {
unsigned int rs32_opcode : 7;
unsigned int rs32_rd : 5;
unsigned int rs32_funct3 : 3;
unsigned int rs32_rs1 : 5;
unsigned int rs32_shamt : 5;
unsigned int rs32_funct7 : 7;
} type_rs32;
/* 64-bit shifts */
struct {
unsigned int rs64_opcode : 7;
unsigned int rs64_rd : 5;
unsigned int rs64_funct3 : 3;
unsigned int rs64_rs1 : 5;
unsigned int rs64_shamt : 6;
unsigned int rs64_zero : 1;
unsigned int rs64_funct5 : 5;
} type_rs64;
/* atomics */
struct {
unsigned int ra_opcode : 7;
unsigned int ra_rd : 5;
unsigned int ra_funct3 : 3;
unsigned int ra_rs1 : 5;
unsigned int ra_rs2 : 5;
unsigned int ra_rl : 1;
unsigned int ra_aq : 1;
unsigned int ra_funct5 : 5;
} type_ra;
/* certain fpu ops */
struct {
unsigned int rf_opcode : 7;
unsigned int rf_rd : 5;
unsigned int rf_rm : 3;
unsigned int rf_rs1 : 5;
unsigned int rf_rs2 : 5;
unsigned int rf_size : 2;
unsigned int rf_funct5 : 5;
} type_rf;
/* other fpu ops */
struct {
unsigned int rf4_opcode : 7;
unsigned int rf4_rd : 5;
unsigned int rf4_rm : 3;
unsigned int rf4_rs1 : 5;
unsigned int rf4_rs2 : 5;
unsigned int rf4_size : 2;
unsigned int rf4_rs3 : 5;
} type_rf4;
/* immediates */
struct {
unsigned int i_opcode : 7;
unsigned int i_rd : 5;
unsigned int i_funct3 : 3;
unsigned int i_rs1 : 5;
signed int i_imm11to0 : 12;
} type_i;
/* stores */
struct {
unsigned int s_opcode : 7;
unsigned int s_imm4_to_0 : 5;
unsigned int s_funct3 : 3;
unsigned int s_rs1 : 5;
unsigned int s_rs2 : 5;
signed int s_imm11_to_5 : 7;
} type_s;
/* branches */
struct {
unsigned int b_opcode : 7;
unsigned int b_imm11 : 1;
unsigned int b_imm4to1 : 4;
unsigned int b_funct3 : 3;
unsigned int b_rs1 : 5;
unsigned int b_rs2 : 5;
unsigned int b_imm10to5 : 6;
signed int b_imm12 : 1;
} type_b;
/* large immediate constants */
struct {
unsigned int u_opcode : 7;
unsigned int u_rd : 5;
signed int u_imm31to12 : 20;
} type_u;
/* large immediate jumps */
struct {
unsigned int j_opcode : 7;
unsigned int j_rd : 5;
unsigned int j_imm19to12 : 9;
unsigned int j_imm11 : 1;
unsigned int j_imm10to1 : 9;
signed int j_imm20 : 1;
} type_j;
};
/*
* old macro still in use with the above
* (XXX, doesn't handle 16-bit instructions)
*/
/* CS format immediates are the same as the CL ones */
#define INSN16_IMM_CS_W(insn) INSN16_IMM_CL_W(insn)
#define INSN16_IMM_CS_D(insn) INSN16_IMM_CL_D(insn)
#define INSN16_IMM_CS_Q(insn) INSN16_IMM_CL_Q(insn)
/*
* Values for the secondary/tertiary opcode field funct7 in 32-bit instructions
* for various primary and secondary opcodes.
*
* Note: for many of these the opcodes shown are the top 5 bits and the
* bottom two serve a separate purpose.
*/
// primary is OP (0b01100, 12)
#define OP_ARITH 0b0000000
#define OP_MULDIV 0b0000001
#define OP_NARITH 0b0100000
// primary is OPFP (0b10100, 20), bottom two bits (operand size)
// these bits also give the size for FMADD/FMSUB/FNMSUB/FNMADD
// and for FCVTFF they appear at the bottom of the rs2 field as well
#define OPFP_S 0b00
#define OPFP_D 0b01
#define OPFP_Q 0b11
// in some instructions they're an integer operand size instead
#define OPFP_W 0b00
#define OPFP_WU 0b01
#define OPFP_L 0b10
#define OPFP_LU 0b11
// primary is AMO (0b01011, 11), top 5 bits
// (bottom two bits are ACQUIRE and RELEASE flags respectively)
// funct3 gives the operand size
#define AMO_ADD 0b00000
#define AMO_SWAP 0b00001
#define AMO_LR 0b00010
#define AMO_SC 0b00011
#define AMO_XOR 0b00100
#define AMO_OR 0b01000
#define AMO_AND 0b01100
#define AMO_MIN 0b10000
#define AMO_MAX 0b10100
#define AMO_MINU 0b11000
#define AMO_MAXU 0b11100
// primary is SYSTEM (0b11100, 28) and funct3 is PRIV (0)
#define PRIV_USER 0b0000000
#define PRIV_SYSTEM 0b0001000
#define PRIV_SFENCE_VMA 0b0001001
#define PRIV_HFENCE_BVMA 0b0010001
#define PRIV_MACHINE 0b0011000
#define PRIV_HFENCE_GVMA 0b1010001
/*
* Values for the secondary/tertiary opcode field funct3 in 32-bit instructions
* for various primary and secondary opcodes.
*/
// primary is AMO (0b01011, 11), funct7 gives the operation
#define AMO_W 0b010
#define AMO_D 0b011 // RV64I
// primary is
// OPIMM (0b00100, 4)
// OPIMM32 (0b00110, 6)
// OP (0b01100, 12) when funct7 is ARITH or NARITH
// OP32 (0b01110, 14)
// OP OP OP32 OP32
// given: OPIMM OPIMM32 ARITH NARITH ARITH NARITH
#define OP_ADDSUB 0b000 // addi addiw add sub addw subw
#define OP_SLL 0b001 // (1) (2) sll - sllw -
#define OP_SLT 0b010 // slti - slt - - -
#define OP_SLTU 0b011 // sltiu - sltu - - -
#define OP_XOR 0b100 // xori - xor - - -
#define OP_SRX 0b101 // (3) (4) srl sra srlw sraw
#define OP_OR 0b110 // ori - or - - -
#define OP_AND 0b111 // andi - and - - -
//
// (1) slli when funct7 is ARITH
// (2) slliw when funct7 is ARITH
// (3) srli when funct7 is ARITH, srai when funct7 is NARITH
// (4) srliw when funct7 is ARITH, sraiw when funct7 is NARITH
//
// caution: on RV64, the immediate field of slli/srli/srai bleeds into
// funct7, so you have to actually only test the upper 6 bits of funct7.
// (and if RV128 ever actually happens, the upper 5 bits; conveniently
// that aligns with other uses of those 5 bits)
//
// primary is
// OP (0b01100, 12) when funct7 is MULDIV
// OP32 (0b01110, 14) when funct7 is MULDIV
//
// given: OP OP32
#define OP_MUL 0b000 // mul mulw
#define OP_MULH 0b001 // mulh -
#define OP_MULHSU 0b010 // mulhsu -
#define OP_MULHU 0b011 // mulhu -
#define OP_DIV 0b100 // div divw
#define OP_DIVU 0b101 // divu divuw
#define OP_REM 0b110 // rem remw
#define OP_REMU 0b111 // remu remuw
// the funct3 field is not used for
// AUIPC (0b00101, 5)
// LUI (0b01101, 13)
// JALR (0b11001, 25) (or rather, it's always 0)
// JAL (0b11011, 27)
// and for these there are no standard instructions defined anyhow
// CUSTOM0 (0b00010, 2)
// CUSTOM1 (0b01010, 10)
// CUSTOM2 (0b10110, 22)
// CUSTOM3 (0b11110, 30)
// rsvd21 (0b10101, 21)
// rsvd29 (0b11101, 29)
// X48a (0b00111, 7)
// X64 (0b01111, 15)
// X48b (0b10111, 23)
// X80 (0b11111, 31)
/*
* quaternary opcodes in rs2 field of 32-bit instructions
*/
// primary is SYSTEM (0b11100, 28)
// funct3 is PRIV (0)
// funct7 is USER (0)
#define USER_ECALL 0b00000
#define USER_EBREAK 0b00001
#define USER_URET 0b00010
// primary is SYSTEM (0b11100, 28)
// funct3 is PRIV (0)
// funct7 is SYSTEM (0b0001000, 16)
#define SYSTEM_SRET 0b00010
#define SYSTEM_WFI 0b00101
// primary is SYSTEM (0b11100, 28)
// funct3 is PRIV (0)
// funct7 is MACHINE (0b0011000, 48)
#define MACHINE_MRET 0b00010
// primary is OPFP (0b10100, 20)
// funct7 is CVTFI or CVTIF
#define CVT_W 0b00000
#define CVT_WU 0b00001
#define CVT_L 0b00010
#define CVT_LU 0b00011