replaced call to CGEN_INSN_SYNTAX()->mnemonic with CGEN_INSN_MNEMONIC()
[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) \
41static TXVU_INSN CONCAT2 (insert_,fn) \
42 PARAMS ((TXVU_INSN, const struct txvu_operand *, \
43 int, long, const char **))
44#define EXTRACT_FN(fn) \
45static long CONCAT2 (extract_,fn) \
46 PARAMS ((TXVU_INSN, const struct txvu_operand *, \
47 int, int *))
48#define PRINT_FN(fn) \
49static void CONCAT2 (print_,fn) \
50 PARAMS ((disassemble_info *, TXVU_INSN, long));
51
52PARSE_FN (dotdest);
71af45ec
DE
53INSERT_FN (dotdest);
54EXTRACT_FN (dotdest);
54cc8ed4
DE
55PRINT_FN (dotdest);
56
71af45ec
DE
57PARSE_FN (vfreg);
58PRINT_FN (vfreg);
54cc8ed4 59
3f897263
DE
60PARSE_FN (bc);
61PRINT_FN (bc);
62
63PARSE_FN (ftregbc);
64PRINT_FN (ftregbc);
65
66PARSE_FN (accdest);
67PRINT_FN (accdest);
68
69PARSE_FN (xyz);
70
71/* Various types of TXVU operands, including insn suffixes.
54cc8ed4
DE
72
73 Fields are:
74
75 BITS SHIFT FLAGS PARSE_FN INSERT_FN EXTRACT_FN PRINT_FN
76
77 Operand values are 128 + table index. This allows ASCII chars to be
78 included in the syntax spec. */
79
80const struct txvu_operand txvu_operands[] =
81{
3f897263 82 /* place holder (??? not sure if needed) */
54cc8ed4
DE
83#define UNUSED 128
84 { 0 },
85
3f897263 86 /* Destination indicator, with leading '.'. */
54cc8ed4
DE
87#define DOTDEST (UNUSED + 1)
88 { 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX,
71af45ec 89 parse_dotdest, insert_dotdest, extract_dotdest, print_dotdest },
54cc8ed4 90
3f897263 91 /* ft reg */
54cc8ed4 92#define FTREG (DOTDEST + 1)
71af45ec 93 { 5, TXVU_SHIFT_FTREG, 0, parse_vfreg, 0, 0, print_vfreg },
54cc8ed4 94
3f897263 95 /* fs reg */
54cc8ed4 96#define FSREG (FTREG + 1)
71af45ec 97 { 5, TXVU_SHIFT_FSREG, 0, parse_vfreg, 0, 0, print_vfreg },
54cc8ed4 98
3f897263 99 /* fd reg */
54cc8ed4 100#define FDREG (FSREG + 1)
71af45ec 101 { 5, TXVU_SHIFT_FDREG, 0, parse_vfreg, 0, 0, print_vfreg },
54cc8ed4 102
3f897263
DE
103 /* broadcast */
104#define BC (FDREG + 1)
105 { 2, 0, 0, parse_bc, 0, 0, print_bc },
106
107 /* ftreg in broadcast case */
108#define FTREGBC (BC + 1)
109 { 5, TXVU_SHIFT_FTREG, 0, parse_ftregbc, 0, 0, print_ftregbc },
110
111 /* accumulator dest */
112#define ACCDEST (FTREGBC + 1)
113 { 0, 0, TXVU_OPERAND_FAKE, parse_accdest, 0, 0, print_accdest },
114
115 /* The XYZ operand is a fake one that is used to ensure only "xyz" is
116 specified. It simplifies the opmula and opmsub entries. */
117#define XYZ (FDREG + 1)
118 { 0, 0, TXVU_OPERAND_FAKE, parse_xyz, 0, 0, 0 },
119
54cc8ed4
DE
120/* end of list place holder */
121 { 0 }
122};
123\f
124/* Macros to put a field's value into the right place. */
3f897263
DE
125/* FIXME: If assembler needs these, move to opcode/txvu.h. */
126
54cc8ed4
DE
127#define R(x,b,m) (((x) & (m)) << (b)) /* value X, mask M, at bit B */
128
3f897263
DE
129/* Upper Flag bits. */
130#define UF(x) R ((x), 27, 31)
131/* Upper REServed two bits next to flag bits. */
132#define URES(x) R ((x), 25, 3)
133/* The DEST field. */
134#define UDEST(x) R ((x), 21, 15)
135/* The FT reg field. */
136#define UFT(x) R ((x), TXVU_SHIFT_FTREG, TXVU_MASK_VFREG)
137/* The FS reg field. */
138#define UFS(x) R ((x), TXVU_SHIFT_FSREG, TXVU_MASK_VFREG)
139/* The FD reg field. */
140#define UFD(x) R ((x), TXVU_SHIFT_FDREG, TXVU_MASK_VFREG)
141/* The 4 bit opcode field. */
142#define UOP4(x) R ((x), 2, 15)
143/* The 6 bit opcode field. */
144#define UOP6(x) R ((x), 0, 63)
145/* The 9 bit opcode field. */
146#define UOP9(x) R ((x), 2, 0x1ff)
147/* The 11 bit opcode field. */
148#define UOP11(x) R ((x), 0, 0x7ff)
149/* The BroadCast field. */
150#define UBC(x) R ((x), 0, 3)
151
152/* Macros for special field values. */
153/* The upper 7 bits of the upper word. */
154#define UUBITS (UF (0) + URES (0))
155/* Mask for UBITS. */
156#define MUUBITS (UF (~0) + URES (~0))
157/* Mask for URES. */
158#define MURES URES (~0)
159/* Mask for OP4. */
160#define MUOP4 UOP4 (~0)
161/* Mask for OP6. */
162#define MUOP6 UOP6 (~0)
163/* Mask for OP9. */
164#define MUOP9 UOP9 (~0)
165/* Mask for OP11. */
166#define MUOP11 UOP11 (~0)
167
168/* A space, separates instruction name (mnemonic + mnemonic operands) from operands. */
169#define SP ' '
170
54cc8ed4
DE
171/* TXVU instructions.
172 [??? some of these comments are left over from the ARC port from which
173 this code is borrowed, delete in time]
174
175 Longer versions of insns must appear before shorter ones (if gas sees
176 "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
177 junk). This isn't necessary for `ld' because of the trailing ']'.
178
179 Instructions that are really macros based on other insns must appear
180 before the real insn so they're chosen when disassembling. Eg: The `mov'
181 insn is really the `and' insn.
182
183 This table is best viewed on a wide screen (161 columns). I'd prefer to
184 keep it this way. The rest of the file, however, should be viewable on an
185 80 column terminal. */
186
187/* ??? This table also includes macros: asl, lsl, and mov. The ppc port has
188 a more general facility for dealing with macros which could be used if
189 we need to. */
190
191/* These tables can't be `const' because members `next_asm' and `next_dis' are
192 computed at run-time. We could split this into two, as that would put the
193 constant stuff into a readonly section. */
194
195struct txvu_opcode txvu_upper_opcodes[] = {
196
197 /* Macros appear first. */
198 /* ??? Any aliases? */
199
3f897263
DE
200 /* The rest of these needn't be sorted, but it helps to find them if they are. */
201 { "abs", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x1fd) },
202 { "add", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x28) },
203 { "addi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x22) },
204 { "addq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x20) },
205 { "add", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + UOP4 (~0), UOP4 (0) },
206 { "adda", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2bc) },
207 { "addai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x23e) },
208 { "addaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x23c) },
209 { "adda", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0xf) },
210 { "clip", { DOTDEST, SP, FSREG }, MURES + UDEST (~0) + UFT (~0) + MUOP11, UDEST (0xf) + UOP11 (0x1ff) },
211 { "ftoi0", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x17c) },
212 { "ftoi4", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x17d) },
213 { "ftoi12", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x17e) },
214 { "ftoi15", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x17f) },
215 { "itof0", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x13c) },
216 { "itof4", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x13d) },
217 { "itof12", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x13e) },
218 { "itof15", { DOTDEST, SP, FTREG, FSREG }, MURES + MUOP11, UOP11 (0x13f) },
219 { "madd", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x29) },
220 { "maddi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x23) },
221 { "maddq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x21) },
222 { "madd", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + MUOP4, UOP4 (0x2) },
223 { "madda", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2bd) },
224 { "maddai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x23f) },
225 { "maddaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x23d) },
226 { "madda", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0x2f) },
227 { "max", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2b) },
228 { "maxi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x2d) },
229 { "max", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + MUOP4, UOP4 (0x4) },
230 /* FIXME: mini or min? */
231 { "mini", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2f) },
232 { "mini", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x1f) },
233 { "mini", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + MUOP4, UOP4 (0x5) },
234 { "msub", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2d) },
235 { "msubi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x27) },
236 { "msubq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x25) },
237 { "msub", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + MUOP4, UOP4 (0x3) },
238 { "msuba", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2fd) },
239 { "msubai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x27f) },
240 { "msubaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x27d) },
241 { "msuba", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0x3f) },
242 { "mul", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2a) },
243 { "muli", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x1e) },
244 { "mulq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x1c) },
245 { "mul", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + UOP4 (~0), UOP4 (6) },
246 { "mula", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2be) },
247 { "mulai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x1fe) },
248 { "mulaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x1fc) },
249 { "mula", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0x6f) },
250 { "nop", { 0 }, MURES + UDEST (~0) + UFT (~0) + UFS (~0) + MUOP11, UOP11 (0x2ff) },
251 { "opmula", { DOTDEST, SP, ACCDEST, FSREG, FTREG, XYZ }, MURES + MUOP11, UOP11 (0x2fe) },
252 { "opmsub", { DOTDEST, SP, FDREG, FSREG, FTREG, XYZ }, MURES + MUOP6, UOP6 (0x2e) },
253 { "sub", { DOTDEST, SP, FDREG, FSREG, FTREG }, MURES + MUOP6, UOP6 (0x2c) },
254 { "subi", { DOTDEST, SP, FDREG, FSREG, 'i' }, MURES + UFT (~0) + MUOP6, UOP6 (0x26) },
255 { "subq", { DOTDEST, SP, FDREG, FSREG, 'q' }, MURES + UFT (~0) + MUOP6, UOP6 (0x24) },
256 { "sub", { BC, DOTDEST, SP, FDREG, FSREG, FTREGBC }, MURES + UOP4 (~0), UOP4 (1) },
257 { "suba", { DOTDEST, SP, ACCDEST, FSREG, FTREG }, MURES + MUOP11, UOP11 (0x2fc) },
258 { "subai", { DOTDEST, SP, ACCDEST, FSREG, 'i' }, MURES + UFT (~0) + MUOP11, UOP11 (0x27e) },
259 { "subaq", { DOTDEST, SP, ACCDEST, FSREG, 'q' }, MURES + UFT (~0) + MUOP11, UOP11 (0x27c) },
260 { "suba", { BC, DOTDEST, SP, ACCDEST, FSREG, FTREGBC }, MURES + MUOP9, UOP9 (0x1f) }
54cc8ed4
DE
261};
262const int txvu_upper_opcodes_count = sizeof (txvu_upper_opcodes) / sizeof (txvu_opcodes[0]);
263
264struct txvu_opcode txvu_lower_opcodes[] = {
265
266 /* Macros appear first. */
267 /* ??? Any aliases? */
268
269 /* The rest of these needn't be sorted, but it helps to find them if they
270 are. */
271 { "waitp", { 0 }, 0xffffffff, 0x800007bf, 0 },
272 { "waitq", { 0 }, 0xffffffff, 0x800003bf, 0 },
273};
274const int txvu_lower_opcodes_count = sizeof (txvu_lower_opcodes) / sizeof (txvu_opcodes[0]);
275
276/* Indexed by first letter of opcode. Points to chain of opcodes with same
277 first letter. */
278/* ??? One can certainly use a better hash. Later. */
279static struct txvu_opcode *upper_opcode_map[26 + 1];
280static struct txvu_opcode *lower_opcode_map[26 + 1];
281
282/* Indexed by insn code. Points to chain of opcodes with same insn code. */
283static struct txvu_opcode *upper_icode_map[64];
284static struct txvu_opcode *lower_icode_map[64];
285\f
286/* Initialize any tables that need it.
287 Must be called once at start up (or when first needed).
288
289 FLAGS is currently unused but is intended to control initialization. */
290
291void
292txvu_opcode_init_tables (flags)
293 int flags;
294{
295 static int init_p = 0;
296
297 /* We may be intentionally called more than once (for example gdb will call
298 us each time the user switches cpu). These tables only need to be init'd
299 once though. */
300 /* ??? We can remove the need for txvu_opcode_supported by taking it into
301 account here, but I'm not sure I want to do that yet (if ever). */
302 if (!init_p)
303 {
304 int i,n;
305
306 memset (upper_opcode_map, 0, sizeof (upper_opcode_map));
307 memset (upper_icode_map, 0, sizeof (upper_icode_map));
308
309 /* Scan the table backwards so macros appear at the front. */
310 for (i = txvu_upper_opcodes_count - 1; i >= 0; --i)
311 {
312 int opcode_hash = TXVU_HASH_UPPER_OPCODE (txvu_upper_opcodes[i].mnemonic);
313 int icode_hash = TXVU_HASH_UPPER_ICODE (txvu_upper_opcodes[i].value);
314
315 txvu_upper_opcodes[i].next_asm = upper_opcode_map[opcode_hash];
316 upper_opcode_map[opcode_hash] = &txvu_upper_opcodes[i];
317
318 txvu_upper_opcodes[i].next_dis = upper_icode_map[icode_hash];
319 upper_icode_map[icode_hash] = &txvu_upper_opcodes[i];
320 }
321
322 memset (lower_opcode_map, 0, sizeof (lower_opcode_map));
323 memset (lower_icode_map, 0, sizeof (lower_icode_map));
324
325 /* Scan the table backwards so macros appear at the front. */
326 for (i = txvu_lower_opcodes_count - 1; i >= 0; --i)
327 {
328 int opcode_hash = TXVU_HASH_LOWER_OPCODE (txvu_lower_opcodes[i].mnemonic);
329 int icode_hash = TXVU_HASH_LOWER_ICODE (txvu_lower_opcodes[i].value);
330
331 txvu_lower_opcodes[i].next_asm = lower_opcode_map[opcode_hash];
332 lower_opcode_map[opcode_hash] = &txvu_lower_opcodes[i];
333
334 txvu_lower_opcodes[i].next_dis = lower_icode_map[icode_hash];
335 lower_icode_map[icode_hash] = &txvu_lower_opcodes[i];
336 }
337
338 init_p = 1;
339 }
340}
341
342/* Return the first insn in the chain for assembling upper INSN. */
343
344const struct txvu_opcode *
345txvu_upper_opcode_lookup_asm (insn)
346 const char *insn;
347{
348 return upper_opcode_map[TXVU_HASH_UPPER_OPCODE (insn)];
349}
350
351/* Return the first insn in the chain for assembling lower INSN. */
352
353const struct txvu_opcode *
354txvu_lower_opcode_lookup_asm (insn)
355 const char *insn;
356{
357 return lower_opcode_map[TXVU_HASH_LOWER_OPCODE (insn)];
358}
359
360/* Return the first insn in the chain for disassembling upper INSN. */
361
362const struct txvu_opcode *
363txvu_upper_opcode_lookup_dis (insn)
364 TXVU_INSN insn;
365{
366 return upper_icode_map[TXVU_HASH_UPPER_ICODE (insn)];
367}
368
369/* Return the first insn in the chain for disassembling lower INSN. */
370
371const struct txvu_opcode *
372txvu_lower_opcode_lookup_dis (insn)
373 TXVU_INSN insn;
374{
375 return lower_icode_map[TXVU_HASH_LOWER_ICODE (insn)];
376}
377\f
378/* Value of DEST in use.
71af45ec 379 Each of the registers must specify the same value as the opcode.
54cc8ed4
DE
380 ??? Perhaps remove the duplication? */
381static int dest;
3f897263
DE
382
383/* Value of BC to use.
384 The register specified for the ftreg must match the broadcast register
385 specified in the opcode. */
386static int bc;
54cc8ed4
DE
387\f
388/* Init fns.
389 These are called before doing each of the respective activities. */
390
391/* Called by the assembler before parsing an instruction. */
392
393void
394txvu_opcode_init_parse ()
395{
396 dest = -1;
3f897263 397 bc = -1;
54cc8ed4
DE
398}
399
400/* Called by the disassembler before printing an instruction. */
401
402void
403txvu_opcode_init_print ()
404{
405 dest = -1;
3f897263 406 bc = -1;
54cc8ed4
DE
407}
408\f
409/* Destination choice support.
410 The "dest" string selects any combination of x,y,z,w.
411 [The letters are ordered that way to follow the manual's style.] */
412
71af45ec
DE
413/* Parse a `dest' spec.
414 Return the found value.
415 *PSTR is set to the character that terminated the parsing.
416 It is up to the caller to do any error checking. */
417
54cc8ed4 418static long
71af45ec 419parse_dest (pstr)
54cc8ed4 420 char **pstr;
54cc8ed4
DE
421{
422 long dest = 0;
423
54cc8ed4
DE
424 while (**pstr)
425 {
426 switch (**pstr)
427 {
428 case 'x' : case 'X' : dest |= TXVU_DEST_X; break;
429 case 'y' : case 'Y' : dest |= TXVU_DEST_Y; break;
430 case 'z' : case 'Z' : dest |= TXVU_DEST_Z; break;
431 case 'w' : case 'W' : dest |= TXVU_DEST_W; break;
71af45ec 432 default : return dest;
54cc8ed4
DE
433 }
434 ++*pstr;
435 }
436
71af45ec
DE
437 return dest;
438}
439
440static long
441parse_dotdest (pstr, errmsg)
442 char **pstr;
443 const char **errmsg;
444{
445 long dest;
446
447 if (**pstr != '.')
448 {
449 *errmsg = "missing `.'";
450 return 0;
451 }
452
453 ++*pstr;
454 dest = parse_dest (pstr);
455 if (dest == 0 || isalnum (**pstr))
456 {
457 *errmsg = "invalid `dest'";
458 return 0;
459 }
54cc8ed4
DE
460 *errmsg = NULL;
461 return dest;
462}
463
71af45ec
DE
464static TXVU_INSN
465insert_dotdest (insn, operand, mods, value, errmsg)
466 TXVU_INSN insn;
467 const struct txvu_operand *operand;
468 int mods;
469 long value;
470 const char **errmsg;
471{
472 /* Record the DEST value in use so the register parser can use it. */
473 dest = value;
474 if (errmsg)
475 *errmsg = NULL;
476 return insn |= value << operand->shift;
477}
478
479static long
480extract_dotdest (insn, operand, mods, pinvalid)
481 TXVU_INSN insn;
482 const struct txvu_operand *operand;
483 int mods;
484 int *pinvalid;
485{
486 /* Record the DEST value in use so the register printer can use it. */
487 dest = (insn >> operand->shift) & ((1 << operand->bits) - 1);
488 return dest;
489}
490
54cc8ed4 491static void
71af45ec 492print_dest (info, insn, value)
54cc8ed4
DE
493 disassemble_info *info;
494 TXVU_INSN insn;
495 long value;
496{
54cc8ed4
DE
497 if (value & TXVU_DEST_X)
498 (*info->fprintf_func) (info->stream, "x");
499 if (value & TXVU_DEST_Y)
500 (*info->fprintf_func) (info->stream, "y");
501 if (value & TXVU_DEST_Z)
502 (*info->fprintf_func) (info->stream, "z");
503 if (value & TXVU_DEST_W)
504 (*info->fprintf_func) (info->stream, "w");
505}
71af45ec
DE
506
507static void
508print_dotdest (info, insn, value)
509 disassemble_info *info;
510 TXVU_INSN insn;
511 long value;
512{
513 (*info->fprintf_func) (info->stream, ".");
514 print_dest (info, insn, value);
515}
54cc8ed4
DE
516\f
517static long
71af45ec 518parse_vfreg (pstr, errmsg)
54cc8ed4
DE
519 char **pstr;
520 const char **errmsg;
521{
522 char *str = *pstr;
523 char *start;
524 long reg;
71af45ec 525 int reg_dest;
54cc8ed4
DE
526
527 if (tolower (str[0]) != 'v'
528 || tolower (str[1]) != 'f')
529 {
530 *errmsg = "unknown register";
531 return 0;
532 }
533
534 /* FIXME: quick hack until the framework works. */
535 start = str = str + 2;
536 while (*str && isdigit (*str))
537 ++str;
538 reg = atoi (start);
71af45ec
DE
539 reg_dest = parse_dest (&str);
540 if (reg_dest == 0 || isalnum (*str))
541 {
542 *errmsg = "invalid `dest'";
543 return 0;
544 }
545 if (reg_dest != dest)
546 {
547 *errmsg = "register `dest' does not match instruction `dest'";
548 return 0;
549 }
54cc8ed4
DE
550 *pstr = str;
551 *errmsg = NULL;
552 return reg;
553}
554
555static void
71af45ec 556print_vfreg (info, insn, value)
54cc8ed4
DE
557 disassemble_info *info;
558 TXVU_INSN insn;
559 long value;
560{
561 (*info->fprintf_func) (info->stream, "vf%ld", value);
71af45ec 562 print_dest (info, insn, dest);
54cc8ed4 563}
3f897263
DE
564\f
565/* Broadcast handling. */
566
567static long
568parse_bc (pstr, errmsg)
569 char **pstr;
570 const char **errmsg;
571{
572 long dest = 0;
573
574 switch (**pstr)
575 {
576 case 'x' : case 'X' : dest = TXVU_BC_X; break;
577 case 'y' : case 'Y' : dest = TXVU_BC_Y; break;
578 case 'z' : case 'Z' : dest = TXVU_BC_Z; break;
579 case 'w' : case 'W' : dest = TXVU_BC_W; break;
580 default : *errmsg = "invalid `bc'"; return 0;
581 }
582 ++*pstr;
583
584 *errmsg = NULL;
585 return dest;
586}
587
588static void
589print_bc (info, insn, value)
590 disassemble_info *info;
591 TXVU_INSN insn;
592 long value;
593{
594 char c;
595
596 switch (value)
597 {
598 case TXVU_BC_X : c = 'x' ; break;
599 case TXVU_BC_Y : c = 'y' ; break;
600 case TXVU_BC_Z : c = 'z' ; break;
601 case TXVU_BC_W : c = 'w' ; break;
602 }
603
604 (*info->fprintf_func) (info->stream, "%c", c);
605}
606\f
607/* FT register in broadcast case. */
608
609static long
610parse_ftregbc (pstr, errmsg)
611 char **pstr;
612 const char **errmsg;
613{
614 char *str = *pstr;
615 char *start;
616 long reg;
617 int reg_bc;
618
619 if (tolower (str[0]) != 'v'
620 || tolower (str[1]) != 'f')
621 {
622 *errmsg = "unknown register";
623 return 0;
624 }
625
626 /* FIXME: quick hack until the framework works. */
627 start = str = str + 2;
628 while (*str && isdigit (*str))
629 ++str;
630 reg = atoi (start);
631 reg_bc = parse_bc (&str, errmsg);
632 if (*errmsg)
633 return 0;
634 if (reg_bc != bc)
635 {
636 *errmsg = "register `bc' does not match instruction `bc'";
637 return 0;
638 }
639 *pstr = str;
640 *errmsg = NULL;
641 return reg;
642}
643
644static void
645print_ftregbc (info, insn, value)
646 disassemble_info *info;
647 TXVU_INSN insn;
648 long value;
649{
650 (*info->fprintf_func) (info->stream, "vf%ld", value);
651 print_bc (info, insn, bc);
652}
653\f
654/* ACC handling. */
655
656static long
657parse_accdest (pstr, errmsg)
658 char **pstr;
659 const char **errmsg;
660{
661 char *str = *pstr;
662 long acc_dest = 0;
663
664 if (strncasecmp (str, "acc", 3) != 0)
665 {
666 *errmsg = "expecting `acc'";
667 return 0;
668 }
669 str += 3;
670 acc_dest = parse_dest (&str);
671 if (acc_dest == 0 || isalnum (*str))
672 {
673 *errmsg = "invalid `dest'";
674 return 0;
675 }
676 if (acc_dest != dest)
677 {
678 *errmsg = "acc `dest' does not match instruction `dest'";
679 return 0;
680 }
681 *pstr = str;
682 *errmsg = NULL;
683 /* Value isn't used, but we must return something. */
684 return 0;
685}
686
687static void
688print_accdest (info, insn, value)
689 disassemble_info *info;
690 TXVU_INSN insn;
691 long value;
692{
693 (*info->fprintf_func) (info->stream, "acc");
694 print_dest (info, insn, value);
695}
696\f
697/* XYZ operand handling.
698 This simplifies the opmula,opmsub entries by keeping them equivalent to
699 the others. */
700
701static long
702parse_xyz (pstr, errmsg)
703 char **pstr;
704 const char **errmsg;
705{
706 if (dest != (TXVU_DEST_X | TXVU_DEST_Y | TXVU_DEST_Z))
707 {
708 *errmsg = "expecting `xyz' for `dest' value";
709 return 0;
710 }
711 return 0;
712}
This page took 0.050827 seconds and 4 git commands to generate.