Home | History | Annotate | Line # | Download | only in opcodes
pru-opc.c revision 1.1.1.6
      1 /* TI PRU opcode list.
      2    Copyright (C) 2014-2026 Free Software Foundation, Inc.
      3    Contributed by Dimitar Dimitrov <dimitar (at) 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
    238