PR25249, Memory leak in microblaze-dis.c
[deliverable/binutils-gdb.git] / opcodes / crx-dis.c
CommitLineData
1fe1f39c 1/* Disassembler code for CRX.
82704155 2 Copyright (C) 2004-2019 Free Software Foundation, Inc.
1fe1f39c
NC
3 Contributed by Tomer Levi, NSC, Israel.
4 Written by Tomer Levi.
5
9b201bb5 6 This file is part of the GNU opcodes library.
1fe1f39c 7
9b201bb5
NC
8 This library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
1fe1f39c
NC
11 any later version.
12
9b201bb5
NC
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
1fe1f39c
NC
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
9b201bb5
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
1fe1f39c 22
1fe1f39c 23#include "sysdep.h"
88c1242d 24#include "disassemble.h"
1fe1f39c
NC
25#include "opcode/crx.h"
26
27/* String to print when opcode was not matched. */
28#define ILLEGAL "illegal"
29 /* Escape to 16-bit immediate. */
30#define ESCAPE_16_BIT 0xE
31
32/* Extract 'n_bits' from 'a' starting from offset 'offs'. */
33#define EXTRACT(a, offs, n_bits) \
a854efa3 34 (n_bits == 32 ? (((a) >> (offs)) & 0xffffffffL) \
1fe1f39c
NC
35 : (((a) >> (offs)) & ((1 << (n_bits)) -1)))
36
37/* Set Bit Mask - a mask to set all bits starting from offset 'offs'. */
38#define SBM(offs) ((((1 << (32 - offs)) -1) << (offs)))
39
40typedef unsigned long dwordU;
41typedef unsigned short wordU;
42
43typedef struct
44{
45 dwordU val;
46 int nbits;
47} parameter;
48
49/* Structure to hold valid 'cinv' instruction options. */
50
51typedef struct
52 {
53 /* Cinv printed string. */
54 char *str;
55 /* Value corresponding to the string. */
56 unsigned int value;
57 }
58cinv_entry;
59
60/* CRX 'cinv' options. */
e5d70d6b 61static const cinv_entry crx_cinvs[] =
1fe1f39c 62{
43e65147
L
63 {"[i]", 2}, {"[i,u]", 3}, {"[d]", 4}, {"[d,u]", 5},
64 {"[d,i]", 6}, {"[d,i,u]", 7}, {"[b]", 8},
65 {"[b,i]", 10}, {"[b,i,u]", 11}, {"[b,d]", 12},
48c9f030 66 {"[b,d,u]", 13}, {"[b,d,i]", 14}, {"[b,d,i,u]", 15}
1fe1f39c
NC
67};
68
a58a3762
TL
69/* Enum to distinguish different registers argument types. */
70typedef enum REG_ARG_TYPE
48c9f030 71 {
a58a3762
TL
72 /* General purpose register (r<N>). */
73 REG_ARG = 0,
74 /* User register (u<N>). */
75 USER_REG_ARG,
76 /* CO-Processor register (c<N>). */
48c9f030 77 COP_ARG,
a58a3762 78 /* CO-Processor special register (cs<N>). */
43e65147 79 COPS_ARG
48c9f030 80 }
a58a3762 81REG_ARG_TYPE;
48c9f030 82
1fe1f39c 83/* Number of valid 'cinv' instruction options. */
e5d70d6b 84static int NUMCINVS = ((sizeof crx_cinvs)/(sizeof crx_cinvs[0]));
1fe1f39c 85/* Current opcode table entry we're disassembling. */
e5d70d6b 86static const inst *instruction;
1fe1f39c 87/* Current instruction we're disassembling. */
e5d70d6b 88static ins currInsn;
1fe1f39c 89/* The current instruction is read into 3 consecutive words. */
e5d70d6b 90static wordU words[3];
1fe1f39c 91/* Contains all words in appropriate order. */
e5d70d6b 92static ULONGLONG allWords;
1fe1f39c 93/* Holds the current processed argument number. */
e5d70d6b 94static int processing_argument_number;
1fe1f39c 95/* Nonzero means a CST4 instruction. */
e5d70d6b 96static int cst4flag;
1fe1f39c
NC
97/* Nonzero means the instruction's original size is
98 incremented (escape sequence is used). */
e5d70d6b 99static int size_changed;
1fe1f39c
NC
100
101static int get_number_of_operands (void);
102static argtype getargtype (operand_type);
103static int getbits (operand_type);
104static char *getregname (reg);
105static char *getcopregname (copreg, reg_type);
106static char * getprocregname (int);
107static char *gettrapstring (unsigned);
108static char *getcinvstring (unsigned);
a58a3762 109static void getregliststring (int, char *, enum REG_ARG_TYPE);
1fe1f39c
NC
110static wordU get_word_at_PC (bfd_vma, struct disassemble_info *);
111static void get_words_at_PC (bfd_vma, struct disassemble_info *);
112static unsigned long build_mask (void);
113static int powerof2 (int);
114static int match_opcode (void);
115static void make_instruction (void);
12855a36
TL
116static void print_arguments (ins *, bfd_vma, struct disassemble_info *);
117static void print_arg (argument *, bfd_vma, struct disassemble_info *);
1fe1f39c
NC
118
119/* Retrieve the number of operands for the current assembled instruction. */
120
121static int
122get_number_of_operands (void)
123{
124 int i;
125
126 for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
127 ;
128
129 return i;
130}
131
132/* Return the bit size for a given operand. */
133
134static int
135getbits (operand_type op)
136{
137 if (op < MAX_OPRD)
138 return crx_optab[op].bit_size;
139 else
140 return 0;
141}
142
143/* Return the argument type of a given operand. */
144
145static argtype
146getargtype (operand_type op)
147{
148 if (op < MAX_OPRD)
149 return crx_optab[op].arg_type;
150 else
151 return nullargs;
152}
153
154/* Given the trap index in dispatch table, return its name.
155 This routine is used when disassembling the 'excp' instruction. */
156
157static char *
91d6fa6a 158gettrapstring (unsigned int trap_index)
1fe1f39c
NC
159{
160 const trap_entry *trap;
161
162 for (trap = crx_traps; trap < crx_traps + NUMTRAPS; trap++)
91d6fa6a 163 if (trap->entry == trap_index)
1fe1f39c
NC
164 return trap->name;
165
166 return ILLEGAL;
167}
168
169/* Given a 'cinv' instruction constant operand, return its corresponding string.
170 This routine is used when disassembling the 'cinv' instruction. */
171
172static char *
173getcinvstring (unsigned int num)
174{
175 const cinv_entry *cinv;
176
177 for (cinv = crx_cinvs; cinv < (crx_cinvs + NUMCINVS); cinv++)
178 if (cinv->value == num)
179 return cinv->str;
180
181 return ILLEGAL;
182}
183
184/* Given a register enum value, retrieve its name. */
185
186char *
187getregname (reg r)
188{
91d6fa6a 189 const reg_entry * regentry = &crx_regtab[r];
1fe1f39c 190
91d6fa6a 191 if (regentry->type != CRX_R_REGTYPE)
1fe1f39c
NC
192 return ILLEGAL;
193 else
91d6fa6a 194 return regentry->name;
1fe1f39c
NC
195}
196
197/* Given a coprocessor register enum value, retrieve its name. */
198
199char *
200getcopregname (copreg r, reg_type type)
201{
91d6fa6a 202 const reg_entry * regentry;
1fe1f39c
NC
203
204 if (type == CRX_C_REGTYPE)
91d6fa6a 205 regentry = &crx_copregtab[r];
1fe1f39c 206 else if (type == CRX_CS_REGTYPE)
91d6fa6a 207 regentry = &crx_copregtab[r+(cs0-c0)];
1fe1f39c
NC
208 else
209 return ILLEGAL;
210
91d6fa6a 211 return regentry->name;
1fe1f39c
NC
212}
213
214
215/* Getting a processor register name. */
216
217static char *
91d6fa6a 218getprocregname (int reg_index)
1fe1f39c
NC
219{
220 const reg_entry *r;
221
222 for (r = crx_regtab; r < crx_regtab + NUMREGS; r++)
91d6fa6a 223 if (r->image == reg_index)
1fe1f39c
NC
224 return r->name;
225
226 return "ILLEGAL REGISTER";
227}
228
229/* Get the power of two for a given integer. */
230
231static int
232powerof2 (int x)
233{
234 int product, i;
235
236 for (i = 0, product = 1; i < x; i++)
237 product *= 2;
238
239 return product;
240}
241
242/* Transform a register bit mask to a register list. */
243
244void
a58a3762 245getregliststring (int mask, char *string, enum REG_ARG_TYPE core_cop)
1fe1f39c 246{
e95b887f 247 char temp_string[16];
1fe1f39c
NC
248 int i;
249
250 string[0] = '{';
251 string[1] = '\0';
252
a58a3762
TL
253
254 /* A zero mask means HI/LO registers. */
255 if (mask == 0)
256 {
257 if (core_cop == USER_REG_ARG)
258 strcat (string, "ulo,uhi");
259 else
260 strcat (string, "lo,hi");
261 }
262 else
1fe1f39c 263 {
a58a3762 264 for (i = 0; i < 16; i++)
48c9f030 265 {
a58a3762 266 if (mask & 0x1)
48c9f030 267 {
a58a3762
TL
268 switch (core_cop)
269 {
270 case REG_ARG:
271 sprintf (temp_string, "r%d", i);
272 break;
273 case USER_REG_ARG:
274 sprintf (temp_string, "u%d", i);
275 break;
276 case COP_ARG:
277 sprintf (temp_string, "c%d", i);
278 break;
279 case COPS_ARG:
280 sprintf (temp_string, "cs%d", i);
281 break;
282 default:
283 break;
284 }
285 strcat (string, temp_string);
286 if (mask & 0xfffe)
287 strcat (string, ",");
48c9f030 288 }
a58a3762
TL
289 mask >>= 1;
290 }
1fe1f39c
NC
291 }
292
293 strcat (string, "}");
294}
295
296/* START and END are relating 'allWords' struct, which is 48 bits size.
297
298 START|--------|END
299 +---------+---------+---------+---------+
300 | | V | A | L |
301 +---------+---------+---------+---------+
302 0 16 32 48
303 words [0] [1] [2] */
304
305static parameter
306makelongparameter (ULONGLONG val, int start, int end)
307{
308 parameter p;
309
310 p.val = (dwordU) EXTRACT(val, 48 - end, end - start);
311 p.nbits = end - start;
312 return p;
313}
314
315/* Build a mask of the instruction's 'constant' opcode,
316 based on the instruction's printing flags. */
317
318static unsigned long
319build_mask (void)
320{
321 unsigned int print_flags;
322 unsigned long mask;
323
324 print_flags = instruction->flags & FMT_CRX;
325 switch (print_flags)
326 {
327 case FMT_1:
328 mask = 0xF0F00000;
329 break;
330 case FMT_2:
331 mask = 0xFFF0FF00;
332 break;
333 case FMT_3:
334 mask = 0xFFF00F00;
335 break;
336 case FMT_4:
337 mask = 0xFFF0F000;
338 break;
339 case FMT_5:
340 mask = 0xFFF0FFF0;
341 break;
342 default:
343 mask = SBM(instruction->match_bits);
344 break;
345 }
346
347 return mask;
348}
349
350/* Search for a matching opcode. Return 1 for success, 0 for failure. */
351
352static int
353match_opcode (void)
354{
355 unsigned long mask;
356
357 /* The instruction 'constant' opcode doewsn't exceed 32 bits. */
4ded9dda 358 unsigned long doubleWord = (words[1] + (words[0] << 16)) & 0xffffffff;
1fe1f39c
NC
359
360 /* Start searching from end of instruction table. */
361 instruction = &crx_instruction[NUMOPCODES - 2];
362
363 /* Loop over instruction table until a full match is found. */
364 while (instruction >= crx_instruction)
365 {
366 mask = build_mask ();
367 if ((doubleWord & mask) == BIN(instruction->match, instruction->match_bits))
368 return 1;
369 else
370 instruction--;
371 }
372 return 0;
373}
374
375/* Set the proper parameter value for different type of arguments. */
376
377static void
378make_argument (argument * a, int start_bits)
379{
380 int inst_bit_size, total_size;
381 parameter p;
382
383 if ((instruction->size == 3) && a->size >= 16)
384 inst_bit_size = 48;
385 else
386 inst_bit_size = 32;
387
388 switch (a->type)
389 {
390 case arg_copr:
391 case arg_copsr:
392 p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
393 inst_bit_size - start_bits);
394 a->cr = p.val;
395 break;
396
397 case arg_r:
398 p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
399 inst_bit_size - start_bits);
400 a->r = p.val;
401 break;
402
403 case arg_ic:
404 p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
405 inst_bit_size - start_bits);
406
407 if ((p.nbits == 4) && cst4flag)
408 {
409 if (IS_INSN_TYPE (CMPBR_INS) && (p.val == ESCAPE_16_BIT))
410 {
411 /* A special case, where the value is actually stored
412 in the last 4 bits. */
413 p = makelongparameter (allWords, 44, 48);
414 /* The size of the instruction should be incremented. */
415 size_changed = 1;
416 }
417
418 if (p.val == 6)
419 p.val = -1;
420 else if (p.val == 13)
421 p.val = 48;
422 else if (p.val == 5)
423 p.val = -4;
424 else if (p.val == 10)
425 p.val = 32;
426 else if (p.val == 11)
427 p.val = 20;
428 else if (p.val == 9)
429 p.val = 16;
430 }
431
432 a->constant = p.val;
433 break;
434
42048ee7 435 case arg_idxr:
1fe1f39c
NC
436 a->scale = 0;
437 total_size = a->size + 10; /* sizeof(rbase + ridx + scl2) = 10. */
438 p = makelongparameter (allWords, inst_bit_size - total_size,
439 inst_bit_size - (total_size - 4));
440 a->r = p.val;
441 p = makelongparameter (allWords, inst_bit_size - (total_size - 4),
442 inst_bit_size - (total_size - 8));
443 a->i_r = p.val;
444 p = makelongparameter (allWords, inst_bit_size - (total_size - 8),
445 inst_bit_size - (total_size - 10));
446 a->scale = p.val;
447 p = makelongparameter (allWords, inst_bit_size - (total_size - 10),
448 inst_bit_size);
449 a->constant = p.val;
450 break;
451
452 case arg_rbase:
453 p = makelongparameter (allWords, inst_bit_size - (start_bits + 4),
454 inst_bit_size - start_bits);
455 a->r = p.val;
456 break;
457
458 case arg_cr:
459 if (a->size <= 8)
460 {
461 p = makelongparameter (allWords, inst_bit_size - (start_bits + 4),
462 inst_bit_size - start_bits);
463 a->r = p.val;
464 /* Case for opc4 r dispu rbase. */
465 p = makelongparameter (allWords, inst_bit_size - (start_bits + 8),
466 inst_bit_size - (start_bits + 4));
467 }
468 else
469 {
470 /* The 'rbase' start_bits is always relative to a 32-bit data type. */
471 p = makelongparameter (allWords, 32 - (start_bits + 4),
472 32 - start_bits);
473 a->r = p.val;
474 p = makelongparameter (allWords, 32 - start_bits,
475 inst_bit_size);
476 }
477 if ((p.nbits == 4) && cst4flag)
478 {
479 if (instruction->flags & DISPUW4)
480 p.val *= 2;
481 else if (instruction->flags & DISPUD4)
482 p.val *= 4;
483 }
484 a->constant = p.val;
485 break;
486
487 case arg_c:
488 p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
489 inst_bit_size - start_bits);
490 a->constant = p.val;
491 break;
492 default:
493 break;
494 }
495}
496
497/* Print a single argument. */
498
499static void
12855a36 500print_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info)
1fe1f39c
NC
501{
502 LONGLONG longdisp, mask;
12855a36
TL
503 int sign_flag = 0;
504 int relative = 0;
505 bfd_vma number;
1fe1f39c
NC
506 int op_index = 0;
507 char string[200];
508 PTR stream = info->stream;
509 fprintf_ftype func = info->fprintf_func;
510
511 switch (a->type)
512 {
513 case arg_copr:
514 func (stream, "%s", getcopregname (a->cr, CRX_C_REGTYPE));
515 break;
516
517 case arg_copsr:
518 func (stream, "%s", getcopregname (a->cr, CRX_CS_REGTYPE));
519 break;
520
521 case arg_r:
522 if (IS_INSN_MNEMONIC ("mtpr") || IS_INSN_MNEMONIC ("mfpr"))
523 func (stream, "%s", getprocregname (a->r));
524 else
525 func (stream, "%s", getregname (a->r));
526 break;
527
528 case arg_ic:
529 if (IS_INSN_MNEMONIC ("excp"))
530 func (stream, "%s", gettrapstring (a->constant));
531
532 else if (IS_INSN_MNEMONIC ("cinv"))
533 func (stream, "%s", getcinvstring (a->constant));
534
535 else if (INST_HAS_REG_LIST)
536 {
43e65147
L
537 REG_ARG_TYPE reg_arg_type = IS_INSN_TYPE (COP_REG_INS) ?
538 COP_ARG : IS_INSN_TYPE (COPS_REG_INS) ?
a58a3762
TL
539 COPS_ARG : (instruction->flags & USER_REG) ?
540 USER_REG_ARG : REG_ARG;
48c9f030 541
a58a3762 542 if ((reg_arg_type == COP_ARG) || (reg_arg_type == COPS_ARG))
48c9f030 543 {
a58a3762
TL
544 /* Check for proper argument number. */
545 if (processing_argument_number == 2)
546 {
547 getregliststring (a->constant, string, reg_arg_type);
548 func (stream, "%s", string);
549 }
550 else
1f42f8b3 551 func (stream, "$0x%lx", a->constant & 0xffffffff);
48c9f030
NC
552 }
553 else
1fe1f39c 554 {
a58a3762 555 getregliststring (a->constant, string, reg_arg_type);
1fe1f39c
NC
556 func (stream, "%s", string);
557 }
1fe1f39c
NC
558 }
559 else
1f42f8b3 560 func (stream, "$0x%lx", a->constant & 0xffffffff);
1fe1f39c
NC
561 break;
562
42048ee7 563 case arg_idxr:
1f42f8b3
AM
564 func (stream, "0x%lx(%s,%s,%d)", a->constant & 0xffffffff,
565 getregname (a->r), getregname (a->i_r), powerof2 (a->scale));
1fe1f39c
NC
566 break;
567
568 case arg_rbase:
569 func (stream, "(%s)", getregname (a->r));
570 break;
571
572 case arg_cr:
1f42f8b3 573 func (stream, "0x%lx(%s)", a->constant & 0xffffffff, getregname (a->r));
1fe1f39c
NC
574
575 if (IS_INSN_TYPE (LD_STOR_INS_INC))
576 func (stream, "+");
577 break;
578
579 case arg_c:
580 /* Removed the *2 part as because implicit zeros are no more required.
581 Have to fix this as this needs a bit of extension in terms of branchins.
582 Have to add support for cmp and branch instructions. */
583 if (IS_INSN_TYPE (BRANCH_INS) || IS_INSN_MNEMONIC ("bal")
584 || IS_INSN_TYPE (CMPBR_INS) || IS_INSN_TYPE (DCR_BRANCH_INS)
585 || IS_INSN_TYPE (COP_BRANCH_INS))
586 {
12855a36 587 relative = 1;
1fe1f39c
NC
588 longdisp = a->constant;
589 longdisp <<= 1;
1fe1f39c
NC
590
591 switch (a->size)
592 {
593 case 8:
594 case 16:
595 case 24:
596 case 32:
597 mask = ((LONGLONG)1 << a->size) - 1;
598 if (longdisp & ((LONGLONG)1 << a->size))
599 {
12855a36 600 sign_flag = 1;
1fe1f39c
NC
601 longdisp = ~(longdisp) + 1;
602 }
603 a->constant = (unsigned long int) (longdisp & mask);
604 break;
605 default:
606 func (stream,
607 "Wrong offset used in branch/bal instruction");
608 break;
609 }
610
1fe1f39c
NC
611 }
612 /* For branch Neq instruction it is 2*offset + 2. */
12855a36 613 else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
1fe1f39c 614 a->constant = 2 * a->constant + 2;
12855a36 615 else if (IS_INSN_TYPE (LD_STOR_INS_INC)
1fe1f39c
NC
616 || IS_INSN_TYPE (LD_STOR_INS)
617 || IS_INSN_TYPE (STOR_IMM_INS)
618 || IS_INSN_TYPE (CSTBIT_INS))
619 {
620 op_index = instruction->flags & REVERSE_MATCH ? 0 : 1;
621 if (instruction->operands[op_index].op_type == abs16)
622 a->constant |= 0xFFFF0000;
623 }
12855a36
TL
624 func (stream, "%s", "0x");
625 number = (relative ? memaddr : 0)
626 + (sign_flag ? -a->constant : a->constant);
627 (*info->print_address_func) (number, info);
1fe1f39c
NC
628 break;
629 default:
630 break;
631 }
632}
633
634/* Print all the arguments of CURRINSN instruction. */
635
636static void
91d6fa6a 637print_arguments (ins *currentInsn, bfd_vma memaddr, struct disassemble_info *info)
1fe1f39c
NC
638{
639 int i;
640
91d6fa6a 641 for (i = 0; i < currentInsn->nargs; i++)
1fe1f39c
NC
642 {
643 processing_argument_number = i;
644
91d6fa6a 645 print_arg (&currentInsn->arg[i], memaddr, info);
1fe1f39c 646
91d6fa6a 647 if (i != currentInsn->nargs - 1)
1fe1f39c
NC
648 info->fprintf_func (info->stream, ", ");
649 }
650}
651
652/* Build the instruction's arguments. */
653
654static void
655make_instruction (void)
656{
657 int i;
89a649f7 658 unsigned int shift;
1fe1f39c
NC
659
660 for (i = 0; i < currInsn.nargs; i++)
661 {
47d8304e 662 argument a;
ec36c4a4 663
47d8304e 664 memset (&a, 0, sizeof (a));
1fe1f39c
NC
665 a.type = getargtype (instruction->operands[i].op_type);
666 if (instruction->operands[i].op_type == cst4
89a649f7 667 || instruction->operands[i].op_type == rbase_dispu4)
1fe1f39c
NC
668 cst4flag = 1;
669 a.size = getbits (instruction->operands[i].op_type);
670 shift = instruction->operands[i].shift;
671
672 make_argument (&a, shift);
673 currInsn.arg[i] = a;
674 }
675
676 /* Calculate instruction size (in bytes). */
677 currInsn.size = instruction->size + (size_changed ? 1 : 0);
89a649f7 678 /* Now in bits. */
1fe1f39c 679 currInsn.size *= 2;
1fe1f39c
NC
680}
681
682/* Retrieve a single word from a given memory address. */
683
684static wordU
685get_word_at_PC (bfd_vma memaddr, struct disassemble_info *info)
686{
687 bfd_byte buffer[4];
688 int status;
689 wordU insn = 0;
690
691 status = info->read_memory_func (memaddr, buffer, 2, info);
692
693 if (status == 0)
694 insn = (wordU) bfd_getl16 (buffer);
695
696 return insn;
697}
698
699/* Retrieve multiple words (3) from a given memory address. */
700
701static void
702get_words_at_PC (bfd_vma memaddr, struct disassemble_info *info)
703{
704 int i;
705 bfd_vma mem;
706
707 for (i = 0, mem = memaddr; i < 3; i++, mem += 2)
708 words[i] = get_word_at_PC (mem, info);
709
710 allWords =
711 ((ULONGLONG) words[0] << 32) + ((unsigned long) words[1] << 16) + words[2];
712}
713
714/* Prints the instruction by calling print_arguments after proper matching. */
715
716int
e6c7cdec 717print_insn_crx (bfd_vma memaddr, struct disassemble_info *info)
1fe1f39c
NC
718{
719 int is_decoded; /* Nonzero means instruction has a match. */
720
721 /* Initialize global variables. */
722 cst4flag = 0;
723 size_changed = 0;
724
725 /* Retrieve the encoding from current memory location. */
726 get_words_at_PC (memaddr, info);
727 /* Find a matching opcode in table. */
728 is_decoded = match_opcode ();
729 /* If found, print the instruction's mnemonic and arguments. */
616ec358 730 if (is_decoded > 0 && (words[0] != 0 || words[1] != 0))
1fe1f39c
NC
731 {
732 info->fprintf_func (info->stream, "%s", instruction->mnemonic);
733 if ((currInsn.nargs = get_number_of_operands ()) != 0)
734 info->fprintf_func (info->stream, "\t");
735 make_instruction ();
12855a36 736 print_arguments (&currInsn, memaddr, info);
1fe1f39c
NC
737 return currInsn.size;
738 }
739
740 /* No match found. */
741 info->fprintf_func (info->stream,"%s ",ILLEGAL);
742 return 2;
743}
This page took 0.69264 seconds and 4 git commands to generate.