2 * Copyright (C) 2009-2012 Marcelina KoĆcielnicka <mwk@0x04.net>
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
33 * Decoding various fields is done by multi-level tables of decode operations.
34 * Fields of a single table entry:
35 * - bitmask of program types for which this entry applies
36 * - value that needs to match
37 * - mask of bits in opcode that need to match the val
38 * - a sequence of 0 to 8 operations to perform if this entry is matched.
40 * Each table is scanned linearly until a matching entry is found, then all
41 * ops in this entry are executed. Length of a table is not checked, so they
42 * need either a terminator showing '???' for unknown stuff, or match all
45 * A single op is supposed to decode some field of the instruction and print
46 * it. In the table, an op is just a function pointer plus a void* that gets
47 * passed to it as an argument. atomtab is an op that descends recursively
48 * into another table to decude a subfield. T(too) is an op shorthand for use
51 * Each op takes five arguments: output file to print to, pointer to the
52 * opcode being decoded, pointer to a mask value of already-used fields,
53 * a free-form void * specified in table entry that called this op, and
54 * allowed program type bitmask.
56 * The mask argument is supposed to detect unknown fields in opcodes: if some
57 * bit in decoded opcode is set, but no op executed along the way claims to
58 * use it, it's probably some unknown field that could totally change the
59 * meaning of instruction and will be printed in bold fucking red to alert
60 * the user. Each op ors in the bitmask that it uses, and after all ops are
61 * executed, main code prints unclaimed bits. This works for fields that can
62 * be used multiple times, like the COND field: it'll be read fine by all ops
63 * that happen to use it, but will be marked red if no op used it, like
64 * an unconditional non-addc non-mov-from-$c insn.
66 * This doesn't work for $a, as there is a special case here: only the first
67 * field using it actually gets its value, next ones just use 0. This is
68 * hacked around by zeroing out the field directly in passed opcode parameter
69 * in the op reading it. This gives proper behavior on stuff like add b32 $r0,
70 * s[$a1+0x4], c0[0x10].
72 * Macros provided for quickly getting the bitfields: BF(...) gets value of
73 * given bitfield and marks it as used in the mask. Args are
74 * given as start bit, size in bits.
76 * Also, two simple ops are provided: N("string") prints a literal to output
77 * and is supposed to be used for instruction names and various modifiers.
78 * OOPS is for unknown encodings,
81 typedef unsigned long long ull
;
83 #define MAXOPLEN (128/64)
89 #define APROTO (struct iasctx *ctx, const void *v, int spos)
90 #define DPROTO (struct disctx *ctx, ull *a, ull *m, const void *v)
94 typedef struct matches
*(*afun
) APROTO
;
95 typedef void (*dfun
) DPROTO
;
113 ull pospreadd
; // <3 xtensa...
145 const struct bitfield
*bf
;
148 const struct sreg
*specials
;
156 const struct bitfield
*idx
;
157 const struct reg
*reg
;
158 const struct rbitfield
*imm
;
159 const struct reg
*reg2
;
161 int postincr
; // nv50dis hack.
168 struct bitfield
*cnt
;
169 struct bitfield
*mask
;
182 struct atom atoms
[32];
196 struct easm_expr
*expr
;
200 * Makes a simple table for checking a single flag.
202 * Arguments: table name, flag position, ops for 0, ops for 1.
205 #define F(n, f, a, b) static struct insn tab ## n[] = {\
206 { 0, 1ull<<(f), a },\
207 { 1ull<<(f), 1ull<<(f), b },\
210 #define F1(n, f, b) static struct insn tab ## n[] = {\
212 { 1ull<<(f), 1ull<<(f), b },\
215 #define F1V(n, v, f, b) static struct insn tab ## n[] = {\
216 { 0, 1ull<<(f), .fmask = v },\
217 { 1ull<<(f), 1ull<<(f), b, .fmask = v },\
221 #define T(x) atomtab_a, atomtab_d, tab ## x
222 struct matches
*atomtab_a APROTO
;
223 void atomtab_d DPROTO
;
225 #define OP1B atomopl_a, atomopl_d, op1blen
226 #define OP2B atomopl_a, atomopl_d, op2blen
227 #define OP3B atomopl_a, atomopl_d, op3blen
228 #define OP4B atomopl_a, atomopl_d, op4blen
229 #define OP5B atomopl_a, atomopl_d, op5blen
230 #define OP6B atomopl_a, atomopl_d, op6blen
231 #define OP8B atomopl_a, atomopl_d, op8blen
232 extern int op1blen
[];
233 extern int op2blen
[];
234 extern int op3blen
[];
235 extern int op4blen
[];
236 extern int op5blen
[];
237 extern int op6blen
[];
238 extern int op8blen
[];
239 struct matches
*atomopl_a APROTO
;
240 void atomopl_d DPROTO
;
242 struct matches
*atomnop_a APROTO
;
243 void atomendmark_d DPROTO
;
244 #define ENDMARK atomnop_a, atomendmark_d, 0
246 struct matches
*atomsestart_a APROTO
;
247 void atomsestart_d DPROTO
;
248 #define SESTART atomsestart_a, atomsestart_d, 0
250 struct matches
*atomseend_a APROTO
;
251 void atomseend_d DPROTO
;
252 #define SEEND atomseend_a, atomseend_d, 0
254 #define N(x) atomname_a, atomname_d, x
255 struct matches
*atomname_a APROTO
;
256 void atomname_d DPROTO
;
257 #define C(x) atomcmd_a, atomcmd_d, x
258 struct matches
*atomcmd_a APROTO
;
259 void atomcmd_d DPROTO
;
261 #define U(x) atomunk_a, atomunk_d, "unk" x
262 #define OOPS atomunk_a, atomunk_d, "???"
263 struct matches
*atomunk_a APROTO
;
264 void atomunk_d DPROTO
;
266 #define DISCARD atomdiscard_a, atomdiscard_d, 0
267 struct matches
*atomdiscard_a APROTO
;
268 void atomdiscard_d DPROTO
;
270 struct matches
*atomimm_a APROTO
;
271 void atomimm_d DPROTO
;
272 #define atomimm atomimm_a, atomimm_d
274 struct matches
*atomrimm_a APROTO
;
275 void atomrimm_d DPROTO
;
276 void atomctarg_d DPROTO
;
277 void atombtarg_d DPROTO
;
278 #define atomrimm atomrimm_a, atomrimm_d
279 #define atombtarg atomrimm_a, atombtarg_d
280 #define atomctarg atomrimm_a, atomctarg_d
282 void atomign_d DPROTO
;
283 #define atomign atomnop_a, atomign_d
285 struct matches
*atomreg_a APROTO
;
286 void atomreg_d DPROTO
;
287 #define atomreg atomreg_a, atomreg_d
289 struct matches
*atommem_a APROTO
;
290 void atommem_d DPROTO
;
291 #define atommem atommem_a, atommem_d
293 struct matches
*atomvec_a APROTO
;
294 void atomvec_d DPROTO
;
295 #define atomvec atomvec_a, atomvec_d
297 struct matches
*atombf_a APROTO
;
298 void atombf_d DPROTO
;
299 #define atombf atombf_a, atombf_d
301 static inline int var_ok(int fmask
, int ptype
, struct varinfo
*varinfo
) {
302 return (!fmask
|| (varinfo
->fmask
[0] & fmask
) == fmask
) && (!ptype
|| (varinfo
->modes
[0] != -1 && ptype
& 1 << varinfo
->modes
[0]));
305 extern struct disisa g80_isa_s
;
306 extern struct disisa gf100_isa_s
;
307 extern struct disisa gk110_isa_s
;
308 extern struct disisa gm107_isa_s
;
309 extern struct disisa ctx_isa_s
;
310 extern struct disisa falcon_isa_s
;
311 extern struct disisa hwsq_isa_s
;
312 extern struct disisa xtensa_isa_s
;
313 extern struct disisa vuc_isa_s
;
314 extern struct disisa macro_isa_s
;
315 extern struct disisa vp1_isa_s
;
316 extern struct disisa vcomp_isa_s
;