* symtab.c: Remove trailing whitespace throughout the file.
[deliverable/binutils-gdb.git] / opcodes / score-dis.c
CommitLineData
1c0d3aa6 1/* Instruction printing code for Score
9b201bb5 2 Copyright 2006, 2007 Free Software Foundation, Inc.
1c0d3aa6
NC
3 Contributed by:
4 Mei Ligang (ligang@sunnorth.com.cn)
5 Pei-Lin Tsai (pltsai@sunplus.com)
6
9b201bb5 7 This file is part of the GNU opcodes library.
1c0d3aa6 8
9b201bb5
NC
9 This library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
1c0d3aa6
NC
12 any later version.
13
9b201bb5
NC
14 It is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
1c0d3aa6
NC
18
19 You should have received a copy of the GNU General Public License
9b201bb5
NC
20 along with this file; see the file COPYING. If not, write to the
21 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
1c0d3aa6
NC
23
24#include "sysdep.h"
25#include "dis-asm.h"
26#define DEFINE_TABLE
27#include "score-opc.h"
28#include "opintl.h"
29#include "bfd.h"
30
31/* FIXME: This shouldn't be done here. */
32#include "elf-bfd.h"
33#include "elf/internal.h"
34#include "elf/score.h"
35
36#ifndef streq
37#define streq(a,b) (strcmp ((a), (b)) == 0)
38#endif
39
40#ifndef strneq
41#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
42#endif
43
44#ifndef NUM_ELEM
45#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
46#endif
47
48typedef struct
49{
50 const char *name;
51 const char *description;
52 const char *reg_names[32];
53} score_regname;
54
55static score_regname regnames[] =
56{
57 {"gcc", "Select register names used by GCC",
58 {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
59 "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20",
60 "r21", "r22", "r23", "r24", "r25", "r26", "r27", "gp", "r29", "r30", "r31"}},
61};
62
63static unsigned int regname_selected = 0;
64
65#define NUM_SCORE_REGNAMES NUM_ELEM (regnames)
66#define score_regnames regnames[regname_selected].reg_names
67
68/* Print one instruction from PC on INFO->STREAM.
69 Return the size of the instruction. */
70static int
71print_insn_score32 (bfd_vma pc, struct disassemble_info *info, long given)
72{
73 struct score_opcode *insn;
74 void *stream = info->stream;
75 fprintf_ftype func = info->fprintf_func;
76
77 for (insn = score_opcodes; insn->assembler; insn++)
78 {
79 if ((insn->mask & 0xffff0000) && (given & insn->mask) == insn->value)
80 {
81 char *c;
82
83 for (c = insn->assembler; *c; c++)
84 {
85 if (*c == '%')
86 {
87 switch (*++c)
88 {
89 case 'j':
90 {
91 int target;
92
93 if (info->flags & INSN_HAS_RELOC)
94 pc = 0;
95 target = (pc & 0xfe000000) | (given & 0x01fffffe);
96 (*info->print_address_func) (target, info);
97 }
98 break;
99 case 'b':
100 {
101 /* Sign-extend a 20-bit number. */
102#define SEXT20(x) ((((x) & 0xfffff) ^ (~ 0x7ffff)) + 0x80000)
103 int disp = ((given & 0x01ff8000) >> 5) | (given & 0x3fe);
104 int target = (pc + SEXT20 (disp));
105
106 (*info->print_address_func) (target, info);
107 }
108 break;
109 case '0':
110 case '1':
111 case '2':
112 case '3':
113 case '4':
114 case '5':
115 case '6':
116 case '7':
117 case '8':
118 case '9':
119 {
120 int bitstart = *c++ - '0';
121 int bitend = 0;
122
123 while (*c >= '0' && *c <= '9')
124 bitstart = (bitstart * 10) + *c++ - '0';
125
126 switch (*c)
127 {
128 case '-':
129 c++;
130 while (*c >= '0' && *c <= '9')
131 bitend = (bitend * 10) + *c++ - '0';
132
133 if (!bitend)
134 abort ();
135
136 switch (*c)
137 {
138 case 'r':
139 {
140 long reg;
141
142 reg = given >> bitstart;
143 reg &= (2 << (bitend - bitstart)) - 1;
144
145 func (stream, "%s", score_regnames[reg]);
146 }
147 break;
148 case 'd':
149 {
150 long reg;
151
152 reg = given >> bitstart;
153 reg &= (2 << (bitend - bitstart)) - 1;
154
155 func (stream, "%ld", reg);
156 }
157 break;
158 case 'i':
159 {
160 long reg;
161
162 reg = given >> bitstart;
163 reg &= (2 << (bitend - bitstart)) - 1;
164 reg = ((reg ^ (1 << (bitend - bitstart))) -
165 (1 << (bitend - bitstart)));
166
167 if (((given & insn->mask) == 0x0c00000a) /* ldc1 */
168 || ((given & insn->mask) == 0x0c000012) /* ldc2 */
169 || ((given & insn->mask) == 0x0c00001c) /* ldc3 */
170 || ((given & insn->mask) == 0x0c00000b) /* stc1 */
171 || ((given & insn->mask) == 0x0c000013) /* stc2 */
172 || ((given & insn->mask) == 0x0c00001b)) /* stc3 */
173 reg <<= 2;
174
175 func (stream, "%ld", reg);
176 }
177 break;
178 case 'x':
179 {
180 long reg;
181
182 reg = given >> bitstart;
183 reg &= (2 << (bitend - bitstart)) - 1;
184
185 func (stream, "%lx", reg);
186 }
187 break;
188 default:
189 abort ();
190 }
191 break;
192 case '`':
193 c++;
194 if ((given & (1 << bitstart)) == 0)
195 func (stream, "%c", *c);
196 break;
197 case '\'':
198 c++;
199 if ((given & (1 << bitstart)) != 0)
200 func (stream, "%c", *c);
201 break;
202 default:
203 abort ();
204 }
205 break;
206
207 default:
208 abort ();
209 }
210 }
211 }
212 else
213 func (stream, "%c", *c);
214 }
215 return 4;
216 }
217 }
218
219#if (SCORE_SIMULATOR_ACTIVE)
220 func (stream, _("<illegal instruction>"));
221 return 4;
222#endif
223
224 abort ();
225}
226
227static void
228print_insn_parallel_sym (struct disassemble_info *info)
229{
230 void *stream = info->stream;
231 fprintf_ftype func = info->fprintf_func;
232
233 /* 10: 0000 nop!
234 4 space + 1 colon + 1 space + 1 tab + 8 opcode + 2 space + 1 tab.
235 FIXME: the space number is not accurate. */
236 func (stream, "%s", " ||\n \t \t");
237}
238
239/* Print one instruction from PC on INFO->STREAM.
240 Return the size of the instruction. */
241static int
242print_insn_score16 (bfd_vma pc, struct disassemble_info *info, long given)
243{
244 struct score_opcode *insn;
245 void *stream = info->stream;
246 fprintf_ftype func = info->fprintf_func;
247
248 given &= 0xffff;
249 for (insn = score_opcodes; insn->assembler; insn++)
250 {
251 if (!(insn->mask & 0xffff0000) && (given & insn->mask) == insn->value)
252 {
253 char *c = insn->assembler;
254
255 info->bytes_per_chunk = 2;
256 info->bytes_per_line = 4;
257 given &= 0xffff;
258
259 for (; *c; c++)
260 {
261 if (*c == '%')
262 {
263 switch (*++c)
264 {
265
266 case 'j':
267 {
268 int target;
269
270 if (info->flags & INSN_HAS_RELOC)
271 pc = 0;
272
273 target = (pc & 0xfffff000) | (given & 0x00000ffe);
274 (*info->print_address_func) (target, info);
275 }
276 break;
277 case 'b':
278 {
279 /* Sign-extend a 9-bit number. */
280#define SEXT9(x) ((((x) & 0x1ff) ^ (~ 0xff)) + 0x100)
281 int disp = (given & 0xff) << 1;
282 int target = (pc + SEXT9 (disp));
283
284 (*info->print_address_func) (target, info);
285 }
286 break;
287
288 case '0':
289 case '1':
290 case '2':
291 case '3':
292 case '4':
293 case '5':
294 case '6':
295 case '7':
296 case '8':
297 case '9':
298 {
299 int bitstart = *c++ - '0';
300 int bitend = 0;
301
302 while (*c >= '0' && *c <= '9')
303 bitstart = (bitstart * 10) + *c++ - '0';
304
305 switch (*c)
306 {
307 case '-':
308 {
309 long reg;
310
311 c++;
312 while (*c >= '0' && *c <= '9')
313 bitend = (bitend * 10) + *c++ - '0';
314 if (!bitend)
315 abort ();
316 reg = given >> bitstart;
317 reg &= (2 << (bitend - bitstart)) - 1;
318 switch (*c)
319 {
320 case 'R':
321 func (stream, "%s", score_regnames[reg + 16]);
322 break;
323 case 'r':
324 func (stream, "%s", score_regnames[reg]);
325 break;
326 case 'd':
327 if (*(c + 1) == '\0')
328 func (stream, "%ld", reg);
329 else
330 {
331 c++;
332 if (*c == '1')
333 func (stream, "%ld", reg << 1);
334 else if (*c == '2')
335 func (stream, "%ld", reg << 2);
336 }
337 break;
338
339 case 'x':
340 if (*(c + 1) == '\0')
341 func (stream, "%lx", reg);
342 else
343 {
344 c++;
345 if (*c == '1')
346 func (stream, "%lx", reg << 1);
347 else if (*c == '2')
348 func (stream, "%lx", reg << 2);
349 }
350 break;
351 case 'i':
352 reg = ((reg ^ (1 << bitend)) - (1 << bitend));
353 func (stream, "%ld", reg);
354 break;
355 default:
356 abort ();
357 }
358 }
359 break;
360
361 case '\'':
362 c++;
363 if ((given & (1 << bitstart)) != 0)
364 func (stream, "%c", *c);
365 break;
366 default:
367 abort ();
368 }
369 }
370 break;
371 default:
372 abort ();
373 }
374 }
375 else
376 func (stream, "%c", *c);
377 }
378
379 return 2;
380 }
381 }
382#if (SCORE_SIMULATOR_ACTIVE)
383 func (stream, _("<illegal instruction>"));
384 return 2;
385#endif
386 /* No match. */
387 abort ();
388}
389
390/* NOTE: There are no checks in these routines that
391 the relevant number of data bytes exist. */
392static int
393print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little)
394{
395 unsigned char b[4];
396 long given;
397 long ridparity;
398 int status;
399 bfd_boolean insn_pce_p = FALSE;
400 bfd_boolean insn_16_p = FALSE;
401
402 info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
403
404 if (pc & 0x2)
405 {
406 info->bytes_per_chunk = 2;
407 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
408 b[3] = b[2] = 0;
409 insn_16_p = TRUE;
410 }
411 else
412 {
413 info->bytes_per_chunk = 4;
414 status = info->read_memory_func (pc, (bfd_byte *) & b[0], 4, info);
415 if (status != 0)
416 {
417 info->bytes_per_chunk = 2;
418 status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
419 b[3] = b[2] = 0;
420 insn_16_p = TRUE;
421 }
422 }
423
424 if (status != 0)
425 {
426 info->memory_error_func (status, pc, info);
427 return -1;
428 }
429
430 if (little)
431 {
432 given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
433 }
434 else
435 {
436 given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
437 }
438
439 if ((given & 0x80008000) == 0x80008000)
440 {
441 insn_pce_p = FALSE;
442 insn_16_p = FALSE;
443 }
444 else if ((given & 0x8000) == 0x8000)
445 {
446 insn_pce_p = TRUE;
447 }
448 else
449 {
450 insn_16_p = TRUE;
451 }
452
453 /* 16 bit instruction. */
454 if (insn_16_p)
455 {
456 if (little)
457 {
458 given = b[0] | (b[1] << 8);
459 }
460 else
461 {
462 given = (b[0] << 8) | b[1];
463 }
464
465 status = print_insn_score16 (pc, info, given);
466 }
467 /* pce instruction. */
468 else if (insn_pce_p)
469 {
470 long other;
471
1c0d3aa6 472 other = given & 0xFFFF;
b138abaa 473 given = (given & 0xFFFF0000) >> 16;
1c0d3aa6
NC
474
475 status = print_insn_score16 (pc, info, given);
476 print_insn_parallel_sym (info);
477 status += print_insn_score16 (pc, info, other);
478 /* disassemble_bytes() will output 4 byte per chunk for pce instructio. */
479 info->bytes_per_chunk = 4;
480 }
481 /* 32 bit instruction. */
482 else
483 {
484 /* Get rid of parity. */
485 ridparity = (given & 0x7FFF);
486 ridparity |= (given & 0x7FFF0000) >> 1;
487 given = ridparity;
488 status = print_insn_score32 (pc, info, given);
489 }
490
491 return status;
492}
493
494int
495print_insn_big_score (bfd_vma pc, struct disassemble_info *info)
496{
497 return print_insn (pc, info, FALSE);
498}
499
500int
501print_insn_little_score (bfd_vma pc, struct disassemble_info *info)
502{
503 return print_insn (pc, info, TRUE);
504}
This page took 0.130184 seconds and 4 git commands to generate.