Commit | Line | Data |
---|---|---|
7499d566 NC |
1 | /* Instruction printing code for the MAXQ |
2 | ||
c7e2358a | 3 | Copyright 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc. |
7499d566 NC |
4 | |
5 | Written by Vineet Sharma(vineets@noida.hcltech.com) Inderpreet | |
6 | S.(inderpreetb@noida.hcltech.com) | |
7 | ||
9b201bb5 | 8 | This file is part of the GNU opcodes library. |
7499d566 | 9 | |
9b201bb5 NC |
10 | This library is free software; you can redistribute it and/or modify |
11 | it under the terms of the GNU General Public License as published by | |
12 | the Free Software Foundation; either version 3, or (at your option) | |
7499d566 NC |
13 | any later version. |
14 | ||
9b201bb5 NC |
15 | It is distributed in the hope that it will be useful, but WITHOUT |
16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
17 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
18 | License for more details. | |
7499d566 NC |
19 | |
20 | You should have received a copy of the GNU General Public License along | |
f4321104 NC |
21 | with this program; if not, write to the Free Software Foundation, Inc., |
22 | 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ | |
7499d566 NC |
23 | |
24 | #include "sysdep.h" | |
25 | #include "dis-asm.h" | |
26 | #include "opcode/maxq.h" | |
27 | ||
28 | struct _group_info | |
29 | { | |
30 | unsigned char group_no; | |
31 | unsigned char sub_opcode; | |
32 | unsigned char src; | |
33 | unsigned char dst; | |
34 | unsigned char fbit; | |
35 | unsigned char bit_no; | |
36 | unsigned char flag; | |
37 | ||
38 | }; | |
39 | ||
40 | typedef struct _group_info group_info; | |
41 | ||
42 | #define SRC 0x01 | |
43 | #define DST 0x02 | |
44 | #define FORMAT 0x04 | |
45 | #define BIT_NO 0x08 | |
46 | #define SUB_OP 0x10 | |
47 | ||
48 | #define MASK_LOW_BYTE 0x0f | |
49 | #define MASK_HIGH_BYTE 0xf0 | |
50 | ||
51 | /* Flags for retrieving the bits from the op-code. */ | |
52 | #define _DECODE_LOWNIB_LOWBYTE 0x000f | |
53 | #define _DECODE_HIGHNIB_LOWBYTE 0x00f0 | |
54 | #define _DECODE_LOWNIB_HIGHBYTE 0x0f00 | |
55 | #define _DECODE_HIGHNIB_HIGHBYTE 0xf000 | |
56 | #define _DECODE_HIGHBYTE 0xff00 | |
57 | #define _DECODE_LOWBYTE 0x00ff | |
58 | #define _DECODE_4TO6_HIGHBYTE 0x7000 | |
59 | #define _DECODE_4TO6_LOWBYTE 0x0070 | |
60 | #define _DECODE_0TO6_HIGHBYTE 0x7f00 | |
61 | #define _DECODE_0TO2_HIGHBYTE 0x0700 | |
62 | #define _DECODE_GET_F_HIGHBYTE 0x8000 | |
63 | #define _DECODE_BIT7_HIGHBYTE 0x8000 | |
64 | #define _DECODE_BIT7_LOWBYTE 0x0080 | |
65 | #define _DECODE_GET_CARRY 0x10000 | |
66 | #define _DECODE_BIT0_LOWBYTE 0x1 | |
67 | #define _DECODE_BIT6AND7_HIGHBYTE 0xc000 | |
68 | ||
69 | /* Module and Register Indexed of System Registers. */ | |
70 | #define _CURR_ACC_MODINDEX 0xa | |
71 | #define _CURR_ACC_REGINDEX 0x0 | |
72 | #define _PSF_REG_MODINDEX 0x8 | |
73 | #define _PSF_REG_REGINDEX 0x4 | |
74 | #define _PFX_REG_MODINDEX 0xb | |
75 | #define _PFX0_REG_REGINDEX 0x0 | |
76 | #define _PFX2_REG_REGINDEX 0x2 | |
77 | #define _DP_REG_MODINDEX 0xf | |
78 | #define _DP0_REG_REGINDEX 0x3 | |
79 | #define _DP1_REG_REGINDEX 0x7 | |
80 | #define _IP_REG_MODINDEX 0xc | |
81 | #define _IP_REG_REGINDEX 0x0 | |
82 | #define _IIR_REG_MODINDEX 0x8 | |
83 | #define _IIR_REG_REGINDEX 0xb | |
84 | #define _SP_REG_MODINDEX 0xd | |
85 | #define _SP_REG_REGINDEX 0x1 | |
86 | #define _IC_REG_MODINDEX 0x8 | |
87 | #define _IC_REG_REGINDEX 0x5 | |
88 | #define _LC_REG_MODINDEX 0xe | |
89 | #define _LC0_REG_REGINDEX 0x0 | |
90 | #define _LC1_REG_REGINDEX 0x1 | |
91 | #define _LC2_REG_REGINDEX 0x2 | |
92 | #define _LC3_REG_REGINDEX 0x3 | |
93 | ||
94 | /* Flags for finding the bits in PSF Register. */ | |
95 | #define SIM_ALU_DECODE_CARRY_BIT_POS 0x2 | |
96 | #define SIM_ALU_DECODE_SIGN_BIT_POS 0x40 | |
97 | #define SIM_ALU_DECODE_ZERO_BIT_POS 0x80 | |
98 | #define SIM_ALU_DECODE_EQUAL_BIT_POS 0x1 | |
99 | #define SIM_ALU_DECODE_IGE_BIT_POS 0x1 | |
100 | ||
101 | /* Number Of Op-code Groups. */ | |
102 | unsigned char const SIM_ALU_DECODE_OPCODE_GROUPS = 11; | |
103 | ||
104 | /* Op-code Groups. */ | |
105 | unsigned char const SIM_ALU_DECODE_LOGICAL_XCHG_OP_GROUP = 1; | |
106 | ||
107 | /* Group1: AND/OR/XOR/ADD/SUB Operations: fxxx 1010 ssss ssss. */ | |
108 | unsigned char const SIM_ALU_DECODE_AND_OR_ADD_SUB_OP_GROUP = 2; | |
109 | ||
110 | /* Group2: Logical Operations: 1000 1010 xxxx 1010. */ | |
111 | unsigned char const SIM_ALU_DECODE_BIT_OP_GROUP = 3; | |
112 | ||
113 | /* XCHG/Bit Operations: 1xxx 1010 xxxx 1010. */ | |
114 | unsigned char const SIM_ALU_DECODE_SET_DEST_BIT_GROUP = 4; | |
115 | ||
116 | /* Move value in bit of destination register: 1ddd dddd xbbb 0111. */ | |
117 | unsigned char const SIM_ALU_DECODE_JUMP_OP_GROUP = 5; | |
118 | ||
119 | #define JUMP_CHECK(insn) \ | |
120 | ( ((insn & _DECODE_4TO6_HIGHBYTE) == 0x0000) \ | |
121 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x2000) \ | |
122 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x6000) \ | |
123 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x1000) \ | |
124 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x5000) \ | |
125 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x3000) \ | |
126 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x7000) \ | |
127 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x4000) ) | |
128 | ||
129 | /* JUMP operations: fxxx 1100 ssss ssss */ | |
130 | unsigned char const SIM_ALU_DECODE_RET_OP_GROUP = 6; | |
131 | ||
132 | /* RET Operations: 1xxx 1100 0000 1101 */ | |
133 | unsigned char const SIM_ALU_DECODE_MOVE_SRC_DST_GROUP = 7; | |
134 | ||
135 | /* Move src into dest register: fddd dddd ssss ssss */ | |
136 | unsigned char const SIM_ALU_DECODE_SET_SRC_BIT_GROUP = 8; | |
137 | ||
138 | /* Move value in bit of source register: fbbb 0111 ssss ssss */ | |
139 | unsigned char const SIM_ALU_DECODE_DJNZ_CALL_PUSH_OP_GROUP = 9; | |
140 | ||
141 | /* PUSH, DJNZ and CALL operations: fxxx 1101 ssss ssss */ | |
142 | unsigned char const SIM_ALU_DECODE_POP_OP_GROUP = 10; | |
143 | ||
144 | /* POP operation: 1ddd dddd 0000 1101 */ | |
145 | unsigned char const SIM_ALU_DECODE_CMP_SRC_OP_GROUP = 11; | |
146 | ||
147 | /* GLOBAL */ | |
53c9ebc5 | 148 | char unres_reg_name[20]; |
7499d566 | 149 | |
53c9ebc5 | 150 | static char * |
7499d566 NC |
151 | get_reg_name (unsigned char reg_code, type1 arg_pos) |
152 | { | |
153 | unsigned char module; | |
91d6fa6a | 154 | unsigned char r_index; |
7499d566 NC |
155 | int ix = 0; |
156 | reg_entry const *reg_x; | |
157 | mem_access_syntax const *syntax; | |
158 | mem_access *mem_acc; | |
159 | ||
160 | module = 0; | |
91d6fa6a | 161 | r_index = 0; |
7499d566 | 162 | module = (reg_code & MASK_LOW_BYTE); |
91d6fa6a NC |
163 | r_index = (reg_code & MASK_HIGH_BYTE); |
164 | r_index = r_index >> 4; | |
7499d566 NC |
165 | |
166 | /* Search the system register table. */ | |
167 | for (reg_x = &system_reg_table[0]; reg_x->reg_name != NULL; ++reg_x) | |
91d6fa6a | 168 | if ((reg_x->Mod_name == module) && (reg_x->Mod_index == r_index)) |
7499d566 NC |
169 | return reg_x->reg_name; |
170 | ||
171 | /* Serch pheripheral table. */ | |
172 | for (ix = 0; ix < num_of_reg; ix++) | |
173 | { | |
174 | reg_x = &new_reg_table[ix]; | |
175 | ||
91d6fa6a | 176 | if ((reg_x->Mod_name == module) && (reg_x->Mod_index == r_index)) |
7499d566 NC |
177 | return reg_x->reg_name; |
178 | } | |
179 | ||
180 | for (mem_acc = &mem_table[0]; mem_acc->name != NULL || !mem_acc; ++mem_acc) | |
181 | { | |
182 | if (reg_code == mem_acc->opcode) | |
183 | { | |
184 | for (syntax = mem_access_syntax_table; | |
c908d778 | 185 | syntax != NULL && syntax->name; |
7499d566 NC |
186 | ++syntax) |
187 | if (!strcmp (mem_acc->name, syntax->name)) | |
188 | { | |
189 | if ((arg_pos == syntax->type) || (syntax->type == BOTH)) | |
190 | return mem_acc->name; | |
191 | ||
192 | break; | |
193 | } | |
194 | } | |
195 | } | |
196 | ||
197 | memset (unres_reg_name, 0, 20); | |
91d6fa6a | 198 | sprintf (unres_reg_name, "%01x%01xh", r_index, module); |
7499d566 NC |
199 | |
200 | return unres_reg_name; | |
201 | } | |
202 | ||
203 | static bfd_boolean | |
204 | check_move (unsigned char insn0, unsigned char insn8) | |
205 | { | |
206 | bfd_boolean first = FALSE; | |
207 | bfd_boolean second = FALSE; | |
7499d566 NC |
208 | reg_entry const *reg_x; |
209 | const unsigned char module1 = insn0 & MASK_LOW_BYTE; | |
210 | const unsigned char index1 = ((insn0 & 0x70) >> 4); | |
211 | const unsigned char module2 = insn8 & MASK_LOW_BYTE; | |
212 | const unsigned char index2 = ((insn8 & MASK_HIGH_BYTE) >> 4); | |
213 | ||
214 | /* DST */ | |
215 | if (((insn0 & MASK_LOW_BYTE) == MASK_LOW_BYTE) | |
216 | && ((index1 == 0) || (index1 == 1) || (index1 == 2) || (index1 == 5) | |
217 | || (index1 == 4) || (index1 == 6))) | |
218 | first = TRUE; | |
219 | ||
220 | else if (((insn0 & MASK_LOW_BYTE) == 0x0D) && (index1 == 0)) | |
221 | first = TRUE; | |
222 | ||
223 | else if ((module1 == 0x0E) | |
224 | && ((index1 == 0) || (index1 == 1) || (index1 == 2))) | |
225 | first = TRUE; | |
226 | ||
227 | else | |
228 | { | |
229 | for (reg_x = &system_reg_table[0]; reg_x->reg_name != NULL && reg_x; | |
230 | ++reg_x) | |
231 | { | |
232 | if ((reg_x->Mod_name == module1) && (reg_x->Mod_index == index1) | |
233 | && ((reg_x->rtype == Reg_16W) || (reg_x->rtype == Reg_8W))) | |
234 | { | |
235 | /* IP not allowed. */ | |
236 | if ((reg_x->Mod_name == 0x0C) && (reg_x->Mod_index == 0x00)) | |
237 | continue; | |
238 | ||
239 | /* A[AP] not allowed. */ | |
240 | if ((reg_x->Mod_name == 0x0A) && (reg_x->Mod_index == 0x01)) | |
241 | continue; | |
7499d566 NC |
242 | first = TRUE; |
243 | break; | |
244 | } | |
245 | } | |
246 | } | |
247 | ||
248 | if (!first) | |
249 | /* No need to check further. */ | |
250 | return FALSE; | |
251 | ||
252 | if (insn0 & 0x80) | |
253 | { | |
254 | /* SRC */ | |
255 | if (((insn8 & MASK_LOW_BYTE) == MASK_LOW_BYTE) | |
256 | && ((index2 == 0) || (index2 == 1) || (index2 == 2) || (index2 == 4) | |
257 | || (index2 == 5) || (index2 == 6))) | |
258 | second = TRUE; | |
259 | ||
260 | else if (((insn8 & MASK_LOW_BYTE) == 0x0D) && (index2 == 0)) | |
261 | second = TRUE; | |
262 | ||
263 | else if ((module2 == 0x0E) | |
264 | && ((index2 == 0) || (index2 == 1) || (index2 == 2))) | |
265 | second = TRUE; | |
266 | ||
267 | else | |
268 | { | |
269 | for (reg_x = &system_reg_table[0]; | |
270 | reg_x->reg_name != NULL && reg_x; | |
271 | ++reg_x) | |
272 | { | |
273 | if ((reg_x->Mod_name == (insn8 & MASK_LOW_BYTE)) | |
274 | && (reg_x->Mod_index == (((insn8 & 0xf0) >> 4)))) | |
275 | { | |
276 | second = TRUE; | |
7499d566 NC |
277 | break; |
278 | } | |
279 | } | |
280 | } | |
281 | ||
282 | if (second) | |
283 | { | |
284 | if ((module1 == 0x0A && index1 == 0x0) | |
285 | && (module2 == 0x0A && index2 == 0x01)) | |
286 | return FALSE; | |
287 | ||
288 | return TRUE; | |
289 | } | |
290 | ||
291 | return FALSE; | |
292 | } | |
293 | ||
294 | return first; | |
295 | } | |
296 | ||
297 | static void | |
298 | maxq_print_arg (MAX_ARG_TYPE arg, | |
299 | struct disassemble_info * info, | |
300 | group_info grp) | |
301 | { | |
302 | switch (arg) | |
303 | { | |
304 | case FLAG_C: | |
305 | info->fprintf_func (info->stream, "C"); | |
306 | break; | |
307 | case FLAG_NC: | |
308 | info->fprintf_func (info->stream, "NC"); | |
309 | break; | |
310 | ||
311 | case FLAG_Z: | |
312 | info->fprintf_func (info->stream, "Z"); | |
313 | break; | |
314 | ||
315 | case FLAG_NZ: | |
316 | info->fprintf_func (info->stream, "NZ"); | |
317 | break; | |
318 | ||
319 | case FLAG_S: | |
320 | info->fprintf_func (info->stream, "S"); | |
321 | break; | |
322 | ||
323 | case FLAG_E: | |
324 | info->fprintf_func (info->stream, "E"); | |
325 | break; | |
326 | ||
327 | case FLAG_NE: | |
328 | info->fprintf_func (info->stream, "NE"); | |
329 | break; | |
330 | ||
331 | case ACC_BIT: | |
332 | info->fprintf_func (info->stream, "Acc"); | |
333 | if ((grp.flag & BIT_NO) == BIT_NO) | |
334 | info->fprintf_func (info->stream, ".%d", grp.bit_no); | |
335 | break; | |
336 | ||
337 | case A_BIT_0: | |
338 | info->fprintf_func (info->stream, "#0"); | |
339 | break; | |
340 | case A_BIT_1: | |
341 | info->fprintf_func (info->stream, "#1"); | |
342 | break; | |
343 | ||
344 | default: | |
345 | break; | |
346 | } | |
347 | } | |
348 | ||
349 | static unsigned char | |
350 | get_group (const unsigned int insn) | |
351 | { | |
352 | if (check_move ((insn >> 8), (insn & _DECODE_LOWBYTE))) | |
353 | return 8; | |
354 | ||
355 | if ((insn & _DECODE_LOWNIB_HIGHBYTE) == 0x0A00) | |
356 | { | |
ca4f2377 AM |
357 | /* && condition with sec part added on 26 May for resolving 2 & 3 grp |
358 | conflict. */ | |
7499d566 NC |
359 | if (((insn & _DECODE_LOWNIB_LOWBYTE) == 0x000A) |
360 | && ((insn & _DECODE_GET_F_HIGHBYTE) == 0x8000)) | |
361 | { | |
362 | if ((insn & _DECODE_HIGHNIB_HIGHBYTE) == 0x8000) | |
363 | return 2; | |
364 | else | |
365 | return 3; | |
366 | } | |
367 | ||
368 | return 1; | |
369 | } | |
370 | else if ((insn & _DECODE_LOWNIB_HIGHBYTE) == 0x0C00) | |
371 | { | |
372 | if (((insn & _DECODE_LOWBYTE) == 0x000D) && JUMP_CHECK (insn) | |
373 | && ((insn & _DECODE_GET_F_HIGHBYTE) == 0x8000)) | |
374 | return 6; | |
375 | else if ((insn & _DECODE_LOWBYTE) == 0x008D) | |
376 | return 7; | |
377 | ||
378 | return 5; | |
379 | } | |
380 | else if (((insn & _DECODE_LOWNIB_HIGHBYTE) == 0x0D00) | |
381 | && (((insn & _DECODE_4TO6_HIGHBYTE) == 0x3000) | |
382 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x4000) | |
383 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x5000) | |
384 | || ((insn & _DECODE_4TO6_HIGHBYTE) == 0x0000))) | |
385 | return 10; | |
386 | ||
387 | else if ((insn & _DECODE_LOWBYTE) == 0x000D) | |
388 | return 11; | |
389 | ||
390 | else if ((insn & _DECODE_LOWBYTE) == 0x008D) | |
391 | return 12; | |
392 | ||
393 | else if ((insn & _DECODE_0TO6_HIGHBYTE) == 0x7800) | |
394 | return 13; | |
395 | ||
396 | else if ((insn & _DECODE_LOWNIB_HIGHBYTE) == 0x0700) | |
397 | return 9; | |
398 | ||
399 | else if (((insn & _DECODE_LOWNIB_LOWBYTE) == 0x0007) | |
400 | && ((insn & _DECODE_GET_F_HIGHBYTE) == 0x8000)) | |
401 | return 4; | |
402 | ||
403 | return 8; | |
404 | } | |
405 | ||
406 | static void | |
407 | get_insn_opcode (const unsigned int insn, group_info *i) | |
408 | { | |
409 | static unsigned char pfx_flag = 0; | |
410 | static unsigned char count_for_pfx = 0; | |
411 | ||
412 | i->flag ^= i->flag; | |
413 | i->bit_no ^= i->bit_no; | |
414 | i->dst ^= i->dst; | |
415 | i->fbit ^= i->fbit; | |
416 | i->group_no ^= i->group_no; | |
417 | i->src ^= i->src; | |
418 | i->sub_opcode ^= i->sub_opcode; | |
419 | ||
420 | if (count_for_pfx > 0) | |
421 | count_for_pfx++; | |
422 | ||
423 | if (((insn >> 8) == 0x0b) || ((insn >> 8) == 0x2b)) | |
424 | { | |
425 | pfx_flag = 1; | |
426 | count_for_pfx = 1; | |
427 | } | |
428 | ||
429 | i->group_no = get_group (insn); | |
430 | ||
431 | if (pfx_flag && (i->group_no == 0x0D) && (count_for_pfx == 2) | |
432 | && ((insn & _DECODE_0TO6_HIGHBYTE) == 0x7800)) | |
433 | { | |
434 | i->group_no = 0x08; | |
435 | count_for_pfx = 0; | |
436 | pfx_flag ^= pfx_flag; | |
437 | } | |
438 | ||
439 | switch (i->group_no) | |
440 | { | |
441 | case 1: | |
442 | i->sub_opcode = ((insn & _DECODE_4TO6_HIGHBYTE) >> 12); | |
443 | i->flag |= SUB_OP; | |
444 | i->src = ((insn & _DECODE_LOWBYTE)); | |
445 | i->flag |= SRC; | |
446 | i->fbit = ((insn & _DECODE_GET_F_HIGHBYTE) >> 15); | |
447 | i->flag |= FORMAT; | |
448 | break; | |
449 | ||
450 | case 2: | |
451 | i->sub_opcode = ((insn & _DECODE_HIGHNIB_LOWBYTE) >> 4); | |
452 | i->flag |= SUB_OP; | |
453 | break; | |
454 | ||
455 | case 3: | |
456 | i->sub_opcode = ((insn & _DECODE_HIGHNIB_HIGHBYTE) >> 12); | |
457 | i->flag |= SUB_OP; | |
458 | i->bit_no = ((insn & _DECODE_HIGHNIB_LOWBYTE) >> 4); | |
459 | i->flag |= BIT_NO; | |
460 | break; | |
461 | ||
462 | case 4: | |
463 | i->sub_opcode = ((insn & _DECODE_BIT7_LOWBYTE) >> 7); | |
464 | i->flag |= SUB_OP; | |
465 | i->dst = ((insn & _DECODE_0TO6_HIGHBYTE) >> 8); | |
466 | i->flag |= DST; | |
467 | i->bit_no = ((insn & _DECODE_4TO6_LOWBYTE) >> 4); | |
468 | i->flag |= BIT_NO; | |
469 | break; | |
470 | ||
471 | case 5: | |
472 | i->sub_opcode = ((insn & _DECODE_4TO6_HIGHBYTE) >> 12); | |
473 | i->flag |= SUB_OP; | |
474 | i->src = ((insn & _DECODE_LOWBYTE)); | |
475 | i->flag |= SRC; | |
476 | i->fbit = ((insn & _DECODE_GET_F_HIGHBYTE) >> 15); | |
477 | i->flag |= FORMAT; | |
478 | break; | |
479 | ||
480 | case 6: | |
481 | i->sub_opcode = ((insn & _DECODE_HIGHNIB_HIGHBYTE) >> 12); | |
482 | i->flag |= SUB_OP; | |
483 | break; | |
484 | ||
485 | case 7: | |
486 | i->sub_opcode = ((insn & _DECODE_HIGHNIB_HIGHBYTE) >> 12); | |
487 | i->flag |= SUB_OP; | |
488 | break; | |
489 | ||
490 | case 8: | |
491 | i->dst = ((insn & _DECODE_0TO6_HIGHBYTE) >> 8); | |
492 | i->flag |= DST; | |
493 | i->src = ((insn & _DECODE_LOWBYTE)); | |
494 | i->flag |= SRC; | |
495 | i->fbit = ((insn & _DECODE_GET_F_HIGHBYTE) >> 15); | |
496 | i->flag |= FORMAT; | |
497 | break; | |
498 | ||
499 | case 9: | |
500 | i->sub_opcode = ((insn & _DECODE_0TO2_HIGHBYTE) >> 8); | |
501 | i->flag |= SUB_OP; | |
502 | i->bit_no = ((insn & _DECODE_4TO6_HIGHBYTE) >> 12); | |
503 | i->flag |= BIT_NO; | |
504 | i->fbit = ((insn & _DECODE_GET_F_HIGHBYTE) >> 15); | |
505 | i->flag |= FORMAT; | |
506 | i->src = ((insn & _DECODE_LOWBYTE)); | |
507 | i->flag |= SRC; | |
508 | break; | |
509 | ||
510 | case 10: | |
511 | i->sub_opcode = ((insn & _DECODE_4TO6_HIGHBYTE) >> 12); | |
512 | i->flag |= SUB_OP; | |
513 | i->src = ((insn & _DECODE_LOWBYTE)); | |
514 | i->flag |= SRC; | |
515 | i->fbit = ((insn & _DECODE_GET_F_HIGHBYTE) >> 15); | |
516 | i->flag |= FORMAT; | |
517 | break; | |
518 | ||
519 | case 11: | |
520 | i->dst = ((insn & _DECODE_0TO6_HIGHBYTE) >> 8); | |
521 | i->flag |= DST; | |
522 | break; | |
523 | ||
524 | case 12: | |
525 | i->dst = ((insn & _DECODE_0TO6_HIGHBYTE) >> 8); | |
526 | i->flag |= DST; | |
527 | break; | |
528 | ||
529 | case 13: | |
530 | i->sub_opcode = ((insn & _DECODE_4TO6_HIGHBYTE) >> 12); | |
531 | i->flag |= SUB_OP; | |
532 | i->src = ((insn & _DECODE_LOWBYTE)); | |
533 | i->flag |= SRC; | |
534 | i->fbit = ((insn & _DECODE_GET_F_HIGHBYTE) >> 15); | |
535 | i->flag |= FORMAT; | |
536 | break; | |
537 | ||
538 | } | |
539 | return; | |
540 | } | |
541 | ||
542 | ||
543 | /* Print one instruction from MEMADDR on INFO->STREAM. Return the size of the | |
544 | instruction (always 2 on MAXQ20). */ | |
545 | ||
546 | static int | |
547 | print_insn (bfd_vma memaddr, struct disassemble_info *info, | |
548 | enum bfd_endian endianess) | |
549 | { | |
550 | /* The raw instruction. */ | |
c7e2358a | 551 | unsigned char insn[2], derived_code; |
7499d566 NC |
552 | unsigned int format; |
553 | unsigned int actual_operands; | |
554 | unsigned int i; | |
555 | /* The group_info collected/decoded. */ | |
556 | group_info grp; | |
557 | MAXQ20_OPCODE_INFO const *opcode; | |
558 | int status; | |
559 | ||
560 | format = 0; | |
561 | ||
562 | status = info->read_memory_func (memaddr, (bfd_byte *) & insn[0], 2, info); | |
563 | ||
564 | if (status != 0) | |
565 | { | |
566 | info->memory_error_func (status, memaddr, info); | |
567 | return -1; | |
568 | } | |
569 | ||
7499d566 NC |
570 | /* FIXME: Endianness always little. */ |
571 | if (endianess == BFD_ENDIAN_BIG) | |
572 | get_insn_opcode (((insn[0] << 8) | (insn[1])), &grp); | |
573 | else | |
574 | get_insn_opcode (((insn[1] << 8) | (insn[0])), &grp); | |
575 | ||
576 | derived_code = ((grp.group_no << 4) | grp.sub_opcode); | |
577 | ||
578 | if (insn[0] == 0 && insn[1] == 0) | |
579 | { | |
580 | info->fprintf_func (info->stream, "00 00"); | |
581 | return 2; | |
582 | } | |
583 | ||
c7e2358a | 584 | /* The opcode is always in insn[0]. */ |
7499d566 NC |
585 | for (opcode = &op_table[0]; opcode->name != NULL; ++opcode) |
586 | { | |
587 | if (opcode->instr_id == derived_code) | |
588 | { | |
589 | if (opcode->instr_id == 0x3D) | |
590 | { | |
591 | if ((grp.bit_no == 0) && (opcode->arg[1] != A_BIT_0)) | |
592 | continue; | |
593 | if ((grp.bit_no == 1) && (opcode->arg[1] != A_BIT_1)) | |
594 | continue; | |
595 | if ((grp.bit_no == 3) && (opcode->arg[0] != 0)) | |
596 | continue; | |
597 | } | |
598 | ||
599 | info->fprintf_func (info->stream, "%s ", opcode->name); | |
600 | ||
601 | actual_operands = 0; | |
602 | ||
603 | if ((grp.flag & SRC) == SRC) | |
604 | actual_operands++; | |
605 | ||
606 | if ((grp.flag & DST) == DST) | |
607 | actual_operands++; | |
608 | ||
609 | /* If Implict FLAG in the Instruction. */ | |
610 | if ((opcode->op_number > actual_operands) | |
611 | && !((grp.flag & SRC) == SRC) && !((grp.flag & DST) == DST)) | |
612 | { | |
613 | for (i = 0; i < opcode->op_number; i++) | |
614 | { | |
615 | if (i == 1 && (opcode->arg[1] != NO_ARG)) | |
616 | info->fprintf_func (info->stream, ","); | |
617 | maxq_print_arg (opcode->arg[i], info, grp); | |
618 | } | |
619 | } | |
620 | ||
621 | /* DST is ABSENT in the grp. */ | |
622 | if ((opcode->op_number > actual_operands) | |
623 | && ((grp.flag & SRC) == SRC)) | |
624 | { | |
625 | maxq_print_arg (opcode->arg[0], info, grp); | |
626 | info->fprintf_func (info->stream, " "); | |
627 | ||
628 | if (opcode->instr_id == 0xA4) | |
629 | info->fprintf_func (info->stream, "LC[0]"); | |
630 | ||
631 | if (opcode->instr_id == 0xA5) | |
632 | info->fprintf_func (info->stream, "LC[1]"); | |
633 | ||
634 | if ((grp.flag & SRC) == SRC) | |
635 | info->fprintf_func (info->stream, ","); | |
636 | } | |
637 | ||
638 | if ((grp.flag & DST) == DST) | |
639 | { | |
640 | if ((grp.flag & BIT_NO) == BIT_NO) | |
641 | { | |
642 | info->fprintf_func (info->stream, " %s.%d", | |
643 | get_reg_name (grp.dst, | |
644 | (type1) 0 /*DST*/), | |
645 | grp.bit_no); | |
646 | } | |
647 | else | |
ca4f2377 AM |
648 | info->fprintf_func (info->stream, " %s", |
649 | get_reg_name (grp.dst, (type1) 0)); | |
7499d566 NC |
650 | } |
651 | ||
652 | /* SRC is ABSENT in the grp. */ | |
653 | if ((opcode->op_number > actual_operands) | |
654 | && ((grp.flag & DST) == DST)) | |
655 | { | |
656 | info->fprintf_func (info->stream, ","); | |
657 | maxq_print_arg (opcode->arg[1], info, grp); | |
658 | info->fprintf_func (info->stream, " "); | |
659 | } | |
660 | ||
661 | if ((grp.flag & SRC) == SRC) | |
662 | { | |
663 | if ((grp.flag & DST) == DST) | |
664 | info->fprintf_func (info->stream, ","); | |
665 | ||
666 | if ((grp.flag & BIT_NO) == BIT_NO) | |
667 | { | |
668 | format = opcode->format; | |
669 | ||
670 | if ((grp.flag & FORMAT) == FORMAT) | |
671 | format = grp.fbit; | |
672 | if (format == 1) | |
673 | info->fprintf_func (info->stream, " %s.%d", | |
674 | get_reg_name (grp.src, | |
675 | (type1) 1 /*SRC*/), | |
676 | grp.bit_no); | |
677 | if (format == 0) | |
678 | info->fprintf_func (info->stream, " #%02xh.%d", | |
ca4f2377 | 679 | grp.src, grp.bit_no); |
7499d566 NC |
680 | } |
681 | else | |
682 | { | |
683 | format = opcode->format; | |
684 | ||
685 | if ((grp.flag & FORMAT) == FORMAT) | |
686 | format = grp.fbit; | |
687 | if (format == 1) | |
688 | info->fprintf_func (info->stream, " %s", | |
ca4f2377 AM |
689 | get_reg_name (grp.src, |
690 | (type1) 1 /*SRC*/)); | |
7499d566 NC |
691 | if (format == 0) |
692 | info->fprintf_func (info->stream, " #%02xh", | |
ca4f2377 | 693 | (grp.src)); |
7499d566 NC |
694 | } |
695 | } | |
696 | ||
697 | return 2; | |
698 | } | |
699 | } | |
700 | ||
701 | info->fprintf_func (info->stream, "Unable to Decode : %02x %02x", | |
ca4f2377 | 702 | insn[0], insn[1]); |
7499d566 NC |
703 | return 2; |
704 | } | |
705 | ||
706 | int | |
707 | print_insn_maxq_little (bfd_vma memaddr, struct disassemble_info *info) | |
708 | { | |
709 | return print_insn (memaddr, info, BFD_ENDIAN_LITTLE); | |
710 | } |