m68k-dis.c revision 1.11 1 1.1 christos /* Print Motorola 68k instructions.
2 1.11 christos Copyright (C) 1986-2024 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of the GNU opcodes library.
5 1.1 christos
6 1.1 christos This library is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3, or (at your option)
9 1.1 christos any later version.
10 1.1 christos
11 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
12 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 1.1 christos License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; if not, write to the Free Software
18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 1.1 christos MA 02110-1301, USA. */
20 1.1 christos
21 1.1 christos #include "sysdep.h"
22 1.8 christos #include "disassemble.h"
23 1.1 christos #include "floatformat.h"
24 1.1 christos #include "libiberty.h"
25 1.1 christos #include "opintl.h"
26 1.9 christos #include "cpu-m68k.h"
27 1.1 christos #include "opcode/m68k.h"
28 1.1 christos
29 1.1 christos /* Local function prototypes. */
30 1.1 christos
31 1.1 christos const char * const fpcr_names[] =
32 1.1 christos {
33 1.1 christos "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr",
34 1.1 christos "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr"
35 1.1 christos };
36 1.1 christos
37 1.1 christos static char *const reg_names[] =
38 1.1 christos {
39 1.1 christos "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
40 1.1 christos "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",
41 1.1 christos "%ps", "%pc"
42 1.1 christos };
43 1.1 christos
44 1.1 christos /* Name of register halves for MAC/EMAC.
45 1.1 christos Seperate from reg_names since 'spu', 'fpl' look weird. */
46 1.1 christos static char *const reg_half_names[] =
47 1.1 christos {
48 1.1 christos "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
49 1.1 christos "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
50 1.1 christos "%ps", "%pc"
51 1.1 christos };
52 1.1 christos
53 1.1 christos /* Sign-extend an (unsigned char). */
54 1.1 christos #if __STDC__ == 1
55 1.1 christos #define COERCE_SIGNED_CHAR(ch) ((signed char) (ch))
56 1.1 christos #else
57 1.1 christos #define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128)
58 1.1 christos #endif
59 1.1 christos
60 1.7 christos /* Error code of print_insn_arg's return value. */
61 1.7 christos
62 1.7 christos enum print_insn_arg_error
63 1.7 christos {
64 1.7 christos /* An invalid operand is found. */
65 1.7 christos PRINT_INSN_ARG_INVALID_OPERAND = -1,
66 1.7 christos
67 1.7 christos /* An opcode table error. */
68 1.7 christos PRINT_INSN_ARG_INVALID_OP_TABLE = -2,
69 1.7 christos
70 1.7 christos /* A memory error. */
71 1.7 christos PRINT_INSN_ARG_MEMORY_ERROR = -3,
72 1.7 christos };
73 1.7 christos
74 1.1 christos /* Get a 1 byte signed integer. */
75 1.1 christos #define NEXTBYTE(p, val) \
76 1.1 christos do \
77 1.1 christos { \
78 1.1 christos p += 2; \
79 1.1 christos if (!FETCH_DATA (info, p)) \
80 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \
81 1.1 christos val = COERCE_SIGNED_CHAR (p[-1]); \
82 1.1 christos } \
83 1.1 christos while (0)
84 1.1 christos
85 1.1 christos /* Get a 2 byte signed integer. */
86 1.1 christos #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
87 1.1 christos
88 1.1 christos #define NEXTWORD(p, val, ret_val) \
89 1.1 christos do \
90 1.1 christos { \
91 1.1 christos p += 2; \
92 1.1 christos if (!FETCH_DATA (info, p)) \
93 1.1 christos return ret_val; \
94 1.1 christos val = COERCE16 ((p[-2] << 8) + p[-1]); \
95 1.1 christos } \
96 1.6 christos while (0)
97 1.1 christos
98 1.1 christos /* Get a 4 byte signed integer. */
99 1.9 christos #define COERCE32(x) (((bfd_vma) (x) ^ 0x80000000) - 0x80000000)
100 1.1 christos
101 1.1 christos #define NEXTLONG(p, val, ret_val) \
102 1.1 christos do \
103 1.1 christos { \
104 1.1 christos p += 4; \
105 1.1 christos if (!FETCH_DATA (info, p)) \
106 1.1 christos return ret_val; \
107 1.9 christos val = COERCE32 (((((((unsigned) p[-4] << 8) + p[-3]) << 8) \
108 1.9 christos + p[-2]) << 8) + p[-1]); \
109 1.1 christos } \
110 1.1 christos while (0)
111 1.1 christos
112 1.1 christos /* Get a 4 byte unsigned integer. */
113 1.1 christos #define NEXTULONG(p, val) \
114 1.1 christos do \
115 1.1 christos { \
116 1.1 christos p += 4; \
117 1.1 christos if (!FETCH_DATA (info, p)) \
118 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \
119 1.9 christos val = (((((((unsigned) p[-4] << 8) + p[-3]) << 8) \
120 1.9 christos + p[-2]) << 8) + p[-1]); \
121 1.1 christos } \
122 1.1 christos while (0)
123 1.1 christos
124 1.1 christos /* Get a single precision float. */
125 1.1 christos #define NEXTSINGLE(val, p) \
126 1.1 christos do \
127 1.1 christos { \
128 1.1 christos p += 4; \
129 1.1 christos if (!FETCH_DATA (info, p)) \
130 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \
131 1.1 christos floatformat_to_double (& floatformat_ieee_single_big, \
132 1.1 christos (char *) p - 4, & val); \
133 1.1 christos } \
134 1.1 christos while (0)
135 1.1 christos
136 1.1 christos /* Get a double precision float. */
137 1.1 christos #define NEXTDOUBLE(val, p) \
138 1.1 christos do \
139 1.1 christos { \
140 1.1 christos p += 8; \
141 1.1 christos if (!FETCH_DATA (info, p)) \
142 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \
143 1.1 christos floatformat_to_double (& floatformat_ieee_double_big, \
144 1.1 christos (char *) p - 8, & val); \
145 1.1 christos } \
146 1.1 christos while (0)
147 1.1 christos
148 1.1 christos /* Get an extended precision float. */
149 1.1 christos #define NEXTEXTEND(val, p) \
150 1.1 christos do \
151 1.1 christos { \
152 1.1 christos p += 12; \
153 1.1 christos if (!FETCH_DATA (info, p)) \
154 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \
155 1.1 christos floatformat_to_double (& floatformat_m68881_ext, \
156 1.1 christos (char *) p - 12, & val); \
157 1.1 christos } \
158 1.1 christos while (0)
159 1.1 christos
160 1.1 christos /* Need a function to convert from packed to double
161 1.1 christos precision. Actually, it's easier to print a
162 1.1 christos packed number than a double anyway, so maybe
163 1.1 christos there should be a special case to handle this... */
164 1.1 christos #define NEXTPACKED(p, val) \
165 1.1 christos do \
166 1.1 christos { \
167 1.1 christos p += 12; \
168 1.1 christos if (!FETCH_DATA (info, p)) \
169 1.7 christos return PRINT_INSN_ARG_MEMORY_ERROR; \
170 1.1 christos val = 0.0; \
171 1.1 christos } \
172 1.1 christos while (0)
173 1.1 christos
174 1.1 christos
175 1.1 christos /* Maximum length of an instruction. */
177 1.1 christos #define MAXLEN 22
178 1.1 christos
179 1.1 christos struct private
180 1.1 christos {
181 1.1 christos /* Points to first byte not fetched. */
182 1.1 christos bfd_byte *max_fetched;
183 1.1 christos bfd_byte the_buffer[MAXLEN];
184 1.1 christos bfd_vma insn_start;
185 1.1 christos };
186 1.1 christos
187 1.7 christos /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
188 1.7 christos to ADDR (exclusive) are valid. Returns 1 for success, 0 on memory
189 1.1 christos error. */
190 1.1 christos #define FETCH_DATA(info, addr) \
191 1.1 christos ((addr) <= ((struct private *) (info->private_data))->max_fetched \
192 1.1 christos ? 1 : fetch_data ((info), (addr)))
193 1.1 christos
194 1.1 christos static int
195 1.1 christos fetch_data (struct disassemble_info *info, bfd_byte *addr)
196 1.1 christos {
197 1.1 christos int status;
198 1.1 christos struct private *priv = (struct private *)info->private_data;
199 1.1 christos bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
200 1.1 christos
201 1.1 christos status = (*info->read_memory_func) (start,
202 1.1 christos priv->max_fetched,
203 1.1 christos addr - priv->max_fetched,
204 1.1 christos info);
205 1.1 christos if (status != 0)
206 1.1 christos {
207 1.1 christos (*info->memory_error_func) (status, start, info);
208 1.1 christos return 0;
209 1.1 christos }
210 1.1 christos else
211 1.1 christos priv->max_fetched = addr;
212 1.1 christos return 1;
213 1.1 christos }
214 1.1 christos
215 1.1 christos /* This function is used to print to the bit-bucket. */
217 1.11 christos static int
218 1.1 christos dummy_printer (void *file ATTRIBUTE_UNUSED,
219 1.1 christos enum disassembler_style style ATTRIBUTE_UNUSED,
220 1.1 christos const char *format ATTRIBUTE_UNUSED,
221 1.1 christos ...)
222 1.1 christos {
223 1.1 christos return 0;
224 1.1 christos }
225 1.1 christos
226 1.1 christos static void
227 1.1 christos dummy_print_address (bfd_vma vma ATTRIBUTE_UNUSED,
228 1.1 christos struct disassemble_info *info ATTRIBUTE_UNUSED)
229 1.1 christos {
230 1.1 christos }
231 1.1 christos
232 1.1 christos /* Fetch BITS bits from a position in the instruction specified by CODE.
233 1.1 christos CODE is a "place to put an argument", or 'x' for a destination
234 1.1 christos that is a general address (mode and register).
235 1.1 christos BUFFER contains the instruction.
236 1.1 christos Returns -1 on failure. */
237 1.1 christos
238 1.1 christos static int
239 1.1 christos fetch_arg (unsigned char *buffer,
240 1.1 christos int code,
241 1.1 christos int bits,
242 1.1 christos disassemble_info *info)
243 1.1 christos {
244 1.1 christos int val = 0;
245 1.1 christos
246 1.1 christos switch (code)
247 1.1 christos {
248 1.1 christos case '/': /* MAC/EMAC mask bit. */
249 1.1 christos val = buffer[3] >> 5;
250 1.1 christos break;
251 1.1 christos
252 1.1 christos case 'G': /* EMAC ACC load. */
253 1.1 christos val = ((buffer[3] >> 3) & 0x2) | ((~buffer[1] >> 7) & 0x1);
254 1.1 christos break;
255 1.1 christos
256 1.1 christos case 'H': /* EMAC ACC !load. */
257 1.1 christos val = ((buffer[3] >> 3) & 0x2) | ((buffer[1] >> 7) & 0x1);
258 1.1 christos break;
259 1.1 christos
260 1.1 christos case ']': /* EMAC ACCEXT bit. */
261 1.1 christos val = buffer[0] >> 2;
262 1.1 christos break;
263 1.1 christos
264 1.1 christos case 'I': /* MAC/EMAC scale factor. */
265 1.1 christos val = buffer[2] >> 1;
266 1.1 christos break;
267 1.1 christos
268 1.1 christos case 'F': /* EMAC ACCx. */
269 1.1 christos val = buffer[0] >> 1;
270 1.1 christos break;
271 1.1 christos
272 1.1 christos case 'f':
273 1.1 christos val = buffer[1];
274 1.1 christos break;
275 1.1 christos
276 1.1 christos case 's':
277 1.1 christos val = buffer[1];
278 1.1 christos break;
279 1.1 christos
280 1.1 christos case 'd': /* Destination, for register or quick. */
281 1.1 christos val = (buffer[0] << 8) + buffer[1];
282 1.1 christos val >>= 9;
283 1.1 christos break;
284 1.1 christos
285 1.1 christos case 'x': /* Destination, for general arg. */
286 1.1 christos val = (buffer[0] << 8) + buffer[1];
287 1.1 christos val >>= 6;
288 1.1 christos break;
289 1.1 christos
290 1.1 christos case 'k':
291 1.1 christos if (! FETCH_DATA (info, buffer + 3))
292 1.1 christos return -1;
293 1.1 christos val = (buffer[3] >> 4);
294 1.1 christos break;
295 1.1 christos
296 1.1 christos case 'C':
297 1.1 christos if (! FETCH_DATA (info, buffer + 3))
298 1.1 christos return -1;
299 1.1 christos val = buffer[3];
300 1.1 christos break;
301 1.1 christos
302 1.1 christos case '1':
303 1.1 christos if (! FETCH_DATA (info, buffer + 3))
304 1.1 christos return -1;
305 1.1 christos val = (buffer[2] << 8) + buffer[3];
306 1.1 christos val >>= 12;
307 1.1 christos break;
308 1.1 christos
309 1.1 christos case '2':
310 1.1 christos if (! FETCH_DATA (info, buffer + 3))
311 1.1 christos return -1;
312 1.1 christos val = (buffer[2] << 8) + buffer[3];
313 1.1 christos val >>= 6;
314 1.1 christos break;
315 1.1 christos
316 1.1 christos case '3':
317 1.1 christos case 'j':
318 1.1 christos if (! FETCH_DATA (info, buffer + 3))
319 1.1 christos return -1;
320 1.1 christos val = (buffer[2] << 8) + buffer[3];
321 1.1 christos break;
322 1.1 christos
323 1.1 christos case '4':
324 1.1 christos if (! FETCH_DATA (info, buffer + 5))
325 1.1 christos return -1;
326 1.1 christos val = (buffer[4] << 8) + buffer[5];
327 1.1 christos val >>= 12;
328 1.1 christos break;
329 1.1 christos
330 1.1 christos case '5':
331 1.1 christos if (! FETCH_DATA (info, buffer + 5))
332 1.1 christos return -1;
333 1.1 christos val = (buffer[4] << 8) + buffer[5];
334 1.1 christos val >>= 6;
335 1.1 christos break;
336 1.1 christos
337 1.1 christos case '6':
338 1.1 christos if (! FETCH_DATA (info, buffer + 5))
339 1.1 christos return -1;
340 1.1 christos val = (buffer[4] << 8) + buffer[5];
341 1.1 christos break;
342 1.1 christos
343 1.1 christos case '7':
344 1.1 christos if (! FETCH_DATA (info, buffer + 3))
345 1.1 christos return -1;
346 1.1 christos val = (buffer[2] << 8) + buffer[3];
347 1.1 christos val >>= 7;
348 1.1 christos break;
349 1.1 christos
350 1.1 christos case '8':
351 1.1 christos if (! FETCH_DATA (info, buffer + 3))
352 1.1 christos return -1;
353 1.1 christos val = (buffer[2] << 8) + buffer[3];
354 1.1 christos val >>= 10;
355 1.1 christos break;
356 1.1 christos
357 1.1 christos case '9':
358 1.1 christos if (! FETCH_DATA (info, buffer + 3))
359 1.1 christos return -1;
360 1.1 christos val = (buffer[2] << 8) + buffer[3];
361 1.1 christos val >>= 5;
362 1.1 christos break;
363 1.1 christos
364 1.1 christos case 'e':
365 1.1 christos val = (buffer[1] >> 6);
366 1.1 christos break;
367 1.1 christos
368 1.1 christos case 'E':
369 1.1 christos if (! FETCH_DATA (info, buffer + 3))
370 1.1 christos return -1;
371 1.1 christos val = (buffer[2] >> 1);
372 1.1 christos break;
373 1.1 christos
374 1.1 christos case 'm':
375 1.1 christos val = (buffer[1] & 0x40 ? 0x8 : 0)
376 1.1 christos | ((buffer[0] >> 1) & 0x7)
377 1.1 christos | (buffer[3] & 0x80 ? 0x10 : 0);
378 1.1 christos break;
379 1.1 christos
380 1.1 christos case 'n':
381 1.1 christos val = (buffer[1] & 0x40 ? 0x8 : 0) | ((buffer[0] >> 1) & 0x7);
382 1.1 christos break;
383 1.1 christos
384 1.1 christos case 'o':
385 1.1 christos val = (buffer[2] >> 4) | (buffer[3] & 0x80 ? 0x10 : 0);
386 1.1 christos break;
387 1.1 christos
388 1.1 christos case 'M':
389 1.1 christos val = (buffer[1] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
390 1.1 christos break;
391 1.1 christos
392 1.1 christos case 'N':
393 1.1 christos val = (buffer[3] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
394 1.1 christos break;
395 1.1 christos
396 1.1 christos case 'h':
397 1.1 christos val = buffer[2] >> 2;
398 1.1 christos break;
399 1.1 christos
400 1.1 christos default:
401 1.1 christos abort ();
402 1.1 christos }
403 1.1 christos
404 1.1 christos /* bits is never too big. */
405 1.1 christos return val & ((1 << bits) - 1);
406 1.1 christos }
407 1.1 christos
408 1.1 christos /* Check if an EA is valid for a particular code. This is required
409 1.1 christos for the EMAC instructions since the type of source address determines
410 1.1 christos if it is a EMAC-load instruciton if the EA is mode 2-5, otherwise it
411 1.1 christos is a non-load EMAC instruction and the bits mean register Ry.
412 1.1 christos A similar case exists for the movem instructions where the register
413 1.10 christos mask is interpreted differently for different EAs. */
414 1.1 christos
415 1.1 christos static bool
416 1.1 christos m68k_valid_ea (char code, int val)
417 1.1 christos {
418 1.1 christos int mode, mask;
419 1.1 christos #define M(n0,n1,n2,n3,n4,n5,n6,n70,n71,n72,n73,n74) \
420 1.1 christos (n0 | n1 << 1 | n2 << 2 | n3 << 3 | n4 << 4 | n5 << 5 | n6 << 6 \
421 1.1 christos | n70 << 7 | n71 << 8 | n72 << 9 | n73 << 10 | n74 << 11)
422 1.1 christos
423 1.1 christos switch (code)
424 1.1 christos {
425 1.1 christos case '*':
426 1.1 christos mask = M (1,1,1,1,1,1,1,1,1,1,1,1);
427 1.1 christos break;
428 1.1 christos case '~':
429 1.1 christos mask = M (0,0,1,1,1,1,1,1,1,0,0,0);
430 1.1 christos break;
431 1.1 christos case '%':
432 1.1 christos mask = M (1,1,1,1,1,1,1,1,1,0,0,0);
433 1.1 christos break;
434 1.1 christos case ';':
435 1.1 christos mask = M (1,0,1,1,1,1,1,1,1,1,1,1);
436 1.1 christos break;
437 1.1 christos case '@':
438 1.1 christos mask = M (1,0,1,1,1,1,1,1,1,1,1,0);
439 1.1 christos break;
440 1.1 christos case '!':
441 1.1 christos mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
442 1.1 christos break;
443 1.1 christos case '&':
444 1.1 christos mask = M (0,0,1,0,0,1,1,1,1,0,0,0);
445 1.1 christos break;
446 1.1 christos case '$':
447 1.1 christos mask = M (1,0,1,1,1,1,1,1,1,0,0,0);
448 1.1 christos break;
449 1.1 christos case '?':
450 1.1 christos mask = M (1,0,1,0,0,1,1,1,1,0,0,0);
451 1.1 christos break;
452 1.1 christos case '/':
453 1.1 christos mask = M (1,0,1,0,0,1,1,1,1,1,1,0);
454 1.1 christos break;
455 1.1 christos case '|':
456 1.1 christos mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
457 1.1 christos break;
458 1.1 christos case '>':
459 1.1 christos mask = M (0,0,1,0,1,1,1,1,1,0,0,0);
460 1.1 christos break;
461 1.1 christos case '<':
462 1.1 christos mask = M (0,0,1,1,0,1,1,1,1,1,1,0);
463 1.1 christos break;
464 1.1 christos case 'm':
465 1.1 christos mask = M (1,1,1,1,1,0,0,0,0,0,0,0);
466 1.1 christos break;
467 1.1 christos case 'n':
468 1.1 christos mask = M (0,0,0,0,0,1,0,0,0,1,0,0);
469 1.1 christos break;
470 1.1 christos case 'o':
471 1.1 christos mask = M (0,0,0,0,0,0,1,1,1,0,1,1);
472 1.1 christos break;
473 1.1 christos case 'p':
474 1.1 christos mask = M (1,1,1,1,1,1,0,0,0,0,0,0);
475 1.1 christos break;
476 1.1 christos case 'q':
477 1.1 christos mask = M (1,0,1,1,1,1,0,0,0,0,0,0);
478 1.1 christos break;
479 1.1 christos case 'v':
480 1.1 christos mask = M (1,0,1,1,1,1,0,1,1,0,0,0);
481 1.1 christos break;
482 1.1 christos case 'b':
483 1.1 christos mask = M (1,0,1,1,1,1,0,0,0,1,0,0);
484 1.1 christos break;
485 1.1 christos case 'w':
486 1.1 christos mask = M (0,0,1,1,1,1,0,0,0,1,0,0);
487 1.1 christos break;
488 1.1 christos case 'y':
489 1.1 christos mask = M (0,0,1,0,0,1,0,0,0,0,0,0);
490 1.1 christos break;
491 1.1 christos case 'z':
492 1.1 christos mask = M (0,0,1,0,0,1,0,0,0,1,0,0);
493 1.1 christos break;
494 1.1 christos case '4':
495 1.1 christos mask = M (0,0,1,1,1,1,0,0,0,0,0,0);
496 1.1 christos break;
497 1.1 christos default:
498 1.1 christos abort ();
499 1.1 christos }
500 1.1 christos #undef M
501 1.1 christos
502 1.1 christos mode = (val >> 3) & 7;
503 1.1 christos if (mode == 7)
504 1.1 christos mode += val & 7;
505 1.1 christos return (mask & (1 << mode)) != 0;
506 1.1 christos }
507 1.1 christos
508 1.1 christos /* Print a base register REGNO and displacement DISP, on INFO->STREAM.
509 1.1 christos REGNO = -1 for pc, -2 for none (suppressed). */
510 1.1 christos
511 1.1 christos static void
512 1.1 christos print_base (int regno, bfd_vma disp, disassemble_info *info)
513 1.1 christos {
514 1.11 christos if (regno == -1)
515 1.11 christos {
516 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%pc");
517 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
518 1.1 christos (*info->print_address_func) (disp, info);
519 1.1 christos }
520 1.11 christos else
521 1.11 christos {
522 1.11 christos if (regno == -3)
523 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
524 1.11 christos "%%zpc");
525 1.11 christos else if (regno != -2)
526 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
527 1.11 christos "%s", reg_names[regno]);
528 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
529 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
530 1.11 christos "%" PRIx64, (uint64_t) disp);
531 1.11 christos }
532 1.11 christos }
533 1.11 christos
534 1.11 christos /* Print the index register of an indexed argument, as encoded in the
535 1.11 christos extension word. */
536 1.11 christos
537 1.11 christos static void
538 1.11 christos print_index_register (int ext, disassemble_info *info)
539 1.11 christos {
540 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
541 1.11 christos "%s", reg_names[(ext >> 12) & 0xf]);
542 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
543 1.11 christos ":%c", ext & 0x800 ? 'l' : 'w');
544 1.11 christos if ((ext >> 9) & 3)
545 1.11 christos {
546 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ":");
547 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
548 1.1 christos "%d", 1 << ((ext >> 9) & 3));
549 1.1 christos }
550 1.1 christos }
551 1.1 christos
552 1.1 christos /* Print an indexed argument. The base register is BASEREG (-1 for pc).
553 1.1 christos P points to extension word, in buffer.
554 1.1 christos ADDR is the nominal core address of that extension word.
555 1.1 christos Returns NULL upon error. */
556 1.1 christos
557 1.1 christos static unsigned char *
558 1.1 christos print_indexed (int basereg,
559 1.1 christos unsigned char *p,
560 1.1 christos bfd_vma addr,
561 1.1 christos disassemble_info *info)
562 1.1 christos {
563 1.1 christos int word;
564 1.11 christos bfd_vma base_disp;
565 1.1 christos bfd_vma outer_disp;
566 1.1 christos bool print_index = true;
567 1.1 christos
568 1.1 christos NEXTWORD (p, word, NULL);
569 1.1 christos
570 1.1 christos /* Handle the 68000 style of indexing. */
571 1.1 christos
572 1.1 christos if ((word & 0x100) == 0)
573 1.1 christos {
574 1.1 christos base_disp = word & 0xff;
575 1.1 christos if ((base_disp & 0x80) != 0)
576 1.1 christos base_disp -= 0x100;
577 1.1 christos if (basereg == -1)
578 1.11 christos base_disp += addr;
579 1.11 christos print_base (basereg, base_disp, info);
580 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
581 1.1 christos print_index_register (word, info);
582 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
583 1.1 christos return p;
584 1.1 christos }
585 1.1 christos
586 1.1 christos /* Handle the generalized kind. */
587 1.1 christos /* First, compute the displacement to add to the base register. */
588 1.1 christos if (word & 0200)
589 1.1 christos {
590 1.1 christos if (basereg == -1)
591 1.1 christos basereg = -3;
592 1.1 christos else
593 1.1 christos basereg = -2;
594 1.11 christos }
595 1.1 christos if (word & 0100)
596 1.1 christos print_index = false;
597 1.1 christos base_disp = 0;
598 1.1 christos switch ((word >> 4) & 3)
599 1.1 christos {
600 1.1 christos case 2:
601 1.1 christos NEXTWORD (p, base_disp, NULL);
602 1.1 christos break;
603 1.1 christos case 3:
604 1.1 christos NEXTLONG (p, base_disp, NULL);
605 1.1 christos }
606 1.1 christos if (basereg == -1)
607 1.1 christos base_disp += addr;
608 1.1 christos
609 1.1 christos /* Handle single-level case (not indirect). */
610 1.1 christos if ((word & 7) == 0)
611 1.11 christos {
612 1.11 christos print_base (basereg, base_disp, info);
613 1.11 christos if (print_index)
614 1.11 christos {
615 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
616 1.11 christos print_index_register (word, info);
617 1.1 christos }
618 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
619 1.1 christos return p;
620 1.1 christos }
621 1.1 christos
622 1.1 christos /* Two level. Compute displacement to add after indirection. */
623 1.1 christos outer_disp = 0;
624 1.1 christos switch (word & 3)
625 1.1 christos {
626 1.1 christos case 2:
627 1.1 christos NEXTWORD (p, outer_disp, NULL);
628 1.1 christos break;
629 1.1 christos case 3:
630 1.1 christos NEXTLONG (p, outer_disp, NULL);
631 1.1 christos }
632 1.11 christos
633 1.1 christos print_base (basereg, base_disp, info);
634 1.11 christos if ((word & 4) == 0 && print_index)
635 1.11 christos {
636 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
637 1.1 christos print_index_register (word, info);
638 1.11 christos print_index = false;
639 1.11 christos }
640 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
641 1.11 christos ")@(");
642 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_address_offset,
643 1.11 christos "%" PRIx64, (uint64_t) outer_disp);
644 1.11 christos if (print_index)
645 1.11 christos {
646 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ",");
647 1.11 christos print_index_register (word, info);
648 1.1 christos }
649 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
650 1.1 christos
651 1.1 christos return p;
652 1.1 christos }
653 1.1 christos
654 1.1 christos #define FETCH_ARG(size, val) \
655 1.1 christos do \
656 1.1 christos { \
657 1.7 christos val = fetch_arg (buffer, place, size, info); \
658 1.1 christos if (val < 0) \
659 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR; \
660 1.1 christos } \
661 1.1 christos while (0)
662 1.7 christos
663 1.7 christos /* Returns number of bytes "eaten" by the operand, or
664 1.1 christos return enum print_insn_arg_error. ADDR is the pc for this arg to be
665 1.1 christos relative to. */
666 1.1 christos
667 1.1 christos static int
668 1.1 christos print_insn_arg (const char *d,
669 1.1 christos unsigned char *buffer,
670 1.1 christos unsigned char *p0,
671 1.1 christos bfd_vma addr,
672 1.1 christos disassemble_info *info)
673 1.1 christos {
674 1.1 christos int val = 0;
675 1.1 christos int place = d[1];
676 1.1 christos unsigned char *p = p0;
677 1.1 christos int regno;
678 1.1 christos const char *regname;
679 1.1 christos unsigned char *p1;
680 1.1 christos double flval;
681 1.1 christos int flt_p;
682 1.1 christos bfd_signed_vma disp;
683 1.1 christos unsigned int uval;
684 1.1 christos
685 1.1 christos switch (*d)
686 1.1 christos {
687 1.1 christos case 'c': /* Cache identifier. */
688 1.1 christos {
689 1.11 christos static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
690 1.11 christos FETCH_ARG (2, val);
691 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic,
692 1.1 christos "%s", cacheFieldName[val]);
693 1.1 christos break;
694 1.1 christos }
695 1.1 christos
696 1.1 christos case 'a': /* Address register indirect only. Cf. case '+'. */
697 1.11 christos {
698 1.11 christos FETCH_ARG (3, val);
699 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%s",
700 1.1 christos reg_names[val + 8]);
701 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
702 1.1 christos break;
703 1.1 christos }
704 1.1 christos
705 1.1 christos case '_': /* 32-bit absolute address for move16. */
706 1.1 christos {
707 1.1 christos NEXTULONG (p, uval);
708 1.1 christos (*info->print_address_func) (uval, info);
709 1.1 christos break;
710 1.1 christos }
711 1.11 christos
712 1.1 christos case 'C':
713 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%ccr");
714 1.1 christos break;
715 1.11 christos
716 1.1 christos case 'S':
717 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%sr");
718 1.1 christos break;
719 1.11 christos
720 1.1 christos case 'U':
721 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%usp");
722 1.1 christos break;
723 1.11 christos
724 1.1 christos case 'E':
725 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%acc");
726 1.1 christos break;
727 1.11 christos
728 1.1 christos case 'G':
729 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%macsr");
730 1.1 christos break;
731 1.11 christos
732 1.1 christos case 'H':
733 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%mask");
734 1.1 christos break;
735 1.1 christos
736 1.1 christos case 'J':
737 1.1 christos {
738 1.1 christos /* FIXME: There's a problem here, different m68k processors call the
739 1.1 christos same address different names. The tables below try to get it right
740 1.1 christos using info->mach, but only for v4e. */
741 1.1 christos struct regname { char * name; int value; };
742 1.1 christos static const struct regname names[] =
743 1.1 christos {
744 1.1 christos {"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
745 1.1 christos {"%tc", 0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
746 1.1 christos {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
747 1.1 christos {"%rgpiobar", 0x009}, {"%acr4",0x00c},
748 1.1 christos {"%acr5",0x00d}, {"%acr6",0x00e}, {"%acr7", 0x00f},
749 1.1 christos {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
750 1.1 christos {"%msp", 0x803}, {"%isp", 0x804},
751 1.1 christos {"%pc", 0x80f},
752 1.1 christos /* Reg c04 is sometimes called flashbar or rambar.
753 1.1 christos Reg c05 is also sometimes called rambar. */
754 1.1 christos {"%rambar0", 0xc04}, {"%rambar1", 0xc05},
755 1.1 christos
756 1.1 christos /* reg c0e is sometimes called mbar2 or secmbar.
757 1.1 christos reg c0f is sometimes called mbar. */
758 1.1 christos {"%mbar0", 0xc0e}, {"%mbar1", 0xc0f},
759 1.1 christos
760 1.1 christos /* Should we be calling this psr like we do in case 'Y'? */
761 1.1 christos {"%mmusr",0x805},
762 1.1 christos
763 1.1 christos {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808},
764 1.1 christos
765 1.1 christos /* Fido added these. */
766 1.1 christos {"%cac", 0xffe}, {"%mbo", 0xfff}
767 1.1 christos };
768 1.1 christos /* Alternate names for v4e (MCF5407/5445x/MCF547x/MCF548x), at least. */
769 1.1 christos static const struct regname names_v4e[] =
770 1.1 christos {
771 1.1 christos {"%asid",0x003}, {"%acr0",0x004}, {"%acr1",0x005},
772 1.1 christos {"%acr2",0x006}, {"%acr3",0x007}, {"%mmubar",0x008},
773 1.1 christos };
774 1.1 christos unsigned int arch_mask;
775 1.1 christos
776 1.1 christos arch_mask = bfd_m68k_mach_to_features (info->mach);
777 1.1 christos FETCH_ARG (12, val);
778 1.1 christos if (arch_mask & (mcfisa_b | mcfisa_c))
779 1.1 christos {
780 1.1 christos for (regno = ARRAY_SIZE (names_v4e); --regno >= 0;)
781 1.11 christos if (names_v4e[regno].value == val)
782 1.11 christos {
783 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
784 1.1 christos "%s", names_v4e[regno].name);
785 1.1 christos break;
786 1.1 christos }
787 1.1 christos if (regno >= 0)
788 1.1 christos break;
789 1.1 christos }
790 1.1 christos for (regno = ARRAY_SIZE (names) - 1; regno >= 0; regno--)
791 1.11 christos if (names[regno].value == val)
792 1.11 christos {
793 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
794 1.1 christos "%s", names[regno].name);
795 1.1 christos break;
796 1.11 christos }
797 1.1 christos if (regno < 0)
798 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "0x%x", val);
799 1.1 christos }
800 1.1 christos break;
801 1.1 christos
802 1.1 christos case 'Q':
803 1.1 christos FETCH_ARG (3, val);
804 1.1 christos /* 0 means 8, except for the bkpt instruction... */
805 1.11 christos if (val == 0 && d[1] != 's')
806 1.11 christos val = 8;
807 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
808 1.1 christos "#%d", val);
809 1.1 christos break;
810 1.1 christos
811 1.1 christos case 'x':
812 1.1 christos FETCH_ARG (3, val);
813 1.1 christos /* 0 means -1. */
814 1.11 christos if (val == 0)
815 1.11 christos val = -1;
816 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
817 1.1 christos "#%d", val);
818 1.1 christos break;
819 1.1 christos
820 1.11 christos case 'j':
821 1.11 christos FETCH_ARG (3, val);
822 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
823 1.1 christos "#%d", val+1);
824 1.1 christos break;
825 1.1 christos
826 1.11 christos case 'K':
827 1.11 christos FETCH_ARG (9, val);
828 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
829 1.1 christos "#%d", val);
830 1.1 christos break;
831 1.1 christos
832 1.1 christos case 'M':
833 1.1 christos if (place == 'h')
834 1.1 christos {
835 1.1 christos static char *const scalefactor_name[] = { "<<", ">>" };
836 1.11 christos
837 1.11 christos FETCH_ARG (1, val);
838 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic,
839 1.1 christos "%s", scalefactor_name[val]);
840 1.1 christos }
841 1.1 christos else
842 1.1 christos {
843 1.1 christos FETCH_ARG (8, val);
844 1.11 christos if (val & 0x80)
845 1.11 christos val = val - 0x100;
846 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
847 1.1 christos "#%d", val);
848 1.1 christos }
849 1.1 christos break;
850 1.1 christos
851 1.11 christos case 'T':
852 1.11 christos FETCH_ARG (4, val);
853 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
854 1.1 christos "#%d", val);
855 1.1 christos break;
856 1.1 christos
857 1.11 christos case 'D':
858 1.11 christos FETCH_ARG (3, val);
859 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
860 1.1 christos "%s", reg_names[val]);
861 1.1 christos break;
862 1.1 christos
863 1.11 christos case 'A':
864 1.11 christos FETCH_ARG (3, val);
865 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
866 1.1 christos "%s", reg_names[val + 010]);
867 1.1 christos break;
868 1.1 christos
869 1.11 christos case 'R':
870 1.11 christos FETCH_ARG (4, val);
871 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
872 1.1 christos "%s", reg_names[val]);
873 1.1 christos break;
874 1.1 christos
875 1.1 christos case 'r':
876 1.11 christos FETCH_ARG (4, regno);
877 1.11 christos if (regno > 7)
878 1.11 christos {
879 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
880 1.11 christos "%s", reg_names[regno]);
881 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
882 1.11 christos }
883 1.11 christos else
884 1.11 christos {
885 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
886 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
887 1.11 christos "%s", reg_names[regno]);
888 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
889 1.1 christos }
890 1.1 christos break;
891 1.1 christos
892 1.11 christos case 'F':
893 1.11 christos FETCH_ARG (3, val);
894 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
895 1.1 christos "%%fp%d", val);
896 1.1 christos break;
897 1.1 christos
898 1.1 christos case 'O':
899 1.11 christos FETCH_ARG (6, val);
900 1.11 christos if (val & 0x20)
901 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
902 1.11 christos "%s", reg_names[val & 7]);
903 1.11 christos else
904 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
905 1.1 christos "%d", val);
906 1.1 christos break;
907 1.1 christos
908 1.11 christos case '+':
909 1.11 christos FETCH_ARG (3, val);
910 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
911 1.1 christos "%s", reg_names[val + 8]);
912 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@+");
913 1.1 christos break;
914 1.1 christos
915 1.11 christos case '-':
916 1.11 christos FETCH_ARG (3, val);
917 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
918 1.1 christos "%s", reg_names[val + 8]);
919 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@-");
920 1.1 christos break;
921 1.1 christos
922 1.1 christos case 'k':
923 1.1 christos if (place == 'k')
924 1.11 christos {
925 1.11 christos FETCH_ARG (3, val);
926 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "{");
927 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
928 1.1 christos "%s", reg_names[val]);
929 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "}");
930 1.1 christos }
931 1.1 christos else if (place == 'C')
932 1.1 christos {
933 1.1 christos FETCH_ARG (7, val);
934 1.11 christos if (val > 63) /* This is a signed constant. */
935 1.11 christos val -= 128;
936 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "{");
937 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
938 1.1 christos "#%d", val);
939 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "}");
940 1.7 christos }
941 1.1 christos else
942 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND;
943 1.1 christos break;
944 1.1 christos
945 1.1 christos case '#':
946 1.1 christos case '^':
947 1.1 christos p1 = buffer + (*d == '#' ? 2 : 4);
948 1.1 christos if (place == 's')
949 1.1 christos FETCH_ARG (4, val);
950 1.1 christos else if (place == 'C')
951 1.1 christos FETCH_ARG (7, val);
952 1.1 christos else if (place == '8')
953 1.1 christos FETCH_ARG (3, val);
954 1.1 christos else if (place == '3')
955 1.1 christos FETCH_ARG (8, val);
956 1.1 christos else if (place == 'b')
957 1.7 christos NEXTBYTE (p1, val);
958 1.1 christos else if (place == 'w' || place == 'W')
959 1.7 christos NEXTWORD (p1, val, PRINT_INSN_ARG_MEMORY_ERROR);
960 1.1 christos else if (place == 'l')
961 1.7 christos NEXTLONG (p1, val, PRINT_INSN_ARG_MEMORY_ERROR);
962 1.1 christos else
963 1.11 christos return PRINT_INSN_ARG_INVALID_OP_TABLE;
964 1.11 christos
965 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
966 1.1 christos "#%d", val);
967 1.1 christos break;
968 1.1 christos
969 1.1 christos case 'B':
970 1.1 christos if (place == 'b')
971 1.1 christos NEXTBYTE (p, disp);
972 1.1 christos else if (place == 'B')
973 1.7 christos disp = COERCE_SIGNED_CHAR (buffer[1]);
974 1.1 christos else if (place == 'w' || place == 'W')
975 1.7 christos NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
976 1.1 christos else if (place == 'l' || place == 'L' || place == 'C')
977 1.1 christos NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
978 1.1 christos else if (place == 'g')
979 1.1 christos {
980 1.7 christos NEXTBYTE (buffer, disp);
981 1.1 christos if (disp == 0)
982 1.7 christos NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
983 1.1 christos else if (disp == -1)
984 1.1 christos NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
985 1.1 christos }
986 1.1 christos else if (place == 'c')
987 1.7 christos {
988 1.1 christos if (buffer[1] & 0x40) /* If bit six is one, long offset. */
989 1.7 christos NEXTLONG (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
990 1.1 christos else
991 1.1 christos NEXTWORD (p, disp, PRINT_INSN_ARG_MEMORY_ERROR);
992 1.7 christos }
993 1.1 christos else
994 1.1 christos return PRINT_INSN_ARG_INVALID_OP_TABLE;
995 1.1 christos
996 1.1 christos (*info->print_address_func) (addr + disp, info);
997 1.1 christos break;
998 1.1 christos
999 1.1 christos case 'd':
1000 1.1 christos {
1001 1.7 christos int val1;
1002 1.1 christos
1003 1.11 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
1004 1.11 christos FETCH_ARG (3, val1);
1005 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1006 1.11 christos "%s", reg_names[val1 + 8]);
1007 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
1008 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_address_offset,
1009 1.1 christos "%d", val);
1010 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
1011 1.1 christos break;
1012 1.1 christos }
1013 1.1 christos
1014 1.11 christos case 's':
1015 1.11 christos FETCH_ARG (3, val);
1016 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1017 1.1 christos "%s", fpcr_names[val]);
1018 1.1 christos break;
1019 1.1 christos
1020 1.11 christos case 'e':
1021 1.11 christos FETCH_ARG (2, val);
1022 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1023 1.1 christos "%%acc%d", val);
1024 1.1 christos break;
1025 1.1 christos
1026 1.11 christos case 'g':
1027 1.11 christos FETCH_ARG (1, val);
1028 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1029 1.1 christos "%%accext%s", val == 0 ? "01" : "23");
1030 1.1 christos break;
1031 1.1 christos
1032 1.1 christos case 'i':
1033 1.11 christos FETCH_ARG (2, val);
1034 1.11 christos if (val == 1)
1035 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic,
1036 1.11 christos "<<");
1037 1.11 christos else if (val == 3)
1038 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_sub_mnemonic,
1039 1.7 christos ">>");
1040 1.1 christos else
1041 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND;
1042 1.1 christos break;
1043 1.1 christos
1044 1.1 christos case 'I':
1045 1.1 christos /* Get coprocessor ID... */
1046 1.7 christos val = fetch_arg (buffer, 'd', 3, info);
1047 1.1 christos if (val < 0)
1048 1.11 christos return PRINT_INSN_ARG_MEMORY_ERROR;
1049 1.11 christos if (val != 1) /* Unusual coprocessor ID? */
1050 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
1051 1.1 christos "(cpid=%d) ", val);
1052 1.1 christos break;
1053 1.1 christos
1054 1.1 christos case '4':
1055 1.1 christos case '*':
1056 1.1 christos case '~':
1057 1.1 christos case '%':
1058 1.1 christos case ';':
1059 1.1 christos case '@':
1060 1.1 christos case '!':
1061 1.1 christos case '$':
1062 1.1 christos case '?':
1063 1.1 christos case '/':
1064 1.1 christos case '&':
1065 1.1 christos case '|':
1066 1.1 christos case '<':
1067 1.1 christos case '>':
1068 1.1 christos case 'm':
1069 1.1 christos case 'n':
1070 1.1 christos case 'o':
1071 1.1 christos case 'p':
1072 1.1 christos case 'q':
1073 1.1 christos case 'v':
1074 1.1 christos case 'b':
1075 1.1 christos case 'w':
1076 1.1 christos case 'y':
1077 1.1 christos case 'z':
1078 1.1 christos if (place == 'd')
1079 1.1 christos {
1080 1.7 christos val = fetch_arg (buffer, 'x', 6, info);
1081 1.1 christos if (val < 0)
1082 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR;
1083 1.1 christos val = ((val & 7) << 3) + ((val >> 3) & 7);
1084 1.1 christos }
1085 1.1 christos else
1086 1.1 christos {
1087 1.7 christos val = fetch_arg (buffer, 's', 6, info);
1088 1.1 christos if (val < 0)
1089 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR;
1090 1.1 christos }
1091 1.1 christos
1092 1.7 christos /* If the <ea> is invalid for *d, then reject this match. */
1093 1.1 christos if (!m68k_valid_ea (*d, val))
1094 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND;
1095 1.1 christos
1096 1.1 christos /* Get register number assuming address register. */
1097 1.1 christos regno = (val & 7) + 8;
1098 1.1 christos regname = reg_names[regno];
1099 1.1 christos switch (val >> 3)
1100 1.11 christos {
1101 1.11 christos case 0:
1102 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1103 1.1 christos "%s", reg_names[val]);
1104 1.1 christos break;
1105 1.11 christos
1106 1.11 christos case 1:
1107 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1108 1.1 christos "%s", regname);
1109 1.1 christos break;
1110 1.11 christos
1111 1.11 christos case 2:
1112 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1113 1.1 christos "%s", regname);
1114 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@");
1115 1.1 christos break;
1116 1.11 christos
1117 1.11 christos case 3:
1118 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1119 1.1 christos "%s", regname);
1120 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@+");
1121 1.1 christos break;
1122 1.11 christos
1123 1.11 christos case 4:
1124 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1125 1.1 christos "%s", regname);
1126 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@-");
1127 1.1 christos break;
1128 1.7 christos
1129 1.11 christos case 5:
1130 1.11 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
1131 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1132 1.11 christos "%s", regname);
1133 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
1134 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_address_offset,
1135 1.1 christos "%d", val);
1136 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
1137 1.1 christos break;
1138 1.1 christos
1139 1.1 christos case 6:
1140 1.7 christos p = print_indexed (regno, p, addr, info);
1141 1.1 christos if (p == NULL)
1142 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR;
1143 1.1 christos break;
1144 1.1 christos
1145 1.1 christos case 7:
1146 1.1 christos switch (val & 7)
1147 1.7 christos {
1148 1.1 christos case 0:
1149 1.1 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
1150 1.1 christos (*info->print_address_func) (val, info);
1151 1.1 christos break;
1152 1.1 christos
1153 1.1 christos case 1:
1154 1.1 christos NEXTULONG (p, uval);
1155 1.1 christos (*info->print_address_func) (uval, info);
1156 1.1 christos break;
1157 1.7 christos
1158 1.11 christos case 2:
1159 1.11 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
1160 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1161 1.1 christos "%%pc");
1162 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "@(");
1163 1.1 christos (*info->print_address_func) (addr + val, info);
1164 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ")");
1165 1.1 christos break;
1166 1.1 christos
1167 1.1 christos case 3:
1168 1.7 christos p = print_indexed (-1, p, addr, info);
1169 1.1 christos if (p == NULL)
1170 1.1 christos return PRINT_INSN_ARG_MEMORY_ERROR;
1171 1.1 christos break;
1172 1.1 christos
1173 1.1 christos case 4:
1174 1.1 christos flt_p = 1; /* Assume it's a float... */
1175 1.1 christos switch (place)
1176 1.1 christos {
1177 1.1 christos case 'b':
1178 1.1 christos NEXTBYTE (p, val);
1179 1.1 christos flt_p = 0;
1180 1.1 christos break;
1181 1.7 christos
1182 1.1 christos case 'w':
1183 1.1 christos NEXTWORD (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
1184 1.1 christos flt_p = 0;
1185 1.1 christos break;
1186 1.7 christos
1187 1.1 christos case 'l':
1188 1.1 christos NEXTLONG (p, val, PRINT_INSN_ARG_MEMORY_ERROR);
1189 1.1 christos flt_p = 0;
1190 1.1 christos break;
1191 1.1 christos
1192 1.1 christos case 'f':
1193 1.1 christos NEXTSINGLE (flval, p);
1194 1.1 christos break;
1195 1.1 christos
1196 1.1 christos case 'F':
1197 1.1 christos NEXTDOUBLE (flval, p);
1198 1.1 christos break;
1199 1.1 christos
1200 1.1 christos case 'x':
1201 1.1 christos NEXTEXTEND (flval, p);
1202 1.1 christos break;
1203 1.1 christos
1204 1.1 christos case 'p':
1205 1.1 christos NEXTPACKED (p, flval);
1206 1.1 christos break;
1207 1.7 christos
1208 1.1 christos default:
1209 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND;
1210 1.11 christos }
1211 1.11 christos if (flt_p) /* Print a float? */
1212 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1213 1.11 christos "#0e%g", flval);
1214 1.11 christos else
1215 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1216 1.1 christos "#%d", val);
1217 1.1 christos break;
1218 1.7 christos
1219 1.1 christos default:
1220 1.1 christos return PRINT_INSN_ARG_INVALID_OPERAND;
1221 1.1 christos }
1222 1.1 christos }
1223 1.1 christos
1224 1.1 christos /* If place is '/', then this is the case of the mask bit for
1225 1.1 christos mac/emac loads. Now that the arg has been printed, grab the
1226 1.1 christos mask bit and if set, add a '&' to the arg. */
1227 1.1 christos if (place == '/')
1228 1.1 christos {
1229 1.11 christos FETCH_ARG (1, val);
1230 1.1 christos if (val)
1231 1.1 christos info->fprintf_styled_func (info->stream, dis_style_text, "&");
1232 1.1 christos }
1233 1.1 christos break;
1234 1.1 christos
1235 1.1 christos case 'L':
1236 1.1 christos case 'l':
1237 1.1 christos if (place == 'w')
1238 1.1 christos {
1239 1.7 christos char doneany;
1240 1.1 christos p1 = buffer + 2;
1241 1.1 christos NEXTWORD (p1, val, PRINT_INSN_ARG_MEMORY_ERROR);
1242 1.1 christos /* Move the pointer ahead if this point is farther ahead
1243 1.1 christos than the last. */
1244 1.1 christos p = p1 > p ? p1 : p;
1245 1.11 christos if (val == 0)
1246 1.11 christos {
1247 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1248 1.1 christos "#0");
1249 1.1 christos break;
1250 1.1 christos }
1251 1.1 christos if (*d == 'l')
1252 1.1 christos {
1253 1.1 christos int newval = 0;
1254 1.1 christos
1255 1.1 christos for (regno = 0; regno < 16; ++regno)
1256 1.1 christos if (val & (0x8000 >> regno))
1257 1.1 christos newval |= 1 << regno;
1258 1.1 christos val = newval;
1259 1.1 christos }
1260 1.1 christos val &= 0xffff;
1261 1.1 christos doneany = 0;
1262 1.1 christos for (regno = 0; regno < 16; ++regno)
1263 1.1 christos if (val & (1 << regno))
1264 1.1 christos {
1265 1.1 christos int first_regno;
1266 1.11 christos
1267 1.11 christos if (doneany)
1268 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
1269 1.11 christos "/");
1270 1.11 christos doneany = 1;
1271 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1272 1.1 christos "%s", reg_names[regno]);
1273 1.1 christos first_regno = regno;
1274 1.1 christos while (val & (1 << (regno + 1)))
1275 1.11 christos ++regno;
1276 1.11 christos if (regno > first_regno)
1277 1.11 christos {
1278 1.11 christos (*info->fprintf_styled_func) (info->stream,
1279 1.11 christos dis_style_text, "-");
1280 1.11 christos (*info->fprintf_styled_func) (info->stream,
1281 1.11 christos dis_style_register, "%s",
1282 1.1 christos reg_names[regno]);
1283 1.1 christos }
1284 1.1 christos }
1285 1.1 christos }
1286 1.1 christos else if (place == '3')
1287 1.1 christos {
1288 1.1 christos /* `fmovem' insn. */
1289 1.1 christos char doneany;
1290 1.1 christos
1291 1.1 christos FETCH_ARG (8, val);
1292 1.11 christos if (val == 0)
1293 1.11 christos {
1294 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1295 1.1 christos "#0");
1296 1.1 christos break;
1297 1.1 christos }
1298 1.1 christos if (*d == 'l')
1299 1.1 christos {
1300 1.1 christos int newval = 0;
1301 1.1 christos
1302 1.1 christos for (regno = 0; regno < 8; ++regno)
1303 1.1 christos if (val & (0x80 >> regno))
1304 1.1 christos newval |= 1 << regno;
1305 1.1 christos val = newval;
1306 1.1 christos }
1307 1.1 christos val &= 0xff;
1308 1.1 christos doneany = 0;
1309 1.1 christos for (regno = 0; regno < 8; ++regno)
1310 1.1 christos if (val & (1 << regno))
1311 1.1 christos {
1312 1.11 christos int first_regno;
1313 1.11 christos if (doneany)
1314 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
1315 1.11 christos "/");
1316 1.11 christos doneany = 1;
1317 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1318 1.1 christos "%%fp%d", regno);
1319 1.1 christos first_regno = regno;
1320 1.1 christos while (val & (1 << (regno + 1)))
1321 1.11 christos ++regno;
1322 1.11 christos if (regno > first_regno)
1323 1.11 christos {
1324 1.11 christos (*info->fprintf_styled_func) (info->stream,
1325 1.11 christos dis_style_text, "-");
1326 1.11 christos (*info->fprintf_styled_func) (info->stream,
1327 1.11 christos dis_style_register,
1328 1.1 christos "%%fp%d", regno);
1329 1.1 christos }
1330 1.1 christos }
1331 1.1 christos }
1332 1.1 christos else if (place == '8')
1333 1.1 christos {
1334 1.11 christos FETCH_ARG (3, val);
1335 1.11 christos /* fmoveml for FP status registers. */
1336 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1337 1.1 christos "%s", fpcr_names[val]);
1338 1.7 christos }
1339 1.1 christos else
1340 1.1 christos return PRINT_INSN_ARG_INVALID_OP_TABLE;
1341 1.1 christos break;
1342 1.1 christos
1343 1.7 christos case 'X':
1344 1.1 christos place = '8';
1345 1.1 christos /* Fall through. */
1346 1.1 christos case 'Y':
1347 1.1 christos case 'Z':
1348 1.1 christos case 'W':
1349 1.1 christos case '0':
1350 1.1 christos case '1':
1351 1.1 christos case '2':
1352 1.1 christos case '3':
1353 1.1 christos {
1354 1.1 christos char *name = 0;
1355 1.1 christos
1356 1.1 christos FETCH_ARG (5, val);
1357 1.1 christos switch (val)
1358 1.1 christos {
1359 1.1 christos case 2: name = "%tt0"; break;
1360 1.1 christos case 3: name = "%tt1"; break;
1361 1.1 christos case 0x10: name = "%tc"; break;
1362 1.1 christos case 0x11: name = "%drp"; break;
1363 1.1 christos case 0x12: name = "%srp"; break;
1364 1.1 christos case 0x13: name = "%crp"; break;
1365 1.1 christos case 0x14: name = "%cal"; break;
1366 1.1 christos case 0x15: name = "%val"; break;
1367 1.1 christos case 0x16: name = "%scc"; break;
1368 1.1 christos case 0x17: name = "%ac"; break;
1369 1.1 christos case 0x18: name = "%psr"; break;
1370 1.1 christos case 0x19: name = "%pcsr"; break;
1371 1.1 christos case 0x1c:
1372 1.1 christos case 0x1d:
1373 1.1 christos {
1374 1.11 christos int break_reg = ((buffer[3] >> 2) & 7);
1375 1.11 christos
1376 1.11 christos (*info->fprintf_styled_func)
1377 1.1 christos (info->stream, dis_style_register,
1378 1.1 christos val == 0x1c ? "%%bad%d" : "%%bac%d", break_reg);
1379 1.1 christos }
1380 1.11 christos break;
1381 1.11 christos default:
1382 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
1383 1.1 christos "<mmu register %d>", val);
1384 1.11 christos }
1385 1.11 christos if (name)
1386 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1387 1.1 christos "%s", name);
1388 1.1 christos }
1389 1.1 christos break;
1390 1.1 christos
1391 1.1 christos case 'f':
1392 1.1 christos {
1393 1.1 christos int fc;
1394 1.1 christos
1395 1.11 christos FETCH_ARG (5, fc);
1396 1.11 christos if (fc == 1)
1397 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1398 1.11 christos "%%dfc");
1399 1.11 christos else if (fc == 0)
1400 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register,
1401 1.1 christos "%%sfc");
1402 1.11 christos else
1403 1.11 christos /* xgettext:c-format */
1404 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_text,
1405 1.1 christos _("<function code %d>"), fc);
1406 1.1 christos }
1407 1.1 christos break;
1408 1.11 christos
1409 1.1 christos case 'V':
1410 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%%val");
1411 1.1 christos break;
1412 1.1 christos
1413 1.1 christos case 't':
1414 1.1 christos {
1415 1.1 christos int level;
1416 1.11 christos
1417 1.11 christos FETCH_ARG (3, level);
1418 1.1 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1419 1.1 christos "%d", level);
1420 1.1 christos }
1421 1.1 christos break;
1422 1.1 christos
1423 1.1 christos case 'u':
1424 1.1 christos {
1425 1.1 christos short is_upper = 0;
1426 1.1 christos int reg;
1427 1.1 christos
1428 1.1 christos FETCH_ARG (5, reg);
1429 1.1 christos if (reg & 0x10)
1430 1.1 christos {
1431 1.1 christos is_upper = 1;
1432 1.11 christos reg &= 0xf;
1433 1.11 christos }
1434 1.11 christos (*info->fprintf_styled_func) (info->stream, dis_style_register, "%s%s",
1435 1.1 christos reg_half_names[reg],
1436 1.1 christos is_upper ? "u" : "l");
1437 1.1 christos }
1438 1.1 christos break;
1439 1.7 christos
1440 1.1 christos default:
1441 1.1 christos return PRINT_INSN_ARG_INVALID_OP_TABLE;
1442 1.1 christos }
1443 1.1 christos
1444 1.1 christos return p - p0;
1445 1.1 christos }
1446 1.7 christos
1447 1.7 christos /* Try to match the current instruction to best and if so, return the
1448 1.1 christos number of bytes consumed from the instruction stream, else zero.
1449 1.1 christos Return -1 on memory error. */
1450 1.1 christos
1451 1.1 christos static int
1452 1.1 christos match_insn_m68k (bfd_vma memaddr,
1453 1.1 christos disassemble_info * info,
1454 1.1 christos const struct m68k_opcode * best)
1455 1.1 christos {
1456 1.1 christos unsigned char *save_p;
1457 1.1 christos unsigned char *p;
1458 1.1 christos const char *d;
1459 1.1 christos const char *args = best->args;
1460 1.1 christos
1461 1.11 christos struct private *priv = (struct private *) info->private_data;
1462 1.1 christos bfd_byte *buffer = priv->the_buffer;
1463 1.1 christos fprintf_styled_ftype save_printer = info->fprintf_styled_func;
1464 1.1 christos void (* save_print_address) (bfd_vma, struct disassemble_info *)
1465 1.1 christos = info->print_address_func;
1466 1.1 christos
1467 1.6 christos if (*args == '.')
1468 1.1 christos args++;
1469 1.1 christos
1470 1.1 christos /* Point at first word of argument data,
1471 1.1 christos and at descriptor for first argument. */
1472 1.1 christos p = buffer + 2;
1473 1.1 christos
1474 1.1 christos /* Figure out how long the fixed-size portion of the instruction is.
1475 1.1 christos The only place this is stored in the opcode table is
1476 1.1 christos in the arguments--look for arguments which specify fields in the 2nd
1477 1.1 christos or 3rd words of the instruction. */
1478 1.1 christos for (d = args; *d; d += 2)
1479 1.1 christos {
1480 1.1 christos /* I don't think it is necessary to be checking d[0] here;
1481 1.1 christos I suspect all this could be moved to the case statement below. */
1482 1.1 christos if (d[0] == '#')
1483 1.1 christos {
1484 1.1 christos if (d[1] == 'l' && p - buffer < 6)
1485 1.1 christos p = buffer + 6;
1486 1.1 christos else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8')
1487 1.1 christos p = buffer + 4;
1488 1.1 christos }
1489 1.1 christos
1490 1.1 christos if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
1491 1.1 christos p = buffer + 4;
1492 1.1 christos
1493 1.1 christos switch (d[1])
1494 1.1 christos {
1495 1.1 christos case '1':
1496 1.1 christos case '2':
1497 1.1 christos case '3':
1498 1.1 christos case '7':
1499 1.1 christos case '8':
1500 1.1 christos case '9':
1501 1.1 christos case 'i':
1502 1.1 christos if (p - buffer < 4)
1503 1.1 christos p = buffer + 4;
1504 1.1 christos break;
1505 1.1 christos case '4':
1506 1.1 christos case '5':
1507 1.1 christos case '6':
1508 1.1 christos if (p - buffer < 6)
1509 1.1 christos p = buffer + 6;
1510 1.1 christos break;
1511 1.1 christos default:
1512 1.1 christos break;
1513 1.1 christos }
1514 1.1 christos }
1515 1.1 christos
1516 1.1 christos /* pflusha is an exceptions. It takes no arguments but is two words
1517 1.1 christos long. Recognize it by looking at the lower 16 bits of the mask. */
1518 1.1 christos if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
1519 1.1 christos p = buffer + 4;
1520 1.1 christos
1521 1.1 christos /* lpstop is another exception. It takes a one word argument but is
1522 1.1 christos three words long. */
1523 1.1 christos if (p - buffer < 6
1524 1.1 christos && (best->match & 0xffff) == 0xffff
1525 1.1 christos && args[0] == '#'
1526 1.1 christos && args[1] == 'w')
1527 1.1 christos {
1528 1.1 christos /* Copy the one word argument into the usual location for a one
1529 1.1 christos word argument, to simplify printing it. We can get away with
1530 1.1 christos this because we know exactly what the second word is, and we
1531 1.7 christos aren't going to print anything based on it. */
1532 1.7 christos p = buffer + 6;
1533 1.1 christos if (!FETCH_DATA (info, p))
1534 1.1 christos return -1;
1535 1.1 christos buffer[2] = buffer[4];
1536 1.1 christos buffer[3] = buffer[5];
1537 1.7 christos }
1538 1.7 christos
1539 1.1 christos if (!FETCH_DATA (info, p))
1540 1.1 christos return -1;
1541 1.1 christos
1542 1.11 christos save_p = p;
1543 1.1 christos info->print_address_func = dummy_print_address;
1544 1.1 christos info->fprintf_styled_func = dummy_printer;
1545 1.1 christos
1546 1.1 christos /* We scan the operands twice. The first time we don't print anything,
1547 1.1 christos but look for errors. */
1548 1.1 christos for (d = args; *d; d += 2)
1549 1.1 christos {
1550 1.1 christos int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
1551 1.1 christos
1552 1.7 christos if (eaten >= 0)
1553 1.7 christos p += eaten;
1554 1.1 christos else if (eaten == PRINT_INSN_ARG_INVALID_OPERAND
1555 1.11 christos || eaten == PRINT_INSN_ARG_MEMORY_ERROR)
1556 1.1 christos {
1557 1.7 christos info->fprintf_styled_func = save_printer;
1558 1.1 christos info->print_address_func = save_print_address;
1559 1.1 christos return eaten == PRINT_INSN_ARG_MEMORY_ERROR ? -1 : 0;
1560 1.1 christos }
1561 1.1 christos else
1562 1.1 christos {
1563 1.11 christos /* We must restore the print functions before trying to print the
1564 1.1 christos error message. */
1565 1.11 christos info->fprintf_styled_func = save_printer;
1566 1.11 christos info->print_address_func = save_print_address;
1567 1.11 christos info->fprintf_styled_func (info->stream, dis_style_text,
1568 1.11 christos /* xgettext:c-format */
1569 1.1 christos _("<internal error in opcode table: %s %s>\n"),
1570 1.1 christos best->name, best->args);
1571 1.1 christos return 2;
1572 1.1 christos }
1573 1.1 christos }
1574 1.11 christos
1575 1.1 christos p = save_p;
1576 1.1 christos info->fprintf_styled_func = save_printer;
1577 1.1 christos info->print_address_func = save_print_address;
1578 1.1 christos
1579 1.11 christos d = args;
1580 1.1 christos
1581 1.1 christos info->fprintf_styled_func (info->stream, dis_style_mnemonic, "%s", best->name);
1582 1.11 christos
1583 1.1 christos if (*d)
1584 1.1 christos info->fprintf_styled_func (info->stream, dis_style_text, " ");
1585 1.1 christos
1586 1.1 christos while (*d)
1587 1.1 christos {
1588 1.1 christos p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
1589 1.1 christos d += 2;
1590 1.11 christos
1591 1.1 christos if (*d && *(d - 2) != 'I' && *d != 'k')
1592 1.1 christos info->fprintf_styled_func (info->stream, dis_style_text, ",");
1593 1.1 christos }
1594 1.1 christos
1595 1.1 christos return p - buffer;
1596 1.1 christos }
1597 1.1 christos
1598 1.1 christos /* Try to interpret the instruction at address MEMADDR as one that
1599 1.7 christos can execute on a processor with the features given by ARCH_MASK.
1600 1.7 christos If successful, print the instruction to INFO->STREAM and return
1601 1.1 christos its length in bytes. Return 0 otherwise. Return -1 on memory
1602 1.1 christos error. */
1603 1.1 christos
1604 1.1 christos static int
1605 1.1 christos m68k_scan_mask (bfd_vma memaddr, disassemble_info *info,
1606 1.1 christos unsigned int arch_mask)
1607 1.1 christos {
1608 1.1 christos int i;
1609 1.1 christos const char *d;
1610 1.1 christos static const struct m68k_opcode **opcodes[16];
1611 1.1 christos static int numopcodes[16];
1612 1.1 christos int val;
1613 1.1 christos int major_opcode;
1614 1.1 christos
1615 1.1 christos struct private *priv = (struct private *) info->private_data;
1616 1.1 christos bfd_byte *buffer = priv->the_buffer;
1617 1.1 christos
1618 1.1 christos if (!opcodes[0])
1619 1.1 christos {
1620 1.1 christos /* Speed up the matching by sorting the opcode
1621 1.1 christos table on the upper four bits of the opcode. */
1622 1.1 christos const struct m68k_opcode **opc_pointer[16];
1623 1.1 christos
1624 1.1 christos /* First count how many opcodes are in each of the sixteen buckets. */
1625 1.1 christos for (i = 0; i < m68k_numopcodes; i++)
1626 1.1 christos numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
1627 1.1 christos
1628 1.1 christos /* Then create a sorted table of pointers
1629 1.1 christos that point into the unsorted table. */
1630 1.1 christos opc_pointer[0] = xmalloc (sizeof (struct m68k_opcode *)
1631 1.1 christos * m68k_numopcodes);
1632 1.1 christos opcodes[0] = opc_pointer[0];
1633 1.1 christos
1634 1.1 christos for (i = 1; i < 16; i++)
1635 1.1 christos {
1636 1.1 christos opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
1637 1.1 christos opcodes[i] = opc_pointer[i];
1638 1.1 christos }
1639 1.1 christos
1640 1.1 christos for (i = 0; i < m68k_numopcodes; i++)
1641 1.1 christos *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
1642 1.7 christos }
1643 1.7 christos
1644 1.1 christos if (!FETCH_DATA (info, buffer + 2))
1645 1.1 christos return -1;
1646 1.1 christos major_opcode = (buffer[0] >> 4) & 15;
1647 1.1 christos
1648 1.1 christos for (i = 0; i < numopcodes[major_opcode]; i++)
1649 1.1 christos {
1650 1.1 christos const struct m68k_opcode *opc = opcodes[major_opcode][i];
1651 1.1 christos unsigned long opcode = opc->opcode;
1652 1.1 christos unsigned long match = opc->match;
1653 1.1 christos const char *args = opc->args;
1654 1.1 christos
1655 1.1 christos if (*args == '.')
1656 1.1 christos args++;
1657 1.1 christos
1658 1.1 christos if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
1659 1.1 christos && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
1660 1.1 christos /* Only fetch the next two bytes if we need to. */
1661 1.1 christos && (((0xffff & match) == 0)
1662 1.1 christos ||
1663 1.1 christos (FETCH_DATA (info, buffer + 4)
1664 1.1 christos && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
1665 1.1 christos && ((0xff & buffer[3] & match) == (0xff & opcode)))
1666 1.1 christos )
1667 1.1 christos && (opc->arch & arch_mask) != 0)
1668 1.1 christos {
1669 1.1 christos /* Don't use for printout the variants of divul and divsl
1670 1.1 christos that have the same register number in two places.
1671 1.1 christos The more general variants will match instead. */
1672 1.1 christos for (d = args; *d; d += 2)
1673 1.1 christos if (d[1] == 'D')
1674 1.1 christos break;
1675 1.1 christos
1676 1.1 christos /* Don't use for printout the variants of most floating
1677 1.1 christos point coprocessor instructions which use the same
1678 1.1 christos register number in two places, as above. */
1679 1.1 christos if (*d == '\0')
1680 1.1 christos for (d = args; *d; d += 2)
1681 1.1 christos if (d[1] == 't')
1682 1.1 christos break;
1683 1.1 christos
1684 1.1 christos /* Don't match fmovel with more than one register;
1685 1.1 christos wait for fmoveml. */
1686 1.1 christos if (*d == '\0')
1687 1.1 christos {
1688 1.1 christos for (d = args; *d; d += 2)
1689 1.1 christos {
1690 1.1 christos if (d[0] == 's' && d[1] == '8')
1691 1.1 christos {
1692 1.1 christos val = fetch_arg (buffer, d[1], 3, info);
1693 1.1 christos if (val < 0)
1694 1.1 christos return 0;
1695 1.1 christos if ((val & (val - 1)) != 0)
1696 1.1 christos break;
1697 1.1 christos }
1698 1.1 christos }
1699 1.1 christos }
1700 1.1 christos
1701 1.1 christos /* Don't match FPU insns with non-default coprocessor ID. */
1702 1.1 christos if (*d == '\0')
1703 1.1 christos {
1704 1.1 christos for (d = args; *d; d += 2)
1705 1.1 christos {
1706 1.1 christos if (d[0] == 'I')
1707 1.1 christos {
1708 1.1 christos val = fetch_arg (buffer, 'd', 3, info);
1709 1.1 christos if (val != 1)
1710 1.1 christos break;
1711 1.1 christos }
1712 1.1 christos }
1713 1.1 christos }
1714 1.1 christos
1715 1.1 christos if (*d == '\0')
1716 1.1 christos if ((val = match_insn_m68k (memaddr, info, opc)))
1717 1.1 christos return val;
1718 1.1 christos }
1719 1.6 christos }
1720 1.1 christos return 0;
1721 1.1 christos }
1722 1.1 christos
1723 1.1 christos /* Print the m68k instruction at address MEMADDR in debugged memory,
1724 1.1 christos on INFO->STREAM. Returns length of the instruction, in bytes. */
1725 1.1 christos
1726 1.1 christos int
1727 1.1 christos print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
1728 1.1 christos {
1729 1.1 christos unsigned int arch_mask;
1730 1.1 christos struct private priv;
1731 1.1 christos int val;
1732 1.1 christos
1733 1.1 christos bfd_byte *buffer = priv.the_buffer;
1734 1.1 christos
1735 1.1 christos info->private_data = & priv;
1736 1.1 christos /* Tell objdump to use two bytes per chunk
1737 1.1 christos and six bytes per line for displaying raw data. */
1738 1.1 christos info->bytes_per_chunk = 2;
1739 1.1 christos info->bytes_per_line = 6;
1740 1.1 christos info->display_endian = BFD_ENDIAN_BIG;
1741 1.1 christos priv.max_fetched = priv.the_buffer;
1742 1.1 christos priv.insn_start = memaddr;
1743 1.1 christos
1744 1.1 christos arch_mask = bfd_m68k_mach_to_features (info->mach);
1745 1.1 christos if (!arch_mask)
1746 1.1 christos {
1747 1.1 christos /* First try printing an m680x0 instruction. Try printing a Coldfire
1748 1.7 christos one if that fails. */
1749 1.1 christos val = m68k_scan_mask (memaddr, info, m68k_mask);
1750 1.1 christos if (val <= 0)
1751 1.1 christos val = m68k_scan_mask (memaddr, info, mcf_mask);
1752 1.1 christos }
1753 1.1 christos else
1754 1.1 christos {
1755 1.1 christos val = m68k_scan_mask (memaddr, info, arch_mask);
1756 1.1 christos }
1757 1.11 christos
1758 1.11 christos if (val == 0)
1759 1.11 christos {
1760 1.11 christos /* Handle undefined instructions. */
1761 1.11 christos info->fprintf_styled_func (info->stream, dis_style_assembler_directive,
1762 1.11 christos ".short");
1763 1.11 christos info->fprintf_styled_func (info->stream, dis_style_text, " ");
1764 1.11 christos info->fprintf_styled_func (info->stream, dis_style_immediate,
1765 1.1 christos "0x%04x", (buffer[0] << 8) + buffer[1]);
1766 1.1 christos }
1767 1.1 christos
1768 return val ? val : 2;
1769 }
1770