1e6c7e151Schristos /* TI PRU opcode list. 2*c42dbd0eSchristos Copyright (C) 2014-2022 Free Software Foundation, Inc. 3e6c7e151Schristos Contributed by Dimitar Dimitrov <dimitar@dinux.eu> 4e6c7e151Schristos 5e6c7e151Schristos This file is part of the GNU opcodes library. 6e6c7e151Schristos 7e6c7e151Schristos This library is free software; you can redistribute it and/or modify 8e6c7e151Schristos it under the terms of the GNU General Public License as published by 9e6c7e151Schristos the Free Software Foundation; either version 3, or (at your option) 10e6c7e151Schristos any later version. 11e6c7e151Schristos 12e6c7e151Schristos It is distributed in the hope that it will be useful, but WITHOUT 13e6c7e151Schristos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14e6c7e151Schristos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15e6c7e151Schristos License for more details. 16e6c7e151Schristos 17e6c7e151Schristos You should have received a copy of the GNU General Public License 18e6c7e151Schristos along with this file; see the file COPYING. If not, write to the 19e6c7e151Schristos Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, 20e6c7e151Schristos MA 02110-1301, USA. */ 21e6c7e151Schristos 22e6c7e151Schristos /* Source: 23e6c7e151Schristos http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit */ 24e6c7e151Schristos 25e6c7e151Schristos #include "sysdep.h" 26e6c7e151Schristos #include <stdio.h> 27e6c7e151Schristos #include "opcode/pru.h" 28e6c7e151Schristos 29e6c7e151Schristos /* Register string table. */ 30e6c7e151Schristos 31e6c7e151Schristos #define DECLARE_REG(name, index) \ 32e6c7e151Schristos { #name ".b0", (index), RSEL_7_0 }, \ 33e6c7e151Schristos { #name ".b1", (index), RSEL_15_8 }, \ 34e6c7e151Schristos { #name ".b2", (index), RSEL_23_16 }, \ 35e6c7e151Schristos { #name ".b3", (index), RSEL_31_24 }, \ 36e6c7e151Schristos { #name ".w0", (index), RSEL_15_0 }, \ 37e6c7e151Schristos { #name ".w1", (index), RSEL_23_8 }, \ 38e6c7e151Schristos { #name ".w2", (index), RSEL_31_16 }, \ 39e6c7e151Schristos { #name , (index), RSEL_31_0 } 40e6c7e151Schristos 41e6c7e151Schristos const struct pru_reg pru_regs[] = { 42e6c7e151Schristos /* Standard register names. */ 43e6c7e151Schristos DECLARE_REG (r0, 0), 44e6c7e151Schristos DECLARE_REG (r1, 1), 45e6c7e151Schristos DECLARE_REG (sp, 2), /* Stack pointer. */ 46e6c7e151Schristos DECLARE_REG (ra, 3), /* Return address. */ 47e6c7e151Schristos DECLARE_REG (fp, 4), /* Frame pointer. */ 48e6c7e151Schristos DECLARE_REG (r5, 5), 49e6c7e151Schristos DECLARE_REG (r6, 6), 50e6c7e151Schristos DECLARE_REG (r7, 7), 51e6c7e151Schristos DECLARE_REG (r8, 8), 52e6c7e151Schristos DECLARE_REG (r9, 9), 53e6c7e151Schristos DECLARE_REG (r10, 10), 54e6c7e151Schristos DECLARE_REG (r11, 11), 55e6c7e151Schristos DECLARE_REG (r12, 12), 56e6c7e151Schristos DECLARE_REG (r13, 13), 57e6c7e151Schristos DECLARE_REG (r14, 14), 58e6c7e151Schristos DECLARE_REG (r15, 15), 59e6c7e151Schristos DECLARE_REG (r16, 16), 60e6c7e151Schristos DECLARE_REG (r17, 17), 61e6c7e151Schristos DECLARE_REG (r18, 18), 62e6c7e151Schristos DECLARE_REG (r19, 19), 63e6c7e151Schristos DECLARE_REG (r20, 20), 64e6c7e151Schristos DECLARE_REG (r21, 21), 65e6c7e151Schristos DECLARE_REG (r22, 22), 66e6c7e151Schristos DECLARE_REG (r23, 23), 67e6c7e151Schristos DECLARE_REG (r24, 24), 68e6c7e151Schristos DECLARE_REG (r25, 25), 69e6c7e151Schristos DECLARE_REG (r26, 26), 70e6c7e151Schristos DECLARE_REG (r27, 27), 71e6c7e151Schristos DECLARE_REG (r28, 28), 72e6c7e151Schristos DECLARE_REG (r29, 29), 73e6c7e151Schristos DECLARE_REG (r30, 30), 74e6c7e151Schristos DECLARE_REG (r31, 31), 75e6c7e151Schristos 76e6c7e151Schristos /* Alternative names for special registers. */ 77e6c7e151Schristos DECLARE_REG (r2, 2), 78e6c7e151Schristos DECLARE_REG (r3, 3), 79e6c7e151Schristos DECLARE_REG (r4, 4) 80e6c7e151Schristos }; 81e6c7e151Schristos 82e6c7e151Schristos #define PRU_NUM_REGS \ 83e6c7e151Schristos ((sizeof pru_regs) / (sizeof (pru_regs[0]))) 84e6c7e151Schristos const int pru_num_regs = PRU_NUM_REGS; 85e6c7e151Schristos 86e6c7e151Schristos #undef PRU_NUM_REGS 87e6c7e151Schristos 88e6c7e151Schristos /* This is the opcode table used by the PRU GNU as and disassembler. */ 89e6c7e151Schristos const struct pru_opcode pru_opcodes[] = 90e6c7e151Schristos { 91e6c7e151Schristos /* { name, args, 92e6c7e151Schristos match, mask, pinfo, overflow_msg } */ 93e6c7e151Schristos #define DECLARE_FORMAT1_OPCODE(str, subop) \ 94e6c7e151Schristos { #str, prui_ ## str, "d,s,b", \ 95e6c7e151Schristos OP_MATCH_ ## subop, OP_MASK_FMT1_OP | OP_MASK_SUBOP, 0, \ 96e6c7e151Schristos unsigned_immed8_overflow } 97e6c7e151Schristos 98e6c7e151Schristos DECLARE_FORMAT1_OPCODE (add, ADD), 99e6c7e151Schristos DECLARE_FORMAT1_OPCODE (adc, ADC), 100e6c7e151Schristos DECLARE_FORMAT1_OPCODE (sub, SUB), 101e6c7e151Schristos DECLARE_FORMAT1_OPCODE (suc, SUC), 102e6c7e151Schristos DECLARE_FORMAT1_OPCODE (lsl, LSL), 103e6c7e151Schristos DECLARE_FORMAT1_OPCODE (lsr, LSR), 104e6c7e151Schristos DECLARE_FORMAT1_OPCODE (rsb, RSB), 105e6c7e151Schristos DECLARE_FORMAT1_OPCODE (rsc, RSC), 106e6c7e151Schristos DECLARE_FORMAT1_OPCODE (and, AND), 107e6c7e151Schristos DECLARE_FORMAT1_OPCODE (or, OR), 108e6c7e151Schristos DECLARE_FORMAT1_OPCODE (xor, XOR), 109e6c7e151Schristos DECLARE_FORMAT1_OPCODE (min, MIN), 110e6c7e151Schristos DECLARE_FORMAT1_OPCODE (max, MAX), 111e6c7e151Schristos DECLARE_FORMAT1_OPCODE (clr, CLR), 112e6c7e151Schristos DECLARE_FORMAT1_OPCODE (set, SET), 113e6c7e151Schristos 114e6c7e151Schristos { "not", prui_not, "d,s", 115e6c7e151Schristos OP_MATCH_NOT | OP_MASK_IO, 116e6c7e151Schristos OP_MASK_FMT1_OP | OP_MASK_SUBOP | OP_MASK_IO, 0, no_overflow}, 117e6c7e151Schristos 118e6c7e151Schristos { "jmp", prui_jmp, "j", 119e6c7e151Schristos OP_MATCH_JMP, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, unsigned_immed16_overflow}, 120e6c7e151Schristos { "jal", prui_jal, "d,j", 121e6c7e151Schristos OP_MATCH_JAL, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, unsigned_immed16_overflow}, 122e6c7e151Schristos { "ldi", prui_ldi, "d,W", 123e6c7e151Schristos OP_MATCH_LDI, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, unsigned_immed16_overflow}, 124*c42dbd0eSchristos { "lmbd", prui_lmbd, "d,s,b", 125*c42dbd0eSchristos OP_MATCH_LMBD, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, unsigned_immed8_overflow}, 126e6c7e151Schristos { "halt", prui_halt, "", 127e6c7e151Schristos OP_MATCH_HALT, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, no_overflow}, 128e6c7e151Schristos { "slp", prui_slp, "w", 129e6c7e151Schristos OP_MATCH_SLP, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 0, no_overflow}, 130e6c7e151Schristos 131e6c7e151Schristos { "xin", prui_xin, "x,D,n", 132e6c7e151Schristos OP_MATCH_XIN, OP_MASK_XFR_OP, 0, unsigned_immed8_overflow}, 133e6c7e151Schristos { "xout", prui_xout, "x,D,n", 134e6c7e151Schristos OP_MATCH_XOUT, OP_MASK_XFR_OP, 0, unsigned_immed8_overflow}, 135e6c7e151Schristos { "xchg", prui_xchg, "x,D,n", 136e6c7e151Schristos OP_MATCH_XCHG, OP_MASK_XFR_OP, 0, unsigned_immed8_overflow}, 137e6c7e151Schristos { "sxin", prui_sxin, "x,D,n", 138e6c7e151Schristos OP_MATCH_SXIN, OP_MASK_XFR_OP, 0, unsigned_immed8_overflow}, 139e6c7e151Schristos { "sxout", prui_sxout, "x,D,n", 140e6c7e151Schristos OP_MATCH_SXOUT, OP_MASK_XFR_OP, 0, unsigned_immed8_overflow}, 141e6c7e151Schristos { "sxchg", prui_sxchg, "x,D,n", 142e6c7e151Schristos OP_MATCH_SXCHG, OP_MASK_XFR_OP, 0, unsigned_immed8_overflow}, 143e6c7e151Schristos 144e6c7e151Schristos { "loop", prui_loop, "O,B", 145e6c7e151Schristos OP_MATCH_LOOP, OP_MASK_LOOP_OP, 0, unsigned_immed8_overflow}, 146e6c7e151Schristos { "iloop", prui_loop, "O,B", 147e6c7e151Schristos OP_MATCH_ILOOP, OP_MASK_LOOP_OP, 0, unsigned_immed8_overflow}, 148e6c7e151Schristos 149e6c7e151Schristos { "qbgt", prui_qbgt, "o,s,b", 150e6c7e151Schristos OP_MATCH_QBGT, OP_MASK_FMT4_OP | OP_MASK_CMP, 0, qbranch_target_overflow}, 151e6c7e151Schristos { "qbge", prui_qbge, "o,s,b", 152e6c7e151Schristos OP_MATCH_QBGE, OP_MASK_FMT4_OP | OP_MASK_CMP, 0, qbranch_target_overflow}, 153e6c7e151Schristos { "qblt", prui_qblt, "o,s,b", 154e6c7e151Schristos OP_MATCH_QBLT, OP_MASK_FMT4_OP | OP_MASK_CMP, 0, qbranch_target_overflow}, 155e6c7e151Schristos { "qble", prui_qble, "o,s,b", 156e6c7e151Schristos OP_MATCH_QBLE, OP_MASK_FMT4_OP | OP_MASK_CMP, 0, qbranch_target_overflow}, 157e6c7e151Schristos { "qbeq", prui_qbeq, "o,s,b", 158e6c7e151Schristos OP_MATCH_QBEQ, OP_MASK_FMT4_OP | OP_MASK_CMP, 0, qbranch_target_overflow}, 159e6c7e151Schristos { "qbne", prui_qbne, "o,s,b", 160e6c7e151Schristos OP_MATCH_QBNE, OP_MASK_FMT4_OP | OP_MASK_CMP, 0, qbranch_target_overflow}, 161e6c7e151Schristos { "qba", prui_qba, "o", 162e6c7e151Schristos OP_MATCH_QBA, OP_MASK_FMT4_OP | OP_MASK_CMP, 0, qbranch_target_overflow}, 163e6c7e151Schristos 164e6c7e151Schristos { "qbbs", prui_qbbs, "o,s,b", 165e6c7e151Schristos OP_MATCH_QBBS, OP_MASK_FMT5_OP | OP_MASK_BCMP, 0, qbranch_target_overflow}, 166e6c7e151Schristos { "qbbc", prui_qbbc, "o,s,b", 167e6c7e151Schristos OP_MATCH_QBBC, OP_MASK_FMT5_OP | OP_MASK_BCMP, 0, qbranch_target_overflow}, 168e6c7e151Schristos 169e6c7e151Schristos { "lbbo", prui_lbbo, "D,S,b,l", 170e6c7e151Schristos OP_MATCH_LBBO, OP_MASK_FMT6AB_OP | OP_MASK_LOADSTORE, 0, 171e6c7e151Schristos unsigned_immed8_overflow}, 172e6c7e151Schristos { "sbbo", prui_sbbo, "D,S,b,l", 173e6c7e151Schristos OP_MATCH_SBBO, OP_MASK_FMT6AB_OP | OP_MASK_LOADSTORE, 0, 174e6c7e151Schristos unsigned_immed8_overflow}, 175e6c7e151Schristos { "lbco", prui_lbco, "D,c,b,l", 176e6c7e151Schristos OP_MATCH_LBCO, OP_MASK_FMT6CD_OP | OP_MASK_LOADSTORE, 0, 177e6c7e151Schristos unsigned_immed8_overflow}, 178e6c7e151Schristos { "sbco", prui_sbco, "D,c,b,l", 179e6c7e151Schristos OP_MATCH_SBCO, OP_MASK_FMT6CD_OP | OP_MASK_LOADSTORE, 0, 180e6c7e151Schristos unsigned_immed8_overflow}, 181e6c7e151Schristos 182e6c7e151Schristos /* Fill in the default values for the real-instruction arguments. 183e6c7e151Schristos The assembler will not do it! */ 184e6c7e151Schristos { "nop", prui_or, "", 185e6c7e151Schristos OP_MATCH_OR 186e6c7e151Schristos | (RSEL_31_0 << OP_SH_RS2SEL) | (0 << OP_SH_RS2) 187e6c7e151Schristos | (RSEL_31_0 << OP_SH_RS1SEL) | (0 << OP_SH_RS1) 188e6c7e151Schristos | (RSEL_31_0 << OP_SH_RDSEL) | (0 << OP_SH_RD), 189e6c7e151Schristos OP_MASK_FMT1_OP | OP_MASK_SUBOP 190e6c7e151Schristos | OP_MASK_RS2SEL | OP_MASK_RS2 | OP_MASK_RS1SEL | OP_MASK_RS1 191e6c7e151Schristos | OP_MASK_RDSEL | OP_MASK_RD | OP_MASK_IO, 192e6c7e151Schristos PRU_INSN_MACRO, no_overflow}, 193e6c7e151Schristos { "mov", prui_or, "d,s", 194e6c7e151Schristos OP_MATCH_OR | (0 << OP_SH_IMM8) | OP_MASK_IO, 195e6c7e151Schristos OP_MASK_FMT1_OP | OP_MASK_SUBOP | OP_MASK_IMM8 | OP_MASK_IO, 196e6c7e151Schristos PRU_INSN_MACRO, no_overflow}, 197e6c7e151Schristos { "ret", prui_jmp, "", 198e6c7e151Schristos OP_MATCH_JMP 199e6c7e151Schristos | (RSEL_31_16 << OP_SH_RS2SEL) | (3 << OP_SH_RS2), 200e6c7e151Schristos OP_MASK_FMT2_OP | OP_MASK_SUBOP 201e6c7e151Schristos | OP_MASK_RS2SEL | OP_MASK_RS2 | OP_MASK_IO, 202e6c7e151Schristos PRU_INSN_MACRO, unsigned_immed16_overflow}, 203e6c7e151Schristos { "call", prui_jal, "j", 204e6c7e151Schristos OP_MATCH_JAL 205e6c7e151Schristos | (RSEL_31_16 << OP_SH_RDSEL) | (3 << OP_SH_RD), 206e6c7e151Schristos OP_MASK_FMT2_OP | OP_MASK_SUBOP 207e6c7e151Schristos | OP_MASK_RDSEL | OP_MASK_RD, 208e6c7e151Schristos PRU_INSN_MACRO, unsigned_immed16_overflow}, 209e6c7e151Schristos 210e6c7e151Schristos { "wbc", prui_qbbs, "s,b", 211e6c7e151Schristos OP_MATCH_QBBS | (0 << OP_SH_BROFF98) | (0 << OP_SH_BROFF70), 212e6c7e151Schristos OP_MASK_FMT5_OP | OP_MASK_BCMP | OP_MASK_BROFF, 213e6c7e151Schristos PRU_INSN_MACRO, qbranch_target_overflow}, 214e6c7e151Schristos { "wbs", prui_qbbc, "s,b", 215e6c7e151Schristos OP_MATCH_QBBC | (0 << OP_SH_BROFF98) | (0 << OP_SH_BROFF70), 216e6c7e151Schristos OP_MASK_FMT5_OP | OP_MASK_BCMP | OP_MASK_BROFF, 217e6c7e151Schristos PRU_INSN_MACRO, qbranch_target_overflow}, 218e6c7e151Schristos 219e6c7e151Schristos { "fill", prui_xin, "D,n", 220e6c7e151Schristos OP_MATCH_XIN | (254 << OP_SH_XFR_WBA), 221e6c7e151Schristos OP_MASK_XFR_OP | OP_MASK_XFR_WBA, 222e6c7e151Schristos PRU_INSN_MACRO, unsigned_immed8_overflow}, 223e6c7e151Schristos { "zero", prui_xin, "D,n", 224e6c7e151Schristos OP_MATCH_XIN | (255 << OP_SH_XFR_WBA), 225e6c7e151Schristos OP_MASK_XFR_OP | OP_MASK_XFR_WBA, 226e6c7e151Schristos PRU_INSN_MACRO, unsigned_immed8_overflow}, 227e6c7e151Schristos 228e6c7e151Schristos { "ldi32", prui_ldi, "R,i", 229e6c7e151Schristos OP_MATCH_LDI, OP_MASK_FMT2_OP | OP_MASK_SUBOP, 230e6c7e151Schristos PRU_INSN_LDI32, unsigned_immed32_overflow}, 231e6c7e151Schristos }; 232e6c7e151Schristos 233e6c7e151Schristos #define PRU_NUM_OPCODES \ 234e6c7e151Schristos ((sizeof pru_opcodes) / (sizeof (pru_opcodes[0]))) 235e6c7e151Schristos const int bfd_pru_num_opcodes = PRU_NUM_OPCODES; 236e6c7e151Schristos 237e6c7e151Schristos #undef PRU_NUM_OPCODES 238