blob: 83b40caf6cf4926d8d48daf86544c731878626b1 [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2016 RIVOS, Inc. All rights reserved.
* **********************************************************/
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * 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.
*
* * Neither the name of Rivos, Inc. nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 RIVOS, INC. 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 CODEC_H
#define CODEC_H 1
#include <stdint.h>
#include "decode_private.h"
#include "decode.h"
/* Interface to the RISC-V instruction codec (encoder/decoder).
*
* Note that the encoder does not verify validity of operand values. This is
* because currently invalid bit encodings are either reserved for future
* extensions (i.e. C.ADDI or C.SLLI) and execute as NOP or HINT instructions
* (which might be used as vendor ISA extensions).
*/
#define ENCFAIL (uint)0x0 /* An invalid instruction (a.k.a c.unimp). */
/* List of ISA extensions handled by the codec. */
typedef enum {
RISCV64_ISA_EXT_RV32A,
RISCV64_ISA_EXT_RV32C,
RISCV64_ISA_EXT_RV32D,
RISCV64_ISA_EXT_RV32F,
RISCV64_ISA_EXT_RV32H,
RISCV64_ISA_EXT_RV32I,
RISCV64_ISA_EXT_RV32M,
RISCV64_ISA_EXT_RV32Q,
RISCV64_ISA_EXT_RV32ZBA,
RISCV64_ISA_EXT_RV32ZBB,
RISCV64_ISA_EXT_RV32ZBC,
RISCV64_ISA_EXT_RV32ZBS,
RISCV64_ISA_EXT_RV64A,
RISCV64_ISA_EXT_RV64C,
RISCV64_ISA_EXT_RV64D,
RISCV64_ISA_EXT_RV64F,
RISCV64_ISA_EXT_RV64H,
RISCV64_ISA_EXT_RV64I,
RISCV64_ISA_EXT_RV64M,
RISCV64_ISA_EXT_RV64Q,
RISCV64_ISA_EXT_RV64ZBA,
RISCV64_ISA_EXT_RV64ZBB,
RISCV64_ISA_EXT_RVC,
RISCV64_ISA_EXT_SVINVAL,
RISCV64_ISA_EXT_SYSTEM,
RISCV64_ISA_EXT_ZICBOM,
RISCV64_ISA_EXT_ZICBOP,
RISCV64_ISA_EXT_ZICBOZ,
RISCV64_ISA_EXT_ZICSR,
RISCV64_ISA_EXT_ZIFENCEI,
RISCV64_ISA_EXT_XTHEADCMO,
RISCV64_ISA_EXT_XTHEADSYNC,
RISCV64_ISA_EXT_V,
RISCV64_ISA_EXT_CNT, /* Keep this last */
} riscv64_isa_ext_t;
/* List of instruction formats handled by the codec.
*
* Note that enum names have to match ones defined in the codec.py.
*/
typedef enum {
/* Uncompressed instruction formats - Chapter 2.2 in the RISC-V Instruction
* Set Manual Volume I: Unprivileged ISA (ver. 20191213).
*/
/* R-type format:
* |31 25|24 20|19 15|14 12|11 7|6 0|
* | funct7 | rs2 | rs1 | funct3 | rd | opcode |
*/
RISCV64_FMT_R = 0,
/* R4-type format:
* |31 27|26 25|24 20|19 15|14 12|11 7|6 0|
* | rs3 | funct2 | rs2 | rs1 | funct3 | rd | opcode |
*/
RISCV64_FMT_R4,
/* I-type format:
* |31 20|19 15|14 12|11 7|6 0|
* | imm[11:0] | rs1 | funct3 | rd | opcode |
*/
RISCV64_FMT_I,
/* S-type format:
* |31 25|24 20|19 15|14 12|11 7|6 0|
* | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode |
*/
RISCV64_FMT_S,
/* B-type format:
* | 31 |30 25|24 20|19 15|14 12|11 8| 7 |6 0|
* |imm[12]|imm[10:5]| rs2 | rs1 | funct3 |imm[4:1]|imm[11]| opcode |
*/
RISCV64_FMT_B,
/* U-type format:
* |31 12|11 7|6 0|
* | imm[31:12] | rd | opcode |
*/
RISCV64_FMT_U,
/* J-type format:
* | 31 |30 21| 20 |19 12|11 7|6 0|
* | imm[20] | imm[10:1] | imm[11] | imm[19:12] | rd | opcode |
*/
RISCV64_FMT_J,
/* Compressed instruction formats - Chapter 16.2 in the RISC-V Instruction
* Set Manual Volume I: Unprivileged ISA (ver. 20191213).
* Unlike uncompressed formats, the bit layout of immediate fields (imm,
* offset) depends on the instruction.
*/
/* Compressed Register (CR) format:
* |15 12|11 7|6 2|1 0|
* | funct4 | rd/rs1 | rs2 | opcode |
*/
RISCV64_FMT_CR,
/* Compressed Immediate (CI) format:
* |15 13| 12 |11 7|6 2|1 0|
* | funct3 | imm | rd/rs1 | imm | opcode |
*/
RISCV64_FMT_CI,
/* Compressed Stack-relative Store (CSS) format:
* |15 13|12 7|6 2|1 0|
* | funct3 | imm | rs2 | opcode |
*/
RISCV64_FMT_CSS,
/* Compressed Wide Immediate (CIW) format:
* |15 13|12 5|4 2|1 0|
* | funct3 | imm | rd' | opcode |
*/
RISCV64_FMT_CIW,
/* Compressed Load (CL) format:
* |15 13|12 10|9 7|6 5|4 2|1 0|
* | funct3 | imm | rs1' | imm | rd' | opcode |
*/
RISCV64_FMT_CL,
/* Compressed Store (CS) format:
* |15 13|12 10|9 7|6 5|4 2|1 0|
* | funct3 | imm | rs1' | imm | rs2' | opcode |
*/
RISCV64_FMT_CS,
/* Compressed Arithmetic (CA) format:
* |15 10|9 7|6 5|4 2|1 0|
* | funct6 | rd'/rs1' | funct2 | rs2' | opcode |
*/
RISCV64_FMT_CA,
/* Compressed Branch (CB) format:
* |15 13|12 10|9 7|6 2|1 0|
* | funct3 | offset | rs1' | offset | opcode |
*/
RISCV64_FMT_CB,
/* Compressed Jump (CJ) format:
* |15 13|12 2|1 0|
* | funct3 | jump target | opcode |
*/
RISCV64_FMT_CJ,
RISCV64_FMT_CNT, /* Keep this last */
} riscv64_inst_fmt_t;
/* List of instruction fields handled by the codec.
*
* Note that enum names have to match ones defined in the codec.py.
*/
typedef enum {
RISCV64_FLD_NONE = 0, /*< Value indicating lack of a given field. */
/* Uncompressed instruction fields */
RISCV64_FLD_RD,
RISCV64_FLD_RDFP,
RISCV64_FLD_RS1,
RISCV64_FLD_RS1FP,
RISCV64_FLD_BASE,
RISCV64_FLD_RS2,
RISCV64_FLD_RS2FP,
RISCV64_FLD_RS3FP,
RISCV64_FLD_FM,
RISCV64_FLD_PRED,
RISCV64_FLD_SUCC,
RISCV64_FLD_AQRL,
RISCV64_FLD_CSR,
RISCV64_FLD_RM,
RISCV64_FLD_SHAMT,
RISCV64_FLD_SHAMT5,
RISCV64_FLD_SHAMT6,
RISCV64_FLD_I_IMM,
RISCV64_FLD_S_IMM,
RISCV64_FLD_B_IMM,
RISCV64_FLD_U_IMM,
RISCV64_FLD_U_IMMPC,
RISCV64_FLD_J_IMM,
/* Compressed instruction fields */
RISCV64_FLD_CRD,
RISCV64_FLD_CRDFP,
RISCV64_FLD_CRS1,
RISCV64_FLD_CRS2,
RISCV64_FLD_CRS2FP,
RISCV64_FLD_CRD_,
RISCV64_FLD_CRD_FP,
RISCV64_FLD_CRS1_,
RISCV64_FLD_CRS2_,
RISCV64_FLD_CRS2_FP,
RISCV64_FLD_CRD__,
RISCV64_FLD_CSHAMT,
RISCV64_FLD_CSR_IMM,
RISCV64_FLD_CADDI16SP_IMM,
RISCV64_FLD_CLWSP_IMM,
RISCV64_FLD_CLDSP_IMM,
RISCV64_FLD_CLUI_IMM,
RISCV64_FLD_CSWSP_IMM,
RISCV64_FLD_CSDSP_IMM,
RISCV64_FLD_CIW_IMM,
RISCV64_FLD_CLW_IMM,
RISCV64_FLD_CLD_IMM,
RISCV64_FLD_CSW_IMM,
RISCV64_FLD_CSD_IMM,
RISCV64_FLD_CIMM5,
RISCV64_FLD_CB_IMM,
RISCV64_FLD_CJ_IMM,
/* Virtual fields - en/decode special cases, i.e. base+disp combination */
RISCV64_FLD_V_L_RS1_DISP,
RISCV64_FLD_V_S_RS1_DISP,
/* Implicit fields - encode is nop. */
RISCV64_FLD_IRS1_SP,
RISCV64_FLD_IRS1_ZERO,
RISCV64_FLD_IRS2_ZERO,
RISCV64_FLD_IRD_ZERO,
RISCV64_FLD_IRD_RA,
RISCV64_FLD_IRD_SP,
RISCV64_FLD_IIMM_0,
RISCV64_FLD_ICRS1,
RISCV64_FLD_ICRS1__,
RISCV64_FLD_I_S_RS1_DISP,
/* Vector extension fields. */
RISCV64_FLD_ZIMM,
RISCV64_FLD_ZIMM10,
RISCV64_FLD_ZIMM11,
RISCV64_FLD_VM,
RISCV64_FLD_NF,
RISCV64_FLD_SIMM5,
RISCV64_FLD_VD,
RISCV64_FLD_VS1,
RISCV64_FLD_VS2,
RISCV64_FLD_VS3,
RISCV64_FLD_CNT, /* Keep this last */
} riscv64_fld_t;
#define BIT(v, b) (((v) >> b) & 1)
#define GET_FIELD(v, high, low) (((v) >> low) & ((1ULL << (high - low + 1)) - 1))
#define SET_FIELD(v, high, low) (((v) & ((1ULL << (high - low + 1)) - 1)) << low)
#define SIGN_EXTEND(val, val_sz) (((int32_t)(val) << (32 - (val_sz))) >> (32 - (val_sz)))
/* Calculate instruction width, see page 8 of Volume I: RISC-V Unprivileged ISA V20191213.
*
* Returns a negative number on an invalid instruction width.
*/
static inline int
instruction_width(uint16_t lower16b)
{
/* xxxxxxxxxxxxxxaa -> 16-bit (aa != 11) */
if (!TESTALL(0b11, GET_FIELD(lower16b, 1, 0)))
return 2;
/* ...xxxxxxxxxxxbbb11 -> 32-bit (bbb != 111) */
else if (!TESTALL(0b111, GET_FIELD(lower16b, 4, 2)))
return 4;
/* ...xxxxxxxxxx011111 -> 48-bit */
else if (TESTALL(0b011111, GET_FIELD(lower16b, 5, 0)))
return 6;
/* ...xxxxxxxxx0111111 -> 64-bit */
else if (TESTALL(0b0111111, GET_FIELD(lower16b, 6, 0)))
return 8;
/* ...xnnnxxxxx1111111 -> (80+16*nnn)-bit (nnn != 111) */
else if (TESTALL(0b1111111, GET_FIELD(lower16b, 6, 0)) &&
!TESTALL(0b111, GET_FIELD(lower16b, 14, 12)))
return (10 + 2 * GET_FIELD(lower16b, 14, 12));
/* Reserved for ≥192-bits. */
else
return -1;
}
/* Return instr_info_t for a given opcode. */
instr_info_t *
get_instruction_info(uint opc);
byte *
decode_common(dcontext_t *dc, byte *pc, byte *orig_pc, instr_t *instr);
uint
encode_common(byte *pc, instr_t *i, decode_info_t *di);
#endif /* CODEC_H */