2 * Author: Humberto Naves (hsnaves@gmail.com)
12 void get_base_name (char *filename
, char *basename
, size_t len
)
16 temp
= strrchr (filename
, '/');
17 if (temp
) filename
= &temp
[1];
19 strncpy (basename
, filename
, len
- 1);
20 basename
[len
- 1] = '\0';
21 temp
= strchr (basename
, '.');
22 if (temp
) *temp
= '\0';
25 void ident_line (FILE *out
, int size
)
28 for (i
= 0; i
< size
; i
++)
33 void print_subroutine_name (FILE *out
, struct subroutine
*sub
)
36 if (sub
->export
->name
) {
37 fprintf (out
, "%s", sub
->export
->name
);
39 fprintf (out
, "%s_%08X", sub
->export
->libname
, sub
->export
->nid
);
41 } else if (sub
->import
) {
42 if (sub
->import
->name
) {
43 fprintf (out
, "%s", sub
->import
->name
);
45 fprintf (out
, "%s_%08X", sub
->import
->libname
, sub
->import
->nid
);
48 fprintf (out
, "sub_%05X", sub
->begin
->address
);
52 void print_subroutine_declaration (FILE *out
, struct subroutine
*sub
)
55 if (sub
->numregout
> 0)
56 fprintf (out
, "int ");
58 fprintf (out
, "void ");
60 print_subroutine_name (out
, sub
);
63 for (i
= 0; i
< sub
->numregargs
; i
++) {
64 if (i
!= 0) fprintf (out
, ", ");
65 fprintf (out
, "int arg%d", i
+ 1);
70 #define ISSPACE(x) ((x) == '\t' || (x) == '\r' || (x) == '\n' || (x) == '\v' || (x) == '\f')
73 int valid_string (struct prx
*file
, uint32 vaddr
)
75 uint32 off
= prx_translate (file
, vaddr
);
78 for (; off
< file
->size
; off
++) {
79 uint8 ch
= file
->data
[off
];
80 if (ch
== '\t' || ch
== '\r' || ch
== '\n' || ch
== '\v' ||
81 ch
== '\f' || (ch
>= 32 && ch
< 127))
91 void print_string (FILE *out
, struct prx
*file
, uint32 vaddr
)
93 uint32 off
= prx_translate (file
, vaddr
);
96 for (; off
< file
->size
; off
++) {
97 uint8 ch
= file
->data
[off
];
98 if (ch
>= 32 && ch
< 127) {
99 fprintf (out
, "%c", ch
);
102 case '\t': fprintf (out
, "\\t"); break;
103 case '\r': fprintf (out
, "\\r"); break;
104 case '\n': fprintf (out
, "\\n"); break;
105 case '\v': fprintf (out
, "\\v"); break;
106 case '\f': fprintf (out
, "\\f"); break;
116 void print_value (FILE *out
, struct value
*val
, int options
)
119 int isstring
= FALSE
;
122 case VAL_CONSTANT
: fprintf (out
, "0x%08X", val
->val
.intval
); break;
124 var
= val
->val
.variable
;
125 if (CONST_TYPE (var
->status
) != VAR_STAT_NOTCONSTANT
&&
126 !(options
& OPTS_RESULT
)) {
128 file
= var
->def
->block
->sub
->code
->file
;
129 if (var
->def
->status
& OP_STAT_HASRELOC
) {
130 isstring
= valid_string (file
, var
->value
);
133 print_string (out
, file
, var
->value
);
135 fprintf (out
, "0x%08X", var
->value
);
139 case SSAVAR_ARGUMENT
:
140 if (var
->name
.val
.intval
>= REGISTER_GPR_A0
&&
141 var
->name
.val
.intval
<= REGISTER_GPR_T3
) {
142 fprintf (out
, "arg%d", var
->name
.val
.intval
- REGISTER_GPR_A0
+ 1);
144 print_value (out
, &var
->name
, options
);
148 fprintf (out
, "var%d", var
->info
);
151 options
= OPTS_NORESULT
;
152 if (((struct value
*) list_headvalue (var
->def
->results
))->val
.variable
!= var
)
153 options
|= OPTS_SECONDRESULT
;
154 if (var
->def
->type
!= OP_MOVE
)
156 print_operation (out
, var
->def
, 0, options
);
157 if (var
->def
->type
!= OP_MOVE
)
161 print_value (out
, &var
->name
, options
);
162 fprintf (out
, "/* Invalid block %d %d */",
163 var
->def
->block
->node
.dfsnum
,
170 if (val
->val
.intval
== REGISTER_HI
) fprintf (out
, "hi");
171 else if (val
->val
.intval
== REGISTER_LO
) fprintf (out
, "lo");
172 else fprintf (out
, "%s", gpr_names
[val
->val
.intval
]);
175 fprintf (out
, "UNK");
180 void print_asm_reglist (FILE *out
, list regs
, int identsize
, int options
)
185 ident_line (out
, identsize
);
186 fprintf (out
, " : ");
188 el
= list_head (regs
);
190 struct value
*val
= element_getvalue (el
);
191 if (el
!= list_head (regs
))
193 fprintf (out
, "\"=r\"(");
194 print_value (out
, val
, 0);
196 el
= element_next (el
);
201 void print_asm (FILE *out
, struct operation
*op
, int identsize
, int options
)
203 struct location
*loc
;
205 ident_line (out
, identsize
);
206 fprintf (out
, "__asm__ (");
207 for (loc
= op
->info
.asmop
.begin
; ; loc
++) {
208 if (loc
!= op
->info
.asmop
.begin
) {
210 ident_line (out
, identsize
);
213 fprintf (out
, "\"%s;\"", allegrex_disassemble (loc
->opc
, loc
->address
, FALSE
));
214 if (loc
== op
->info
.asmop
.end
) break;
216 if (list_size (op
->results
) != 0 || list_size (op
->operands
) != 0) {
217 print_asm_reglist (out
, op
->results
, identsize
, options
);
218 if (list_size (op
->operands
) != 0) {
219 print_asm_reglist (out
, op
->operands
, identsize
, options
);
223 fprintf (out
, ");\n");
227 void print_binaryop (FILE *out
, struct operation
*op
, const char *opsymbol
, int options
)
229 if (!(options
& OPTS_NORESULT
)) {
230 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
231 fprintf (out
, " = ");
233 print_value (out
, list_headvalue (op
->operands
), 0);
234 fprintf (out
, " %s ", opsymbol
);
235 print_value (out
, list_tailvalue (op
->operands
), 0);
239 void print_revbinaryop (FILE *out
, struct operation
*op
, const char *opsymbol
, int options
)
241 if (!(options
& OPTS_NORESULT
)) {
242 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
243 fprintf (out
, " = ");
245 print_value (out
, list_tailvalue (op
->operands
), 0);
246 fprintf (out
, " %s ", opsymbol
);
247 print_value (out
, list_headvalue (op
->operands
), 0);
251 void print_complexop (FILE *out
, struct operation
*op
, const char *opsymbol
, int options
)
255 if (list_size (op
->results
) != 0 && !(options
& OPTS_NORESULT
)) {
256 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
257 fprintf (out
, " = ");
260 fprintf (out
, "%s (", opsymbol
);
261 el
= list_head (op
->operands
);
264 val
= element_getvalue (el
);
265 if (val
->type
== VAL_SSAVAR
) {
266 if (val
->val
.variable
->type
== SSAVAR_INVALID
) break;
268 if (el
!= list_head (op
->operands
))
270 print_value (out
, val
, 0);
271 el
= element_next (el
);
277 void print_call (FILE *out
, struct operation
*op
, int options
)
281 if (list_size (op
->info
.callop
.retvalues
) != 0 && !(options
& OPTS_NORESULT
)) {
282 el
= list_head (op
->info
.callop
.retvalues
);
284 print_value (out
, element_getvalue (el
), OPTS_RESULT
);
286 el
= element_next (el
);
291 if (op
->block
->info
.call
.calltarget
) {
292 print_subroutine_name (out
, op
->block
->info
.call
.calltarget
);
295 print_value (out
, list_headvalue (op
->block
->info
.call
.from
->jumpop
->operands
), 0);
301 el
= list_head (op
->info
.callop
.arguments
);
304 val
= element_getvalue (el
);
305 if (val
->type
== VAL_SSAVAR
) {
306 if (val
->val
.variable
->type
== SSAVAR_INVALID
) break;
308 if (el
!= list_head (op
->info
.callop
.arguments
))
310 print_value (out
, val
, 0);
311 el
= element_next (el
);
317 void print_return (FILE *out
, struct operation
*op
, int options
)
321 fprintf (out
, "return");
322 el
= list_head (op
->info
.endop
.arguments
);
325 val
= element_getvalue (el
);
327 print_value (out
, val
, 0);
328 el
= element_next (el
);
333 void print_ext (FILE *out
, struct operation
*op
, int options
)
335 struct value
*val1
, *val2
, *val3
;
339 el
= list_head (op
->operands
);
340 val1
= element_getvalue (el
); el
= element_next (el
);
341 val2
= element_getvalue (el
); el
= element_next (el
);
342 val3
= element_getvalue (el
);
344 mask
= 0xFFFFFFFF >> (32 - val3
->val
.intval
);
345 if (!(options
& OPTS_NORESULT
)) {
346 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
347 fprintf (out
, " = ");
351 print_value (out
, val1
, 0);
352 fprintf (out
, " >> %d)", val2
->val
.intval
);
353 fprintf (out
, " & 0x%08X", mask
);
357 void print_ins (FILE *out
, struct operation
*op
, int options
)
359 struct value
*val1
, *val2
, *val3
, *val4
;
363 el
= list_head (op
->operands
);
364 val1
= element_getvalue (el
); el
= element_next (el
);
365 val2
= element_getvalue (el
); el
= element_next (el
);
366 val3
= element_getvalue (el
); el
= element_next (el
);
367 val4
= element_getvalue (el
);
369 mask
= 0xFFFFFFFF >> (32 - val4
->val
.intval
);
370 if (!(options
& OPTS_NORESULT
)) {
371 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
372 fprintf (out
, " = ");
376 print_value (out
, val2
, 0);
377 fprintf (out
, " & 0x%08X) | (", ~(mask
<< val3
->val
.intval
));
378 print_value (out
, val1
, 0);
379 fprintf (out
, " & 0x%08X)", mask
);
383 void print_nor (FILE *out
, struct operation
*op
, int options
)
385 struct value
*val1
, *val2
;
388 val1
= list_headvalue (op
->operands
);
389 val2
= list_tailvalue (op
->operands
);
391 if (val1
->val
.intval
== 0 || val2
->val
.intval
== 0) {
393 if (val1
->val
.intval
== 0) val1
= val2
;
396 if (!(options
& OPTS_NORESULT
)) {
397 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
398 fprintf (out
, " = ");
403 print_value (out
, val1
, 0);
404 fprintf (out
, " | ");
405 print_value (out
, val2
, 0);
409 print_value (out
, val1
, 0);
414 void print_movnz (FILE *out
, struct operation
*op
, int ismovn
, int options
)
416 struct value
*val1
, *val2
, *val3
;
417 struct value
*result
;
420 el
= list_head (op
->operands
);
421 val1
= element_getvalue (el
); el
= element_next (el
);
422 val2
= element_getvalue (el
); el
= element_next (el
);
423 val3
= element_getvalue (el
);
424 result
= list_headvalue (op
->results
);
426 if (!(options
& OPTS_NORESULT
)) {
427 print_value (out
, result
, OPTS_RESULT
);
428 fprintf (out
, " = ");
435 print_value (out
, val2
, 0);
436 fprintf (out
, ") ? ");
437 print_value (out
, val1
, 0);
438 fprintf (out
, " : ");
439 print_value (out
, val3
, 0);
443 void print_mult (FILE *out
, struct operation
*op
, int options
)
445 if (!(options
& OPTS_NORESULT
)) {
446 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
448 print_value (out
, list_tailvalue (op
->results
), OPTS_RESULT
);
449 fprintf (out
, " = ");
451 if (options
& OPTS_SECONDRESULT
)
452 fprintf (out
, "hi (");
454 print_value (out
, list_headvalue (op
->operands
), 0);
455 fprintf (out
, " * ");
456 print_value (out
, list_tailvalue (op
->operands
), 0);
458 if (options
& OPTS_SECONDRESULT
)
463 void print_madd (FILE *out
, struct operation
*op
, int options
)
465 struct value
*val1
, *val2
, *val3
, *val4
;
466 element el
= list_head (op
->operands
);
468 val1
= element_getvalue (el
); el
= element_next (el
);
469 val2
= element_getvalue (el
); el
= element_next (el
);
470 val3
= element_getvalue (el
); el
= element_next (el
);
471 val4
= element_getvalue (el
);
473 if (!(options
& OPTS_NORESULT
)) {
474 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
476 print_value (out
, list_tailvalue (op
->results
), OPTS_RESULT
);
477 fprintf (out
, " = ");
480 print_value (out
, val1
, 0);
481 fprintf (out
, " * ");
482 print_value (out
, val2
, 0);
484 fprintf (out
, " + (");
485 print_value (out
, val3
, 0);
487 print_value (out
, val4
, 0);
493 void print_msub (FILE *out
, struct operation
*op
, int options
)
495 struct value
*val1
, *val2
, *val3
, *val4
;
496 element el
= list_head (op
->operands
);
498 val1
= element_getvalue (el
); el
= element_next (el
);
499 val2
= element_getvalue (el
); el
= element_next (el
);
500 val3
= element_getvalue (el
); el
= element_next (el
);
501 val4
= element_getvalue (el
);
503 if (!(options
& OPTS_NORESULT
)) {
504 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
506 print_value (out
, list_tailvalue (op
->results
), OPTS_RESULT
);
507 fprintf (out
, " = ");
511 print_value (out
, val3
, 0);
513 print_value (out
, val4
, 0);
514 fprintf (out
, ") - ");
516 print_value (out
, val1
, 0);
517 fprintf (out
, " * ");
518 print_value (out
, val2
, 0);
523 void print_div (FILE *out
, struct operation
*op
, int options
)
525 if (!(options
& OPTS_NORESULT
)) {
526 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
528 print_value (out
, list_tailvalue (op
->results
), OPTS_RESULT
);
529 fprintf (out
, " = ");
531 print_value (out
, list_headvalue (op
->operands
), 0);
533 if (options
& OPTS_SECONDRESULT
)
534 fprintf (out
, " %% ");
536 fprintf (out
, " / ");
538 print_value (out
, list_tailvalue (op
->operands
), 0);
542 void print_slt (FILE *out
, struct operation
*op
, int isunsigned
, int options
)
544 struct value
*val1
, *val2
;
545 struct value
*result
;
548 el
= list_head (op
->operands
);
549 val1
= element_getvalue (el
); el
= element_next (el
);
550 val2
= element_getvalue (el
);
551 result
= list_headvalue (op
->results
);
553 if (!(options
& OPTS_NORESULT
)) {
554 print_value (out
, result
, OPTS_RESULT
);
555 fprintf (out
, " = ");
560 print_value (out
, val1
, 0);
561 fprintf (out
, " < ");
562 print_value (out
, val2
, 0);
567 void print_signextend (FILE *out
, struct operation
*op
, int isbyte
, int options
)
569 if (!(options
& OPTS_NORESULT
)) {
570 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
571 fprintf (out
, " = ");
575 fprintf (out
, "(char) ");
577 fprintf (out
, "(short) ");
579 print_value (out
, list_headvalue (op
->operands
), 0);
583 void print_memory_address (FILE *out
, struct operation
*op
, int size
, int isunsigned
, int options
)
590 if (isunsigned
) type
= "unsigned char *";
591 else type
= "char *";
592 } else if (size
== 1) {
593 if (isunsigned
) type
= "unsigned short *";
594 else type
= "short *";
595 } else if (size
== 2) {
599 val
= list_headvalue (op
->operands
);
600 if (val
->type
== VAL_SSAVAR
) {
601 if (CONST_TYPE (val
->val
.variable
->status
) != VAR_STAT_NOTCONSTANT
) {
602 address
= val
->val
.variable
->value
;
603 val
= list_tailvalue (op
->operands
);
604 address
+= val
->val
.intval
;
605 fprintf (out
, "*((%s) 0x%08X)", type
, address
);
610 fprintf (out
, "((%s) ", type
);
611 print_value (out
, val
, 0);
612 val
= list_tailvalue (op
->operands
);
613 fprintf (out
, ")[%d]", val
->val
.intval
>> size
);
617 void print_load (FILE *out
, struct operation
*op
, int size
, int isunsigned
, int options
)
619 if (!(options
& OPTS_NORESULT
)) {
620 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
621 fprintf (out
, " = ");
623 print_memory_address (out
, op
, size
, isunsigned
, options
);
627 void print_store (FILE *out
, struct operation
*op
, int size
, int isunsigned
, int options
)
629 struct value
*val
= element_getvalue (element_next (list_head (op
->operands
)));
630 print_memory_address (out
, op
, size
, isunsigned
, options
);
631 fprintf (out
, " = ");
632 print_value (out
, val
, 0);
636 void print_condition (FILE *out
, struct operation
*op
, int options
)
638 fprintf (out
, "if (");
639 if (options
& OPTS_REVERSECOND
) fprintf (out
, "!(");
640 print_value (out
, list_headvalue (op
->operands
), 0);
641 switch (op
->info
.iop
.insn
) {
643 fprintf (out
, " != ");
646 fprintf (out
, " == ");
650 fprintf (out
, " >= 0");
653 fprintf (out
, " > 0");
656 fprintf (out
, " <= 0");
660 fprintf (out
, " < 0");
665 if (list_size (op
->operands
) == 2)
666 print_value (out
, list_tailvalue (op
->operands
), 0);
668 if (options
& OPTS_REVERSECOND
) fprintf (out
, ")");
674 void print_operation (FILE *out
, struct operation
*op
, int identsize
, int options
)
676 struct location
*loc
;
677 int nosemicolon
= FALSE
;
679 if (op
->type
== OP_ASM
) {
680 print_asm (out
, op
, identsize
, options
);
684 loc
= op
->info
.iop
.loc
;
685 if (op
->type
== OP_INSTRUCTION
) {
686 if (op
->info
.iop
.loc
->insn
->flags
& (INSN_JUMP
))
688 if (loc
->branchalways
) return;
689 } else if (op
->type
== OP_NOP
|| op
->type
== OP_START
|| op
->type
== OP_PHI
) {
693 ident_line (out
, identsize
);
695 if ((op
->status
& (OP_STAT_CONSTANT
| OP_STAT_DEFERRED
)) == OP_STAT_CONSTANT
) {
696 struct value
*val
= list_headvalue (op
->results
);
697 if (!(options
& OPTS_NORESULT
)) {
698 print_value (out
, val
, OPTS_RESULT
);
699 fprintf (out
, " = ");
701 print_value (out
, val
, 0);
703 if (op
->type
== OP_INSTRUCTION
) {
704 switch (op
->info
.iop
.insn
) {
706 case I_ADDU
: print_binaryop (out
, op
, "+", options
); break;
708 case I_SUBU
: print_binaryop (out
, op
, "-", options
); break;
709 case I_XOR
: print_binaryop (out
, op
, "^", options
); break;
710 case I_AND
: print_binaryop (out
, op
, "&", options
); break;
711 case I_OR
: print_binaryop (out
, op
, "|", options
); break;
713 case I_SRLV
: print_revbinaryop (out
, op
, ">>", options
); break;
714 case I_SLLV
: print_revbinaryop (out
, op
, "<<", options
); break;
715 case I_ROTV
: print_complexop (out
, op
, "ROTV", options
); break;
716 case I_INS
: print_ins (out
, op
, options
); break;
717 case I_EXT
: print_ext (out
, op
, options
); break;
718 case I_MIN
: print_complexop (out
, op
, "MIN", options
); break;
719 case I_MAX
: print_complexop (out
, op
, "MAX", options
); break;
720 case I_BITREV
: print_complexop (out
, op
, "BITREV", options
); break;
721 case I_CLZ
: print_complexop (out
, op
, "CLZ", options
); break;
722 case I_CLO
: print_complexop (out
, op
, "CLO", options
); break;
723 case I_NOR
: print_nor (out
, op
, options
); break;
724 case I_MOVN
: print_movnz (out
, op
, TRUE
, options
); break;
725 case I_MOVZ
: print_movnz (out
, op
, FALSE
, options
); break;
727 case I_MULTU
: print_mult (out
, op
, options
); break;
729 case I_MADDU
: print_madd (out
, op
, options
); break;
731 case I_MSUBU
: print_msub (out
, op
, options
); break;
733 case I_DIVU
: print_div (out
, op
, options
); break;
734 case I_SLT
: print_slt (out
, op
, FALSE
, options
); break;
735 case I_SLTU
: print_slt (out
, op
, TRUE
, options
); break;
736 case I_LW
: print_load (out
, op
, 2, FALSE
, options
); break;
737 case I_LB
: print_load (out
, op
, 0, FALSE
, options
); break;
738 case I_LBU
: print_load (out
, op
, 0, TRUE
, options
); break;
739 case I_LH
: print_load (out
, op
, 1, FALSE
, options
); break;
740 case I_LHU
: print_load (out
, op
, 1, TRUE
, options
); break;
741 case I_LL
: print_complexop (out
, op
, "LL", options
); break;
742 case I_LWL
: print_complexop (out
, op
, "LWL", options
); break;
743 case I_LWR
: print_complexop (out
, op
, "LWR", options
); break;
744 case I_SW
: print_store (out
, op
, 2, FALSE
, options
); break;
745 case I_SH
: print_store (out
, op
, 1, FALSE
, options
); break;
746 case I_SB
: print_store (out
, op
, 0, FALSE
, options
); break;
747 case I_SC
: print_complexop (out
, op
, "SC", options
); break;
748 case I_SWL
: print_complexop (out
, op
, "SWL", options
); break;
749 case I_SWR
: print_complexop (out
, op
, "SWR", options
); break;
750 case I_SEB
: print_signextend (out
, op
, TRUE
, options
); break;
751 case I_SEH
: print_signextend (out
, op
, TRUE
, options
); break;
753 if (loc
->insn
->flags
& INSN_BRANCH
) {
754 print_condition (out
, op
, options
);
759 } else if (op
->type
== OP_MOVE
) {
760 if (!(options
& OPTS_NORESULT
)) {
761 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
762 fprintf (out
, " = ");
764 print_value (out
, list_headvalue (op
->operands
), 0);
765 } else if (op
->type
== OP_CALL
) {
766 print_call (out
, op
, options
);
767 } else if (op
->type
== OP_END
) {
768 print_return (out
, op
, options
);
769 /*} else if (op->type == OP_PHI) {
770 print_complexop (out, op, "PHI", options);*/
774 if (!(options
& OPTS_NORESULT
)) {
775 if (nosemicolon
) fprintf (out
, "\n");
776 else fprintf (out
, ";\n");