Problemas com os relocs
[pspdecompiler.git] / analyser.c
blob6dd83805d84e09335ea10243696452a4d239b13f
2 #include <string.h>
3 #include <stdlib.h>
5 #include "analyser.h"
6 #include "utils.h"
8 static
9 int analyse_jumps (struct code *c, const uint8 *code, uint32 size, uint32 address)
11 struct location *base;
12 uint32 i, numopc = size >> 2;
14 if (size & 0x03 || address & 0x03) {
15 error (__FILE__ ": size/address is not multiple of 4");
16 return 0;
19 base = (struct location *) xmalloc (numopc * sizeof (struct location));
20 memset (base, 0, numopc * sizeof (struct location));
21 c->base = base;
22 c->baddr = address;
23 c->numopc = numopc;
25 for (i = 0; i < numopc; i++) {
26 uint32 tgt;
27 base[i].opc = code[i << 2];
28 base[i].opc |= code[(i << 2) + 1] << 8;
29 base[i].opc |= code[(i << 2) + 2] << 16;
30 base[i].opc |= code[(i << 2) + 3] << 24;
31 base[i].itype = allegrex_insn_type (base[i].opc);
32 base[i].address = address + (i << 2);
34 switch (base[i].itype) {
35 case I_BEQ:
36 case I_BNE:
37 case I_BGEZ:
38 case I_BGTZ:
39 case I_BLEZ:
40 case I_BLTZ:
41 case I_BC1F:
42 case I_BC1T:
43 case I_BVF:
44 case I_BVT:
45 base[i].jtype = JTYPE_BRANCH;
46 break;
48 case I_BEQL:
49 case I_BNEL:
50 case I_BGEZL:
51 case I_BGTZL:
52 case I_BLEZL:
53 case I_BLTZL:
54 case I_BC1FL:
55 case I_BC1TL:
56 case I_BVFL:
57 case I_BVTL:
58 base[i].jtype = JTYPE_BRANCHLIKELY;
59 break;
61 case I_BGEZAL:
62 case I_BLTZAL:
63 base[i].jtype = JTYPE_BRANCHANDLINK;
64 break;
66 case I_BLTZALL:
67 base[i].jtype = JTYPE_BRANCHANDLINKLIKELY;
68 break;
70 case I_J:
71 base[i].jtype = JTYPE_JUMP;
72 break;
74 case I_JAL:
75 base[i].jtype = JTYPE_JUMPANDLINK;
76 break;
78 case I_JALR:
79 base[i].jtype = JTYPE_JUMPANDLINKREGISTER;
80 break;
82 case I_JR:
83 base[i].jtype = JTYPE_JUMPREGISTER;
84 break;
86 default:
87 base[i].jtype = JTYPE_NONE;
88 break;
91 switch (base[i].jtype) {
92 case JTYPE_BRANCH:
93 case JTYPE_BRANCHANDLINK:
94 case JTYPE_BRANCHANDLINKLIKELY:
95 case JTYPE_BRANCHLIKELY:
96 tgt = base[i].opc & 0xFFFF;
97 if (tgt & 0x8000) {
98 tgt |= ~0xFFFF;
100 tgt += i + 1;
101 if (tgt < numopc) {
102 if (base[i].jtype == JTYPE_BRANCHANDLINK ||
103 base[i].jtype == JTYPE_BRANCHANDLINKLIKELY) {
104 LLIST_ADD (c->pool, base[tgt].callrefs, &base[i]);
105 } else {
106 LLIST_ADD (c->pool, base[tgt].jumprefs, &base[i]);
108 } else {
109 error (__FILE__ ": branch outside file\n%s", allegrex_disassemble (base[i].opc, base[i].address));
111 base[i].target_addr = (tgt << 2) + address;
112 break;
113 case JTYPE_JUMP:
114 case JTYPE_JUMPANDLINK:
115 base[i].target_addr = (base[i].opc & 0x3FFFFFF) << 2;;
116 base[i].target_addr |= ((base[i].address) & 0xF0000000);
117 tgt = (base[i].target_addr - address) >> 2;
118 if (tgt < numopc) {
119 llist ref = llist_alloc (c->pool);
120 ref->value = &base[i];
121 base[i].target = &base[tgt];
122 if (base[i].jtype == JTYPE_JUMPANDLINK) {
123 ref->next = base[tgt].callrefs;
124 base[tgt].callrefs = ref;
125 } else {
126 ref->next = base[tgt].jumprefs;
127 base[tgt].jumprefs = ref;
129 } else {
130 error (__FILE__ ": jump outside file\n%s", allegrex_disassemble (base[i].opc, base[i].address));
132 break;
133 default:
134 base[i].target_addr = 0;
138 i = numopc - 1;
139 do {
140 if (base[i].callrefs) {
141 LLIST_ADD (c->pool, c->subroutines, &base[i]);
143 } while (i-- != 0);
145 return 1;
148 static
149 int analyse_relocs (struct code *c)
151 return 1;
154 static
155 int analyse_registers (struct code *c)
157 return 1;
161 struct code* analyse_code (struct prx *p)
163 struct code *c;
164 c = (struct code *) xmalloc (sizeof (struct code));
165 c->image = p;
166 c->pool = llist_create ();
167 c->subroutines = NULL;
169 if (!analyse_jumps (c, p->programs->data,
170 p->modinfo->expvaddr - 4, p->programs->vaddr)) {
171 free_code (c);
172 return NULL;
175 if (!analyse_relocs (c)) {
176 free_code (c);
177 return NULL;
180 return c;
184 void free_code (struct code *c)
186 if (c->base)
187 free (c->base);
188 c->base = NULL;
189 if (c->pool)
190 llist_destroy (c->pool);
191 c->pool = NULL;
192 free (c);
195 void print_code (struct code *c)
197 uint32 i;
199 for (i = 0; i < c->numopc; i++) {
200 if (c->base[i].callrefs || c->base[i].jumprefs) {
201 report ("\n");
204 if (c->base[i].callrefs) {
205 llist l;
206 report ("; Called from: ");
207 for (l = c->base[i].callrefs; l; l = l->next) {
208 struct location *loc = (struct location *) l->value;
209 report ("0x%08X ", loc->address);
211 report ("\n");
213 if (c->base[i].jumprefs) {
214 llist l;
215 report ("; Jumped from: ");
216 for (l = c->base[i].jumprefs; l; l = l->next) {
217 struct location *loc = (struct location *) l->value;
218 report ("0x%08X ", loc->address);
220 report ("\n");
222 report ("%s", allegrex_disassemble (c->base[i].opc, c->base[i].address));
223 report ("\n");