Melhorado o structures
[pspdecompiler.git] / outcode.c
blob0e727dadee787b92fb356c31699b63f441bac2cd
1 /**
2 * Author: Humberto Naves (hsnaves@gmail.com)
3 */
5 #include <stdio.h>
6 #include <ctype.h>
8 #include "output.h"
9 #include "utils.h"
12 static
13 void print_block (FILE *out, struct basicblock *block, int identsize, int reversecond)
15 element opel;
16 int options = 0;
18 if (reversecond) options |= OPTS_REVERSECOND;
19 opel = list_head (block->operations);
20 while (opel) {
21 struct operation *op = element_getvalue (opel);
22 if (!(op->status & OP_STAT_DEFERRED)) {
23 if (op != block->jumpop)
24 print_operation (out, op, identsize, options);
26 opel = element_next (opel);
28 if (block->jumpop)
29 print_operation (out, block->jumpop, identsize, options);
32 static
33 void print_block_recursive (FILE *out, struct basicblock *block)
35 element ref;
36 struct basicedge *edge;
37 int identsize = block->st->identsize;
38 int revcond = block->status & BLOCK_STAT_REVCOND;
39 int first = TRUE, isloop = FALSE;
41 if (g_verbosity > 1) {
42 fprintf (out, "block%d:\n", block->node.dfsnum);
43 if (block->type == BLOCK_SIMPLE){
44 struct location *loc;
45 loc = block->info.simple.begin;
46 while (1) {
47 fprintf (out, " %s\n", allegrex_disassemble (loc->opc, loc->address, TRUE));
48 if (loc++ == block->info.simple.end) break;
53 if (block->status & BLOCK_STAT_ISSWITCHTARGET) {
54 ref = list_head (block->inrefs);
55 while (ref) {
56 edge = element_getvalue (ref);
57 if (edge->from->status & BLOCK_STAT_ISSWITCH) {
58 ident_line (out, identsize);
59 fprintf (out, "case %d:\n", edge->fromnum);
61 ref = element_next (ref);
65 if (block->status & BLOCK_STAT_HASLABEL) {
66 fprintf (out, "\n");
67 ident_line (out, identsize);
68 fprintf (out, "label%d:\n", block->node.dfsnum);
71 if (block->st->start == block && block->st->type == CONTROL_LOOP) {
72 isloop = TRUE;
73 ident_line (out, identsize);
74 fprintf (out, "while (1) {\n");
77 block->mark1 = 1;
78 print_block (out, block, identsize + 1, revcond);
80 if (block->status & BLOCK_STAT_ISSWITCH) {
81 revcond = TRUE;
82 ident_line (out, identsize + 1);
83 fprintf (out, "switch () {\n");
86 if (revcond) ref = list_head (block->outrefs);
87 else ref = list_tail (block->outrefs);
89 while (ref) {
90 edge = element_getvalue (ref);
91 if (edge->type != EDGE_CASE && edge->type != EDGE_NEXT &&
92 edge->type != EDGE_IFEXIT && edge->type != EDGE_UNKNOWN) {
93 ident_line (out, identsize + 1);
94 if (first && list_size (block->outrefs) == 2 &&
95 !(block->status & BLOCK_STAT_ISSWITCH) && edge->type != EDGE_IFENTER)
96 ident_line (out, 1);
99 switch (edge->type) {
100 case EDGE_BREAK:
101 fprintf (out, "break;\n");
102 break;
103 case EDGE_CONTINUE:
104 fprintf (out, "continue;\n");
105 break;
106 case EDGE_INVALID:
107 case EDGE_GOTO:
108 fprintf (out, "goto label%d;\n", edge->to->node.dfsnum);
109 break;
110 case EDGE_UNKNOWN:
111 case EDGE_IFEXIT:
112 break;
113 case EDGE_CASE:
114 if (!edge->to->mark1)
115 print_block_recursive (out, edge->to);
116 break;
117 case EDGE_NEXT:
118 print_block_recursive (out, edge->to);
119 break;
120 case EDGE_IFENTER:
121 fprintf (out, "{\n");
122 print_block_recursive (out, edge->to);
123 ident_line (out, identsize + 1);
124 fprintf (out, "}\n");
125 break;
128 if (revcond) ref = element_next (ref);
129 else ref = element_previous (ref);
131 if ((block->status & BLOCK_STAT_HASELSE) && ref) {
132 ident_line (out, identsize + 1);
133 fprintf (out, "else\n");
135 first = FALSE;
138 if (block->ifst) {
139 if (block->ifst->hasendgoto) {
140 ident_line (out, identsize + 1);
141 fprintf (out, "goto label%d;\n", block->ifst->end->node.dfsnum);
142 } else if (block->ifst->info.ifctrl.endfollow) {
143 print_block_recursive (out, block->ifst->end);
147 if (block->status & BLOCK_STAT_ISSWITCH) {
148 ident_line (out, identsize + 1);
149 fprintf (out, "}\n");
152 if (block->st->start == block && block->st->type == CONTROL_LOOP) {
153 ident_line (out, identsize);
154 fprintf (out, "}\n");
155 if (block->st->hasendgoto) {
156 ident_line (out, identsize);
157 fprintf (out, "goto label%d;\n", block->st->end->node.dfsnum);
158 } else {
159 print_block_recursive (out, block->st->end);
165 static
166 void print_subroutine (FILE *out, struct subroutine *sub)
168 if (sub->import) { return; }
170 fprintf (out, "/**\n * Subroutine at address 0x%08X\n", sub->begin->address);
171 fprintf (out, " */\n");
172 print_subroutine_declaration (out, sub);
173 fprintf (out, "\n{\n");
175 if (sub->haserror) {
176 struct location *loc;
177 for (loc = sub->begin; ; loc++) {
178 fprintf (out, "%s\n", allegrex_disassemble (loc->opc, loc->address, TRUE));
179 if (loc == sub->end) break;
181 } else {
182 element el;
183 reset_marks (sub);
185 el = list_head (sub->blocks);
186 while (el) {
187 struct basicblock *block = element_getvalue (el);
188 if (!block->mark1)
189 print_block_recursive (out, block);
190 el = element_next (el);
193 fprintf (out, "}\n\n");
196 static
197 void print_source (FILE *out, struct code *c, char *headerfilename)
199 uint32 i, j;
200 element el;
202 fprintf (out, "#include <pspsdk.h>\n");
203 fprintf (out, "#include \"%s\"\n\n", headerfilename);
205 for (i = 0; i < c->file->modinfo->numimports; i++) {
206 struct prx_import *imp = &c->file->modinfo->imports[i];
208 fprintf (out, "/*\n * Imports from library: %s\n */\n", imp->name);
209 for (j = 0; j < imp->nfuncs; j++) {
210 struct prx_function *func = &imp->funcs[j];
211 if (func->pfunc) {
212 fprintf (out, "extern ");
213 print_subroutine_declaration (out, func->pfunc);
214 fprintf (out, ";\n");
217 fprintf (out, "\n");
220 el = list_head (c->subroutines);
221 while (el) {
222 struct subroutine *sub;
223 sub = element_getvalue (el);
225 print_subroutine (out, sub);
226 el = element_next (el);
231 static
232 void print_header (FILE *out, struct code *c, char *headerfilename)
234 uint32 i, j;
235 char buffer[256];
236 int pos = 0;
238 while (pos < sizeof (buffer) - 1) {
239 char c = headerfilename[pos];
240 if (!c) break;
241 if (c == '.') c = '_';
242 else c = toupper (c);
243 buffer[pos++] = c;
245 buffer[pos] = '\0';
247 fprintf (out, "#ifndef __%s\n", buffer);
248 fprintf (out, "#define __%s\n\n", buffer);
250 for (i = 0; i < c->file->modinfo->numexports; i++) {
251 struct prx_export *exp = &c->file->modinfo->exports[i];
253 fprintf (out, "/*\n * Exports from library: %s\n */\n", exp->name);
254 for (j = 0; j < exp->nfuncs; j++) {
255 struct prx_function *func = &exp->funcs[j];
256 if (func->name) {
257 fprintf (out, "void %s (void);\n",func->name);
258 } else {
259 fprintf (out, "void %s_%08X (void);\n", exp->name, func->nid);
262 fprintf (out, "\n");
265 fprintf (out, "#endif /* __%s */\n", buffer);
269 int print_code (struct code *c, char *prxname)
271 char buffer[64];
272 char basename[32];
273 FILE *cout, *hout;
276 get_base_name (prxname, basename, sizeof (basename));
277 sprintf (buffer, "%s.c", basename);
279 cout = fopen (buffer, "w");
280 if (!cout) {
281 xerror (__FILE__ ": can't open file for writing `%s'", buffer);
282 return 0;
285 sprintf (buffer, "%s.h", basename);
286 hout = fopen (buffer, "w");
287 if (!hout) {
288 xerror (__FILE__ ": can't open file for writing `%s'", buffer);
289 return 0;
293 print_header (hout, c, buffer);
294 print_source (cout, c, buffer);
296 fclose (cout);
297 fclose (hout);
298 return 1;