9 void get_base_name (char *filename
, char *basename
, size_t len
)
13 temp
= strrchr (filename
, '/');
14 if (temp
) filename
= &temp
[1];
16 strncpy (basename
, filename
, len
- 1);
17 basename
[len
- 1] = '\0';
18 temp
= strchr (basename
, '.');
19 if (temp
) *temp
= '\0';
22 void ident_line (FILE *out
, int size
)
25 for (i
= 0; i
< size
; i
++)
30 void print_subroutine_name (FILE *out
, struct subroutine
*sub
)
33 if (sub
->export
->name
) {
34 fprintf (out
, "%s", sub
->export
->name
);
36 fprintf (out
, "%s_%08X", sub
->export
->libname
, sub
->export
->nid
);
38 } else if (sub
->import
) {
39 if (sub
->import
->name
) {
40 fprintf (out
, "%s", sub
->import
->name
);
42 fprintf (out
, "%s_%08X", sub
->import
->libname
, sub
->import
->nid
);
45 fprintf (out
, "sub_%05X", sub
->begin
->address
);
49 void print_subroutine_declaration (FILE *out
, struct subroutine
*sub
)
52 if (sub
->numregout
> 0)
53 fprintf (out
, "int ");
55 fprintf (out
, "void ");
57 print_subroutine_name (out
, sub
);
60 for (i
= 0; i
< sub
->numregargs
; i
++) {
61 if (i
!= 0) fprintf (out
, ", ");
62 fprintf (out
, "int arg%d", i
+ 1);
67 #define ISSPACE(x) ((x) == '\t' || (x) == '\r' || (x) == '\n' || (x) == '\v' || (x) == '\f')
70 int valid_string (struct prx
*file
, uint32 vaddr
)
72 uint32 off
= prx_translate (file
, vaddr
);
75 for (; off
< file
->size
; off
++) {
76 uint8 ch
= file
->data
[off
];
77 if (ch
== '\t' || ch
== '\r' || ch
== '\n' || ch
== '\v' ||
78 ch
== '\f' || (ch
>= 32 && ch
< 127))
88 void print_string (FILE *out
, struct prx
*file
, uint32 vaddr
)
90 uint32 off
= prx_translate (file
, vaddr
);
93 for (; off
< file
->size
; off
++) {
94 uint8 ch
= file
->data
[off
];
95 if (ch
>= 32 && ch
< 127) {
96 fprintf (out
, "%c", ch
);
99 case '\t': fprintf (out
, "\\t"); break;
100 case '\r': fprintf (out
, "\\r"); break;
101 case '\n': fprintf (out
, "\\n"); break;
102 case '\v': fprintf (out
, "\\v"); break;
103 case '\f': fprintf (out
, "\\f"); break;
113 void print_value (FILE *out
, struct value
*val
)
117 int isstring
= FALSE
;
120 case VAL_CONSTANT
: fprintf (out
, "0x%08X", val
->val
.intval
); break;
122 var
= val
->val
.variable
;
124 case SSAVAR_ARGUMENT
:
125 if (var
->name
.val
.intval
>= REGISTER_GPR_A0
&&
126 var
->name
.val
.intval
<= REGISTER_GPR_T3
) {
127 fprintf (out
, "arg%d", var
->name
.val
.intval
- REGISTER_GPR_A0
+ 1);
129 print_value (out
, &var
->name
);
133 fprintf (out
, "var%d", var
->info
);
135 case SSAVAR_CONSTANT
:
136 file
= var
->def
->block
->sub
->code
->file
;
137 if (var
->def
->status
& OP_STAT_HASRELOC
) {
138 isstring
= valid_string (file
, var
->info
);
141 print_string (out
, file
, var
->info
);
143 fprintf (out
, "0x%08X", var
->info
);
146 if (var
->def
->type
!= OP_MOVE
)
148 print_operation (out
, var
->def
, 0, TRUE
);
149 if (var
->def
->type
!= OP_MOVE
)
153 print_value (out
, &var
->name
);
154 fprintf (out
, "/* Invalid block %d %d */",
155 var
->def
->block
->node
.dfsnum
,
161 if (val
->val
.intval
== REGISTER_HI
) fprintf (out
, "hi");
162 else if (val
->val
.intval
== REGISTER_LO
) fprintf (out
, "lo");
163 else fprintf (out
, "%s", gpr_names
[val
->val
.intval
]);
166 fprintf (out
, "UNK");
171 void print_asm_reglist (FILE *out
, list regs
, int identsize
, int options
)
176 ident_line (out
, identsize
);
177 fprintf (out
, " : ");
179 el
= list_head (regs
);
181 struct value
*val
= element_getvalue (el
);
182 if (el
!= list_head (regs
))
184 fprintf (out
, "\"=r\"(");
185 print_value (out
, val
);
187 el
= element_next (el
);
192 void print_asm (FILE *out
, struct operation
*op
, int identsize
, int options
)
194 struct location
*loc
;
196 ident_line (out
, identsize
);
197 fprintf (out
, "__asm__ (");
198 for (loc
= op
->info
.asmop
.begin
; ; loc
++) {
199 if (loc
!= op
->info
.asmop
.begin
) {
201 ident_line (out
, identsize
);
204 fprintf (out
, "\"%s\"", allegrex_disassemble (loc
->opc
, loc
->address
, FALSE
));
205 if (loc
== op
->info
.asmop
.end
) break;
207 if (list_size (op
->results
) != 0 || list_size (op
->operands
) != 0) {
208 print_asm_reglist (out
, op
->results
, identsize
, options
);
209 if (list_size (op
->operands
) != 0) {
210 print_asm_reglist (out
, op
->operands
, identsize
, options
);
214 fprintf (out
, ");\n");
218 void print_binaryop (FILE *out
, struct operation
*op
, const char *opsymbol
, int options
)
220 if (!(options
& OPTS_DEFERRED
)) {
221 print_value (out
, list_headvalue (op
->results
));
222 fprintf (out
, " = ");
224 print_value (out
, list_headvalue (op
->operands
));
225 fprintf (out
, " %s ", opsymbol
);
226 print_value (out
, list_tailvalue (op
->operands
));
229 void print_complexop (FILE *out
, struct operation
*op
, const char *opsymbol
, int options
)
233 if (list_size (op
->results
) != 0 && !(options
& OPTS_DEFERRED
)) {
234 print_value (out
, list_headvalue (op
->results
));
235 fprintf (out
, " = ");
238 fprintf (out
, "%s (", opsymbol
);
239 el
= list_head (op
->operands
);
242 val
= element_getvalue (el
);
243 if (val
->type
== VAL_SSAVAR
) {
244 if (val
->val
.variable
->type
== SSAVAR_INVALID
) break;
246 if (el
!= list_head (op
->operands
))
248 print_value (out
, val
);
249 el
= element_next (el
);
254 void print_call (FILE *out
, struct operation
*op
, int options
)
258 if (list_size (op
->info
.callop
.retvalues
) != 0 && !(options
& OPTS_DEFERRED
)) {
259 el
= list_head (op
->info
.callop
.retvalues
);
261 print_value (out
, list_tailvalue (op
->results
));
263 el
= element_next (el
);
268 if (op
->block
->info
.call
.calltarget
) {
269 print_subroutine_name (out
, op
->block
->info
.call
.calltarget
);
271 fprintf (out
, "CALL");
276 el
= list_head (op
->info
.callop
.arguments
);
279 val
= element_getvalue (el
);
280 if (val
->type
== VAL_SSAVAR
) {
281 if (val
->val
.variable
->type
== SSAVAR_INVALID
) break;
283 if (el
!= list_head (op
->info
.callop
.arguments
))
285 print_value (out
, val
);
286 el
= element_next (el
);
292 void print_ext (FILE *out
, struct operation
*op
, int options
)
294 struct value
*val1
, *val2
, *val3
;
298 el
= list_head (op
->operands
);
299 val1
= element_getvalue (el
); el
= element_next (el
);
300 val2
= element_getvalue (el
); el
= element_next (el
);
301 val3
= element_getvalue (el
);
303 mask
= 0xFFFFFFFF >> (32 - val3
->val
.intval
);
304 if (!(options
& OPTS_DEFERRED
)) {
305 print_value (out
, list_headvalue (op
->results
));
306 fprintf (out
, " = ");
310 print_value (out
, val1
);
311 fprintf (out
, " >> %d)", val2
->val
.intval
);
312 fprintf (out
, " & 0x%08X", mask
);
316 void print_ins (FILE *out
, struct operation
*op
, int options
)
318 struct value
*val1
, *val2
, *val3
, *val4
;
322 el
= list_head (op
->operands
);
323 val1
= element_getvalue (el
); el
= element_next (el
);
324 val2
= element_getvalue (el
); el
= element_next (el
);
325 val3
= element_getvalue (el
); el
= element_next (el
);
326 val4
= element_getvalue (el
);
328 mask
= 0xFFFFFFFF >> (32 - val4
->val
.intval
);
329 if (!(options
& OPTS_DEFERRED
)) {
330 print_value (out
, list_headvalue (op
->results
));
331 fprintf (out
, " = ");
335 print_value (out
, val2
);
336 fprintf (out
, " & 0x%08X) | (", ~(mask
<< val3
->val
.intval
));
337 print_value (out
, val1
);
338 fprintf (out
, " & 0x%08X)", mask
);
342 void print_nor (FILE *out
, struct operation
*op
, int options
)
344 struct value
*val1
, *val2
;
347 val1
= list_headvalue (op
->operands
);
348 val2
= list_tailvalue (op
->operands
);
350 if (val1
->val
.intval
== 0 || val2
->val
.intval
== 0) {
352 if (val1
->val
.intval
== 0) val1
= val2
;
355 if (!(options
& OPTS_DEFERRED
)) {
356 print_value (out
, list_headvalue (op
->results
));
357 fprintf (out
, " = ");
362 print_value (out
, val1
);
363 fprintf (out
, " | ");
364 print_value (out
, val2
);
368 print_value (out
, val1
);
373 void print_movnz (FILE *out
, struct operation
*op
, int ismovn
, int options
)
375 struct value
*val1
, *val2
, *val3
;
376 struct value
*result
;
379 el
= list_head (op
->operands
);
380 val1
= element_getvalue (el
); el
= element_next (el
);
381 val2
= element_getvalue (el
); el
= element_next (el
);
382 val3
= element_getvalue (el
);
383 result
= list_headvalue (op
->results
);
385 if (!(options
& OPTS_DEFERRED
)) {
386 print_value (out
, result
);
387 fprintf (out
, " = ");
394 print_value (out
, val2
);
395 fprintf (out
, ") ? ");
396 print_value (out
, val1
);
397 fprintf (out
, " : ");
398 print_value (out
, val3
);
402 void print_slt (FILE *out
, struct operation
*op
, int isunsigned
, int options
)
404 struct value
*val1
, *val2
;
405 struct value
*result
;
408 el
= list_head (op
->operands
);
409 val1
= element_getvalue (el
); el
= element_next (el
);
410 val2
= element_getvalue (el
);
411 result
= list_headvalue (op
->results
);
413 if (!(options
& OPTS_DEFERRED
)) {
414 print_value (out
, result
);
415 fprintf (out
, " = ");
420 print_value (out
, val1
);
421 fprintf (out
, " < ");
422 print_value (out
, val2
);
427 void print_signextend (FILE *out
, struct operation
*op
, int isbyte
, int options
)
429 if (!(options
& OPTS_DEFERRED
)) {
430 print_value (out
, list_headvalue (op
->results
));
431 fprintf (out
, " = ");
435 fprintf (out
, "(char) ");
437 fprintf (out
, "(short) ");
439 print_value (out
, list_headvalue (op
->operands
));
443 void print_memory_address (FILE *out
, struct operation
*op
, int size
, int isunsigned
, int options
)
450 if (isunsigned
) type
= "unsigned char *";
451 else type
= "char *";
452 } else if (size
== 1) {
453 if (isunsigned
) type
= "unsigned short *";
454 else type
= "short *";
455 } else if (size
== 2) {
459 val
= list_headvalue (op
->operands
);
460 if (val
->type
== VAL_SSAVAR
) {
461 if (val
->val
.variable
->type
== SSAVAR_CONSTANT
) {
462 address
= val
->val
.variable
->type
;
463 val
= list_tailvalue (op
->operands
);
464 address
+= val
->val
.intval
;
465 fprintf (out
, "*((%s) 0x%08X)", type
, address
);
470 fprintf (out
, "((%s) ", type
);
471 print_value (out
, val
);
472 val
= list_tailvalue (op
->operands
);
473 fprintf (out
, ")[%d]", val
->val
.intval
>> size
);
477 void print_load (FILE *out
, struct operation
*op
, int size
, int isunsigned
, int options
)
479 if (!(options
& OPTS_DEFERRED
)) {
480 print_value (out
, list_headvalue (op
->results
));
481 fprintf (out
, " = ");
483 print_memory_address (out
, op
, size
, isunsigned
, options
);
487 void print_store (FILE *out
, struct operation
*op
, int size
, int isunsigned
, int options
)
489 struct value
*val
= element_getvalue (element_next (list_head (op
->operands
)));
490 print_memory_address (out
, op
, size
, isunsigned
, options
);
491 fprintf (out
, " = ");
492 print_value (out
, val
);
496 void print_condition (FILE *out
, struct operation
*op
, int options
)
498 fprintf (out
, "if (");
499 if (options
& OPTS_REVERSECOND
) fprintf (out
, "!(");
500 print_value (out
, list_headvalue (op
->operands
));
501 switch (op
->info
.iop
.insn
) {
503 fprintf (out
, " != ");
506 fprintf (out
, " == ");
510 fprintf (out
, " >= 0");
513 fprintf (out
, " > 0");
516 fprintf (out
, " <= 0");
520 fprintf (out
, " < 0");
525 if (list_size (op
->operands
) == 2)
526 print_value (out
, list_tailvalue (op
->operands
));
528 if (options
& OPTS_REVERSECOND
) fprintf (out
, ")");
534 void print_operation (FILE *out
, struct operation
*op
, int identsize
, int options
)
536 struct location
*loc
;
537 int nosemicolon
= FALSE
;
539 if (op
->type
== OP_ASM
) {
540 print_asm (out
, op
, identsize
, options
);
544 if (op
->type
== OP_INSTRUCTION
) {
545 if (op
->info
.iop
.loc
->insn
->flags
& (INSN_JUMP
))
547 } else if (op
->type
== OP_NOP
|| op
->type
== OP_START
||
548 op
->type
== OP_END
|| op
->type
== OP_PHI
) {
552 loc
= op
->info
.iop
.loc
;
553 if (op
->type
== OP_INSTRUCTION
) {
554 if (loc
->branchalways
) return;
557 ident_line (out
, identsize
);
558 if (op
->type
== OP_INSTRUCTION
) {
559 switch (op
->info
.iop
.insn
) {
560 case I_ADD
: print_binaryop (out
, op
, "+", options
); break;
561 case I_ADDU
: print_binaryop (out
, op
, "+", options
); break;
562 case I_SUB
: print_binaryop (out
, op
, "-", options
); break;
563 case I_SUBU
: print_binaryop (out
, op
, "-", options
); break;
564 case I_XOR
: print_binaryop (out
, op
, "^", options
); break;
565 case I_AND
: print_binaryop (out
, op
, "&", options
); break;
566 case I_OR
: print_binaryop (out
, op
, "|", options
); break;
567 case I_SRAV
: print_binaryop (out
, op
, ">>", options
); break;
568 case I_SRLV
: print_binaryop (out
, op
, ">>", options
); break;
569 case I_SLLV
: print_binaryop (out
, op
, "<<", options
); break;
570 case I_INS
: print_ins (out
, op
, options
); break;
571 case I_EXT
: print_ext (out
, op
, options
); break;
572 case I_MIN
: print_complexop (out
, op
, "MIN", options
); break;
573 case I_MAX
: print_complexop (out
, op
, "MAX", options
); break;
574 case I_BITREV
: print_complexop (out
, op
, "BITREV", options
); break;
575 case I_CLZ
: print_complexop (out
, op
, "CLZ", options
); break;
576 case I_CLO
: print_complexop (out
, op
, "CLO", options
); break;
577 case I_NOR
: print_nor (out
, op
, options
); break;
578 case I_MOVN
: print_movnz (out
, op
, TRUE
, options
); break;
579 case I_MOVZ
: print_movnz (out
, op
, FALSE
, options
); break;
580 case I_SLT
: print_slt (out
, op
, FALSE
, options
); break;
581 case I_SLTU
: print_slt (out
, op
, TRUE
, options
); break;
582 case I_LW
: print_load (out
, op
, 2, FALSE
, options
); break;
583 case I_LB
: print_load (out
, op
, 0, FALSE
, options
); break;
584 case I_LBU
: print_load (out
, op
, 0, TRUE
, options
); break;
585 case I_LH
: print_load (out
, op
, 1, FALSE
, options
); break;
586 case I_LHU
: print_load (out
, op
, 1, TRUE
, options
); break;
587 case I_LL
: print_complexop (out
, op
, "LL", options
); break;
588 case I_LWL
: print_complexop (out
, op
, "LWL", options
); break;
589 case I_LWR
: print_complexop (out
, op
, "LWR", options
); break;
590 case I_SW
: print_store (out
, op
, 2, FALSE
, options
); break;
591 case I_SH
: print_store (out
, op
, 1, FALSE
, options
); break;
592 case I_SB
: print_store (out
, op
, 0, FALSE
, options
); break;
593 case I_SC
: print_complexop (out
, op
, "SC", options
); break;
594 case I_SWL
: print_complexop (out
, op
, "SWL", options
); break;
595 case I_SWR
: print_complexop (out
, op
, "SWR", options
); break;
596 case I_SEB
: print_signextend (out
, op
, TRUE
, options
); break;
597 case I_SEH
: print_signextend (out
, op
, TRUE
, options
); break;
599 if (loc
->insn
->flags
& INSN_BRANCH
) {
600 print_condition (out
, op
, options
);
605 } else if (op
->type
== OP_MOVE
) {
607 print_value (out
, list_headvalue (op
->results
));
608 fprintf (out
, " = ");
610 print_value (out
, list_headvalue (op
->operands
));
611 } else if (op
->type
== OP_CALL
) {
612 print_call (out
, op
, options
);
615 if (!(options
& OPTS_DEFERRED
)) {
616 if (nosemicolon
) fprintf (out
, "\n");
617 else fprintf (out
, ";\n");