Merge pull request #218 from saper/build-fixes
[envytools.git] / envydis / dis-intern.h
blobd1ef49a51ca2f43c4f8d150da2abe75aca949795
1 /*
2 * Copyright (C) 2009-2012 Marcelina Koƛcielnicka <mwk@0x04.net>
3 * All Rights Reserved.
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
14 * Software.
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.
25 #ifndef DIS_INTERN_H
26 #define DIS_INTERN_H
28 #include "dis.h"
31 * Table format
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
43 * possible values.
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
49 * in tables.
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)
85 struct iasctx;
86 struct disctx;
87 struct disisa;
89 #define APROTO (struct iasctx *ctx, const void *v, int spos)
90 #define DPROTO (struct disctx *ctx, ull *a, ull *m, const void *v)
92 struct matches;
94 typedef struct matches *(*afun) APROTO;
95 typedef void (*dfun) DPROTO;
97 struct sbf {
98 int pos;
99 int len;
102 struct rbitfield {
103 struct sbf sbf[2];
104 enum {
105 RBF_UNSIGNED,
106 RBF_SIGNED,
107 RBF_SLIGHTLY_SIGNED,
108 RBF_ULTRASIGNED,
109 } mode;
110 int shr;
111 int pcrel;
112 ull addend;
113 ull pospreadd; // <3 xtensa...
114 int wrapok;
117 struct bitfield {
118 struct sbf sbf[2];
119 enum {
120 BF_UNSIGNED,
121 BF_SIGNED,
122 BF_SLIGHTLY_SIGNED,
123 BF_ULTRASIGNED,
124 BF_LUT,
125 } mode;
126 int shr;
127 ull addend;
128 ull *lut;
129 ull xorend;
132 struct sreg {
133 int num;
134 const char *name;
135 enum {
136 SR_NAMED,
137 SR_ZERO,
138 SR_ONE,
139 SR_DISCARD,
140 } mode;
141 int fmask;
144 struct reg {
145 const struct bitfield *bf;
146 const char *name;
147 const char *suffix;
148 const struct sreg *specials;
149 int always_special;
150 int hilo;
151 int cool;
154 struct mem {
155 const char *name;
156 const struct bitfield *idx;
157 const struct reg *reg;
158 const struct rbitfield *imm;
159 const struct reg *reg2;
160 int reg2shr;
161 int postincr; // nv50dis hack.
162 int literal;
165 struct vec {
166 char *name;
167 struct bitfield *bf;
168 struct bitfield *cnt;
169 struct bitfield *mask;
170 int cool;
173 struct atom {
174 afun fun_as;
175 dfun fun_dis;
176 const void *arg;
179 struct insn {
180 ull val;
181 ull mask;
182 struct atom atoms[32];
183 int fmask;
184 int ptype;
187 struct litem {
188 enum etype {
189 LITEM_NAME,
190 LITEM_EXPR,
191 LITEM_SESTART,
192 LITEM_SEEND,
193 } type;
194 char *str;
195 int isunk;
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 },\
208 { 0, 0, OOPS },\
210 #define F1(n, f, b) static struct insn tab ## n[] = {\
211 { 0, 1ull<<(f) },\
212 { 1ull<<(f), 1ull<<(f), b },\
213 { 0, 0, OOPS },\
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 },\
218 { 0, 0 },\
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;
318 #endif