Add support for the GBZ80, Z180, and eZ80 variants of the Z80 architecure. Add an...
[deliverable/binutils-gdb.git] / opcodes / cr16-dis.c
CommitLineData
3d3d428f 1/* Disassembler code for CR16.
b3adc24a 2 Copyright (C) 2007-2020 Free Software Foundation, Inc.
3d3d428f
NC
3 Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com).
4
5 This file is part of GAS, GDB and the GNU binutils.
6
9b201bb5
NC
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3, or (at your option)
3d3d428f
NC
10 any later version.
11
12 This program is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20
3d3d428f 21#include "sysdep.h"
88c1242d 22#include "disassemble.h"
3d3d428f
NC
23#include "opcode/cr16.h"
24#include "libiberty.h"
25
26/* String to print when opcode was not matched. */
27#define ILLEGAL "illegal"
28 /* Escape to 16-bit immediate. */
29#define ESCAPE_16_BIT 0xB
30
31/* Extract 'n_bits' from 'a' starting from offset 'offs'. */
32#define EXTRACT(a, offs, n_bits) \
0ef562a4 33 (((a) >> (offs)) & ((1ul << ((n_bits) - 1) << 1) - 1))
3d3d428f 34
0ef562a4
AM
35/* Set Bit Mask - a mask to set all bits in a 32-bit word starting
36 from offset 'offs'. */
37#define SBM(offs) ((1ul << 31 << 1) - (1ul << (offs)))
3d3d428f 38
3d3d428f
NC
39typedef struct
40{
41 dwordU val;
42 int nbits;
43} parameter;
44
45/* Structure to map valid 'cinv' instruction options. */
46
47typedef struct
48 {
49 /* Cinv printed string. */
50 char *istr;
51 /* Value corresponding to the string. */
52 char *ostr;
53 }
54cinv_entry;
55
56/* CR16 'cinv' options mapping. */
e5d70d6b 57static const cinv_entry cr16_cinvs[] =
3d3d428f
NC
58{
59 {"cinv[i]", "cinv [i]"},
60 {"cinv[i,u]", "cinv [i,u]"},
61 {"cinv[d]", "cinv [d]"},
62 {"cinv[d,u]", "cinv [d,u]"},
63 {"cinv[d,i]", "cinv [d,i]"},
64 {"cinv[d,i,u]", "cinv [d,i,u]"}
65};
66
67/* Number of valid 'cinv' instruction options. */
68static int NUMCINVS = ARRAY_SIZE (cr16_cinvs);
69
70/* Enum to distinguish different registers argument types. */
71typedef enum REG_ARG_TYPE
72 {
73 /* General purpose register (r<N>). */
74 REG_ARG = 0,
75 /*Processor register */
76 P_ARG,
77 }
78REG_ARG_TYPE;
79
80/* Current opcode table entry we're disassembling. */
e5d70d6b 81static const inst *instruction;
3d3d428f 82/* Current instruction we're disassembling. */
e5d70d6b 83static ins cr16_currInsn;
3d3d428f 84/* The current instruction is read into 3 consecutive words. */
e5d70d6b 85static wordU cr16_words[3];
3d3d428f 86/* Contains all words in appropriate order. */
e5d70d6b 87static ULONGLONG cr16_allWords;
3d3d428f 88/* Holds the current processed argument number. */
e5d70d6b 89static int processing_argument_number;
3d3d428f 90/* Nonzero means a IMM4 instruction. */
e5d70d6b 91static int imm4flag;
3d3d428f
NC
92/* Nonzero means the instruction's original size is
93 incremented (escape sequence is used). */
e5d70d6b 94static int size_changed;
3d3d428f
NC
95
96
97/* Print the constant expression length. */
98
99static char *
100print_exp_len (int size)
101{
102 switch (size)
103 {
104 case 4:
105 case 5:
106 case 6:
107 case 8:
108 case 14:
109 case 16:
110 return ":s";
111 case 20:
112 case 24:
113 case 32:
114 return ":m";
115 case 48:
116 return ":l";
117 default:
118 return "";
119 }
120}
121
122
123/* Retrieve the number of operands for the current assembled instruction. */
124
125static int
126get_number_of_operands (void)
127{
128 int i;
129
130 for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
131 ;
132
133 return i;
134}
135
136/* Return the bit size for a given operand. */
137
138static int
139getbits (operand_type op)
140{
141 if (op < MAX_OPRD)
142 return cr16_optab[op].bit_size;
143
144 return 0;
145}
146
147/* Return the argument type of a given operand. */
148
149static argtype
150getargtype (operand_type op)
151{
152 if (op < MAX_OPRD)
153 return cr16_optab[op].arg_type;
154
155 return nullargs;
156}
157
158/* Given a 'CC' instruction constant operand, return its corresponding
159 string. This routine is used when disassembling the 'CC' instruction. */
160
161static char *
91d6fa6a 162getccstring (unsigned cc_insn)
3d3d428f 163{
91d6fa6a 164 return (char *) cr16_b_cond_tab[cc_insn];
3d3d428f
NC
165}
166
167
168/* Given a 'cinv' instruction constant operand, return its corresponding
169 string. This routine is used when disassembling the 'cinv' instruction. */
170
171static char *
ddb341a7 172getcinvstring (const char *str)
3d3d428f
NC
173{
174 const cinv_entry *cinv;
175
176 for (cinv = cr16_cinvs; cinv < (cr16_cinvs + NUMCINVS); cinv++)
177 if (strcmp (cinv->istr, str) == 0)
178 return cinv->ostr;
179
180 return ILLEGAL;
181}
182
183/* Given the trap index in dispatch table, return its name.
184 This routine is used when disassembling the 'excp' instruction. */
185
186static char *
91d6fa6a 187gettrapstring (unsigned int trap_index)
3d3d428f
NC
188{
189 const trap_entry *trap;
190
191 for (trap = cr16_traps; trap < cr16_traps + NUMTRAPS; trap++)
91d6fa6a 192 if (trap->entry == trap_index)
3d3d428f
NC
193 return trap->name;
194
195 return ILLEGAL;
196}
197
198/* Given a register enum value, retrieve its name. */
199
200static char *
201getregname (reg r)
202{
91d6fa6a 203 const reg_entry * regentry = cr16_regtab + r;
3d3d428f 204
91d6fa6a 205 if (regentry->type != CR16_R_REGTYPE)
3d3d428f
NC
206 return ILLEGAL;
207
91d6fa6a 208 return regentry->name;
3d3d428f
NC
209}
210
211/* Given a register pair enum value, retrieve its name. */
212
213static char *
214getregpname (reg r)
215{
91d6fa6a 216 const reg_entry * regentry = cr16_regptab + r;
3d3d428f 217
91d6fa6a 218 if (regentry->type != CR16_RP_REGTYPE)
3d3d428f
NC
219 return ILLEGAL;
220
91d6fa6a 221 return regentry->name;
3d3d428f
NC
222}
223
224/* Given a index register pair enum value, retrieve its name. */
225
226static char *
227getidxregpname (reg r)
228{
91d6fa6a 229 const reg_entry * regentry;
3d3d428f
NC
230
231 switch (r)
232 {
233 case 0: r = 0; break;
234 case 1: r = 2; break;
235 case 2: r = 4; break;
236 case 3: r = 6; break;
237 case 4: r = 8; break;
238 case 5: r = 10; break;
239 case 6: r = 3; break;
240 case 7: r = 5; break;
241 default:
242 break;
243 }
244
91d6fa6a 245 regentry = cr16_regptab + r;
3d3d428f 246
91d6fa6a 247 if (regentry->type != CR16_RP_REGTYPE)
3d3d428f
NC
248 return ILLEGAL;
249
91d6fa6a 250 return regentry->name;
3d3d428f
NC
251}
252
253/* Getting a processor register name. */
254
255static char *
91d6fa6a 256getprocregname (int reg_index)
3d3d428f
NC
257{
258 const reg_entry *r;
259
260 for (r = cr16_pregtab; r < cr16_pregtab + NUMPREGS; r++)
91d6fa6a 261 if (r->image == reg_index)
3d3d428f
NC
262 return r->name;
263
264 return "ILLEGAL REGISTER";
265}
266
267/* Getting a processor register name - 32 bit size. */
268
269static char *
91d6fa6a 270getprocpregname (int reg_index)
3d3d428f
NC
271{
272 const reg_entry *r;
273
274 for (r = cr16_pregptab; r < cr16_pregptab + NUMPREGPS; r++)
91d6fa6a 275 if (r->image == reg_index)
3d3d428f
NC
276 return r->name;
277
278 return "ILLEGAL REGISTER";
279}
280
bab4becb 281/* START and END are relating 'cr16_allWords' struct, which is 48 bits size.
3d3d428f
NC
282
283 START|--------|END
284 +---------+---------+---------+---------+
285 | | V | A | L |
286 +---------+---------+---------+---------+
287 0 16 32 48
288 words [0] [1] [2] */
289
290static parameter
291makelongparameter (ULONGLONG val, int start, int end)
292{
293 parameter p;
294
295 p.val = (dwordU) EXTRACT (val, 48 - end, end - start);
296 p.nbits = end - start;
297 return p;
298}
299
300/* Build a mask of the instruction's 'constant' opcode,
301 based on the instruction's printing flags. */
302
303static unsigned long
304build_mask (void)
305{
306 unsigned long mask = SBM (instruction->match_bits);
3ce6fddb
NC
307
308 /* Adjust mask for bcond with 32-bit size instruction. */
309 if ((IS_INSN_MNEMONIC("b") && instruction->size == 2))
310 mask = 0xff0f0000;
311
3d3d428f
NC
312 return mask;
313}
314
315/* Search for a matching opcode. Return 1 for success, 0 for failure. */
316
bab4becb 317int
73335eae 318cr16_match_opcode (void)
3d3d428f
NC
319{
320 unsigned long mask;
f1a133ff 321 /* The instruction 'constant' opcode doesn't exceed 32 bits. */
bab4becb
NC
322 unsigned long doubleWord = (cr16_words[1]
323 + (cr16_words[0] << 16)) & 0xffffffff;
3d3d428f
NC
324
325 /* Start searching from end of instruction table. */
326 instruction = &cr16_instruction[NUMOPCODES - 2];
327
328 /* Loop over instruction table until a full match is found. */
329 while (instruction >= cr16_instruction)
330 {
331 mask = build_mask ();
59b098c9 332
3d3d428f
NC
333 if ((doubleWord & mask) == BIN (instruction->match,
334 instruction->match_bits))
335 return 1;
336 else
337 instruction--;
338 }
339 return 0;
340}
341
342/* Set the proper parameter value for different type of arguments. */
343
344static void
345make_argument (argument * a, int start_bits)
346{
347 int inst_bit_size;
348 parameter p;
349
350 if ((instruction->size == 3) && a->size >= 16)
351 inst_bit_size = 48;
352 else
353 inst_bit_size = 32;
354
355 switch (a->type)
356 {
357 case arg_r:
43e65147 358 p = makelongparameter (cr16_allWords,
bab4becb
NC
359 inst_bit_size - (start_bits + a->size),
360 inst_bit_size - start_bits);
3d3d428f
NC
361 a->r = p.val;
362 break;
363
364 case arg_rp:
bab4becb
NC
365 p = makelongparameter (cr16_allWords,
366 inst_bit_size - (start_bits + a->size),
367 inst_bit_size - start_bits);
3d3d428f
NC
368 a->rp = p.val;
369 break;
370
371 case arg_pr:
bab4becb
NC
372 p = makelongparameter (cr16_allWords,
373 inst_bit_size - (start_bits + a->size),
374 inst_bit_size - start_bits);
3d3d428f
NC
375 a->pr = p.val;
376 break;
377
378 case arg_prp:
bab4becb
NC
379 p = makelongparameter (cr16_allWords,
380 inst_bit_size - (start_bits + a->size),
381 inst_bit_size - start_bits);
3d3d428f
NC
382 a->prp = p.val;
383 break;
384
385 case arg_ic:
43e65147 386 p = makelongparameter (cr16_allWords,
bab4becb
NC
387 inst_bit_size - (start_bits + a->size),
388 inst_bit_size - start_bits);
3d3d428f
NC
389 a->constant = p.val;
390 break;
391
392 case arg_cc:
bab4becb
NC
393 p = makelongparameter (cr16_allWords,
394 inst_bit_size - (start_bits + a->size),
395 inst_bit_size - start_bits);
3d3d428f
NC
396
397 a->cc = p.val;
398 break;
399
400 case arg_idxr:
401 if ((IS_INSN_MNEMONIC ("cbitb"))
402 || (IS_INSN_MNEMONIC ("sbitb"))
403 || (IS_INSN_MNEMONIC ("tbitb")))
bab4becb 404 p = makelongparameter (cr16_allWords, 8, 9);
3d3d428f 405 else
bab4becb 406 p = makelongparameter (cr16_allWords, 9, 10);
3d3d428f 407 a->i_r = p.val;
bab4becb
NC
408 p = makelongparameter (cr16_allWords,
409 inst_bit_size - a->size, inst_bit_size);
3d3d428f
NC
410 a->constant = p.val;
411 break;
412
413 case arg_idxrp:
bab4becb 414 p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 13);
3d3d428f 415 a->i_r = p.val;
bab4becb 416 p = makelongparameter (cr16_allWords, start_bits + 13, start_bits + 16);
3d3d428f
NC
417 a->rp = p.val;
418 if (inst_bit_size > 32)
419 {
bab4becb 420 p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12,
3d3d428f
NC
421 inst_bit_size);
422 a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
423 }
424 else if (instruction->size == 2)
425 {
bab4becb
NC
426 p = makelongparameter (cr16_allWords, inst_bit_size - 22,
427 inst_bit_size);
3d3d428f
NC
428 a->constant = (p.val & 0xf) | (((p.val >>20) & 0x3) << 4)
429 | ((p.val >>14 & 0x3) << 6) | (((p.val >>7) & 0x1f) <<7);
430 }
431 else if (instruction->size == 1 && a->size == 0)
432 a->constant = 0;
433
434 break;
435
436 case arg_rbase:
bab4becb 437 p = makelongparameter (cr16_allWords, inst_bit_size, inst_bit_size);
3d3d428f 438 a->constant = p.val;
bab4becb 439 p = makelongparameter (cr16_allWords, inst_bit_size - (start_bits + 4),
3d3d428f
NC
440 inst_bit_size - start_bits);
441 a->r = p.val;
442 break;
443
444 case arg_cr:
bab4becb 445 p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16);
3d3d428f 446 a->r = p.val;
bab4becb 447 p = makelongparameter (cr16_allWords, inst_bit_size - 16, inst_bit_size);
3d3d428f
NC
448 a->constant = p.val;
449 break;
450
451 case arg_crp:
452 if (instruction->size == 1)
bab4becb 453 p = makelongparameter (cr16_allWords, 12, 16);
3d3d428f 454 else
bab4becb 455 p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16);
3d3d428f
NC
456 a->rp = p.val;
457
458 if (inst_bit_size > 32)
459 {
bab4becb 460 p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12,
3d3d428f
NC
461 inst_bit_size);
462 a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
463 }
464 else if (instruction->size == 2)
465 {
43e65147 466 p = makelongparameter (cr16_allWords, inst_bit_size - 16,
bab4becb 467 inst_bit_size);
3d3d428f
NC
468 a->constant = p.val;
469 }
470 else if (instruction->size == 1 && a->size != 0)
471 {
bab4becb 472 p = makelongparameter (cr16_allWords, 4, 8);
3d3d428f
NC
473 if (IS_INSN_MNEMONIC ("loadw")
474 || IS_INSN_MNEMONIC ("loadd")
475 || IS_INSN_MNEMONIC ("storw")
476 || IS_INSN_MNEMONIC ("stord"))
477 a->constant = (p.val * 2);
478 else
479 a->constant = p.val;
480 }
481 else /* below case for 0x0(reg pair) */
482 a->constant = 0;
483
484 break;
485
486 case arg_c:
487
488 if ((IS_INSN_TYPE (BRANCH_INS))
489 || (IS_INSN_MNEMONIC ("bal"))
490 || (IS_INSN_TYPE (CSTBIT_INS))
491 || (IS_INSN_TYPE (LD_STOR_INS)))
492 {
493 switch (a->size)
494 {
495 case 8 :
bab4becb 496 p = makelongparameter (cr16_allWords, 0, start_bits);
3d3d428f
NC
497 a->constant = ((((p.val&0xf00)>>4)) | (p.val&0xf));
498 break;
499
500 case 24:
501 if (instruction->size == 3)
502 {
bab4becb 503 p = makelongparameter (cr16_allWords, 16, inst_bit_size);
3d3d428f
NC
504 a->constant = ((((p.val>>16)&0xf) << 20)
505 | (((p.val>>24)&0xf) << 16)
506 | (p.val & 0xffff));
507 }
508 else if (instruction->size == 2)
509 {
bab4becb 510 p = makelongparameter (cr16_allWords, 8, inst_bit_size);
3d3d428f
NC
511 a->constant = p.val;
512 }
513 break;
514
515 default:
bab4becb
NC
516 p = makelongparameter (cr16_allWords,
517 inst_bit_size - (start_bits + a->size),
518 inst_bit_size - start_bits);
3d3d428f
NC
519 a->constant = p.val;
520 break;
521 }
522 }
523 else
524 {
bab4becb
NC
525 p = makelongparameter (cr16_allWords,
526 inst_bit_size - (start_bits + a->size),
3d3d428f
NC
527 inst_bit_size - start_bits);
528 a->constant = p.val;
529 }
530 break;
531
532 default:
533 break;
534 }
535}
536
537/* Print a single argument. */
538
539static void
540print_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info)
541{
542 LONGLONG longdisp, mask;
543 int sign_flag = 0;
544 int relative = 0;
545 bfd_vma number;
546 PTR stream = info->stream;
547 fprintf_ftype func = info->fprintf_func;
548
549 switch (a->type)
550 {
551 case arg_r:
552 func (stream, "%s", getregname (a->r));
553 break;
554
555 case arg_rp:
556 func (stream, "%s", getregpname (a->rp));
557 break;
558
559 case arg_pr:
560 func (stream, "%s", getprocregname (a->pr));
561 break;
562
563 case arg_prp:
564 func (stream, "%s", getprocpregname (a->prp));
565 break;
566
567 case arg_cc:
568 func (stream, "%s", getccstring (a->cc));
569 func (stream, "%s", "\t");
570 break;
571
572 case arg_ic:
573 if (IS_INSN_MNEMONIC ("excp"))
574 {
575 func (stream, "%s", gettrapstring (a->constant));
576 break;
577 }
578 else if ((IS_INSN_TYPE (ARITH_INS) || IS_INSN_TYPE (ARITH_BYTE_INS))
579 && ((instruction->size == 1) && (a->constant == 9)))
580 func (stream, "$%d", -1);
581 else if (INST_HAS_REG_LIST)
582 func (stream, "$0x%lx", a->constant +1);
583 else if (IS_INSN_TYPE (SHIFT_INS))
584 {
585 longdisp = a->constant;
586 mask = ((LONGLONG)1 << a->size) - 1;
587 if (longdisp & ((LONGLONG)1 << (a->size -1)))
588 {
589 sign_flag = 1;
590 longdisp = ~(longdisp) + 1;
591 }
592 a->constant = (unsigned long int) (longdisp & mask);
593 func (stream, "$%d", ((int)(sign_flag ? -a->constant :
594 a->constant)));
595 }
596 else
597 func (stream, "$0x%lx", a->constant);
598 switch (a->size)
599 {
600 case 4 : case 5 : case 6 : case 8 :
601 func (stream, "%s", ":s"); break;
602 case 16 : case 20 : func (stream, "%s", ":m"); break;
603 case 24 : case 32 : func (stream, "%s", ":l"); break;
604 default: break;
605 }
606 break;
607
608 case arg_idxr:
609 if (a->i_r == 0) func (stream, "[r12]");
610 if (a->i_r == 1) func (stream, "[r13]");
611 func (stream, "0x%lx", a->constant);
612 func (stream, "%s", print_exp_len (instruction->size * 16));
613 break;
614
615 case arg_idxrp:
616 if (a->i_r == 0) func (stream, "[r12]");
617 if (a->i_r == 1) func (stream, "[r13]");
618 func (stream, "0x%lx", a->constant);
619 func (stream, "%s", print_exp_len (instruction->size * 16));
620 func (stream, "%s", getidxregpname (a->rp));
621 break;
622
623 case arg_rbase:
624 func (stream, "(%s)", getregname (a->r));
625 break;
626
627 case arg_cr:
628 func (stream, "0x%lx", a->constant);
629 func (stream, "%s", print_exp_len (instruction->size * 16));
630 func (stream, "(%s)", getregname (a->r));
631 break;
632
633 case arg_crp:
634 func (stream, "0x%lx", a->constant);
635 func (stream, "%s", print_exp_len (instruction->size * 16));
636 func (stream, "%s", getregpname (a->rp));
637 break;
638
639 case arg_c:
640 /*Removed the *2 part as because implicit zeros are no more required.
641 Have to fix this as this needs a bit of extension in terms of branch
642 instructions. */
643 if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal"))
644 {
645 relative = 1;
646 longdisp = a->constant;
647 /* REVISIT: To sync with WinIDEA and CR16 4.1tools, the below
648 line commented */
649 /* longdisp <<= 1; */
650 mask = ((LONGLONG)1 << a->size) - 1;
651 switch (a->size)
652 {
653 case 8 :
654 {
655 longdisp <<= 1;
656 if (longdisp & ((LONGLONG)1 << a->size))
657 {
658 sign_flag = 1;
659 longdisp = ~(longdisp) + 1;
660 }
661 break;
662 }
663 case 16 :
664 case 24 :
665 {
666 if (longdisp & 1)
667 {
668 sign_flag = 1;
669 longdisp = ~(longdisp) + 1;
670 }
671 break;
672 }
673 default:
674 func (stream, "Wrong offset used in branch/bal instruction");
675 break;
676 }
677 a->constant = (unsigned long int) (longdisp & mask);
678 }
679 /* For branch Neq instruction it is 2*offset + 2. */
680 else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
681 a->constant = 2 * a->constant + 2;
682
683 if ((!IS_INSN_TYPE (CSTBIT_INS)) && (!IS_INSN_TYPE (LD_STOR_INS)))
684 (sign_flag) ? func (stream, "%s", "*-"): func (stream, "%s","*+");
685
522fe561 686 /* PR 10173: Avoid printing the 0x prefix twice. */
e20cc039 687 if (info->symtab_size > 0)
522fe561 688 func (stream, "%s", "0x");
3d3d428f
NC
689 number = ((relative ? memaddr : 0) +
690 (sign_flag ? ((- a->constant) & 0xffffffe) : a->constant));
691
692 (*info->print_address_func) ((number & ((1 << 24) - 1)), info);
693
694 func (stream, "%s", print_exp_len (instruction->size * 16));
695 break;
696
697 default:
698 break;
699 }
700}
701
702/* Print all the arguments of CURRINSN instruction. */
703
704static void
91d6fa6a 705print_arguments (ins *currentInsn, bfd_vma memaddr, struct disassemble_info *info)
3d3d428f
NC
706{
707 int i;
708
709 /* For "pop/push/popret RA instruction only. */
710 if ((IS_INSN_MNEMONIC ("pop")
711 || (IS_INSN_MNEMONIC ("popret")
712 || (IS_INSN_MNEMONIC ("push"))))
91d6fa6a 713 && currentInsn->nargs == 1)
3d3d428f
NC
714 {
715 info->fprintf_func (info->stream, "RA");
716 return;
717 }
718
91d6fa6a 719 for (i = 0; i < currentInsn->nargs; i++)
3d3d428f
NC
720 {
721 processing_argument_number = i;
722
723 /* For "bal (ra), disp17" instruction only. */
724 if ((IS_INSN_MNEMONIC ("bal")) && (i == 0) && instruction->size == 2)
725 {
726 info->fprintf_func (info->stream, "(ra),");
727 continue;
728 }
729
730 if ((INST_HAS_REG_LIST) && (i == 2))
731 info->fprintf_func (info->stream, "RA");
732 else
91d6fa6a 733 print_arg (&currentInsn->arg[i], memaddr, info);
3d3d428f 734
91d6fa6a 735 if ((i != currentInsn->nargs - 1) && (!IS_INSN_MNEMONIC ("b")))
3d3d428f
NC
736 info->fprintf_func (info->stream, ",");
737 }
738}
739
740/* Build the instruction's arguments. */
741
bab4becb 742void
73335eae 743cr16_make_instruction (void)
3d3d428f
NC
744{
745 int i;
746 unsigned int shift;
747
bab4becb 748 for (i = 0; i < cr16_currInsn.nargs; i++)
3d3d428f
NC
749 {
750 argument a;
751
752 memset (&a, 0, sizeof (a));
753 a.type = getargtype (instruction->operands[i].op_type);
754 a.size = getbits (instruction->operands[i].op_type);
755 shift = instruction->operands[i].shift;
756
757 make_argument (&a, shift);
bab4becb 758 cr16_currInsn.arg[i] = a;
3d3d428f
NC
759 }
760
761 /* Calculate instruction size (in bytes). */
bab4becb 762 cr16_currInsn.size = instruction->size + (size_changed ? 1 : 0);
3d3d428f 763 /* Now in bits. */
bab4becb 764 cr16_currInsn.size *= 2;
3d3d428f
NC
765}
766
767/* Retrieve a single word from a given memory address. */
768
769static wordU
770get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info)
771{
772 bfd_byte buffer[4];
773 int status;
774 wordU insn = 0;
775
776 status = info->read_memory_func (memaddr, buffer, 2, info);
777
778 if (status == 0)
779 insn = (wordU) bfd_getl16 (buffer);
780
781 return insn;
782}
783
784/* Retrieve multiple words (3) from a given memory address. */
785
786static void
787get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info)
788{
789 int i;
790 bfd_vma mem;
791
792 for (i = 0, mem = memaddr; i < 3; i++, mem += 2)
bab4becb 793 cr16_words[i] = get_word_at_PC (mem, info);
3d3d428f 794
43e65147 795 cr16_allWords = ((ULONGLONG) cr16_words[0] << 32)
bab4becb 796 + ((unsigned long) cr16_words[1] << 16) + cr16_words[2];
3d3d428f
NC
797}
798
799/* Prints the instruction by calling print_arguments after proper matching. */
800
801int
802print_insn_cr16 (bfd_vma memaddr, struct disassemble_info *info)
803{
804 int is_decoded; /* Nonzero means instruction has a match. */
805
806 /* Initialize global variables. */
807 imm4flag = 0;
808 size_changed = 0;
809
810 /* Retrieve the encoding from current memory location. */
811 get_words_at_PC (memaddr, info);
812 /* Find a matching opcode in table. */
73335eae 813 is_decoded = cr16_match_opcode ();
3d3d428f 814 /* If found, print the instruction's mnemonic and arguments. */
616ec358 815 if (is_decoded > 0 && (cr16_words[0] != 0 || cr16_words[1] != 0))
3d3d428f
NC
816 {
817 if (strneq (instruction->mnemonic, "cinv", 4))
ddb341a7 818 info->fprintf_func (info->stream,"%s", getcinvstring (instruction->mnemonic));
3d3d428f
NC
819 else
820 info->fprintf_func (info->stream, "%s", instruction->mnemonic);
821
bab4becb 822 if (((cr16_currInsn.nargs = get_number_of_operands ()) != 0)
3d3d428f
NC
823 && ! (IS_INSN_MNEMONIC ("b")))
824 info->fprintf_func (info->stream, "\t");
73335eae 825 cr16_make_instruction ();
3d3d428f 826 /* For push/pop/pushrtn with RA instructions. */
bab4becb
NC
827 if ((INST_HAS_REG_LIST) && ((cr16_words[0] >> 7) & 0x1))
828 cr16_currInsn.nargs +=1;
829 print_arguments (&cr16_currInsn, memaddr, info);
830 return cr16_currInsn.size;
3d3d428f
NC
831 }
832
833 /* No match found. */
834 info->fprintf_func (info->stream,"%s ",ILLEGAL);
835 return 2;
836}
This page took 0.65304 seconds and 4 git commands to generate.