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