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