| /* ********************************************************** |
| * 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_ */ |