Liveness funcionando
[pspdecompiler.git] / output.c
blob3c4c204d358a35497e0669475683483ffbc93d3e
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_value (FILE *out, struct value *val)
51 switch (val->type) {
52 case VAL_CONSTANT: fprintf (out, "0x%08X", val->val.intval); break;
53 case VAL_VARIABLE:
54 switch (val->val.variable->type) {
55 case VARIABLE_ARGUMENT:
56 fprintf (out, "arg%d", val->val.variable->name.val.intval);
57 break;
58 case VARIABLE_LOCAL:
59 fprintf (out, "local%d", val->val.variable->info);
60 break;
61 case VARIABLE_CONSTANT:
62 fprintf (out, "0x%08X", val->val.variable->info);
63 break;
64 case VARIABLE_TEMP:
65 if (val->val.variable->def->type != OP_MOVE)
66 fprintf (out, "(");
67 print_operation (out, val->val.variable->def, 0, TRUE);
68 if (val->val.variable->def->type != OP_MOVE)
69 fprintf (out, ")");
70 break;
71 default:
72 print_value (out, &val->val.variable->name);
73 fprintf (out, "/* Invalid block %d %d */",
74 val->val.variable->def->block->node.dfsnum,
75 val->val.variable->def->type);
76 break;
78 break;
79 case VAL_REGISTER:
80 if (val->val.intval == REGISTER_HI) fprintf (out, "hi");
81 else if (val->val.intval == REGISTER_LO) fprintf (out, "lo");
82 else fprintf (out, "%s", gpr_names[val->val.intval]);
83 break;
84 default:
85 fprintf (out, "UNK");
89 static
90 void print_asm_reglist (FILE *out, list regs, int identsize, int options)
92 element el;
94 fprintf (out, "\n");
95 ident_line (out, identsize);
96 fprintf (out, " : ");
98 el = list_head (regs);
99 while (el) {
100 struct value *val = element_getvalue (el);
101 if (el != list_head (regs))
102 fprintf (out, ", ");
103 fprintf (out, "\"=r\"(");
104 print_value (out, val);
105 fprintf (out, ")");
106 el = element_next (el);
110 static
111 void print_asm (FILE *out, struct operation *op, int identsize, int options)
113 struct location *loc;
115 ident_line (out, identsize);
116 fprintf (out, "__asm__ (");
117 for (loc = op->info.asmop.begin; ; loc++) {
118 if (loc != op->info.asmop.begin) {
119 fprintf (out, "\n");
120 ident_line (out, identsize);
121 fprintf (out, " ");
123 fprintf (out, "\"%s\"", allegrex_disassemble (loc->opc, loc->address, FALSE));
124 if (loc == op->info.asmop.end) break;
126 if (list_size (op->results) != 0 || list_size (op->operands) != 0) {
127 print_asm_reglist (out, op->results, identsize, options);
128 if (list_size (op->operands) != 0) {
129 print_asm_reglist (out, op->operands, identsize, options);
133 fprintf (out, ");\n");
136 static
137 void print_binaryop (FILE *out, struct operation *op, const char *opsymbol, int options)
139 if (!(options & OPTS_DEFERRED)) {
140 print_value (out, list_headvalue (op->results));
141 fprintf (out, " = ");
143 print_value (out, list_headvalue (op->operands));
144 fprintf (out, " %s ", opsymbol);
145 print_value (out, list_tailvalue (op->operands));
148 void print_complexop (FILE *out, struct operation *op, const char *opsymbol, int options)
150 element el;
152 if (list_size (op->results) != 0 && !(options & OPTS_DEFERRED)) {
153 print_value (out, list_headvalue (op->results));
154 fprintf (out, " = ");
157 fprintf (out, "%s (", opsymbol);
158 el = list_head (op->operands);
159 while (el) {
160 struct value *val;
161 val = element_getvalue (el);
162 if (val->type == VAL_VARIABLE) {
163 if (val->val.variable->type == VARIABLE_INVALID) break;
165 if (el != list_head (op->operands))
166 fprintf (out, ", ");
167 print_value (out, val);
168 el = element_next (el);
170 fprintf (out, ")");
173 void print_call (FILE *out, struct operation *op, int options)
175 element el;
177 if (list_size (op->info.callop.retvalues) != 0 && !(options & OPTS_DEFERRED)) {
178 el = list_head (op->info.callop.retvalues);
179 while (el) {
180 print_value (out, list_tailvalue (op->results));
181 fprintf (out, " ");
182 el = element_next (el);
184 fprintf (out, "= ");
187 if (op->block->info.call.calltarget) {
188 print_subroutine_name (out, op->block->info.call.calltarget);
189 } else {
190 fprintf (out, "CALL");
193 fprintf (out, " (");
195 el = list_head (op->info.callop.arguments);
196 while (el) {
197 struct value *val;
198 val = element_getvalue (el);
199 if (val->type == VAL_VARIABLE) {
200 if (val->val.variable->type == VARIABLE_INVALID) break;
202 if (el != list_head (op->info.callop.arguments))
203 fprintf (out, ", ");
204 print_value (out, val);
205 el = element_next (el);
207 fprintf (out, ")");
210 static
211 void print_ext (FILE *out, struct operation *op, int options)
213 struct value *val1, *val2, *val3;
214 element el;
215 uint32 mask;
217 el = list_head (op->operands);
218 val1 = element_getvalue (el); el = element_next (el);
219 val2 = element_getvalue (el); el = element_next (el);
220 val3 = element_getvalue (el);
222 mask = 0xFFFFFFFF >> (32 - val3->val.intval);
223 if (!(options & OPTS_DEFERRED)) {
224 print_value (out, list_headvalue (op->results));
225 fprintf (out, " = ");
228 fprintf (out, "(");
229 print_value (out, val1);
230 fprintf (out, " >> %d)", val2->val.intval);
231 fprintf (out, " & 0x%08X", mask);
234 static
235 void print_ins (FILE *out, struct operation *op, int options)
237 struct value *val1, *val2, *val3, *val4;
238 element el;
239 uint32 mask;
241 el = list_head (op->operands);
242 val1 = element_getvalue (el); el = element_next (el);
243 val2 = element_getvalue (el); el = element_next (el);
244 val3 = element_getvalue (el); el = element_next (el);
245 val4 = element_getvalue (el);
247 mask = 0xFFFFFFFF >> (32 - val4->val.intval);
248 if (!(options & OPTS_DEFERRED)) {
249 print_value (out, list_headvalue (op->results));
250 fprintf (out, " = ");
253 fprintf (out, "(");
254 print_value (out, val2);
255 fprintf (out, " & 0x%08X) | (", ~(mask << val3->val.intval));
256 print_value (out, val1);
257 fprintf (out, " & 0x%08X)", mask);
260 static
261 void print_nor (FILE *out, struct operation *op, int options)
263 struct value *val1, *val2;
264 int simple = 0;
266 val1 = list_headvalue (op->operands);
267 val2 = list_tailvalue (op->operands);
269 if (val1->val.intval == 0 || val2->val.intval == 0) {
270 simple = 1;
271 if (val1->val.intval == 0) val1 = val2;
274 if (!(options & OPTS_DEFERRED)) {
275 print_value (out, list_headvalue (op->results));
276 fprintf (out, " = ");
279 if (!simple) {
280 fprintf (out, "!(");
281 print_value (out, val1);
282 fprintf (out, " | ");
283 print_value (out, val2);
284 fprintf (out, ")");
285 } else {
286 fprintf (out, "!");
287 print_value (out, val1);
291 static
292 void print_movnz (FILE *out, struct operation *op, int ismovn, int options)
294 struct value *val1, *val2, *val3;
295 struct value *result;
296 element el;
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);
302 result = list_headvalue (op->results);
304 if (!(options & OPTS_DEFERRED)) {
305 print_value (out, result);
306 fprintf (out, " = ");
309 if (ismovn)
310 fprintf (out, "(");
311 else
312 fprintf (out, "!(");
313 print_value (out, val2);
314 fprintf (out, ") ? ");
315 print_value (out, val1);
316 fprintf (out, " : ");
317 print_value (out, val3);
320 static
321 void print_slt (FILE *out, struct operation *op, int isunsigned, int options)
323 struct value *val1, *val2;
324 struct value *result;
325 element el;
327 el = list_head (op->operands);
328 val1 = element_getvalue (el); el = element_next (el);
329 val2 = element_getvalue (el);
330 result = list_headvalue (op->results);
332 if (!(options & OPTS_DEFERRED)) {
333 print_value (out, result);
334 fprintf (out, " = ");
337 fprintf (out, "(");
339 print_value (out, val1);
340 fprintf (out, " < ");
341 print_value (out, val2);
342 fprintf (out, ")");
345 static
346 void print_signextend (FILE *out, struct operation *op, int isbyte, int options)
348 if (!(options & OPTS_DEFERRED)) {
349 print_value (out, list_headvalue (op->results));
350 fprintf (out, " = ");
353 if (isbyte)
354 fprintf (out, "(char) ");
355 else
356 fprintf (out, "(short) ");
358 print_value (out, list_headvalue (op->operands));
361 static
362 void print_memory_address (FILE *out, struct operation *op, int size, int isunsigned, int options)
364 struct value *val;
365 uint32 address;
366 const char *type;
368 if (size == 0) {
369 if (isunsigned) type = "unsigned char *";
370 else type = "char *";
371 } else if (size == 1) {
372 if (isunsigned) type = "unsigned short *";
373 else type = "short *";
374 } else if (size == 2) {
375 type = "int *";
378 val = list_headvalue (op->operands);
379 if (val->type == VAL_VARIABLE) {
380 if (val->val.variable->type == VARIABLE_CONSTANT) {
381 address = val->val.variable->type;
382 val = list_tailvalue (op->operands);
383 address += val->val.intval;
384 fprintf (out, "*((%s) 0x%08X)", type, address);
385 return;
389 fprintf (out, "((%s) ", type);
390 print_value (out, val);
391 val = list_tailvalue (op->operands);
392 fprintf (out, ")[%d]", val->val.intval >> size);
395 static
396 void print_load (FILE *out, struct operation *op, int size, int isunsigned, int options)
398 if (!(options & OPTS_DEFERRED)) {
399 print_value (out, list_headvalue (op->results));
400 fprintf (out, " = ");
402 print_memory_address (out, op, size, isunsigned, options);
405 static
406 void print_store (FILE *out, struct operation *op, int size, int isunsigned, int options)
408 struct value *val = element_getvalue (element_next (list_head (op->operands)));
409 print_memory_address (out, op, size, isunsigned, options);
410 fprintf (out, " = ");
411 print_value (out, val);
414 static
415 void print_condition (FILE *out, struct operation *op, int options)
417 fprintf (out, "if (");
418 if (options & OPTS_REVERSECOND) fprintf (out, "!(");
419 print_value (out, list_headvalue (op->operands));
420 switch (op->info.iop.insn) {
421 case I_BNE:
422 fprintf (out, " != ");
423 break;
424 case I_BEQ:
425 fprintf (out, " == ");
426 break;
427 case I_BGEZ:
428 case I_BGEZAL:
429 fprintf (out, " >= 0");
430 break;
431 case I_BGTZ:
432 fprintf (out, " > 0");
433 break;
434 case I_BLEZ:
435 fprintf (out, " <= 0");
436 break;
437 case I_BLTZ:
438 case I_BLTZAL:
439 fprintf (out, " < 0");
440 break;
441 default:
442 break;
444 if (list_size (op->operands) == 2)
445 print_value (out, list_tailvalue (op->operands));
447 if (options & OPTS_REVERSECOND) fprintf (out, ")");
448 fprintf (out, ")");
453 void print_operation (FILE *out, struct operation *op, int identsize, int options)
455 int nosemicolon = FALSE;
457 if (op->type == OP_ASM) {
458 print_asm (out, op, identsize, options);
459 return;
462 if (op->type == OP_INSTRUCTION) {
463 if (op->info.iop.loc->insn->flags & (INSN_JUMP))
464 return;
465 } else if (op->type == OP_NOP || op->type == OP_START ||
466 op->type == OP_END || op->type == OP_PHI) {
467 return;
470 ident_line (out, identsize);
471 if (op->type == OP_INSTRUCTION) {
472 switch (op->info.iop.insn) {
473 case I_ADD: print_binaryop (out, op, "+", options); break;
474 case I_ADDU: print_binaryop (out, op, "+", options); break;
475 case I_SUB: print_binaryop (out, op, "-", options); break;
476 case I_SUBU: print_binaryop (out, op, "-", options); break;
477 case I_XOR: print_binaryop (out, op, "^", options); break;
478 case I_AND: print_binaryop (out, op, "&", options); break;
479 case I_OR: print_binaryop (out, op, "|", options); break;
480 case I_SRAV: print_binaryop (out, op, ">>", options); break;
481 case I_SRLV: print_binaryop (out, op, ">>", options); break;
482 case I_SLLV: print_binaryop (out, op, "<<", options); break;
483 case I_INS: print_ins (out, op, options); break;
484 case I_EXT: print_ext (out, op, options); break;
485 case I_MIN: print_complexop (out, op, "MIN", options); break;
486 case I_MAX: print_complexop (out, op, "MAX", options); break;
487 case I_BITREV: print_complexop (out, op, "BITREV", options); break;
488 case I_CLZ: print_complexop (out, op, "CLZ", options); break;
489 case I_CLO: print_complexop (out, op, "CLO", options); break;
490 case I_NOR: print_nor (out, op, options); break;
491 case I_MOVN: print_movnz (out, op, TRUE, options); break;
492 case I_MOVZ: print_movnz (out, op, FALSE, options); break;
493 case I_SLT: print_slt (out, op, FALSE, options); break;
494 case I_SLTU: print_slt (out, op, TRUE, options); break;
495 case I_LW: print_load (out, op, 2, FALSE, options); break;
496 case I_LB: print_load (out, op, 0, FALSE, options); break;
497 case I_LBU: print_load (out, op, 0, TRUE, options); break;
498 case I_LH: print_load (out, op, 1, FALSE, options); break;
499 case I_LHU: print_load (out, op, 1, TRUE, options); break;
500 case I_LL: print_complexop (out, op, "LL", options); break;
501 case I_LWL: print_complexop (out, op, "LWL", options); break;
502 case I_LWR: print_complexop (out, op, "LWR", options); break;
503 case I_SW: print_store (out, op, 2, FALSE, options); break;
504 case I_SH: print_store (out, op, 1, FALSE, options); break;
505 case I_SB: print_store (out, op, 0, FALSE, options); break;
506 case I_SC: print_complexop (out, op, "SC", options); break;
507 case I_SWL: print_complexop (out, op, "SWL", options); break;
508 case I_SWR: print_complexop (out, op, "SWR", options); break;
509 case I_SEB: print_signextend (out, op, TRUE, options); break;
510 case I_SEH: print_signextend (out, op, TRUE, options); break;
511 default:
512 if (op->info.iop.loc->insn->flags & INSN_BRANCH) {
513 print_condition (out, op, options);
514 nosemicolon = TRUE;
516 break;
518 } else if (op->type == OP_MOVE) {
519 if (!options) {
520 print_value (out, list_headvalue (op->results));
521 fprintf (out, " = ");
523 print_value (out, list_headvalue (op->operands));
524 } else if (op->type == OP_CALL) {
525 print_call (out, op, options);
528 if (!(options & OPTS_DEFERRED)) {
529 if (nosemicolon) fprintf (out, "\n");
530 else fprintf (out, ";\n");