Commit | Line | Data |
---|---|---|
23cf992f NC |
1 | /* -- dis.c */ |
2 | ||
3 | #undef CGEN_PRINT_INSN | |
4 | #define CGEN_PRINT_INSN my_print_insn | |
5 | ||
6 | static int | |
7 | my_print_insn (pc, info, buf, buflen) | |
8 | bfd_vma pc; | |
9 | disassemble_info *info; | |
10 | char *buf; | |
11 | int buflen; | |
12 | { | |
13 | /* 32 bit insn? */ | |
14 | if ((pc & 3) == 0 && (buf[0] & 0x80) != 0) | |
15 | return print_insn (pc, info, buf, buflen); | |
16 | ||
17 | /* Print the first insn. */ | |
18 | if ((pc & 3) == 0) | |
19 | { | |
20 | if (print_insn (pc, info, buf, 16) == 0) | |
21 | (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); | |
22 | buf += 2; | |
23 | } | |
24 | ||
25 | if (buf[0] & 0x80) | |
26 | { | |
27 | /* Parallel. */ | |
28 | (*info->fprintf_func) (info->stream, " || "); | |
29 | buf[0] &= 0x7f; | |
30 | } | |
31 | else | |
32 | (*info->fprintf_func) (info->stream, " -> "); | |
33 | ||
34 | /* The "& 3" is to ensure the branch address is computed correctly | |
35 | [if it is a branch]. */ | |
36 | if (print_insn (pc & ~ (bfd_vma) 3, info, buf, 16) == 0) | |
37 | (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); | |
38 | ||
39 | return (pc & 3) ? 2 : 4; | |
40 | } | |
41 | ||
42 | /* -- */ | |
43 | ||
44 | /* Main entry point for operand extraction. | |
45 | ||
46 | This function is basically just a big switch statement. Earlier versions | |
47 | used tables to look up the function to use, but | |
48 | - if the table contains both assembler and disassembler functions then | |
49 | the disassembler contains much of the assembler and vice-versa, | |
50 | - there's a lot of inlining possibilities as things grow, | |
51 | - using a switch statement avoids the function call overhead. | |
52 | ||
53 | This function could be moved into `print_insn_normal', but keeping it | |
54 | separate makes clear the interface between `print_insn_normal' and each of | |
55 | the handlers. | |
56 | */ | |
57 | ||
58 | CGEN_INLINE int | |
59 | m32r_cgen_extract_operand (opindex, buf_ctrl, insn_value, fields) | |
60 | int opindex; | |
61 | void *buf_ctrl; | |
62 | cgen_insn_t insn_value; | |
63 | CGEN_FIELDS *fields; | |
64 | { | |
65 | int length; | |
66 | ||
67 | switch (opindex) | |
68 | { | |
69 | case M32R_OPERAND_SR : | |
70 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2); | |
71 | break; | |
72 | case M32R_OPERAND_DR : | |
73 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1); | |
74 | break; | |
75 | case M32R_OPERAND_SRC1 : | |
76 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1); | |
77 | break; | |
78 | case M32R_OPERAND_SRC2 : | |
79 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2); | |
80 | break; | |
81 | case M32R_OPERAND_SCR : | |
82 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2); | |
83 | break; | |
84 | case M32R_OPERAND_DCR : | |
85 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1); | |
86 | break; | |
87 | case M32R_OPERAND_SIMM8 : | |
88 | length = extract_normal (NULL /*FIXME*/, insn_value, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm8); | |
89 | break; | |
90 | case M32R_OPERAND_SIMM16 : | |
91 | length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm16); | |
92 | break; | |
93 | case M32R_OPERAND_UIMM4 : | |
94 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm4); | |
95 | break; | |
96 | case M32R_OPERAND_UIMM5 : | |
97 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm5); | |
98 | break; | |
99 | case M32R_OPERAND_UIMM16 : | |
100 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm16); | |
101 | break; | |
102 | case M32R_OPERAND_ACC_S : | |
103 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 2, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_acc_s); | |
104 | break; | |
105 | case M32R_OPERAND_ACC : | |
106 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 1, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_acc); | |
107 | break; | |
108 | case M32R_OPERAND_HI16 : | |
109 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_hi16); | |
110 | break; | |
111 | case M32R_OPERAND_SLO16 : | |
112 | length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm16); | |
113 | break; | |
114 | case M32R_OPERAND_ULO16 : | |
115 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm16); | |
116 | break; | |
117 | case M32R_OPERAND_UIMM24 : | |
118 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm24); | |
119 | break; | |
120 | case M32R_OPERAND_DISP8 : | |
121 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp8); | |
122 | break; | |
123 | case M32R_OPERAND_DISP16 : | |
124 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp16); | |
125 | break; | |
126 | case M32R_OPERAND_DISP24 : | |
127 | length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp24); | |
128 | break; | |
129 | ||
130 | default : | |
131 | fprintf (stderr, "Unrecognized field %d while decoding insn.\n", | |
132 | opindex); | |
133 | abort (); | |
134 | } | |
135 | ||
136 | return length; | |
137 | } | |
138 | ||
139 | /* Main entry point for printing operands. | |
140 | ||
141 | This function is basically just a big switch statement. Earlier versions | |
142 | used tables to look up the function to use, but | |
143 | - if the table contains both assembler and disassembler functions then | |
144 | the disassembler contains much of the assembler and vice-versa, | |
145 | - there's a lot of inlining possibilities as things grow, | |
146 | - using a switch statement avoids the function call overhead. | |
147 | ||
148 | This function could be moved into `print_insn_normal', but keeping it | |
149 | separate makes clear the interface between `print_insn_normal' and each of | |
150 | the handlers. | |
151 | */ | |
152 | ||
153 | CGEN_INLINE void | |
154 | m32r_cgen_print_operand (opindex, info, fields, attrs, pc, length) | |
155 | int opindex; | |
156 | disassemble_info *info; | |
157 | CGEN_FIELDS *fields; | |
158 | void const * attrs; | |
159 | bfd_vma pc; | |
160 | int length; | |
161 | { | |
162 | switch (opindex) | |
163 | { | |
164 | case M32R_OPERAND_SR : | |
165 | print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED)); | |
166 | break; | |
167 | case M32R_OPERAND_DR : | |
168 | print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED)); | |
169 | break; | |
170 | case M32R_OPERAND_SRC1 : | |
171 | print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED)); | |
172 | break; | |
173 | case M32R_OPERAND_SRC2 : | |
174 | print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED)); | |
175 | break; | |
176 | case M32R_OPERAND_SCR : | |
177 | print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED)); | |
178 | break; | |
179 | case M32R_OPERAND_DCR : | |
180 | print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED)); | |
181 | break; | |
182 | case M32R_OPERAND_SIMM8 : | |
183 | print_normal (info, fields->f_simm8, 0, pc, length); | |
184 | break; | |
185 | case M32R_OPERAND_SIMM16 : | |
186 | print_normal (info, fields->f_simm16, 0, pc, length); | |
187 | break; | |
188 | case M32R_OPERAND_UIMM4 : | |
189 | print_normal (info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length); | |
190 | break; | |
191 | case M32R_OPERAND_UIMM5 : | |
192 | print_normal (info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length); | |
193 | break; | |
194 | case M32R_OPERAND_UIMM16 : | |
195 | print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length); | |
196 | break; | |
197 | case M32R_OPERAND_ACC_S : | |
198 | print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_acc_s, 0|(1<<CGEN_OPERAND_UNSIGNED)); | |
199 | break; | |
200 | case M32R_OPERAND_ACC : | |
201 | print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED)); | |
202 | break; | |
203 | case M32R_OPERAND_HI16 : | |
204 | print_normal (info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); | |
205 | break; | |
206 | case M32R_OPERAND_SLO16 : | |
207 | print_normal (info, fields->f_simm16, 0, pc, length); | |
208 | break; | |
209 | case M32R_OPERAND_ULO16 : | |
210 | print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length); | |
211 | break; | |
212 | case M32R_OPERAND_UIMM24 : | |
213 | print_normal (info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); | |
214 | break; | |
215 | case M32R_OPERAND_DISP8 : | |
216 | print_normal (info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); | |
217 | break; | |
218 | case M32R_OPERAND_DISP16 : | |
219 | print_normal (info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); | |
220 | break; | |
221 | case M32R_OPERAND_DISP24 : | |
222 | print_normal (info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); | |
223 | break; | |
224 | ||
225 | default : | |
226 | fprintf (stderr, "Unrecognized field %d while printing insn.\n", | |
227 | opindex); | |
228 | abort (); | |
229 | } | |
230 | } | |
231 | ||
232 | cgen_extract_fn *m32r_cgen_extract_handlers[] = { | |
233 | 0, /* default */ | |
234 | extract_insn_normal, | |
235 | }; | |
236 | ||
237 | cgen_print_fn *m32r_cgen_print_handlers[] = { | |
238 | 0, /* default */ | |
239 | print_insn_normal, | |
240 | }; | |
241 | ||
242 | ||
243 | void | |
244 | m32r_cgen_init_dis (mach, endian) | |
245 | int mach; | |
246 | enum cgen_endian endian; | |
247 | { | |
248 | m32r_cgen_init_tables (mach); | |
249 | cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian); | |
250 | cgen_dis_init (); | |
251 | } | |
252 |