v850-dis.c revision 1.1 1 1.1 christos /* Disassemble V850 instructions.
2 1.1 christos Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010
3 1.1 christos Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of the GNU opcodes library.
6 1.1 christos
7 1.1 christos This library is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
13 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 christos License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; if not, write to the Free Software
19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 christos MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos
23 1.1 christos #include <stdio.h>
24 1.1 christos
25 1.1 christos #include "sysdep.h"
26 1.1 christos #include "opcode/v850.h"
27 1.1 christos #include "dis-asm.h"
28 1.1 christos #include "opintl.h"
29 1.1 christos
30 1.1 christos static const char *const v850_reg_names[] =
31 1.1 christos {
32 1.1 christos "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
33 1.1 christos "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
34 1.1 christos "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
35 1.1 christos "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
36 1.1 christos };
37 1.1 christos
38 1.1 christos static const char *const v850_sreg_names[] =
39 1.1 christos {
40 1.1 christos "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
41 1.1 christos "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
42 1.1 christos "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
43 1.1 christos "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
44 1.1 christos "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
45 1.1 christos "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
46 1.1 christos "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
47 1.1 christos "fewr", "dbwr", "bsel"
48 1.1 christos };
49 1.1 christos
50 1.1 christos static const char *const v850_cc_names[] =
51 1.1 christos {
52 1.1 christos "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
53 1.1 christos "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
54 1.1 christos };
55 1.1 christos
56 1.1 christos static const char *const v850_float_cc_names[] =
57 1.1 christos {
58 1.1 christos "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
59 1.1 christos "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
60 1.1 christos };
61 1.1 christos
62 1.1 christos
63 1.1 christos static void
64 1.1 christos print_value (int flags, bfd_vma memaddr, struct disassemble_info *info, long value)
65 1.1 christos {
66 1.1 christos if (flags & V850_PCREL)
67 1.1 christos {
68 1.1 christos bfd_vma addr = value + memaddr;
69 1.1 christos info->print_address_func (addr, info);
70 1.1 christos }
71 1.1 christos else if (flags & V850_OPERAND_DISP)
72 1.1 christos {
73 1.1 christos if (flags & V850_OPERAND_SIGNED)
74 1.1 christos {
75 1.1 christos info->fprintf_func (info->stream, "%ld", value);
76 1.1 christos }
77 1.1 christos else
78 1.1 christos {
79 1.1 christos info->fprintf_func (info->stream, "%lu", value);
80 1.1 christos }
81 1.1 christos }
82 1.1 christos else if (flags & V850E_IMMEDIATE32)
83 1.1 christos {
84 1.1 christos info->fprintf_func (info->stream, "0x%lx", value);
85 1.1 christos }
86 1.1 christos else
87 1.1 christos {
88 1.1 christos if (flags & V850_OPERAND_SIGNED)
89 1.1 christos {
90 1.1 christos info->fprintf_func (info->stream, "%ld", value);
91 1.1 christos }
92 1.1 christos else
93 1.1 christos {
94 1.1 christos info->fprintf_func (info->stream, "%lu", value);
95 1.1 christos }
96 1.1 christos }
97 1.1 christos }
98 1.1 christos
99 1.1 christos static long
100 1.1 christos get_operand_value (const struct v850_operand *operand,
101 1.1 christos unsigned long insn,
102 1.1 christos int bytes_read,
103 1.1 christos bfd_vma memaddr,
104 1.1 christos struct disassemble_info * info,
105 1.1 christos bfd_boolean noerror,
106 1.1 christos int *invalid)
107 1.1 christos {
108 1.1 christos long value;
109 1.1 christos bfd_byte buffer[4];
110 1.1 christos
111 1.1 christos if ((operand->flags & V850E_IMMEDIATE16)
112 1.1 christos || (operand->flags & V850E_IMMEDIATE16HI))
113 1.1 christos {
114 1.1 christos int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
115 1.1 christos
116 1.1 christos if (status == 0)
117 1.1 christos {
118 1.1 christos value = bfd_getl16 (buffer);
119 1.1 christos
120 1.1 christos if (operand->flags & V850E_IMMEDIATE16HI)
121 1.1 christos value <<= 16;
122 1.1 christos
123 1.1 christos return value;
124 1.1 christos }
125 1.1 christos
126 1.1 christos if (!noerror)
127 1.1 christos info->memory_error_func (status, memaddr + bytes_read, info);
128 1.1 christos
129 1.1 christos return 0;
130 1.1 christos }
131 1.1 christos
132 1.1 christos if (operand->flags & V850E_IMMEDIATE23)
133 1.1 christos {
134 1.1 christos int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
135 1.1 christos
136 1.1 christos if (status == 0)
137 1.1 christos {
138 1.1 christos value = bfd_getl32 (buffer);
139 1.1 christos
140 1.1 christos value = (operand->extract) (value, invalid);
141 1.1 christos
142 1.1 christos return value;
143 1.1 christos }
144 1.1 christos
145 1.1 christos if (!noerror)
146 1.1 christos info->memory_error_func (status, memaddr + bytes_read, info);
147 1.1 christos
148 1.1 christos return 0;
149 1.1 christos }
150 1.1 christos
151 1.1 christos if (operand->flags & V850E_IMMEDIATE32)
152 1.1 christos {
153 1.1 christos int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
154 1.1 christos
155 1.1 christos if (status == 0)
156 1.1 christos {
157 1.1 christos bytes_read += 4;
158 1.1 christos value = bfd_getl32 (buffer);
159 1.1 christos
160 1.1 christos return value;
161 1.1 christos }
162 1.1 christos
163 1.1 christos if (!noerror)
164 1.1 christos info->memory_error_func (status, memaddr + bytes_read, info);
165 1.1 christos
166 1.1 christos return 0;
167 1.1 christos }
168 1.1 christos
169 1.1 christos if (operand->extract)
170 1.1 christos value = (operand->extract) (insn, invalid);
171 1.1 christos else
172 1.1 christos {
173 1.1 christos if (operand->bits == -1)
174 1.1 christos value = (insn & operand->shift);
175 1.1 christos else
176 1.1 christos value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
177 1.1 christos
178 1.1 christos if (operand->flags & V850_OPERAND_SIGNED)
179 1.1 christos value = ((long)(value << (sizeof (long)*8 - operand->bits))
180 1.1 christos >> (sizeof (long)*8 - operand->bits));
181 1.1 christos }
182 1.1 christos
183 1.1 christos return value;
184 1.1 christos }
185 1.1 christos
186 1.1 christos
187 1.1 christos static int
188 1.1 christos disassemble (bfd_vma memaddr, struct disassemble_info *info, int bytes_read, unsigned long insn)
189 1.1 christos {
190 1.1 christos struct v850_opcode *op = (struct v850_opcode *)v850_opcodes;
191 1.1 christos const struct v850_operand *operand;
192 1.1 christos int match = 0;
193 1.1 christos int target_processor;
194 1.1 christos
195 1.1 christos switch (info->mach)
196 1.1 christos {
197 1.1 christos case 0:
198 1.1 christos default:
199 1.1 christos target_processor = PROCESSOR_V850;
200 1.1 christos break;
201 1.1 christos
202 1.1 christos case bfd_mach_v850e:
203 1.1 christos target_processor = PROCESSOR_V850E;
204 1.1 christos break;
205 1.1 christos
206 1.1 christos case bfd_mach_v850e1:
207 1.1 christos target_processor = PROCESSOR_V850E;
208 1.1 christos break;
209 1.1 christos
210 1.1 christos case bfd_mach_v850e2:
211 1.1 christos target_processor = PROCESSOR_V850E2;
212 1.1 christos break;
213 1.1 christos
214 1.1 christos case bfd_mach_v850e2v3:
215 1.1 christos target_processor = PROCESSOR_V850E2V3;
216 1.1 christos break;
217 1.1 christos }
218 1.1 christos
219 1.1 christos /* If this is a two byte insn, then mask off the high bits. */
220 1.1 christos if (bytes_read == 2)
221 1.1 christos insn &= 0xffff;
222 1.1 christos
223 1.1 christos /* Find the opcode. */
224 1.1 christos while (op->name)
225 1.1 christos {
226 1.1 christos if ((op->mask & insn) == op->opcode
227 1.1 christos && (op->processors & target_processor)
228 1.1 christos && !(op->processors & PROCESSOR_OPTION_ALIAS))
229 1.1 christos {
230 1.1 christos /* Code check start. */
231 1.1 christos const unsigned char *opindex_ptr;
232 1.1 christos unsigned int opnum;
233 1.1 christos unsigned int memop;
234 1.1 christos
235 1.1 christos for (opindex_ptr = op->operands, opnum = 1;
236 1.1 christos *opindex_ptr != 0;
237 1.1 christos opindex_ptr++, opnum++)
238 1.1 christos {
239 1.1 christos int invalid = 0;
240 1.1 christos long value;
241 1.1 christos
242 1.1 christos operand = &v850_operands[*opindex_ptr];
243 1.1 christos
244 1.1 christos value = get_operand_value (operand, insn, bytes_read, memaddr, info, 1, &invalid);
245 1.1 christos
246 1.1 christos if (invalid)
247 1.1 christos goto next_opcode;
248 1.1 christos
249 1.1 christos if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
250 1.1 christos goto next_opcode;
251 1.1 christos
252 1.1 christos if ((operand->flags & V850_NOT_SA) && value == 0xd)
253 1.1 christos goto next_opcode;
254 1.1 christos
255 1.1 christos if ((operand->flags & V850_NOT_IMM0) && value == 0)
256 1.1 christos goto next_opcode;
257 1.1 christos }
258 1.1 christos
259 1.1 christos /* Code check end. */
260 1.1 christos
261 1.1 christos match = 1;
262 1.1 christos (*info->fprintf_func) (info->stream, "%s\t", op->name);
263 1.1 christos #if 0
264 1.1 christos fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
265 1.1 christos insn, op->mask, op->opcode, op->name );
266 1.1 christos #endif
267 1.1 christos
268 1.1 christos memop = op->memop;
269 1.1 christos /* Now print the operands.
270 1.1 christos
271 1.1 christos MEMOP is the operand number at which a memory
272 1.1 christos address specification starts, or zero if this
273 1.1 christos instruction has no memory addresses.
274 1.1 christos
275 1.1 christos A memory address is always two arguments.
276 1.1 christos
277 1.1 christos This information allows us to determine when to
278 1.1 christos insert commas into the output stream as well as
279 1.1 christos when to insert disp[reg] expressions onto the
280 1.1 christos output stream. */
281 1.1 christos
282 1.1 christos for (opindex_ptr = op->operands, opnum = 1;
283 1.1 christos *opindex_ptr != 0;
284 1.1 christos opindex_ptr++, opnum++)
285 1.1 christos {
286 1.1 christos long value;
287 1.1 christos int flag;
288 1.1 christos char *prefix;
289 1.1 christos
290 1.1 christos operand = &v850_operands[*opindex_ptr];
291 1.1 christos
292 1.1 christos value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0);
293 1.1 christos
294 1.1 christos /* The first operand is always output without any
295 1.1 christos special handling.
296 1.1 christos
297 1.1 christos For the following arguments:
298 1.1 christos
299 1.1 christos If memop && opnum == memop + 1, then we need '[' since
300 1.1 christos we're about to output the register used in a memory
301 1.1 christos reference.
302 1.1 christos
303 1.1 christos If memop && opnum == memop + 2, then we need ']' since
304 1.1 christos we just finished the register in a memory reference. We
305 1.1 christos also need a ',' before this operand.
306 1.1 christos
307 1.1 christos Else we just need a comma.
308 1.1 christos
309 1.1 christos We may need to output a trailing ']' if the last operand
310 1.1 christos in an instruction is the register for a memory address.
311 1.1 christos
312 1.1 christos The exception (and there's always an exception) is the
313 1.1 christos "jmp" insn which needs square brackets around it's only
314 1.1 christos register argument. */
315 1.1 christos prefix = "";
316 1.1 christos if (operand->flags & V850_OPERAND_BANG)
317 1.1 christos {
318 1.1 christos prefix = "!";
319 1.1 christos }
320 1.1 christos else if (operand->flags & V850_OPERAND_PERCENT)
321 1.1 christos {
322 1.1 christos prefix = "%";
323 1.1 christos }
324 1.1 christos
325 1.1 christos if (opnum == 1 && opnum == memop)
326 1.1 christos info->fprintf_func (info->stream, "%s[", prefix);
327 1.1 christos else if (opnum > 1
328 1.1 christos && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0
329 1.1 christos && opnum == memop)
330 1.1 christos info->fprintf_func (info->stream, "%s[", prefix);
331 1.1 christos else if (opnum > 1)
332 1.1 christos info->fprintf_func (info->stream, ", %s", prefix);
333 1.1 christos
334 1.1 christos /* Extract the flags, ignoring ones which do not effect disassembly output. */
335 1.1 christos flag = operand->flags & (V850_OPERAND_REG
336 1.1 christos | V850_REG_EVEN
337 1.1 christos | V850_OPERAND_EP
338 1.1 christos | V850_OPERAND_SRG
339 1.1 christos | V850E_OPERAND_REG_LIST
340 1.1 christos | V850_OPERAND_CC
341 1.1 christos | V850_OPERAND_FLOAT_CC);
342 1.1 christos
343 1.1 christos switch (flag)
344 1.1 christos {
345 1.1 christos case V850_OPERAND_REG: info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
346 1.1 christos case (V850_OPERAND_REG|V850_REG_EVEN): info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break;
347 1.1 christos case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break;
348 1.1 christos case V850_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
349 1.1 christos
350 1.1 christos case V850E_OPERAND_REG_LIST:
351 1.1 christos {
352 1.1 christos static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
353 1.1 christos 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
354 1.1 christos int *regs;
355 1.1 christos int i;
356 1.1 christos unsigned long int mask = 0;
357 1.1 christos int pc = 0;
358 1.1 christos
359 1.1 christos
360 1.1 christos switch (operand->shift)
361 1.1 christos {
362 1.1 christos case 0xffe00001: regs = list12_regs; break;
363 1.1 christos default:
364 1.1 christos /* xgettext:c-format */
365 1.1 christos fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
366 1.1 christos abort ();
367 1.1 christos }
368 1.1 christos
369 1.1 christos for (i = 0; i < 32; i++)
370 1.1 christos {
371 1.1 christos if (value & (1 << i))
372 1.1 christos {
373 1.1 christos switch (regs[ i ])
374 1.1 christos {
375 1.1 christos default: mask |= (1 << regs[ i ]); break;
376 1.1 christos /* xgettext:c-format */
377 1.1 christos case 0: fprintf (stderr, _("unknown reg: %d\n"), i ); abort ();
378 1.1 christos case -1: pc = 1; break;
379 1.1 christos }
380 1.1 christos }
381 1.1 christos }
382 1.1 christos
383 1.1 christos info->fprintf_func (info->stream, "{");
384 1.1 christos
385 1.1 christos if (mask || pc)
386 1.1 christos {
387 1.1 christos if (mask)
388 1.1 christos {
389 1.1 christos unsigned int bit;
390 1.1 christos int shown_one = 0;
391 1.1 christos
392 1.1 christos for (bit = 0; bit < 32; bit++)
393 1.1 christos if (mask & (1 << bit))
394 1.1 christos {
395 1.1 christos unsigned long int first = bit;
396 1.1 christos unsigned long int last;
397 1.1 christos
398 1.1 christos if (shown_one)
399 1.1 christos info->fprintf_func (info->stream, ", ");
400 1.1 christos else
401 1.1 christos shown_one = 1;
402 1.1 christos
403 1.1 christos info->fprintf_func (info->stream, v850_reg_names[first]);
404 1.1 christos
405 1.1 christos for (bit++; bit < 32; bit++)
406 1.1 christos if ((mask & (1 << bit)) == 0)
407 1.1 christos break;
408 1.1 christos
409 1.1 christos last = bit;
410 1.1 christos
411 1.1 christos if (last > first + 1)
412 1.1 christos {
413 1.1 christos info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
414 1.1 christos }
415 1.1 christos }
416 1.1 christos }
417 1.1 christos
418 1.1 christos if (pc)
419 1.1 christos info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
420 1.1 christos }
421 1.1 christos
422 1.1 christos info->fprintf_func (info->stream, "}");
423 1.1 christos }
424 1.1 christos break;
425 1.1 christos
426 1.1 christos case V850_OPERAND_CC: info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
427 1.1 christos case V850_OPERAND_FLOAT_CC: info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break;
428 1.1 christos
429 1.1 christos default:
430 1.1 christos print_value (operand->flags, memaddr, info, value);
431 1.1 christos break;
432 1.1 christos }
433 1.1 christos
434 1.1 christos if (opnum == 2 && opnum == memop)
435 1.1 christos (*info->fprintf_func) (info->stream, "]");
436 1.1 christos }
437 1.1 christos
438 1.1 christos /* All done. */
439 1.1 christos break;
440 1.1 christos }
441 1.1 christos next_opcode:
442 1.1 christos op++;
443 1.1 christos }
444 1.1 christos
445 1.1 christos return match;
446 1.1 christos }
447 1.1 christos
448 1.1 christos int
449 1.1 christos print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
450 1.1 christos {
451 1.1 christos int status, status2, match;
452 1.1 christos bfd_byte buffer[8];
453 1.1 christos int length = 0, code_length = 0;
454 1.1 christos unsigned long insn = 0, insn2 = 0;
455 1.1 christos int target_processor;
456 1.1 christos
457 1.1 christos switch (info->mach)
458 1.1 christos {
459 1.1 christos case 0:
460 1.1 christos default:
461 1.1 christos target_processor = PROCESSOR_V850;
462 1.1 christos break;
463 1.1 christos
464 1.1 christos case bfd_mach_v850e:
465 1.1 christos target_processor = PROCESSOR_V850E;
466 1.1 christos break;
467 1.1 christos
468 1.1 christos case bfd_mach_v850e1:
469 1.1 christos target_processor = PROCESSOR_V850E;
470 1.1 christos break;
471 1.1 christos
472 1.1 christos case bfd_mach_v850e2:
473 1.1 christos target_processor = PROCESSOR_V850E2;
474 1.1 christos break;
475 1.1 christos
476 1.1 christos case bfd_mach_v850e2v3:
477 1.1 christos target_processor = PROCESSOR_V850E2V3;
478 1.1 christos break;
479 1.1 christos }
480 1.1 christos
481 1.1 christos status = info->read_memory_func (memaddr, buffer, 2, info);
482 1.1 christos
483 1.1 christos if (status)
484 1.1 christos {
485 1.1 christos info->memory_error_func (status, memaddr, info);
486 1.1 christos return -1;
487 1.1 christos }
488 1.1 christos
489 1.1 christos insn = bfd_getl16 (buffer);
490 1.1 christos
491 1.1 christos status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
492 1.1 christos
493 1.1 christos if (!status2)
494 1.1 christos {
495 1.1 christos insn2 = bfd_getl16 (buffer);
496 1.1 christos /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
497 1.1 christos }
498 1.1 christos
499 1.1 christos /* Special case. */
500 1.1 christos if (length == 0
501 1.1 christos && (target_processor == PROCESSOR_V850E2
502 1.1 christos || target_processor == PROCESSOR_V850E2V3))
503 1.1 christos {
504 1.1 christos if ((insn & 0xffff) == 0x02e0 /* jr 32bit */
505 1.1 christos && !status2 && (insn2 & 0x1) == 0)
506 1.1 christos {
507 1.1 christos length = 2;
508 1.1 christos code_length = 6;
509 1.1 christos }
510 1.1 christos else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */
511 1.1 christos && !status2 && (insn2 & 0x1) == 0)
512 1.1 christos {
513 1.1 christos length = 2;
514 1.1 christos code_length = 6;
515 1.1 christos }
516 1.1 christos else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */
517 1.1 christos && !status2 && (insn2 & 0x1) == 0)
518 1.1 christos {
519 1.1 christos length = 2;
520 1.1 christos code_length = 6;
521 1.1 christos }
522 1.1 christos }
523 1.1 christos
524 1.1 christos if (length == 0
525 1.1 christos && target_processor == PROCESSOR_V850E2V3)
526 1.1 christos {
527 1.1 christos if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */
528 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0005)
529 1.1 christos || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */
530 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0005)
531 1.1 christos || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */
532 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0007)
533 1.1 christos || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */
534 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0007)
535 1.1 christos || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */
536 1.1 christos && !status2 && (insn2 & 0x000f) == 0x0009))
537 1.1 christos {
538 1.1 christos length = 4;
539 1.1 christos code_length = 6;
540 1.1 christos }
541 1.1 christos else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */
542 1.1 christos && !status2 && (insn2 & 0x000f) == 0x000d)
543 1.1 christos || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */
544 1.1 christos && !status2 && (insn2 & 0x000f) == 0x000d)
545 1.1 christos || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */
546 1.1 christos && !status2 && (insn2 & 0x000f) == 0x000f))
547 1.1 christos {
548 1.1 christos length = 4;
549 1.1 christos code_length = 6;
550 1.1 christos }
551 1.1 christos }
552 1.1 christos
553 1.1 christos if (length == 0
554 1.1 christos && target_processor != PROCESSOR_V850)
555 1.1 christos {
556 1.1 christos if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */
557 1.1 christos {
558 1.1 christos length = 2;
559 1.1 christos code_length = 6;
560 1.1 christos }
561 1.1 christos else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */
562 1.1 christos && !status2 && (insn2 & 0x001f) == 0x0013)
563 1.1 christos {
564 1.1 christos length = 4;
565 1.1 christos code_length = 6;
566 1.1 christos }
567 1.1 christos else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */
568 1.1 christos && !status2 && (insn2 & 0x001f) == 0x000b)
569 1.1 christos {
570 1.1 christos length = 4;
571 1.1 christos code_length = 6;
572 1.1 christos }
573 1.1 christos else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */
574 1.1 christos && !status2 && (insn2 & 0x001f) == 0x001b)
575 1.1 christos {
576 1.1 christos length = 4;
577 1.1 christos code_length = 8;
578 1.1 christos }
579 1.1 christos }
580 1.1 christos
581 1.1 christos if (length == 4
582 1.1 christos || (length == 0
583 1.1 christos && (insn & 0x0600) == 0x0600))
584 1.1 christos {
585 1.1 christos /* This is a 4 byte insn. */
586 1.1 christos status = info->read_memory_func (memaddr, buffer, 4, info);
587 1.1 christos if (!status)
588 1.1 christos {
589 1.1 christos insn = bfd_getl32 (buffer);
590 1.1 christos
591 1.1 christos if (!length)
592 1.1 christos length = code_length = 4;
593 1.1 christos }
594 1.1 christos }
595 1.1 christos
596 1.1 christos if (code_length > length)
597 1.1 christos {
598 1.1 christos status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
599 1.1 christos if (status)
600 1.1 christos length = 0;
601 1.1 christos }
602 1.1 christos
603 1.1 christos if (length == 0 && !status)
604 1.1 christos length = code_length = 2;
605 1.1 christos
606 1.1 christos if (length == 2)
607 1.1 christos insn &= 0xffff;
608 1.1 christos
609 1.1 christos match = disassemble (memaddr, info, length, insn);
610 1.1 christos
611 1.1 christos if (!match)
612 1.1 christos {
613 1.1 christos int l = 0;
614 1.1 christos
615 1.1 christos status = info->read_memory_func (memaddr, buffer, code_length, info);
616 1.1 christos
617 1.1 christos while (l < code_length)
618 1.1 christos {
619 1.1 christos if (code_length - l == 2)
620 1.1 christos {
621 1.1 christos insn = bfd_getl16 (buffer + l) & 0xffff;
622 1.1 christos info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
623 1.1 christos l += 2;
624 1.1 christos }
625 1.1 christos else
626 1.1 christos {
627 1.1 christos insn = bfd_getl32 (buffer + l);
628 1.1 christos info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
629 1.1 christos l += 4;
630 1.1 christos }
631 1.1 christos }
632 1.1 christos }
633 1.1 christos
634 1.1 christos return code_length;
635 1.1 christos }
636