Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/opcodes/pj-dis.c
Line
Count
Source (jump to first uncovered line)
1
/* pj-dis.c -- Disassemble picoJava instructions.
2
   Copyright (C) 1999-2025 Free Software Foundation, Inc.
3
   Contributed by Steve Chamberlain, of Transmeta (sac@pobox.com).
4
5
   This file is part of the GNU opcodes library.
6
7
   This library is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3, or (at your option)
10
   any later version.
11
12
   It is distributed in the hope that it will be useful, but WITHOUT
13
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15
   License for 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
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
22
#include "sysdep.h"
23
#include <stdio.h>
24
#include "libiberty.h"
25
#include "opcode/pj.h"
26
#include "disassemble.h"
27
28
extern const pj_opc_info_t pj_opc_info[512];
29
30
static int
31
get_int (bfd_vma memaddr, int *iptr, struct disassemble_info *info)
32
0
{
33
0
  unsigned char ival[4];
34
0
  int status = info->read_memory_func (memaddr, ival, 4, info);
35
36
0
  *iptr = (((unsigned) ival[0] << 24)
37
0
     | (ival[1] << 16)
38
0
     | (ival[2] << 8)
39
0
     | (ival[3] << 0));
40
41
0
  return status;
42
0
}
43
44
int
45
print_insn_pj (bfd_vma addr, struct disassemble_info *info)
46
0
{
47
0
  fprintf_ftype fprintf_fn = info->fprintf_func;
48
0
  void *stream = info->stream;
49
0
  unsigned char opcode;
50
0
  int status;
51
52
0
  if ((status = info->read_memory_func (addr, &opcode, 1, info)))
53
0
    goto fail;
54
55
0
  if (opcode == 0xff)
56
0
    {
57
0
      unsigned char byte_2;
58
59
0
      if ((status = info->read_memory_func (addr + 1, &byte_2, 1, info)))
60
0
  goto fail;
61
0
      fprintf_fn (stream, "%s", pj_opc_info[opcode + byte_2].u.name);
62
0
      return 2;
63
0
    }
64
0
  else
65
0
    {
66
0
      char *sep = "\t";
67
0
      int insn_start = addr;
68
0
      const pj_opc_info_t *op = &pj_opc_info[opcode];
69
0
      unsigned int a;
70
71
0
      addr++;
72
0
      fprintf_fn (stream, "%s", op->u.name);
73
74
      /* The tableswitch instruction is followed by the default
75
   address, low value, high value and the destinations.  */
76
77
0
      if (strcmp (op->u.name, "tableswitch") == 0)
78
0
  {
79
0
    int lowval;
80
0
    int highval;
81
0
    int val;
82
83
0
    addr = (addr + 3) & ~3;
84
0
    if ((status = get_int (addr, &val, info)))
85
0
      goto fail;
86
87
0
    fprintf_fn (stream, " default: ");
88
0
    (*info->print_address_func) (val + insn_start, info);
89
0
    addr += 4;
90
91
0
    if ((status = get_int (addr, &lowval, info)))
92
0
      goto fail;
93
0
    addr += 4;
94
95
0
    if ((status = get_int (addr, &highval, info)))
96
0
      goto fail;
97
0
    addr += 4;
98
99
0
    while (lowval <= highval)
100
0
      {
101
0
        if ((status = get_int (addr, &val, info)))
102
0
    goto fail;
103
0
        fprintf_fn (stream, " %d:[", lowval);
104
0
        (*info->print_address_func) (val + insn_start, info);
105
0
        fprintf_fn (stream, " ]");
106
0
        addr += 4;
107
0
        lowval++;
108
0
      }
109
0
    return addr - insn_start;
110
0
  }
111
112
      /* The lookupswitch instruction is followed by the default
113
   address, element count and pairs of values and
114
   addresses.  */
115
0
      if (strcmp (op->u.name, "lookupswitch") == 0)
116
0
  {
117
0
    int count;
118
0
    int val;
119
120
0
    addr = (addr + 3) & ~3;
121
0
    if ((status = get_int (addr, &val, info)))
122
0
      goto fail;
123
0
    addr += 4;
124
125
0
    fprintf_fn (stream, " default: ");
126
0
    (*info->print_address_func) (val + insn_start, info);
127
128
0
    if ((status = get_int (addr, &count, info)))
129
0
      goto fail;
130
0
    addr += 4;
131
132
0
    while (count--)
133
0
      {
134
0
        if ((status = get_int (addr, &val, info)))
135
0
    goto fail;
136
0
        addr += 4;
137
0
        fprintf_fn (stream, " %d:[", val);
138
139
0
        if ((status = get_int (addr, &val, info)))
140
0
    goto fail;
141
0
        addr += 4;
142
143
0
        (*info->print_address_func) (val + insn_start, info);
144
0
        fprintf_fn (stream, " ]");
145
0
      }
146
0
    return addr - insn_start;
147
0
  }
148
149
0
      for (a = 0; a < ARRAY_SIZE (op->arg) && op->arg[a]; a++)
150
0
  {
151
0
    unsigned char data[4];
152
0
    int val = 0;
153
0
    int i;
154
0
    int size = ASIZE (op->arg[a]);
155
156
0
    if ((status = info->read_memory_func (addr, data, size, info)))
157
0
      goto fail;
158
159
0
    val = (UNS (op->arg[0]) || ((data[0] & 0x80) == 0)) ? 0 : -1;
160
161
0
    for (i = 0; i < size; i++)
162
0
      val = ((unsigned) val << 8) | (data[i] & 0xff);
163
164
0
    fprintf_fn (stream, "%s", sep);
165
0
    if (PCREL (op->arg[a]))
166
0
      (*info->print_address_func) (val + insn_start, info);
167
0
    else
168
0
      fprintf_fn (stream, "%d", val);
169
170
0
    sep = ",";
171
0
    addr += size;
172
0
  }
173
0
      return op->len;
174
0
    }
175
176
0
 fail:
177
0
  info->memory_error_func (status, addr, info);
178
0
  return -1;
179
0
}