Passo intermediario, ainda falta um longo caminho
[pspdecompiler.git] / output.c
blobce30b7c05989bfec5e79616417a66061ffeae2c8
2 #include <stdio.h>
3 #include <string.h>
5 #include "output.h"
6 #include "allegrex.h"
7 #include "utils.h"
9 void get_base_name (char *filename, char *basename, size_t len)
11 char *temp;
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)
24 int i;
25 for (i = 0; i < size; i++)
26 fprintf (out, " ");
30 void print_subroutine_name (FILE *out, struct subroutine *sub)
32 if (sub->export) {
33 if (sub->export->name) {
34 fprintf (out, "%s", sub->export->name);
35 } else {
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);
41 } else {
42 fprintf (out, "%s_%08X", sub->import->libname, sub->import->nid);
44 } else {
45 fprintf (out, "sub_%05X", sub->begin->address);
49 void print_subroutine_declaration (FILE *out, struct subroutine *sub)
51 int i;
52 if (sub->numregout > 0)
53 fprintf (out, "int ");
54 else
55 fprintf (out, "void ");
57 print_subroutine_name (out, sub);
59 fprintf (out, " (");
60 for (i = 0; i < sub->numregargs; i++) {
61 if (i != 0) fprintf (out, ", ");
62 fprintf (out, "int arg%d", i + 1);
64 fprintf (out, ")");
67 void print_value (FILE *out, struct value *val)
69 switch (val->type) {
70 case VAL_CONSTANT: fprintf (out, "0x%08X", val->val.intval); break;
71 case VAL_SSAVAR:
72 switch (val->val.variable->type) {
73 case SSAVAR_ARGUMENT:
74 if (val->val.variable->name.val.intval >= REGISTER_GPR_A0 &&
75 val->val.variable->name.val.intval <= REGISTER_GPR_T3) {
76 fprintf (out, "arg%d", val->val.variable->name.val.intval - REGISTER_GPR_A0 + 1);
77 } else {
78 print_value (out, &val->val.variable->name);
80 break;
81 case SSAVAR_LOCAL:
82 fprintf (out, "local%d", val->val.variable->info);
83 break;
84 case SSAVAR_CONSTANT:
85 fprintf (out, "0x%08X", val->val.variable->info);
86 break;
87 case SSAVAR_TEMP:
88 if (val->val.variable->def->type != OP_MOVE)
89 fprintf (out, "(");
90 print_operation (out, val->val.variable->def, 0, TRUE);
91 if (val->val.variable->def->type != OP_MOVE)
92 fprintf (out, ")");
93 break;
94 default:
95 print_value (out, &val->val.variable->name);
96 fprintf (out, "/* Invalid block %d %d */",
97 val->val.variable->def->block->node.dfsnum,
98 val->val.variable->def->type);
99 break;
101 break;
102 case VAL_REGISTER:
103 if (val->val.intval == REGISTER_HI) fprintf (out, "hi");
104 else if (val->val.intval == REGISTER_LO) fprintf (out, "lo");
105 else fprintf (out, "%s", gpr_names[val->val.intval]);
106 break;
107 default:
108 fprintf (out, "UNK");
112 static
113 void print_asm_reglist (FILE *out, list regs, int identsize, int options)
115 element el;
117 fprintf (out, "\n");
118 ident_line (out, identsize);
119 fprintf (out, " : ");
121 el = list_head (regs);
122 while (el) {
123 struct value *val = element_getvalue (el);
124 if (el != list_head (regs))
125 fprintf (out, ", ");
126 fprintf (out, "\"=r\"(");
127 print_value (out, val);
128 fprintf (out, ")");
129 el = element_next (el);
133 static
134 void print_asm (FILE *out, struct operation *op, int identsize, int options)
136 struct location *loc;
138 ident_line (out, identsize);
139 fprintf (out, "__asm__ (");
140 for (loc = op->info.asmop.begin; ; loc++) {
141 if (loc != op->info.asmop.begin) {
142 fprintf (out, "\n");
143 ident_line (out, identsize);
144 fprintf (out, " ");
146 fprintf (out, "\"%s\"", allegrex_disassemble (loc->opc, loc->address, FALSE));
147 if (loc == op->info.asmop.end) break;
149 if (list_size (op->results) != 0 || list_size (op->operands) != 0) {
150 print_asm_reglist (out, op->results, identsize, options);
151 if (list_size (op->operands) != 0) {
152 print_asm_reglist (out, op->operands, identsize, options);
156 fprintf (out, ");\n");
159 static
160 void print_binaryop (FILE *out, struct operation *op, const char *opsymbol, int options)
162 if (!(options & OPTS_DEFERRED)) {
163 print_value (out, list_headvalue (op->results));
164 fprintf (out, " = ");
166 print_value (out, list_headvalue (op->operands));
167 fprintf (out, " %s ", opsymbol);
168 print_value (out, list_tailvalue (op->operands));
171 void print_complexop (FILE *out, struct operation *op, const char *opsymbol, int options)
173 element el;
175 if (list_size (op->results) != 0 && !(options & OPTS_DEFERRED)) {
176 print_value (out, list_headvalue (op->results));
177 fprintf (out, " = ");
180 fprintf (out, "%s (", opsymbol);
181 el = list_head (op->operands);
182 while (el) {
183 struct value *val;
184 val = element_getvalue (el);
185 if (val->type == VAL_SSAVAR) {
186 if (val->val.variable->type == SSAVAR_INVALID) break;
188 if (el != list_head (op->operands))
189 fprintf (out, ", ");
190 print_value (out, val);
191 el = element_next (el);
193 fprintf (out, ")");
196 void print_call (FILE *out, struct operation *op, int options)
198 element el;
200 if (list_size (op->info.callop.retvalues) != 0 && !(options & OPTS_DEFERRED)) {
201 el = list_head (op->info.callop.retvalues);
202 while (el) {
203 print_value (out, list_tailvalue (op->results));
204 fprintf (out, " ");
205 el = element_next (el);
207 fprintf (out, "= ");
210 if (op->block->info.call.calltarget) {
211 print_subroutine_name (out, op->block->info.call.calltarget);
212 } else {
213 fprintf (out, "CALL");
216 fprintf (out, " (");
218 el = list_head (op->info.callop.arguments);
219 while (el) {
220 struct value *val;
221 val = element_getvalue (el);
222 if (val->type == VAL_SSAVAR) {
223 if (val->val.variable->type == SSAVAR_INVALID) break;
225 if (el != list_head (op->info.callop.arguments))
226 fprintf (out, ", ");
227 print_value (out, val);
228 el = element_next (el);
230 fprintf (out, ")");
233 static
234 void print_ext (FILE *out, struct operation *op, int options)
236 struct value *val1, *val2, *val3;
237 element el;
238 uint32 mask;
240 el = list_head (op->operands);
241 val1 = element_getvalue (el); el = element_next (el);
242 val2 = element_getvalue (el); el = element_next (el);
243 val3 = element_getvalue (el);
245 mask = 0xFFFFFFFF >> (32 - val3->val.intval);
246 if (!(options & OPTS_DEFERRED)) {
247 print_value (out, list_headvalue (op->results));
248 fprintf (out, " = ");
251 fprintf (out, "(");
252 print_value (out, val1);
253 fprintf (out, " >> %d)", val2->val.intval);
254 fprintf (out, " & 0x%08X", mask);
257 static
258 void print_ins (FILE *out, struct operation *op, int options)
260 struct value *val1, *val2, *val3, *val4;
261 element el;
262 uint32 mask;
264 el = list_head (op->operands);
265 val1 = element_getvalue (el); el = element_next (el);
266 val2 = element_getvalue (el); el = element_next (el);
267 val3 = element_getvalue (el); el = element_next (el);
268 val4 = element_getvalue (el);
270 mask = 0xFFFFFFFF >> (32 - val4->val.intval);
271 if (!(options & OPTS_DEFERRED)) {
272 print_value (out, list_headvalue (op->results));
273 fprintf (out, " = ");
276 fprintf (out, "(");
277 print_value (out, val2);
278 fprintf (out, " & 0x%08X) | (", ~(mask << val3->val.intval));
279 print_value (out, val1);
280 fprintf (out, " & 0x%08X)", mask);
283 static
284 void print_nor (FILE *out, struct operation *op, int options)
286 struct value *val1, *val2;
287 int simple = 0;
289 val1 = list_headvalue (op->operands);
290 val2 = list_tailvalue (op->operands);
292 if (val1->val.intval == 0 || val2->val.intval == 0) {
293 simple = 1;
294 if (val1->val.intval == 0) val1 = val2;
297 if (!(options & OPTS_DEFERRED)) {
298 print_value (out, list_headvalue (op->results));
299 fprintf (out, " = ");
302 if (!simple) {
303 fprintf (out, "!(");
304 print_value (out, val1);
305 fprintf (out, " | ");
306 print_value (out, val2);
307 fprintf (out, ")");
308 } else {
309 fprintf (out, "!");
310 print_value (out, val1);
314 static
315 void print_movnz (FILE *out, struct operation *op, int ismovn, int options)
317 struct value *val1, *val2, *val3;
318 struct value *result;
319 element el;
321 el = list_head (op->operands);
322 val1 = element_getvalue (el); el = element_next (el);
323 val2 = element_getvalue (el); el = element_next (el);
324 val3 = element_getvalue (el);
325 result = list_headvalue (op->results);
327 if (!(options & OPTS_DEFERRED)) {
328 print_value (out, result);
329 fprintf (out, " = ");
332 if (ismovn)
333 fprintf (out, "(");
334 else
335 fprintf (out, "!(");
336 print_value (out, val2);
337 fprintf (out, ") ? ");
338 print_value (out, val1);
339 fprintf (out, " : ");
340 print_value (out, val3);
343 static
344 void print_slt (FILE *out, struct operation *op, int isunsigned, int options)
346 struct value *val1, *val2;
347 struct value *result;
348 element el;
350 el = list_head (op->operands);
351 val1 = element_getvalue (el); el = element_next (el);
352 val2 = element_getvalue (el);
353 result = list_headvalue (op->results);
355 if (!(options & OPTS_DEFERRED)) {
356 print_value (out, result);
357 fprintf (out, " = ");
360 fprintf (out, "(");
362 print_value (out, val1);
363 fprintf (out, " < ");
364 print_value (out, val2);
365 fprintf (out, ")");
368 static
369 void print_signextend (FILE *out, struct operation *op, int isbyte, int options)
371 if (!(options & OPTS_DEFERRED)) {
372 print_value (out, list_headvalue (op->results));
373 fprintf (out, " = ");
376 if (isbyte)
377 fprintf (out, "(char) ");
378 else
379 fprintf (out, "(short) ");
381 print_value (out, list_headvalue (op->operands));
384 static
385 void print_memory_address (FILE *out, struct operation *op, int size, int isunsigned, int options)
387 struct value *val;
388 uint32 address;
389 const char *type;
391 if (size == 0) {
392 if (isunsigned) type = "unsigned char *";
393 else type = "char *";
394 } else if (size == 1) {
395 if (isunsigned) type = "unsigned short *";
396 else type = "short *";
397 } else if (size == 2) {
398 type = "int *";
401 val = list_headvalue (op->operands);
402 if (val->type == VAL_SSAVAR) {
403 if (val->val.variable->type == SSAVAR_CONSTANT) {
404 address = val->val.variable->type;
405 val = list_tailvalue (op->operands);
406 address += val->val.intval;
407 fprintf (out, "*((%s) 0x%08X)", type, address);
408 return;
412 fprintf (out, "((%s) ", type);
413 print_value (out, val);
414 val = list_tailvalue (op->operands);
415 fprintf (out, ")[%d]", val->val.intval >> size);
418 static
419 void print_load (FILE *out, struct operation *op, int size, int isunsigned, int options)
421 if (!(options & OPTS_DEFERRED)) {
422 print_value (out, list_headvalue (op->results));
423 fprintf (out, " = ");
425 print_memory_address (out, op, size, isunsigned, options);
428 static
429 void print_store (FILE *out, struct operation *op, int size, int isunsigned, int options)
431 struct value *val = element_getvalue (element_next (list_head (op->operands)));
432 print_memory_address (out, op, size, isunsigned, options);
433 fprintf (out, " = ");
434 print_value (out, val);
437 static
438 void print_condition (FILE *out, struct operation *op, int options)
440 fprintf (out, "if (");
441 if (options & OPTS_REVERSECOND) fprintf (out, "!(");
442 print_value (out, list_headvalue (op->operands));
443 switch (op->info.iop.insn) {
444 case I_BNE:
445 fprintf (out, " != ");
446 break;
447 case I_BEQ:
448 fprintf (out, " == ");
449 break;
450 case I_BGEZ:
451 case I_BGEZAL:
452 fprintf (out, " >= 0");
453 break;
454 case I_BGTZ:
455 fprintf (out, " > 0");
456 break;
457 case I_BLEZ:
458 fprintf (out, " <= 0");
459 break;
460 case I_BLTZ:
461 case I_BLTZAL:
462 fprintf (out, " < 0");
463 break;
464 default:
465 break;
467 if (list_size (op->operands) == 2)
468 print_value (out, list_tailvalue (op->operands));
470 if (options & OPTS_REVERSECOND) fprintf (out, ")");
471 fprintf (out, ")");
476 void print_operation (FILE *out, struct operation *op, int identsize, int options)
478 struct location *loc;
479 int nosemicolon = FALSE;
481 if (op->type == OP_ASM) {
482 print_asm (out, op, identsize, options);
483 return;
486 if (op->type == OP_INSTRUCTION) {
487 if (op->info.iop.loc->insn->flags & (INSN_JUMP))
488 return;
489 } else if (op->type == OP_NOP || op->type == OP_START ||
490 op->type == OP_END || op->type == OP_PHI) {
491 return;
494 loc = op->info.iop.loc;
495 if (op->type == OP_INSTRUCTION) {
496 if (loc->branchalways) return;
499 ident_line (out, identsize);
500 if (op->type == OP_INSTRUCTION) {
501 switch (op->info.iop.insn) {
502 case I_ADD: print_binaryop (out, op, "+", options); break;
503 case I_ADDU: print_binaryop (out, op, "+", options); break;
504 case I_SUB: print_binaryop (out, op, "-", options); break;
505 case I_SUBU: print_binaryop (out, op, "-", options); break;
506 case I_XOR: print_binaryop (out, op, "^", options); break;
507 case I_AND: print_binaryop (out, op, "&", options); break;
508 case I_OR: print_binaryop (out, op, "|", options); break;
509 case I_SRAV: print_binaryop (out, op, ">>", options); break;
510 case I_SRLV: print_binaryop (out, op, ">>", options); break;
511 case I_SLLV: print_binaryop (out, op, "<<", options); break;
512 case I_INS: print_ins (out, op, options); break;
513 case I_EXT: print_ext (out, op, options); break;
514 case I_MIN: print_complexop (out, op, "MIN", options); break;
515 case I_MAX: print_complexop (out, op, "MAX", options); break;
516 case I_BITREV: print_complexop (out, op, "BITREV", options); break;
517 case I_CLZ: print_complexop (out, op, "CLZ", options); break;
518 case I_CLO: print_complexop (out, op, "CLO", options); break;
519 case I_NOR: print_nor (out, op, options); break;
520 case I_MOVN: print_movnz (out, op, TRUE, options); break;
521 case I_MOVZ: print_movnz (out, op, FALSE, options); break;
522 case I_SLT: print_slt (out, op, FALSE, options); break;
523 case I_SLTU: print_slt (out, op, TRUE, options); break;
524 case I_LW: print_load (out, op, 2, FALSE, options); break;
525 case I_LB: print_load (out, op, 0, FALSE, options); break;
526 case I_LBU: print_load (out, op, 0, TRUE, options); break;
527 case I_LH: print_load (out, op, 1, FALSE, options); break;
528 case I_LHU: print_load (out, op, 1, TRUE, options); break;
529 case I_LL: print_complexop (out, op, "LL", options); break;
530 case I_LWL: print_complexop (out, op, "LWL", options); break;
531 case I_LWR: print_complexop (out, op, "LWR", options); break;
532 case I_SW: print_store (out, op, 2, FALSE, options); break;
533 case I_SH: print_store (out, op, 1, FALSE, options); break;
534 case I_SB: print_store (out, op, 0, FALSE, options); break;
535 case I_SC: print_complexop (out, op, "SC", options); break;
536 case I_SWL: print_complexop (out, op, "SWL", options); break;
537 case I_SWR: print_complexop (out, op, "SWR", options); break;
538 case I_SEB: print_signextend (out, op, TRUE, options); break;
539 case I_SEH: print_signextend (out, op, TRUE, options); break;
540 default:
541 if (loc->insn->flags & INSN_BRANCH) {
542 print_condition (out, op, options);
543 nosemicolon = TRUE;
545 break;
547 } else if (op->type == OP_MOVE) {
548 if (!options) {
549 print_value (out, list_headvalue (op->results));
550 fprintf (out, " = ");
552 print_value (out, list_headvalue (op->operands));
553 } else if (op->type == OP_CALL) {
554 print_call (out, op, options);
557 if (!(options & OPTS_DEFERRED)) {
558 if (nosemicolon) fprintf (out, "\n");
559 else fprintf (out, ";\n");