disasmif.c
2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <string.h>
#include "opcode.h"
extern int regsUsed;
void rspDis_init( char *addr_format, char *value_format, char *reg_names[],
int print_jal_targets )
{
/* well, just don't do anything */
}
void rspDis_regs( char *buffer, unsigned regmask, unsigned reg_values[] )
{
register int i, displayed = 0;
unsigned int whichReg = 2; /* start at reg 1 */
for ( i = 1; i < 32; ++i, whichReg <<= 1 )
{
if ( regmask & whichReg )
{
if ( displayed )
strcat( buffer, "," );
else
strcat( buffer, "\t<" );
sprintf( buffer + strlen( buffer ), "$%d=0x%d",
i, reg_values[i] );
++displayed;
}
}
if ( displayed )
strcat( buffer, ">" );
}
extern void rsp_DisasmInst( unsigned int, char *, int );
int rspDisasmReturnType( unsigned int inst )
{
switch ( ExtractOpcode( inst ) )
{
case rsp_SPECIAL:
switch ( ExtractBits( inst, 5, 0 ) )
{
case rsp_JR:
case rsp_JALR:
return 2;
default:
return 0;
}
case rsp_REGIMM:
switch ( ExtractBits(inst, 20, 16) )
{
case rsp_BLTZ:
case rsp_BGEZ:
case rsp_BLTZAL:
case rsp_BGEZAL:
return 2;
default:
return 0;
}
case rsp_COP0:
switch( ExtractBits(inst, 25, 21) )
{
case rsp_BC0:
return 2;
case rsp_MFC0:
case rsp_MTC0:
regsUsed = 1 << ExtractBits( inst, 20, 16 );
default:
return 0;
}
case rsp_COP2:
regsUsed = 0;
switch( ExtractBits(inst, 25, 21) )
{
case rsp_BC:
return 2;
case rsp_MFC2:
case rsp_CFC2:
case rsp_MTC2:
case rsp_CTC2:
regsUsed = 1 << ExtractBits( inst, 20, 16 );
default:
return 0;
}
case rsp_J:
case rsp_BEQ:
case rsp_BNE:
case rsp_BLEZ:
case rsp_BGTZ:
return 2;
case rsp_JAL:
return 1;
case rsp_LWC2:
case rsp_SWC2:
regsUsed = 1 << ExtractBits( inst, 25, 21 );
/* and fall through to */
case rsp_LB:
case rsp_LBU:
case rsp_LH:
case rsp_LHU:
case rsp_LW:
case rsp_SB:
case rsp_SH:
case rsp_SW:
case rsp_LUI:
return -1;
default:
break;
}
return 0;
}
int rspDisasm( char *buffer, unsigned address, unsigned iword, unsigned *regmask,
unsigned *symbol_value, unsigned *ls_register )
{
int retval;
short immed;
rsp_DisasmInst( iword, buffer, address );
*symbol_value = 0; /* target or load address */
retval = rspDisasmReturnType( iword );
if ( retval == -1 ) /* load or store */
{
*ls_register = ExtractBits( iword, 25, 21 );
immed = iword & 0xffff;
*symbol_value = (int) immed;
}
else if ( retval == 1 )
{
*symbol_value = ((iword << 2) & 0xfff) + 0x4001000; /* 12 bit addr! */
strcpy( buffer, "jal\t" );
}
*regmask = regsUsed; /* should be the regs used by the inst */
return retval;
}