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