Commit | Line | Data |
---|---|---|
9c03036a DE |
1 | /* Disassembler interface for targets using CGEN. -*- C -*- |
2 | CGEN: Cpu tools GENerator | |
3 | ||
1c8f439e | 4 | THIS FILE IS USED TO GENERATE m32r-dis.c. |
9c03036a | 5 | |
1294c286 | 6 | Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. |
9c03036a DE |
7 | |
8 | This file is part of the GNU Binutils and GDB, the GNU debugger. | |
9 | ||
10 | This program is free software; you can redistribute it and/or modify | |
11 | it under the terms of the GNU General Public License as published by | |
12 | the Free Software Foundation; either version 2, or (at your option) | |
13 | any later version. | |
14 | ||
15 | This program is distributed in the hope that it will be useful, | |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | GNU General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
1c8f439e DE |
21 | along with this program; if not, write to the Free Software Foundation, Inc., |
22 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
9c03036a | 23 | |
23cf992f | 24 | #include "sysdep.h" |
9c03036a DE |
25 | #include <stdio.h> |
26 | #include "ansidecl.h" | |
27 | #include "dis-asm.h" | |
9c03036a | 28 | #include "bfd.h" |
0bf55db8 | 29 | #include "symcat.h" |
23cf992f | 30 | #include "m32r-opc.h" |
1c8f439e | 31 | #include "opintl.h" |
9c03036a | 32 | |
1c8f439e DE |
33 | #undef INLINE |
34 | #ifdef __GNUC__ | |
35 | #define INLINE __inline__ | |
36 | #else | |
37 | #define INLINE | |
9c03036a DE |
38 | #endif |
39 | ||
1c8f439e DE |
40 | /* Default text to print if an instruction isn't recognized. */ |
41 | #define UNKNOWN_INSN_MSG _("*unknown*") | |
9c03036a | 42 | |
5730d39d DE |
43 | /* Used by the ifield rtx function. */ |
44 | #define FLD(f) (fields->f) | |
45 | ||
1294c286 | 46 | static int extract_normal |
5730d39d DE |
47 | PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, |
48 | unsigned int, unsigned int, unsigned int, unsigned int, | |
49 | unsigned int, unsigned int, bfd_vma, long *)); | |
1294c286 | 50 | static void print_normal |
1c8f439e DE |
51 | PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int)); |
52 | static void print_address | |
53 | PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int)); | |
1294c286 | 54 | static void print_keyword |
1c8f439e | 55 | PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int)); |
9c03036a | 56 | static int extract_insn_normal |
1c8f439e | 57 | PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *, |
5730d39d | 58 | CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma)); |
9c03036a | 59 | static void print_insn_normal |
1c8f439e DE |
60 | PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *, |
61 | bfd_vma, int)); | |
62 | static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma, | |
63 | disassemble_info *, char *, int)); | |
64 | static int default_print_insn | |
65 | PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *)); | |
9c03036a | 66 | \f |
1294c286 DE |
67 | /* -- disassembler routines inserted here */ |
68 | /* -- dis.c */ | |
9c03036a | 69 | |
1294c286 | 70 | /* Immediate values are prefixed with '#'. */ |
0bf55db8 | 71 | |
1c8f439e | 72 | #define CGEN_PRINT_NORMAL(od, info, value, attrs, pc, length) \ |
1294c286 DE |
73 | do { \ |
74 | if ((attrs) & (1 << CGEN_OPERAND_HASH_PREFIX)) \ | |
75 | (*info->fprintf_func) (info->stream, "#"); \ | |
76 | } while (0) | |
9c03036a | 77 | |
1294c286 | 78 | /* Handle '#' prefixes as operands. */ |
9c03036a DE |
79 | |
80 | static void | |
1c8f439e DE |
81 | print_hash (od, dis_info, value, attrs, pc, length) |
82 | CGEN_OPCODE_DESC od; | |
ab0bd049 | 83 | PTR dis_info; |
853713a7 DE |
84 | long value; |
85 | unsigned int attrs; | |
1c8f439e | 86 | bfd_vma pc; |
853713a7 | 87 | int length; |
9c03036a | 88 | { |
b2ebff7b | 89 | disassemble_info *info = (disassemble_info *) dis_info; |
1294c286 | 90 | (*info->fprintf_func) (info->stream, "#"); |
9c03036a DE |
91 | } |
92 | ||
853713a7 DE |
93 | #undef CGEN_PRINT_INSN |
94 | #define CGEN_PRINT_INSN my_print_insn | |
95 | ||
96 | static int | |
1c8f439e DE |
97 | my_print_insn (od, pc, info) |
98 | CGEN_OPCODE_DESC od; | |
853713a7 DE |
99 | bfd_vma pc; |
100 | disassemble_info *info; | |
853713a7 | 101 | { |
1c8f439e DE |
102 | char buffer[CGEN_MAX_INSN_SIZE]; |
103 | char *buf = buffer; | |
104 | int status; | |
105 | int buflen = (pc & 3) == 0 ? 4 : 2; | |
106 | ||
107 | /* Read the base part of the insn. */ | |
108 | ||
109 | status = (*info->read_memory_func) (pc, buf, buflen, info); | |
110 | if (status != 0) | |
111 | { | |
112 | (*info->memory_error_func) (status, pc, info); | |
113 | return -1; | |
114 | } | |
115 | ||
853713a7 DE |
116 | /* 32 bit insn? */ |
117 | if ((pc & 3) == 0 && (buf[0] & 0x80) != 0) | |
1c8f439e | 118 | return print_insn (od, pc, info, buf, buflen); |
853713a7 DE |
119 | |
120 | /* Print the first insn. */ | |
121 | if ((pc & 3) == 0) | |
122 | { | |
1c8f439e | 123 | if (print_insn (od, pc, info, buf, 2) == 0) |
853713a7 DE |
124 | (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); |
125 | buf += 2; | |
126 | } | |
127 | ||
128 | if (buf[0] & 0x80) | |
129 | { | |
130 | /* Parallel. */ | |
131 | (*info->fprintf_func) (info->stream, " || "); | |
132 | buf[0] &= 0x7f; | |
133 | } | |
134 | else | |
135 | (*info->fprintf_func) (info->stream, " -> "); | |
136 | ||
1c8f439e DE |
137 | /* The "& 3" is to pass a consistent address. |
138 | Parallel insns arguably both begin on the word boundary. | |
139 | Also, branch insns are calculated relative to the word boundary. */ | |
140 | if (print_insn (od, pc & ~ (bfd_vma) 3, info, buf, 2) == 0) | |
853713a7 DE |
141 | (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); |
142 | ||
143 | return (pc & 3) ? 2 : 4; | |
144 | } | |
145 | ||
146 | /* -- */ | |
147 | ||
148 | /* Main entry point for operand extraction. | |
149 | ||
150 | This function is basically just a big switch statement. Earlier versions | |
151 | used tables to look up the function to use, but | |
152 | - if the table contains both assembler and disassembler functions then | |
153 | the disassembler contains much of the assembler and vice-versa, | |
154 | - there's a lot of inlining possibilities as things grow, | |
155 | - using a switch statement avoids the function call overhead. | |
156 | ||
157 | This function could be moved into `print_insn_normal', but keeping it | |
158 | separate makes clear the interface between `print_insn_normal' and each of | |
159 | the handlers. | |
160 | */ | |
161 | ||
0bf55db8 | 162 | int |
1c8f439e DE |
163 | m32r_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) |
164 | CGEN_OPCODE_DESC od; | |
5d07b6cf | 165 | int opindex; |
1c8f439e | 166 | CGEN_EXTRACT_INFO *ex_info; |
5730d39d | 167 | CGEN_INSN_INT insn_value; |
853713a7 | 168 | CGEN_FIELDS * fields; |
1c8f439e | 169 | bfd_vma pc; |
853713a7 DE |
170 | { |
171 | int length; | |
5730d39d | 172 | unsigned int total_length = CGEN_FIELDS_BITSIZE (fields); |
853713a7 DE |
173 | |
174 | switch (opindex) | |
175 | { | |
176 | case M32R_OPERAND_SR : | |
5730d39d | 177 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 32, total_length, pc, & fields->f_r2); |
853713a7 DE |
178 | break; |
179 | case M32R_OPERAND_DR : | |
5730d39d | 180 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 32, total_length, pc, & fields->f_r1); |
853713a7 DE |
181 | break; |
182 | case M32R_OPERAND_SRC1 : | |
5730d39d | 183 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 32, total_length, pc, & fields->f_r1); |
853713a7 DE |
184 | break; |
185 | case M32R_OPERAND_SRC2 : | |
5730d39d | 186 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 32, total_length, pc, & fields->f_r2); |
853713a7 DE |
187 | break; |
188 | case M32R_OPERAND_SCR : | |
5730d39d | 189 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 32, total_length, pc, & fields->f_r2); |
853713a7 DE |
190 | break; |
191 | case M32R_OPERAND_DCR : | |
5730d39d | 192 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 32, total_length, pc, & fields->f_r1); |
853713a7 DE |
193 | break; |
194 | case M32R_OPERAND_SIMM8 : | |
5730d39d | 195 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 8, 8, 32, total_length, pc, & fields->f_simm8); |
853713a7 DE |
196 | break; |
197 | case M32R_OPERAND_SIMM16 : | |
5730d39d | 198 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 16, 16, 32, total_length, pc, & fields->f_simm16); |
853713a7 DE |
199 | break; |
200 | case M32R_OPERAND_UIMM4 : | |
5730d39d | 201 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 32, total_length, pc, & fields->f_uimm4); |
853713a7 DE |
202 | break; |
203 | case M32R_OPERAND_UIMM5 : | |
5730d39d | 204 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 11, 5, 32, total_length, pc, & fields->f_uimm5); |
853713a7 DE |
205 | break; |
206 | case M32R_OPERAND_UIMM16 : | |
5730d39d | 207 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_uimm16); |
853713a7 | 208 | break; |
ab0bd049 DE |
209 | /* start-sanitize-m32rx */ |
210 | case M32R_OPERAND_IMM1 : | |
0bf55db8 DE |
211 | { |
212 | long value; | |
5730d39d | 213 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 15, 1, 32, total_length, pc, & value); |
1c8f439e DE |
214 | value = ((value) + (1)); |
215 | fields->f_imm1 = value; | |
0bf55db8 | 216 | } |
ab0bd049 DE |
217 | break; |
218 | /* end-sanitize-m32rx */ | |
219 | /* start-sanitize-m32rx */ | |
220 | case M32R_OPERAND_ACCD : | |
5730d39d | 221 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 2, 32, total_length, pc, & fields->f_accd); |
ab0bd049 DE |
222 | break; |
223 | /* end-sanitize-m32rx */ | |
224 | /* start-sanitize-m32rx */ | |
225 | case M32R_OPERAND_ACCS : | |
5730d39d | 226 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 2, 32, total_length, pc, & fields->f_accs); |
ab0bd049 DE |
227 | break; |
228 | /* end-sanitize-m32rx */ | |
229 | /* start-sanitize-m32rx */ | |
230 | case M32R_OPERAND_ACC : | |
5730d39d | 231 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 1, 32, total_length, pc, & fields->f_acc); |
ab0bd049 DE |
232 | break; |
233 | /* end-sanitize-m32rx */ | |
1294c286 | 234 | case M32R_OPERAND_HASH : |
5730d39d | 235 | length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil); |
1294c286 | 236 | break; |
853713a7 | 237 | case M32R_OPERAND_HI16 : |
5730d39d | 238 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_hi16); |
853713a7 DE |
239 | break; |
240 | case M32R_OPERAND_SLO16 : | |
5730d39d | 241 | length = extract_normal (od, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_simm16); |
853713a7 DE |
242 | break; |
243 | case M32R_OPERAND_ULO16 : | |
5730d39d | 244 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_uimm16); |
853713a7 DE |
245 | break; |
246 | case M32R_OPERAND_UIMM24 : | |
5730d39d | 247 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 24, 32, total_length, pc, & fields->f_uimm24); |
853713a7 DE |
248 | break; |
249 | case M32R_OPERAND_DISP8 : | |
0bf55db8 DE |
250 | { |
251 | long value; | |
5730d39d | 252 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value); |
1c8f439e DE |
253 | value = ((((value) << (2))) + (((pc) & (-4)))); |
254 | fields->f_disp8 = value; | |
0bf55db8 | 255 | } |
853713a7 DE |
256 | break; |
257 | case M32R_OPERAND_DISP16 : | |
0bf55db8 DE |
258 | { |
259 | long value; | |
5730d39d | 260 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 16, 16, 32, total_length, pc, & value); |
1c8f439e DE |
261 | value = ((((value) << (2))) + (pc)); |
262 | fields->f_disp16 = value; | |
0bf55db8 | 263 | } |
853713a7 DE |
264 | break; |
265 | case M32R_OPERAND_DISP24 : | |
0bf55db8 DE |
266 | { |
267 | long value; | |
5730d39d | 268 | length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 8, 24, 32, total_length, pc, & value); |
1c8f439e DE |
269 | value = ((((value) << (2))) + (pc)); |
270 | fields->f_disp24 = value; | |
0bf55db8 | 271 | } |
853713a7 DE |
272 | break; |
273 | ||
274 | default : | |
1c8f439e DE |
275 | /* xgettext:c-format */ |
276 | fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"), | |
853713a7 DE |
277 | opindex); |
278 | abort (); | |
279 | } | |
280 | ||
281 | return length; | |
282 | } | |
283 | ||
284 | /* Main entry point for printing operands. | |
285 | ||
286 | This function is basically just a big switch statement. Earlier versions | |
287 | used tables to look up the function to use, but | |
288 | - if the table contains both assembler and disassembler functions then | |
289 | the disassembler contains much of the assembler and vice-versa, | |
290 | - there's a lot of inlining possibilities as things grow, | |
291 | - using a switch statement avoids the function call overhead. | |
292 | ||
293 | This function could be moved into `print_insn_normal', but keeping it | |
294 | separate makes clear the interface between `print_insn_normal' and each of | |
295 | the handlers. | |
296 | */ | |
297 | ||
0bf55db8 | 298 | void |
1c8f439e DE |
299 | m32r_cgen_print_operand (od, opindex, info, fields, attrs, pc, length) |
300 | CGEN_OPCODE_DESC od; | |
5d07b6cf | 301 | int opindex; |
853713a7 | 302 | disassemble_info * info; |
5d07b6cf DE |
303 | CGEN_FIELDS * fields; |
304 | void const * attrs; | |
305 | bfd_vma pc; | |
306 | int length; | |
853713a7 DE |
307 | { |
308 | switch (opindex) | |
309 | { | |
310 | case M32R_OPERAND_SR : | |
1c8f439e | 311 | print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED)); |
853713a7 DE |
312 | break; |
313 | case M32R_OPERAND_DR : | |
1c8f439e | 314 | print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED)); |
853713a7 DE |
315 | break; |
316 | case M32R_OPERAND_SRC1 : | |
1c8f439e | 317 | print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED)); |
853713a7 DE |
318 | break; |
319 | case M32R_OPERAND_SRC2 : | |
1c8f439e | 320 | print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED)); |
853713a7 DE |
321 | break; |
322 | case M32R_OPERAND_SCR : | |
1c8f439e | 323 | print_keyword (od, info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED)); |
853713a7 DE |
324 | break; |
325 | case M32R_OPERAND_DCR : | |
1c8f439e | 326 | print_keyword (od, info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED)); |
853713a7 DE |
327 | break; |
328 | case M32R_OPERAND_SIMM8 : | |
1c8f439e | 329 | print_normal (od, info, fields->f_simm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length); |
853713a7 DE |
330 | break; |
331 | case M32R_OPERAND_SIMM16 : | |
1c8f439e | 332 | print_normal (od, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length); |
853713a7 DE |
333 | break; |
334 | case M32R_OPERAND_UIMM4 : | |
1c8f439e | 335 | print_normal (od, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); |
853713a7 DE |
336 | break; |
337 | case M32R_OPERAND_UIMM5 : | |
1c8f439e | 338 | print_normal (od, info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); |
853713a7 DE |
339 | break; |
340 | case M32R_OPERAND_UIMM16 : | |
1c8f439e | 341 | print_normal (od, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); |
853713a7 | 342 | break; |
ab0bd049 DE |
343 | /* start-sanitize-m32rx */ |
344 | case M32R_OPERAND_IMM1 : | |
1c8f439e | 345 | print_normal (od, info, fields->f_imm1, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); |
ab0bd049 DE |
346 | break; |
347 | /* end-sanitize-m32rx */ | |
348 | /* start-sanitize-m32rx */ | |
349 | case M32R_OPERAND_ACCD : | |
1c8f439e | 350 | print_keyword (od, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0|(1<<CGEN_OPERAND_UNSIGNED)); |
ab0bd049 DE |
351 | break; |
352 | /* end-sanitize-m32rx */ | |
353 | /* start-sanitize-m32rx */ | |
354 | case M32R_OPERAND_ACCS : | |
1c8f439e | 355 | print_keyword (od, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0|(1<<CGEN_OPERAND_UNSIGNED)); |
ab0bd049 DE |
356 | break; |
357 | /* end-sanitize-m32rx */ | |
358 | /* start-sanitize-m32rx */ | |
359 | case M32R_OPERAND_ACC : | |
1c8f439e | 360 | print_keyword (od, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED)); |
ab0bd049 DE |
361 | break; |
362 | /* end-sanitize-m32rx */ | |
1294c286 | 363 | case M32R_OPERAND_HASH : |
1c8f439e | 364 | print_hash (od, info, fields->f_nil, 0, pc, length); |
1294c286 | 365 | break; |
853713a7 | 366 | case M32R_OPERAND_HI16 : |
1c8f439e | 367 | print_normal (od, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); |
853713a7 DE |
368 | break; |
369 | case M32R_OPERAND_SLO16 : | |
1c8f439e | 370 | print_normal (od, info, fields->f_simm16, 0, pc, length); |
853713a7 DE |
371 | break; |
372 | case M32R_OPERAND_ULO16 : | |
1c8f439e | 373 | print_normal (od, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length); |
853713a7 DE |
374 | break; |
375 | case M32R_OPERAND_UIMM24 : | |
1c8f439e | 376 | print_address (od, info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), pc, length); |
853713a7 DE |
377 | break; |
378 | case M32R_OPERAND_DISP8 : | |
1c8f439e | 379 | print_address (od, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); |
853713a7 DE |
380 | break; |
381 | case M32R_OPERAND_DISP16 : | |
1c8f439e | 382 | print_address (od, info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); |
853713a7 DE |
383 | break; |
384 | case M32R_OPERAND_DISP24 : | |
1c8f439e | 385 | print_address (od, info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); |
853713a7 DE |
386 | break; |
387 | ||
388 | default : | |
1c8f439e DE |
389 | /* xgettext:c-format */ |
390 | fprintf (stderr, _("Unrecognized field %d while printing insn.\n"), | |
853713a7 DE |
391 | opindex); |
392 | abort (); | |
393 | } | |
394 | } | |
395 | ||
1c8f439e | 396 | cgen_extract_fn * const m32r_cgen_extract_handlers[] = |
5d07b6cf DE |
397 | { |
398 | 0, /* default */ | |
853713a7 DE |
399 | extract_insn_normal, |
400 | }; | |
401 | ||
1c8f439e | 402 | cgen_print_fn * const m32r_cgen_print_handlers[] = |
5d07b6cf DE |
403 | { |
404 | 0, /* default */ | |
853713a7 DE |
405 | print_insn_normal, |
406 | }; | |
407 | ||
408 | ||
409 | void | |
1c8f439e DE |
410 | m32r_cgen_init_dis (od) |
411 | CGEN_OPCODE_DESC od; | |
853713a7 | 412 | { |
853713a7 DE |
413 | } |
414 | ||
1294c286 | 415 | \f |
1c8f439e DE |
416 | #if ! CGEN_INT_INSN_P |
417 | ||
5730d39d DE |
418 | /* Subroutine of extract_normal. |
419 | Ensure sufficient bytes are cached in EX_INFO. | |
420 | OFFSET is the offset in bytes from the start of the insn of the value. | |
421 | BYTES is the length of the needed value. | |
422 | Returns 1 for success, 0 for failure. */ | |
423 | ||
424 | static INLINE int | |
425 | fill_cache (od, ex_info, offset, bytes, pc) | |
426 | CGEN_OPCODE_DESC od; | |
427 | CGEN_EXTRACT_INFO *ex_info; | |
428 | int offset, bytes; | |
429 | bfd_vma pc; | |
430 | { | |
431 | /* It's doubtful that the middle part has already been fetched so | |
432 | we don't optimize that case. kiss. */ | |
433 | int mask; | |
434 | disassemble_info *info = (disassemble_info *) ex_info->dis_info; | |
435 | ||
436 | /* First do a quick check. */ | |
437 | mask = (1 << bytes) - 1; | |
438 | if (((ex_info->valid >> offset) & mask) == mask) | |
439 | return 1; | |
440 | ||
441 | /* Search for the first byte we need to read. */ | |
442 | for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1) | |
443 | if (! (mask & ex_info->valid)) | |
444 | break; | |
445 | ||
446 | if (bytes) | |
447 | { | |
448 | int status; | |
449 | ||
450 | pc += offset; | |
451 | status = (*info->read_memory_func) | |
452 | (pc, ex_info->insn_bytes + offset, bytes, info); | |
453 | ||
454 | if (status != 0) | |
455 | { | |
456 | (*info->memory_error_func) (status, pc, info); | |
457 | return 0; | |
458 | } | |
459 | ||
460 | ex_info->valid |= ((1 << bytes) - 1) << offset; | |
461 | } | |
462 | ||
463 | return 1; | |
464 | } | |
465 | ||
1c8f439e DE |
466 | /* Subroutine of extract_normal. */ |
467 | ||
468 | static INLINE long | |
5730d39d | 469 | extract_1 (od, ex_info, start, length, word_length, bufp, pc) |
1c8f439e | 470 | CGEN_OPCODE_DESC od; |
5730d39d | 471 | CGEN_EXTRACT_INFO *ex_info; |
1c8f439e DE |
472 | int start,length,word_length; |
473 | unsigned char *bufp; | |
5730d39d | 474 | bfd_vma pc; |
1c8f439e DE |
475 | { |
476 | unsigned long x,mask; | |
477 | int shift; | |
478 | int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG; | |
479 | ||
1c8f439e DE |
480 | switch (word_length) |
481 | { | |
482 | case 8: | |
483 | x = *bufp; | |
484 | break; | |
485 | case 16: | |
486 | if (big_p) | |
487 | x = bfd_getb16 (bufp); | |
488 | else | |
489 | x = bfd_getl16 (bufp); | |
490 | break; | |
491 | case 24: | |
492 | /* ??? This may need reworking as these cases don't necessarily | |
493 | want the first byte and the last two bytes handled like this. */ | |
494 | if (big_p) | |
5730d39d | 495 | x = (bufp[0] << 16) | bfd_getb16 (bufp + 1); |
1c8f439e | 496 | else |
5730d39d | 497 | x = bfd_getl16 (bufp) | (bufp[2] << 16); |
1c8f439e DE |
498 | break; |
499 | case 32: | |
500 | if (big_p) | |
501 | x = bfd_getb32 (bufp); | |
502 | else | |
503 | x = bfd_getl32 (bufp); | |
504 | break; | |
505 | default : | |
506 | abort (); | |
507 | } | |
508 | ||
509 | /* Written this way to avoid undefined behaviour. */ | |
510 | mask = (((1L << (length - 1)) - 1) << 1) | 1; | |
511 | if (CGEN_INSN_LSB0_P) | |
5730d39d | 512 | shift = (start + 1) - length; |
1c8f439e DE |
513 | else |
514 | shift = (word_length - (start + length)); | |
515 | return (x >> shift) & mask; | |
516 | } | |
517 | ||
518 | #endif /* ! CGEN_INT_INSN_P */ | |
519 | ||
1294c286 DE |
520 | /* Default extraction routine. |
521 | ||
5730d39d DE |
522 | INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order, |
523 | or sometimes less for cases like the m32r where the base insn size is 32 | |
524 | but some insns are 16 bits. | |
525 | ATTRS is a mask of the boolean attributes. We only need `UNSIGNED', | |
526 | but for generality we take a bitmask of all of them. | |
527 | WORD_OFFSET is the offset in bits from the start of the insn of the value. | |
528 | WORD_LENGTH is the length of the word in bits in which the value resides. | |
529 | START is the starting bit number in the word, architecture origin. | |
530 | LENGTH is the length of VALUE in bits. | |
531 | TOTAL_LENGTH is the total length of the insn in bits. | |
532 | ||
533 | Returns 1 for success, 0 for failure. */ | |
534 | ||
535 | /* ??? The return code isn't properly used. wip. */ | |
1294c286 | 536 | |
1c8f439e DE |
537 | /* ??? This doesn't handle bfd_vma's. Create another function when |
538 | necessary. */ | |
539 | ||
1294c286 | 540 | static int |
5730d39d DE |
541 | extract_normal (od, ex_info, insn_value, attrs, word_offset, start, length, |
542 | word_length, total_length, pc, valuep) | |
1c8f439e DE |
543 | CGEN_OPCODE_DESC od; |
544 | CGEN_EXTRACT_INFO *ex_info; | |
5730d39d | 545 | CGEN_INSN_INT insn_value; |
1294c286 | 546 | unsigned int attrs; |
5730d39d DE |
547 | unsigned int word_offset, start, length, word_length, total_length; |
548 | bfd_vma pc; | |
1294c286 DE |
549 | long *valuep; |
550 | { | |
5730d39d | 551 | CGEN_INSN_INT value; |
1c8f439e DE |
552 | |
553 | /* If LENGTH is zero, this operand doesn't contribute to the value | |
554 | so give it a standard value of zero. */ | |
555 | if (length == 0) | |
556 | { | |
557 | *valuep = 0; | |
558 | return 1; | |
559 | } | |
560 | ||
5730d39d DE |
561 | if (CGEN_INT_INSN_P |
562 | && word_offset != 0) | |
563 | abort (); | |
1c8f439e | 564 | |
5730d39d DE |
565 | if (word_length > 32) |
566 | abort (); | |
1c8f439e | 567 | |
5730d39d DE |
568 | /* For architectures with insns smaller than the insn-base-bitsize, |
569 | word_length may be too big. */ | |
570 | #if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE | |
571 | if (word_offset == 0 | |
572 | && word_length > total_length) | |
573 | word_length = total_length; | |
574 | #endif | |
1c8f439e | 575 | |
5730d39d | 576 | /* Does the value reside in INSN_VALUE? */ |
1c8f439e | 577 | |
5730d39d | 578 | if (word_offset == 0) |
1c8f439e | 579 | { |
5730d39d DE |
580 | /* Written this way to avoid undefined behaviour. */ |
581 | CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1; | |
582 | ||
583 | if (CGEN_INSN_LSB0_P) | |
584 | value = insn_value >> ((start + 1) - length); | |
585 | else | |
586 | value = insn_value >> (word_length - (start + length)); | |
587 | value &= mask; | |
588 | /* sign extend? */ | |
589 | if (! CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED) | |
590 | && (value & (1L << (length - 1)))) | |
591 | value |= ~mask; | |
1c8f439e | 592 | } |
5730d39d DE |
593 | |
594 | #if ! CGEN_INT_INSN_P | |
595 | ||
1c8f439e DE |
596 | else |
597 | { | |
5730d39d | 598 | unsigned char *bufp = ex_info->insn_bytes + word_offset / 8; |
1c8f439e | 599 | |
5730d39d | 600 | if (word_length > 32) |
1c8f439e DE |
601 | abort (); |
602 | ||
5730d39d DE |
603 | if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0) |
604 | return 0; | |
1c8f439e | 605 | |
5730d39d | 606 | value = extract_1 (od, ex_info, start, length, word_length, bufp, pc); |
1c8f439e DE |
607 | } |
608 | ||
609 | #endif /* ! CGEN_INT_INSN_P */ | |
1294c286 DE |
610 | |
611 | *valuep = value; | |
612 | ||
1294c286 DE |
613 | return 1; |
614 | } | |
615 | ||
616 | /* Default print handler. */ | |
617 | ||
618 | static void | |
1c8f439e DE |
619 | print_normal (od, dis_info, value, attrs, pc, length) |
620 | CGEN_OPCODE_DESC od; | |
1294c286 DE |
621 | PTR dis_info; |
622 | long value; | |
623 | unsigned int attrs; | |
1c8f439e | 624 | bfd_vma pc; |
1294c286 DE |
625 | int length; |
626 | { | |
1c8f439e | 627 | disassemble_info *info = (disassemble_info *) dis_info; |
1294c286 DE |
628 | |
629 | #ifdef CGEN_PRINT_NORMAL | |
1c8f439e | 630 | CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length); |
1294c286 DE |
631 | #endif |
632 | ||
633 | /* Print the operand as directed by the attributes. */ | |
1c8f439e DE |
634 | if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY)) |
635 | ; /* nothing to do */ | |
1294c286 DE |
636 | else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED)) |
637 | (*info->fprintf_func) (info->stream, "0x%lx", value); | |
638 | else | |
639 | (*info->fprintf_func) (info->stream, "%ld", value); | |
640 | } | |
641 | ||
1c8f439e DE |
642 | /* Default address handler. */ |
643 | ||
644 | static void | |
645 | print_address (od, dis_info, value, attrs, pc, length) | |
646 | CGEN_OPCODE_DESC od; | |
647 | PTR dis_info; | |
648 | bfd_vma value; | |
649 | unsigned int attrs; | |
650 | bfd_vma pc; | |
651 | int length; | |
652 | { | |
653 | disassemble_info *info = (disassemble_info *) dis_info; | |
654 | ||
655 | #ifdef CGEN_PRINT_ADDRESS | |
656 | CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length); | |
657 | #endif | |
658 | ||
659 | /* Print the operand as directed by the attributes. */ | |
660 | if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY)) | |
661 | ; /* nothing to do */ | |
662 | else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR)) | |
663 | (*info->print_address_func) (value, info); | |
664 | else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR)) | |
665 | (*info->print_address_func) (value, info); | |
666 | else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED)) | |
667 | (*info->fprintf_func) (info->stream, "0x%lx", (long) value); | |
668 | else | |
669 | (*info->fprintf_func) (info->stream, "%ld", (long) value); | |
670 | } | |
671 | ||
1294c286 DE |
672 | /* Keyword print handler. */ |
673 | ||
674 | static void | |
1c8f439e DE |
675 | print_keyword (od, dis_info, keyword_table, value, attrs) |
676 | CGEN_OPCODE_DESC od; | |
1294c286 DE |
677 | PTR dis_info; |
678 | CGEN_KEYWORD *keyword_table; | |
679 | long value; | |
680 | unsigned int attrs; | |
681 | { | |
1c8f439e | 682 | disassemble_info *info = (disassemble_info *) dis_info; |
1294c286 DE |
683 | const CGEN_KEYWORD_ENTRY *ke; |
684 | ||
685 | ke = cgen_keyword_lookup_value (keyword_table, value); | |
686 | if (ke != NULL) | |
687 | (*info->fprintf_func) (info->stream, "%s", ke->name); | |
688 | else | |
689 | (*info->fprintf_func) (info->stream, "???"); | |
690 | } | |
9c03036a DE |
691 | \f |
692 | /* Default insn extractor. | |
693 | ||
1c8f439e DE |
694 | INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order. |
695 | The extracted fields are stored in FIELDS. | |
696 | EX_INFO is used to handle reading variable length insns. | |
697 | Return the length of the insn in bits, or 0 if no match, | |
698 | or -1 if an error occurs fetching data (memory_error_func will have | |
699 | been called). */ | |
9c03036a DE |
700 | |
701 | static int | |
1c8f439e DE |
702 | extract_insn_normal (od, insn, ex_info, insn_value, fields, pc) |
703 | CGEN_OPCODE_DESC od; | |
853713a7 | 704 | const CGEN_INSN *insn; |
1c8f439e | 705 | CGEN_EXTRACT_INFO *ex_info; |
5730d39d | 706 | CGEN_INSN_INT insn_value; |
853713a7 | 707 | CGEN_FIELDS *fields; |
1c8f439e | 708 | bfd_vma pc; |
9c03036a | 709 | { |
853713a7 DE |
710 | const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); |
711 | const unsigned char *syn; | |
9c03036a | 712 | |
9c03036a DE |
713 | CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); |
714 | ||
1c8f439e | 715 | CGEN_INIT_EXTRACT (od); |
9c03036a | 716 | |
853713a7 | 717 | for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn) |
9c03036a DE |
718 | { |
719 | int length; | |
720 | ||
853713a7 | 721 | if (CGEN_SYNTAX_CHAR_P (*syn)) |
9c03036a DE |
722 | continue; |
723 | ||
1c8f439e DE |
724 | length = m32r_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn), |
725 | ex_info, insn_value, fields, pc); | |
726 | if (length <= 0) | |
727 | return length; | |
9c03036a DE |
728 | } |
729 | ||
23cf992f NC |
730 | /* We recognized and successfully extracted this insn. */ |
731 | return CGEN_INSN_BITSIZE (insn); | |
9c03036a DE |
732 | } |
733 | ||
734 | /* Default insn printer. | |
735 | ||
ab0bd049 | 736 | DIS_INFO is defined as `PTR' so the disassembler needn't know anything |
1c8f439e | 737 | about disassemble_info. */ |
9c03036a DE |
738 | |
739 | static void | |
1c8f439e DE |
740 | print_insn_normal (od, dis_info, insn, fields, pc, length) |
741 | CGEN_OPCODE_DESC od; | |
ab0bd049 | 742 | PTR dis_info; |
853713a7 DE |
743 | const CGEN_INSN *insn; |
744 | CGEN_FIELDS *fields; | |
745 | bfd_vma pc; | |
746 | int length; | |
9c03036a | 747 | { |
853713a7 | 748 | const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); |
1c8f439e | 749 | disassemble_info *info = (disassemble_info *) dis_info; |
853713a7 | 750 | const unsigned char *syn; |
9c03036a | 751 | |
1c8f439e | 752 | CGEN_INIT_PRINT (od); |
9c03036a | 753 | |
853713a7 | 754 | for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn) |
9c03036a | 755 | { |
853713a7 | 756 | if (CGEN_SYNTAX_MNEMONIC_P (*syn)) |
23cf992f | 757 | { |
853713a7 | 758 | (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn)); |
23cf992f NC |
759 | continue; |
760 | } | |
853713a7 | 761 | if (CGEN_SYNTAX_CHAR_P (*syn)) |
9c03036a | 762 | { |
853713a7 | 763 | (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn)); |
9c03036a DE |
764 | continue; |
765 | } | |
766 | ||
767 | /* We have an operand. */ | |
1c8f439e DE |
768 | m32r_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info, |
769 | fields, CGEN_INSN_ATTRS (insn), pc, length); | |
9c03036a DE |
770 | } |
771 | } | |
772 | \f | |
1c8f439e DE |
773 | /* Utility to print an insn. |
774 | BUF is the base part of the insn, target byte order, BUFLEN bytes long. | |
775 | The result is the size of the insn in bytes or zero for an unknown insn | |
776 | or -1 if an error occurs fetching data (memory_error_func will have | |
777 | been called). */ | |
9c03036a DE |
778 | |
779 | static int | |
1c8f439e DE |
780 | print_insn (od, pc, info, buf, buflen) |
781 | CGEN_OPCODE_DESC od; | |
853713a7 DE |
782 | bfd_vma pc; |
783 | disassemble_info *info; | |
784 | char *buf; | |
785 | int buflen; | |
9c03036a | 786 | { |
853713a7 DE |
787 | unsigned long insn_value; |
788 | const CGEN_INSN_LIST *insn_list; | |
1c8f439e DE |
789 | CGEN_EXTRACT_INFO ex_info; |
790 | ||
791 | ex_info.dis_info = info; | |
792 | ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1; | |
5730d39d | 793 | ex_info.insn_bytes = buf; |
853713a7 | 794 | |
9c03036a DE |
795 | switch (buflen) |
796 | { | |
1c8f439e | 797 | case 1: |
9c03036a DE |
798 | insn_value = buf[0]; |
799 | break; | |
1c8f439e | 800 | case 2: |
9c03036a DE |
801 | insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf); |
802 | break; | |
1c8f439e | 803 | case 4: |
9c03036a DE |
804 | insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf); |
805 | break; | |
806 | default: | |
807 | abort (); | |
808 | } | |
809 | ||
810 | /* The instructions are stored in hash lists. | |
811 | Pick the first one and keep trying until we find the right one. */ | |
812 | ||
1c8f439e | 813 | insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value); |
9c03036a DE |
814 | while (insn_list != NULL) |
815 | { | |
853713a7 | 816 | const CGEN_INSN *insn = insn_list->insn; |
853713a7 DE |
817 | CGEN_FIELDS fields; |
818 | int length; | |
9c03036a DE |
819 | |
820 | #if 0 /* not needed as insn shouldn't be in hash lists if not supported */ | |
821 | /* Supported by this cpu? */ | |
1c8f439e | 822 | if (! m32r_cgen_insn_supported (od, insn)) |
9c03036a DE |
823 | continue; |
824 | #endif | |
825 | ||
826 | /* Basic bit mask must be correct. */ | |
827 | /* ??? May wish to allow target to defer this check until the extract | |
828 | handler. */ | |
5730d39d DE |
829 | if ((insn_value & CGEN_INSN_BASE_MASK (insn)) |
830 | == CGEN_INSN_BASE_VALUE (insn)) | |
9c03036a DE |
831 | { |
832 | /* Printing is handled in two passes. The first pass parses the | |
833 | machine insn and extracts the fields. The second pass prints | |
834 | them. */ | |
835 | ||
1c8f439e DE |
836 | length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value, |
837 | &fields, pc); | |
838 | /* length < 0 -> error */ | |
839 | if (length < 0) | |
840 | return length; | |
9c03036a DE |
841 | if (length > 0) |
842 | { | |
1c8f439e | 843 | (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length); |
9c03036a | 844 | /* length is in bits, result is in bytes */ |
853713a7 | 845 | return length / 8; |
9c03036a DE |
846 | } |
847 | } | |
853713a7 | 848 | |
9c03036a DE |
849 | insn_list = CGEN_DIS_NEXT_INSN (insn_list); |
850 | } | |
851 | ||
853713a7 | 852 | return 0; |
9c03036a DE |
853 | } |
854 | ||
1c8f439e DE |
855 | /* Default value for CGEN_PRINT_INSN. |
856 | The result is the size of the insn in bytes or zero for an unknown insn | |
857 | or -1 if an error occured fetching bytes. */ | |
858 | ||
859 | #ifndef CGEN_PRINT_INSN | |
860 | #define CGEN_PRINT_INSN default_print_insn | |
861 | #endif | |
862 | ||
863 | static int | |
864 | default_print_insn (od, pc, info) | |
865 | CGEN_OPCODE_DESC od; | |
866 | bfd_vma pc; | |
867 | disassemble_info *info; | |
868 | { | |
869 | char buf[CGEN_MAX_INSN_SIZE]; | |
870 | int status; | |
871 | ||
872 | /* Read the base part of the insn. */ | |
873 | ||
874 | status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info); | |
875 | if (status != 0) | |
876 | { | |
877 | (*info->memory_error_func) (status, pc, info); | |
878 | return -1; | |
879 | } | |
880 | ||
881 | return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE); | |
882 | } | |
883 | ||
9c03036a DE |
884 | /* Main entry point. |
885 | Print one instruction from PC on INFO->STREAM. | |
886 | Return the size of the instruction (in bytes). */ | |
887 | ||
888 | int | |
889 | print_insn_m32r (pc, info) | |
853713a7 DE |
890 | bfd_vma pc; |
891 | disassemble_info *info; | |
9c03036a | 892 | { |
1c8f439e DE |
893 | int length; |
894 | static CGEN_OPCODE_DESC od = 0; | |
853713a7 DE |
895 | int mach = info->mach; |
896 | int big_p = info->endian == BFD_ENDIAN_BIG; | |
9c03036a | 897 | |
1c8f439e DE |
898 | /* If we haven't initialized yet, initialize the opcode table. */ |
899 | if (! od) | |
9c03036a | 900 | { |
1c8f439e DE |
901 | od = m32r_cgen_opcode_open (mach, |
902 | big_p ? | |
903 | CGEN_ENDIAN_BIG | |
904 | : CGEN_ENDIAN_LITTLE); | |
905 | m32r_cgen_init_dis (od); | |
9c03036a | 906 | } |
1c8f439e DE |
907 | /* If we've switched cpu's, re-initialize. */ |
908 | /* ??? Perhaps we should use BFD_ENDIAN. */ | |
909 | else if (mach != CGEN_OPCODE_MACH (od) | |
910 | || (CGEN_OPCODE_ENDIAN (od) | |
911 | != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE))) | |
9c03036a | 912 | { |
1c8f439e | 913 | cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE); |
9c03036a DE |
914 | } |
915 | ||
916 | /* We try to have as much common code as possible. | |
917 | But at this point some targets need to take over. */ | |
918 | /* ??? Some targets may need a hook elsewhere. Try to avoid this, | |
23cf992f | 919 | but if not possible try to move this hook elsewhere rather than |
9c03036a | 920 | have two hooks. */ |
1c8f439e DE |
921 | length = CGEN_PRINT_INSN (od, pc, info); |
922 | if (length > 0) | |
9c03036a | 923 | return length; |
1c8f439e DE |
924 | if (length < 0) |
925 | return -1; | |
9c03036a | 926 | |
853713a7 | 927 | (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); |
9c03036a DE |
928 | return CGEN_DEFAULT_INSN_SIZE; |
929 | } |