Com o autor
[pspdecompiler.git] / outcode.c
blobd744415a850f3d25d7f81609a14be05708686aee
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 struct operation *jumpop = NULL;
17 int options = 0;
19 if (reversecond) options |= OPTS_REVERSECOND;
20 opel = list_head (block->operations);
21 while (opel) {
22 struct operation *op = element_getvalue (opel);
23 if (!(op->status & OP_STAT_DEFERRED)) {
24 if (op->type == OP_INSTRUCTION) {
25 if (op->info.iop.loc->insn->flags & (INSN_JUMP | INSN_BRANCH))
26 jumpop = op;
28 if (op != jumpop)
29 print_operation (out, op, identsize, options);
31 opel = element_next (opel);
33 if (jumpop)
34 print_operation (out, jumpop, identsize, options);
37 static
38 void print_block_recursive (FILE *out, struct basicblock *block)
40 element ref;
41 struct basicedge *edge;
42 int identsize = block->st->identsize;
43 int revcond = block->status & BLOCK_STAT_REVCOND;
44 int first = TRUE, isloop = FALSE;
46 if (block->status & BLOCK_STAT_ISSWITCHTARGET) {
47 ref = list_head (block->inrefs);
48 while (ref) {
49 edge = element_getvalue (ref);
50 if (edge->from->status & BLOCK_STAT_ISSWITCH) {
51 ident_line (out, identsize);
52 fprintf (out, "case %d:\n", edge->fromnum);
54 ref = element_next (ref);
58 if (block->status & BLOCK_STAT_HASLABEL) {
59 fprintf (out, "\n");
60 ident_line (out, identsize);
61 fprintf (out, "label%d:\n", block->node.dfsnum);
64 if (block->st->start == block && block->st->type == CONTROL_LOOP) {
65 isloop = TRUE;
66 ident_line (out, identsize);
67 fprintf (out, "while (1) {\n");
70 block->mark1 = 1;
71 print_block (out, block, identsize + 1, revcond);
73 if (block->status & BLOCK_STAT_ISSWITCH) {
74 revcond = TRUE;
75 ident_line (out, identsize + 1);
76 fprintf (out, "switch () {\n");
79 if (revcond) ref = list_head (block->outrefs);
80 else ref = list_tail (block->outrefs);
82 while (ref) {
83 edge = element_getvalue (ref);
84 if (edge->type != EDGE_CASE && edge->type != EDGE_NEXT &&
85 edge->type != EDGE_IFEXIT && edge->type != EDGE_UNKNOWN) {
86 ident_line (out, identsize + 1);
87 if (first && list_size (block->outrefs) == 2 &&
88 !(block->status & BLOCK_STAT_ISSWITCH) && edge->type != EDGE_IFENTER)
89 ident_line (out, 1);
92 switch (edge->type) {
93 case EDGE_BREAK:
94 fprintf (out, "break;\n");
95 break;
96 case EDGE_CONTINUE:
97 fprintf (out, "continue;\n");
98 break;
99 case EDGE_INVALID:
100 case EDGE_GOTO:
101 fprintf (out, "goto label%d;\n", edge->to->node.dfsnum);
102 break;
103 case EDGE_UNKNOWN:
104 case EDGE_IFEXIT:
105 break;
106 case EDGE_CASE:
107 if (!edge->to->mark1)
108 print_block_recursive (out, edge->to);
109 break;
110 case EDGE_NEXT:
111 print_block_recursive (out, edge->to);
112 break;
113 case EDGE_IFENTER:
114 fprintf (out, "{\n");
115 print_block_recursive (out, edge->to);
116 ident_line (out, identsize + 1);
117 fprintf (out, "}\n");
118 break;
121 if (revcond) ref = element_next (ref);
122 else ref = element_previous (ref);
124 if ((block->status & BLOCK_STAT_HASELSE) && ref) {
125 ident_line (out, identsize + 1);
126 fprintf (out, "else\n");
128 first = FALSE;
131 if (block->ifst) {
132 if (block->ifst->hasendgoto) {
133 ident_line (out, identsize + 1);
134 fprintf (out, "goto label%d;\n", block->ifst->end->node.dfsnum);
135 } else if (block->ifst->info.ifctrl.endfollow) {
136 print_block_recursive (out, block->ifst->end);
140 if (block->status & BLOCK_STAT_ISSWITCH) {
141 ident_line (out, identsize + 1);
142 fprintf (out, "}\n");
145 if (block->st->start == block && block->st->type == CONTROL_LOOP) {
146 ident_line (out, identsize);
147 fprintf (out, "}\n");
148 if (block->st->hasendgoto) {
149 ident_line (out, identsize);
150 fprintf (out, "goto label%d;\n", block->st->end->node.dfsnum);
151 } else {
152 print_block_recursive (out, block->st->end);
158 static
159 void print_subroutine (FILE *out, struct subroutine *sub)
161 if (sub->import) { return; }
163 fprintf (out, "/**\n * Subroutine at address 0x%08X\n", sub->begin->address);
164 fprintf (out, " */\n");
165 print_subroutine_declaration (out, sub);
166 fprintf (out, "\n{\n");
168 if (sub->haserror) {
169 struct location *loc;
170 for (loc = sub->begin; ; loc++) {
171 fprintf (out, "%s\n", allegrex_disassemble (loc->opc, loc->address, TRUE));
172 if (loc == sub->end) break;
174 } else {
175 element el;
176 reset_marks (sub);
178 el = list_head (sub->blocks);
179 while (el) {
180 struct basicblock *block = element_getvalue (el);
181 if (!block->mark1)
182 print_block_recursive (out, block);
183 el = element_next (el);
186 fprintf (out, "}\n\n");
189 static
190 void print_source (FILE *out, struct code *c, char *headerfilename)
192 uint32 i, j;
193 element el;
195 fprintf (out, "#include <pspsdk.h>\n");
196 fprintf (out, "#include \"%s\"\n\n", headerfilename);
198 for (i = 0; i < c->file->modinfo->numimports; i++) {
199 struct prx_import *imp = &c->file->modinfo->imports[i];
201 fprintf (out, "/*\n * Imports from library: %s\n */\n", imp->name);
202 for (j = 0; j < imp->nfuncs; j++) {
203 struct prx_function *func = &imp->funcs[j];
204 if (func->pfunc) {
205 fprintf (out, "extern ");
206 print_subroutine_declaration (out, func->pfunc);
207 fprintf (out, ";\n");
210 fprintf (out, "\n");
213 el = list_head (c->subroutines);
214 while (el) {
215 struct subroutine *sub;
216 sub = element_getvalue (el);
218 print_subroutine (out, sub);
219 el = element_next (el);
224 static
225 void print_header (FILE *out, struct code *c, char *headerfilename)
227 uint32 i, j;
228 char buffer[256];
229 int pos = 0;
231 while (pos < sizeof (buffer) - 1) {
232 char c = headerfilename[pos];
233 if (!c) break;
234 if (c == '.') c = '_';
235 else c = toupper (c);
236 buffer[pos++] = c;
238 buffer[pos] = '\0';
240 fprintf (out, "#ifndef __%s\n", buffer);
241 fprintf (out, "#define __%s\n\n", buffer);
243 for (i = 0; i < c->file->modinfo->numexports; i++) {
244 struct prx_export *exp = &c->file->modinfo->exports[i];
246 fprintf (out, "/*\n * Exports from library: %s\n */\n", exp->name);
247 for (j = 0; j < exp->nfuncs; j++) {
248 struct prx_function *func = &exp->funcs[j];
249 if (func->name) {
250 fprintf (out, "void %s (void);\n",func->name);
251 } else {
252 fprintf (out, "void %s_%08X (void);\n", exp->name, func->nid);
255 fprintf (out, "\n");
258 fprintf (out, "#endif /* __%s */\n", buffer);
262 int print_code (struct code *c, char *prxname)
264 char buffer[64];
265 char basename[32];
266 FILE *cout, *hout;
269 get_base_name (prxname, basename, sizeof (basename));
270 sprintf (buffer, "%s.c", basename);
272 cout = fopen (buffer, "w");
273 if (!cout) {
274 xerror (__FILE__ ": can't open file for writing `%s'", buffer);
275 return 0;
278 sprintf (buffer, "%s.h", basename);
279 hout = fopen (buffer, "w");
280 if (!hout) {
281 xerror (__FILE__ ": can't open file for writing `%s'", buffer);
282 return 0;
286 print_header (hout, c, buffer);
287 print_source (cout, c, buffer);
289 fclose (cout);
290 fclose (hout);
291 return 1;