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");
20 base
= (struct location
*) xmalloc (numopc
* sizeof (struct location
));
21 memset (base
, 0, numopc
* sizeof (struct location
));
26 for (i
= 0; i
< numopc
; i
++) {
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);
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
;
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
;
47 case I_BGEZAL
: case I_BLTZAL
:
48 base
[i
].jtype
= JTYPE_BRANCHANDLINK
;
51 base
[i
].jtype
= JTYPE_BRANCHANDLINKLIKELY
;
54 base
[i
].jtype
= JTYPE_JUMP
;
57 base
[i
].jtype
= JTYPE_JUMPANDLINK
;
60 base
[i
].jtype
= JTYPE_JUMPANDLINKREGISTER
;
63 base
[i
].jtype
= JTYPE_JUMPREGISTER
;
66 base
[i
].jtype
= JTYPE_NONE
;
70 if (base
[i
].jtype
!= JTYPE_NONE
) {
71 if (dslot
) error (__FILE__
": jump inside a delay slot at 0x%08X", base
[i
].address
);
73 if (base
[i
].jtype
== JTYPE_JUMP
|| base
[i
].jtype
== JTYPE_JUMPREGISTER
)
80 if (!dslot
) skip
= FALSE
;
84 switch (base
[i
].jtype
) {
86 case JTYPE_BRANCHANDLINK
:
87 case JTYPE_BRANCHANDLINKLIKELY
:
88 case JTYPE_BRANCHLIKELY
:
89 tgt
= base
[i
].opc
& 0xFFFF;
90 if (tgt
& 0x8000) { tgt
|= ~0xFFFF; }
95 error (__FILE__
": branch outside file\n%s", allegrex_disassemble (base
[i
].opc
, base
[i
].address
));
97 base
[i
].target_addr
= (tgt
<< 2) + address
;
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;
105 base
[tgt
].refcount
++;
107 error (__FILE__
": jump outside file\n%s", allegrex_disassemble (base
[i
].opc
, base
[i
].address
));
111 base
[i
].target_addr
= 0;
119 int analyse_relocs (struct code
*c
)
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
++;
135 int analyse_registers (struct code
*c
)
141 struct code
* analyse_code (struct prx
*p
)
144 c
= (struct code
*) xmalloc (sizeof (struct code
));
147 if (!analyse_jumps (c
, p
->programs
->data
,
148 p
->modinfo
->expvaddr
- 4, p
->programs
->vaddr
)) {
153 if (!analyse_relocs (c
)) {
162 void free_code (struct code
*c
)
170 void print_code (struct code
*c
)
174 for (i
= 0; i
< c
->numopc
; i
++) {
175 report ("%s", allegrex_disassemble (c
->base
[i
].opc
, c
->base
[i
].address
));