Fix disassembly of RX zero-offset register indirect instructions.
[deliverable/binutils-gdb.git] / opcodes / rx-dis.c
CommitLineData
c7927a3c 1/* Disassembler code for Renesas RX.
b90efa5b 2 Copyright (C) 2008-2015 Free Software Foundation, Inc.
c7927a3c
NC
3 Contributed by Red Hat.
4 Written by DJ Delorie.
5
6 This file is part of the GNU opcodes library.
7
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)
11 any later version.
12
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.
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
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
5eb3690e 23#include "sysdep.h"
c7927a3c
NC
24#include <stdio.h>
25
26#include "bfd.h"
27#include "dis-asm.h"
28#include "opcode/rx.h"
29
30typedef struct
31{
32 bfd_vma pc;
33 disassemble_info * dis;
34} RX_Data;
35
36static int
37rx_get_byte (void * vdata)
38{
39 bfd_byte buf[1];
40 RX_Data *rx_data = (RX_Data *) vdata;
41
42 rx_data->dis->read_memory_func (rx_data->pc,
43 buf,
44 1,
45 rx_data->dis);
46
47 rx_data->pc ++;
48 return buf[0];
49}
50
f04265ec 51static char const * size_names[RX_MAX_SIZE] =
c7927a3c 52{
f04265ec 53 "", ".b", ".ub", ".b", ".w", ".uw", ".w", ".a", ".l", "<error>"
c7927a3c
NC
54};
55
f04265ec 56static char const * opsize_names[RX_MAX_SIZE] =
c7927a3c 57{
f04265ec 58 "", ".b", ".b", ".b", ".w", ".w", ".w", ".a", ".l", "<error>"
c7927a3c
NC
59};
60
61static char const * register_names[] =
62{
63 /* general registers */
64 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
65 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
66 /* control register */
f04265ec
NC
67 "psw", "pc", "usp", "fpsw", NULL, NULL, NULL, NULL,
68 "bpsw", "bpc", "isp", "fintv", "intb", NULL, NULL, NULL,
69 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
70 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
c7927a3c
NC
71};
72
73static char const * condition_names[] =
74{
75 /* condition codes */
76 "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
77 "ge", "lt", "gt", "le", "o", "no", "always", "never"
78};
79
80static const char * flag_names[] =
81{
82 "c", "z", "s", "o", "", "", "", "",
83 "", "", "", "", "", "", "", "",
84 "i", "u", "", "", "", "", "", ""
85 "", "", "", "", "", "", "", "",
86};
87
88int
89print_insn_rx (bfd_vma addr, disassemble_info * dis)
90{
91 int rv;
92 RX_Data rx_data;
93 RX_Opcode_Decoded opcode;
94 const char * s;
95
96 rx_data.pc = addr;
97 rx_data.dis = dis;
98
99 rv = rx_decode_opcode (addr, &opcode, rx_get_byte, &rx_data);
100
101 dis->bytes_per_line = 10;
102
103#define PR (dis->fprintf_func)
104#define PS (dis->stream)
105#define PC(c) PR (PS, "%c", c)
106
f04265ec
NC
107 /* Detect illegal instructions. */
108 if (opcode.op[0].size == RX_Bad_Size
109 || register_names [opcode.op[0].reg] == NULL
110 || register_names [opcode.op[1].reg] == NULL
111 || register_names [opcode.op[2].reg] == NULL)
112 {
113 bfd_byte buf[10];
114 int i;
115
116 PR (PS, ".byte ");
117 rx_data.dis->read_memory_func (rx_data.pc - rv, buf, rv, rx_data.dis);
118
119 for (i = 0 ; i < rv; i++)
120 PR (PS, "0x%02x ", buf[i]);
121 return rv;
122 }
123
c7927a3c
NC
124 for (s = opcode.syntax; *s; s++)
125 {
126 if (*s != '%')
127 {
128 PC (*s);
129 }
130 else
131 {
132 RX_Opcode_Operand * oper;
133 int do_size = 0;
134 int do_hex = 0;
135 int do_addr = 0;
136
137 s ++;
138
139 if (*s == 'S')
140 {
141 do_size = 1;
142 s++;
143 }
144 if (*s == 'x')
145 {
146 do_hex = 1;
147 s++;
148 }
149 if (*s == 'a')
150 {
151 do_addr = 1;
152 s++;
153 }
154
155 switch (*s)
156 {
157 case '%':
158 PC ('%');
159 break;
160
161 case 's':
162 PR (PS, "%s", opsize_names[opcode.size]);
163 break;
164
165 case '0':
166 case '1':
167 case '2':
168 oper = opcode.op + *s - '0';
169 if (do_size)
170 {
e292aa7a 171 if (oper->type == RX_Operand_Indirect || oper->type == RX_Operand_Zero_Indirect)
c7927a3c
NC
172 PR (PS, "%s", size_names[oper->size]);
173 }
174 else
175 switch (oper->type)
176 {
177 case RX_Operand_Immediate:
178 if (do_addr)
179 dis->print_address_func (oper->addend, dis);
180 else if (do_hex
181 || oper->addend > 999
182 || oper->addend < -999)
183 PR (PS, "%#x", oper->addend);
184 else
185 PR (PS, "%d", oper->addend);
186 break;
187 case RX_Operand_Register:
90d6ff62 188 case RX_Operand_TwoReg:
c7927a3c
NC
189 PR (PS, "%s", register_names[oper->reg]);
190 break;
191 case RX_Operand_Indirect:
e292aa7a
NC
192 PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]);
193 break;
194 case RX_Operand_Zero_Indirect:
195 PR (PS, "[%s]", register_names[oper->reg]);
c7927a3c
NC
196 break;
197 case RX_Operand_Postinc:
198 PR (PS, "[%s+]", register_names[oper->reg]);
199 break;
200 case RX_Operand_Predec:
201 PR (PS, "[-%s]", register_names[oper->reg]);
202 break;
203 case RX_Operand_Condition:
204 PR (PS, "%s", condition_names[oper->reg]);
205 break;
206 case RX_Operand_Flag:
207 PR (PS, "%s", flag_names[oper->reg]);
208 break;
209 default:
210 PR (PS, "[???]");
211 break;
212 }
213 }
214 }
215 }
216
217 return rv;
218}
This page took 0.291759 seconds and 4 git commands to generate.