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 if (var
->def
->type
!= OP_MOVE
)
153 print_operation (out
, var
->def
, 0, TRUE
);
154 if (var
->def
->type
!= OP_MOVE
)
158 print_value (out
, &var
->name
, options
);
159 fprintf (out
, "/* Invalid block %d %d */",
160 var
->def
->block
->node
.dfsnum
,
167 if (val
->val
.intval
== REGISTER_HI
) fprintf (out
, "hi");
168 else if (val
->val
.intval
== REGISTER_LO
) fprintf (out
, "lo");
169 else fprintf (out
, "%s", gpr_names
[val
->val
.intval
]);
172 fprintf (out
, "UNK");
177 void print_asm_reglist (FILE *out
, list regs
, int identsize
, int options
)
182 ident_line (out
, identsize
);
183 fprintf (out
, " : ");
185 el
= list_head (regs
);
187 struct value
*val
= element_getvalue (el
);
188 if (el
!= list_head (regs
))
190 fprintf (out
, "\"=r\"(");
191 print_value (out
, val
, 0);
193 el
= element_next (el
);
198 void print_asm (FILE *out
, struct operation
*op
, int identsize
, int options
)
200 struct location
*loc
;
202 ident_line (out
, identsize
);
203 fprintf (out
, "__asm__ (");
204 for (loc
= op
->info
.asmop
.begin
; ; loc
++) {
205 if (loc
!= op
->info
.asmop
.begin
) {
207 ident_line (out
, identsize
);
210 fprintf (out
, "\"%s;\"", allegrex_disassemble (loc
->opc
, loc
->address
, FALSE
));
211 if (loc
== op
->info
.asmop
.end
) break;
213 if (list_size (op
->results
) != 0 || list_size (op
->operands
) != 0) {
214 print_asm_reglist (out
, op
->results
, identsize
, options
);
215 if (list_size (op
->operands
) != 0) {
216 print_asm_reglist (out
, op
->operands
, identsize
, options
);
220 fprintf (out
, ");\n");
224 void print_binaryop (FILE *out
, struct operation
*op
, const char *opsymbol
, int options
)
226 if (!(options
& OPTS_NORESULT
)) {
227 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
228 fprintf (out
, " = ");
230 print_value (out
, list_headvalue (op
->operands
), 0);
231 fprintf (out
, " %s ", opsymbol
);
232 print_value (out
, list_tailvalue (op
->operands
), 0);
236 void print_complexop (FILE *out
, struct operation
*op
, const char *opsymbol
, int options
)
240 if (list_size (op
->results
) != 0 && !(options
& OPTS_NORESULT
)) {
241 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
242 fprintf (out
, " = ");
245 fprintf (out
, "%s (", opsymbol
);
246 el
= list_head (op
->operands
);
249 val
= element_getvalue (el
);
250 if (val
->type
== VAL_SSAVAR
) {
251 if (val
->val
.variable
->type
== SSAVAR_INVALID
) break;
253 if (el
!= list_head (op
->operands
))
255 print_value (out
, val
, 0);
256 el
= element_next (el
);
262 void print_call (FILE *out
, struct operation
*op
, int options
)
266 if (list_size (op
->info
.callop
.retvalues
) != 0 && !(options
& OPTS_NORESULT
)) {
267 el
= list_head (op
->info
.callop
.retvalues
);
269 print_value (out
, element_getvalue (el
), OPTS_RESULT
);
271 el
= element_next (el
);
276 if (op
->block
->info
.call
.calltarget
) {
277 print_subroutine_name (out
, op
->block
->info
.call
.calltarget
);
280 print_value (out
, list_headvalue (op
->block
->info
.call
.from
->jumpop
->operands
), 0);
286 el
= list_head (op
->info
.callop
.arguments
);
289 val
= element_getvalue (el
);
290 if (val
->type
== VAL_SSAVAR
) {
291 if (val
->val
.variable
->type
== SSAVAR_INVALID
) break;
293 if (el
!= list_head (op
->info
.callop
.arguments
))
295 print_value (out
, val
, 0);
296 el
= element_next (el
);
302 void print_return (FILE *out
, struct operation
*op
, int options
)
306 fprintf (out
, "return");
307 el
= list_head (op
->info
.endop
.arguments
);
310 val
= element_getvalue (el
);
312 print_value (out
, val
, 0);
313 el
= element_next (el
);
318 void print_ext (FILE *out
, struct operation
*op
, int options
)
320 struct value
*val1
, *val2
, *val3
;
324 el
= list_head (op
->operands
);
325 val1
= element_getvalue (el
); el
= element_next (el
);
326 val2
= element_getvalue (el
); el
= element_next (el
);
327 val3
= element_getvalue (el
);
329 mask
= 0xFFFFFFFF >> (32 - val3
->val
.intval
);
330 if (!(options
& OPTS_NORESULT
)) {
331 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
332 fprintf (out
, " = ");
336 print_value (out
, val1
, 0);
337 fprintf (out
, " >> %d)", val2
->val
.intval
);
338 fprintf (out
, " & 0x%08X", mask
);
342 void print_ins (FILE *out
, struct operation
*op
, int options
)
344 struct value
*val1
, *val2
, *val3
, *val4
;
348 el
= list_head (op
->operands
);
349 val1
= element_getvalue (el
); el
= element_next (el
);
350 val2
= element_getvalue (el
); el
= element_next (el
);
351 val3
= element_getvalue (el
); el
= element_next (el
);
352 val4
= element_getvalue (el
);
354 mask
= 0xFFFFFFFF >> (32 - val4
->val
.intval
);
355 if (!(options
& OPTS_NORESULT
)) {
356 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
357 fprintf (out
, " = ");
361 print_value (out
, val2
, 0);
362 fprintf (out
, " & 0x%08X) | (", ~(mask
<< val3
->val
.intval
));
363 print_value (out
, val1
, 0);
364 fprintf (out
, " & 0x%08X)", mask
);
368 void print_nor (FILE *out
, struct operation
*op
, int options
)
370 struct value
*val1
, *val2
;
373 val1
= list_headvalue (op
->operands
);
374 val2
= list_tailvalue (op
->operands
);
376 if (val1
->val
.intval
== 0 || val2
->val
.intval
== 0) {
378 if (val1
->val
.intval
== 0) val1
= val2
;
381 if (!(options
& OPTS_NORESULT
)) {
382 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
383 fprintf (out
, " = ");
388 print_value (out
, val1
, 0);
389 fprintf (out
, " | ");
390 print_value (out
, val2
, 0);
394 print_value (out
, val1
, 0);
399 void print_movnz (FILE *out
, struct operation
*op
, int ismovn
, int options
)
401 struct value
*val1
, *val2
, *val3
;
402 struct value
*result
;
405 el
= list_head (op
->operands
);
406 val1
= element_getvalue (el
); el
= element_next (el
);
407 val2
= element_getvalue (el
); el
= element_next (el
);
408 val3
= element_getvalue (el
);
409 result
= list_headvalue (op
->results
);
411 if (!(options
& OPTS_NORESULT
)) {
412 print_value (out
, result
, OPTS_RESULT
);
413 fprintf (out
, " = ");
420 print_value (out
, val2
, 0);
421 fprintf (out
, ") ? ");
422 print_value (out
, val1
, 0);
423 fprintf (out
, " : ");
424 print_value (out
, val3
, 0);
428 void print_slt (FILE *out
, struct operation
*op
, int isunsigned
, int options
)
430 struct value
*val1
, *val2
;
431 struct value
*result
;
434 el
= list_head (op
->operands
);
435 val1
= element_getvalue (el
); el
= element_next (el
);
436 val2
= element_getvalue (el
);
437 result
= list_headvalue (op
->results
);
439 if (!(options
& OPTS_NORESULT
)) {
440 print_value (out
, result
, OPTS_RESULT
);
441 fprintf (out
, " = ");
446 print_value (out
, val1
, 0);
447 fprintf (out
, " < ");
448 print_value (out
, val2
, 0);
453 void print_signextend (FILE *out
, struct operation
*op
, int isbyte
, int options
)
455 if (!(options
& OPTS_NORESULT
)) {
456 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
457 fprintf (out
, " = ");
461 fprintf (out
, "(char) ");
463 fprintf (out
, "(short) ");
465 print_value (out
, list_headvalue (op
->operands
), 0);
469 void print_memory_address (FILE *out
, struct operation
*op
, int size
, int isunsigned
, int options
)
476 if (isunsigned
) type
= "unsigned char *";
477 else type
= "char *";
478 } else if (size
== 1) {
479 if (isunsigned
) type
= "unsigned short *";
480 else type
= "short *";
481 } else if (size
== 2) {
485 val
= list_headvalue (op
->operands
);
486 if (val
->type
== VAL_SSAVAR
) {
487 if (CONST_TYPE (val
->val
.variable
->status
) != VAR_STAT_NOTCONSTANT
) {
488 address
= val
->val
.variable
->value
;
489 val
= list_tailvalue (op
->operands
);
490 address
+= val
->val
.intval
;
491 fprintf (out
, "*((%s) 0x%08X)", type
, address
);
496 fprintf (out
, "((%s) ", type
);
497 print_value (out
, val
, 0);
498 val
= list_tailvalue (op
->operands
);
499 fprintf (out
, ")[%d]", val
->val
.intval
>> size
);
503 void print_load (FILE *out
, struct operation
*op
, int size
, int isunsigned
, int options
)
505 if (!(options
& OPTS_NORESULT
)) {
506 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
507 fprintf (out
, " = ");
509 print_memory_address (out
, op
, size
, isunsigned
, options
);
513 void print_store (FILE *out
, struct operation
*op
, int size
, int isunsigned
, int options
)
515 struct value
*val
= element_getvalue (element_next (list_head (op
->operands
)));
516 print_memory_address (out
, op
, size
, isunsigned
, options
);
517 fprintf (out
, " = ");
518 print_value (out
, val
, 0);
522 void print_condition (FILE *out
, struct operation
*op
, int options
)
524 fprintf (out
, "if (");
525 if (options
& OPTS_REVERSECOND
) fprintf (out
, "!(");
526 print_value (out
, list_headvalue (op
->operands
), 0);
527 switch (op
->info
.iop
.insn
) {
529 fprintf (out
, " != ");
532 fprintf (out
, " == ");
536 fprintf (out
, " >= 0");
539 fprintf (out
, " > 0");
542 fprintf (out
, " <= 0");
546 fprintf (out
, " < 0");
551 if (list_size (op
->operands
) == 2)
552 print_value (out
, list_tailvalue (op
->operands
), 0);
554 if (options
& OPTS_REVERSECOND
) fprintf (out
, ")");
560 void print_operation (FILE *out
, struct operation
*op
, int identsize
, int options
)
562 struct location
*loc
;
563 int nosemicolon
= FALSE
;
565 if (op
->type
== OP_ASM
) {
566 print_asm (out
, op
, identsize
, options
);
570 loc
= op
->info
.iop
.loc
;
571 if (op
->type
== OP_INSTRUCTION
) {
572 if (op
->info
.iop
.loc
->insn
->flags
& (INSN_JUMP
))
574 if (loc
->branchalways
) return;
575 } else if (op
->type
== OP_NOP
|| op
->type
== OP_START
|| op
->type
== OP_PHI
) {
579 ident_line (out
, identsize
);
581 if ((op
->status
& (OP_STAT_CONSTANT
| OP_STAT_DEFERRED
)) == OP_STAT_CONSTANT
) {
582 struct value
*val
= list_headvalue (op
->results
);
583 if (!(options
& OPTS_NORESULT
)) {
584 print_value (out
, val
, OPTS_RESULT
);
585 fprintf (out
, " = ");
587 print_value (out
, val
, 0);
589 if (op
->type
== OP_INSTRUCTION
) {
590 switch (op
->info
.iop
.insn
) {
591 case I_ADD
: print_binaryop (out
, op
, "+", options
); break;
592 case I_ADDU
: print_binaryop (out
, op
, "+", options
); break;
593 case I_SUB
: print_binaryop (out
, op
, "-", options
); break;
594 case I_SUBU
: print_binaryop (out
, op
, "-", options
); break;
595 case I_XOR
: print_binaryop (out
, op
, "^", options
); break;
596 case I_AND
: print_binaryop (out
, op
, "&", options
); break;
597 case I_OR
: print_binaryop (out
, op
, "|", options
); break;
598 case I_SRAV
: print_binaryop (out
, op
, ">>", options
); break;
599 case I_SRLV
: print_binaryop (out
, op
, ">>", options
); break;
600 case I_SLLV
: print_binaryop (out
, op
, "<<", options
); break;
601 case I_INS
: print_ins (out
, op
, options
); break;
602 case I_EXT
: print_ext (out
, op
, options
); break;
603 case I_MIN
: print_complexop (out
, op
, "MIN", options
); break;
604 case I_MAX
: print_complexop (out
, op
, "MAX", options
); break;
605 case I_BITREV
: print_complexop (out
, op
, "BITREV", options
); break;
606 case I_CLZ
: print_complexop (out
, op
, "CLZ", options
); break;
607 case I_CLO
: print_complexop (out
, op
, "CLO", options
); break;
608 case I_NOR
: print_nor (out
, op
, options
); break;
609 case I_MOVN
: print_movnz (out
, op
, TRUE
, options
); break;
610 case I_MOVZ
: print_movnz (out
, op
, FALSE
, options
); break;
611 case I_SLT
: print_slt (out
, op
, FALSE
, options
); break;
612 case I_SLTU
: print_slt (out
, op
, TRUE
, options
); break;
613 case I_LW
: print_load (out
, op
, 2, FALSE
, options
); break;
614 case I_LB
: print_load (out
, op
, 0, FALSE
, options
); break;
615 case I_LBU
: print_load (out
, op
, 0, TRUE
, options
); break;
616 case I_LH
: print_load (out
, op
, 1, FALSE
, options
); break;
617 case I_LHU
: print_load (out
, op
, 1, TRUE
, options
); break;
618 case I_LL
: print_complexop (out
, op
, "LL", options
); break;
619 case I_LWL
: print_complexop (out
, op
, "LWL", options
); break;
620 case I_LWR
: print_complexop (out
, op
, "LWR", options
); break;
621 case I_SW
: print_store (out
, op
, 2, FALSE
, options
); break;
622 case I_SH
: print_store (out
, op
, 1, FALSE
, options
); break;
623 case I_SB
: print_store (out
, op
, 0, FALSE
, options
); break;
624 case I_SC
: print_complexop (out
, op
, "SC", options
); break;
625 case I_SWL
: print_complexop (out
, op
, "SWL", options
); break;
626 case I_SWR
: print_complexop (out
, op
, "SWR", options
); break;
627 case I_SEB
: print_signextend (out
, op
, TRUE
, options
); break;
628 case I_SEH
: print_signextend (out
, op
, TRUE
, options
); break;
630 if (loc
->insn
->flags
& INSN_BRANCH
) {
631 print_condition (out
, op
, options
);
636 } else if (op
->type
== OP_MOVE
) {
637 if (!(options
& OPTS_NORESULT
)) {
638 print_value (out
, list_headvalue (op
->results
), OPTS_RESULT
);
639 fprintf (out
, " = ");
641 print_value (out
, list_headvalue (op
->operands
), 0);
642 } else if (op
->type
== OP_CALL
) {
643 print_call (out
, op
, options
);
644 } else if (op
->type
== OP_END
) {
645 print_return (out
, op
, options
);
646 /*} else if (op->type == OP_PHI) {
647 print_complexop (out, op, "PHI", options);*/
651 if (!(options
& OPTS_NORESULT
)) {
652 if (nosemicolon
) fprintf (out
, "\n");
653 else fprintf (out
, ";\n");