Renomeando os arquivos
[pspdecompiler.git] / analyser.c
blob0dfcfd16f3d2b77011499831d8a4f25957bb3e31
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;
13 int dslot = FALSE, skip = FALSE;
15 if (size & 0x03 || address & 0x03) {
16 error (__FILE__ ": size/address is not multiple of 4");
17 return 0;
20 base = (struct location *) xmalloc (numopc * sizeof (struct location));
21 memset (base, 0, numopc * sizeof (struct location));
22 c->base = base;
23 c->baddr = address;
24 c->numopc = numopc;
26 for (i = 0; i < numopc; i++) {
27 uint32 tgt;
28 base[i].opc = code[i << 2];
29 base[i].opc |= code[(i << 2) + 1] << 8;
30 base[i].opc |= code[(i << 2) + 2] << 16;
31 base[i].opc |= code[(i << 2) + 3] << 24;
32 base[i].itype = allegrex_insn_type (base[i].opc);
33 base[i].address = address + (i << 2);
35 if (!skip || dslot)
36 base[i].refcount++;
38 switch (base[i].itype) {
39 case I_BEQ: case I_BNE: case I_BGEZ: case I_BGTZ: case I_BLEZ:
40 case I_BLTZ: case I_BC1F: case I_BC1T: case I_BVF: case I_BVT:
41 base[i].jtype = JTYPE_BRANCH;
42 break;
43 case I_BEQL: case I_BNEL: case I_BGEZL: case I_BGTZL: case I_BLEZL:
44 case I_BLTZL: case I_BC1FL: case I_BC1TL: case I_BVFL: case I_BVTL:
45 base[i].jtype = JTYPE_BRANCHLIKELY;
46 break;
47 case I_BGEZAL: case I_BLTZAL:
48 base[i].jtype = JTYPE_BRANCHANDLINK;
49 break;
50 case I_BLTZALL:
51 base[i].jtype = JTYPE_BRANCHANDLINKLIKELY;
52 break;
53 case I_J:
54 base[i].jtype = JTYPE_JUMP;
55 break;
56 case I_JAL:
57 base[i].jtype = JTYPE_JUMPANDLINK;
58 break;
59 case I_JALR:
60 base[i].jtype = JTYPE_JUMPANDLINKREGISTER;
61 break;
62 case I_JR:
63 base[i].jtype = JTYPE_JUMPREGISTER;
64 break;
65 default:
66 base[i].jtype = JTYPE_NONE;
67 break;
70 if (base[i].jtype != JTYPE_NONE) {
71 if (dslot) error (__FILE__ ": jump inside a delay slot at 0x%08X", base[i].address);
72 else {
73 if (base[i].jtype == JTYPE_JUMP || base[i].jtype == JTYPE_JUMPREGISTER)
74 skip = TRUE;
75 else
76 skip = FALSE;
78 dslot = TRUE;
79 } else {
80 if (!dslot) skip = FALSE;
81 dslot = FALSE;
84 switch (base[i].jtype) {
85 case JTYPE_BRANCH:
86 case JTYPE_BRANCHANDLINK:
87 case JTYPE_BRANCHANDLINKLIKELY:
88 case JTYPE_BRANCHLIKELY:
89 tgt = base[i].opc & 0xFFFF;
90 if (tgt & 0x8000) { tgt |= ~0xFFFF; }
91 tgt += i + 1;
92 if (tgt < numopc) {
93 base[tgt].refcount++;
94 } else {
95 error (__FILE__ ": branch outside file\n%s", allegrex_disassemble (base[i].opc, base[i].address));
97 base[i].target_addr = (tgt << 2) + address;
98 break;
99 case JTYPE_JUMP:
100 case JTYPE_JUMPANDLINK:
101 base[i].target_addr = (base[i].opc & 0x3FFFFFF) << 2;;
102 base[i].target_addr |= ((base[i].address) & 0xF0000000);
103 tgt = (base[i].target_addr - address) >> 2;
104 if (tgt < numopc) {
105 base[tgt].refcount++;
106 } else {
107 error (__FILE__ ": jump outside file\n%s", allegrex_disassemble (base[i].opc, base[i].address));
109 break;
110 default:
111 base[i].target_addr = 0;
115 return 1;
118 static
119 int analyse_relocs (struct code *c)
121 uint32 i, opc;
122 for (i = 0; i < c->file->relocnum; i++) {
123 struct prx_reloc *rel = &c->file->relocs[i];
124 if (rel->target < c->baddr) continue;
126 opc = (rel->target - c->baddr) >> 2;
127 if (opc >= c->numopc) continue;
129 c->base[opc].ext_refcount++;
131 return 1;
134 static
135 int analyse_registers (struct code *c)
137 return 1;
141 struct code* analyse_code (struct prx *p)
143 struct code *c;
144 c = (struct code *) xmalloc (sizeof (struct code));
145 c->file = p;
147 if (!analyse_jumps (c, p->programs->data,
148 p->modinfo->expvaddr - 4, p->programs->vaddr)) {
149 free_code (c);
150 return NULL;
153 if (!analyse_relocs (c)) {
154 free_code (c);
155 return NULL;
158 return c;
162 void free_code (struct code *c)
164 if (c->base)
165 free (c->base);
166 c->base = NULL;
167 free (c);
170 void print_code (struct code *c)
172 uint32 i;
174 for (i = 0; i < c->numopc; i++) {
175 report ("%s", allegrex_disassemble (c->base[i].opc, c->base[i].address));
176 report ("\n");