6 const uint32 regmask_call_gen
[NUM_REGMASK
] = { 0xAC000000, 0x00000000 };
7 const uint32 regmask_call_kill
[NUM_REGMASK
] = { 0x0300FFFE, 0x00000003 };
8 const uint32 regmask_subend_gen
[NUM_REGMASK
] = { 0xF0FF0000, 0x00000000 };
11 #define BLOCK_GPR_KILL() \
13 BIT_SET (block->reg_kill, regno); \
16 #define BLOCK_GPR_GEN() \
17 if (!IS_BIT_SET (block->reg_kill, regno) && regno != 0 && \
18 !IS_BIT_SET (block->reg_gen, regno)) { \
19 BIT_SET (block->reg_gen, regno); \
22 #define ASM_GPR_KILL() \
24 if (!IS_BIT_SET (asm_kill, regno) && regno != 0) { \
25 BIT_SET (asm_kill, regno); \
26 value_append (sub, op->results, VAL_REGISTER, regno); \
29 #define ASM_GPR_GEN() \
31 if (!IS_BIT_SET (asm_kill, regno) && regno != 0 && \
32 !IS_BIT_SET (asm_gen, regno)) { \
33 BIT_SET (asm_gen, regno); \
34 value_append (sub, op->operands, VAL_REGISTER, regno); \
38 struct operation
*operation_alloc (struct basicblock
*block
)
41 struct code
*c
= block
->sub
->code
;
43 op
= fixedpool_alloc (c
->opspool
);
45 op
->operands
= list_alloc (c
->lstpool
);
46 op
->results
= list_alloc (c
->lstpool
);
51 void reset_operation (struct operation
*op
)
54 struct code
*c
= op
->block
->sub
->code
;
56 while (list_size (op
->results
)) {
57 val
= list_removehead (op
->results
);
58 fixedpool_free (c
->valspool
, val
);
61 while (list_size (op
->operands
)) {
62 val
= list_removehead (op
->operands
);
63 fixedpool_free (c
->valspool
, val
);
68 void simplify_reg_zero (list l
)
75 val
= element_getvalue (el
);
76 if (val
->type
== VAL_REGISTER
&& val
->val
.intval
== 0) {
77 val
->type
= VAL_CONSTANT
;
79 el
= element_next (el
);
84 void simplify_operation (struct operation
*op
)
87 struct code
*c
= op
->block
->sub
->code
;
89 if (op
->type
!= OP_INSTRUCTION
) return;
91 if (list_size (op
->results
) == 1 && !(op
->info
.iop
.loc
->insn
->flags
& (INSN_LOAD
| INSN_JUMP
))) {
92 val
= list_headvalue (op
->results
);
93 if (val
->val
.intval
== 0) {
99 simplify_reg_zero (op
->results
);
100 simplify_reg_zero (op
->operands
);
102 switch (op
->info
.iop
.insn
) {
107 val
= list_headvalue (op
->operands
);
108 if (val
->val
.intval
== 0) {
109 val
= list_removehead (op
->operands
);
110 fixedpool_free (c
->valspool
, val
);
113 val
= list_tailvalue (op
->operands
);
114 if (val
->val
.intval
== 0) {
115 val
= list_removetail (op
->operands
);
116 fixedpool_free (c
->valspool
, val
);
122 val
= list_headvalue (op
->operands
);
123 if (val
->val
.intval
== 0) {
124 val
= list_removetail (op
->operands
);
125 fixedpool_free (c
->valspool
, val
);
128 val
= list_tailvalue (op
->operands
);
129 if (val
->val
.intval
== 0) {
130 val
= list_removehead (op
->operands
);
131 fixedpool_free (c
->valspool
, val
);
142 val
= list_headvalue (op
->operands
);
143 if (val
->val
.intval
== 0) {
153 val
= list_tailvalue (op
->operands
);
154 if (val
->val
.intval
== 0) {
155 val
= list_removetail (op
->operands
);
156 fixedpool_free (c
->valspool
, val
);
160 val
= element_getvalue (element_next (list_head (op
->operands
)));
161 if (val
->val
.intval
== 0) {
162 reset_operation (op
);
167 val
= element_getvalue (element_next (list_head (op
->operands
)));
168 if (val
->val
.intval
== 0) {
169 val
= list_removetail (op
->operands
);
170 fixedpool_free (c
->valspool
, val
);
171 val
= list_removetail (op
->operands
);
172 fixedpool_free (c
->valspool
, val
);
183 struct value
*value_append (struct subroutine
*sub
, list l
, enum valuetype type
, uint32 value
)
186 val
= fixedpool_alloc (sub
->code
->valspool
);
188 val
->val
.intval
= value
;
189 list_inserttail (l
, val
);
193 void extract_operations (struct subroutine
*sub
)
195 struct operation
*op
;
196 struct basicblock
*block
;
197 struct location
*loc
;
198 uint32 asm_gen
[NUM_REGMASK
], asm_kill
[NUM_REGMASK
];
199 int i
, regno
, lastasm
;
202 el
= list_head (sub
->blocks
);
204 block
= element_getvalue (el
);
205 block
->operations
= list_alloc (sub
->code
->lstpool
);
207 for (i
= 0; i
< NUM_REGMASK
; i
++)
208 block
->reg_gen
[i
] = block
->reg_kill
[i
] = 0;
210 switch (block
->type
) {
213 for (i
= 0; i
< NUM_REGMASK
; i
++)
214 asm_gen
[i
] = asm_kill
[i
] = 0;
216 for (loc
= block
->info
.simple
.begin
; ; loc
++) {
217 if (INSN_TYPE (loc
->insn
->flags
) == INSN_ALLEGREX
) {
218 enum allegrex_insn insn
;
221 list_inserttail (block
->operations
, op
);
224 op
= operation_alloc (block
);
225 op
->type
= OP_INSTRUCTION
;
226 op
->info
.iop
.loc
= loc
;
228 if (loc
->insn
->flags
& INSN_READ_GPR_S
) {
229 regno
= RS (loc
->opc
);
231 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
234 if (loc
->insn
->flags
& INSN_READ_GPR_T
) {
235 regno
= RT (loc
->opc
);
237 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
240 if (loc
->insn
->flags
& INSN_READ_GPR_D
) {
241 regno
= RD (loc
->opc
);
243 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
246 if (loc
->insn
->flags
& INSN_READ_LO
) {
249 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
252 if (loc
->insn
->flags
& INSN_READ_HI
) {
255 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
258 if (loc
->insn
->flags
& (INSN_LOAD
| INSN_STORE
)) {
259 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
262 switch (loc
->insn
->insn
) {
265 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
269 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
273 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMMU (loc
->opc
));
277 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMMU (loc
->opc
));
281 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMMU (loc
->opc
));
285 value_append (sub
, op
->operands
, VAL_CONSTANT
, ((unsigned int) IMMU (loc
->opc
)) << 16);
289 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
293 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
297 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
298 value_append (sub
, op
->operands
, VAL_CONSTANT
, RD (loc
->opc
) + 1);
302 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
303 value_append (sub
, op
->operands
, VAL_CONSTANT
, RD (loc
->opc
) - SA (loc
->opc
) + 1);
307 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
311 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
315 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
319 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
343 insn
= loc
->insn
->insn
;
345 op
->info
.iop
.insn
= insn
;
347 if (loc
->insn
->flags
& INSN_WRITE_GPR_T
) {
348 regno
= RT (loc
->opc
);
350 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
353 if (loc
->insn
->flags
& INSN_WRITE_GPR_D
) {
354 regno
= RD (loc
->opc
);
356 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
359 if (loc
->insn
->flags
& INSN_WRITE_LO
) {
362 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
365 if (loc
->insn
->flags
& INSN_WRITE_HI
) {
368 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
371 if (loc
->insn
->flags
& INSN_LINK
) {
372 regno
= REGISTER_GPR_RA
;
374 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
377 simplify_operation (op
);
378 list_inserttail (block
->operations
, op
);
382 op
= operation_alloc (block
);
383 op
->info
.asmop
.begin
= op
->info
.asmop
.end
= loc
;
385 for (i
= 0; i
< NUM_REGMASK
; i
++)
386 asm_gen
[i
] = asm_kill
[i
] = 0;
388 op
->info
.asmop
.end
= loc
;
392 if (loc
->insn
->flags
& INSN_READ_LO
) {
397 if (loc
->insn
->flags
& INSN_READ_HI
) {
402 if (loc
->insn
->flags
& INSN_READ_GPR_D
) {
403 regno
= RD (loc
->opc
);
407 if (loc
->insn
->flags
& INSN_READ_GPR_T
) {
408 regno
= RT (loc
->opc
);
412 if (loc
->insn
->flags
& INSN_READ_GPR_S
) {
413 regno
= RS (loc
->opc
);
417 if (loc
->insn
->flags
& INSN_WRITE_GPR_T
) {
418 regno
= RT (loc
->opc
);
422 if (loc
->insn
->flags
& INSN_WRITE_GPR_D
) {
423 regno
= RD (loc
->opc
);
427 if (loc
->insn
->flags
& INSN_WRITE_LO
) {
432 if (loc
->insn
->flags
& INSN_WRITE_HI
) {
437 if (loc
->insn
->flags
& INSN_LINK
) {
438 regno
= REGISTER_GPR_RA
;
443 if (loc
== block
->info
.simple
.end
) {
445 list_inserttail (block
->operations
, op
);
452 op
= operation_alloc (block
);
454 op
->info
.callop
.arguments
= list_alloc (sub
->code
->lstpool
);
455 op
->info
.callop
.retvalues
= list_alloc (sub
->code
->lstpool
);
456 list_inserttail (block
->operations
, op
);
458 for (regno
= 1; regno
<= NUM_REGISTERS
; regno
++) {
459 if (IS_BIT_SET (regmask_call_gen
, regno
)) {
461 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
463 if (IS_BIT_SET (regmask_call_kill
, regno
)) {
465 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
471 op
= operation_alloc (block
);
474 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
476 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
478 list_inserttail (block
->operations
, op
);
482 op
= operation_alloc (block
);
485 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
486 if (IS_BIT_SET (regmask_subend_gen
, regno
)) {
488 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
492 list_inserttail (block
->operations
, op
);
496 el
= element_next (el
);
501 void fixup_call_arguments (struct subroutine
*sub
)
503 struct operation
*op
;
504 struct basicblock
*block
;
509 el
= list_head (sub
->blocks
);
511 block
= element_getvalue (el
);
512 if (block
->type
== BLOCK_CALL
) {
513 struct subroutine
*target
;
514 op
= list_tailvalue (block
->operations
);
515 target
= block
->info
.call
.calltarget
;
517 regend
= REGISTER_GPR_T4
;
519 if (target
->numregargs
!= -1)
520 regend
= REGISTER_GPR_A0
+ target
->numregargs
;
522 for (regno
= REGISTER_GPR_A0
; regno
< regend
; regno
++) {
523 val
= value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
524 list_inserttail (op
->info
.callop
.arguments
, val
);
527 if (target
) regend
= REGISTER_GPR_V0
+ target
->numregout
;
528 else regend
= REGISTER_GPR_A0
;
530 for (regno
= REGISTER_GPR_V0
; regno
< regend
; regno
++) {
531 val
= value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
532 list_inserttail (op
->info
.callop
.retvalues
, val
);
535 el
= element_next (el
);
539 void remove_call_arguments (struct subroutine
*sub
)
541 struct operation
*op
;
542 struct basicblock
*block
;
546 el
= list_head (sub
->blocks
);
548 block
= element_getvalue (el
);
549 if (block
->type
== BLOCK_CALL
) {
550 op
= list_tailvalue (block
->operations
);
551 while (list_size (op
->info
.callop
.arguments
) != 0) {
552 val
= list_removetail (op
->info
.callop
.arguments
);
553 list_removetail (op
->operands
);
554 fixedpool_free (sub
->code
->valspool
, val
);
556 while (list_size (op
->info
.callop
.retvalues
) != 0) {
557 val
= list_removetail (op
->info
.callop
.retvalues
);
558 list_removetail (op
->results
);
559 fixedpool_free (sub
->code
->valspool
, val
);
562 el
= element_next (el
);