filename | src/xlat/xir.h |
changeset | 1011:fdd58619b760 |
prev | 1006:3a169c224c12 |
next | 1012:0b8cc74ac83a |
author | nkeynes |
date | Sun Apr 12 07:24:45 2009 +0000 (14 years ago) |
branch | xlat-refactor |
permissions | -rw-r--r-- |
last change | Restructure operand types - rename to forms to avoid conflict for actual data types temporary operands are now a first class form remove explicit types for immediates - now implied by opcode Initial work on promote-source-reg pass |
view | annotate | diff | log | raw |
1 /**
2 * $Id: xir.h 931 2008-10-31 02:57:59Z nkeynes $
3 *
4 * This file defines the translation IR and associated functions.
5 *
6 * Copyright (c) 2009 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #ifndef lxdream_xir_H
20 #define lxdream_xir_H 1
22 #include <stdint.h>
24 /*****************************************************************************
25 *
26 * We use a very simple low-level 2-op instruction form, largely intended to
27 * closely match the x86 ISA to simplify final code generation. Complex
28 * instructions are either broken up into simpler ops, or inserted as
29 * opaque macros. First operand is source, second operand is destination.
30 *
31 * Data types are encoded in the instruction:
32 * Byte (B) 8-bit integer
33 * Word (W) 16-bit integer
34 * Long (L) 32-bit integer
35 * Quad (Q) 64-bit integer
36 * Float (F) 32-bit floating point
37 * Double (D) 64-bit floating point
38 * Vec4 (V) 4x32-bit floating point
39 * Matrix (M) 4x4x32-bit floating point in column-major order
40 * This is not an exhaustive list, but it is sufficient to cover all operations
41 * required for the SH4.
42 *
43 * ALU instructions come in two variants, xxxS which modifies the condition
44 * flags, and the regular xxx version that does not. Implementations are assumed
45 * to have at least the standard NZVC flags available (or will have to fake it)
46 *
47 * Variations in flag behaviour between implementations need to be accounted for
48 * somehow.
49 ****************************************************************************/
51 #define MAX_SOURCE_REGISTER 1023
52 #define MAX_TEMP_REGISTER 511
53 #define MAX_DEST_REGISTER 127
55 /* Preallocated temporaries for convenience */
56 #define REG_TMP0 0
57 #define REG_TMP1 1
58 #define REG_TMP2 2
59 #define REG_TMPQ0 3
60 #define REG_TMPQ1 4
63 /**
64 * Operands are either integer, float, or double, and are either immediate or
65 * assigned to a source-machine register, destination-machine register, or a
66 * temporary register. (All temporaries have to be resolved to a dest-reg before
67 * code generation)
68 */
69 typedef enum {
70 NO_OPERAND = 0,
71 SOURCE_OPERAND =1, // Source (or temp) register
72 DEST_OPERAND =2,
73 TEMP_OPERAND=3,
74 IMMEDIATE_OPERAND=4
75 } xir_operand_form_t;
77 typedef struct xir_operand {
78 xir_operand_form_t form;
79 union {
80 uint32_t i;
81 uint64_t q;
82 float f;
83 double d;
84 void *p;
85 } value;
86 } *xir_operand_t;
88 typedef enum {
89 XTY_LONG = 0, /* 32-bit integer */
90 XTY_QUAD = 1, /* 64-bit integer */
91 XTY_FLOAT = 2, /* 32-bit float */
92 XTY_DOUBLE = 3,/* 64-bit float */
93 XTY_VEC4F = 4,/* 4x 32-bit floats (16 bytes) */
94 XTY_MAT16F = 5,/* 4x4x 32-bit floats (64 bytes) */
95 XTY_PTR = 6, /* Native pointer (of appropriate size) */
96 } xir_type_t;
98 /* Condition codes */
99 typedef enum {
100 CC_TRUE = -1, /* Always */
101 CC_OV = 0, /* Overflow */
102 CC_NO = 1, /* !Overflow */
103 CC_UGE = 2, /* Unsigned greater or equal */
104 CC_ULT = 3, /* Unsigned less than */
105 CC_ULE = 4, /* Unsigned less or equal */
106 CC_UGT = 5, /* Unsigned greater than */
107 CC_EQ = 6, /* Equal */
108 CC_NE = 7, /* !Equal */
109 CC_NEG = 8, /* Negative */
110 CC_POS = 9, /* Not-negative (positive or zero) */
111 CC_SGE = 10,
112 CC_SLT = 11,
113 CC_SLE = 12,
114 CC_SGT = 13
115 } xir_cc_t;
117 #define CC_C CC_ULT
118 #define CC_NC CC_UGE
120 typedef enum {
121 // No operands
122 OP_NOP = 0,
123 OP_BARRIER, // Direction to register allocator - Ensure all state is committed
125 // One operand
126 OP_DEC, /* Decrement and set Z if result == 0 */
127 OP_LD, /* Load flags from reg/imm (1 = condition, 0 = !condition) */
128 OP_ST, /* Set reg to 1 on condition, 0 on !condition */
129 OP_RESTFLAGS, /* Restore flags from register */
130 OP_SAVEFLAGS, /* Save flags into register */
131 OP_ENTER, // Block start - immediate operand is a bitmask of target registers used
132 OP_BRREL,
133 OP_BR,
134 OP_CALL0, // Call function with no arguments or return value
135 OP_OCBI,
136 OP_OCBP,
137 OP_OCBWB,
138 OP_PREF,
140 // Register moves */
141 OP_MOV,
142 OP_MOVQ,
143 OP_MOVV,
144 OP_MOVM,
145 OP_MOVSX8,
146 OP_MOVSX16,
147 OP_MOVSX32,
148 OP_MOVZX8,
149 OP_MOVZX16,
150 OP_MOVZX32,
152 /* ALU */
153 OP_ADD,
154 OP_ADDS,
155 OP_ADDC,
156 OP_ADDCS,
157 OP_AND,
158 OP_ANDS,
159 OP_CMP,
160 OP_DIV, /* Unsigned division */
161 OP_DIVS, /* Unsigned divison and update flags */
162 OP_MUL,
163 OP_MULS,
164 OP_MULQ,
165 OP_MULQS,
166 OP_NEG,
167 OP_NEGS,
168 OP_NOT,
169 OP_NOTS,
170 OP_OR,
171 OP_ORS,
172 OP_RCL,
173 OP_RCR,
174 OP_ROL, /* Rotate left w/o updating flags */
175 OP_ROLS, /* Rotate left, and set carry */
176 OP_ROR, /* Rotate right */
177 OP_RORS, /* Rotate right and set carry */
178 OP_SAR, /* Shift arithmetic right */
179 OP_SARS, /* Shift arithmetic right and set carry */
180 OP_SDIV, /* Signed division */
181 OP_SDIVS, /* Signed division and update flags */
182 OP_SLL, /* Shift logical left */
183 OP_SLLS, /* Shift logical left and set carry */
184 OP_SLR, /* Shift logical right */
185 OP_SLRS, /* Shift logical right and set carry */
186 OP_SUB, /* Subtract, no flags changed/used */
187 OP_SUBS, /* Subtract, flag set on overflow */
188 OP_SUBB, /* Subtract with borrow */
189 OP_SUBBS, /* Subtract with borrow and set carry */
190 OP_SHUFFLE, /* Rearrange bytes according to immediate pattern */
191 OP_TST,
192 OP_XOR,
193 OP_XORS,
195 /* FPU */
196 OP_ABSD,
197 OP_ABSF,
198 OP_ABSV,
199 OP_ADDD,
200 OP_ADDF,
201 OP_ADDV,
202 OP_CMPD,
203 OP_CMPF,
204 OP_DIVD,
205 OP_DIVF,
206 OP_DIVV,
207 OP_MULD,
208 OP_MULF,
209 OP_MULV,
210 OP_NEGD,
211 OP_NEGF,
212 OP_NEGV,
213 OP_SQRTD,
214 OP_SQRTF,
215 OP_SQRTV,
216 OP_RSQRTD,
217 OP_RSQRTF,
218 OP_RSQRTV,
219 OP_SUBD,
220 OP_SUBF,
221 OP_SUBV,
222 OP_DTOF,
223 OP_DTOI,
224 OP_FTOD,
225 OP_FTOI,
226 OP_ITOD,
227 OP_ITOF,
228 OP_SINCOSF,
229 OP_DOTPRODV,
230 OP_MATMULV,
232 // Memory operations - these all indirect through the memory tables.
233 OP_LOADB,
234 OP_LOADBFW,
235 OP_LOADW,
236 OP_LOADL,
237 OP_LOADQ,
238 OP_STOREB,
239 OP_STOREW,
240 OP_STOREL,
241 OP_STOREQ,
242 OP_STORELCA,
244 OP_BRCOND,
245 OP_BRCONDDEL, // Delayed branch - sets newpc rather than pc (and is not a terminator)
246 OP_RAISEME, // imm mask in, reg in - branch to exception if (reg & mask) == 0
247 OP_RAISEMNE, // imm mask in, reg in - branch to exception if (reg & mask) != 0
250 // Native operations
251 OP_CALLLUT, // Call indirect through base pointer (reg) + displacement
252 OP_CALL1, // Call function with single argument and no return value
253 OP_CALLR, // Call function with no arguments and a single return value
254 OP_LOADPTRL,
255 OP_LOADPTRQ,
256 OP_XLAT,
258 /********************** SH4-specific macro operations *************************/
259 /* TODO: These need to be broken down into smaller operations eventually,
260 * especially as some are likely to be partially optimizable. But in the
261 * meantime this at least gets things working
262 */
264 /**
265 * ADDQSAT32 Rm, Rn - 64-bit Add Rm to Rn, saturating to 32-bits if S==1 (per SH4 MAC.W)
266 *
267 * if R_S == 0 ->
268 * Rn += Rm
269 * else ->
270 * if overflow32( Rn + Rm ) ->
271 * Rn = saturate32( Rn + Rm ) | 0x100000000
272 * else ->
273 * Rn += Rm
274 */
275 OP_ADDQSAT32,
277 /**
278 * ADDSAT48 Rm, Rn - 64-bit Add Rm to Rn, saturating to 48-bits if S==1 (per SH4 MAC.L)
279 *
280 * if R_S == 0 ->
281 * Rn += Rm
282 * else ->
283 * if( Rm + Rn > 0x00007FFFFFFFFFFF ) ->
284 * Rn = 0x00007FFFFFFFFFFF
285 * else if( Rm + Rn < 0x0000800000000000 ) ->
286 * Rn = 0x0000800000000000
287 * else ->
288 * Rn += Rm
289 */
290 OP_ADDQSAT48,
292 /**
293 * CMP/STR Rm, Rn - Set T if any byte is the same between Rm and Rn
294 *
295 * Macro expansion:
296 * MOV Rm, %tmp
297 * XOR Rn, %tmp
298 * TEST 0x000000FF, %tmp
299 * TESTne 0x0000FF00, %tmp
300 * TESTne 0x00FF0000, %tmp
301 * TESTne 0xFF000000, %tmp
302 * SETe T
303 *
304 */
305 OP_CMPSTR,
307 /**
308 * DIV1 Rm,Rn performs a single-step division of Rm/Rn, modifying flags
309 * as it goes.
310 *
311 * sign = Rn >> 31
312 * Rn = (Rn << 1) | R_T
313 * If R_Q == R_M -> Rn = Rn - Rm
314 * Else -> Rn = Rn + Rm
315 * R_Q = sign ^ R_M ^ (Rn>>31)
316 * R_T = (R_Q == R_M) ; or newq == (rn>>31)
317 *
318 * Macro expansion:
319 * LDc R_T
320 * RCL 1, Rn
321 * SETc temp
322 * CMP R_Q, R_M
323 * ADDne Rm, Rn
324 * SUBeq Rm, Rn
325 * MOV Rn, R_Q
326 * SHR 31, Rn
327 * XOR temp, R_Q
328 * XOR R_M, R_Q
329 * CMP R_M, R_Q
330 * SETe R_T
331 */
332 OP_DIV1,
334 /**
335 * SHAD Rm, Rn performs an arithmetic shift of Rn as follows:
336 * If Rm >= 0 -> Rn = Rn << (Rm&0x1F)
337 * If Rm < 0 ->
338 * If Rm&0x1F == 0 -> Rn = Rn >> 31
339 * Else -> Rn = Rn >> 32 - (Rm&0x1F)
340 *
341 * CMP 0, Rm
342 * ANDuge 0x1F, Rm
343 * SLLuge Rm, Rn
344 * ORult 0xFFFFFFE0, Rm
345 * NEGult Rm
346 * SARult Rm, Rn ; unmasked shift
347 *
348 */
349 OP_SHAD, // Shift dynamic arithmetic (left or right)
351 /**
352 * SHLD Rm, Rn performs a logical shift of Rn as follows:
353 * If Rm >= 0 -> Rn = Rn << (Rm&0x1F)
354 * If Rm < 0 ->
355 * If Rm&0x1F == 0 -> Rn = 0
356 * Else -> Rn = Rn >> 32 - (Rm&0x1F)
357 */
358 OP_SHLD, // Shift dynamic logical (left or right)
359 } xir_opcode_t;
361 #define MAX_OP0_OPCODE OP_BARRIER
362 #define MAX_OP1_OPCODE OP_PREF
363 #define MAX_OP2_OPCODE OP_SHLD
364 #define NUM_OP0_OPCODES (MAX_OP0_OPCODE+1)
365 #define NUM_OP1_OPCODES (MAX_OP1_OPCODE-MAX_OP0_OPCODE)
366 #define NUM_OP2_OPCODES (MAX_OP2_OPCODE-MAX_OP1_OPCODE)
367 #define MAX_OPCODE (MAX_OP2_OPCODE)
368 #define NUM_OPCODES (MAX_OP2_OPCODE+1)
370 typedef struct xir_op {
371 xir_opcode_t opcode;
372 xir_cc_t cond;
373 struct xir_operand operand[2];
374 struct xir_op *next; /* Next instruction (normal path) - NULL in the case of the last instruction */
375 struct xir_op *prev; /* Previous instruction (normal path) - NULL in the case of the first instruction */
376 struct xir_op *exc; /* Next instruction if the opcode takes an exception - NULL if no exception is possible */
377 } *xir_op_t;
379 /* Defined in xlat/xlat.h */
380 typedef struct xlat_source_machine *xlat_source_machine_t;
381 typedef struct xlat_target_machine *xlat_target_machine_t;
383 typedef struct xir_temp_register {
384 xir_type_t type;
385 uint32_t home_register; /* corresponding source register, or -1 for none */
386 } *xir_temp_register_t;
388 /**
389 * Source data structure. This mainly exists to manage memory for XIR operations
390 */
391 typedef struct xir_basic_block {
392 xir_op_t ir_begin; /* Beginning of code block */
393 xir_op_t ir_end; /* End of code block (Last instruction in code block) */
394 xir_op_t ir_ptr; /* First unallocated instruction in allocation block */
395 xir_op_t ir_alloc_begin; /* Beginning of memory allocation */
396 xir_op_t ir_alloc_end; /* End of allocation */
397 uint32_t pc_begin; /* first instruction */
398 uint32_t pc_end; /* next instruction after end */
399 struct xir_temp_register temp_regs[MAX_TEMP_REGISTER+1]; /* temporary register table */
400 uint32_t next_temp_reg;
401 xlat_source_machine_t source;
402 xlat_target_machine_t target;
403 struct mem_region_fn **address_space; /* source machine memory access table */
404 } *xir_basic_block_t;
406 typedef int xir_offset_t;
408 /**************************** OP Information ******************************/
410 /* Instruction operand modes */
411 #define OPM_NO 0x000000 /* No operands */
412 #define OPM_R 0x000001 /* Single operand, read-only */
413 #define OPM_W 0x000002 /* Single operand, write-only */
414 #define OPM_RW 0x000003 /* Single operand, read-write */
415 #define OPM_R_R 0x000005 /* Two operands, both read-only */
416 #define OPM_R_W 0x000009 /* Two operands, first read-only, second write-only */
417 #define OPM_R_RW 0x00000D /* Two operands, first read-only, second read-write */
418 #define OPM_I_I 0x000000 /* Both operands i32 */
419 #define OPM_Q_Q 0x000110 /* Both operands i64 */
420 #define OPM_I_Q 0x000100 /* i32,i64 operands */
421 #define OPM_Q_I 0x000010 /* i64,i32 operands */
422 #define OPM_F_F 0x000220 /* Both operands float */
423 #define OPM_D_D 0x000330 /* Both operands double */
424 #define OPM_I_F 0x000200 /* i32,float operands */
425 #define OPM_I_D 0x000300 /* i32,double operands */
426 #define OPM_F_I 0x000020 /* float,i32 operands */
427 #define OPM_D_I 0x000030 /* double,i32 operands */
428 #define OPM_F_D 0x000320 /* float,double operands */
429 #define OPM_D_F 0x000230 /* double,float operands */
430 #define OPM_V_V 0x000440 /* vec4,vec4 operands */
431 #define OPM_V_M 0x000540 /* vec4,matrix16 operands */
432 #define OPM_M_M 0x000550 /* mat16,mat16 operands */
433 #define OPM_TR 0x001000 /* Use T */
434 #define OPM_TW 0x002000 /* Set T */
435 #define OPM_TRW 0x003000 /* Use+Set T */
436 #define OPM_EXC 0x004000 /* May raise an exception, clobbers volatiles */
437 #define OPM_CLB 0x008000 /* Clobbers volatile registers */
438 #define OPM_CLBT 0x00C000 /* Clobbers 'temporary regs' but not the full volatile set */
439 #define OPM_TERM 0x010000 /* Terminates block. (Must be final instruction in block) */
441 #define OPM_R_R_TW (OPM_R_R|OPM_TW) /* Read two ops + set flags */
442 #define OPM_R_RW_TR (OPM_R_RW|OPM_TR) /* Read/write + use flags */
443 #define OPM_R_RW_TW (OPM_R_RW|OPM_TW) /* Read/write + set flags */
444 #define OPM_R_RW_TRW (OPM_R_RW|OPM_TRW) /* Read/write + use/set flags */
445 #define OPM_R_W_TW (OPM_R_W|OPM_TW) /* Read/write + set flags */
446 #define OPM_RW_TW (OPM_RW|OPM_TW) /* Read/write single op + set flags */
447 #define OPM_RW_TRW (OPM_RW|OPM_TRW) /* Read/write single op + use/set flags */
448 #define OPM_FRW (OPM_RW|OPM_F_F) /* Read/write single float op */
449 #define OPM_FR_FRW (OPM_R_RW|OPM_F_F) /* Read/write float op pair */
450 #define OPM_FR_FW (OPM_R_W|OPM_F_F) /* Read/write float op pair */
451 #define OPM_FR_FR_TW (OPM_R_R_TW|OPM_F_F) /* Read two float ops + set flags */
452 #define OPM_DRW (OPM_RW|OPM_D_D) /* Read/write single double op */
453 #define OPM_DR_DRW (OPM_R_RW|OPM_D_D) /* Read/write double op pair */
454 #define OPM_DR_DW (OPM_R_W|OPM_D_D) /* Read/write double op pair */
455 #define OPM_VR_VRW (OPM_R_RW|OPM_V_V) /* Vector Read/write double op pair */
456 #define OPM_VR_VW (OPM_R_W|OPM_V_V) /* Vector Read/write double op pair */
457 #define OPM_DR_DR_TW (OPM_R_R_TW|OPM_D_D) /* Read two double ops + set flags */
459 #define OPM_R_W_EXC (OPM_R_W|OPM_EXC) /* Read first, write second, possible exc (typical load) */
460 #define OPM_R_R_EXC (OPM_R_R|OPM_EXC) /* Read first, write second, possible exc (typical store) */
461 #define OPM_R_EXC (OPM_R|OPM_EXC) /* Read-only single op, possible exc (eg pref) */
463 struct xir_opcode_entry {
464 char *name;
465 int mode;
466 };
468 struct xir_symbol_entry {
469 const char *name;
470 void *ptr;
471 };
473 extern const struct xir_opcode_entry XIR_OPCODE_TABLE[];
474 extern const int XIR_OPERAND_SIZE[];
476 #define XOP_REG(op,n) (op->operand[n].value.i)
477 #define XOP_REG1(op) XOP_REG(op,0)
478 #define XOP_REG2(op) XOP_REG(op,1)
479 #define XOP_INT(op,n) (op->operand[n].value.i)
480 #define XOP_QUAD(op,n) (op->operand[n].value.q)
481 #define XOP_FLOAT(op,n) (op->operand[n].value.f)
482 #define XOP_DOUBLE(op,n) (op->operand[n].value.d)
483 #define XOP_PTR(op,n) (op->operand[n].value.p)
485 #define XOP_IS_TERMINATOR(op) (XIR_OPCODE_TABLE[op->opcode].mode & OPM_TERM)
486 #define XOP_HAS_0_OPERANDS(op) ((XIR_OPCODE_TABLE[op->opcode].mode & 0x0F) == 0)
487 #define XOP_HAS_1_OPERAND(op) ((XIR_OPCODE_TABLE[op->opcode].mode & 0x0F) < 4)
488 #define XOP_HAS_2_OPERANDS(op) ((XIR_OPCODE_TABLE[op->opcode].mode & 0x0C) != 0)
489 #define XOP_HAS_EXCEPTION(op) ((XIR_OPCODE_TABLE[op->opcode].mode & 0xC000) == OPM_EXC)
491 #define XOP_READS_OP1(op) (XIR_OPCODE_TABLE[op->opcode].mode & 0x01)
492 #define XOP_WRITES_OP1(op) (XIR_OPCODE_TABLE[op->opcode].mode & 0x02)
493 #define XOP_READS_OP2(op) (XIR_OPCODE_TABLE[op->opcode].mode & 0x04)
494 #define XOP_WRITES_OP2(op) (XIR_OPCODE_TABLE[op->opcode].mode & 0x08)
495 #define XOP_READS_FLAGS(op) ((XIR_OPCODE_TABLE[op->opcode].mode & OPM_TR) || (op->cond != CC_TRUE && op->opcode != OP_LD))
496 #define XOP_WRITES_FLAGS(op) (XIR_OPCODE_TABLE[op->opcode].mode & OPM_TW)
498 #define XOP_READS_REG1(op) (XOP_READS_OP1(op) && XOP_IS_REG(op,0))
499 #define XOP_WRITES_REG1(op) (XOP_WRITES_OP1(op) && XOP_IS_REG(op,0))
500 #define XOP_READS_REG2(op) (XOP_READS_OP2(op) && XOP_IS_REG(op,1))
501 #define XOP_WRITES_REG2(op) (XOP_WRITES_OP2(op) && XOP_IS_REG(op,1))
503 #define XOP_TYPE1(op) ((XIR_OPCODE_TABLE[op->opcode].mode >> 4) & 0x0F)
504 #define XOP_TYPE2(op) ((XIR_OPCODE_TABLE[op->opcode].mode >> 8) & 0x0F)
505 #define XOP_FORM1(op) (op->operand[0].form)
506 #define XOP_FORM2(op) (op->operand[1].form)
507 #define XOP_OPERAND(op,i) (&op->operand[i])
508 #define XOP_OPTYPE(op,n) (n == 0 ? XOP_TYPE1(op) : XOP_TYPE2(op))
509 #define XOP_OPSIZE(op,n) (XIR_OPERAND_SIZE[XOP_OPTYPE(op,n)])
511 #define XOP_IS_SRC(op,n) (op->operand[n].form == SOURCE_OPERAND)
512 #define XOP_IS_DST(op,n) (op->operand[n].form == DEST_OPERAND)
513 #define XOP_IS_TMP(op,n) (op->operand[n].form == TEMP_OPERAND)
514 #define XOP_IS_IMM(op,n) (op->operand[n].form == IMMEDIATE_OPERAND)
515 #define XOP_IS_IMMF(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_FLOAT)
516 #define XOP_IS_IMMD(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_DOUBLE)
517 #define XOP_IS_IMML(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_LONG)
518 #define XOP_IS_IMMQ(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_QUAD)
519 #define XOP_IS_IMMP(op,n) (XOP_IS_IMM(op,n) && XOP_OPTYPE(op,n) == XTY_PTR)
520 #define XOP_IS_REG(op,n) (op->operand[n].form >= SOURCE_OPERAND && op->operand[n].form <= TEMP_OPERAND)
521 #define XOP_IS_FORM(op,t1,t2) (op->operand[0].form == t1 && op->operand[1].form == t2)
523 /******************************* IR Construction ******************************/
525 /**
526 * Clear out a basic block structure, ready for reuse
527 */
528 void xir_clear_basic_block( xir_basic_block_t xbb );
530 /**
531 * Allocate a temporary register of the given type, with given home position
532 * (-1 for a pure temporary)
533 */
534 uint32_t xir_alloc_temp_reg( xir_basic_block_t xbb, xir_type_t type, int home );
536 xir_op_t xir_append_op2( xir_basic_block_t xbb, int op, int arg0form, uint32_t arg0, int arg1form, uint32_t arg1 );
537 xir_op_t xir_append_op2cc( xir_basic_block_t xbb, int op, int cc, int arg0form, uint32_t arg0, int arg1form, uint32_t arg1 );
538 xir_op_t xir_append_float_op2( xir_basic_block_t xbb, int op, float imm1, int arg1form, uint32_t arg1 );
539 xir_op_t xir_append_ptr_op2( xir_basic_block_t xbb, int op, void *arg0, int arg1form, uint32_t arg1 );
542 #define XOP1I( op, arg0 ) xir_append_op2(xbb, op, IMMEDIATE_OPERAND, arg0, NO_OPERAND, 0)
543 #define XOP1S( op, arg0 ) xir_append_op2(xbb, op, SOURCE_OPERAND, arg0, NO_OPERAND, 0)
544 #define XOP1SCC( op, cc, arg0 ) xir_append_op2cc(xbb, op, cc, SOURCE_OPERAND, arg0, NO_OPERAND, 0)
545 #define XOP1T( op, arg0 ) xir_append_op2(xbb, op, TEMP_OPERAND, arg0, NO_OPERAND, 0)
546 #define XOP1TCC( op, cc, arg0 ) xir_append_op2cc(xbb, op, cc, TEMP_OPERAND, arg0, NO_OPERAND, 0)
547 #define XOP2IS( op, arg0, arg1 ) xir_append_op2(xbb, op, IMMEDIATE_OPERAND, arg0, SOURCE_OPERAND, arg1)
548 #define XOP2IT( op, arg0, arg1 ) xir_append_op2(xbb, op, IMMEDIATE_OPERAND, arg0, TEMP_OPERAND, arg1)
549 #define XOP2II( op, arg0, arg1 ) xir_append_op2(xbb, op, IMMEDIATE_OPERAND, arg0, IMMEDIATE_OPERAND, arg1)
550 #define XOP2IICC( op, cc, arg0, arg1 ) xir_append_op2cc(xbb, op, cc, IMMEDIATE_OPERAND, arg0, IMMEDIATE_OPERAND, arg1)
551 #define XOP2SS( op, arg0, arg1 ) xir_append_op2(xbb, op, SOURCE_OPERAND, arg0, SOURCE_OPERAND, arg1)
552 #define XOP2ST( op, arg0, arg1 ) xir_append_op2(xbb, op, SOURCE_OPERAND, arg0, TEMP_OPERAND, arg1)
553 #define XOP2TS( op, arg0, arg1 ) xir_append_op2(xbb, op, TEMP_OPERAND, arg0, SOURCE_OPERAND, arg1)
554 #define XOP2TT( op, arg0, arg1 ) xir_append_op2(xbb, op, TEMP_OPERAND, arg0, TEMP_OPERAND, arg1)
555 #define XOP2CC( op, cc, arg0, arg1 ) xir_append_op2cc(xbb, op, cc, SOURCE_OPERAND, arg0, SOURCE_OPERAND, arg1)
556 #define XOP2FS( op, arg0, arg1 ) xir_append_float_op2(xbb, op, arg0, SOURCE_OPERAND, arg1)
557 #define XOP2PS( op, arg0, arg1 ) xir_append_ptr_op2(xbb, op, arg0, SOURCE_OPERAND, arg1)
558 #define XOP2PT( op, arg0, arg1 ) xir_append_ptr_op2(xbb, op, arg0, TEMP_OPERAND, arg1)
559 #define XOP0( op ) xir_append_op2(xbb, op, NO_OPERAND, 0, NO_OPERAND, 0)
560 #define XOPCALL0( arg0 ) xir_append_ptr_op2(xbb, OP_CALL0, arg0, NO_OPERAND, 0)
561 #define XOPCALL1I( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALL1, arg0, IMMEDIATE_OPERAND, arg1)
562 #define XOPCALL1S( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALL1, arg0, SOURCE_OPERAND, arg1)
563 #define XOPCALL1T( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALL1, arg0, TEMP_OPERAND, arg1)
564 #define XOPCALLRS( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALLR, arg0, SOURCE_OPERAND, arg1)
565 #define XOPCALLRT( arg0, arg1 ) xir_append_ptr_op2(xbb, OP_CALLR, arg0, TEMP_OPERAND, arg1)
567 /**************************** IR Modification ******************************/
569 /**
570 * Insert a new instruction immediately before the given existing inst.
571 */
572 void xir_insert_op( xir_op_t op, xir_op_t before );
574 /**
575 * Insert the block start..end immediately before the given instruction
576 */
577 void xir_insert_block( xir_op_t start, xir_op_t end, xir_op_t before );
579 /**
580 * Remove the specified instruction completely from the block in which it appears.
581 * Note: removing terminators with this method may break the representation.
582 * Op itself is not modified.
583 */
584 void xir_remove_op( xir_op_t op );
586 /**
587 * Apply a shuffle directly to the given operand, and return the result
588 */
589 uint32_t xir_shuffle_imm32( uint32_t shuffle, uint32_t operand );
591 /**
592 * Apply a shuffle transitively to the operation (which must also be a shuffle).
593 * For example, given the sequence
594 * op1: shuffle 0x2134, r12
595 * op2: shuffle 0x3412, r12
596 * xir_trans_shuffle( 0x2134, op2 ) can be used to replace op2 wih
597 * shuffle 0x3421, r12
598 */
599 void xir_shuffle_op( uint32_t shuffle, xir_op_t it );
601 /**
602 * Return the number of instructions that would be emitted by xir_shuffle_lower
603 * for the given instruction (not including the leading nop, if there is one)
604 */
605 int xir_shuffle_lower_size( xir_op_t it );
607 /**
608 * Transform a shuffle instruction into an equivalent sequence of shifts, and
609 * logical operations.
610 * @return the last instruction in the resultant sequence (which may be the
611 * original instruction pointer).
612 */
613 xir_op_t xir_shuffle_lower( xir_basic_block_t xbb, xir_op_t it, int tmp1, int tmp2 );
616 /**************************** Debugging ******************************/
618 /**
619 * Verify the integrity of an IR block - abort with assertion failure on any
620 * errors.
621 */
622 void xir_verify_block( xir_basic_block_t xbb, xir_op_t begin, xir_op_t end );
624 /**
625 * Set the symbol table mappings for target points - also only really for
626 * debugging output.
627 */
628 void xir_set_symbol_table( const struct xir_symbol_entry *symtab );
630 /**
631 * Dump the specified block of IR to stdout
632 */
633 void xir_dump_block( xir_basic_block_t xbb );
636 #endif /* !lxdream_xir_H */
.