* txvu-dis.c (print_insn): Extract/print fns take pointer to
[deliverable/binutils-gdb.git] / opcodes / txvu-opc.c
CommitLineData
54cc8ed4
DE
1/* Opcode table for the TXVU
2 Copyright 1998 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18#include "ansidecl.h"
19#include "dis-asm.h"
20#include "opcode/txvu.h"
21
22#ifndef NULL
23#define NULL 0
24#endif
25
26#if defined (__STDC__) || defined (ALMOST_STDC)
27#define XCONCAT2(a,b) a##b
28#else
29#define XCONCAT2(a,b) a/**/b
30#endif
31#define CONCAT2(a,b) XCONCAT2(a,b)
32
33/* ??? One can argue it's preferable to have the PARSE_FN support in tc-vxvu.c
34 and the PRINT_FN support in txvu-dis.c. For this project I like having
35 them all in one place. */
36
37#define PARSE_FN(fn) \
38static long CONCAT2 (parse_,fn) \
39 PARAMS ((char **, const char **));
40#define INSERT_FN(fn) \
f31e2072
DE
41static void CONCAT2 (insert_,fn) \
42 PARAMS ((TXVU_INSN *, const struct txvu_operand *, \
54cc8ed4
DE
43 int, long, const char **))
44#define EXTRACT_FN(fn) \
45static long CONCAT2 (extract_,fn) \
f31e2072 46 PARAMS ((TXVU_INSN *, const struct txvu_operand *, \
54cc8ed4
DE
47 int, int *))
48#define PRINT_FN(fn) \
49static void CONCAT2 (print_,fn) \
f31e2072 50 PARAMS ((disassemble_info *, TXVU_INSN *, long));
54cc8ed4
DE
51
52PARSE_FN (dotdest);
71af45ec
DE
53INSERT_FN (dotdest);
54EXTRACT_FN (dotdest);
54cc8ed4
DE
55PRINT_FN (dotdest);
56
eb7168e5 57PARSE_FN (dotdest1);
42e65676 58PARSE_FN (dest1);
17893656 59PRINT_FN (dest1);
eb7168e5
DE
60
61PARSE_FN (bc);
d1128f73 62EXTRACT_FN (bc);
eb7168e5 63PRINT_FN (sdest);
8ea2f96f 64
71af45ec
DE
65PARSE_FN (vfreg);
66PRINT_FN (vfreg);
54cc8ed4 67
0b988d39
DE
68PARSE_FN (bcftreg);
69PRINT_FN (bcftreg);
3f897263
DE
70
71PARSE_FN (accdest);
72PRINT_FN (accdest);
73
d1128f73 74INSERT_FN (xyz);
3f897263 75
0b988d39
DE
76PARSE_FN (ireg);
77PRINT_FN (ireg);
78
79PARSE_FN (freg);
80PRINT_FN (freg);
81
82PARSE_FN (ffstreg);
83INSERT_FN (ffstreg);
84EXTRACT_FN (ffstreg);
85PRINT_FN (ffstreg);
86
87PARSE_FN (vi01);
88PRINT_FN (vi01);
89
eb7168e5
DE
90INSERT_FN (luimm12);
91EXTRACT_FN (luimm12);
0b988d39 92
42e65676
DE
93INSERT_FN (luimm12up6);
94
8ea2f96f
DE
95INSERT_FN (luimm15);
96EXTRACT_FN (luimm15);
97
3f897263 98/* Various types of TXVU operands, including insn suffixes.
54cc8ed4
DE
99
100 Fields are:
101
102 BITS SHIFT FLAGS PARSE_FN INSERT_FN EXTRACT_FN PRINT_FN
103
104 Operand values are 128 + table index. This allows ASCII chars to be
105 included in the syntax spec. */
106
107const struct txvu_operand txvu_operands[] =
108{
3f897263 109 /* place holder (??? not sure if needed) */
54cc8ed4
DE
110#define UNUSED 128
111 { 0 },
112
8ea2f96f 113 /* Operands that exist in the same place for essentially the same purpose
eb7168e5
DE
114 in both upper and lower instructions. These don't have a U or L prefix.
115 Operands specific to the upper or lower instruction are so prefixed. */
0b988d39 116
42e65676 117 /* Destination indicator attached to mnemonic, with leading '.' or '/'.
8ea2f96f
DE
118 After parsing this, the value is stored in global `dest' so that the
119 register parser can verify the same choice of xyzw is used. */
120#define DOTDEST (UNUSED + 1)
54cc8ed4 121 { 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX,
71af45ec 122 parse_dotdest, insert_dotdest, extract_dotdest, print_dotdest },
54cc8ed4 123
8ea2f96f
DE
124 /* ft reg, with vector specification same as DOTDEST */
125#define VFTREG (DOTDEST + 1)
126 { 5, TXVU_SHIFT_TREG, 0, parse_vfreg, 0, 0, print_vfreg },
54cc8ed4 127
8ea2f96f
DE
128 /* fs reg, with vector specification same as DOTDEST */
129#define VFSREG (VFTREG + 1)
130 { 5, TXVU_SHIFT_SREG, 0, parse_vfreg, 0, 0, print_vfreg },
54cc8ed4 131
8ea2f96f
DE
132 /* fd reg, with vector specification same as DOTDEST */
133#define VFDREG (VFSREG + 1)
134 { 5, TXVU_SHIFT_DREG, 0, parse_vfreg, 0, 0, print_vfreg },
135
136 /* Upper word operands. */
54cc8ed4 137
3f897263 138 /* broadcast */
8ea2f96f 139#define UBC (VFDREG + 1)
d1128f73 140 { 2, 0, TXVU_OPERAND_SUFFIX, parse_bc, 0, extract_bc, print_sdest },
3f897263
DE
141
142 /* ftreg in broadcast case */
0b988d39 143#define UBCFTREG (UBC + 1)
8ea2f96f 144 { 5, TXVU_SHIFT_TREG, 0, parse_bcftreg, 0, 0, print_bcftreg },
3f897263
DE
145
146 /* accumulator dest */
0b988d39 147#define UACCDEST (UBCFTREG + 1)
d1128f73 148 { 0, 0, 0, parse_accdest, 0, 0, print_accdest },
3f897263
DE
149
150 /* The XYZ operand is a fake one that is used to ensure only "xyz" is
151 specified. It simplifies the opmula and opmsub entries. */
0b988d39 152#define UXYZ (UACCDEST + 1)
d1128f73 153 { 0, 0, TXVU_OPERAND_FAKE, 0, insert_xyz, 0, 0 },
3f897263 154
0b988d39
DE
155 /* Lower word operands. */
156
97a6824d 157 /* 5 bit signed immediate. */
8ea2f96f 158#define LIMM5 (UXYZ + 1)
97a6824d 159 { 5, 6, TXVU_OPERAND_SIGNED, 0, 0, 0, 0 },
8ea2f96f 160
97a6824d 161 /* 11 bit signed immediate. */
8ea2f96f 162#define LIMM11 (LIMM5 + 1)
97a6824d 163 { 11, 0, TXVU_OPERAND_SIGNED, 0, 0, 0, 0 },
0b988d39 164
8ea2f96f
DE
165 /* 15 bit unsigned immediate. */
166#define LUIMM15 (LIMM11 + 1)
97a6824d 167 { 15, 0, 0, 0, insert_luimm15, extract_luimm15, 0 },
8ea2f96f
DE
168
169 /* ID register. */
170#define LIDREG (LUIMM15 + 1)
171 { 5, 6, 0, parse_ireg, 0, 0, print_ireg },
172
0b988d39 173 /* IS register. */
8ea2f96f 174#define LISREG (LIDREG + 1)
0b988d39
DE
175 { 5, 11, 0, parse_ireg, 0, 0, print_ireg },
176
177 /* IT register. */
178#define LITREG (LISREG + 1)
179 { 5, 16, 0, parse_ireg, 0, 0, print_ireg },
180
181 /* FS reg, with FSF field selector. */
182#define LFSFFSREG (LITREG + 1)
183 { 5, 11, 0, parse_ffstreg, insert_ffstreg, extract_ffstreg, print_ffstreg },
184
185 /* FS reg, no selector (choice of x,y,z,w is provided by opcode). */
186#define LFSREG (LFSFFSREG + 1)
187 { 5, 11, 0, parse_freg, 0, 0, print_freg },
188
189 /* FT reg, with FTF field selector. */
190#define LFTFFTREG (LFSREG + 1)
191 { 5, 16, 0, parse_ffstreg, insert_ffstreg, extract_ffstreg, print_ffstreg },
192
193 /* VI01 register. */
194#define LVI01 (LFTFFTREG + 1)
d1128f73 195 { 0, 0, 0, parse_vi01, 0, 0, print_vi01 },
0b988d39 196
97a6824d
DE
197 /* 24 bit unsigned immediate. */
198#define LUIMM24 (LVI01 + 1)
0b988d39
DE
199 { 24, 0, 0, 0, 0, 0, 0 },
200
eb7168e5 201 /* 12 bit unsigned immediate, split into 1 and 11 bit pieces. */
97a6824d 202#define LUIMM12 (LUIMM24 + 1)
eb7168e5 203 { 12, 0, 0, 0, insert_luimm12, extract_luimm12, 0 },
0b988d39 204
42e65676
DE
205 /* upper 6 bits of 12 bit unsigned immediate */
206#define LUIMM12UP6 (LUIMM12 + 1)
207 { 12, 0, 0, 0, insert_luimm12up6, extract_luimm12, 0 },
208
1a702a24 209 /* 11 bit pc-relative signed immediate. */
42e65676 210#define LPCREL11 (LUIMM12UP6 + 1)
1a702a24 211 { 11, 0, TXVU_OPERAND_SIGNED + TXVU_OPERAND_RELATIVE_BRANCH, 0, 0, 0, 0 },
8ea2f96f 212
eb7168e5
DE
213 /* Destination indicator, single letter only, with leading '.'. */
214#define LDOTDEST1 (LPCREL11 + 1)
8ea2f96f
DE
215 { 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX,
216 /* Note that we borrow the insert/extract/print functions from the
217 vector case. */
eb7168e5 218 parse_dotdest1, insert_dotdest, extract_dotdest, print_dotdest },
8ea2f96f 219
42e65676
DE
220 /* Destination indicator, single letter only, no leading '.'. */
221#define LDEST1 (LDOTDEST1 + 1)
17893656 222 { 0, 0, 0, parse_dest1, 0, 0, print_dest1 },
42e65676 223
54cc8ed4
DE
224/* end of list place holder */
225 { 0 }
226};
227\f
228/* Macros to put a field's value into the right place. */
1a702a24 229/* ??? If assembler needs these, move to opcode/txvu.h. */
3f897263 230
0b988d39 231/* value X, B bits, shift S */
1a702a24 232#define V(x,b,s) (((x) & ((1 << (b)) - 1)) << (s))
0b988d39 233
8ea2f96f
DE
234/* Field value macros for both upper and lower instructions.
235 These shift a value into the right place in the instruction. */
236
237/* [FI] T reg field (remember it's V for value, not vector, here). */
1a702a24 238#define VT(x) V ((x), 5, TXVU_SHIFT_TREG)
8ea2f96f 239/* [FI] S reg field. */
1a702a24 240#define VS(x) V ((x), 5, TXVU_SHIFT_SREG)
8ea2f96f 241/* [FI] D reg field. */
1a702a24 242#define VD(x) V ((x), 5, TXVU_SHIFT_DREG)
8ea2f96f 243/* DEST field. */
1a702a24 244#define VDEST(x) V ((x), 4, 21)
8ea2f96f
DE
245
246/* Masks for fields in both upper and lower instructions.
247 These mask out all bits but the ones for the field in the instruction. */
248
249#define MT VT (~0)
250#define MS VS (~0)
251#define MD VD (~0)
252#define MDEST VDEST (~0)
253
0b988d39 254/* Upper instruction Value macros. */
54cc8ed4 255
3f897263 256/* Upper Flag bits. */
1a702a24 257#define VUF(x) V ((x), 5, 27)
3f897263 258/* Upper REServed two bits next to flag bits. */
1a702a24 259#define VURES(x) V ((x), 2, 25)
0b988d39 260/* 4 bit opcode field. */
1a702a24 261#define VUOP4(x) V ((x), 4, 2)
0b988d39 262/* 6 bit opcode field. */
1a702a24 263#define VUOP6(x) V ((x), 6, 0)
0b988d39 264/* 9 bit opcode field. */
1a702a24 265#define VUOP9(x) V ((x), 9, 2)
0b988d39 266/* 11 bit opcode field. */
1a702a24 267#define VUOP11(x) V ((x), 11, 0)
0b988d39 268/* BroadCast field. */
1a702a24 269#define VUBC(x) V ((x), 2, 0)
0b988d39 270
8ea2f96f 271/* Upper instruction field masks. */
0b988d39
DE
272#define MUUBITS (VUF (~0) + VURES (~0))
273#define MURES VURES (~0)
274#define MUOP4 VUOP4 (~0)
275#define MUOP6 VUOP6 (~0)
276#define MUOP9 VUOP9 (~0)
277#define MUOP11 VUOP11 (~0)
278
1a702a24
DE
279/* A space, separates instruction name (mnemonic + mnemonic operands) from
280 operands. */
3f897263 281#define SP ' '
1a702a24
DE
282/* Commas separate operands. */
283#define C ','
284/* Special I,P,Q,R operands. */
285#define I 'i'
286#define P 'p'
287#define Q 'q'
288#define R 'r'
3f897263 289
54cc8ed4
DE
290/* TXVU instructions.
291 [??? some of these comments are left over from the ARC port from which
292 this code is borrowed, delete in time]
293
294 Longer versions of insns must appear before shorter ones (if gas sees
295 "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
296 junk). This isn't necessary for `ld' because of the trailing ']'.
297
298 Instructions that are really macros based on other insns must appear
299 before the real insn so they're chosen when disassembling. Eg: The `mov'
300 insn is really the `and' insn.
301
302 This table is best viewed on a wide screen (161 columns). I'd prefer to
303 keep it this way. The rest of the file, however, should be viewable on an
304 80 column terminal. */
305
306/* ??? This table also includes macros: asl, lsl, and mov. The ppc port has
307 a more general facility for dealing with macros which could be used if
308 we need to. */
309
310/* These tables can't be `const' because members `next_asm' and `next_dis' are
311 computed at run-time. We could split this into two, as that would put the
312 constant stuff into a readonly section. */
313
b5d20cf6
DE
314struct txvu_opcode txvu_upper_opcodes[] =
315{
1a702a24 316 /* Macros appear first, so the disassembler will try them first. */
54cc8ed4 317 /* ??? Any aliases? */
1a702a24 318 /* ??? When close to being finished, clean up by aligning fields. */
54cc8ed4 319
3f897263 320 /* The rest of these needn't be sorted, but it helps to find them if they are. */
1a702a24
DE
321 { "abs", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x1fd) },
322 { "add", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x28) },
323 { "addi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x22) },
324 { "addq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x20) },
325 { "add", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + VUOP4 (~0), VUOP4 (0) },
326 { "adda", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2bc) },
327 { "addai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x23e) },
328 { "addaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x23c) },
329 { "adda", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0xf) },
8ea2f96f 330 { "clip", { DOTDEST, SP, VFSREG }, MURES + MDEST + MT + MUOP11, VDEST (0xf) + VUOP11 (0x1ff) },
1a702a24
DE
331 { "ftoi0", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x17c) },
332 { "ftoi4", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x17d) },
333 { "ftoi12", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x17e) },
334 { "ftoi15", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x17f) },
335 { "itof0", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x13c) },
336 { "itof4", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x13d) },
337 { "itof12", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x13e) },
338 { "itof15", { DOTDEST, SP, VFTREG, C, VFSREG }, MURES + MUOP11, VUOP11 (0x13f) },
339 { "madd", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x29) },
340 { "maddi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x23) },
341 { "maddq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x21) },
342 { "madd", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + MUOP4, VUOP4 (0x2) },
343 { "madda", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2bd) },
344 { "maddai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x23f) },
345 { "maddaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x23d) },
346 { "madda", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0x2f) },
347 { "max", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2b) },
348 { "maxi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x2d) },
349 { "max", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + MUOP4, VUOP4 (0x4) },
350 /* ??? mini or min? */
351 { "mini", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2f) },
d1128f73 352 { "minii", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x1f) },
1a702a24
DE
353 { "mini", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + MUOP4, VUOP4 (0x5) },
354 { "msub", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2d) },
355 { "msubi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x27) },
356 { "msubq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x25) },
357 { "msub", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + MUOP4, VUOP4 (0x3) },
358 { "msuba", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2fd) },
359 { "msubai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x27f) },
360 { "msubaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x27d) },
361 { "msuba", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0x3f) },
362 { "mul", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2a) },
363 { "muli", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x1e) },
364 { "mulq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x1c) },
365 { "mul", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + VUOP4 (~0), VUOP4 (6) },
366 { "mula", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2be) },
367 { "mulai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x1fe) },
368 { "mulaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x1fc) },
369 { "mula", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0x6f) },
8ea2f96f 370 { "nop", { 0 }, MURES + MDEST + MT + MS + MUOP11, VUOP11 (0x2ff) },
1a702a24
DE
371 { "opmula", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG, UXYZ }, MURES + MUOP11, VUOP11 (0x2fe) },
372 { "opmsub", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG, UXYZ }, MURES + MUOP6, VUOP6 (0x2e) },
373 { "sub", { DOTDEST, SP, VFDREG, C, VFSREG, C, VFTREG }, MURES + MUOP6, VUOP6 (0x2c) },
374 { "subi", { DOTDEST, SP, VFDREG, C, VFSREG, C, I }, MURES + MT + MUOP6, VUOP6 (0x26) },
375 { "subq", { DOTDEST, SP, VFDREG, C, VFSREG, C, Q }, MURES + MT + MUOP6, VUOP6 (0x24) },
376 { "sub", { UBC, DOTDEST, SP, VFDREG, C, VFSREG, C, UBCFTREG }, MURES + VUOP4 (~0), VUOP4 (1) },
377 { "suba", { DOTDEST, SP, UACCDEST, C, VFSREG, C, VFTREG }, MURES + MUOP11, VUOP11 (0x2fc) },
378 { "subai", { DOTDEST, SP, UACCDEST, C, VFSREG, C, I }, MURES + MT + MUOP11, VUOP11 (0x27e) },
379 { "subaq", { DOTDEST, SP, UACCDEST, C, VFSREG, C, Q }, MURES + MT + MUOP11, VUOP11 (0x27c) },
380 { "suba", { UBC, DOTDEST, SP, UACCDEST, C, VFSREG, C, UBCFTREG }, MURES + MUOP9, VUOP9 (0x1f) }
54cc8ed4 381};
97a6824d 382const int txvu_upper_opcodes_count = sizeof (txvu_upper_opcodes) / sizeof (txvu_upper_opcodes[0]);
8ea2f96f
DE
383\f
384/* Lower instruction Value macros. */
385
386/* 6 bit opcode. */
1a702a24 387#define VLOP6(x) V ((x), 6, 0)
8ea2f96f 388/* 7 bit opcode. */
1a702a24 389#define VLOP7(x) V ((x), 7, 25)
8ea2f96f 390/* 11 bit opcode. */
1a702a24 391#define VLOP11(x) V ((x), 11, 0)
8ea2f96f 392/* 11 bit immediate. */
1a702a24 393#define VLIMM11(x) V ((x), 11, 0)
8ea2f96f 394/* FTF field. */
1a702a24 395#define VLFTF(x) V ((x), 2, 23)
8ea2f96f 396/* FSF field. */
1a702a24 397#define VLFSF(x) V ((x), 2, 21)
eb7168e5 398/* Upper bit of 12 bit unsigned immediate. */
1a702a24 399#define VLUIMM12TOP(x) V ((x), 1, 21)
eb7168e5
DE
400/* Upper 4 bits of 15 bit unsigned immediate. */
401#define VLUIMM15TOP(x) VDEST (x)
8ea2f96f
DE
402
403/* Lower instruction field masks. */
404#define MLOP6 VLOP6 (~0)
405#define MLOP7 VLOP7 (~0)
406#define MLOP11 VLOP11 (~0)
407#define MLIMM11 VLIMM11 (~0)
1a702a24 408#define MLB24 V (1, 1, 24)
eb7168e5
DE
409#define MLUIMM12TOP VLUIMM12TOP (~0)
410/* 12 bit unsigned immediates are split into two parts, 1 bit and 11 bits.
8ea2f96f
DE
411 The upper 1 bit is part of the `dest' field. This mask is for the
412 other 3 bits of the dest field. */
1a702a24 413#define MLUIMM12UNUSED V (7, 3, 22)
eb7168e5 414#define MLUIMM15TOP MDEST
54cc8ed4 415
b5d20cf6
DE
416struct txvu_opcode txvu_lower_opcodes[] =
417{
1a702a24 418 /* Macros appear first, so the disassembler will try them first. */
54cc8ed4 419 /* ??? Any aliases? */
1a702a24
DE
420 /* ??? There isn't an explicit nop. Apparently it's "move vf0,vf0". */
421 { "nop", { 0 }, 0xffffffff, VLOP7 (0x40) + VLIMM11 (0x33c) },
54cc8ed4 422
0b988d39 423 /* The rest of these needn't be sorted, but it helps to find them if they are. */
8ea2f96f 424 { "b", { SP, LPCREL11 }, MLOP7 + MDEST + MT + MS, VLOP7 (0x20) },
1a702a24
DE
425 { "bal", { SP, LITREG, C, LPCREL11 }, MLOP7 + MDEST + MS, VLOP7 (0x21) },
426 { "div", { SP, Q, C, LFSFFSREG, C, LFTFFTREG }, MLOP7 + MLOP11, VLOP7 (0x40) + VLOP11 (0x3bc) },
427 { "eatan", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7fd) },
428 { "eatanxy", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x77c) },
429 { "eatanxz", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x77d) },
430 { "eexp", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7fe) },
431 { "eleng", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x74e) },
432 { "ercpr", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7be) },
433 { "erleng", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x73f) },
434 { "ersadd", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x73d) },
435 { "ersqrt", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7bd) },
436 { "esadd", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x73c) },
437 { "esin", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7fc) },
438 { "esqrt", { SP, P, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLOP11, VLOP7 (0x40) + VLOP11 (0x7bc) },
439 { "esum", { SP, P, C, LFSREG }, MLOP7 + MDEST + MT + MLOP11, VLOP7 (0x40) + VDEST (0xf) + VLOP11 (0x77e) },
440 { "fcand", { SP, LVI01, C, LUIMM24 }, MLOP7 + MLB24, VLOP7 (0x12) },
441 { "fceq", { SP, LVI01, C, LUIMM24 }, MLOP7 + MLB24, VLOP7 (0x10) },
8ea2f96f 442 { "fcget", { SP, LITREG }, MLOP7 + MDEST + MS + MLIMM11, VLOP7 (0x1c) },
1a702a24 443 { "fcor", { SP, LVI01, C, LUIMM24 }, MLOP7 + MLB24, VLOP7 (0x13) },
42e65676 444 { "fcset", { SP, LUIMM24 }, MLOP7 + MLB24, VLOP7 (0x11) },
1a702a24
DE
445 { "fmand", { SP, LITREG, C, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x1a) },
446 { "fmeq", { SP, LITREG, C, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x18) },
447 { "fmor", { SP, LITREG, C, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x1b) },
448 { "fsand", { SP, LITREG, C, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x16) },
449 { "fseq", { SP, LITREG, C, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x14) },
450 { "fsor", { SP, LITREG, C, LUIMM12 }, MLOP7 + MLUIMM12UNUSED + MS, VLOP7 (0x17) },
42e65676 451 { "fsset", { SP, LUIMM12UP6 }, MLOP7 + MLUIMM12UNUSED + V (~0, 6, 0) + MS + MT, VLOP7 (0x15) },
1a702a24
DE
452 { "iadd", { SP, LIDREG, C, LISREG, C, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x30) },
453 { "iaddi", { SP, LITREG, C, LISREG, C, LIMM5 }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x32) },
454 { "iaddiu", { SP, LITREG, C, LISREG, C, LUIMM15 }, MLOP7, VLOP7 (0x08) },
455 { "iand", { SP, LIDREG, C, LISREG, C, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x34) },
456 { "ibeq", { SP, LITREG, C, LISREG, C, LPCREL11 }, MLOP7 + MDEST, VLOP7 (0x28) },
457 { "ibgez", { SP, LISREG, C, LPCREL11 }, MLOP7 + MDEST + MT, VLOP7 (0x2f) },
42e65676 458 { "ibgtz", { SP, LISREG, C, LPCREL11 }, MLOP7 + MDEST + MT, VLOP7 (0x2d) },
1a702a24
DE
459 { "iblez", { SP, LISREG, C, LPCREL11 }, MLOP7 + MDEST + MT, VLOP7 (0x2e) },
460 { "ibltz", { SP, LISREG, C, LPCREL11 }, MLOP7 + MDEST + MT, VLOP7 (0x2c) },
461 { "ibne", { SP, LITREG, C, LISREG, C, LPCREL11 }, MLOP7 + MDEST, VLOP7 (0x29) },
42e65676 462 { "ilw", { LDOTDEST1, SP, LITREG, C, LIMM11, '(', LISREG, ')', LDEST1 }, MLOP7, VLOP7 (0x04) },
17893656 463 { "ilwr", { LDOTDEST1, SP, LITREG, C, '(', LISREG, ')', LDEST1 }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fe) },
1a702a24
DE
464 { "ior", { SP, LIDREG, C, LISREG, C, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x34) },
465 { "isub", { SP, LIDREG, C, LISREG, C, LITREG }, MLOP7 + MDEST + MLOP6, VLOP7 (0x40) + VLOP6 (0x31) },
466 { "isubiu", { SP, LITREG, C, LISREG, C, LUIMM15 }, MLOP7, VLOP7 (0x09) },
42e65676 467 { "isw", { LDOTDEST1, SP, LITREG, C, LIMM11, '(', LISREG, ')', LDEST1 }, MLOP7, VLOP7 (0x05) },
17893656 468 { "iswr", { LDOTDEST1, SP, LITREG, C, '(', LISREG, ')', LDEST1 }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3ff) },
1a702a24 469 { "jalr", { SP, LITREG, C, LISREG }, MLOP7 + MDEST + MLIMM11, VLOP7 (0x25) },
8ea2f96f 470 { "jr", { SP, LISREG }, MLOP7 + MDEST + MT + MLIMM11, VLOP7 (0x24) },
1a702a24 471 { "lq", { DOTDEST, SP, VFTREG, C, LIMM11, '(', LISREG, ')' }, MLOP7, VLOP7 (0x00) },
42e65676
DE
472 { "lqd", { DOTDEST, SP, VFTREG, C, '(', '-', '-', LISREG, ')' }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x37e) },
473 { "lqi", { DOTDEST, SP, VFTREG, C, '(', LISREG, '+', '+', ')' }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x37c) },
eb7168e5 474 /* Only a single VF reg is allowed here. We can use VFTREG because LDOTDEST1
8ea2f96f 475 handles verifying only a single choice of xyzw is present. */
1a702a24
DE
476 { "mfir", { LDOTDEST1, SP, VFTREG, C, LISREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fc) },
477 { "mfp", { DOTDEST, SP, VFTREG, C, P }, MLOP7 + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x67c) },
478 { "move", { DOTDEST, SP, VFTREG, C, VFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x33c) },
479 { "mr32", { DOTDEST, SP, VFTREG, C, VFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x33d) },
42e65676 480 { "mtir", { LDOTDEST1, SP, LITREG, C, VFSREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3fd) },
1a702a24
DE
481 { "rget", { DOTDEST, SP, VFTREG, C, R }, MLOP7 + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43d) },
482 { "rinit", { SP, R, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43e) },
483 { "rnext", { DOTDEST, SP, VFTREG, C, R }, MLOP7 + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43c) },
484 { "rsqrt", { SP, Q, C, LFSFFSREG, C, LFTFFTREG }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3be) },
42e65676 485 { "rxor", { SP, R, C, LFSFFSREG }, MLOP7 + VLFTF (~0) + MT + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x43f) },
1a702a24 486 { "sq", { DOTDEST, SP, VFTREG, C, LIMM11, '(', LISREG, ')' }, MLOP7, VLOP7 (0x01) },
42e65676
DE
487 { "sqd", { DOTDEST, SP, VFTREG, C, '(', '-', '-', LISREG, ')' }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x37f) },
488 { "sqi", { DOTDEST, SP, VFTREG, C, '(', LISREG, '+', '+', ')' }, MLOP7 + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x37d) },
1a702a24 489 { "sqrt", { SP, Q, C, LFTFFTREG }, MLOP7 + VLFSF (~0) + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x3bd) },
8ea2f96f
DE
490 { "waitp", { 0 }, 0xffffffff, VLOP7 (0x40) + VLIMM11 (0x7bf) },
491 { "waitq", { 0 }, 0xffffffff, VLOP7 (0x40) + VLIMM11 (0x3bf) },
42e65676
DE
492 { "xgkick", { SP, LISREG }, MLOP7 + MDEST + MT + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x6fc) },
493 { "xitop", { SP, LITREG }, MLOP7 + MDEST + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x6bd) },
494 { "xtop", { SP, LITREG }, MLOP7 + MDEST + MS + MLIMM11, VLOP7 (0x40) + VLIMM11 (0x6bc) }
54cc8ed4 495};
97a6824d 496const int txvu_lower_opcodes_count = sizeof (txvu_lower_opcodes) / sizeof (txvu_lower_opcodes[0]);
8ea2f96f 497\f
54cc8ed4 498/* Value of DEST in use.
71af45ec 499 Each of the registers must specify the same value as the opcode.
54cc8ed4 500 ??? Perhaps remove the duplication? */
42e65676 501static int mnemonic_dest;
3f897263
DE
502
503/* Value of BC to use.
504 The register specified for the ftreg must match the broadcast register
505 specified in the opcode. */
42e65676 506static int mnemonic_bc;
54cc8ed4 507\f
8ea2f96f 508/* Multiple destination choice support.
54cc8ed4
DE
509 The "dest" string selects any combination of x,y,z,w.
510 [The letters are ordered that way to follow the manual's style.] */
511
eb7168e5 512/* Utility to parse a `dest' spec.
71af45ec
DE
513 Return the found value.
514 *PSTR is set to the character that terminated the parsing.
515 It is up to the caller to do any error checking. */
516
54cc8ed4 517static long
eb7168e5 518_parse_dest (pstr)
54cc8ed4 519 char **pstr;
54cc8ed4
DE
520{
521 long dest = 0;
522
54cc8ed4
DE
523 while (**pstr)
524 {
525 switch (**pstr)
526 {
527 case 'x' : case 'X' : dest |= TXVU_DEST_X; break;
528 case 'y' : case 'Y' : dest |= TXVU_DEST_Y; break;
529 case 'z' : case 'Z' : dest |= TXVU_DEST_Z; break;
530 case 'w' : case 'W' : dest |= TXVU_DEST_W; break;
71af45ec 531 default : return dest;
54cc8ed4
DE
532 }
533 ++*pstr;
534 }
535
71af45ec
DE
536 return dest;
537}
538
539static long
540parse_dotdest (pstr, errmsg)
541 char **pstr;
542 const char **errmsg;
543{
544 long dest;
545
546 if (**pstr != '.')
547 {
548 *errmsg = "missing `.'";
549 return 0;
550 }
551
552 ++*pstr;
eb7168e5 553 dest = _parse_dest (pstr);
71af45ec
DE
554 if (dest == 0 || isalnum (**pstr))
555 {
556 *errmsg = "invalid `dest'";
557 return 0;
558 }
eb7168e5 559
54cc8ed4
DE
560 return dest;
561}
562
eb7168e5
DE
563/* Parse a `dest' spec where only a single letter is allowed,
564 but the encoding handles all four. */
8ea2f96f
DE
565
566static long
eb7168e5 567parse_dotdest1 (pstr, errmsg)
8ea2f96f
DE
568 char **pstr;
569 const char **errmsg;
570{
eb7168e5 571 char c;
8ea2f96f
DE
572 long dest;
573
574 if (**pstr != '.')
575 {
576 *errmsg = "missing `.'";
577 return 0;
578 }
579
580 ++*pstr;
581 switch (**pstr)
582 {
42e65676
DE
583 case 'x' : case 'X' : dest = TXVU_DEST_X; break;
584 case 'y' : case 'Y' : dest = TXVU_DEST_Y; break;
585 case 'z' : case 'Z' : dest = TXVU_DEST_Z; break;
586 case 'w' : case 'W' : dest = TXVU_DEST_W; break;
8ea2f96f
DE
587 default : *errmsg = "invalid `dest'"; return 0;
588 }
eb7168e5 589 ++*pstr;
42e65676 590 c = tolower (**pstr);
eb7168e5
DE
591 if (c == 'x' || c == 'y' || c == 'z' || c == 'w')
592 {
593 *errmsg = "only one of x,y,z,w can be specified";
594 return 0;
595 }
596 if (isalnum (**pstr))
597 {
598 *errmsg = "invalid `dest'";
599 return 0;
600 }
601
8ea2f96f
DE
602 return dest;
603}
604
42e65676
DE
605/* Parse a `dest' spec with no leading '.', where only a single letter is
606 allowed, but the encoding handles all four. The parsed value must match
607 that recorded in `dest'. */
608
609static long
610parse_dest1 (pstr, errmsg)
611 char **pstr;
612 const char **errmsg;
613{
614 char c;
615 long dest;
616
617 dest = _parse_dest (pstr);
618 if (dest != TXVU_DEST_X
619 && dest != TXVU_DEST_Y
620 && dest != TXVU_DEST_Z
621 && dest != TXVU_DEST_W)
622 {
623 *errmsg = "expecting one of x,y,z,w";
624 return 0;
625 }
626
627 if (dest != mnemonic_dest)
628 {
629 *errmsg = "`dest' suffix does not match instruction `dest'";
630 return 0;
631 }
632
42e65676
DE
633 return dest;
634}
635
f31e2072 636static void
71af45ec 637insert_dotdest (insn, operand, mods, value, errmsg)
f31e2072 638 TXVU_INSN *insn;
71af45ec
DE
639 const struct txvu_operand *operand;
640 int mods;
641 long value;
642 const char **errmsg;
643{
644 /* Record the DEST value in use so the register parser can use it. */
42e65676 645 mnemonic_dest = value;
f31e2072 646 *insn |= value << operand->shift;
71af45ec
DE
647}
648
649static long
650extract_dotdest (insn, operand, mods, pinvalid)
f31e2072 651 TXVU_INSN *insn;
71af45ec
DE
652 const struct txvu_operand *operand;
653 int mods;
654 int *pinvalid;
655{
656 /* Record the DEST value in use so the register printer can use it. */
f31e2072 657 mnemonic_dest = (*insn >> operand->shift) & ((1 << operand->bits) - 1);
42e65676 658 return mnemonic_dest;
71af45ec
DE
659}
660
eb7168e5
DE
661/* Utility to print a multiple dest spec. */
662
54cc8ed4 663static void
eb7168e5 664_print_dest (info, insn, value)
54cc8ed4 665 disassemble_info *info;
f31e2072 666 TXVU_INSN *insn;
54cc8ed4
DE
667 long value;
668{
54cc8ed4
DE
669 if (value & TXVU_DEST_X)
670 (*info->fprintf_func) (info->stream, "x");
671 if (value & TXVU_DEST_Y)
672 (*info->fprintf_func) (info->stream, "y");
673 if (value & TXVU_DEST_Z)
674 (*info->fprintf_func) (info->stream, "z");
675 if (value & TXVU_DEST_W)
676 (*info->fprintf_func) (info->stream, "w");
677}
71af45ec
DE
678
679static void
680print_dotdest (info, insn, value)
681 disassemble_info *info;
f31e2072 682 TXVU_INSN *insn;
71af45ec
DE
683 long value;
684{
685 (*info->fprintf_func) (info->stream, ".");
eb7168e5
DE
686 _print_dest (info, insn, value);
687}
17893656
DE
688
689static void
690print_dest1 (info, insn, value)
691 disassemble_info *info;
f31e2072 692 TXVU_INSN *insn;
17893656
DE
693 long value;
694{
695 _print_dest (info, insn, mnemonic_dest);
696}
eb7168e5
DE
697\f
698/* Utilities for single destination choice handling. */
699
700static long
701_parse_sdest (pstr, errmsg)
702 char **pstr;
703 const char **errmsg;
704{
705 char c;
706 long dest = 0;
707
708 switch (**pstr)
709 {
710 case 'x' : case 'X' : dest = TXVU_SDEST_X; break;
711 case 'y' : case 'Y' : dest = TXVU_SDEST_Y; break;
712 case 'z' : case 'Z' : dest = TXVU_SDEST_Z; break;
713 case 'w' : case 'W' : dest = TXVU_SDEST_W; break;
714 default : *errmsg = "only one of x,y,z,w can be specified"; return 0;
715 }
716 ++*pstr;
42e65676 717 c = tolower (**pstr);
eb7168e5
DE
718 if (c == 'x' || c == 'y' || c == 'z' || c == 'w')
719 {
720 *errmsg = "only one of x,y,z,w can be specified";
721 return 0;
722 }
723 if (isalnum (**pstr))
724 {
725 *errmsg = "invalid `dest'";
726 return 0;
727 }
728
eb7168e5
DE
729 return dest;
730}
731
732static void
733print_sdest (info, insn, value)
734 disassemble_info *info;
f31e2072 735 TXVU_INSN *insn;
eb7168e5
DE
736 long value;
737{
738 char c;
739
740 switch (value)
741 {
742 case TXVU_SDEST_X : c = 'x'; break;
743 case TXVU_SDEST_Y : c = 'y'; break;
744 case TXVU_SDEST_Z : c = 'z'; break;
745 case TXVU_SDEST_W : c = 'w'; break;
746 }
747
748 (*info->fprintf_func) (info->stream, "%c", c);
749}
750\f
751/* Broadcase field. */
752
753static long
754parse_bc (pstr, errmsg)
755 char **pstr;
756 const char **errmsg;
757{
758 long value = _parse_sdest (pstr, errmsg);
759
760 if (*errmsg)
761 return 0;
762 /* Save value for later verification in register parsing. */
42e65676 763 mnemonic_bc = value;
eb7168e5
DE
764 return value;
765}
766
767/* During the extraction process, save the bc field for use in
768 printing the bc register. */
769
770static long
771extract_bc (insn, operand, mods, pinvalid)
f31e2072 772 TXVU_INSN *insn;
eb7168e5
DE
773 const struct txvu_operand *operand;
774 int mods;
775 int *pinvalid;
776{
f31e2072 777 mnemonic_bc = *insn & 3;
42e65676 778 return mnemonic_bc;
71af45ec 779}
54cc8ed4
DE
780\f
781static long
71af45ec 782parse_vfreg (pstr, errmsg)
54cc8ed4
DE
783 char **pstr;
784 const char **errmsg;
785{
786 char *str = *pstr;
787 char *start;
788 long reg;
71af45ec 789 int reg_dest;
54cc8ed4
DE
790
791 if (tolower (str[0]) != 'v'
792 || tolower (str[1]) != 'f')
793 {
794 *errmsg = "unknown register";
795 return 0;
796 }
797
798 /* FIXME: quick hack until the framework works. */
799 start = str = str + 2;
800 while (*str && isdigit (*str))
801 ++str;
802 reg = atoi (start);
eb7168e5
DE
803 if (reg < 0 || reg > 31)
804 {
805 *errmsg = "invalid register number";
806 return 0;
807 }
808 reg_dest = _parse_dest (&str);
71af45ec
DE
809 if (reg_dest == 0 || isalnum (*str))
810 {
811 *errmsg = "invalid `dest'";
812 return 0;
813 }
42e65676 814 if (reg_dest != mnemonic_dest)
71af45ec
DE
815 {
816 *errmsg = "register `dest' does not match instruction `dest'";
817 return 0;
818 }
54cc8ed4 819 *pstr = str;
54cc8ed4
DE
820 return reg;
821}
822
823static void
71af45ec 824print_vfreg (info, insn, value)
54cc8ed4 825 disassemble_info *info;
f31e2072 826 TXVU_INSN *insn;
54cc8ed4
DE
827 long value;
828{
d1128f73 829 (*info->fprintf_func) (info->stream, "vf%02ld", value);
42e65676 830 _print_dest (info, insn, mnemonic_dest);
3f897263
DE
831}
832\f
833/* FT register in broadcast case. */
834
835static long
0b988d39 836parse_bcftreg (pstr, errmsg)
3f897263
DE
837 char **pstr;
838 const char **errmsg;
839{
840 char *str = *pstr;
841 char *start;
842 long reg;
843 int reg_bc;
844
845 if (tolower (str[0]) != 'v'
846 || tolower (str[1]) != 'f')
847 {
848 *errmsg = "unknown register";
849 return 0;
850 }
851
852 /* FIXME: quick hack until the framework works. */
853 start = str = str + 2;
854 while (*str && isdigit (*str))
855 ++str;
856 reg = atoi (start);
eb7168e5
DE
857 if (reg < 0 || reg > 31)
858 {
859 *errmsg = "invalid register number";
860 return 0;
861 }
862 reg_bc = _parse_sdest (&str, errmsg);
3f897263
DE
863 if (*errmsg)
864 return 0;
42e65676 865 if (reg_bc != mnemonic_bc)
3f897263
DE
866 {
867 *errmsg = "register `bc' does not match instruction `bc'";
868 return 0;
869 }
870 *pstr = str;
3f897263
DE
871 return reg;
872}
873
874static void
0b988d39 875print_bcftreg (info, insn, value)
3f897263 876 disassemble_info *info;
f31e2072 877 TXVU_INSN *insn;
3f897263
DE
878 long value;
879{
d1128f73 880 (*info->fprintf_func) (info->stream, "vf%02ld", value);
42e65676 881 print_sdest (info, insn, mnemonic_bc);
3f897263
DE
882}
883\f
884/* ACC handling. */
885
886static long
887parse_accdest (pstr, errmsg)
888 char **pstr;
889 const char **errmsg;
890{
891 char *str = *pstr;
892 long acc_dest = 0;
893
894 if (strncasecmp (str, "acc", 3) != 0)
895 {
896 *errmsg = "expecting `acc'";
897 return 0;
898 }
899 str += 3;
eb7168e5 900 acc_dest = _parse_dest (&str);
3f897263
DE
901 if (acc_dest == 0 || isalnum (*str))
902 {
903 *errmsg = "invalid `dest'";
904 return 0;
905 }
42e65676 906 if (acc_dest != mnemonic_dest)
3f897263
DE
907 {
908 *errmsg = "acc `dest' does not match instruction `dest'";
909 return 0;
910 }
911 *pstr = str;
3f897263
DE
912 /* Value isn't used, but we must return something. */
913 return 0;
914}
915
916static void
917print_accdest (info, insn, value)
918 disassemble_info *info;
f31e2072 919 TXVU_INSN *insn;
3f897263
DE
920 long value;
921{
922 (*info->fprintf_func) (info->stream, "acc");
42e65676 923 _print_dest (info, insn, mnemonic_dest);
3f897263
DE
924}
925\f
926/* XYZ operand handling.
927 This simplifies the opmula,opmsub entries by keeping them equivalent to
928 the others. */
929
f31e2072 930static void
d1128f73 931insert_xyz (insn, operand, mods, value, errmsg)
f31e2072 932 TXVU_INSN *insn;
d1128f73
DE
933 const struct txvu_operand *operand;
934 int mods;
935 long value;
3f897263
DE
936 const char **errmsg;
937{
42e65676 938 if (mnemonic_dest != (TXVU_DEST_X | TXVU_DEST_Y | TXVU_DEST_Z))
f31e2072 939 *errmsg = "expecting `xyz' for `dest' value";
3f897263 940}
0b988d39 941\f
eb7168e5
DE
942/* F[ST] register using selector in F[ST]F field.
943 Internally, the value is encoded in 7 bits: the 2 bit xyzw indicator
944 followed by the 5 bit register number. */
0b988d39
DE
945
946static long
947parse_ffstreg (pstr, errmsg)
948 char **pstr;
949 const char **errmsg;
950{
951 char *str = *pstr;
952 char *start;
eb7168e5 953 int reg, xyzw;
0b988d39
DE
954
955 if (tolower (str[0]) != 'v'
956 || tolower (str[1]) != 'f')
957 {
958 *errmsg = "unknown register";
959 return 0;
960 }
961
962 /* FIXME: quick hack until the framework works. */
963 start = str = str + 2;
964 while (*str && isdigit (*str))
965 ++str;
966 reg = atoi (start);
eb7168e5 967 if (reg < 0 || reg > 31)
0b988d39 968 {
eb7168e5 969 *errmsg = "invalid register number";
0b988d39
DE
970 return 0;
971 }
eb7168e5
DE
972 xyzw = _parse_sdest (&str, errmsg);
973 if (*errmsg)
974 return 0;
0b988d39 975 *pstr = str;
eb7168e5 976 return reg | (xyzw << 5);
0b988d39
DE
977}
978
979static void
980print_ffstreg (info, insn, value)
981 disassemble_info *info;
f31e2072 982 TXVU_INSN *insn;
0b988d39
DE
983 long value;
984{
17893656 985 (*info->fprintf_func) (info->stream, "vf%02ld", value & TXVU_MASK_REG);
eb7168e5 986 print_sdest (info, insn, (value >> 5) & 3);
0b988d39
DE
987}
988
f31e2072 989static void
0b988d39 990insert_ffstreg (insn, operand, mods, value, errmsg)
f31e2072 991 TXVU_INSN *insn;
0b988d39
DE
992 const struct txvu_operand *operand;
993 int mods;
994 long value;
995 const char **errmsg;
996{
eb7168e5 997 if (operand->shift == TXVU_SHIFT_SREG)
f31e2072 998 *insn |= VLFSF (value >> 5) | VS (value);
eb7168e5 999 else
f31e2072 1000 *insn |= VLFTF (value >> 5) | VT (value);
0b988d39
DE
1001}
1002
1003static long
1004extract_ffstreg (insn, operand, mods, pinvalid)
f31e2072 1005 TXVU_INSN *insn;
0b988d39
DE
1006 const struct txvu_operand *operand;
1007 int mods;
1008 int *pinvalid;
1009{
eb7168e5 1010 if (operand->shift == TXVU_SHIFT_SREG)
f31e2072 1011 return (((*insn & VLFSF (~0)) >> 21) << 5) | VS (*insn);
eb7168e5 1012 else
f31e2072 1013 return (((*insn & VLFTF (~0)) >> 21) << 5) | VT (*insn);
0b988d39
DE
1014}
1015\f
1016/* F register. */
1017
1018static long
1019parse_freg (pstr, errmsg)
1020 char **pstr;
1021 const char **errmsg;
1022{
1023 char *str = *pstr;
1024 char *start;
1025 long reg;
0b988d39
DE
1026
1027 if (tolower (str[0]) != 'v'
1028 || tolower (str[1]) != 'f')
1029 {
1030 *errmsg = "unknown register";
1031 return 0;
1032 }
1033
1034 /* FIXME: quick hack until the framework works. */
1035 start = str = str + 2;
1036 while (*str && isdigit (*str))
1037 ++str;
1038 reg = atoi (start);
eb7168e5 1039 if (reg < 0 || reg > 31)
0b988d39 1040 {
eb7168e5 1041 *errmsg = "invalid register number";
0b988d39
DE
1042 return 0;
1043 }
1044 *pstr = str;
0b988d39
DE
1045 return reg;
1046}
1047
1048static void
1049print_freg (info, insn, value)
1050 disassemble_info *info;
f31e2072 1051 TXVU_INSN *insn;
0b988d39
DE
1052 long value;
1053{
17893656 1054 (*info->fprintf_func) (info->stream, "vf%02ld", value);
0b988d39
DE
1055}
1056\f
1057/* I register. */
1058
1059static long
1060parse_ireg (pstr, errmsg)
1061 char **pstr;
1062 const char **errmsg;
1063{
1064 char *str = *pstr;
1065 char *start;
1066 long reg;
0b988d39
DE
1067
1068 if (tolower (str[0]) != 'v'
eb7168e5 1069 || tolower (str[1]) != 'i')
0b988d39
DE
1070 {
1071 *errmsg = "unknown register";
1072 return 0;
1073 }
1074
1075 /* FIXME: quick hack until the framework works. */
1076 start = str = str + 2;
1077 while (*str && isdigit (*str))
1078 ++str;
1079 reg = atoi (start);
eb7168e5 1080 if (reg < 0 || reg > 31)
0b988d39 1081 {
eb7168e5 1082 *errmsg = "invalid register number";
0b988d39
DE
1083 return 0;
1084 }
1085 *pstr = str;
0b988d39
DE
1086 return reg;
1087}
1088
1089static void
1090print_ireg (info, insn, value)
1091 disassemble_info *info;
f31e2072 1092 TXVU_INSN *insn;
0b988d39
DE
1093 long value;
1094{
17893656 1095 (*info->fprintf_func) (info->stream, "vi%02ld", value);
0b988d39
DE
1096}
1097\f
1098/* VI01 register. */
1099
1100static long
1101parse_vi01 (pstr, errmsg)
1102 char **pstr;
1103 const char **errmsg;
1104{
1105 char *str = *pstr;
1106 char *start;
1107 long reg;
0b988d39
DE
1108
1109 if (tolower (str[0]) != 'v'
eb7168e5 1110 || tolower (str[1]) != 'i')
0b988d39
DE
1111 {
1112 *errmsg = "unknown register";
1113 return 0;
1114 }
1115
1116 /* FIXME: quick hack until the framework works. */
1117 start = str = str + 2;
1118 while (*str && isdigit (*str))
1119 ++str;
1120 reg = atoi (start);
eb7168e5 1121 if (reg != 1)
0b988d39 1122 {
eb7168e5 1123 *errmsg = "vi01 required here";
0b988d39
DE
1124 return 0;
1125 }
1126 *pstr = str;
0b988d39
DE
1127 return reg;
1128}
1129
1130static void
1131print_vi01 (info, insn, value)
1132 disassemble_info *info;
f31e2072 1133 TXVU_INSN *insn;
0b988d39
DE
1134 long value;
1135{
eb7168e5 1136 (*info->fprintf_func) (info->stream, "vi01");
0b988d39
DE
1137}
1138\f
eb7168e5 1139/* Lower instruction 12 bit unsigned immediate. */
0b988d39 1140
f31e2072 1141static void
eb7168e5 1142insert_luimm12 (insn, operand, mods, value, errmsg)
f31e2072 1143 TXVU_INSN *insn;
0b988d39
DE
1144 const struct txvu_operand *operand;
1145 int mods;
1146 long value;
1147 const char **errmsg;
1148{
f31e2072 1149 *insn |= VLUIMM12TOP ((value & (1 << 11)) != 0) | VLIMM11 (value);
0b988d39
DE
1150}
1151
1152static long
eb7168e5 1153extract_luimm12 (insn, operand, mods, pinvalid)
f31e2072 1154 TXVU_INSN *insn;
0b988d39
DE
1155 const struct txvu_operand *operand;
1156 int mods;
1157 int *pinvalid;
1158{
f31e2072 1159 return (((*insn & MLUIMM12TOP) != 0) << 11) | VLIMM11 (*insn);
0b988d39 1160}
42e65676
DE
1161
1162/* Lower instruction 12 bit unsigned immediate, upper 6 bits. */
1163
f31e2072 1164static void
42e65676 1165insert_luimm12up6 (insn, operand, mods, value, errmsg)
f31e2072 1166 TXVU_INSN *insn;
42e65676
DE
1167 const struct txvu_operand *operand;
1168 int mods;
1169 long value;
1170 const char **errmsg;
1171{
f31e2072 1172 *insn |= VLUIMM12TOP ((value & (1 << 11)) != 0) | (value & 0x7c0);
42e65676 1173}
8ea2f96f
DE
1174\f
1175/* Lower instruction 15 bit unsigned immediate. */
1176
f31e2072 1177static void
8ea2f96f 1178insert_luimm15 (insn, operand, mods, value, errmsg)
f31e2072 1179 TXVU_INSN *insn;
8ea2f96f
DE
1180 const struct txvu_operand *operand;
1181 int mods;
1182 long value;
1183 const char **errmsg;
1184{
f31e2072 1185 *insn |= VLUIMM15TOP (value >> 11) | VLIMM11 (value);
8ea2f96f
DE
1186}
1187
1188static long
1189extract_luimm15 (insn, operand, mods, pinvalid)
f31e2072 1190 TXVU_INSN *insn;
8ea2f96f
DE
1191 const struct txvu_operand *operand;
1192 int mods;
1193 int *pinvalid;
1194{
f31e2072 1195 return (((*insn & MLUIMM15TOP) >> 21) << 11) | VLIMM11 (*insn);
8ea2f96f 1196}
b5d20cf6
DE
1197\f
1198/* PKE support. */
1199
1200PARSE_FN (pke_ibit);
1201PRINT_FN (pke_ibit);
1202
1203PARSE_FN (pke_mode);
1204PRINT_FN (pke_mode);
1205
1206PARSE_FN (pke_ability);
1207PRINT_FN (pke_ability);
1208
1209PARSE_FN (pke_mpgaddr);
1210
1211PARSE_FN (pke_varlendata);
1212
1213PARSE_FN (pke_imrbits);
1214PRINT_FN (pke_imrbits);
1215
1216PARSE_FN (pke_unpacktype);
1217PRINT_FN (pke_unpacktype);
1218
1219PARSE_FN (pke_unpackaddr);
1220
f31e2072 1221const struct txvu_operand pke_operands[] =
b5d20cf6
DE
1222{
1223 /* place holder (??? not sure if needed) */
1224#define PKE_UNUSED 128
1225 { 0 },
1226
1227 /* The I bit. */
1228#define PKE_IBIT (PKE_UNUSED + 1)
1229 { 1, 31, TXVU_OPERAND_SUFFIX, parse_pke_ibit, 0, 0, print_pke_ibit },
1230
1231 /* An 8 bit unsigned immediate, stored in upper 8 bits of immed field. */
1232#define PKE_UIMM8UP (PKE_IBIT + 1)
1233 { 8, 8, 0, 0, 0, 0, 0 },
1234
1235 /* An 8 bit unsigned immediate, stored in lower 8 bits of immed field. */
1236#define PKE_UIMM8LO (PKE_UIMM8UP + 1)
1237 { 8, 0, 0, 0, 0, 0, 0 },
1238
1239 /* An 16 bit unsigned immediate, stored in lower 8 bits of immed field. */
1240#define PKE_UIMM16 (PKE_UIMM8LO + 1)
1241 { 16, 0, 0, 0, 0, 0, 0 },
1242
1243 /* The mode operand of `stmod'. */
1244#define PKE_MODE (PKE_UIMM16 + 1)
1245 { 2, 0, 0, parse_pke_mode, 0, 0, print_pke_mode },
1246
1247 /* The ability operand of `mskpath3'. */
1248#define PKE_ABILITY (PKE_MODE + 1)
1249 { 1, 15, 0, parse_pke_ability, 0, 0, print_pke_ability },
1250
1251 /* A VU address. */
1252#define PKE_VUADDR (PKE_ABILITY + 1)
1253 { 16, 0, 0, 0, 0, 0, 0 },
1254
1255 /* A 32 bit immediate, appearing in 2nd,3rd,4th,5th words. */
1256#define PKE_UIMM32 (PKE_VUADDR + 1)
1257 { 32, 0, 0, 0, 0, 0, 0 },
1258
1259 /* VU address used by mpg insn. */
1260#define PKE_MPGADDR (PKE_UIMM32 + 1)
1261 { 16, 0, TXVU_OPERAND_ADDRESS, parse_pke_mpgaddr, 0, 0, 0 },
1262
1263 /* A variable length data specifier.
1264 Any of: file name, number, or '*'. */
1265#define PKE_VARLENDATA (PKE_MPGADDR + 1)
1266 { 0, 0, 0, parse_pke_varlendata, 0, 0, 0 },
1267
1268 /* The IMR bits of the unpack insn. */
1269#define PKE_IMRBITS (PKE_VARLENDATA + 1)
1270 { 0, 0, 0, parse_pke_imrbits, 0, 0, print_pke_imrbits },
1271
1272 /* The type of the unpack insn. */
1273#define PKE_UNPACKTYPE (PKE_IMRBITS + 1)
1274 { 4, 24, 0, parse_pke_unpacktype, 0, 0, print_pke_unpacktype },
1275
1276 /* VU address used by unpack insn. */
1277#define PKE_UNPACKADDR (PKE_UIMM32 + 1)
1278 { 16, 0, TXVU_OPERAND_ADDRESS, parse_pke_unpackaddr, 0, 0, 0 },
1279
1280/* end of list place holder */
1281 { 0 }
1282};
1283
1284/* Field mask values. */
1285#define MPKECMD 0x7f000000
1286#define MPKEUNPACK 0x60000000
1287
1288/* Field values. */
1289#define VPKECMD(x) V ((x), 7, 24)
1290#define VPKEUNPACK V (0x60, 8, 24)
1291
f31e2072 1292struct txvu_opcode pke_opcodes[] =
b5d20cf6
DE
1293{
1294 { "pkenop", { PKE_IBIT }, 0x7fffffff, 0 },
1295 { "stcycle", { PKE_IBIT, SP, PKE_UIMM8UP, C, PKE_UIMM8LO }, MPKECMD, VPKECMD (1) },
1296 { "offset", { PKE_IBIT, SP, PKE_UIMM16 }, MPKECMD, VPKECMD (2) },
1297 { "base", { PKE_IBIT, SP, PKE_UIMM16 }, MPKECMD, VPKECMD (3) },
1298 { "itop", { PKE_IBIT, SP, PKE_UIMM16 }, MPKECMD, VPKECMD (4) },
1299 { "stmod", { PKE_IBIT, SP, PKE_MODE }, MPKECMD + V (~0, 14, 2), VPKECMD (5) },
1300 { "mskpath3", { PKE_IBIT, SP, PKE_ABILITY }, MPKECMD + V (~0, 15, 0), VPKECMD (6) },
1301 { "pkemark", { PKE_IBIT, SP, PKE_UIMM16 }, MPKECMD, VPKECMD (7) },
1302 { "flushe", { PKE_IBIT }, MPKECMD, VPKECMD (16) },
1303 { "flush", { PKE_IBIT }, MPKECMD, VPKECMD (17) },
1304 { "flusha", { PKE_IBIT }, MPKECMD, VPKECMD (19) },
1305 { "pkemscal", { PKE_IBIT, SP, PKE_VUADDR }, MPKECMD, VPKECMD (20) },
1306 { "pkemscnt", { PKE_IBIT }, MPKECMD, VPKECMD (23) },
1307 { "pkemscalf", { PKE_IBIT, SP, PKE_VUADDR }, MPKECMD, VPKECMD (21) },
1308
1309 /* 2 word instructions */
1310 { "stmask", { PKE_IBIT, SP, PKE_UIMM32 }, MPKECMD, VPKECMD (32), PKE_OPCODE_LEN2 },
1311
1312 /* 5 word instructions */
1313 { "strow", { PKE_IBIT, SP, PKE_UIMM32, PKE_UIMM32, PKE_UIMM32, PKE_UIMM32 }, MPKECMD, VPKECMD (48), PKE_OPCODE_LEN5 },
1314 { "stcol", { PKE_IBIT, SP, PKE_UIMM32, PKE_UIMM32, PKE_UIMM32, PKE_UIMM32 }, MPKECMD, VPKECMD (49), PKE_OPCODE_LEN5 },
1315
1316 /* variable length instructions */
1317 { "mpg", { PKE_IBIT, SP, PKE_MPGADDR, PKE_VARLENDATA }, MPKECMD, VPKECMD (0x4a), PKE_OPCODE_LENVAR + PKE_OPCODE_MPG },
1318 { "direct", { PKE_IBIT, SP, PKE_VARLENDATA }, MPKECMD, VPKECMD (0x50), PKE_OPCODE_LENVAR + PKE_OPCODE_DIRECT },
1319 { "directhl", { PKE_IBIT, SP, PKE_VARLENDATA }, MPKECMD, VPKECMD (0x51), PKE_OPCODE_LENVAR + PKE_OPCODE_DIRECT },
1320 { "unpack", { PKE_IMRBITS, SP, PKE_UNPACKTYPE, C, PKE_UNPACKADDR, C, PKE_VARLENDATA }, MPKEUNPACK, VPKEUNPACK, PKE_OPCODE_LENVAR + PKE_OPCODE_UNPACK },
1321};
f31e2072 1322const int pke_opcodes_count = sizeof (pke_opcodes) / sizeof (pke_opcodes[0]);
b5d20cf6
DE
1323\f
1324/* PKE parse,insert,extract,print helper fns. */
1325
1326static long
1327parse_pke_ibit (pstr, errmsg)
1328 char **pstr;
1329 const char **errmsg;
1330{
1331}
1332
1333static void
1334print_pke_ibit (info, insn, value)
1335 disassemble_info *info;
f31e2072 1336 TXVU_INSN *insn;
b5d20cf6
DE
1337 long value;
1338{
1339 (*info->fprintf_func) (info->stream, "???");
1340}
1341
1342static long
1343parse_pke_mode (pstr, errmsg)
1344 char **pstr;
1345 const char **errmsg;
1346{
1347}
1348
1349static void
1350print_pke_mode (info, insn, value)
1351 disassemble_info *info;
f31e2072 1352 TXVU_INSN *insn;
b5d20cf6
DE
1353 long value;
1354{
1355 (*info->fprintf_func) (info->stream, "???");
1356}
1357
1358static long
1359parse_pke_ability (pstr, errmsg)
1360 char **pstr;
1361 const char **errmsg;
1362{
1363}
1364
1365static void
1366print_pke_ability (info, insn, value)
1367 disassemble_info *info;
f31e2072 1368 TXVU_INSN *insn;
b5d20cf6
DE
1369 long value;
1370{
1371 (*info->fprintf_func) (info->stream, "???");
1372}
1373
1374static long
1375parse_pke_mpgaddr (pstr, errmsg)
1376 char **pstr;
1377 const char **errmsg;
1378{
1379}
1380
1381static long
1382parse_pke_varlendata (pstr, errmsg)
1383 char **pstr;
1384 const char **errmsg;
1385{
1386 /* The result here is either the length specified,
1387 or PKE_VARLENDATA_FILE or PKE_VARLENDATA_UNKNOWN. */
1388}
1389
1390static long
1391parse_pke_imrbits (pstr, errmsg)
1392 char **pstr;
1393 const char **errmsg;
1394{
1395}
1396
1397static void
1398print_pke_imrbits (info, insn, value)
1399 disassemble_info *info;
f31e2072 1400 TXVU_INSN *insn;
b5d20cf6
DE
1401 long value;
1402{
1403 (*info->fprintf_func) (info->stream, "???");
1404}
1405
1406static long
1407parse_pke_unpacktype (pstr, errmsg)
1408 char **pstr;
1409 const char **errmsg;
1410{
1411}
1412
1413static void
1414print_pke_unpacktype (info, insn, value)
1415 disassemble_info *info;
f31e2072 1416 TXVU_INSN *insn;
b5d20cf6
DE
1417 long value;
1418{
1419 (*info->fprintf_func) (info->stream, "???");
1420}
1421
1422static long
1423parse_pke_unpackaddr (pstr, errmsg)
1424 char **pstr;
1425 const char **errmsg;
1426{
1427}
1428\f
1429/* DMA support. */
1430
1431PARSE_FN (dma_flags);
1432INSERT_FN (dma_flags);
1433EXTRACT_FN (dma_flags);
1434PRINT_FN (dma_flags);
1435
1436PARSE_FN (dma_data);
1437INSERT_FN (dma_data);
1438EXTRACT_FN (dma_data);
1439PRINT_FN (dma_data);
1440
1441PARSE_FN (dma_next);
1442INSERT_FN (dma_next);
1443EXTRACT_FN (dma_next);
1444PRINT_FN (dma_next);
1445
f31e2072 1446const struct txvu_operand dma_operands[] =
b5d20cf6
DE
1447{
1448 /* place holder (??? not sure if needed) */
1449#define DMA_UNUSED 128
1450 { 0 },
1451
1452 /* dma tag flag bits */
1453#define DMA_FLAGS (DMA_UNUSED + 1)
1454 { 0, 0, TXVU_OPERAND_SUFFIX,
1455 parse_dma_flags, insert_dma_flags, extract_dma_flags, print_dma_flags },
1456
1457 /* dma tag flag bits */
1458#define DMA_DATA (DMA_FLAGS + 1)
1459 { 0, 0, 0,
1460 parse_dma_data, insert_dma_data, extract_dma_data, print_dma_data },
1461
1462 /* dma tag flag bits */
1463#define DMA_NEXT (DMA_DATA + 1)
1464 { 0, 0, 0,
1465 parse_dma_next, insert_dma_next, extract_dma_next, print_dma_next },
1466
1467/* end of list place holder */
1468 { 0 }
1469};
1470
f31e2072 1471struct txvu_opcode dma_opcodes[] =
b5d20cf6
DE
1472{
1473 { "dmacnt", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 1 },
1474 { "dmanext", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 2 },
1475 { "dmaref", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 3 },
1476 { "dmarefs", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 4 },
1477 { "dmacall", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 5 },
1478 { "dmareg", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 6 },
1479 { "dmaend", { DMA_FLAGS, SP, DMA_DATA, C, DMA_NEXT }, 0, 7 }
1480};
f31e2072 1481const int dma_opcodes_count = sizeof (dma_opcodes) / sizeof (dma_opcodes[0]);
b5d20cf6
DE
1482\f
1483/* DMA parse,insert,extract,print helper fns. */
1484
1485static long
1486parse_dma_flags (pstr, errmsg)
1487 char **pstr;
1488 const char **errmsg;
1489{
f31e2072
DE
1490 char *str = *pstr;
1491 int flags = 0;
1492
1493 if (*str != '[')
1494 return 0;
1495
1496 for (str = str + 1; *str != ']'; ++str)
1497 {
1498 switch (tolower (*str))
1499 {
1500 case '0' : flags |= DMA_FLAG_PCE0; break;
1501 case '1' : flags |= DMA_FLAG_PCE1; break;
1502 case 'i' : flags |= DMA_FLAG_INT; break;
1503 case 's' : flags |= DMA_FLAG_SPR; break;
1504 default : *errmsg = "unknown dma flag"; return 0;
1505 }
1506 }
1507
1508 *errmsg = NULL;
1509 *pstr = str + 1;
1510 return flags;
b5d20cf6
DE
1511}
1512
f31e2072 1513static void
b5d20cf6 1514insert_dma_flags (insn, operand, mods, value, errmsg)
f31e2072 1515 TXVU_INSN *insn;
b5d20cf6
DE
1516 const struct txvu_operand *operand;
1517 int mods;
1518 long value;
1519 const char **errmsg;
1520{
b5d20cf6
DE
1521}
1522
1523static long
1524extract_dma_flags (insn, operand, mods, pinvalid)
f31e2072 1525 TXVU_INSN *insn;
b5d20cf6
DE
1526 const struct txvu_operand *operand;
1527 int mods;
1528 int *pinvalid;
1529{
1530 return 0;
1531}
1532
1533static void
1534print_dma_flags (info, insn, value)
1535 disassemble_info *info;
f31e2072 1536 TXVU_INSN *insn;
b5d20cf6
DE
1537 long value;
1538{
f31e2072
DE
1539 if (value)
1540 {
1541 (*info->fprintf_func) (info->stream, "[");
1542 if (value & DMA_FLAG_PCE0)
1543 (*info->fprintf_func) (info->stream, "0");
1544 if (value & DMA_FLAG_PCE1)
1545 (*info->fprintf_func) (info->stream, "1");
1546 if (value & DMA_FLAG_INT)
1547 (*info->fprintf_func) (info->stream, "i");
1548 if (value & DMA_FLAG_SPR)
1549 (*info->fprintf_func) (info->stream, "s");
1550 (*info->fprintf_func) (info->stream, "]");
1551 }
b5d20cf6
DE
1552}
1553
1554static long
1555parse_dma_data (pstr, errmsg)
1556 char **pstr;
1557 const char **errmsg;
1558{
1559}
1560
f31e2072 1561static void
b5d20cf6 1562insert_dma_data (insn, operand, mods, value, errmsg)
f31e2072 1563 TXVU_INSN *insn;
b5d20cf6
DE
1564 const struct txvu_operand *operand;
1565 int mods;
1566 long value;
1567 const char **errmsg;
1568{
b5d20cf6
DE
1569}
1570
1571static long
1572extract_dma_data (insn, operand, mods, pinvalid)
f31e2072 1573 TXVU_INSN *insn;
b5d20cf6
DE
1574 const struct txvu_operand *operand;
1575 int mods;
1576 int *pinvalid;
1577{
1578 return 0;
1579}
1580
1581static void
1582print_dma_data (info, insn, value)
1583 disassemble_info *info;
f31e2072 1584 TXVU_INSN *insn;
b5d20cf6
DE
1585 long value;
1586{
1587 (*info->fprintf_func) (info->stream, "???");
1588}
1589
1590static long
1591parse_dma_next (pstr, errmsg)
1592 char **pstr;
1593 const char **errmsg;
1594{
1595}
1596
f31e2072 1597static void
b5d20cf6 1598insert_dma_next (insn, operand, mods, value, errmsg)
f31e2072 1599 TXVU_INSN *insn;
b5d20cf6
DE
1600 const struct txvu_operand *operand;
1601 int mods;
1602 long value;
1603 const char **errmsg;
1604{
b5d20cf6
DE
1605}
1606
1607static long
1608extract_dma_next (insn, operand, mods, pinvalid)
f31e2072 1609 TXVU_INSN *insn;
b5d20cf6
DE
1610 const struct txvu_operand *operand;
1611 int mods;
1612 int *pinvalid;
1613{
1614 return 0;
1615}
1616
1617static void
1618print_dma_next (info, insn, value)
1619 disassemble_info *info;
f31e2072 1620 TXVU_INSN *insn;
b5d20cf6
DE
1621 long value;
1622{
1623 (*info->fprintf_func) (info->stream, "???");
1624}
1625\f
1626/* GPUIF support. */
1627
1628PARSE_FN (gpuif_prim);
1629INSERT_FN (gpuif_prim);
1630EXTRACT_FN (gpuif_prim);
1631PRINT_FN (gpuif_prim);
1632
1633PARSE_FN (gpuif_regs);
1634INSERT_FN (gpuif_regs);
1635EXTRACT_FN (gpuif_regs);
1636PRINT_FN (gpuif_regs);
1637
1638PARSE_FN (gpuif_nloop);
1639INSERT_FN (gpuif_nloop);
1640EXTRACT_FN (gpuif_nloop);
1641PRINT_FN (gpuif_nloop);
1642
1643PARSE_FN (gpuif_eop);
1644INSERT_FN (gpuif_eop);
1645EXTRACT_FN (gpuif_eop);
1646PRINT_FN (gpuif_eop);
1647
f31e2072 1648const struct txvu_operand gpuif_operands[] =
b5d20cf6
DE
1649{
1650 /* place holder (??? not sure if needed) */
1651#define GPUIF_UNUSED 128
1652 { 0 },
1653
1654 /* PRIM=foo operand */
1655#define GPUIF_PRIM (GPUIF_UNUSED + 1)
1656 { 0, 0, 0, parse_gpuif_prim, insert_gpuif_prim, extract_gpuif_prim, print_gpuif_prim },
1657
1658 /* REGS=foo operand */
1659#define GPUIF_REGS (GPUIF_PRIM + 1)
1660 { 0, 0, 0, parse_gpuif_regs, insert_gpuif_regs, extract_gpuif_regs, print_gpuif_regs },
1661
1662 /* NLOOP=foo operand */
1663#define GPUIF_NLOOP (GPUIF_REGS + 1)
1664 { 0, 0, 0, parse_gpuif_nloop, insert_gpuif_nloop, extract_gpuif_nloop, print_gpuif_nloop },
1665
1666 /* EOP operand */
1667#define GPUIF_EOP (GPUIF_NLOOP + 1)
1668 { 0, 0, 0, parse_gpuif_eop, insert_gpuif_eop, extract_gpuif_eop, print_gpuif_eop },
1669
1670/* end of list place holder */
1671 { 0 }
1672};
1673
f31e2072 1674struct txvu_opcode gpuif_opcodes[] =
b5d20cf6
DE
1675{
1676 { "gpuifpacked", { SP, GPUIF_PRIM, C, GPUIF_REGS, C, GPUIF_NLOOP, C, GPUIF_EOP }, 0, 1 },
1677 { "gpuifreglist", { SP, GPUIF_REGS, C, GPUIF_NLOOP, C, GPUIF_EOP }, 0, 2 },
1678 { "gpuifimage", { SP, GPUIF_NLOOP }, 0, 3 },
1679};
f31e2072 1680const int gpuif_opcodes_count = sizeof (gpuif_opcodes) / sizeof (gpuif_opcodes[0]);
b5d20cf6
DE
1681\f
1682/* GPUIF parse,insert,extract,print helper fns. */
1683
1684static long
1685parse_gpuif_prim (pstr, errmsg)
1686 char **pstr;
1687 const char **errmsg;
1688{
1689}
1690
f31e2072 1691static void
b5d20cf6 1692insert_gpuif_prim (insn, operand, mods, value, errmsg)
f31e2072 1693 TXVU_INSN *insn;
b5d20cf6
DE
1694 const struct txvu_operand *operand;
1695 int mods;
1696 long value;
1697 const char **errmsg;
1698{
b5d20cf6
DE
1699}
1700
1701static long
1702extract_gpuif_prim (insn, operand, mods, pinvalid)
f31e2072 1703 TXVU_INSN *insn;
b5d20cf6
DE
1704 const struct txvu_operand *operand;
1705 int mods;
1706 int *pinvalid;
1707{
1708 return 0;
1709}
1710
1711static void
1712print_gpuif_prim (info, insn, value)
1713 disassemble_info *info;
f31e2072 1714 TXVU_INSN *insn;
b5d20cf6
DE
1715 long value;
1716{
1717 (*info->fprintf_func) (info->stream, "???");
1718}
1719
1720static long
1721parse_gpuif_regs (pstr, errmsg)
1722 char **pstr;
1723 const char **errmsg;
1724{
1725}
1726
f31e2072 1727static void
b5d20cf6 1728insert_gpuif_regs (insn, operand, mods, value, errmsg)
f31e2072 1729 TXVU_INSN *insn;
b5d20cf6
DE
1730 const struct txvu_operand *operand;
1731 int mods;
1732 long value;
1733 const char **errmsg;
1734{
b5d20cf6
DE
1735}
1736
1737static long
1738extract_gpuif_regs (insn, operand, mods, pinvalid)
f31e2072 1739 TXVU_INSN *insn;
b5d20cf6
DE
1740 const struct txvu_operand *operand;
1741 int mods;
1742 int *pinvalid;
1743{
1744 return 0;
1745}
1746
1747static void
1748print_gpuif_regs (info, insn, value)
1749 disassemble_info *info;
f31e2072 1750 TXVU_INSN *insn;
b5d20cf6
DE
1751 long value;
1752{
1753 (*info->fprintf_func) (info->stream, "???");
1754}
1755
1756static long
1757parse_gpuif_nloop (pstr, errmsg)
1758 char **pstr;
1759 const char **errmsg;
1760{
1761}
1762
f31e2072 1763static void
b5d20cf6 1764insert_gpuif_nloop (insn, operand, mods, value, errmsg)
f31e2072 1765 TXVU_INSN *insn;
b5d20cf6
DE
1766 const struct txvu_operand *operand;
1767 int mods;
1768 long value;
1769 const char **errmsg;
1770{
b5d20cf6
DE
1771}
1772
1773static long
1774extract_gpuif_nloop (insn, operand, mods, pinvalid)
f31e2072 1775 TXVU_INSN *insn;
b5d20cf6
DE
1776 const struct txvu_operand *operand;
1777 int mods;
1778 int *pinvalid;
1779{
1780 return 0;
1781}
1782
1783static void
1784print_gpuif_nloop (info, insn, value)
1785 disassemble_info *info;
f31e2072 1786 TXVU_INSN *insn;
b5d20cf6
DE
1787 long value;
1788{
1789 (*info->fprintf_func) (info->stream, "???");
1790}
1791
1792static long
1793parse_gpuif_eop (pstr, errmsg)
1794 char **pstr;
1795 const char **errmsg;
1796{
1797}
1798
f31e2072 1799static void
b5d20cf6 1800insert_gpuif_eop (insn, operand, mods, value, errmsg)
f31e2072 1801 TXVU_INSN *insn;
b5d20cf6
DE
1802 const struct txvu_operand *operand;
1803 int mods;
1804 long value;
1805 const char **errmsg;
1806{
b5d20cf6
DE
1807}
1808
1809static long
1810extract_gpuif_eop (insn, operand, mods, pinvalid)
f31e2072 1811 TXVU_INSN *insn;
b5d20cf6
DE
1812 const struct txvu_operand *operand;
1813 int mods;
1814 int *pinvalid;
1815{
1816 return 0;
1817}
1818
1819static void
1820print_gpuif_eop (info, insn, value)
1821 disassemble_info *info;
f31e2072 1822 TXVU_INSN *insn;
b5d20cf6
DE
1823 long value;
1824{
1825 (*info->fprintf_func) (info->stream, "???");
1826}
f31e2072
DE
1827\f
1828/* Init fns.
1829 These are called before doing each of the respective activities. */
1830
1831/* Called by the assembler before parsing an instruction. */
1832
1833void
1834txvu_opcode_init_parse ()
1835{
1836 mnemonic_dest = -1;
1837 mnemonic_bc = -1;
1838}
1839
1840/* Called by the disassembler before printing an instruction. */
1841
1842void
1843txvu_opcode_init_print ()
1844{
1845 mnemonic_dest = -1;
1846 mnemonic_bc = -1;
1847}
1848\f
1849/* Indexed by first letter of opcode. Points to chain of opcodes with same
1850 first letter. */
1851/* ??? One can certainly use a better hash. Later. */
1852static struct txvu_opcode *upper_opcode_map[26 + 1];
1853static struct txvu_opcode *lower_opcode_map[26 + 1];
1854
1855/* Indexed by insn code. Points to chain of opcodes with same insn code. */
1856static struct txvu_opcode *upper_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1];
1857static struct txvu_opcode *lower_icode_map[(1 << TXVU_ICODE_HASH_SIZE) - 1];
1858\f
1859/* Initialize any tables that need it.
1860 Must be called once at start up (or when first needed).
1861
1862 FLAGS is currently unused but is intended to control initialization. */
1863
1864void
1865txvu_opcode_init_tables (flags)
1866 int flags;
1867{
1868 static int init_p = 0;
1869
1870 /* We may be intentionally called more than once (for example gdb will call
1871 us each time the user switches cpu). These tables only need to be init'd
1872 once though. */
1873 /* ??? We can remove the need for txvu_opcode_supported by taking it into
1874 account here, but I'm not sure I want to do that yet (if ever). */
1875 if (!init_p)
1876 {
1877 int i,n;
1878
1879 /* Upper VU table. */
1880
1881 memset (upper_opcode_map, 0, sizeof (upper_opcode_map));
1882 memset (upper_icode_map, 0, sizeof (upper_icode_map));
1883 /* Scan the table backwards so macros appear at the front. */
1884 for (i = txvu_upper_opcodes_count - 1; i >= 0; --i)
1885 {
1886 int opcode_hash = TXVU_HASH_UPPER_OPCODE (txvu_upper_opcodes[i].mnemonic);
1887 int icode_hash = TXVU_HASH_UPPER_ICODE (txvu_upper_opcodes[i].value);
1888
1889 txvu_upper_opcodes[i].next_asm = upper_opcode_map[opcode_hash];
1890 upper_opcode_map[opcode_hash] = &txvu_upper_opcodes[i];
1891
1892 txvu_upper_opcodes[i].next_dis = upper_icode_map[icode_hash];
1893 upper_icode_map[icode_hash] = &txvu_upper_opcodes[i];
1894 }
1895
1896 /* Lower VU table. */
1897
1898 memset (lower_opcode_map, 0, sizeof (lower_opcode_map));
1899 memset (lower_icode_map, 0, sizeof (lower_icode_map));
1900 /* Scan the table backwards so macros appear at the front. */
1901 for (i = txvu_lower_opcodes_count - 1; i >= 0; --i)
1902 {
1903 int opcode_hash = TXVU_HASH_LOWER_OPCODE (txvu_lower_opcodes[i].mnemonic);
1904 int icode_hash = TXVU_HASH_LOWER_ICODE (txvu_lower_opcodes[i].value);
1905
1906 txvu_lower_opcodes[i].next_asm = lower_opcode_map[opcode_hash];
1907 lower_opcode_map[opcode_hash] = &txvu_lower_opcodes[i];
1908
1909 txvu_lower_opcodes[i].next_dis = lower_icode_map[icode_hash];
1910 lower_icode_map[icode_hash] = &txvu_lower_opcodes[i];
1911 }
1912
1913 /* PKE table. */
1914
1915 for (i = pke_opcodes_count - 2; i >= 0; --i)
1916 {
1917 pke_opcodes[i].next_asm = & pke_opcodes[i+1];
1918 pke_opcodes[i].next_dis = & pke_opcodes[i+1];
1919 }
1920
1921 /* DMA table. */
1922
1923 for (i = dma_opcodes_count - 2; i >= 0; --i)
1924 {
1925 dma_opcodes[i].next_asm = & dma_opcodes[i+1];
1926 dma_opcodes[i].next_dis = & dma_opcodes[i+1];
1927 }
1928
1929 /* GPUIF table. */
1930
1931 for (i = gpuif_opcodes_count - 2; i >= 0; --i)
1932 {
1933 gpuif_opcodes[i].next_asm = & gpuif_opcodes[i+1];
1934 gpuif_opcodes[i].next_dis = & gpuif_opcodes[i+1];
1935 }
1936
1937 init_p = 1;
1938 }
1939}
1940
1941/* Return the first insn in the chain for assembling upper INSN. */
1942
1943const struct txvu_opcode *
1944txvu_upper_opcode_lookup_asm (insn)
1945 const char *insn;
1946{
1947 return upper_opcode_map[TXVU_HASH_UPPER_OPCODE (insn)];
1948}
1949
1950/* Return the first insn in the chain for disassembling upper INSN. */
1951
1952const struct txvu_opcode *
1953txvu_upper_opcode_lookup_dis (insn)
1954 TXVU_INSN insn;
1955{
1956 return upper_icode_map[TXVU_HASH_UPPER_ICODE (insn)];
1957}
1958
1959/* Return the first insn in the chain for assembling lower INSN. */
1960
1961const struct txvu_opcode *
1962txvu_lower_opcode_lookup_asm (insn)
1963 const char *insn;
1964{
1965 return lower_opcode_map[TXVU_HASH_LOWER_OPCODE (insn)];
1966}
1967
1968/* Return the first insn in the chain for disassembling lower INSN. */
1969
1970const struct txvu_opcode *
1971txvu_lower_opcode_lookup_dis (insn)
1972 TXVU_INSN insn;
1973{
1974 return lower_icode_map[TXVU_HASH_LOWER_ICODE (insn)];
1975}
1976
1977/* Return the first insn in the chain for assembling lower INSN. */
1978
1979const struct txvu_opcode *
1980pke_opcode_lookup_asm (insn)
1981 const char *insn;
1982{
1983 return &pke_opcodes[0];
1984}
1985
1986/* Return the first insn in the chain for disassembling lower INSN. */
1987
1988const struct txvu_opcode *
1989pke_opcode_lookup_dis (insn)
1990 TXVU_INSN insn;
1991{
1992 return &pke_opcodes[0];
1993}
1994
1995/* Return the first insn in the chain for assembling lower INSN. */
1996
1997const struct txvu_opcode *
1998dma_opcode_lookup_asm (insn)
1999 const char *insn;
2000{
2001 return &dma_opcodes[0];
2002}
2003
2004/* Return the first insn in the chain for disassembling lower INSN. */
2005
2006const struct txvu_opcode *
2007dma_opcode_lookup_dis (insn)
2008 TXVU_INSN insn;
2009{
2010 return &dma_opcodes[0];
2011}
2012
2013/* Return the first insn in the chain for assembling lower INSN. */
2014
2015const struct txvu_opcode *
2016gpuif_opcode_lookup_asm (insn)
2017 const char *insn;
2018{
2019 return &gpuif_opcodes[0];
2020}
2021
2022/* Return the first insn in the chain for disassembling lower INSN. */
2023
2024const struct txvu_opcode *
2025gpuif_opcode_lookup_dis (insn)
2026 TXVU_INSN insn;
2027{
2028 return &gpuif_opcodes[0];
2029}
This page took 0.114141 seconds and 4 git commands to generate.