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