blob: ba02e2495cef6cb7869cae62ae1d2fe6f68086ff [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2022 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 _DR_IR_MACROS_RISCV64_H_
#define _DR_IR_MACROS_RISCV64_H_ 1
/****************************************************************************
* Platform-independent INSTR_CREATE_* macros
*/
/** @name Platform-independent macros */
/** @{ */ /* doxygen start group */
/**
* This platform-independent macro creates an instr_t for a debug trap
* instruction, automatically supplying any implicit operands.
* \param dc The void * dcontext used to allocate memory for the instr_t.
*/
#define XINST_CREATE_debug_instr(dc) INSTR_CREATE_ebreak(dc)
/**
* This platform-independent macro creates an instr_t for a 4-byte
* or 8-byte memory load instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param r The destination register opnd.
* \param m The source memory opnd.
*/
#define XINST_CREATE_load(dc, r, m) \
((opnd_get_size(m) == OPSZ_4) ? INSTR_CREATE_lwu(dc, r, m) \
: INSTR_CREATE_ld(dc, r, m))
/**
* This platform-independent macro creates an instr_t which loads 1 byte
* from memory, zero-extends it to 4 bytes, and writes it to a 4 byte
* destination register.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param r The destination register opnd.
* \param m The source memory opnd.
*/
#define XINST_CREATE_load_1byte_zext4(dc, r, m) INSTR_CREATE_lbu(dc, r, m)
/**
* This platform-independent macro creates an instr_t for a 1-byte
* memory load instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param r The destination register opnd.
* \param m The source memory opnd.
*/
#define XINST_CREATE_load_1byte(dc, r, m) INSTR_CREATE_lbu(dc, r, m)
/**
* This platform-independent macro creates an instr_t for a 2-byte
* memory load instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param r The destination register opnd.
* \param m The source memory opnd.
*/
#define XINST_CREATE_load_2bytes(dc, r, m) INSTR_CREATE_lhu(dc, r, m)
/**
* This platform-independent macro creates an instr_t for a 4-byte
* or 8-byte memory store instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param m The destination memory opnd.
* \param r The source register opnd.
*/
#define XINST_CREATE_store(dc, m, r) \
((opnd_get_size(m) == OPSZ_4) ? INSTR_CREATE_sw(dc, m, r) : INSTR_CREATE_sd(dc, m, r))
/**
* This platform-independent macro creates an instr_t for a 1-byte
* memory store instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param m The destination memory opnd.
* \param r The source register opnd.
*/
#define XINST_CREATE_store_1byte(dc, m, r) INSTR_CREATE_sb(dc, m, r)
/**
* This platform-independent macro creates an instr_t for a 2-byte
* memory store instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param m The destination memory opnd.
* \param r The source register opnd.
*/
#define XINST_CREATE_store_2bytes(dc, m, r) INSTR_CREATE_sh(dc, m, r)
/**
* This platform-independent macro creates an instr_t for a register
* to register move instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param d The destination register opnd.
* \param s The source register opnd.
*/
#define XINST_CREATE_move(dc, d, s) \
INSTR_CREATE_addi(dc, d, s, opnd_create_immed_int(0, OPSZ_12b))
/**
* This platform-independent macro creates an instr_t for a multimedia
* register load instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param r The destination register opnd.
* \param m The source memory opnd.
*
* FIXME i#3544: Serve as a placeholder for now. Add a proper implementation once it makes
* sense.
*/
#define XINST_CREATE_load_simd(dc, r, m) XINST_CREATE_load(dc, r, m)
/**
* This platform-independent macro creates an instr_t for a multimedia
* register store instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param m The destination memory opnd.
* \param r The source register opnd.
*
* FIXME i#3544: Serve as a placeholder for now. Add a proper implementation once it makes
* sense.
*/
#define XINST_CREATE_store_simd(dc, m, r) XINST_CREATE_store(dc, m, r)
/**
* This platform-independent macro creates an instr_t for an indirect
* jump instruction through a register.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param r The register opnd holding the target.
*/
#define XINST_CREATE_jump_reg(dc, r) \
INSTR_CREATE_jalr(dc, opnd_create_reg(DR_REG_ZERO), r, \
opnd_create_immed_int(0, OPSZ_12b))
/**
* This platform-independent macro creates an instr_t for an immediate
* integer load instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param r The destination register opnd.
* \param i The source immediate integer opnd.
*/
#define XINST_CREATE_load_int(dc, r, i) \
INSTR_CREATE_addi(dc, r, opnd_create_reg(DR_REG_ZERO), i)
/**
* This platform-independent macro creates an instr_t for a return instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
*/
#define XINST_CREATE_return(dc) \
INSTR_CREATE_jalr(dc, opnd_create_reg(DR_REG_ZERO), opnd_create_reg(DR_REG_RA), \
opnd_create_immed_int(0, OPSZ_12b))
/**
* This platform-independent macro creates an instr_t for an unconditional
* branch instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param t The opnd_t target operand for the instruction, which can be
* either a pc (opnd_create_pc)()) or an instr_t (opnd_create_instr()).
* Be sure to ensure that the limited reach of this short branch will reach
* the target (a pc operand is not suitable for most uses unless you know
* precisely where this instruction will be encoded).
*/
#define XINST_CREATE_jump(dc, t) INSTR_CREATE_jal(dc, opnd_create_reg(DR_REG_ZERO), t)
/**
* This platform-independent macro creates an instr_t for an unconditional
* branch instruction with the smallest available reach.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param t The opnd_t target operand for the instruction, which can be
* either a pc (opnd_create_pc)()) or an instr_t (opnd_create_instr()).
* Be sure to ensure that the limited reach of this short branch will reach
* the target (a pc operand is not suitable for most uses unless you know
* precisely where this instruction will be encoded).
*/
#define XINST_CREATE_jump_short(dc, t) \
INSTR_CREATE_jal(dc, opnd_create_reg(DR_REG_ZERO), t)
/**
* This platform-independent macro creates an instr_t for an unconditional
* branch instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param t The opnd_t target operand for the instruction, which can be
* either a pc (opnd_create_pc)()) or an instr_t (opnd_create_instr()).
* Be sure to ensure that the limited reach of this short branch will reach
* the target (a pc operand is not suitable for most uses unless you know
* precisely where this instruction will be encoded).
*/
#define XINST_CREATE_call(dc, t) INSTR_CREATE_jal(dc, opnd_create_reg(DR_REG_RA), t)
/**
* This platform-independent macro creates an instr_t for an addition
* instruction that does not affect the status flags.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param d The opnd_t explicit destination operand for the instruction.
* \param s The opnd_t explicit source operand for the instruction.
*/
#define XINST_CREATE_add(dc, d, s) XINST_CREATE_add_2src(dc, d, d, s)
/**
* This platform-independent macro creates an instr_t for an addition
* instruction that does not affect the status flags and takes two sources
* plus a destination.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param d The opnd_t explicit destination operand for the instruction.
* \param s1 The opnd_t explicit first source operand for the instruction. This
* must be a register.
* \param s2 The opnd_t explicit source operand for the instruction. This
* can be either a register or an immediate integer.
*/
#define XINST_CREATE_add_2src(dc, d, s1, s2) \
opnd_is_reg(s2) ? INSTR_CREATE_add(dc, d, s1, s2) : INSTR_CREATE_addi(dc, d, s1, s2)
/**
* This platform-independent macro creates an instr_t for a subtraction
* instruction that does not affect the status flags.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param d The opnd_t explicit destination operand for the instruction.
* \param s The opnd_t explicit source operand for the instruction.
*/
#define XINST_CREATE_sub(dc, d, s) \
opnd_is_reg(s) \
? INSTR_CREATE_sub(dc, d, d, s) \
: INSTR_CREATE_addi(dc, d, d, \
opnd_create_immed_int(-opnd_get_immed_int(s), OPSZ_12b))
/**
* This platform-independent macro creates an instr_t for a software
* interrupt instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param i The source integer constant opnd_t operand.
*/
#define XINST_CREATE_interrupt(dc, i) INSTR_CREATE_ebreak(dc)
/**
* This platform-independent macro creates an instr_t for a nop instruction.
* \param dc The void * dcontext used to allocate memory for the instr_t.
*/
#define XINST_CREATE_nop(dc) INSTR_CREATE_c_nop(dc)
/**
* This platform-independent macro creates an instr_t for an indirect call instr
* through a register.
* \param dc The void * dcontext used to allocate memory for the instr_t.
* \param r The opnd_t explicit source operand for the instruction. This should
* be a reg_id_t operand with the address of the subroutine.
*/
#define XINST_CREATE_call_reg(dc, r) \
INSTR_CREATE_jalr(dc, opnd_create_reg(DR_REG_RA), r, \
opnd_create_immed_int(0, OPSZ_12b))
/**
* Create an absolute address operand encoded as pc-relative.
* Encoding will fail if addr is out of the maximum signed displacement
* reach for the architecture.
*/
#define OPND_CREATE_ABSMEM(addr, size) opnd_create_rel_addr(addr, size)
/**
* Create an immediate integer operand. For RISCV64 the size of an immediate
* is ignored when encoding, so there is no need to specify the final size.
*/
#define OPND_CREATE_INT(val) OPND_CREATE_INTPTR(val)
/** @} */ /* end doxygen group */
/****************************************************************************
* RISC-V-specific INSTR_CREATE_* macros
*/
/** @name No-operand instructions */
/** @{ */ /* doxygen start group; w/ DISTRIBUTE_GROUP_DOC=YES, one comment suffices. */
/**
* This INSTR_CREATE_xxx macro creates an instr_t with opcode OP_xxx, automatically
* supplying any implicit operands.
* \param dc The void * dcontext used to allocate memory for the instr_t.
*/
/* Auto-generated by codec.py. */
// clang-format off
@INSTR_MACROS@
// clang-format on
/** @} */ /* end doxygen group */
#endif /* _DR_IR_MACROS_RISCV64_H_ */