Add m32rx sanitization for new files.
[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
0b988d39
DE
63PARSE_FN (bcftreg);
64PRINT_FN (bcftreg);
3f897263
DE
65
66PARSE_FN (accdest);
67PRINT_FN (accdest);
68
69PARSE_FN (xyz);
70
0b988d39
DE
71PARSE_FN (ireg);
72PRINT_FN (ireg);
73
74PARSE_FN (freg);
75PRINT_FN (freg);
76
77PARSE_FN (ffstreg);
78INSERT_FN (ffstreg);
79EXTRACT_FN (ffstreg);
80PRINT_FN (ffstreg);
81
82PARSE_FN (vi01);
83PRINT_FN (vi01);
84
85INSERT_FN (limm12);
86EXTRACT_FN (limm12);
87
3f897263 88/* Various types of TXVU operands, including insn suffixes.
54cc8ed4
DE
89
90 Fields are:
91
92 BITS SHIFT FLAGS PARSE_FN INSERT_FN EXTRACT_FN PRINT_FN
93
94 Operand values are 128 + table index. This allows ASCII chars to be
95 included in the syntax spec. */
96
97const struct txvu_operand txvu_operands[] =
98{
3f897263 99 /* place holder (??? not sure if needed) */
54cc8ed4
DE
100#define UNUSED 128
101 { 0 },
102
0b988d39
DE
103 /* Upper word operands. */
104
3f897263 105 /* Destination indicator, with leading '.'. */
0b988d39 106#define UDOTDEST (UNUSED + 1)
54cc8ed4 107 { 4, TXVU_SHIFT_DEST, TXVU_OPERAND_SUFFIX,
71af45ec 108 parse_dotdest, insert_dotdest, extract_dotdest, print_dotdest },
54cc8ed4 109
3f897263 110 /* ft reg */
0b988d39 111#define UVFTREG (UDOTDEST + 1)
71af45ec 112 { 5, TXVU_SHIFT_FTREG, 0, parse_vfreg, 0, 0, print_vfreg },
54cc8ed4 113
3f897263 114 /* fs reg */
0b988d39 115#define UVFSREG (UVFTREG + 1)
71af45ec 116 { 5, TXVU_SHIFT_FSREG, 0, parse_vfreg, 0, 0, print_vfreg },
54cc8ed4 117
3f897263 118 /* fd reg */
0b988d39 119#define UVFDREG (UVFSREG + 1)
71af45ec 120 { 5, TXVU_SHIFT_FDREG, 0, parse_vfreg, 0, 0, print_vfreg },
54cc8ed4 121
3f897263 122 /* broadcast */
0b988d39 123#define UBC (UVFDREG + 1)
3f897263
DE
124 { 2, 0, 0, parse_bc, 0, 0, print_bc },
125
126 /* ftreg in broadcast case */
0b988d39
DE
127#define UBCFTREG (UBC + 1)
128 { 5, TXVU_SHIFT_FTREG, 0, parse_bcftreg, 0, 0, print_bcftreg },
3f897263
DE
129
130 /* accumulator dest */
0b988d39 131#define UACCDEST (UBCFTREG + 1)
3f897263
DE
132 { 0, 0, TXVU_OPERAND_FAKE, parse_accdest, 0, 0, print_accdest },
133
134 /* The XYZ operand is a fake one that is used to ensure only "xyz" is
135 specified. It simplifies the opmula and opmsub entries. */
0b988d39 136#define UXYZ (UACCDEST + 1)
3f897263
DE
137 { 0, 0, TXVU_OPERAND_FAKE, parse_xyz, 0, 0, 0 },
138
0b988d39
DE
139 /* Lower word operands. */
140
141 /* 11 bit immediate. */
142#define LIMM11 (UXYZ + 1)
143 { 11, 0, 0, 0, 0, 0, 0 },
144
145 /* IS register. */
146#define LISREG (LIMM11 + 1)
147 { 5, 11, 0, parse_ireg, 0, 0, print_ireg },
148
149 /* IT register. */
150#define LITREG (LISREG + 1)
151 { 5, 16, 0, parse_ireg, 0, 0, print_ireg },
152
153 /* FS reg, with FSF field selector. */
154#define LFSFFSREG (LITREG + 1)
155 { 5, 11, 0, parse_ffstreg, insert_ffstreg, extract_ffstreg, print_ffstreg },
156
157 /* FS reg, no selector (choice of x,y,z,w is provided by opcode). */
158#define LFSREG (LFSFFSREG + 1)
159 { 5, 11, 0, parse_freg, 0, 0, print_freg },
160
161 /* FT reg, with FTF field selector. */
162#define LFTFFTREG (LFSREG + 1)
163 { 5, 16, 0, parse_ffstreg, insert_ffstreg, extract_ffstreg, print_ffstreg },
164
165 /* VI01 register. */
166#define LVI01 (LFTFFTREG + 1)
167 { 0, 0, TXVU_OPERAND_FAKE, parse_vi01, 0, 0, print_vi01 },
168
169 /* 24 bit immediate. */
170#define LIMM24 (LVI01 + 1)
171 { 24, 0, 0, 0, 0, 0, 0 },
172
173 /* 12 bit immediate, split into 1 and 11 bit pieces. */
174#define LIMM12 (LIMM24 + 1)
175 { 12, 0, 0, 0, insert_limm12, extract_limm12, 0 },
176
54cc8ed4
DE
177/* end of list place holder */
178 { 0 }
179};
180\f
181/* Macros to put a field's value into the right place. */
3f897263
DE
182/* FIXME: If assembler needs these, move to opcode/txvu.h. */
183
0b988d39
DE
184/* value X, B bits, shift S */
185#define R(x,b,s) (((x) & ((1 << (b)) - 1)) << (s))
186
187/* Upper instruction Value macros. */
54cc8ed4 188
3f897263 189/* Upper Flag bits. */
0b988d39 190#define VUF(x) R ((x), 5, 27)
3f897263 191/* Upper REServed two bits next to flag bits. */
0b988d39
DE
192#define VURES(x) R ((x), 2, 25)
193/* DEST field. */
194#define VUDEST(x) R ((x), 4, 21)
195/* FT reg field. */
196#define VUFT(x) R ((x), 5, TXVU_SHIFT_FTREG)
197/* FS reg field. */
198#define VUFS(x) R ((x), 5, TXVU_SHIFT_FSREG)
199/* FD reg field. */
200#define VUFD(x) R ((x), 5, TXVU_SHIFT_FDREG)
201/* 4 bit opcode field. */
202#define VUOP4(x) R ((x), 4, 2)
203/* 6 bit opcode field. */
204#define VUOP6(x) R ((x), 6, 0)
205/* 9 bit opcode field. */
206#define VUOP9(x) R ((x), 9, 2)
207/* 11 bit opcode field. */
208#define VUOP11(x) R ((x), 11, 0)
209/* BroadCast field. */
210#define VUBC(x) R ((x), 2, 0)
211
212/* Field masks. */
213#define MUUBITS (VUF (~0) + VURES (~0))
214#define MURES VURES (~0)
215#define MUOP4 VUOP4 (~0)
216#define MUOP6 VUOP6 (~0)
217#define MUOP9 VUOP9 (~0)
218#define MUOP11 VUOP11 (~0)
219
220/* Lower instruction Value macros. */
221
222/* 7 bit opcode. */
223#define VLOP7(x) R ((x), 7, 25)
224/* 11 bit opcode. */
225#define VLOP11(x) R ((x), 11, 0)
226/* dest field. */
227#define VLDEST(x) R ((x), 4, 21)
228/* IT reg. */
229#define VLIT(x) R ((x), 5, 16)
230/* IS reg. */
231#define VLIS(x) R ((x), 5, 11)
232/* 11 bit immediate. */
233#define VLIMM11(x) R ((x), 11, 0)
234/* FTF field. */
235#define VLFTF(x) R ((x), 2, 23)
236/* FSF field. */
237#define VLFSF(x) R ((x), 2, 21)
238/* FT reg. */
239#define VLFT(x) R ((x), 5, 16)
240/* FS reg. */
241#define VLFS(x) R ((x), 5, 11)
242
243/* Field masks. */
244#define MLOP7 VLOP7 (~0)
245#define MLOP11 VLOP11 (~0)
246#define MLDEST VLDEST (~0)
247#define MLIT VLIT (~0)
248#define MLIS VLIS (~0)
249#define MLIMM11 VLIMM11 (~0)
250#define MLB24 R (1, 1, 24)
251/* 12 bit immediates are split into two parts, 1 bit and 11 bits.
252 The upper 1 bit is part of the `dest' field. This mask is for the
253 other 3 bits of the dest field. */
254#define MLIMM12TOP R (7, 3, 22)
3f897263
DE
255
256/* A space, separates instruction name (mnemonic + mnemonic operands) from operands. */
257#define SP ' '
258
54cc8ed4
DE
259/* TXVU instructions.
260 [??? some of these comments are left over from the ARC port from which
261 this code is borrowed, delete in time]
262
263 Longer versions of insns must appear before shorter ones (if gas sees
264 "lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
265 junk). This isn't necessary for `ld' because of the trailing ']'.
266
267 Instructions that are really macros based on other insns must appear
268 before the real insn so they're chosen when disassembling. Eg: The `mov'
269 insn is really the `and' insn.
270
271 This table is best viewed on a wide screen (161 columns). I'd prefer to
272 keep it this way. The rest of the file, however, should be viewable on an
273 80 column terminal. */
274
275/* ??? This table also includes macros: asl, lsl, and mov. The ppc port has
276 a more general facility for dealing with macros which could be used if
277 we need to. */
278
279/* These tables can't be `const' because members `next_asm' and `next_dis' are
280 computed at run-time. We could split this into two, as that would put the
281 constant stuff into a readonly section. */
282
283struct txvu_opcode txvu_upper_opcodes[] = {
284
285 /* Macros appear first. */
286 /* ??? Any aliases? */
0b988d39 287 /* FIXME: When close to being finished, clean up by aligning fields. */
54cc8ed4 288
3f897263 289 /* The rest of these needn't be sorted, but it helps to find them if they are. */
0b988d39
DE
290 { "abs", { UDOTDEST, SP, UVFTREG, UVFSREG }, MURES + MUOP11, VUOP11 (0x1fd) },
291 { "add", { UDOTDEST, SP, UVFDREG, UVFSREG, UVFTREG }, MURES + MUOP6, VUOP6 (0x28) },
292 { "addi", { UDOTDEST, SP, UVFDREG, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x22) },
293 { "addq", { UDOTDEST, SP, UVFDREG, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x20) },
294 { "add", { UBC, UDOTDEST, SP, UVFDREG, UVFSREG, UBCFTREG }, MURES + VUOP4 (~0), VUOP4 (0) },
295 { "adda", { UDOTDEST, SP, UACCDEST, UVFSREG, UVFTREG }, MURES + MUOP11, VUOP11 (0x2bc) },
296 { "addai", { UDOTDEST, SP, UACCDEST, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x23e) },
297 { "addaq", { UDOTDEST, SP, UACCDEST, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x23c) },
298 { "adda", { UBC, UDOTDEST, SP, UACCDEST, UVFSREG, UBCFTREG }, MURES + MUOP9, VUOP9 (0xf) },
299 { "clip", { UDOTDEST, SP, UVFSREG }, MURES + VUDEST (~0) + VUFT (~0) + MUOP11, VUDEST (0xf) + VUOP11 (0x1ff) },
300 { "ftoi0", { UDOTDEST, SP, UVFTREG, UVFSREG }, MURES + MUOP11, VUOP11 (0x17c) },
301 { "ftoi4", { UDOTDEST, SP, UVFTREG, UVFSREG }, MURES + MUOP11, VUOP11 (0x17d) },
302 { "ftoi12", { UDOTDEST, SP, UVFTREG, UVFSREG }, MURES + MUOP11, VUOP11 (0x17e) },
303 { "ftoi15", { UDOTDEST, SP, UVFTREG, UVFSREG }, MURES + MUOP11, VUOP11 (0x17f) },
304 { "itof0", { UDOTDEST, SP, UVFTREG, UVFSREG }, MURES + MUOP11, VUOP11 (0x13c) },
305 { "itof4", { UDOTDEST, SP, UVFTREG, UVFSREG }, MURES + MUOP11, VUOP11 (0x13d) },
306 { "itof12", { UDOTDEST, SP, UVFTREG, UVFSREG }, MURES + MUOP11, VUOP11 (0x13e) },
307 { "itof15", { UDOTDEST, SP, UVFTREG, UVFSREG }, MURES + MUOP11, VUOP11 (0x13f) },
308 { "madd", { UDOTDEST, SP, UVFDREG, UVFSREG, UVFTREG }, MURES + MUOP6, VUOP6 (0x29) },
309 { "maddi", { UDOTDEST, SP, UVFDREG, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x23) },
310 { "maddq", { UDOTDEST, SP, UVFDREG, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x21) },
311 { "madd", { UBC, UDOTDEST, SP, UVFDREG, UVFSREG, UBCFTREG }, MURES + MUOP4, VUOP4 (0x2) },
312 { "madda", { UDOTDEST, SP, UACCDEST, UVFSREG, UVFTREG }, MURES + MUOP11, VUOP11 (0x2bd) },
313 { "maddai", { UDOTDEST, SP, UACCDEST, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x23f) },
314 { "maddaq", { UDOTDEST, SP, UACCDEST, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x23d) },
315 { "madda", { UBC, UDOTDEST, SP, UACCDEST, UVFSREG, UBCFTREG }, MURES + MUOP9, VUOP9 (0x2f) },
316 { "max", { UDOTDEST, SP, UVFDREG, UVFSREG, UVFTREG }, MURES + MUOP6, VUOP6 (0x2b) },
317 { "maxi", { UDOTDEST, SP, UVFDREG, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x2d) },
318 { "max", { UBC, UDOTDEST, SP, UVFDREG, UVFSREG, UBCFTREG }, MURES + MUOP4, VUOP4 (0x4) },
3f897263 319 /* FIXME: mini or min? */
0b988d39
DE
320 { "mini", { UDOTDEST, SP, UVFDREG, UVFSREG, UVFTREG }, MURES + MUOP6, VUOP6 (0x2f) },
321 { "mini", { UDOTDEST, SP, UVFDREG, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x1f) },
322 { "mini", { UBC, UDOTDEST, SP, UVFDREG, UVFSREG, UBCFTREG }, MURES + MUOP4, VUOP4 (0x5) },
323 { "msub", { UDOTDEST, SP, UVFDREG, UVFSREG, UVFTREG }, MURES + MUOP6, VUOP6 (0x2d) },
324 { "msubi", { UDOTDEST, SP, UVFDREG, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x27) },
325 { "msubq", { UDOTDEST, SP, UVFDREG, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x25) },
326 { "msub", { UBC, UDOTDEST, SP, UVFDREG, UVFSREG, UBCFTREG }, MURES + MUOP4, VUOP4 (0x3) },
327 { "msuba", { UDOTDEST, SP, UACCDEST, UVFSREG, UVFTREG }, MURES + MUOP11, VUOP11 (0x2fd) },
328 { "msubai", { UDOTDEST, SP, UACCDEST, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x27f) },
329 { "msubaq", { UDOTDEST, SP, UACCDEST, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x27d) },
330 { "msuba", { UBC, UDOTDEST, SP, UACCDEST, UVFSREG, UBCFTREG }, MURES + MUOP9, VUOP9 (0x3f) },
331 { "mul", { UDOTDEST, SP, UVFDREG, UVFSREG, UVFTREG }, MURES + MUOP6, VUOP6 (0x2a) },
332 { "muli", { UDOTDEST, SP, UVFDREG, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x1e) },
333 { "mulq", { UDOTDEST, SP, UVFDREG, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x1c) },
334 { "mul", { UBC, UDOTDEST, SP, UVFDREG, UVFSREG, UBCFTREG }, MURES + VUOP4 (~0), VUOP4 (6) },
335 { "mula", { UDOTDEST, SP, UACCDEST, UVFSREG, UVFTREG }, MURES + MUOP11, VUOP11 (0x2be) },
336 { "mulai", { UDOTDEST, SP, UACCDEST, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x1fe) },
337 { "mulaq", { UDOTDEST, SP, UACCDEST, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x1fc) },
338 { "mula", { UBC, UDOTDEST, SP, UACCDEST, UVFSREG, UBCFTREG }, MURES + MUOP9, VUOP9 (0x6f) },
339 { "nop", { 0 }, MURES + VUDEST (~0) + VUFT (~0) + VUFS (~0) + MUOP11, VUOP11 (0x2ff) },
340 { "opmula", { UDOTDEST, SP, UACCDEST, UVFSREG, UVFTREG, UXYZ }, MURES + MUOP11, VUOP11 (0x2fe) },
341 { "opmsub", { UDOTDEST, SP, UVFDREG, UVFSREG, UVFTREG, UXYZ }, MURES + MUOP6, VUOP6 (0x2e) },
342 { "sub", { UDOTDEST, SP, UVFDREG, UVFSREG, UVFTREG }, MURES + MUOP6, VUOP6 (0x2c) },
343 { "subi", { UDOTDEST, SP, UVFDREG, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x26) },
344 { "subq", { UDOTDEST, SP, UVFDREG, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP6, VUOP6 (0x24) },
345 { "sub", { UBC, UDOTDEST, SP, UVFDREG, UVFSREG, UBCFTREG }, MURES + VUOP4 (~0), VUOP4 (1) },
346 { "suba", { UDOTDEST, SP, UACCDEST, UVFSREG, UVFTREG }, MURES + MUOP11, VUOP11 (0x2fc) },
347 { "subai", { UDOTDEST, SP, UACCDEST, UVFSREG, 'i' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x27e) },
348 { "subaq", { UDOTDEST, SP, UACCDEST, UVFSREG, 'q' }, MURES + VUFT (~0) + MUOP11, VUOP11 (0x27c) },
349 { "suba", { UBC, UDOTDEST, SP, UACCDEST, UVFSREG, UBCFTREG }, MURES + MUOP9, VUOP9 (0x1f) }
54cc8ed4
DE
350};
351const int txvu_upper_opcodes_count = sizeof (txvu_upper_opcodes) / sizeof (txvu_opcodes[0]);
352
353struct txvu_opcode txvu_lower_opcodes[] = {
354
355 /* Macros appear first. */
356 /* ??? Any aliases? */
357
0b988d39
DE
358 /* The rest of these needn't be sorted, but it helps to find them if they are. */
359 { "b", { SP, LIMM11 }, MLOP7 + MLDEST + MLIT + MLIS, VLOP7 (0x20) },
360 { "bal", { SP, LITREG, LIMM11 }, MLOP7 + MLDEST + MLIS, VLOP7 (0x21) },
361 { "div", { 'q', LFSFFSREG, LFTFFTREG }, MLOP7 + MLOP11, VLOP7 (0x40) + VLOP11 (0x3bc) },
362 { "eatan", { 'p', LFSFFSREG }, MLOP7 + VLFTF (~0) + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLOP11 (0x7fd) },
363 { "eatanxy", { 'p', LFSREG }, MLOP7 + MLDEST + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLDEST (0xf) + VLOP11 (0x77c) },
364 { "eatanxz", { 'p', LFSREG }, MLOP7 + MLDEST + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLDEST (0xf) + VLOP11 (0x77d) },
365 { "eexp", { 'p', LFSFFSREG }, MLOP7 + VLFTF (~0) + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLOP11 (0x7fe) },
366 { "eleng", { 'p', LFSREG }, MLOP7 + MLDEST + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLDEST (0xf) + VLOP11 (0x74e) },
367 { "ercpr", { 'p', LFSFFSREG }, MLOP7 + VLFTF (~0) + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLOP11 (0x7be) },
368 { "erleng", { 'p', LFSREG }, MLOP7 + MLDEST + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLDEST (0xf) + VLOP11 (0x73f) },
369 { "ersadd", { 'p', LFSREG }, MLOP7 + MLDEST + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLDEST (0xf) + VLOP11 (0x73d) },
370 { "ersqrt", { 'p', LFSFFSREG }, MLOP7 + VLFTF (~0) + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLOP11 (0x7bd) },
371 { "esadd", { 'p', LFSREG }, MLOP7 + MLDEST + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLDEST (0xf) + VLOP11 (0x73c) },
372 { "esin", { 'p', LFSFFSREG }, MLOP7 + VLFTF (~0) + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLOP11 (0x7fc) },
373 { "esqrt", { 'p', LFSFFSREG }, MLOP7 + VLFTF (~0) + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLOP11 (0x7bc) },
374 { "esum", { 'p', LFSREG }, MLOP7 + MLDEST + VLFT (~0) + MLOP11, VLOP7 (0x40) + VLDEST (0xf) + VLOP11 (0x77e) },
375 { "fcand", { LVI01, LIMM24 }, MLOP7 + MLB24, VLOP7 (0x12) },
376 { "fceq", { LVI01, LIMM24 }, MLOP7 + MLB24, VLOP7 (0x10) },
377 { "fcget", { LITREG }, MLOP7 + MLDEST + MLIS + MLIMM11, VLOP7 (0x1c) },
378 { "fcor", { LVI01, LIMM24 }, MLOP7 + MLB24, VLOP7 (0x13) },
379 { "fcset", { LVI01, LIMM24 }, MLOP7 + MLB24, VLOP7 (0x11) },
380 { "fmand", { LITREG, LISREG }, MLOP7 + MLDEST + MLIMM11, VLOP7 (0x1a) },
381 { "fmeq", { LITREG, LISREG }, MLOP7 + MLDEST + MLIMM11, VLOP7 (0x18) },
382 { "fmor", { LITREG, LISREG }, MLOP7 + MLDEST + MLIMM11, VLOP7 (0x1b) },
383 { "fsand", { LITREG, LIMM12 }, MLOP7 + MLIMM12TOP + MLIS, VLOP7 (0x16) },
384 { "fseq", { LITREG, LIMM12 }, MLOP7 + MLIMM12TOP + MLIS, VLOP7 (0x14) },
385 { "fsor", { LITREG, LIMM12 }, MLOP7 + MLIMM12TOP + MLIS, VLOP7 (0x17) },
386 { "fsset", { LITREG, LIMM12 }, MLOP7 + MLIMM12TOP + MLIS, VLOP7 (0x15) },
387 { "waitp", { 0 }, 0xffffffff, 0x800007bf },
388 { "waitq", { 0 }, 0xffffffff, 0x800003bf },
54cc8ed4
DE
389};
390const int txvu_lower_opcodes_count = sizeof (txvu_lower_opcodes) / sizeof (txvu_opcodes[0]);
391
392/* Indexed by first letter of opcode. Points to chain of opcodes with same
393 first letter. */
394/* ??? One can certainly use a better hash. Later. */
395static struct txvu_opcode *upper_opcode_map[26 + 1];
396static struct txvu_opcode *lower_opcode_map[26 + 1];
397
398/* Indexed by insn code. Points to chain of opcodes with same insn code. */
399static struct txvu_opcode *upper_icode_map[64];
400static struct txvu_opcode *lower_icode_map[64];
401\f
402/* Initialize any tables that need it.
403 Must be called once at start up (or when first needed).
404
405 FLAGS is currently unused but is intended to control initialization. */
406
407void
408txvu_opcode_init_tables (flags)
409 int flags;
410{
411 static int init_p = 0;
412
413 /* We may be intentionally called more than once (for example gdb will call
414 us each time the user switches cpu). These tables only need to be init'd
415 once though. */
416 /* ??? We can remove the need for txvu_opcode_supported by taking it into
417 account here, but I'm not sure I want to do that yet (if ever). */
418 if (!init_p)
419 {
420 int i,n;
421
422 memset (upper_opcode_map, 0, sizeof (upper_opcode_map));
423 memset (upper_icode_map, 0, sizeof (upper_icode_map));
424
425 /* Scan the table backwards so macros appear at the front. */
426 for (i = txvu_upper_opcodes_count - 1; i >= 0; --i)
427 {
428 int opcode_hash = TXVU_HASH_UPPER_OPCODE (txvu_upper_opcodes[i].mnemonic);
429 int icode_hash = TXVU_HASH_UPPER_ICODE (txvu_upper_opcodes[i].value);
430
431 txvu_upper_opcodes[i].next_asm = upper_opcode_map[opcode_hash];
432 upper_opcode_map[opcode_hash] = &txvu_upper_opcodes[i];
433
434 txvu_upper_opcodes[i].next_dis = upper_icode_map[icode_hash];
435 upper_icode_map[icode_hash] = &txvu_upper_opcodes[i];
436 }
437
438 memset (lower_opcode_map, 0, sizeof (lower_opcode_map));
439 memset (lower_icode_map, 0, sizeof (lower_icode_map));
440
441 /* Scan the table backwards so macros appear at the front. */
442 for (i = txvu_lower_opcodes_count - 1; i >= 0; --i)
443 {
444 int opcode_hash = TXVU_HASH_LOWER_OPCODE (txvu_lower_opcodes[i].mnemonic);
445 int icode_hash = TXVU_HASH_LOWER_ICODE (txvu_lower_opcodes[i].value);
446
447 txvu_lower_opcodes[i].next_asm = lower_opcode_map[opcode_hash];
448 lower_opcode_map[opcode_hash] = &txvu_lower_opcodes[i];
449
450 txvu_lower_opcodes[i].next_dis = lower_icode_map[icode_hash];
451 lower_icode_map[icode_hash] = &txvu_lower_opcodes[i];
452 }
453
454 init_p = 1;
455 }
456}
457
458/* Return the first insn in the chain for assembling upper INSN. */
459
460const struct txvu_opcode *
461txvu_upper_opcode_lookup_asm (insn)
462 const char *insn;
463{
464 return upper_opcode_map[TXVU_HASH_UPPER_OPCODE (insn)];
465}
466
467/* Return the first insn in the chain for assembling lower INSN. */
468
469const struct txvu_opcode *
470txvu_lower_opcode_lookup_asm (insn)
471 const char *insn;
472{
473 return lower_opcode_map[TXVU_HASH_LOWER_OPCODE (insn)];
474}
475
476/* Return the first insn in the chain for disassembling upper INSN. */
477
478const struct txvu_opcode *
479txvu_upper_opcode_lookup_dis (insn)
480 TXVU_INSN insn;
481{
482 return upper_icode_map[TXVU_HASH_UPPER_ICODE (insn)];
483}
484
485/* Return the first insn in the chain for disassembling lower INSN. */
486
487const struct txvu_opcode *
488txvu_lower_opcode_lookup_dis (insn)
489 TXVU_INSN insn;
490{
491 return lower_icode_map[TXVU_HASH_LOWER_ICODE (insn)];
492}
493\f
494/* Value of DEST in use.
71af45ec 495 Each of the registers must specify the same value as the opcode.
54cc8ed4
DE
496 ??? Perhaps remove the duplication? */
497static int dest;
3f897263
DE
498
499/* Value of BC to use.
500 The register specified for the ftreg must match the broadcast register
501 specified in the opcode. */
502static int bc;
54cc8ed4
DE
503\f
504/* Init fns.
505 These are called before doing each of the respective activities. */
506
507/* Called by the assembler before parsing an instruction. */
508
509void
510txvu_opcode_init_parse ()
511{
512 dest = -1;
3f897263 513 bc = -1;
54cc8ed4
DE
514}
515
516/* Called by the disassembler before printing an instruction. */
517
518void
519txvu_opcode_init_print ()
520{
521 dest = -1;
3f897263 522 bc = -1;
54cc8ed4
DE
523}
524\f
525/* Destination choice support.
526 The "dest" string selects any combination of x,y,z,w.
527 [The letters are ordered that way to follow the manual's style.] */
528
71af45ec
DE
529/* Parse a `dest' spec.
530 Return the found value.
531 *PSTR is set to the character that terminated the parsing.
532 It is up to the caller to do any error checking. */
533
54cc8ed4 534static long
71af45ec 535parse_dest (pstr)
54cc8ed4 536 char **pstr;
54cc8ed4
DE
537{
538 long dest = 0;
539
54cc8ed4
DE
540 while (**pstr)
541 {
542 switch (**pstr)
543 {
544 case 'x' : case 'X' : dest |= TXVU_DEST_X; break;
545 case 'y' : case 'Y' : dest |= TXVU_DEST_Y; break;
546 case 'z' : case 'Z' : dest |= TXVU_DEST_Z; break;
547 case 'w' : case 'W' : dest |= TXVU_DEST_W; break;
71af45ec 548 default : return dest;
54cc8ed4
DE
549 }
550 ++*pstr;
551 }
552
71af45ec
DE
553 return dest;
554}
555
556static long
557parse_dotdest (pstr, errmsg)
558 char **pstr;
559 const char **errmsg;
560{
561 long dest;
562
563 if (**pstr != '.')
564 {
565 *errmsg = "missing `.'";
566 return 0;
567 }
568
569 ++*pstr;
570 dest = parse_dest (pstr);
571 if (dest == 0 || isalnum (**pstr))
572 {
573 *errmsg = "invalid `dest'";
574 return 0;
575 }
54cc8ed4
DE
576 *errmsg = NULL;
577 return dest;
578}
579
71af45ec
DE
580static TXVU_INSN
581insert_dotdest (insn, operand, mods, value, errmsg)
582 TXVU_INSN insn;
583 const struct txvu_operand *operand;
584 int mods;
585 long value;
586 const char **errmsg;
587{
588 /* Record the DEST value in use so the register parser can use it. */
589 dest = value;
590 if (errmsg)
591 *errmsg = NULL;
592 return insn |= value << operand->shift;
593}
594
595static long
596extract_dotdest (insn, operand, mods, pinvalid)
597 TXVU_INSN insn;
598 const struct txvu_operand *operand;
599 int mods;
600 int *pinvalid;
601{
602 /* Record the DEST value in use so the register printer can use it. */
603 dest = (insn >> operand->shift) & ((1 << operand->bits) - 1);
604 return dest;
605}
606
54cc8ed4 607static void
71af45ec 608print_dest (info, insn, value)
54cc8ed4
DE
609 disassemble_info *info;
610 TXVU_INSN insn;
611 long value;
612{
54cc8ed4
DE
613 if (value & TXVU_DEST_X)
614 (*info->fprintf_func) (info->stream, "x");
615 if (value & TXVU_DEST_Y)
616 (*info->fprintf_func) (info->stream, "y");
617 if (value & TXVU_DEST_Z)
618 (*info->fprintf_func) (info->stream, "z");
619 if (value & TXVU_DEST_W)
620 (*info->fprintf_func) (info->stream, "w");
621}
71af45ec
DE
622
623static void
624print_dotdest (info, insn, value)
625 disassemble_info *info;
626 TXVU_INSN insn;
627 long value;
628{
629 (*info->fprintf_func) (info->stream, ".");
630 print_dest (info, insn, value);
631}
54cc8ed4
DE
632\f
633static long
71af45ec 634parse_vfreg (pstr, errmsg)
54cc8ed4
DE
635 char **pstr;
636 const char **errmsg;
637{
638 char *str = *pstr;
639 char *start;
640 long reg;
71af45ec 641 int reg_dest;
54cc8ed4
DE
642
643 if (tolower (str[0]) != 'v'
644 || tolower (str[1]) != 'f')
645 {
646 *errmsg = "unknown register";
647 return 0;
648 }
649
650 /* FIXME: quick hack until the framework works. */
651 start = str = str + 2;
652 while (*str && isdigit (*str))
653 ++str;
654 reg = atoi (start);
71af45ec
DE
655 reg_dest = parse_dest (&str);
656 if (reg_dest == 0 || isalnum (*str))
657 {
658 *errmsg = "invalid `dest'";
659 return 0;
660 }
661 if (reg_dest != dest)
662 {
663 *errmsg = "register `dest' does not match instruction `dest'";
664 return 0;
665 }
54cc8ed4
DE
666 *pstr = str;
667 *errmsg = NULL;
668 return reg;
669}
670
671static void
71af45ec 672print_vfreg (info, insn, value)
54cc8ed4
DE
673 disassemble_info *info;
674 TXVU_INSN insn;
675 long value;
676{
677 (*info->fprintf_func) (info->stream, "vf%ld", value);
71af45ec 678 print_dest (info, insn, dest);
54cc8ed4 679}
3f897263
DE
680\f
681/* Broadcast handling. */
682
683static long
684parse_bc (pstr, errmsg)
685 char **pstr;
686 const char **errmsg;
687{
688 long dest = 0;
689
690 switch (**pstr)
691 {
692 case 'x' : case 'X' : dest = TXVU_BC_X; break;
693 case 'y' : case 'Y' : dest = TXVU_BC_Y; break;
694 case 'z' : case 'Z' : dest = TXVU_BC_Z; break;
695 case 'w' : case 'W' : dest = TXVU_BC_W; break;
696 default : *errmsg = "invalid `bc'"; return 0;
697 }
698 ++*pstr;
699
700 *errmsg = NULL;
701 return dest;
702}
703
704static void
705print_bc (info, insn, value)
706 disassemble_info *info;
707 TXVU_INSN insn;
708 long value;
709{
710 char c;
711
712 switch (value)
713 {
714 case TXVU_BC_X : c = 'x' ; break;
715 case TXVU_BC_Y : c = 'y' ; break;
716 case TXVU_BC_Z : c = 'z' ; break;
717 case TXVU_BC_W : c = 'w' ; break;
718 }
719
720 (*info->fprintf_func) (info->stream, "%c", c);
721}
722\f
723/* FT register in broadcast case. */
724
725static long
0b988d39 726parse_bcftreg (pstr, errmsg)
3f897263
DE
727 char **pstr;
728 const char **errmsg;
729{
730 char *str = *pstr;
731 char *start;
732 long reg;
733 int reg_bc;
734
735 if (tolower (str[0]) != 'v'
736 || tolower (str[1]) != 'f')
737 {
738 *errmsg = "unknown register";
739 return 0;
740 }
741
742 /* FIXME: quick hack until the framework works. */
743 start = str = str + 2;
744 while (*str && isdigit (*str))
745 ++str;
746 reg = atoi (start);
747 reg_bc = parse_bc (&str, errmsg);
748 if (*errmsg)
749 return 0;
750 if (reg_bc != bc)
751 {
752 *errmsg = "register `bc' does not match instruction `bc'";
753 return 0;
754 }
755 *pstr = str;
756 *errmsg = NULL;
757 return reg;
758}
759
760static void
0b988d39 761print_bcftreg (info, insn, value)
3f897263
DE
762 disassemble_info *info;
763 TXVU_INSN insn;
764 long value;
765{
766 (*info->fprintf_func) (info->stream, "vf%ld", value);
767 print_bc (info, insn, bc);
768}
769\f
770/* ACC handling. */
771
772static long
773parse_accdest (pstr, errmsg)
774 char **pstr;
775 const char **errmsg;
776{
777 char *str = *pstr;
778 long acc_dest = 0;
779
780 if (strncasecmp (str, "acc", 3) != 0)
781 {
782 *errmsg = "expecting `acc'";
783 return 0;
784 }
785 str += 3;
786 acc_dest = parse_dest (&str);
787 if (acc_dest == 0 || isalnum (*str))
788 {
789 *errmsg = "invalid `dest'";
790 return 0;
791 }
792 if (acc_dest != dest)
793 {
794 *errmsg = "acc `dest' does not match instruction `dest'";
795 return 0;
796 }
797 *pstr = str;
798 *errmsg = NULL;
799 /* Value isn't used, but we must return something. */
800 return 0;
801}
802
803static void
804print_accdest (info, insn, value)
805 disassemble_info *info;
806 TXVU_INSN insn;
807 long value;
808{
809 (*info->fprintf_func) (info->stream, "acc");
810 print_dest (info, insn, value);
811}
812\f
813/* XYZ operand handling.
814 This simplifies the opmula,opmsub entries by keeping them equivalent to
815 the others. */
816
817static long
818parse_xyz (pstr, errmsg)
819 char **pstr;
820 const char **errmsg;
821{
822 if (dest != (TXVU_DEST_X | TXVU_DEST_Y | TXVU_DEST_Z))
823 {
824 *errmsg = "expecting `xyz' for `dest' value";
825 return 0;
826 }
827 return 0;
828}
0b988d39
DE
829\f
830/* F[ST] register using selector in F[ST]F field. */
831
832static long
833parse_ffstreg (pstr, errmsg)
834 char **pstr;
835 const char **errmsg;
836{
837 char *str = *pstr;
838 char *start;
839 long reg;
840 int reg_bc;
841
842 if (tolower (str[0]) != 'v'
843 || tolower (str[1]) != 'f')
844 {
845 *errmsg = "unknown register";
846 return 0;
847 }
848
849 /* FIXME: quick hack until the framework works. */
850 start = str = str + 2;
851 while (*str && isdigit (*str))
852 ++str;
853 reg = atoi (start);
854 reg_bc = parse_bc (&str, errmsg);
855 if (*errmsg)
856 return 0;
857 if (reg_bc != bc)
858 {
859 *errmsg = "register `bc' does not match instruction `bc'";
860 return 0;
861 }
862 *pstr = str;
863 *errmsg = NULL;
864 return reg;
865}
866
867static void
868print_ffstreg (info, insn, value)
869 disassemble_info *info;
870 TXVU_INSN insn;
871 long value;
872{
873 (*info->fprintf_func) (info->stream, "vf%ld", value);
874 print_bc (info, insn, bc);
875}
876
877#define INSERT_FN(fn) \
878static TXVU_INSN CONCAT2 (insert_,fn) \
879 PARAMS ((TXVU_INSN, const struct txvu_operand *, \
880 int, long, const char **))
881#define EXTRACT_FN(fn) \
882static long CONCAT2 (extract_,fn) \
883 PARAMS ((TXVU_INSN, const struct txvu_operand *, \
884 int, int *))
885
886static TXVU_INSN
887insert_ffstreg (insn, operand, mods, value, errmsg)
888 TXVU_INSN insn;
889 const struct txvu_operand *operand;
890 int mods;
891 long value;
892 const char **errmsg;
893{
894}
895
896static long
897extract_ffstreg (insn, operand, mods, pinvalid)
898 TXVU_INSN insn;
899 const struct txvu_operand *operand;
900 int mods;
901 int *pinvalid;
902{
903}
904\f
905/* F register. */
906
907static long
908parse_freg (pstr, errmsg)
909 char **pstr;
910 const char **errmsg;
911{
912 char *str = *pstr;
913 char *start;
914 long reg;
915 int reg_bc;
916
917 if (tolower (str[0]) != 'v'
918 || tolower (str[1]) != 'f')
919 {
920 *errmsg = "unknown register";
921 return 0;
922 }
923
924 /* FIXME: quick hack until the framework works. */
925 start = str = str + 2;
926 while (*str && isdigit (*str))
927 ++str;
928 reg = atoi (start);
929 reg_bc = parse_bc (&str, errmsg);
930 if (*errmsg)
931 return 0;
932 if (reg_bc != bc)
933 {
934 *errmsg = "register `bc' does not match instruction `bc'";
935 return 0;
936 }
937 *pstr = str;
938 *errmsg = NULL;
939 return reg;
940}
941
942static void
943print_freg (info, insn, value)
944 disassemble_info *info;
945 TXVU_INSN insn;
946 long value;
947{
948 (*info->fprintf_func) (info->stream, "vf%ld", value);
949 print_bc (info, insn, bc);
950}
951\f
952/* I register. */
953
954static long
955parse_ireg (pstr, errmsg)
956 char **pstr;
957 const char **errmsg;
958{
959 char *str = *pstr;
960 char *start;
961 long reg;
962 int reg_bc;
963
964 if (tolower (str[0]) != 'v'
965 || tolower (str[1]) != 'f')
966 {
967 *errmsg = "unknown register";
968 return 0;
969 }
970
971 /* FIXME: quick hack until the framework works. */
972 start = str = str + 2;
973 while (*str && isdigit (*str))
974 ++str;
975 reg = atoi (start);
976 reg_bc = parse_bc (&str, errmsg);
977 if (*errmsg)
978 return 0;
979 if (reg_bc != bc)
980 {
981 *errmsg = "register `bc' does not match instruction `bc'";
982 return 0;
983 }
984 *pstr = str;
985 *errmsg = NULL;
986 return reg;
987}
988
989static void
990print_ireg (info, insn, value)
991 disassemble_info *info;
992 TXVU_INSN insn;
993 long value;
994{
995 (*info->fprintf_func) (info->stream, "vf%ld", value);
996 print_bc (info, insn, bc);
997}
998\f
999/* VI01 register. */
1000
1001static long
1002parse_vi01 (pstr, errmsg)
1003 char **pstr;
1004 const char **errmsg;
1005{
1006 char *str = *pstr;
1007 char *start;
1008 long reg;
1009 int reg_bc;
1010
1011 if (tolower (str[0]) != 'v'
1012 || tolower (str[1]) != 'f')
1013 {
1014 *errmsg = "unknown register";
1015 return 0;
1016 }
1017
1018 /* FIXME: quick hack until the framework works. */
1019 start = str = str + 2;
1020 while (*str && isdigit (*str))
1021 ++str;
1022 reg = atoi (start);
1023 reg_bc = parse_bc (&str, errmsg);
1024 if (*errmsg)
1025 return 0;
1026 if (reg_bc != bc)
1027 {
1028 *errmsg = "register `bc' does not match instruction `bc'";
1029 return 0;
1030 }
1031 *pstr = str;
1032 *errmsg = NULL;
1033 return reg;
1034}
1035
1036static void
1037print_vi01 (info, insn, value)
1038 disassemble_info *info;
1039 TXVU_INSN insn;
1040 long value;
1041{
1042 (*info->fprintf_func) (info->stream, "vf%ld", value);
1043 print_bc (info, insn, bc);
1044}
1045\f
1046/* Lower instruction 12 bit immediate. */
1047
1048static TXVU_INSN
1049insert_limm12 (insn, operand, mods, value, errmsg)
1050 TXVU_INSN insn;
1051 const struct txvu_operand *operand;
1052 int mods;
1053 long value;
1054 const char **errmsg;
1055{
1056}
1057
1058static long
1059extract_limm12 (insn, operand, mods, pinvalid)
1060 TXVU_INSN insn;
1061 const struct txvu_operand *operand;
1062 int mods;
1063 int *pinvalid;
1064{
1065}
This page took 0.063321 seconds and 4 git commands to generate.