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
;
199 uint32 asm_gen
[NUM_REGMASK
], asm_kill
[NUM_REGMASK
];
200 int i
, regno
, lastasm
, relocnum
;
203 file
= sub
->code
->file
;
204 el
= list_head (sub
->blocks
);
206 block
= element_getvalue (el
);
207 block
->operations
= list_alloc (sub
->code
->lstpool
);
209 for (i
= 0; i
< NUM_REGMASK
; i
++)
210 block
->reg_gen
[i
] = block
->reg_kill
[i
] = 0;
212 switch (block
->type
) {
215 relocnum
= prx_findrelocbyaddr (file
, block
->info
.simple
.begin
->address
);
217 for (i
= 0; i
< NUM_REGMASK
; i
++)
218 asm_gen
[i
] = asm_kill
[i
] = 0;
220 for (loc
= block
->info
.simple
.begin
; ; loc
++) {
221 int hasreloc
= FALSE
;
223 if (relocnum
< file
->relocnum
) {
224 if (file
->relocsbyaddr
[relocnum
].vaddr
== loc
->address
) {
230 if (INSN_TYPE (loc
->insn
->flags
) == INSN_ALLEGREX
) {
231 enum allegrex_insn insn
;
234 list_inserttail (block
->operations
, op
);
237 op
= operation_alloc (block
);
238 op
->type
= OP_INSTRUCTION
;
240 op
->status
|= OP_STAT_HASRELOC
;
241 op
->info
.iop
.loc
= loc
;
243 if (loc
->insn
->flags
& INSN_READ_GPR_S
) {
244 regno
= RS (loc
->opc
);
246 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
249 if (loc
->insn
->flags
& INSN_READ_GPR_T
) {
250 regno
= RT (loc
->opc
);
252 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
255 if (loc
->insn
->flags
& INSN_READ_GPR_D
) {
256 regno
= RD (loc
->opc
);
258 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
261 if (loc
->insn
->flags
& INSN_READ_LO
) {
264 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
267 if (loc
->insn
->flags
& INSN_READ_HI
) {
270 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
273 if (loc
->insn
->flags
& (INSN_LOAD
| INSN_STORE
)) {
274 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
277 switch (loc
->insn
->insn
) {
280 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
284 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
288 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMMU (loc
->opc
));
292 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMMU (loc
->opc
));
296 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMMU (loc
->opc
));
300 value_append (sub
, op
->operands
, VAL_CONSTANT
, ((unsigned int) IMMU (loc
->opc
)) << 16);
304 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
308 value_append (sub
, op
->operands
, VAL_CONSTANT
, IMM (loc
->opc
));
312 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
313 value_append (sub
, op
->operands
, VAL_CONSTANT
, RD (loc
->opc
) + 1);
317 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
318 value_append (sub
, op
->operands
, VAL_CONSTANT
, RD (loc
->opc
) - SA (loc
->opc
) + 1);
322 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
326 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
330 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
334 value_append (sub
, op
->operands
, VAL_CONSTANT
, SA (loc
->opc
));
358 insn
= loc
->insn
->insn
;
360 op
->info
.iop
.insn
= insn
;
362 if (loc
->insn
->flags
& INSN_WRITE_GPR_T
) {
363 regno
= RT (loc
->opc
);
365 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
368 if (loc
->insn
->flags
& INSN_WRITE_GPR_D
) {
369 regno
= RD (loc
->opc
);
371 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
374 if (loc
->insn
->flags
& INSN_WRITE_LO
) {
377 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
380 if (loc
->insn
->flags
& INSN_WRITE_HI
) {
383 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
386 if (loc
->insn
->flags
& INSN_LINK
) {
387 regno
= REGISTER_GPR_RA
;
389 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
392 simplify_operation (op
);
393 list_inserttail (block
->operations
, op
);
397 op
= operation_alloc (block
);
398 op
->info
.asmop
.begin
= op
->info
.asmop
.end
= loc
;
400 for (i
= 0; i
< NUM_REGMASK
; i
++)
401 asm_gen
[i
] = asm_kill
[i
] = 0;
403 op
->info
.asmop
.end
= loc
;
407 if (loc
->insn
->flags
& INSN_READ_LO
) {
412 if (loc
->insn
->flags
& INSN_READ_HI
) {
417 if (loc
->insn
->flags
& INSN_READ_GPR_D
) {
418 regno
= RD (loc
->opc
);
422 if (loc
->insn
->flags
& INSN_READ_GPR_T
) {
423 regno
= RT (loc
->opc
);
427 if (loc
->insn
->flags
& INSN_READ_GPR_S
) {
428 regno
= RS (loc
->opc
);
432 if (loc
->insn
->flags
& INSN_WRITE_GPR_T
) {
433 regno
= RT (loc
->opc
);
437 if (loc
->insn
->flags
& INSN_WRITE_GPR_D
) {
438 regno
= RD (loc
->opc
);
442 if (loc
->insn
->flags
& INSN_WRITE_LO
) {
447 if (loc
->insn
->flags
& INSN_WRITE_HI
) {
452 if (loc
->insn
->flags
& INSN_LINK
) {
453 regno
= REGISTER_GPR_RA
;
458 if (loc
== block
->info
.simple
.end
) {
460 list_inserttail (block
->operations
, op
);
467 op
= operation_alloc (block
);
469 op
->info
.callop
.arguments
= list_alloc (sub
->code
->lstpool
);
470 op
->info
.callop
.retvalues
= list_alloc (sub
->code
->lstpool
);
471 list_inserttail (block
->operations
, op
);
473 for (regno
= 1; regno
<= NUM_REGISTERS
; regno
++) {
474 if (IS_BIT_SET (regmask_call_gen
, regno
)) {
476 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
478 if (IS_BIT_SET (regmask_call_kill
, regno
)) {
480 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
486 op
= operation_alloc (block
);
489 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
491 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
493 list_inserttail (block
->operations
, op
);
497 op
= operation_alloc (block
);
500 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
501 if (IS_BIT_SET (regmask_subend_gen
, regno
)) {
503 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
507 list_inserttail (block
->operations
, op
);
511 el
= element_next (el
);
516 void fixup_call_arguments (struct subroutine
*sub
)
518 struct operation
*op
;
519 struct basicblock
*block
;
524 el
= list_head (sub
->blocks
);
526 block
= element_getvalue (el
);
527 if (block
->type
== BLOCK_CALL
) {
528 struct subroutine
*target
;
529 op
= list_tailvalue (block
->operations
);
530 target
= block
->info
.call
.calltarget
;
532 regend
= REGISTER_GPR_T4
;
534 if (target
->numregargs
!= -1)
535 regend
= REGISTER_GPR_A0
+ target
->numregargs
;
537 for (regno
= REGISTER_GPR_A0
; regno
< regend
; regno
++) {
538 val
= value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
539 list_inserttail (op
->info
.callop
.arguments
, val
);
542 if (target
) regend
= REGISTER_GPR_V0
+ target
->numregout
;
543 else regend
= REGISTER_GPR_A0
;
545 for (regno
= REGISTER_GPR_V0
; regno
< regend
; regno
++) {
546 val
= value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
547 list_inserttail (op
->info
.callop
.retvalues
, val
);
550 el
= element_next (el
);
554 void remove_call_arguments (struct subroutine
*sub
)
556 struct operation
*op
;
557 struct basicblock
*block
;
561 el
= list_head (sub
->blocks
);
563 block
= element_getvalue (el
);
564 if (block
->type
== BLOCK_CALL
) {
565 op
= list_tailvalue (block
->operations
);
566 while (list_size (op
->info
.callop
.arguments
) != 0) {
567 val
= list_removetail (op
->info
.callop
.arguments
);
568 list_removetail (op
->operands
);
569 fixedpool_free (sub
->code
->valspool
, val
);
571 while (list_size (op
->info
.callop
.retvalues
) != 0) {
572 val
= list_removetail (op
->info
.callop
.retvalues
);
573 list_removetail (op
->results
);
574 fixedpool_free (sub
->code
->valspool
, val
);
577 el
= element_next (el
);