]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/d10v-dis.c
include/opcode/
[thirdparty/binutils-gdb.git] / opcodes / d10v-dis.c
CommitLineData
252b5132 1/* Disassemble D10V instructions.
df7b86aa 2 Copyright 1996, 1997, 1998, 2000, 2001, 2005, 2007, 2012
9b201bb5 3 Free Software Foundation, Inc.
252b5132 4
9b201bb5
NC
5 This file is part of the GNU opcodes library.
6
7 This library is free software; you can redistribute it and/or modify
47b0e7ad 8 it under the terms of the GNU General Public License as published by
9b201bb5
NC
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
252b5132 11
9b201bb5
NC
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.
252b5132 16
47b0e7ad
NC
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. */
252b5132 21
0d8dfecf 22#include "sysdep.h"
df7b86aa 23#include <stdio.h>
2dcee538 24#include "opcode/d10v.h"
252b5132
RH
25#include "dis-asm.h"
26
2dcee538
KH
27/* The PC wraps at 18 bits, except for the segment number,
28 so use this mask to keep the parts we want. */
252b5132
RH
29#define PC_MASK 0x0303FFFF
30
252b5132 31static void
47b0e7ad
NC
32print_operand (struct d10v_operand *oper,
33 unsigned long insn,
34 struct d10v_opcode *op,
35 bfd_vma memaddr,
36 struct disassemble_info *info)
252b5132
RH
37{
38 int num, shift;
39
40 if (oper->flags == OPERAND_ATMINUS)
41 {
2dcee538 42 (*info->fprintf_func) (info->stream, "@-");
252b5132
RH
43 return;
44 }
45 if (oper->flags == OPERAND_MINUS)
46 {
2dcee538 47 (*info->fprintf_func) (info->stream, "-");
252b5132
RH
48 return;
49 }
50 if (oper->flags == OPERAND_PLUS)
51 {
2dcee538 52 (*info->fprintf_func) (info->stream, "+");
252b5132
RH
53 return;
54 }
55 if (oper->flags == OPERAND_ATSIGN)
56 {
2dcee538 57 (*info->fprintf_func) (info->stream, "@");
252b5132
RH
58 return;
59 }
60 if (oper->flags == OPERAND_ATPAR)
61 {
2dcee538 62 (*info->fprintf_func) (info->stream, "@(");
252b5132
RH
63 return;
64 }
65
66 shift = oper->shift;
67
2dcee538 68 /* The LONG_L format shifts registers over by 15. */
252b5132
RH
69 if (op->format == LONG_L && (oper->flags & OPERAND_REG))
70 shift += 15;
71
72 num = (insn >> shift) & (0x7FFFFFFF >> (31 - oper->bits));
73
74 if (oper->flags & OPERAND_REG)
75 {
76 int i;
2dcee538 77 int match = 0;
47b0e7ad 78
252b5132 79 num += (oper->flags
2dcee538
KH
80 & (OPERAND_GPR | OPERAND_FFLAG | OPERAND_CFLAG | OPERAND_CONTROL));
81 if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
252b5132 82 num += num ? OPERAND_ACC1 : OPERAND_ACC0;
2dcee538 83 for (i = 0; i < d10v_reg_name_cnt (); i++)
252b5132 84 {
d1267250 85 if (num == (d10v_predefined_registers[i].value & ~ OPERAND_SP))
252b5132
RH
86 {
87 if (d10v_predefined_registers[i].pname)
2dcee538
KH
88 (*info->fprintf_func) (info->stream, "%s",
89 d10v_predefined_registers[i].pname);
252b5132 90 else
2dcee538
KH
91 (*info->fprintf_func) (info->stream, "%s",
92 d10v_predefined_registers[i].name);
93 match = 1;
252b5132
RH
94 break;
95 }
96 }
97 if (match == 0)
98 {
2dcee538
KH
99 /* This would only get executed if a register was not in the
100 register table. */
101 if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
252b5132
RH
102 (*info->fprintf_func) (info->stream, "a");
103 else if (oper->flags & OPERAND_CONTROL)
104 (*info->fprintf_func) (info->stream, "cr");
2dcee538 105 else if (oper->flags & OPERAND_REG)
252b5132 106 (*info->fprintf_func) (info->stream, "r");
373efcb3 107 (*info->fprintf_func) (info->stream, "%d", num & REGISTER_MASK);
252b5132
RH
108 }
109 }
110 else
111 {
2dcee538 112 /* Addresses are right-shifted by 2. */
252b5132
RH
113 if (oper->flags & OPERAND_ADDR)
114 {
115 long max;
2dcee538 116 int neg = 0;
47b0e7ad 117
252b5132
RH
118 max = (1 << (oper->bits - 1));
119 if (num & max)
120 {
2dcee538 121 num = -num & ((1 << oper->bits) - 1);
252b5132
RH
122 neg = 1;
123 }
2dcee538 124 num = num << 2;
252b5132
RH
125 if (info->flags & INSN_HAS_RELOC)
126 (*info->print_address_func) (num & PC_MASK, info);
127 else
128 {
129 if (neg)
130 (*info->print_address_func) ((memaddr - num) & PC_MASK, info);
131 else
132 (*info->print_address_func) ((memaddr + num) & PC_MASK, info);
133 }
134 }
135 else
136 {
137 if (oper->flags & OPERAND_SIGNED)
138 {
139 int max = (1 << (oper->bits - 1));
140 if (num & max)
141 {
2dcee538 142 num = -num & ((1 << oper->bits) - 1);
252b5132
RH
143 (*info->fprintf_func) (info->stream, "-");
144 }
145 }
2dcee538 146 (*info->fprintf_func) (info->stream, "0x%x", num);
252b5132
RH
147 }
148 }
149}
150
252b5132 151static void
47b0e7ad
NC
152dis_long (unsigned long insn,
153 bfd_vma memaddr,
154 struct disassemble_info *info)
252b5132
RH
155{
156 int i;
2dcee538 157 struct d10v_opcode *op = (struct d10v_opcode *) d10v_opcodes;
252b5132
RH
158 struct d10v_operand *oper;
159 int need_paren = 0;
160 int match = 0;
161
162 while (op->name)
163 {
47b0e7ad
NC
164 if ((op->format & LONG_OPCODE)
165 && ((op->mask & insn) == (unsigned long) op->opcode))
252b5132
RH
166 {
167 match = 1;
2dcee538 168 (*info->fprintf_func) (info->stream, "%s\t", op->name);
47b0e7ad 169
2dcee538 170 for (i = 0; op->operands[i]; i++)
252b5132 171 {
2dcee538 172 oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
252b5132
RH
173 if (oper->flags == OPERAND_ATPAR)
174 need_paren = 1;
175 print_operand (oper, insn, op, memaddr, info);
2dcee538
KH
176 if (op->operands[i + 1] && oper->bits
177 && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
178 && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
179 (*info->fprintf_func) (info->stream, ", ");
252b5132
RH
180 }
181 break;
182 }
183 op++;
184 }
185
186 if (!match)
0fd3a477 187 (*info->fprintf_func) (info->stream, ".long\t0x%08lx", insn);
252b5132
RH
188
189 if (need_paren)
2dcee538 190 (*info->fprintf_func) (info->stream, ")");
252b5132
RH
191}
192
193static void
47b0e7ad
NC
194dis_2_short (unsigned long insn,
195 bfd_vma memaddr,
196 struct disassemble_info *info,
197 int order)
252b5132 198{
2dcee538 199 int i, j;
252b5132
RH
200 unsigned int ins[2];
201 struct d10v_opcode *op;
2dcee538 202 int match, num_match = 0;
252b5132
RH
203 struct d10v_operand *oper;
204 int need_paren = 0;
205
206 ins[0] = (insn & 0x3FFFFFFF) >> 15;
207 ins[1] = insn & 0x00007FFF;
208
2dcee538 209 for (j = 0; j < 2; j++)
252b5132 210 {
2dcee538
KH
211 op = (struct d10v_opcode *) d10v_opcodes;
212 match = 0;
252b5132
RH
213 while (op->name)
214 {
2dcee538 215 if ((op->format & SHORT_OPCODE)
920a34a7
L
216 && ((((unsigned int) op->mask) & ins[j])
217 == (unsigned int) op->opcode))
252b5132 218 {
2dcee538
KH
219 (*info->fprintf_func) (info->stream, "%s\t", op->name);
220 for (i = 0; op->operands[i]; i++)
252b5132 221 {
2dcee538 222 oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
252b5132
RH
223 if (oper->flags == OPERAND_ATPAR)
224 need_paren = 1;
225 print_operand (oper, ins[j], op, memaddr, info);
2dcee538
KH
226 if (op->operands[i + 1] && oper->bits
227 && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
228 && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
229 (*info->fprintf_func) (info->stream, ", ");
252b5132
RH
230 }
231 match = 1;
232 num_match++;
233 break;
234 }
235 op++;
236 }
237 if (!match)
2dcee538 238 (*info->fprintf_func) (info->stream, "unknown");
252b5132
RH
239
240 switch (order)
241 {
242 case 0:
2dcee538 243 (*info->fprintf_func) (info->stream, "\t->\t");
252b5132
RH
244 order = -1;
245 break;
246 case 1:
2dcee538 247 (*info->fprintf_func) (info->stream, "\t<-\t");
252b5132
RH
248 order = -1;
249 break;
250 case 2:
2dcee538 251 (*info->fprintf_func) (info->stream, "\t||\t");
252b5132
RH
252 order = -1;
253 break;
254 default:
255 break;
256 }
257 }
258
259 if (num_match == 0)
0fd3a477 260 (*info->fprintf_func) (info->stream, ".long\t0x%08lx", insn);
252b5132
RH
261
262 if (need_paren)
2dcee538 263 (*info->fprintf_func) (info->stream, ")");
252b5132 264}
47b0e7ad
NC
265
266int
267print_insn_d10v (bfd_vma memaddr, struct disassemble_info *info)
268{
269 int status;
270 bfd_byte buffer[4];
271 unsigned long insn;
272
273 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
274 if (status != 0)
275 {
276 (*info->memory_error_func) (status, memaddr, info);
277 return -1;
278 }
279 insn = bfd_getb32 (buffer);
280
281 status = insn & FM11;
282 switch (status)
283 {
284 case 0:
285 dis_2_short (insn, memaddr, info, 2);
286 break;
287 case FM01:
288 dis_2_short (insn, memaddr, info, 0);
289 break;
290 case FM10:
291 dis_2_short (insn, memaddr, info, 1);
292 break;
293 case FM11:
294 dis_long (insn, memaddr, info);
295 break;
296 }
297 return 4;
298}