tic30-dis.c revision 1.1.1.2 1 1.1 skrll /* Disassembly routines for TMS320C30 architecture
2 1.1.1.2 christos Copyright 1998, 1999, 2000, 2002, 2005, 2007, 2009
3 1.1.1.2 christos Free Software Foundation, Inc.
4 1.1 skrll Contributed by Steven Haworth (steve (at) pm.cse.rmit.edu.au)
5 1.1 skrll
6 1.1 skrll This file is part of the GNU opcodes library.
7 1.1 skrll
8 1.1 skrll This library is free software; you can redistribute it and/or modify
9 1.1 skrll it under the terms of the GNU General Public License as published by
10 1.1 skrll the Free Software Foundation; either version 3, or (at your option)
11 1.1 skrll any later version.
12 1.1 skrll
13 1.1 skrll It is distributed in the hope that it will be useful, but WITHOUT
14 1.1 skrll ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 1.1 skrll or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 1.1 skrll License for more details.
17 1.1 skrll
18 1.1 skrll You should have received a copy of the GNU General Public License
19 1.1 skrll along with this file; see the file COPYING. If not, write to the
20 1.1 skrll Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
21 1.1 skrll MA 02110-1301, USA. */
22 1.1 skrll
23 1.1 skrll #include <errno.h>
24 1.1 skrll #include <math.h>
25 1.1 skrll #include "sysdep.h"
26 1.1 skrll #include "dis-asm.h"
27 1.1 skrll #include "opcode/tic30.h"
28 1.1 skrll
29 1.1 skrll #define NORMAL_INSN 1
30 1.1 skrll #define PARALLEL_INSN 2
31 1.1 skrll
32 1.1 skrll /* Gets the type of instruction based on the top 2 or 3 bits of the
33 1.1 skrll instruction word. */
34 1.1 skrll #define GET_TYPE(insn) (insn & 0x80000000 ? insn & 0xC0000000 : insn & 0xE0000000)
35 1.1 skrll
36 1.1 skrll /* Instruction types. */
37 1.1 skrll #define TWO_OPERAND_1 0x00000000
38 1.1 skrll #define TWO_OPERAND_2 0x40000000
39 1.1 skrll #define THREE_OPERAND 0x20000000
40 1.1 skrll #define PAR_STORE 0xC0000000
41 1.1 skrll #define MUL_ADDS 0x80000000
42 1.1 skrll #define BRANCHES 0x60000000
43 1.1 skrll
44 1.1 skrll /* Specific instruction id bits. */
45 1.1 skrll #define NORMAL_IDEN 0x1F800000
46 1.1 skrll #define PAR_STORE_IDEN 0x3E000000
47 1.1 skrll #define MUL_ADD_IDEN 0x2C000000
48 1.1 skrll #define BR_IMM_IDEN 0x1F000000
49 1.1 skrll #define BR_COND_IDEN 0x1C3F0000
50 1.1 skrll
51 1.1 skrll /* Addressing modes. */
52 1.1 skrll #define AM_REGISTER 0x00000000
53 1.1 skrll #define AM_DIRECT 0x00200000
54 1.1 skrll #define AM_INDIRECT 0x00400000
55 1.1 skrll #define AM_IMM 0x00600000
56 1.1 skrll
57 1.1 skrll #define P_FIELD 0x03000000
58 1.1 skrll
59 1.1 skrll #define REG_AR0 0x08
60 1.1 skrll #define LDP_INSN 0x08700000
61 1.1 skrll
62 1.1 skrll /* TMS320C30 program counter for current instruction. */
63 1.1 skrll static unsigned int _pc;
64 1.1 skrll
65 1.1 skrll struct instruction
66 1.1 skrll {
67 1.1 skrll int type;
68 1.1.1.2 christos insn_template *tm;
69 1.1 skrll partemplate *ptm;
70 1.1 skrll };
71 1.1 skrll
72 1.1 skrll static int
73 1.1 skrll get_tic30_instruction (unsigned long insn_word, struct instruction *insn)
74 1.1 skrll {
75 1.1 skrll switch (GET_TYPE (insn_word))
76 1.1 skrll {
77 1.1 skrll case TWO_OPERAND_1:
78 1.1 skrll case TWO_OPERAND_2:
79 1.1 skrll case THREE_OPERAND:
80 1.1 skrll insn->type = NORMAL_INSN;
81 1.1 skrll {
82 1.1.1.2 christos insn_template *current_optab = (insn_template *) tic30_optab;
83 1.1 skrll
84 1.1 skrll for (; current_optab < tic30_optab_end; current_optab++)
85 1.1 skrll {
86 1.1 skrll if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
87 1.1 skrll {
88 1.1 skrll if (current_optab->operands == 0)
89 1.1 skrll {
90 1.1 skrll if (current_optab->base_opcode == insn_word)
91 1.1 skrll {
92 1.1 skrll insn->tm = current_optab;
93 1.1 skrll break;
94 1.1 skrll }
95 1.1 skrll }
96 1.1 skrll else if ((current_optab->base_opcode & NORMAL_IDEN) == (insn_word & NORMAL_IDEN))
97 1.1 skrll {
98 1.1 skrll insn->tm = current_optab;
99 1.1 skrll break;
100 1.1 skrll }
101 1.1 skrll }
102 1.1 skrll }
103 1.1 skrll }
104 1.1 skrll break;
105 1.1 skrll
106 1.1 skrll case PAR_STORE:
107 1.1 skrll insn->type = PARALLEL_INSN;
108 1.1 skrll {
109 1.1 skrll partemplate *current_optab = (partemplate *) tic30_paroptab;
110 1.1 skrll
111 1.1 skrll for (; current_optab < tic30_paroptab_end; current_optab++)
112 1.1 skrll {
113 1.1 skrll if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
114 1.1 skrll {
115 1.1 skrll if ((current_optab->base_opcode & PAR_STORE_IDEN)
116 1.1 skrll == (insn_word & PAR_STORE_IDEN))
117 1.1 skrll {
118 1.1 skrll insn->ptm = current_optab;
119 1.1 skrll break;
120 1.1 skrll }
121 1.1 skrll }
122 1.1 skrll }
123 1.1 skrll }
124 1.1 skrll break;
125 1.1 skrll
126 1.1 skrll case MUL_ADDS:
127 1.1 skrll insn->type = PARALLEL_INSN;
128 1.1 skrll {
129 1.1 skrll partemplate *current_optab = (partemplate *) tic30_paroptab;
130 1.1 skrll
131 1.1 skrll for (; current_optab < tic30_paroptab_end; current_optab++)
132 1.1 skrll {
133 1.1 skrll if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
134 1.1 skrll {
135 1.1 skrll if ((current_optab->base_opcode & MUL_ADD_IDEN)
136 1.1 skrll == (insn_word & MUL_ADD_IDEN))
137 1.1 skrll {
138 1.1 skrll insn->ptm = current_optab;
139 1.1 skrll break;
140 1.1 skrll }
141 1.1 skrll }
142 1.1 skrll }
143 1.1 skrll }
144 1.1 skrll break;
145 1.1 skrll
146 1.1 skrll case BRANCHES:
147 1.1 skrll insn->type = NORMAL_INSN;
148 1.1 skrll {
149 1.1.1.2 christos insn_template *current_optab = (insn_template *) tic30_optab;
150 1.1 skrll
151 1.1 skrll for (; current_optab < tic30_optab_end; current_optab++)
152 1.1 skrll {
153 1.1 skrll if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
154 1.1 skrll {
155 1.1 skrll if (current_optab->operand_types[0] & Imm24)
156 1.1 skrll {
157 1.1 skrll if ((current_optab->base_opcode & BR_IMM_IDEN)
158 1.1 skrll == (insn_word & BR_IMM_IDEN))
159 1.1 skrll {
160 1.1 skrll insn->tm = current_optab;
161 1.1 skrll break;
162 1.1 skrll }
163 1.1 skrll }
164 1.1 skrll else if (current_optab->operands > 0)
165 1.1 skrll {
166 1.1 skrll if ((current_optab->base_opcode & BR_COND_IDEN)
167 1.1 skrll == (insn_word & BR_COND_IDEN))
168 1.1 skrll {
169 1.1 skrll insn->tm = current_optab;
170 1.1 skrll break;
171 1.1 skrll }
172 1.1 skrll }
173 1.1 skrll else
174 1.1 skrll {
175 1.1 skrll if ((current_optab->base_opcode & (BR_COND_IDEN | 0x00800000))
176 1.1 skrll == (insn_word & (BR_COND_IDEN | 0x00800000)))
177 1.1 skrll {
178 1.1 skrll insn->tm = current_optab;
179 1.1 skrll break;
180 1.1 skrll }
181 1.1 skrll }
182 1.1 skrll }
183 1.1 skrll }
184 1.1 skrll }
185 1.1 skrll break;
186 1.1 skrll default:
187 1.1 skrll return 0;
188 1.1 skrll }
189 1.1 skrll return 1;
190 1.1 skrll }
191 1.1 skrll
192 1.1 skrll static int
193 1.1 skrll get_register_operand (unsigned char fragment, char *buffer)
194 1.1 skrll {
195 1.1 skrll const reg *current_reg = tic30_regtab;
196 1.1 skrll
197 1.1 skrll if (buffer == NULL)
198 1.1 skrll return 0;
199 1.1 skrll for (; current_reg < tic30_regtab_end; current_reg++)
200 1.1 skrll {
201 1.1 skrll if ((fragment & 0x1F) == current_reg->opcode)
202 1.1 skrll {
203 1.1 skrll strcpy (buffer, current_reg->name);
204 1.1 skrll return 1;
205 1.1 skrll }
206 1.1 skrll }
207 1.1 skrll return 0;
208 1.1 skrll }
209 1.1 skrll
210 1.1 skrll static int
211 1.1 skrll get_indirect_operand (unsigned short fragment,
212 1.1 skrll int size,
213 1.1 skrll char *buffer)
214 1.1 skrll {
215 1.1 skrll unsigned char mod;
216 1.1 skrll unsigned arnum;
217 1.1 skrll unsigned char disp;
218 1.1 skrll
219 1.1 skrll if (buffer == NULL)
220 1.1 skrll return 0;
221 1.1 skrll /* Determine which bits identify the sections of the indirect
222 1.1 skrll operand based on the size in bytes. */
223 1.1 skrll switch (size)
224 1.1 skrll {
225 1.1 skrll case 1:
226 1.1 skrll mod = (fragment & 0x00F8) >> 3;
227 1.1 skrll arnum = (fragment & 0x0007);
228 1.1 skrll disp = 0;
229 1.1 skrll break;
230 1.1 skrll case 2:
231 1.1 skrll mod = (fragment & 0xF800) >> 11;
232 1.1 skrll arnum = (fragment & 0x0700) >> 8;
233 1.1 skrll disp = (fragment & 0x00FF);
234 1.1 skrll break;
235 1.1 skrll default:
236 1.1 skrll return 0;
237 1.1 skrll }
238 1.1 skrll {
239 1.1 skrll const ind_addr_type *current_ind = tic30_indaddr_tab;
240 1.1 skrll
241 1.1 skrll for (; current_ind < tic30_indaddrtab_end; current_ind++)
242 1.1 skrll {
243 1.1 skrll if (current_ind->modfield == mod)
244 1.1 skrll {
245 1.1 skrll if (current_ind->displacement == IMPLIED_DISP && size == 2)
246 1.1 skrll continue;
247 1.1 skrll
248 1.1 skrll else
249 1.1 skrll {
250 1.1 skrll size_t i, len;
251 1.1 skrll int bufcnt;
252 1.1 skrll
253 1.1 skrll len = strlen (current_ind->syntax);
254 1.1 skrll for (i = 0, bufcnt = 0; i < len; i++, bufcnt++)
255 1.1 skrll {
256 1.1 skrll buffer[bufcnt] = current_ind->syntax[i];
257 1.1 skrll if (buffer[bufcnt - 1] == 'a' && buffer[bufcnt] == 'r')
258 1.1 skrll buffer[++bufcnt] = arnum + '0';
259 1.1 skrll if (buffer[bufcnt] == '('
260 1.1 skrll && current_ind->displacement == DISP_REQUIRED)
261 1.1 skrll {
262 1.1 skrll sprintf (&buffer[bufcnt + 1], "%u", disp);
263 1.1 skrll bufcnt += strlen (&buffer[bufcnt + 1]);
264 1.1 skrll }
265 1.1 skrll }
266 1.1 skrll buffer[bufcnt + 1] = '\0';
267 1.1 skrll break;
268 1.1 skrll }
269 1.1 skrll }
270 1.1 skrll }
271 1.1 skrll }
272 1.1 skrll return 1;
273 1.1 skrll }
274 1.1 skrll
275 1.1 skrll static int
276 1.1 skrll cnvt_tmsfloat_ieee (unsigned long tmsfloat, int size, float *ieeefloat)
277 1.1 skrll {
278 1.1.1.2 christos unsigned long exponent, sign, mant;
279 1.1 skrll union
280 1.1 skrll {
281 1.1 skrll unsigned long l;
282 1.1 skrll float f;
283 1.1 skrll } val;
284 1.1 skrll
285 1.1 skrll if (size == 2)
286 1.1 skrll {
287 1.1 skrll if ((tmsfloat & 0x0000F000) == 0x00008000)
288 1.1 skrll tmsfloat = 0x80000000;
289 1.1 skrll else
290 1.1 skrll {
291 1.1 skrll tmsfloat <<= 16;
292 1.1 skrll tmsfloat = (long) tmsfloat >> 4;
293 1.1 skrll }
294 1.1 skrll }
295 1.1.1.2 christos exponent = tmsfloat & 0xFF000000;
296 1.1.1.2 christos if (exponent == 0x80000000)
297 1.1 skrll {
298 1.1 skrll *ieeefloat = 0.0;
299 1.1 skrll return 1;
300 1.1 skrll }
301 1.1.1.2 christos exponent += 0x7F000000;
302 1.1 skrll sign = (tmsfloat & 0x00800000) << 8;
303 1.1 skrll mant = tmsfloat & 0x007FFFFF;
304 1.1.1.2 christos if (exponent == 0xFF000000)
305 1.1 skrll {
306 1.1 skrll if (mant == 0)
307 1.1 skrll *ieeefloat = ERANGE;
308 1.1 skrll #ifdef HUGE_VALF
309 1.1 skrll if (sign == 0)
310 1.1 skrll *ieeefloat = HUGE_VALF;
311 1.1 skrll else
312 1.1 skrll *ieeefloat = -HUGE_VALF;
313 1.1 skrll #else
314 1.1 skrll if (sign == 0)
315 1.1 skrll *ieeefloat = 1.0 / 0.0;
316 1.1 skrll else
317 1.1 skrll *ieeefloat = -1.0 / 0.0;
318 1.1 skrll #endif
319 1.1 skrll return 1;
320 1.1 skrll }
321 1.1.1.2 christos exponent >>= 1;
322 1.1 skrll if (sign)
323 1.1 skrll {
324 1.1 skrll mant = (~mant) & 0x007FFFFF;
325 1.1 skrll mant += 1;
326 1.1.1.2 christos exponent += mant & 0x00800000;
327 1.1.1.2 christos exponent &= 0x7F800000;
328 1.1 skrll mant &= 0x007FFFFF;
329 1.1 skrll }
330 1.1 skrll if (tmsfloat == 0x80000000)
331 1.1.1.2 christos sign = mant = exponent = 0;
332 1.1.1.2 christos tmsfloat = sign | exponent | mant;
333 1.1 skrll val.l = tmsfloat;
334 1.1 skrll *ieeefloat = val.f;
335 1.1 skrll return 1;
336 1.1 skrll }
337 1.1 skrll
338 1.1 skrll static int
339 1.1 skrll print_two_operand (disassemble_info *info,
340 1.1 skrll unsigned long insn_word,
341 1.1 skrll struct instruction *insn)
342 1.1 skrll {
343 1.1 skrll char name[12];
344 1.1 skrll char operand[2][13] =
345 1.1 skrll {
346 1.1 skrll {0},
347 1.1 skrll {0}
348 1.1 skrll };
349 1.1 skrll float f_number;
350 1.1 skrll
351 1.1 skrll if (insn->tm == NULL)
352 1.1 skrll return 0;
353 1.1 skrll strcpy (name, insn->tm->name);
354 1.1 skrll if (insn->tm->opcode_modifier == AddressMode)
355 1.1 skrll {
356 1.1 skrll int src_op, dest_op;
357 1.1 skrll /* Determine whether instruction is a store or a normal instruction. */
358 1.1 skrll if ((insn->tm->operand_types[1] & (Direct | Indirect))
359 1.1 skrll == (Direct | Indirect))
360 1.1 skrll {
361 1.1 skrll src_op = 1;
362 1.1 skrll dest_op = 0;
363 1.1 skrll }
364 1.1 skrll else
365 1.1 skrll {
366 1.1 skrll src_op = 0;
367 1.1 skrll dest_op = 1;
368 1.1 skrll }
369 1.1 skrll /* Get the destination register. */
370 1.1 skrll if (insn->tm->operands == 2)
371 1.1 skrll get_register_operand ((insn_word & 0x001F0000) >> 16, operand[dest_op]);
372 1.1 skrll /* Get the source operand based on addressing mode. */
373 1.1 skrll switch (insn_word & AddressMode)
374 1.1 skrll {
375 1.1 skrll case AM_REGISTER:
376 1.1 skrll /* Check for the NOP instruction before getting the operand. */
377 1.1 skrll if ((insn->tm->operand_types[0] & NotReq) == 0)
378 1.1 skrll get_register_operand ((insn_word & 0x0000001F), operand[src_op]);
379 1.1 skrll break;
380 1.1 skrll case AM_DIRECT:
381 1.1 skrll sprintf (operand[src_op], "@0x%lX", (insn_word & 0x0000FFFF));
382 1.1 skrll break;
383 1.1 skrll case AM_INDIRECT:
384 1.1 skrll get_indirect_operand ((insn_word & 0x0000FFFF), 2, operand[src_op]);
385 1.1 skrll break;
386 1.1 skrll case AM_IMM:
387 1.1 skrll /* Get the value of the immediate operand based on variable type. */
388 1.1 skrll switch (insn->tm->imm_arg_type)
389 1.1 skrll {
390 1.1 skrll case Imm_Float:
391 1.1 skrll cnvt_tmsfloat_ieee ((insn_word & 0x0000FFFF), 2, &f_number);
392 1.1 skrll sprintf (operand[src_op], "%2.2f", f_number);
393 1.1 skrll break;
394 1.1 skrll case Imm_SInt:
395 1.1 skrll sprintf (operand[src_op], "%d", (short) (insn_word & 0x0000FFFF));
396 1.1 skrll break;
397 1.1 skrll case Imm_UInt:
398 1.1 skrll sprintf (operand[src_op], "%lu", (insn_word & 0x0000FFFF));
399 1.1 skrll break;
400 1.1 skrll default:
401 1.1 skrll return 0;
402 1.1 skrll }
403 1.1 skrll /* Handle special case for LDP instruction. */
404 1.1 skrll if ((insn_word & 0xFFFFFF00) == LDP_INSN)
405 1.1 skrll {
406 1.1 skrll strcpy (name, "ldp");
407 1.1 skrll sprintf (operand[0], "0x%06lX", (insn_word & 0x000000FF) << 16);
408 1.1 skrll operand[1][0] = '\0';
409 1.1 skrll }
410 1.1 skrll }
411 1.1 skrll }
412 1.1 skrll /* Handle case for stack and rotate instructions. */
413 1.1 skrll else if (insn->tm->operands == 1)
414 1.1 skrll {
415 1.1 skrll if (insn->tm->opcode_modifier == StackOp)
416 1.1 skrll get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]);
417 1.1 skrll }
418 1.1 skrll /* Output instruction to stream. */
419 1.1 skrll info->fprintf_func (info->stream, " %s %s%c%s", name,
420 1.1 skrll operand[0][0] ? operand[0] : "",
421 1.1 skrll operand[1][0] ? ',' : ' ',
422 1.1 skrll operand[1][0] ? operand[1] : "");
423 1.1 skrll return 1;
424 1.1 skrll }
425 1.1 skrll
426 1.1 skrll static int
427 1.1 skrll print_three_operand (disassemble_info *info,
428 1.1 skrll unsigned long insn_word,
429 1.1 skrll struct instruction *insn)
430 1.1 skrll {
431 1.1 skrll char operand[3][13] =
432 1.1 skrll {
433 1.1 skrll {0},
434 1.1 skrll {0},
435 1.1 skrll {0}
436 1.1 skrll };
437 1.1 skrll
438 1.1 skrll if (insn->tm == NULL)
439 1.1 skrll return 0;
440 1.1 skrll switch (insn_word & AddressMode)
441 1.1 skrll {
442 1.1 skrll case AM_REGISTER:
443 1.1 skrll get_register_operand ((insn_word & 0x000000FF), operand[0]);
444 1.1 skrll get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
445 1.1 skrll break;
446 1.1 skrll case AM_DIRECT:
447 1.1 skrll get_register_operand ((insn_word & 0x000000FF), operand[0]);
448 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
449 1.1 skrll break;
450 1.1 skrll case AM_INDIRECT:
451 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
452 1.1 skrll get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
453 1.1 skrll break;
454 1.1 skrll case AM_IMM:
455 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
456 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
457 1.1 skrll break;
458 1.1 skrll default:
459 1.1 skrll return 0;
460 1.1 skrll }
461 1.1 skrll if (insn->tm->operands == 3)
462 1.1 skrll get_register_operand ((insn_word & 0x001F0000) >> 16, operand[2]);
463 1.1 skrll info->fprintf_func (info->stream, " %s %s,%s%c%s", insn->tm->name,
464 1.1 skrll operand[0], operand[1],
465 1.1 skrll operand[2][0] ? ',' : ' ',
466 1.1 skrll operand[2][0] ? operand[2] : "");
467 1.1 skrll return 1;
468 1.1 skrll }
469 1.1 skrll
470 1.1 skrll static int
471 1.1 skrll print_par_insn (disassemble_info *info,
472 1.1 skrll unsigned long insn_word,
473 1.1 skrll struct instruction *insn)
474 1.1 skrll {
475 1.1 skrll size_t i, len;
476 1.1 skrll char *name1, *name2;
477 1.1 skrll char operand[2][3][13] =
478 1.1 skrll {
479 1.1 skrll {
480 1.1 skrll {0},
481 1.1 skrll {0},
482 1.1 skrll {0}
483 1.1 skrll },
484 1.1 skrll {
485 1.1 skrll {0},
486 1.1 skrll {0},
487 1.1 skrll {0}
488 1.1 skrll }
489 1.1 skrll };
490 1.1 skrll
491 1.1 skrll if (insn->ptm == NULL)
492 1.1 skrll return 0;
493 1.1 skrll /* Parse out the names of each of the parallel instructions from the
494 1.1 skrll q_insn1_insn2 format. */
495 1.1 skrll name1 = (char *) strdup (insn->ptm->name + 2);
496 1.1 skrll name2 = "";
497 1.1 skrll len = strlen (name1);
498 1.1 skrll for (i = 0; i < len; i++)
499 1.1 skrll {
500 1.1 skrll if (name1[i] == '_')
501 1.1 skrll {
502 1.1 skrll name2 = &name1[i + 1];
503 1.1 skrll name1[i] = '\0';
504 1.1 skrll break;
505 1.1 skrll }
506 1.1 skrll }
507 1.1 skrll /* Get the operands of the instruction based on the operand order. */
508 1.1 skrll switch (insn->ptm->oporder)
509 1.1 skrll {
510 1.1 skrll case OO_4op1:
511 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
512 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
513 1.1 skrll get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
514 1.1 skrll get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
515 1.1 skrll break;
516 1.1 skrll case OO_4op2:
517 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
518 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
519 1.1 skrll get_register_operand ((insn_word >> 19) & 0x07, operand[1][1]);
520 1.1 skrll get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
521 1.1 skrll break;
522 1.1 skrll case OO_4op3:
523 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
524 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
525 1.1 skrll get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
526 1.1 skrll get_register_operand ((insn_word >> 22) & 0x07, operand[0][0]);
527 1.1 skrll break;
528 1.1 skrll case OO_5op1:
529 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
530 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
531 1.1 skrll get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
532 1.1 skrll get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
533 1.1 skrll get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
534 1.1 skrll break;
535 1.1 skrll case OO_5op2:
536 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
537 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
538 1.1 skrll get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
539 1.1 skrll get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
540 1.1 skrll get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
541 1.1 skrll break;
542 1.1 skrll case OO_PField:
543 1.1 skrll if (insn_word & 0x00800000)
544 1.1 skrll get_register_operand (0x01, operand[0][2]);
545 1.1 skrll else
546 1.1 skrll get_register_operand (0x00, operand[0][2]);
547 1.1 skrll if (insn_word & 0x00400000)
548 1.1 skrll get_register_operand (0x03, operand[1][2]);
549 1.1 skrll else
550 1.1 skrll get_register_operand (0x02, operand[1][2]);
551 1.1 skrll switch (insn_word & P_FIELD)
552 1.1 skrll {
553 1.1 skrll case 0x00000000:
554 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
555 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
556 1.1 skrll get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
557 1.1 skrll get_register_operand ((insn_word >> 19) & 0x07, operand[1][0]);
558 1.1 skrll break;
559 1.1 skrll case 0x01000000:
560 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][0]);
561 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
562 1.1 skrll get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
563 1.1 skrll get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
564 1.1 skrll break;
565 1.1 skrll case 0x02000000:
566 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
567 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
568 1.1 skrll get_register_operand ((insn_word >> 16) & 0x07, operand[0][1]);
569 1.1 skrll get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
570 1.1 skrll break;
571 1.1 skrll case 0x03000000:
572 1.1 skrll get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
573 1.1 skrll get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
574 1.1 skrll get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
575 1.1 skrll get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
576 1.1 skrll break;
577 1.1 skrll }
578 1.1 skrll break;
579 1.1 skrll default:
580 1.1 skrll return 0;
581 1.1 skrll }
582 1.1 skrll info->fprintf_func (info->stream, " %s %s,%s%c%s", name1,
583 1.1 skrll operand[0][0], operand[0][1],
584 1.1 skrll operand[0][2][0] ? ',' : ' ',
585 1.1 skrll operand[0][2][0] ? operand[0][2] : "");
586 1.1 skrll info->fprintf_func (info->stream, "\n\t\t\t|| %s %s,%s%c%s", name2,
587 1.1 skrll operand[1][0], operand[1][1],
588 1.1 skrll operand[1][2][0] ? ',' : ' ',
589 1.1 skrll operand[1][2][0] ? operand[1][2] : "");
590 1.1 skrll free (name1);
591 1.1 skrll return 1;
592 1.1 skrll }
593 1.1 skrll
594 1.1 skrll static int
595 1.1 skrll print_branch (disassemble_info *info,
596 1.1 skrll unsigned long insn_word,
597 1.1 skrll struct instruction *insn)
598 1.1 skrll {
599 1.1 skrll char operand[2][13] =
600 1.1 skrll {
601 1.1 skrll {0},
602 1.1 skrll {0}
603 1.1 skrll };
604 1.1 skrll unsigned long address;
605 1.1 skrll int print_label = 0;
606 1.1 skrll
607 1.1 skrll if (insn->tm == NULL)
608 1.1 skrll return 0;
609 1.1 skrll /* Get the operands for 24-bit immediate jumps. */
610 1.1 skrll if (insn->tm->operand_types[0] & Imm24)
611 1.1 skrll {
612 1.1 skrll address = insn_word & 0x00FFFFFF;
613 1.1 skrll sprintf (operand[0], "0x%lX", address);
614 1.1 skrll print_label = 1;
615 1.1 skrll }
616 1.1 skrll /* Get the operand for the trap instruction. */
617 1.1 skrll else if (insn->tm->operand_types[0] & IVector)
618 1.1 skrll {
619 1.1 skrll address = insn_word & 0x0000001F;
620 1.1 skrll sprintf (operand[0], "0x%lX", address);
621 1.1 skrll }
622 1.1 skrll else
623 1.1 skrll {
624 1.1 skrll address = insn_word & 0x0000FFFF;
625 1.1 skrll /* Get the operands for the DB instructions. */
626 1.1 skrll if (insn->tm->operands == 2)
627 1.1 skrll {
628 1.1 skrll get_register_operand (((insn_word & 0x01C00000) >> 22) + REG_AR0, operand[0]);
629 1.1 skrll if (insn_word & PCRel)
630 1.1 skrll {
631 1.1 skrll sprintf (operand[1], "%d", (short) address);
632 1.1 skrll print_label = 1;
633 1.1 skrll }
634 1.1 skrll else
635 1.1 skrll get_register_operand (insn_word & 0x0000001F, operand[1]);
636 1.1 skrll }
637 1.1 skrll /* Get the operands for the standard branches. */
638 1.1 skrll else if (insn->tm->operands == 1)
639 1.1 skrll {
640 1.1 skrll if (insn_word & PCRel)
641 1.1 skrll {
642 1.1 skrll address = (short) address;
643 1.1 skrll sprintf (operand[0], "%ld", address);
644 1.1 skrll print_label = 1;
645 1.1 skrll }
646 1.1 skrll else
647 1.1 skrll get_register_operand (insn_word & 0x0000001F, operand[0]);
648 1.1 skrll }
649 1.1 skrll }
650 1.1 skrll info->fprintf_func (info->stream, " %s %s%c%s", insn->tm->name,
651 1.1 skrll operand[0][0] ? operand[0] : "",
652 1.1 skrll operand[1][0] ? ',' : ' ',
653 1.1 skrll operand[1][0] ? operand[1] : "");
654 1.1 skrll /* Print destination of branch in relation to current symbol. */
655 1.1 skrll if (print_label && info->symbols)
656 1.1 skrll {
657 1.1 skrll asymbol *sym = *info->symbols;
658 1.1 skrll
659 1.1 skrll if ((insn->tm->opcode_modifier == PCRel) && (insn_word & PCRel))
660 1.1 skrll {
661 1.1 skrll address = (_pc + 1 + (short) address) - ((sym->section->vma + sym->value) / 4);
662 1.1 skrll /* Check for delayed instruction, if so adjust destination. */
663 1.1 skrll if (insn_word & 0x00200000)
664 1.1 skrll address += 2;
665 1.1 skrll }
666 1.1 skrll else
667 1.1 skrll {
668 1.1 skrll address -= ((sym->section->vma + sym->value) / 4);
669 1.1 skrll }
670 1.1 skrll if (address == 0)
671 1.1 skrll info->fprintf_func (info->stream, " <%s>", sym->name);
672 1.1 skrll else
673 1.1 skrll info->fprintf_func (info->stream, " <%s %c %d>", sym->name,
674 1.1 skrll ((short) address < 0) ? '-' : '+',
675 1.1 skrll abs (address));
676 1.1 skrll }
677 1.1 skrll return 1;
678 1.1 skrll }
679 1.1 skrll
680 1.1 skrll int
681 1.1 skrll print_insn_tic30 (bfd_vma pc, disassemble_info *info)
682 1.1 skrll {
683 1.1 skrll unsigned long insn_word;
684 1.1 skrll struct instruction insn = { 0, NULL, NULL };
685 1.1 skrll bfd_vma bufaddr = pc - info->buffer_vma;
686 1.1 skrll
687 1.1 skrll /* Obtain the current instruction word from the buffer. */
688 1.1 skrll insn_word = (*(info->buffer + bufaddr) << 24) | (*(info->buffer + bufaddr + 1) << 16) |
689 1.1 skrll (*(info->buffer + bufaddr + 2) << 8) | *(info->buffer + bufaddr + 3);
690 1.1 skrll _pc = pc / 4;
691 1.1 skrll /* Get the instruction refered to by the current instruction word
692 1.1 skrll and print it out based on its type. */
693 1.1 skrll if (!get_tic30_instruction (insn_word, &insn))
694 1.1 skrll return -1;
695 1.1 skrll switch (GET_TYPE (insn_word))
696 1.1 skrll {
697 1.1 skrll case TWO_OPERAND_1:
698 1.1 skrll case TWO_OPERAND_2:
699 1.1 skrll if (!print_two_operand (info, insn_word, &insn))
700 1.1 skrll return -1;
701 1.1 skrll break;
702 1.1 skrll case THREE_OPERAND:
703 1.1 skrll if (!print_three_operand (info, insn_word, &insn))
704 1.1 skrll return -1;
705 1.1 skrll break;
706 1.1 skrll case PAR_STORE:
707 1.1 skrll case MUL_ADDS:
708 1.1 skrll if (!print_par_insn (info, insn_word, &insn))
709 1.1 skrll return -1;
710 1.1 skrll break;
711 1.1 skrll case BRANCHES:
712 1.1 skrll if (!print_branch (info, insn_word, &insn))
713 1.1 skrll return -1;
714 1.1 skrll break;
715 1.1 skrll }
716 1.1 skrll return 4;
717 1.1 skrll }
718