2 * Author: Humberto Naves (hsnaves@gmail.com)
9 int check_switch (struct code
*c
, struct codeswitch
*cs
)
11 struct location
*loc
= cs
->location
;
15 if (!loc
->insn
) return 0;
17 if (loc
->insn
->insn
== I_LW
) {
18 def
= location_gpr_defined (loc
);
20 if (loc
++ == c
->end
) return 0;
21 if (!loc
->insn
) return 0;
22 used
= location_gpr_used (loc
);
24 if (loc
->insn
->insn
!= I_JR
)
28 if (loc
->insn
->flags
& (INSN_JUMP
| INSN_BRANCH
)) return 0;
30 } else if (loc
->insn
->insn
== I_ADDIU
) {
32 def
= location_gpr_defined (loc
);
34 if (loc
++ == c
->end
) return 0;
35 if (!loc
->insn
) return 0;
36 used
= location_gpr_used (loc
);
39 if (loc
->insn
->insn
!= I_ADDU
) return 0;
40 } else if (count
== 1) {
41 if (loc
->insn
->insn
!= I_LW
) return 0;
43 if (loc
->insn
->insn
!= I_JR
)
48 def
= location_gpr_defined (loc
);
50 if (loc
->insn
->flags
& (INSN_JUMP
| INSN_BRANCH
)) return 0;
54 cs
->jumplocation
= loc
;
55 cs
->jumplocation
->cswitch
= cs
;
57 el
= list_head (cs
->references
);
59 struct location
*target
= element_getvalue (el
);
61 el
= element_next (el
);
67 void extract_switches (struct code
*c
)
69 struct prx_reloc
*aux
;
70 uint32 base
, end
, count
= 0;
73 for (i
= 0; i
< c
->file
->relocnum
; i
++) {
74 struct prx_reloc
*rel
= &c
->file
->relocsbyaddr
[i
];
77 if (rel
->type
!= R_MIPS_32
) break;
78 tgt
= (rel
[count
].target
- c
->baddr
) >> 2;
79 if (tgt
>= c
->numopc
) break;
80 if (rel
[count
].target
& 0x03) break;
83 } while ((i
+ count
) < c
->file
->relocnum
);
85 if (count
== 0) continue;
87 base
= end
= prx_findreloc (c
->file
, rel
->vaddr
);
88 if (base
>= c
->file
->relocnum
) continue;
89 if (c
->file
->relocs
[base
].target
!= rel
->vaddr
) continue;
91 for (; end
< c
->file
->relocnum
; end
++) {
92 aux
= &c
->file
->relocs
[end
];
93 if (aux
->target
!= rel
->vaddr
) {
94 if (aux
->target
& 0x03) {
95 error (__FILE__
": relocation target not word aligned 0x%08X", aux
->target
);
97 } else if (count
> ((aux
->target
- rel
->vaddr
) >> 2))
98 count
= (aux
->target
- rel
->vaddr
) >> 2;
103 if (count
<= 1) continue;
105 for (;base
< end
; base
++) {
106 aux
= &c
->file
->relocs
[base
];
107 tgt
= (aux
->vaddr
- c
->baddr
) >> 2;
108 if (tgt
>= c
->numopc
) continue;
109 if (aux
->vaddr
& 0x03) {
110 error (__FILE__
": relocation vaddr not word aligned 0x%08X", aux
->vaddr
);
114 if (aux
->type
== R_MIPS_LO16
) {
115 struct codeswitch
*cs
;
117 cs
= fixedpool_alloc (c
->switchpool
);
120 cs
->switchreloc
= rel
;
121 cs
->location
= &c
->base
[tgt
];
123 cs
->references
= list_alloc (c
->lstpool
);
124 for (j
= 0; j
< count
; j
++) {
125 tgt
= (rel
[j
].target
- c
->baddr
) >> 2;
126 list_inserttail (cs
->references
, &c
->base
[tgt
]);
129 if (!check_switch (c
, cs
)) {
130 fixedpool_free (c
->switchpool
, cs
);