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