2 Copyright (C) 2014-2024 Free Software Foundation, Inc.
3 Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
5 This file is part of the GNU opcodes library.
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)
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.
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. */
23 http://processors.wiki.ti.com/index.php/Programmable_Realtime_Unit */
27 #include "opcode/pru.h"
29 /* Register string table. */
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 }
41 const struct pru_reg pru_regs
[] = {
42 /* Standard register names. */
45 DECLARE_REG (sp
, 2), /* Stack pointer. */
46 DECLARE_REG (ra
, 3), /* Return address. */
47 DECLARE_REG (fp
, 4), /* Frame pointer. */
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),
76 /* Alternative names for special registers. */
82 #define PRU_NUM_REGS \
83 ((sizeof pru_regs) / (sizeof (pru_regs[0])))
84 const int pru_num_regs
= PRU_NUM_REGS
;
88 /* This is the opcode table used by the PRU GNU as and disassembler. */
89 const struct pru_opcode pru_opcodes
[] =
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 }
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
),
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
},
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
},
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
},
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
},
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
},
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
},
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
},
182 /* Fill in the default values for the real-instruction arguments.
183 The assembler will not do it! */
184 { "nop", prui_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
, "",
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",
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
},
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
},
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
},
228 { "ldi32", prui_ldi
, "R,i",
229 OP_MATCH_LDI
, OP_MASK_FMT2_OP
| OP_MASK_SUBOP
,
230 PRU_INSN_LDI32
, unsigned_immed32_overflow
},
233 #define PRU_NUM_OPCODES \
234 ((sizeof pru_opcodes) / (sizeof (pru_opcodes[0])))
235 const int bfd_pru_num_opcodes
= PRU_NUM_OPCODES
;
237 #undef PRU_NUM_OPCODES