2 * Author: Humberto Naves (hsnaves@gmail.com)
10 int decode_instructions (struct code
*c
)
12 struct location
*base
;
13 uint32 i
, numopc
, size
, address
;
17 address
= c
->file
->programs
->vaddr
;
18 size
= c
->file
->modinfo
->expvaddr
- 4;
19 code
= c
->file
->programs
->data
;
23 if ((size
& 0x03) || (address
& 0x03)) {
24 error (__FILE__
": size/address is not multiple of 4");
28 base
= (struct location
*) xmalloc ((numopc
) * sizeof (struct location
));
29 memset (base
, 0, (numopc
) * sizeof (struct location
));
32 c
->end
= &base
[numopc
- 1];
36 for (i
= 0; i
< numopc
; i
++) {
37 struct location
*loc
= &base
[i
];
41 loc
->opc
= code
[i
<< 2];
42 loc
->opc
|= code
[(i
<< 2) + 1] << 8;
43 loc
->opc
|= code
[(i
<< 2) + 2] << 16;
44 loc
->opc
|= code
[(i
<< 2) + 3] << 24;
45 loc
->insn
= allegrex_decode (loc
->opc
, FALSE
);
46 loc
->address
= address
+ (i
<< 2);
48 if (loc
->insn
== NULL
) {
49 loc
->error
= ERROR_INVALID_OPCODE
;
55 if (INSN_TYPE (loc->insn->flags) != INSN_ALLEGREX) {
61 if (loc
->insn
->flags
& (INSN_BRANCH
| INSN_JUMP
)) {
62 if (slot
) c
->base
[i
- 1].error
= ERROR_DELAY_SLOT
;
68 if (loc
->insn
->flags
& INSN_BRANCH
) {
69 tgt
= loc
->opc
& 0xFFFF;
70 if (tgt
& 0x8000) { tgt
|= ~0xFFFF; }
73 loc
->target
= &base
[tgt
];
75 loc
->error
= ERROR_TARGET_OUTSIDE_FILE
;
78 if (location_gpr_used (loc
) == 0 ||
79 ((loc
->insn
->flags
& INSN_READ_GPR_T
) && RS (loc
->opc
) == RT (loc
->opc
))) {
80 switch (loc
->insn
->insn
) {
88 loc
->branchalways
= TRUE
;
98 loc
->error
= ERROR_ILLEGAL_BRANCH
;
101 loc
->branchalways
= FALSE
;
105 } else if (loc
->insn
->insn
== I_J
|| loc
->insn
->insn
== I_JAL
) {
106 uint32 target_addr
= (loc
->opc
& 0x3FFFFFF) << 2;;
107 target_addr
|= ((loc
->address
) & 0xF0000000);
108 tgt
= (target_addr
- address
) >> 2;
110 loc
->target
= &base
[tgt
];
112 loc
->error
= ERROR_TARGET_OUTSIDE_FILE
;
118 c
->base
[i
- 1].error
= ERROR_TARGET_OUTSIDE_FILE
;
124 uint32
location_gpr_used (struct location
*loc
)
128 if (loc
->insn
->flags
& INSN_READ_GPR_S
) {
129 if (RS (loc
->opc
) != 0)
130 result
|= 1 << (RS (loc
->opc
));
133 if (loc
->insn
->flags
& INSN_READ_GPR_T
) {
134 if (RT (loc
->opc
) != 0)
135 result
|= 1 << (RT (loc
->opc
));
138 if (loc
->insn
->flags
& INSN_READ_GPR_D
) {
139 if (RD (loc
->opc
) != 0)
140 result
|= 1 << (RD (loc
->opc
));
146 uint32
location_gpr_defined (struct location
*loc
)
150 if (loc
->insn
->flags
& INSN_LINK
) {
154 if (loc
->insn
->flags
& INSN_WRITE_GPR_D
) {
155 if (RD (loc
->opc
) != 0)
156 result
|= 1 << (RD (loc
->opc
));
159 if (loc
->insn
->flags
& INSN_WRITE_GPR_T
) {
160 if (RT (loc
->opc
) != 0)
161 result
|= 1 << (RT (loc
->opc
));
166 int location_branch_may_swap (struct location
*branch
)
168 int gpr_used
, gpr_defined
;
170 gpr_used
= location_gpr_used (branch
);
171 gpr_defined
= location_gpr_defined (&branch
[1]);
172 return (!(gpr_used
& gpr_defined
));