6 int check_switch (struct code
*c
, struct codeswitch
*cs
)
8 struct location
*loc
= cs
->location
;
12 if (!loc
->insn
) return 0;
14 if (loc
->insn
->insn
== I_LW
) {
15 def
= location_gpr_defined (loc
);
17 if (loc
++ == c
->end
) return 0;
18 if (!loc
->insn
) return 0;
19 used
= location_gpr_used (loc
);
21 if (loc
->insn
->insn
!= I_JR
)
25 if (loc
->insn
->flags
& (INSN_JUMP
| INSN_BRANCH
)) return 0;
27 } else if (loc
->insn
->insn
== I_ADDIU
) {
29 def
= location_gpr_defined (loc
);
31 if (loc
++ == c
->end
) return 0;
32 if (!loc
->insn
) return 0;
33 used
= location_gpr_used (loc
);
36 if (loc
->insn
->insn
!= I_ADDU
) return 0;
37 } else if (count
== 1) {
38 if (loc
->insn
->insn
!= I_LW
) return 0;
40 if (loc
->insn
->insn
!= I_JR
)
45 def
= location_gpr_defined (loc
);
47 if (loc
->insn
->flags
& (INSN_JUMP
| INSN_BRANCH
)) return 0;
51 cs
->jumplocation
= loc
;
52 cs
->jumplocation
->cswitch
= cs
;
54 el
= list_head (cs
->references
);
56 struct location
*target
= element_getvalue (el
);
58 el
= element_next (el
);
64 void extract_switches (struct code
*c
)
66 struct prx_reloc
*aux
;
67 uint32 base
, end
, count
= 0;
70 for (i
= 0; i
< c
->file
->relocnum
; i
++) {
71 struct prx_reloc
*rel
= &c
->file
->relocsbyaddr
[i
];
74 if (rel
->type
!= R_MIPS_32
) break;
75 tgt
= (rel
[count
].target
- c
->baddr
) >> 2;
76 if (tgt
>= c
->numopc
) break;
77 if (rel
[count
].target
& 0x03) break;
80 } while ((i
+ count
) < c
->file
->relocnum
);
82 if (count
== 0) continue;
84 base
= end
= prx_findreloc (c
->file
, rel
->vaddr
);
85 if (base
>= c
->file
->relocnum
) continue;
86 if (c
->file
->relocs
[base
].target
!= rel
->vaddr
) continue;
88 for (; end
< c
->file
->relocnum
; end
++) {
89 aux
= &c
->file
->relocs
[end
];
90 if (aux
->target
!= rel
->vaddr
) {
91 if (aux
->target
& 0x03) {
92 error (__FILE__
": relocation target not word aligned 0x%08X", aux
->target
);
94 } else if (count
> ((aux
->target
- rel
->vaddr
) >> 2))
95 count
= (aux
->target
- rel
->vaddr
) >> 2;
100 if (count
<= 1) continue;
102 for (;base
< end
; base
++) {
103 aux
= &c
->file
->relocs
[base
];
104 tgt
= (aux
->vaddr
- c
->baddr
) >> 2;
105 if (tgt
>= c
->numopc
) continue;
106 if (aux
->vaddr
& 0x03) {
107 error (__FILE__
": relocation vaddr not word aligned 0x%08X", aux
->vaddr
);
111 if (aux
->type
== R_MIPS_LO16
) {
112 struct codeswitch
*cs
;
114 cs
= fixedpool_alloc (c
->switchpool
);
117 cs
->switchreloc
= rel
;
118 cs
->location
= &c
->base
[tgt
];
120 cs
->references
= list_alloc (c
->lstpool
);
121 for (j
= 0; j
< count
; j
++) {
122 tgt
= (rel
[j
].target
- c
->baddr
) >> 2;
123 list_inserttail (cs
->references
, &c
->base
[tgt
]);
126 if (!check_switch (c
, cs
)) {
127 fixedpool_free (c
->switchpool
, cs
);