1 /* Instruction printing code for Score
2 Copyright 2006 Free Software Foundation, Inc.
4 Mei Ligang (ligang@sunnorth.com.cn)
5 Pei-Lin Tsai (pltsai@sunplus.com)
7 This file is part of libopcodes.
9 This program is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2 of the License, or (at your option)
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
27 #include "score-opc.h"
31 /* FIXME: This shouldn't be done here. */
33 #include "elf/internal.h"
34 #include "elf/score.h"
37 #define streq(a,b) (strcmp ((a), (b)) == 0)
41 #define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
45 #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
51 const char *description
;
52 const char *reg_names
[32];
55 static score_regname regnames
[] =
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"}},
63 static unsigned int regname_selected
= 0;
65 #define NUM_SCORE_REGNAMES NUM_ELEM (regnames)
66 #define score_regnames regnames[regname_selected].reg_names
68 /* Print one instruction from PC on INFO->STREAM.
69 Return the size of the instruction. */
71 print_insn_score32 (bfd_vma pc
, struct disassemble_info
*info
, long given
)
73 struct score_opcode
*insn
;
74 void *stream
= info
->stream
;
75 fprintf_ftype func
= info
->fprintf_func
;
77 for (insn
= score_opcodes
; insn
->assembler
; insn
++)
79 if ((insn
->mask
& 0xffff0000) && (given
& insn
->mask
) == insn
->value
)
83 for (c
= insn
->assembler
; *c
; c
++)
93 if (info
->flags
& INSN_HAS_RELOC
)
95 target
= (pc
& 0xfe000000) | (given
& 0x01fffffe);
96 (*info
->print_address_func
) (target
, info
);
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
));
106 (*info
->print_address_func
) (target
, info
);
120 int bitstart
= *c
++ - '0';
123 while (*c
>= '0' && *c
<= '9')
124 bitstart
= (bitstart
* 10) + *c
++ - '0';
130 while (*c
>= '0' && *c
<= '9')
131 bitend
= (bitend
* 10) + *c
++ - '0';
142 reg
= given
>> bitstart
;
143 reg
&= (2 << (bitend
- bitstart
)) - 1;
145 func (stream
, "%s", score_regnames
[reg
]);
152 reg
= given
>> bitstart
;
153 reg
&= (2 << (bitend
- bitstart
)) - 1;
155 func (stream
, "%ld", reg
);
162 reg
= given
>> bitstart
;
163 reg
&= (2 << (bitend
- bitstart
)) - 1;
164 reg
= ((reg
^ (1 << (bitend
- bitstart
))) -
165 (1 << (bitend
- bitstart
)));
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 */
175 func (stream
, "%ld", reg
);
182 reg
= given
>> bitstart
;
183 reg
&= (2 << (bitend
- bitstart
)) - 1;
185 func (stream
, "%lx", reg
);
194 if ((given
& (1 << bitstart
)) == 0)
195 func (stream
, "%c", *c
);
199 if ((given
& (1 << bitstart
)) != 0)
200 func (stream
, "%c", *c
);
213 func (stream
, "%c", *c
);
219 #if (SCORE_SIMULATOR_ACTIVE)
220 func (stream
, _("<illegal instruction>"));
228 print_insn_parallel_sym (struct disassemble_info
*info
)
230 void *stream
= info
->stream
;
231 fprintf_ftype func
= info
->fprintf_func
;
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");
239 /* Print one instruction from PC on INFO->STREAM.
240 Return the size of the instruction. */
242 print_insn_score16 (bfd_vma pc
, struct disassemble_info
*info
, long given
)
244 struct score_opcode
*insn
;
245 void *stream
= info
->stream
;
246 fprintf_ftype func
= info
->fprintf_func
;
249 for (insn
= score_opcodes
; insn
->assembler
; insn
++)
251 if (!(insn
->mask
& 0xffff0000) && (given
& insn
->mask
) == insn
->value
)
253 char *c
= insn
->assembler
;
255 info
->bytes_per_chunk
= 2;
256 info
->bytes_per_line
= 4;
270 if (info
->flags
& INSN_HAS_RELOC
)
273 target
= (pc
& 0xfffff000) | (given
& 0x00000ffe);
274 (*info
->print_address_func
) (target
, info
);
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
));
284 (*info
->print_address_func
) (target
, info
);
299 int bitstart
= *c
++ - '0';
302 while (*c
>= '0' && *c
<= '9')
303 bitstart
= (bitstart
* 10) + *c
++ - '0';
312 while (*c
>= '0' && *c
<= '9')
313 bitend
= (bitend
* 10) + *c
++ - '0';
316 reg
= given
>> bitstart
;
317 reg
&= (2 << (bitend
- bitstart
)) - 1;
321 func (stream
, "%s", score_regnames
[reg
+ 16]);
324 func (stream
, "%s", score_regnames
[reg
]);
327 if (*(c
+ 1) == '\0')
328 func (stream
, "%ld", reg
);
333 func (stream
, "%ld", reg
<< 1);
335 func (stream
, "%ld", reg
<< 2);
340 if (*(c
+ 1) == '\0')
341 func (stream
, "%lx", reg
);
346 func (stream
, "%lx", reg
<< 1);
348 func (stream
, "%lx", reg
<< 2);
352 reg
= ((reg
^ (1 << bitend
)) - (1 << bitend
));
353 func (stream
, "%ld", reg
);
363 if ((given
& (1 << bitstart
)) != 0)
364 func (stream
, "%c", *c
);
376 func (stream
, "%c", *c
);
382 #if (SCORE_SIMULATOR_ACTIVE)
383 func (stream
, _("<illegal instruction>"));
390 /* NOTE: There are no checks in these routines that
391 the relevant number of data bytes exist. */
393 print_insn (bfd_vma pc
, struct disassemble_info
*info
, bfd_boolean little
)
399 bfd_boolean insn_pce_p
= FALSE
;
400 bfd_boolean insn_16_p
= FALSE
;
402 info
->display_endian
= little
? BFD_ENDIAN_LITTLE
: BFD_ENDIAN_BIG
;
406 info
->bytes_per_chunk
= 2;
407 status
= info
->read_memory_func (pc
, (bfd_byte
*) b
, 2, info
);
413 info
->bytes_per_chunk
= 4;
414 status
= info
->read_memory_func (pc
, (bfd_byte
*) & b
[0], 4, info
);
417 info
->bytes_per_chunk
= 2;
418 status
= info
->read_memory_func (pc
, (bfd_byte
*) b
, 2, info
);
426 info
->memory_error_func (status
, pc
, info
);
432 given
= (b
[0]) | (b
[1] << 8) | (b
[2] << 16) | (b
[3] << 24);
436 given
= (b
[0] << 24) | (b
[1] << 16) | (b
[2] << 8) | (b
[3]);
439 if ((given
& 0x80008000) == 0x80008000)
444 else if ((given
& 0x8000) == 0x8000)
453 /* 16 bit instruction. */
458 given
= b
[0] | (b
[1] << 8);
462 given
= (b
[0] << 8) | b
[1];
465 status
= print_insn_score16 (pc
, info
, given
);
467 /* pce instruction. */
472 other
= given
& 0xFFFF;
473 given
= (given
& 0xFFFF0000) >> 16;
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;
481 /* 32 bit instruction. */
484 /* Get rid of parity. */
485 ridparity
= (given
& 0x7FFF);
486 ridparity
|= (given
& 0x7FFF0000) >> 1;
488 status
= print_insn_score32 (pc
, info
, given
);
495 print_insn_big_score (bfd_vma pc
, struct disassemble_info
*info
)
497 return print_insn (pc
, info
, FALSE
);
501 print_insn_little_score (bfd_vma pc
, struct disassemble_info
*info
)
503 return print_insn (pc
, info
, TRUE
);