Hlide problem solved (i believe)
[pspdecompiler.git] / outcode.c
blobfaea6b811c22f572e34e93e1759a7adc03f4bc5b
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 ident_line (out, identsize + 1);
43 fprintf (out, "/** Block %d\n", block->node.dfsnum);
44 if (block->type == BLOCK_SIMPLE){
45 struct location *loc;
46 loc = block->info.simple.begin;
47 while (1) {
48 ident_line (out, identsize + 1);
49 fprintf (out, " * %s\n", allegrex_disassemble (loc->opc, loc->address, TRUE));
50 if (loc++ == block->info.simple.end) break;
53 ident_line (out, identsize + 1);
54 fprintf (out, " */\n");
57 if (block->status & BLOCK_STAT_ISSWITCHTARGET) {
58 ref = list_head (block->inrefs);
59 while (ref) {
60 edge = element_getvalue (ref);
61 if (edge->from->status & BLOCK_STAT_ISSWITCH) {
62 ident_line (out, identsize);
63 fprintf (out, "case %d:\n", edge->fromnum);
65 ref = element_next (ref);
69 if (block->status & BLOCK_STAT_HASLABEL) {
70 fprintf (out, "\n");
71 ident_line (out, identsize);
72 fprintf (out, "label%d:\n", block->node.dfsnum);
75 if (block->st->start == block && block->st->type == CONTROL_LOOP) {
76 isloop = TRUE;
77 ident_line (out, identsize);
78 fprintf (out, "while (1) {\n");
81 block->mark1 = 1;
82 print_block (out, block, identsize + 1, revcond);
84 if (block->status & BLOCK_STAT_ISSWITCH) {
85 revcond = TRUE;
86 ident_line (out, identsize + 1);
87 fprintf (out, "switch () {\n");
90 if (revcond) ref = list_head (block->outrefs);
91 else ref = list_tail (block->outrefs);
93 while (ref) {
94 edge = element_getvalue (ref);
96 switch (edge->type) {
97 case EDGE_BREAK:
98 case EDGE_CONTINUE:
99 case EDGE_INVALID:
100 case EDGE_GOTO:
101 case EDGE_IFENTER:
102 ident_line (out, identsize + 1);
103 if (first && list_size (block->outrefs) == 2 &&
104 !(block->status & BLOCK_STAT_ISSWITCH) && edge->type != EDGE_IFENTER)
105 ident_line (out, 1);
106 break;
108 case EDGE_CASE:
109 case EDGE_NEXT:
110 case EDGE_RETURN:
111 case EDGE_IFEXIT:
112 case EDGE_UNKNOWN:
113 break;
116 switch (edge->type) {
117 case EDGE_BREAK:
118 fprintf (out, "break;\n");
119 break;
120 case EDGE_CONTINUE:
121 fprintf (out, "continue;\n");
122 break;
123 case EDGE_INVALID:
124 case EDGE_GOTO:
125 fprintf (out, "goto label%d;\n", edge->to->node.dfsnum);
126 break;
127 case EDGE_UNKNOWN:
128 case EDGE_IFEXIT:
129 break;
130 case EDGE_CASE:
131 if (!edge->to->mark1)
132 print_block_recursive (out, edge->to);
133 break;
134 case EDGE_NEXT:
135 case EDGE_RETURN:
136 print_block_recursive (out, edge->to);
137 break;
138 case EDGE_IFENTER:
139 fprintf (out, "{\n");
140 print_block_recursive (out, edge->to);
141 ident_line (out, identsize + 1);
142 fprintf (out, "}\n");
143 break;
146 if (revcond) ref = element_next (ref);
147 else ref = element_previous (ref);
149 if ((block->status & BLOCK_STAT_HASELSE) && ref) {
150 ident_line (out, identsize + 1);
151 fprintf (out, "else\n");
153 first = FALSE;
156 if (block->ifst) {
157 if (block->ifst->hasendgoto) {
158 ident_line (out, identsize + 1);
159 fprintf (out, "goto label%d;\n", block->ifst->end->node.dfsnum);
160 } else if (block->ifst->endfollow) {
161 print_block_recursive (out, block->ifst->end);
165 if (block->status & BLOCK_STAT_ISSWITCH) {
166 ident_line (out, identsize + 1);
167 fprintf (out, "}\n");
170 if (block->st->start == block && block->st->type == CONTROL_LOOP) {
171 ident_line (out, identsize);
172 fprintf (out, "}\n");
173 if (block->st->hasendgoto) {
174 ident_line (out, identsize);
175 fprintf (out, "goto label%d;\n", block->st->end->node.dfsnum);
176 } else if (block->st->endfollow) {
177 print_block_recursive (out, block->st->end);
183 static
184 void print_subroutine (FILE *out, struct subroutine *sub)
186 if (sub->import) { return; }
188 fprintf (out, "/**\n * Subroutine at address 0x%08X\n", sub->begin->address);
189 fprintf (out, " */\n");
190 print_subroutine_declaration (out, sub);
191 fprintf (out, "\n{\n");
193 if (sub->haserror) {
194 struct location *loc;
195 for (loc = sub->begin; ; loc++) {
196 fprintf (out, "%s\n", allegrex_disassemble (loc->opc, loc->address, TRUE));
197 if (loc == sub->end) break;
199 } else {
200 element el;
201 reset_marks (sub);
203 el = list_head (sub->blocks);
204 while (el) {
205 struct basicblock *block = element_getvalue (el);
206 if (!block->mark1)
207 print_block_recursive (out, block);
208 el = element_next (el);
211 fprintf (out, "}\n\n");
214 static
215 void print_source (FILE *out, struct code *c, char *headerfilename)
217 uint32 i, j;
218 element el;
220 fprintf (out, "#include <pspsdk.h>\n");
221 fprintf (out, "#include \"%s\"\n\n", headerfilename);
223 for (i = 0; i < c->file->modinfo->numimports; i++) {
224 struct prx_import *imp = &c->file->modinfo->imports[i];
226 fprintf (out, "/*\n * Imports from library: %s\n */\n", imp->name);
227 for (j = 0; j < imp->nfuncs; j++) {
228 struct prx_function *func = &imp->funcs[j];
229 if (func->pfunc) {
230 fprintf (out, "extern ");
231 print_subroutine_declaration (out, func->pfunc);
232 fprintf (out, ";\n");
235 fprintf (out, "\n");
238 el = list_head (c->subroutines);
239 while (el) {
240 struct subroutine *sub;
241 sub = element_getvalue (el);
243 print_subroutine (out, sub);
244 el = element_next (el);
249 static
250 void print_header (FILE *out, struct code *c, char *headerfilename)
252 uint32 i, j;
253 char buffer[256];
254 int pos = 0;
256 while (pos < sizeof (buffer) - 1) {
257 char c = headerfilename[pos];
258 if (!c) break;
259 if (c == '.') c = '_';
260 else c = toupper (c);
261 buffer[pos++] = c;
263 buffer[pos] = '\0';
265 fprintf (out, "#ifndef __%s\n", buffer);
266 fprintf (out, "#define __%s\n\n", buffer);
268 for (i = 0; i < c->file->modinfo->numexports; i++) {
269 struct prx_export *exp = &c->file->modinfo->exports[i];
271 fprintf (out, "/*\n * Exports from library: %s\n */\n", exp->name);
272 for (j = 0; j < exp->nfuncs; j++) {
273 struct prx_function *func = &exp->funcs[j];
274 if (func->name) {
275 fprintf (out, "void %s (void);\n",func->name);
276 } else {
277 fprintf (out, "void %s_%08X (void);\n", exp->name, func->nid);
280 fprintf (out, "\n");
283 fprintf (out, "#endif /* __%s */\n", buffer);
287 int print_code (struct code *c, char *prxname)
289 char buffer[64];
290 char basename[32];
291 FILE *cout, *hout;
294 get_base_name (prxname, basename, sizeof (basename));
295 sprintf (buffer, "%s.c", basename);
297 cout = fopen (buffer, "w");
298 if (!cout) {
299 xerror (__FILE__ ": can't open file for writing `%s'", buffer);
300 return 0;
303 sprintf (buffer, "%s.h", basename);
304 hout = fopen (buffer, "w");
305 if (!hout) {
306 xerror (__FILE__ ": can't open file for writing `%s'", buffer);
307 return 0;
311 print_header (hout, c, buffer);
312 print_source (cout, c, buffer);
314 fclose (cout);
315 fclose (hout);
316 return 1;