gdb: add target_ops::supports_displaced_step
[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. */
5f57d4ec 322 unsigned long doubleWord = cr16_words[1] + ((unsigned) cr16_words[0] << 16);
3d3d428f
NC
323
324 /* Start searching from end of instruction table. */
325 instruction = &cr16_instruction[NUMOPCODES - 2];
326
327 /* Loop over instruction table until a full match is found. */
328 while (instruction >= cr16_instruction)
329 {
330 mask = build_mask ();
59b098c9 331
3d3d428f
NC
332 if ((doubleWord & mask) == BIN (instruction->match,
333 instruction->match_bits))
334 return 1;
335 else
336 instruction--;
337 }
338 return 0;
339}
340
341/* Set the proper parameter value for different type of arguments. */
342
343static void
344make_argument (argument * a, int start_bits)
345{
346 int inst_bit_size;
347 parameter p;
348
349 if ((instruction->size == 3) && a->size >= 16)
350 inst_bit_size = 48;
351 else
352 inst_bit_size = 32;
353
354 switch (a->type)
355 {
356 case arg_r:
43e65147 357 p = makelongparameter (cr16_allWords,
bab4becb
NC
358 inst_bit_size - (start_bits + a->size),
359 inst_bit_size - start_bits);
3d3d428f
NC
360 a->r = p.val;
361 break;
362
363 case arg_rp:
bab4becb
NC
364 p = makelongparameter (cr16_allWords,
365 inst_bit_size - (start_bits + a->size),
366 inst_bit_size - start_bits);
3d3d428f
NC
367 a->rp = p.val;
368 break;
369
370 case arg_pr:
bab4becb
NC
371 p = makelongparameter (cr16_allWords,
372 inst_bit_size - (start_bits + a->size),
373 inst_bit_size - start_bits);
3d3d428f
NC
374 a->pr = p.val;
375 break;
376
377 case arg_prp:
bab4becb
NC
378 p = makelongparameter (cr16_allWords,
379 inst_bit_size - (start_bits + a->size),
380 inst_bit_size - start_bits);
3d3d428f
NC
381 a->prp = p.val;
382 break;
383
384 case arg_ic:
43e65147 385 p = makelongparameter (cr16_allWords,
bab4becb
NC
386 inst_bit_size - (start_bits + a->size),
387 inst_bit_size - start_bits);
3d3d428f
NC
388 a->constant = p.val;
389 break;
390
391 case arg_cc:
bab4becb
NC
392 p = makelongparameter (cr16_allWords,
393 inst_bit_size - (start_bits + a->size),
394 inst_bit_size - start_bits);
3d3d428f
NC
395
396 a->cc = p.val;
397 break;
398
399 case arg_idxr:
400 if ((IS_INSN_MNEMONIC ("cbitb"))
401 || (IS_INSN_MNEMONIC ("sbitb"))
402 || (IS_INSN_MNEMONIC ("tbitb")))
bab4becb 403 p = makelongparameter (cr16_allWords, 8, 9);
3d3d428f 404 else
bab4becb 405 p = makelongparameter (cr16_allWords, 9, 10);
3d3d428f 406 a->i_r = p.val;
bab4becb
NC
407 p = makelongparameter (cr16_allWords,
408 inst_bit_size - a->size, inst_bit_size);
3d3d428f
NC
409 a->constant = p.val;
410 break;
411
412 case arg_idxrp:
bab4becb 413 p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 13);
3d3d428f 414 a->i_r = p.val;
bab4becb 415 p = makelongparameter (cr16_allWords, start_bits + 13, start_bits + 16);
3d3d428f
NC
416 a->rp = p.val;
417 if (inst_bit_size > 32)
418 {
bab4becb 419 p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12,
3d3d428f
NC
420 inst_bit_size);
421 a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
422 }
423 else if (instruction->size == 2)
424 {
bab4becb
NC
425 p = makelongparameter (cr16_allWords, inst_bit_size - 22,
426 inst_bit_size);
3d3d428f
NC
427 a->constant = (p.val & 0xf) | (((p.val >>20) & 0x3) << 4)
428 | ((p.val >>14 & 0x3) << 6) | (((p.val >>7) & 0x1f) <<7);
429 }
430 else if (instruction->size == 1 && a->size == 0)
431 a->constant = 0;
432
433 break;
434
435 case arg_rbase:
bab4becb 436 p = makelongparameter (cr16_allWords, inst_bit_size, inst_bit_size);
3d3d428f 437 a->constant = p.val;
bab4becb 438 p = makelongparameter (cr16_allWords, inst_bit_size - (start_bits + 4),
3d3d428f
NC
439 inst_bit_size - start_bits);
440 a->r = p.val;
441 break;
442
443 case arg_cr:
bab4becb 444 p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16);
3d3d428f 445 a->r = p.val;
bab4becb 446 p = makelongparameter (cr16_allWords, inst_bit_size - 16, inst_bit_size);
3d3d428f
NC
447 a->constant = p.val;
448 break;
449
450 case arg_crp:
451 if (instruction->size == 1)
bab4becb 452 p = makelongparameter (cr16_allWords, 12, 16);
3d3d428f 453 else
bab4becb 454 p = makelongparameter (cr16_allWords, start_bits + 12, start_bits + 16);
3d3d428f
NC
455 a->rp = p.val;
456
457 if (inst_bit_size > 32)
458 {
bab4becb 459 p = makelongparameter (cr16_allWords, inst_bit_size - start_bits - 12,
3d3d428f
NC
460 inst_bit_size);
461 a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
462 }
463 else if (instruction->size == 2)
464 {
43e65147 465 p = makelongparameter (cr16_allWords, inst_bit_size - 16,
bab4becb 466 inst_bit_size);
3d3d428f
NC
467 a->constant = p.val;
468 }
469 else if (instruction->size == 1 && a->size != 0)
470 {
bab4becb 471 p = makelongparameter (cr16_allWords, 4, 8);
3d3d428f
NC
472 if (IS_INSN_MNEMONIC ("loadw")
473 || IS_INSN_MNEMONIC ("loadd")
474 || IS_INSN_MNEMONIC ("storw")
475 || IS_INSN_MNEMONIC ("stord"))
476 a->constant = (p.val * 2);
477 else
478 a->constant = p.val;
479 }
480 else /* below case for 0x0(reg pair) */
481 a->constant = 0;
482
483 break;
484
485 case arg_c:
486
487 if ((IS_INSN_TYPE (BRANCH_INS))
488 || (IS_INSN_MNEMONIC ("bal"))
489 || (IS_INSN_TYPE (CSTBIT_INS))
490 || (IS_INSN_TYPE (LD_STOR_INS)))
491 {
492 switch (a->size)
493 {
494 case 8 :
bab4becb 495 p = makelongparameter (cr16_allWords, 0, start_bits);
3d3d428f
NC
496 a->constant = ((((p.val&0xf00)>>4)) | (p.val&0xf));
497 break;
498
499 case 24:
500 if (instruction->size == 3)
501 {
bab4becb 502 p = makelongparameter (cr16_allWords, 16, inst_bit_size);
3d3d428f
NC
503 a->constant = ((((p.val>>16)&0xf) << 20)
504 | (((p.val>>24)&0xf) << 16)
505 | (p.val & 0xffff));
506 }
507 else if (instruction->size == 2)
508 {
bab4becb 509 p = makelongparameter (cr16_allWords, 8, inst_bit_size);
3d3d428f
NC
510 a->constant = p.val;
511 }
512 break;
513
514 default:
bab4becb
NC
515 p = makelongparameter (cr16_allWords,
516 inst_bit_size - (start_bits + a->size),
517 inst_bit_size - start_bits);
3d3d428f
NC
518 a->constant = p.val;
519 break;
520 }
521 }
522 else
523 {
bab4becb
NC
524 p = makelongparameter (cr16_allWords,
525 inst_bit_size - (start_bits + a->size),
3d3d428f
NC
526 inst_bit_size - start_bits);
527 a->constant = p.val;
528 }
529 break;
530
531 default:
532 break;
533 }
534}
535
536/* Print a single argument. */
537
538static void
539print_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info)
540{
541 LONGLONG longdisp, mask;
542 int sign_flag = 0;
543 int relative = 0;
544 bfd_vma number;
545 PTR stream = info->stream;
546 fprintf_ftype func = info->fprintf_func;
547
548 switch (a->type)
549 {
550 case arg_r:
551 func (stream, "%s", getregname (a->r));
552 break;
553
554 case arg_rp:
555 func (stream, "%s", getregpname (a->rp));
556 break;
557
558 case arg_pr:
559 func (stream, "%s", getprocregname (a->pr));
560 break;
561
562 case arg_prp:
563 func (stream, "%s", getprocpregname (a->prp));
564 break;
565
566 case arg_cc:
567 func (stream, "%s", getccstring (a->cc));
568 func (stream, "%s", "\t");
569 break;
570
571 case arg_ic:
572 if (IS_INSN_MNEMONIC ("excp"))
573 {
574 func (stream, "%s", gettrapstring (a->constant));
575 break;
576 }
577 else if ((IS_INSN_TYPE (ARITH_INS) || IS_INSN_TYPE (ARITH_BYTE_INS))
578 && ((instruction->size == 1) && (a->constant == 9)))
579 func (stream, "$%d", -1);
580 else if (INST_HAS_REG_LIST)
581 func (stream, "$0x%lx", a->constant +1);
582 else if (IS_INSN_TYPE (SHIFT_INS))
583 {
584 longdisp = a->constant;
585 mask = ((LONGLONG)1 << a->size) - 1;
586 if (longdisp & ((LONGLONG)1 << (a->size -1)))
587 {
588 sign_flag = 1;
589 longdisp = ~(longdisp) + 1;
590 }
591 a->constant = (unsigned long int) (longdisp & mask);
592 func (stream, "$%d", ((int)(sign_flag ? -a->constant :
593 a->constant)));
594 }
595 else
596 func (stream, "$0x%lx", a->constant);
597 switch (a->size)
598 {
599 case 4 : case 5 : case 6 : case 8 :
600 func (stream, "%s", ":s"); break;
601 case 16 : case 20 : func (stream, "%s", ":m"); break;
602 case 24 : case 32 : func (stream, "%s", ":l"); break;
603 default: break;
604 }
605 break;
606
607 case arg_idxr:
608 if (a->i_r == 0) func (stream, "[r12]");
609 if (a->i_r == 1) func (stream, "[r13]");
610 func (stream, "0x%lx", a->constant);
611 func (stream, "%s", print_exp_len (instruction->size * 16));
612 break;
613
614 case arg_idxrp:
615 if (a->i_r == 0) func (stream, "[r12]");
616 if (a->i_r == 1) func (stream, "[r13]");
617 func (stream, "0x%lx", a->constant);
618 func (stream, "%s", print_exp_len (instruction->size * 16));
619 func (stream, "%s", getidxregpname (a->rp));
620 break;
621
622 case arg_rbase:
623 func (stream, "(%s)", getregname (a->r));
624 break;
625
626 case arg_cr:
627 func (stream, "0x%lx", a->constant);
628 func (stream, "%s", print_exp_len (instruction->size * 16));
629 func (stream, "(%s)", getregname (a->r));
630 break;
631
632 case arg_crp:
633 func (stream, "0x%lx", a->constant);
634 func (stream, "%s", print_exp_len (instruction->size * 16));
635 func (stream, "%s", getregpname (a->rp));
636 break;
637
638 case arg_c:
639 /*Removed the *2 part as because implicit zeros are no more required.
640 Have to fix this as this needs a bit of extension in terms of branch
641 instructions. */
642 if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal"))
643 {
644 relative = 1;
645 longdisp = a->constant;
646 /* REVISIT: To sync with WinIDEA and CR16 4.1tools, the below
647 line commented */
648 /* longdisp <<= 1; */
649 mask = ((LONGLONG)1 << a->size) - 1;
650 switch (a->size)
651 {
652 case 8 :
653 {
654 longdisp <<= 1;
655 if (longdisp & ((LONGLONG)1 << a->size))
656 {
657 sign_flag = 1;
658 longdisp = ~(longdisp) + 1;
659 }
660 break;
661 }
662 case 16 :
663 case 24 :
664 {
665 if (longdisp & 1)
666 {
667 sign_flag = 1;
668 longdisp = ~(longdisp) + 1;
669 }
670 break;
671 }
672 default:
673 func (stream, "Wrong offset used in branch/bal instruction");
674 break;
675 }
676 a->constant = (unsigned long int) (longdisp & mask);
677 }
678 /* For branch Neq instruction it is 2*offset + 2. */
679 else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
680 a->constant = 2 * a->constant + 2;
681
682 if ((!IS_INSN_TYPE (CSTBIT_INS)) && (!IS_INSN_TYPE (LD_STOR_INS)))
683 (sign_flag) ? func (stream, "%s", "*-"): func (stream, "%s","*+");
684
522fe561 685 /* PR 10173: Avoid printing the 0x prefix twice. */
e20cc039 686 if (info->symtab_size > 0)
522fe561 687 func (stream, "%s", "0x");
3d3d428f
NC
688 number = ((relative ? memaddr : 0) +
689 (sign_flag ? ((- a->constant) & 0xffffffe) : a->constant));
690
691 (*info->print_address_func) ((number & ((1 << 24) - 1)), info);
692
693 func (stream, "%s", print_exp_len (instruction->size * 16));
694 break;
695
696 default:
697 break;
698 }
699}
700
701/* Print all the arguments of CURRINSN instruction. */
702
703static void
91d6fa6a 704print_arguments (ins *currentInsn, bfd_vma memaddr, struct disassemble_info *info)
3d3d428f
NC
705{
706 int i;
707
708 /* For "pop/push/popret RA instruction only. */
709 if ((IS_INSN_MNEMONIC ("pop")
710 || (IS_INSN_MNEMONIC ("popret")
711 || (IS_INSN_MNEMONIC ("push"))))
91d6fa6a 712 && currentInsn->nargs == 1)
3d3d428f
NC
713 {
714 info->fprintf_func (info->stream, "RA");
715 return;
716 }
717
91d6fa6a 718 for (i = 0; i < currentInsn->nargs; i++)
3d3d428f
NC
719 {
720 processing_argument_number = i;
721
722 /* For "bal (ra), disp17" instruction only. */
723 if ((IS_INSN_MNEMONIC ("bal")) && (i == 0) && instruction->size == 2)
724 {
725 info->fprintf_func (info->stream, "(ra),");
726 continue;
727 }
728
729 if ((INST_HAS_REG_LIST) && (i == 2))
730 info->fprintf_func (info->stream, "RA");
731 else
91d6fa6a 732 print_arg (&currentInsn->arg[i], memaddr, info);
3d3d428f 733
91d6fa6a 734 if ((i != currentInsn->nargs - 1) && (!IS_INSN_MNEMONIC ("b")))
3d3d428f
NC
735 info->fprintf_func (info->stream, ",");
736 }
737}
738
739/* Build the instruction's arguments. */
740
bab4becb 741void
73335eae 742cr16_make_instruction (void)
3d3d428f
NC
743{
744 int i;
745 unsigned int shift;
746
bab4becb 747 for (i = 0; i < cr16_currInsn.nargs; i++)
3d3d428f
NC
748 {
749 argument a;
750
751 memset (&a, 0, sizeof (a));
752 a.type = getargtype (instruction->operands[i].op_type);
753 a.size = getbits (instruction->operands[i].op_type);
754 shift = instruction->operands[i].shift;
755
756 make_argument (&a, shift);
bab4becb 757 cr16_currInsn.arg[i] = a;
3d3d428f
NC
758 }
759
760 /* Calculate instruction size (in bytes). */
bab4becb 761 cr16_currInsn.size = instruction->size + (size_changed ? 1 : 0);
3d3d428f 762 /* Now in bits. */
bab4becb 763 cr16_currInsn.size *= 2;
3d3d428f
NC
764}
765
766/* Retrieve a single word from a given memory address. */
767
768static wordU
769get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info)
770{
771 bfd_byte buffer[4];
772 int status;
773 wordU insn = 0;
774
775 status = info->read_memory_func (memaddr, buffer, 2, info);
776
777 if (status == 0)
778 insn = (wordU) bfd_getl16 (buffer);
779
780 return insn;
781}
782
783/* Retrieve multiple words (3) from a given memory address. */
784
785static void
786get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info)
787{
788 int i;
789 bfd_vma mem;
790
791 for (i = 0, mem = memaddr; i < 3; i++, mem += 2)
bab4becb 792 cr16_words[i] = get_word_at_PC (mem, info);
3d3d428f 793
43e65147 794 cr16_allWords = ((ULONGLONG) cr16_words[0] << 32)
bab4becb 795 + ((unsigned long) cr16_words[1] << 16) + cr16_words[2];
3d3d428f
NC
796}
797
798/* Prints the instruction by calling print_arguments after proper matching. */
799
800int
801print_insn_cr16 (bfd_vma memaddr, struct disassemble_info *info)
802{
803 int is_decoded; /* Nonzero means instruction has a match. */
804
805 /* Initialize global variables. */
806 imm4flag = 0;
807 size_changed = 0;
808
809 /* Retrieve the encoding from current memory location. */
810 get_words_at_PC (memaddr, info);
811 /* Find a matching opcode in table. */
73335eae 812 is_decoded = cr16_match_opcode ();
3d3d428f 813 /* If found, print the instruction's mnemonic and arguments. */
616ec358 814 if (is_decoded > 0 && (cr16_words[0] != 0 || cr16_words[1] != 0))
3d3d428f
NC
815 {
816 if (strneq (instruction->mnemonic, "cinv", 4))
ddb341a7 817 info->fprintf_func (info->stream,"%s", getcinvstring (instruction->mnemonic));
3d3d428f
NC
818 else
819 info->fprintf_func (info->stream, "%s", instruction->mnemonic);
820
bab4becb 821 if (((cr16_currInsn.nargs = get_number_of_operands ()) != 0)
3d3d428f
NC
822 && ! (IS_INSN_MNEMONIC ("b")))
823 info->fprintf_func (info->stream, "\t");
73335eae 824 cr16_make_instruction ();
3d3d428f 825 /* For push/pop/pushrtn with RA instructions. */
bab4becb
NC
826 if ((INST_HAS_REG_LIST) && ((cr16_words[0] >> 7) & 0x1))
827 cr16_currInsn.nargs +=1;
828 print_arguments (&cr16_currInsn, memaddr, info);
829 return cr16_currInsn.size;
3d3d428f
NC
830 }
831
832 /* No match found. */
833 info->fprintf_func (info->stream,"%s ",ILLEGAL);
834 return 2;
835}
This page took 0.63522 seconds and 4 git commands to generate.