Passo intermediario, ainda falta um longo caminho
[pspdecompiler.git] / outcode.c
blobdf79c58870199480a40a17530d1786d35c54f27b
2 #include <stdio.h>
3 #include <ctype.h>
5 #include "output.h"
6 #include "utils.h"
9 static
10 void print_block (FILE *out, struct basicblock *block, int reversecond)
12 element opel;
13 struct operation *jumpop = NULL;
14 int options = 0;
16 if (reversecond) options |= OPTS_REVERSECOND;
17 opel = list_head (block->operations);
18 while (opel) {
19 struct operation *op = element_getvalue (opel);
20 if (!(op->status & OPERATION_DEFERRED)) {
21 if (op->type == OP_INSTRUCTION) {
22 if (op->info.iop.loc->insn->flags & (INSN_JUMP | INSN_BRANCH))
23 jumpop = op;
25 if (op != jumpop)
26 print_operation (out, op, block->identsize + 1, options);
28 opel = element_next (opel);
30 if (jumpop)
31 print_operation (out, jumpop, block->identsize + 1, options);
34 static
35 void print_block_recursive (FILE *out, struct basicblock *block, int verbosity)
37 struct basicedge *edge;
38 int reversecond = FALSE, haselse = FALSE;
39 element ref;
41 block->mark1 = 1;
43 if (block->haslabel) {
44 fprintf (out, "\n");
45 ident_line (out, block->identsize);
46 fprintf (out, "label%d:\n", block->node.dfsnum);
49 if (block->loopst) {
50 if (block->loopst->start == block) {
51 ident_line (out, block->identsize);
52 fprintf (out, "loop {\n");
56 if (verbosity > 2) {
57 ident_line (out, block->identsize + 1);
58 fprintf (out, "/* Block %d ", block->node.dfsnum);
59 if (block->type == BLOCK_SIMPLE) {
60 fprintf (out, "Address 0x%08X ", block->info.simple.begin->address);
62 fprintf (out, "*/\n");
65 if (block->st) {
66 struct basicedge *edge1, *edge2;
68 edge1 = list_headvalue (block->outrefs);
69 edge2 = list_tailvalue (block->outrefs);
71 if (edge1->type != EDGE_IFEXIT &&
72 edge2->type != EDGE_IFEXIT) {
73 haselse = TRUE;
74 } else {
75 if (edge2->type == EDGE_IFEXIT)
76 reversecond = TRUE;
80 print_block (out, block, reversecond);
83 if (reversecond)
84 ref = list_tail (block->outrefs);
85 else
86 ref = list_head (block->outrefs);
88 while (ref) {
89 edge = element_getvalue (ref);
91 if (edge->type == EDGE_FOLLOW) {
92 if (block->st) {
93 ident_line (out, block->identsize + 1);
94 fprintf (out, "{\n");
96 print_block_recursive (out, edge->to, verbosity);
97 if (block->st) {
98 ident_line (out, block->identsize + 1);
99 fprintf (out, "}\n");
101 } else if (edge->type != EDGE_IFEXIT) {
102 int identsize = block->identsize + 1;
103 if (block->st) identsize++;
104 ident_line (out, identsize);
105 switch (edge->type) {
106 case EDGE_GOTO: fprintf (out, "goto label%d;\n", edge->to->node.dfsnum); break;
107 case EDGE_BREAK: fprintf (out, "break;\n"); break;
108 case EDGE_CONTINUE: fprintf (out, "continue;\n"); break;
109 default:
110 break;
114 if (reversecond)
115 ref = element_previous (ref);
116 else
117 ref = element_next (ref);
119 if (ref && haselse) {
120 ident_line (out, block->identsize + 1);
121 fprintf (out, "else\n");
126 if (block->st) {
127 if (block->st->end && block->st->info.ifctrl.isoutermost) {
128 if (block->st->hasendgoto) {
129 ident_line (out, block->identsize + 1);
130 fprintf (out, "goto label%d;\n", block->st->end->node.dfsnum);
131 } else {
132 print_block_recursive (out, block->st->end, verbosity);
137 if (block->loopst) {
138 if (block->loopst->start == block) {
139 ident_line (out, block->identsize);
140 fprintf (out, "}\n");
141 if (block->loopst->end) {
142 if (block->loopst->hasendgoto) {
143 ident_line (out, block->identsize);
144 fprintf (out, "goto label%d;\n", block->loopst->end->node.dfsnum);
145 } else {
146 print_block_recursive (out, block->loopst->end, verbosity);
153 static
154 void print_subroutine (FILE *out, struct subroutine *sub, int verbosity)
156 if (sub->import) { return; }
158 fprintf (out, "/**\n * Subroutine at address 0x%08X\n", sub->begin->address);
159 if (verbosity > 1 && !sub->haserror) {
160 struct location *loc = sub->begin;
161 for (loc = sub->begin; ; loc++) {
162 fprintf (out, " * %s\n", allegrex_disassemble (loc->opc, loc->address, TRUE));
163 if (loc == sub->end) break;
166 fprintf (out, " */\n");
167 print_subroutine_declaration (out, sub);
168 fprintf (out, "\n{\n");
170 if (sub->haserror) {
171 struct location *loc;
172 for (loc = sub->begin; ; loc++) {
173 fprintf (out, "%s\n", allegrex_disassemble (loc->opc, loc->address, TRUE));
174 if (loc == sub->end) break;
176 } else {
177 element el;
178 reset_marks (sub);
180 el = list_head (sub->blocks);
181 while (el) {
182 struct basicblock *block = element_getvalue (el);
183 if (!block->mark1)
184 print_block_recursive (out, block, verbosity);
185 el = element_next (el);
188 fprintf (out, "}\n\n");
191 static
192 void print_source (FILE *out, struct code *c, char *headerfilename, int verbosity)
194 uint32 i, j;
195 element el;
197 fprintf (out, "#include <pspsdk.h>\n");
198 fprintf (out, "#include \"%s\"\n\n", headerfilename);
200 for (i = 0; i < c->file->modinfo->numimports; i++) {
201 struct prx_import *imp = &c->file->modinfo->imports[i];
203 fprintf (out, "/*\n * Imports from library: %s\n */\n", imp->name);
204 for (j = 0; j < imp->nfuncs; j++) {
205 struct prx_function *func = &imp->funcs[j];
206 if (func->pfunc) {
207 fprintf (out, "extern ");
208 print_subroutine_declaration (out, func->pfunc);
209 fprintf (out, ";\n");
212 fprintf (out, "\n");
215 el = list_head (c->subroutines);
216 while (el) {
217 struct subroutine *sub;
218 sub = element_getvalue (el);
220 print_subroutine (out, sub, verbosity);
221 el = element_next (el);
226 static
227 void print_header (FILE *out, struct code *c, char *headerfilename)
229 uint32 i, j;
230 char buffer[256];
231 int pos = 0;
233 while (pos < sizeof (buffer) - 1) {
234 char c = headerfilename[pos];
235 if (!c) break;
236 if (c == '.') c = '_';
237 else c = toupper (c);
238 buffer[pos++] = c;
240 buffer[pos] = '\0';
242 fprintf (out, "#ifndef __%s\n", buffer);
243 fprintf (out, "#define __%s\n\n", buffer);
245 for (i = 0; i < c->file->modinfo->numexports; i++) {
246 struct prx_export *exp = &c->file->modinfo->exports[i];
248 fprintf (out, "/*\n * Exports from library: %s\n */\n", exp->name);
249 for (j = 0; j < exp->nfuncs; j++) {
250 struct prx_function *func = &exp->funcs[j];
251 if (func->name) {
252 fprintf (out, "void %s (void);\n",func->name);
253 } else {
254 fprintf (out, "void %s_%08X (void);\n", exp->name, func->nid);
257 fprintf (out, "\n");
260 fprintf (out, "#endif /* __%s */\n", buffer);
264 int print_code (struct code *c, char *prxname, int verbosity)
266 char buffer[64];
267 char basename[32];
268 FILE *cout, *hout;
271 get_base_name (prxname, basename, sizeof (basename));
272 sprintf (buffer, "%s.c", basename);
274 cout = fopen (buffer, "w");
275 if (!cout) {
276 xerror (__FILE__ ": can't open file for writing `%s'", buffer);
277 return 0;
280 sprintf (buffer, "%s.h", basename);
281 hout = fopen (buffer, "w");
282 if (!hout) {
283 xerror (__FILE__ ": can't open file for writing `%s'", buffer);
284 return 0;
288 print_header (hout, c, buffer);
289 print_source (cout, c, buffer, verbosity);
291 fclose (cout);
292 fclose (hout);
293 return 1;