7 int decode_instructions (struct code
*c
)
10 uint32 i
, numopc
, size
, address
;
14 address
= c
->file
->programs
->vaddr
;
15 size
= c
->file
->modinfo
->expvaddr
- 4;
16 code
= c
->file
->programs
->data
;
20 if ((size
& 0x03) || (address
& 0x03)) {
21 error (__FILE__
": size/address is not multiple of 4");
25 base
= (struct location
*) xmalloc ((numopc
) * sizeof (struct location
));
26 memset (base
, 0, (numopc
) * sizeof (struct location
));
29 c
->end
= &base
[numopc
- 1];
33 for (i
= 0; i
< numopc
; i
++) {
34 struct location
*loc
= &base
[i
];
38 loc
->opc
= code
[i
<< 2];
39 loc
->opc
|= code
[(i
<< 2) + 1] << 8;
40 loc
->opc
|= code
[(i
<< 2) + 2] << 16;
41 loc
->opc
|= code
[(i
<< 2) + 3] << 24;
42 loc
->insn
= allegrex_decode (loc
->opc
, FALSE
);
43 loc
->address
= address
+ (i
<< 2);
45 if (loc
->insn
== NULL
) {
46 loc
->error
= ERROR_INVALID_OPCODE
;
52 if (INSN_TYPE (loc->insn->flags) != INSN_ALLEGREX) {
58 if (loc
->insn
->flags
& (INSN_BRANCH
| INSN_JUMP
)) {
59 if (slot
) c
->base
[i
- 1].error
= ERROR_DELAY_SLOT
;
65 if (loc
->insn
->flags
& INSN_BRANCH
) {
66 tgt
= loc
->opc
& 0xFFFF;
67 if (tgt
& 0x8000) { tgt
|= ~0xFFFF; }
70 loc
->target
= &base
[tgt
];
72 loc
->error
= ERROR_TARGET_OUTSIDE_FILE
;
75 if (location_gpr_used (loc
) == 0 ||
76 ((loc
->insn
->flags
& INSN_READ_GPR_T
) && RS (loc
->opc
) == RT (loc
->opc
))) {
77 switch (loc
->insn
->insn
) {
85 loc
->branchalways
= TRUE
;
95 loc
->error
= ERROR_ILLEGAL_BRANCH
;
98 loc
->branchalways
= FALSE
;
102 } else if (loc
->insn
->insn
== I_J
|| loc
->insn
->insn
== I_JAL
) {
103 uint32 target_addr
= (loc
->opc
& 0x3FFFFFF) << 2;;
104 target_addr
|= ((loc
->address
) & 0xF0000000);
105 tgt
= (target_addr
- address
) >> 2;
107 loc
->target
= &base
[tgt
];
109 loc
->error
= ERROR_TARGET_OUTSIDE_FILE
;
115 c
->base
[i
- 1].error
= ERROR_TARGET_OUTSIDE_FILE
;
121 uint32
location_gpr_used (struct location
*loc
)
125 if (loc
->insn
->flags
& INSN_READ_GPR_S
) {
126 if (RS (loc
->opc
) != 0)
127 result
|= 1 << (RS (loc
->opc
));
130 if (loc
->insn
->flags
& INSN_READ_GPR_T
) {
131 if (RT (loc
->opc
) != 0)
132 result
|= 1 << (RT (loc
->opc
));
135 if (loc
->insn
->flags
& INSN_READ_GPR_D
) {
136 if (RD (loc
->opc
) != 0)
137 result
|= 1 << (RD (loc
->opc
));
143 uint32
location_gpr_defined (struct location
*loc
)
147 if (loc
->insn
->flags
& INSN_LINK
) {
151 if (loc
->insn
->flags
& INSN_WRITE_GPR_D
) {
152 if (RD (loc
->opc
) != 0)
153 result
|= 1 << (RD (loc
->opc
));
156 if (loc
->insn
->flags
& INSN_WRITE_GPR_T
) {
157 if (RT (loc
->opc
) != 0)
158 result
|= 1 << (RT (loc
->opc
));
163 int location_branch_may_swap (struct location
*branch
)
165 int gpr_used
, gpr_defined
;
167 gpr_used
= location_gpr_used (branch
);
168 gpr_defined
= location_gpr_defined (&branch
[1]);
169 return (!(gpr_used
& gpr_defined
));