Thu Nov 26 11:26:32 1998 Dave Brolley <brolley@cygnus.com>
[deliverable/binutils-gdb.git] / opcodes / fr30-dis.c
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE fr30-dis.c.
5
6 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
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
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. */
23
24 #include "sysdep.h"
25 #include <stdio.h>
26 #include "ansidecl.h"
27 #include "dis-asm.h"
28 #include "bfd.h"
29 #include "symcat.h"
30 #include "fr30-opc.h"
31 #include "opintl.h"
32
33 #undef INLINE
34 #ifdef __GNUC__
35 #define INLINE __inline__
36 #else
37 #define INLINE
38 #endif
39
40 /* Default text to print if an instruction isn't recognized. */
41 #define UNKNOWN_INSN_MSG _("*unknown*")
42
43 static int extract_normal
44 PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
45 unsigned int, int, int, int, bfd_vma, long *));
46 static void print_normal
47 PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int));
48 static void print_address
49 PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
50 static void print_keyword
51 PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
52 static int extract_insn_normal
53 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
54 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
55 static void print_insn_normal
56 PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
57 bfd_vma, int));
58 static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma,
59 disassemble_info *, char *, int));
60 static int default_print_insn
61 PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *));
62 \f
63 /* -- disassembler routines inserted here */
64 /* -- dis.c */
65
66 static void
67 print_register_list (dis_info, value, offset)
68 PTR dis_info;
69 long value;
70 long offset;
71 {
72 disassemble_info *info = dis_info;
73 int mask = 1;
74 int index;
75
76 if (value & mask)
77 (*info->fprintf_func) (info->stream, "r%i", index + offset);
78
79 for (index = 1; index <= 7; ++index)
80 {
81 mask <<= 1;
82 if (value & mask)
83 (*info->fprintf_func) (info->stream, ",r%i", index + offset);
84 }
85 }
86
87 static void
88 print_hi_register_list (od, dis_info, value, attrs, pc, length)
89 CGEN_OPCODE_DESC od;
90 PTR dis_info;
91 long value;
92 unsigned int attrs;
93 bfd_vma pc;
94 int length;
95 {
96 print_register_list (dis_info, value, 8);
97 }
98
99 static void
100 print_low_register_list (od, dis_info, value, attrs, pc, length)
101 CGEN_OPCODE_DESC od;
102 PTR dis_info;
103 long value;
104 unsigned int attrs;
105 bfd_vma pc;
106 int length;
107 {
108 print_register_list (dis_info, value, 0);
109 }
110
111 static void
112 print_label9 (od, dis_info, value, attrs, pc, length)
113 CGEN_OPCODE_DESC od;
114 PTR dis_info;
115 long value;
116 unsigned int attrs;
117 bfd_vma pc;
118 int length;
119 {
120 disassemble_info *info = (disassemble_info *) dis_info;
121 (*info->fprintf_func) (info->stream, "0x%lx", value);
122 }
123
124 /* -- */
125
126 /* Main entry point for operand extraction.
127
128 This function is basically just a big switch statement. Earlier versions
129 used tables to look up the function to use, but
130 - if the table contains both assembler and disassembler functions then
131 the disassembler contains much of the assembler and vice-versa,
132 - there's a lot of inlining possibilities as things grow,
133 - using a switch statement avoids the function call overhead.
134
135 This function could be moved into `print_insn_normal', but keeping it
136 separate makes clear the interface between `print_insn_normal' and each of
137 the handlers.
138 */
139
140 int
141 fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc)
142 CGEN_OPCODE_DESC od;
143 int opindex;
144 CGEN_EXTRACT_INFO *ex_info;
145 CGEN_INSN_INT insn_value;
146 CGEN_FIELDS * fields;
147 bfd_vma pc;
148 {
149 int length;
150
151 switch (opindex)
152 {
153 case FR30_OPERAND_RI :
154 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Ri);
155 break;
156 case FR30_OPERAND_RJ :
157 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Rj);
158 break;
159 case FR30_OPERAND_RIC :
160 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 28, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Ric);
161 break;
162 case FR30_OPERAND_RJC :
163 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 24, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Rjc);
164 break;
165 case FR30_OPERAND_CRI :
166 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 28, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_CRi);
167 break;
168 case FR30_OPERAND_CRJ :
169 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 24, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_CRj);
170 break;
171 case FR30_OPERAND_RS1 :
172 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Rs1);
173 break;
174 case FR30_OPERAND_RS2 :
175 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Rs2);
176 break;
177 case FR30_OPERAND_R13 :
178 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil);
179 break;
180 case FR30_OPERAND_R14 :
181 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil);
182 break;
183 case FR30_OPERAND_R15 :
184 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil);
185 break;
186 case FR30_OPERAND_PS :
187 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil);
188 break;
189 case FR30_OPERAND_U4 :
190 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_u4);
191 break;
192 case FR30_OPERAND_U4C :
193 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_u4c);
194 break;
195 case FR30_OPERAND_M4 :
196 {
197 long value;
198 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & value);
199 value = ((value) | ((! (15))));
200 fields->f_m4 = value;
201 }
202 break;
203 case FR30_OPERAND_U8 :
204 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_u8);
205 break;
206 case FR30_OPERAND_I8 :
207 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_i8);
208 break;
209 case FR30_OPERAND_UDISP6 :
210 {
211 long value;
212 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & value);
213 value = ((value) << (2));
214 fields->f_udisp6 = value;
215 }
216 break;
217 case FR30_OPERAND_DISP8 :
218 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_disp8);
219 break;
220 case FR30_OPERAND_DISP9 :
221 {
222 long value;
223 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
224 value = ((value) << (1));
225 fields->f_disp9 = value;
226 }
227 break;
228 case FR30_OPERAND_DISP10 :
229 {
230 long value;
231 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
232 value = ((value) << (2));
233 fields->f_disp10 = value;
234 }
235 break;
236 case FR30_OPERAND_S10 :
237 {
238 long value;
239 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
240 value = ((value) << (2));
241 fields->f_s10 = value;
242 }
243 break;
244 case FR30_OPERAND_U10 :
245 {
246 long value;
247 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
248 value = ((value) << (2));
249 fields->f_u10 = value;
250 }
251 break;
252 case FR30_OPERAND_I32 :
253 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 32, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_i32);
254 break;
255 case FR30_OPERAND_DIR8 :
256 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_dir8);
257 break;
258 case FR30_OPERAND_DIR9 :
259 {
260 long value;
261 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
262 value = ((value) << (1));
263 fields->f_dir9 = value;
264 }
265 break;
266 case FR30_OPERAND_DIR10 :
267 {
268 long value;
269 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
270 value = ((value) << (2));
271 fields->f_dir10 = value;
272 }
273 break;
274 case FR30_OPERAND_LABEL9 :
275 {
276 long value;
277 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
278 value = ((((value) << (1))) + (((pc) + (2))));
279 fields->f_rel9 = value;
280 }
281 break;
282 case FR30_OPERAND_LABEL12 :
283 {
284 long value;
285 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 5, 11, CGEN_FIELDS_BITSIZE (fields), pc, & value);
286 value = ((((value) << (1))) + (((pc) & (-2))));
287 fields->f_rel12 = value;
288 }
289 break;
290 case FR30_OPERAND_REGLIST_LOW :
291 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_reglist_low);
292 break;
293 case FR30_OPERAND_REGLIST_HI :
294 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_reglist_hi);
295 break;
296 case FR30_OPERAND_CC :
297 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_cc);
298 break;
299 case FR30_OPERAND_CCC :
300 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_ccc);
301 break;
302
303 default :
304 /* xgettext:c-format */
305 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
306 opindex);
307 abort ();
308 }
309
310 return length;
311 }
312
313 /* Main entry point for printing operands.
314
315 This function is basically just a big switch statement. Earlier versions
316 used tables to look up the function to use, but
317 - if the table contains both assembler and disassembler functions then
318 the disassembler contains much of the assembler and vice-versa,
319 - there's a lot of inlining possibilities as things grow,
320 - using a switch statement avoids the function call overhead.
321
322 This function could be moved into `print_insn_normal', but keeping it
323 separate makes clear the interface between `print_insn_normal' and each of
324 the handlers.
325 */
326
327 void
328 fr30_cgen_print_operand (od, opindex, info, fields, attrs, pc, length)
329 CGEN_OPCODE_DESC od;
330 int opindex;
331 disassemble_info * info;
332 CGEN_FIELDS * fields;
333 void const * attrs;
334 bfd_vma pc;
335 int length;
336 {
337 switch (opindex)
338 {
339 case FR30_OPERAND_RI :
340 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Ri, 0|(1<<CGEN_OPERAND_UNSIGNED));
341 break;
342 case FR30_OPERAND_RJ :
343 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Rj, 0|(1<<CGEN_OPERAND_UNSIGNED));
344 break;
345 case FR30_OPERAND_RIC :
346 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Ric, 0|(1<<CGEN_OPERAND_UNSIGNED));
347 break;
348 case FR30_OPERAND_RJC :
349 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Rjc, 0|(1<<CGEN_OPERAND_UNSIGNED));
350 break;
351 case FR30_OPERAND_CRI :
352 print_keyword (od, info, & fr30_cgen_opval_h_cr, fields->f_CRi, 0|(1<<CGEN_OPERAND_UNSIGNED));
353 break;
354 case FR30_OPERAND_CRJ :
355 print_keyword (od, info, & fr30_cgen_opval_h_cr, fields->f_CRj, 0|(1<<CGEN_OPERAND_UNSIGNED));
356 break;
357 case FR30_OPERAND_RS1 :
358 print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs1, 0|(1<<CGEN_OPERAND_UNSIGNED));
359 break;
360 case FR30_OPERAND_RS2 :
361 print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs2, 0|(1<<CGEN_OPERAND_UNSIGNED));
362 break;
363 case FR30_OPERAND_R13 :
364 print_keyword (od, info, & fr30_cgen_opval_h_r13, fields->f_nil, 0);
365 break;
366 case FR30_OPERAND_R14 :
367 print_keyword (od, info, & fr30_cgen_opval_h_r14, fields->f_nil, 0);
368 break;
369 case FR30_OPERAND_R15 :
370 print_keyword (od, info, & fr30_cgen_opval_h_r15, fields->f_nil, 0);
371 break;
372 case FR30_OPERAND_PS :
373 print_keyword (od, info, & fr30_cgen_opval_h_ps, fields->f_nil, 0);
374 break;
375 case FR30_OPERAND_U4 :
376 print_normal (od, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
377 break;
378 case FR30_OPERAND_U4C :
379 print_normal (od, info, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
380 break;
381 case FR30_OPERAND_M4 :
382 print_normal (od, info, fields->f_m4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
383 break;
384 case FR30_OPERAND_U8 :
385 print_normal (od, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
386 break;
387 case FR30_OPERAND_I8 :
388 print_normal (od, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
389 break;
390 case FR30_OPERAND_UDISP6 :
391 print_normal (od, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
392 break;
393 case FR30_OPERAND_DISP8 :
394 print_normal (od, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
395 break;
396 case FR30_OPERAND_DISP9 :
397 print_normal (od, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
398 break;
399 case FR30_OPERAND_DISP10 :
400 print_normal (od, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
401 break;
402 case FR30_OPERAND_S10 :
403 print_normal (od, info, fields->f_s10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
404 break;
405 case FR30_OPERAND_U10 :
406 print_normal (od, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
407 break;
408 case FR30_OPERAND_I32 :
409 print_normal (od, info, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
410 break;
411 case FR30_OPERAND_DIR8 :
412 print_normal (od, info, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
413 break;
414 case FR30_OPERAND_DIR9 :
415 print_normal (od, info, fields->f_dir9, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
416 break;
417 case FR30_OPERAND_DIR10 :
418 print_normal (od, info, fields->f_dir10, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
419 break;
420 case FR30_OPERAND_LABEL9 :
421 print_label9 (od, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), pc, length);
422 break;
423 case FR30_OPERAND_LABEL12 :
424 print_normal (od, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), pc, length);
425 break;
426 case FR30_OPERAND_REGLIST_LOW :
427 print_low_register_list (od, info, fields->f_reglist_low, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
428 break;
429 case FR30_OPERAND_REGLIST_HI :
430 print_hi_register_list (od, info, fields->f_reglist_hi, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
431 break;
432 case FR30_OPERAND_CC :
433 print_normal (od, info, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
434 break;
435 case FR30_OPERAND_CCC :
436 print_normal (od, info, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
437 break;
438
439 default :
440 /* xgettext:c-format */
441 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
442 opindex);
443 abort ();
444 }
445 }
446
447 cgen_extract_fn * const fr30_cgen_extract_handlers[] =
448 {
449 0, /* default */
450 extract_insn_normal,
451 };
452
453 cgen_print_fn * const fr30_cgen_print_handlers[] =
454 {
455 0, /* default */
456 print_insn_normal,
457 };
458
459
460 void
461 fr30_cgen_init_dis (od)
462 CGEN_OPCODE_DESC od;
463 {
464 }
465
466 \f
467 #if ! CGEN_INT_INSN_P
468
469 /* Subroutine of extract_normal.
470 Ensure sufficient bytes are cached in EX_INFO.
471 Returns 1 for success, 0 for failure. */
472
473 static INLINE int
474 fill_cache (od, ex_info, offset, bytes, pc)
475 CGEN_OPCODE_DESC od;
476 CGEN_EXTRACT_INFO *ex_info;
477 int offset, bytes;
478 bfd_vma pc;
479 {
480 /* It's doubtful that the middle part has already been fetched so
481 we don't optimize that case. kiss. */
482 int mask;
483 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
484
485 /* First do a quick check. */
486 mask = (1 << bytes) - 1;
487 if (((ex_info->valid >> offset) & mask) == mask)
488 return 1;
489
490 /* Search for the first byte we need to read. */
491 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
492 if (! (mask & ex_info->valid))
493 break;
494
495 if (bytes)
496 {
497 int status;
498
499 pc += offset;
500 status = (*info->read_memory_func)
501 (pc, ex_info->insn_bytes + offset, bytes, info);
502
503 if (status != 0)
504 {
505 (*info->memory_error_func) (status, pc, info);
506 return 0;
507 }
508
509 ex_info->valid |= ((1 << bytes) - 1) << offset;
510 }
511
512 return 1;
513 }
514
515 /* Subroutine of extract_normal. */
516
517 static INLINE long
518 extract_1 (od, ex_info, start, length, word_length, bufp, pc)
519 CGEN_OPCODE_DESC od;
520 CGEN_EXTRACT_INFO *ex_info;
521 int start,length,word_length;
522 unsigned char *bufp;
523 bfd_vma pc;
524 {
525 unsigned long x,mask;
526 int shift;
527 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
528
529 switch (word_length)
530 {
531 case 8:
532 x = *bufp;
533 break;
534 case 16:
535 if (big_p)
536 x = bfd_getb16 (bufp);
537 else
538 x = bfd_getl16 (bufp);
539 break;
540 case 24:
541 /* ??? This may need reworking as these cases don't necessarily
542 want the first byte and the last two bytes handled like this. */
543 if (big_p)
544 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
545 else
546 x = bfd_getl16 (bufp) | (bufp[2] << 16);
547 break;
548 case 32:
549 if (big_p)
550 x = bfd_getb32 (bufp);
551 else
552 x = bfd_getl32 (bufp);
553 break;
554 default :
555 abort ();
556 }
557
558 /* Written this way to avoid undefined behaviour. */
559 mask = (((1L << (length - 1)) - 1) << 1) | 1;
560 if (CGEN_INSN_LSB0_P)
561 shift = start;
562 else
563 shift = (word_length - (start + length));
564 return (x >> shift) & mask;
565 }
566
567 #endif /* ! CGEN_INT_INSN_P */
568
569 /* Default extraction routine.
570
571 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order,
572 or sometimes less for cases like the m32r where the base insn size is 32
573 but some insns are 16 bits.
574 ATTRS is a mask of the boolean attributes. We only need `unsigned',
575 but for generality we take a bitmask of all of them.
576 TOTAL_LENGTH is the length of the insn in bits.
577
578 Returns 1 for success, 0 for failure. */
579
580 /* ??? This doesn't handle bfd_vma's. Create another function when
581 necessary. */
582
583 static int
584 extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, pc, valuep)
585 CGEN_OPCODE_DESC od;
586 CGEN_EXTRACT_INFO *ex_info;
587 CGEN_INSN_INT insn_value;
588 unsigned int attrs;
589 int start, length, total_length;
590 bfd_vma pc;
591 long *valuep;
592 {
593 unsigned long value;
594
595 /* If LENGTH is zero, this operand doesn't contribute to the value
596 so give it a standard value of zero. */
597 if (length == 0)
598 {
599 *valuep = 0;
600 return 1;
601 }
602
603 if (CGEN_INT_INSN_P
604 || (CGEN_INSN_LSB0_P
605 ? ((total_length - start) <= CGEN_BASE_INSN_BITSIZE)
606 : ((start + length) <= CGEN_BASE_INSN_BITSIZE)))
607 {
608 /* Written this way to avoid undefined behaviour. */
609 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
610
611 if (CGEN_INSN_LSB0_P)
612 value = insn_value >> start;
613 else
614 value = insn_value >> (total_length - (start + length));
615 value &= mask;
616 /* sign extend? */
617 if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
618 && (value & (1L << (length - 1))))
619 value |= ~mask;
620 }
621
622 #if ! CGEN_INT_INSN_P
623
624 /* The hard case is probably too slow for the normal cases.
625 It's certainly more difficult to understand than the normal case.
626 Thus this is split into two. The hard case is defined
627 to be when a field straddles a (loosely defined) word boundary
628 (??? which may require target specific help to determine). */
629
630 #define HARD_CASE_P 0 /* FIXME:wip */
631
632 else if (HARD_CASE_P)
633 {
634 }
635
636 else
637 {
638 unsigned char *bufp = ex_info->insn_bytes;
639 int offset = 0;
640
641 if (length > 32)
642 abort ();
643
644 /* Adjust start,total_length,bufp to point to the pseudo-word that holds
645 the value. For example in a 48 bit insn where the value to insert
646 (say an immediate value) is the last 16 bits then fetch_length here
647 would be 16. To handle a 24 bit insn with an 18 bit immediate,
648 extract_1 handles 24 bits. */
649
650 if (total_length > 32)
651 {
652 int needed_width = start % 8 + length;
653 int fetch_length = (needed_width <= 8 ? 8
654 : needed_width <= 16 ? 16
655 : 32);
656
657 if (CGEN_INSN_LSB0_P)
658 {
659 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
660 {
661 abort (); /* wip */
662 }
663 else
664 {
665 offset = start & ~7;
666
667 bufp += offset / 8;
668 start -= offset;
669 total_length = fetch_length;
670 }
671 }
672 else
673 {
674 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
675 {
676 offset = start & ~7;
677
678 bufp += offset / 8;
679 start -= offset;
680 total_length = fetch_length;
681 }
682 else
683 {
684 abort (); /* wip */
685 }
686 }
687 }
688
689 if (fill_cache (od, ex_info, offset / 8, total_length / 8, pc) == 0)
690 return 0;
691
692 value = extract_1 (od, ex_info, start, length, total_length, bufp, pc);
693 }
694
695 #endif /* ! CGEN_INT_INSN_P */
696
697 *valuep = value;
698
699 return 1;
700 }
701
702 /* Default print handler. */
703
704 static void
705 print_normal (od, dis_info, value, attrs, pc, length)
706 CGEN_OPCODE_DESC od;
707 PTR dis_info;
708 long value;
709 unsigned int attrs;
710 bfd_vma pc;
711 int length;
712 {
713 disassemble_info *info = (disassemble_info *) dis_info;
714
715 #ifdef CGEN_PRINT_NORMAL
716 CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length);
717 #endif
718
719 /* Print the operand as directed by the attributes. */
720 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
721 ; /* nothing to do */
722 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
723 (*info->fprintf_func) (info->stream, "0x%lx", value);
724 else
725 (*info->fprintf_func) (info->stream, "%ld", value);
726 }
727
728 /* Default address handler. */
729
730 static void
731 print_address (od, dis_info, value, attrs, pc, length)
732 CGEN_OPCODE_DESC od;
733 PTR dis_info;
734 bfd_vma value;
735 unsigned int attrs;
736 bfd_vma pc;
737 int length;
738 {
739 disassemble_info *info = (disassemble_info *) dis_info;
740
741 #ifdef CGEN_PRINT_ADDRESS
742 CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length);
743 #endif
744
745 /* Print the operand as directed by the attributes. */
746 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
747 ; /* nothing to do */
748 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
749 (*info->print_address_func) (value, info);
750 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
751 (*info->print_address_func) (value, info);
752 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
753 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
754 else
755 (*info->fprintf_func) (info->stream, "%ld", (long) value);
756 }
757
758 /* Keyword print handler. */
759
760 static void
761 print_keyword (od, dis_info, keyword_table, value, attrs)
762 CGEN_OPCODE_DESC od;
763 PTR dis_info;
764 CGEN_KEYWORD *keyword_table;
765 long value;
766 unsigned int attrs;
767 {
768 disassemble_info *info = (disassemble_info *) dis_info;
769 const CGEN_KEYWORD_ENTRY *ke;
770
771 ke = cgen_keyword_lookup_value (keyword_table, value);
772 if (ke != NULL)
773 (*info->fprintf_func) (info->stream, "%s", ke->name);
774 else
775 (*info->fprintf_func) (info->stream, "???");
776 }
777 \f
778 /* Default insn extractor.
779
780 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order.
781 The extracted fields are stored in FIELDS.
782 EX_INFO is used to handle reading variable length insns.
783 Return the length of the insn in bits, or 0 if no match,
784 or -1 if an error occurs fetching data (memory_error_func will have
785 been called). */
786
787 static int
788 extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
789 CGEN_OPCODE_DESC od;
790 const CGEN_INSN *insn;
791 CGEN_EXTRACT_INFO *ex_info;
792 CGEN_INSN_INT insn_value;
793 CGEN_FIELDS *fields;
794 bfd_vma pc;
795 {
796 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
797 const unsigned char *syn;
798
799 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
800
801 CGEN_INIT_EXTRACT (od);
802
803 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
804 {
805 int length;
806
807 if (CGEN_SYNTAX_CHAR_P (*syn))
808 continue;
809
810 length = fr30_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn),
811 ex_info, insn_value, fields, pc);
812 if (length <= 0)
813 return length;
814 }
815
816 /* We recognized and successfully extracted this insn. */
817 return CGEN_INSN_BITSIZE (insn);
818 }
819
820 /* Default insn printer.
821
822 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
823 about disassemble_info. */
824
825 static void
826 print_insn_normal (od, dis_info, insn, fields, pc, length)
827 CGEN_OPCODE_DESC od;
828 PTR dis_info;
829 const CGEN_INSN *insn;
830 CGEN_FIELDS *fields;
831 bfd_vma pc;
832 int length;
833 {
834 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
835 disassemble_info *info = (disassemble_info *) dis_info;
836 const unsigned char *syn;
837
838 CGEN_INIT_PRINT (od);
839
840 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
841 {
842 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
843 {
844 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
845 continue;
846 }
847 if (CGEN_SYNTAX_CHAR_P (*syn))
848 {
849 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
850 continue;
851 }
852
853 /* We have an operand. */
854 fr30_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
855 fields, CGEN_INSN_ATTRS (insn), pc, length);
856 }
857 }
858 \f
859 /* Utility to print an insn.
860 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
861 The result is the size of the insn in bytes or zero for an unknown insn
862 or -1 if an error occurs fetching data (memory_error_func will have
863 been called). */
864
865 static int
866 print_insn (od, pc, info, buf, buflen)
867 CGEN_OPCODE_DESC od;
868 bfd_vma pc;
869 disassemble_info *info;
870 char *buf;
871 int buflen;
872 {
873 unsigned long insn_value;
874 const CGEN_INSN_LIST *insn_list;
875 CGEN_EXTRACT_INFO ex_info;
876
877 ex_info.dis_info = info;
878 ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
879 ex_info.insn_bytes = buf;
880
881 switch (buflen)
882 {
883 case 1:
884 insn_value = buf[0];
885 break;
886 case 2:
887 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
888 break;
889 case 4:
890 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
891 break;
892 default:
893 abort ();
894 }
895
896 /* The instructions are stored in hash lists.
897 Pick the first one and keep trying until we find the right one. */
898
899 insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
900 while (insn_list != NULL)
901 {
902 const CGEN_INSN *insn = insn_list->insn;
903 CGEN_FIELDS fields;
904 int length;
905
906 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
907 /* Supported by this cpu? */
908 if (! fr30_cgen_insn_supported (od, insn))
909 continue;
910 #endif
911
912 /* Basic bit mask must be correct. */
913 /* ??? May wish to allow target to defer this check until the extract
914 handler. */
915 if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
916 {
917 /* Printing is handled in two passes. The first pass parses the
918 machine insn and extracts the fields. The second pass prints
919 them. */
920
921 length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value,
922 &fields, pc);
923 /* length < 0 -> error */
924 if (length < 0)
925 return length;
926 if (length > 0)
927 {
928 (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
929 /* length is in bits, result is in bytes */
930 return length / 8;
931 }
932 }
933
934 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
935 }
936
937 return 0;
938 }
939
940 /* Default value for CGEN_PRINT_INSN.
941 The result is the size of the insn in bytes or zero for an unknown insn
942 or -1 if an error occured fetching bytes. */
943
944 #ifndef CGEN_PRINT_INSN
945 #define CGEN_PRINT_INSN default_print_insn
946 #endif
947
948 static int
949 default_print_insn (od, pc, info)
950 CGEN_OPCODE_DESC od;
951 bfd_vma pc;
952 disassemble_info *info;
953 {
954 char buf[CGEN_MAX_INSN_SIZE];
955 int status;
956
957 /* Read the base part of the insn. */
958
959 status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info);
960 if (status != 0)
961 {
962 (*info->memory_error_func) (status, pc, info);
963 return -1;
964 }
965
966 return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE);
967 }
968
969 /* Main entry point.
970 Print one instruction from PC on INFO->STREAM.
971 Return the size of the instruction (in bytes). */
972
973 int
974 print_insn_fr30 (pc, info)
975 bfd_vma pc;
976 disassemble_info *info;
977 {
978 int length;
979 static CGEN_OPCODE_DESC od = 0;
980 int mach = info->mach;
981 int big_p = info->endian == BFD_ENDIAN_BIG;
982
983 /* If we haven't initialized yet, initialize the opcode table. */
984 if (! od)
985 {
986 od = fr30_cgen_opcode_open (mach,
987 big_p ?
988 CGEN_ENDIAN_BIG
989 : CGEN_ENDIAN_LITTLE);
990 fr30_cgen_init_dis (od);
991 }
992 /* If we've switched cpu's, re-initialize. */
993 /* ??? Perhaps we should use BFD_ENDIAN. */
994 else if (mach != CGEN_OPCODE_MACH (od)
995 || (CGEN_OPCODE_ENDIAN (od)
996 != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE)))
997 {
998 cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
999 }
1000
1001 /* We try to have as much common code as possible.
1002 But at this point some targets need to take over. */
1003 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
1004 but if not possible try to move this hook elsewhere rather than
1005 have two hooks. */
1006 length = CGEN_PRINT_INSN (od, pc, info);
1007 if (length > 0)
1008 return length;
1009 if (length < 0)
1010 return -1;
1011
1012 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1013 return CGEN_DEFAULT_INSN_SIZE;
1014 }
This page took 0.106502 seconds and 5 git commands to generate.