1 /* Disassemble D30V instructions.
2 Copyright (C) 1997 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19 #include "opcode/d30v.h"
22 #define PC_MASK 0xFFFFFFFF
24 static int lookup_opcode
PARAMS (( struct d30v_insn
*insn
, long num
, int is_long
));
25 static void print_insn
PARAMS (( struct disassemble_info
*info
, bfd_vma memaddr
, long long num
,
26 struct d30v_insn
*insn
, int is_long
));
27 static int extract_value
PARAMS (( long long num
, struct d30v_operand
*oper
, int is_long
));
30 print_insn_d30v (memaddr
, info
)
32 struct disassemble_info
*info
;
36 unsigned long in1
,in2
;
37 struct d30v_insn insn
;
40 insn
.form
= (struct d30v_format
*)NULL
;
42 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 8, info
);
45 (*info
->memory_error_func
) (status
, memaddr
, info
);
48 info
->bytes_per_line
= 8;
49 info
->bytes_per_chunk
= 4;
50 info
->display_endian
= BFD_ENDIAN_BIG
;
51 in1
= bfd_getb32 (buffer
);
52 in2
= bfd_getb32 (buffer
+4);
56 /* LONG instruction */
57 if (!lookup_opcode(&insn
, in1
, 1))
59 (*info
->fprintf_func
) (info
->stream
, ".long\t0x%x,0x%x",in1
,in2
);
62 num
= (long long)in1
<< 32 | in2
;
63 print_insn(info
, memaddr
, num
, &insn
, 1);
68 if (!lookup_opcode(&insn
, in1
, 0))
69 (*info
->fprintf_func
) (info
->stream
, ".long\t0x%x",in1
);
71 print_insn(info
, memaddr
, num
, &insn
, 0);
73 switch ( ((in1
>>31)<<1) | (in2
>>31) )
76 (*info
->fprintf_func
) (info
->stream
, "\t||\t");
79 (*info
->fprintf_func
) (info
->stream
, "\t->\t");
82 (*info
->fprintf_func
) (info
->stream
, "\t<-\t");
87 insn
.form
= (struct d30v_format
*)NULL
;
89 if (!lookup_opcode(&insn
, in2
, 0))
90 (*info
->fprintf_func
) (info
->stream
, ".long\t0x%x",in2
);
92 print_insn(info
, memaddr
, num
, &insn
, 0);
100 lookup_opcode (insn
, num
, is_long
)
101 struct d30v_insn
*insn
;
106 struct d30v_format
*f
;
107 struct d30v_opcode
*op
= (struct d30v_opcode
*)d30v_opcode_table
;
108 int op1
= (num
>> 25) & 0x7;
109 int op2
= (num
>> 20) & 0x1f;
110 int mod
= (num
>> 18) & 0x3;
112 /* find the opcode */
114 if ((op
->op1
== op1
) && (op
->op2
== op2
))
119 if (!op
|| !op
->name
)
122 while (op
->op1
== op1
&& op
->op2
== op2
)
124 /* scan through all the formats for the opcode */
125 while (index
= op
->format
[i
++])
127 f
= (struct d30v_format
*)&d30v_format_table
[index
];
128 while (f
->form
== index
)
130 if ((!is_long
|| f
->form
>= LONG
) && (f
->modifier
== mod
))
145 if (insn
->form
== NULL
)
149 insn
->ecc
= (num
>> 28) & 0x7;
155 print_insn ( info
, memaddr
, num
, insn
, is_long
)
156 struct disassemble_info
*info
;
159 struct d30v_insn
*insn
;
163 int val
, opnum
, need_comma
=0;
164 struct d30v_operand
*oper
;
165 int i
, match
, opind
=0, need_paren
=0, found_control
=0;
167 (*info
->fprintf_func
) (info
->stream
, "%s",insn
->op
->name
);
169 /* check for CMP or CMPU */
170 if (d30v_operand_table
[insn
->form
->operands
[0]].flags
& OPERAND_NAME
)
173 val
= extract_value(num
,(struct d30v_operand
*)&d30v_operand_table
[insn
->form
->operands
[0]],is_long
);
174 (*info
->fprintf_func
) (info
->stream
, "%s",d30v_cc_names
[val
]);
178 (*info
->fprintf_func
) (info
->stream
, "/%s",d30v_ecc_names
[insn
->ecc
]);
180 (*info
->fprintf_func
) (info
->stream
, "\t");
182 while (opnum
= insn
->form
->operands
[opind
++])
184 oper
= (struct d30v_operand
*)&d30v_operand_table
[opnum
];
186 if (need_comma
&& oper
->flags
!= OPERAND_PLUS
&& oper
->flags
!= OPERAND_MINUS
)
189 (*info
->fprintf_func
) (info
->stream
, ", ");
192 if (oper
->flags
== OPERAND_ATMINUS
)
194 (*info
->fprintf_func
) (info
->stream
, "@-");
197 if (oper
->flags
== OPERAND_MINUS
)
199 (*info
->fprintf_func
) (info
->stream
, "-");
202 if (oper
->flags
== OPERAND_PLUS
)
204 (*info
->fprintf_func
) (info
->stream
, "+");
207 if (oper
->flags
== OPERAND_ATSIGN
)
209 (*info
->fprintf_func
) (info
->stream
, "@");
212 if (oper
->flags
== OPERAND_ATPAR
)
214 (*info
->fprintf_func
) (info
->stream
, "@(");
219 if (oper
->flags
== OPERAND_SPECIAL
)
222 val
= extract_value(num
, oper
, is_long
);
224 if (oper
->flags
& OPERAND_REG
)
227 if (oper
->flags
& OPERAND_CONTROL
)
229 struct d30v_operand
*oper3
=
230 (struct d30v_operand
*)&d30v_operand_table
[insn
->form
->operands
[2]];
231 int id
= extract_value (num
, oper3
, is_long
);
236 val
|= OPERAND_CONTROL
;
240 val
= OPERAND_CONTROL
+ MAX_CONTROL_REG
+ id
;
246 fprintf(stderr
,"illegal id (%d)\n",id
);
249 else if (oper
->flags
& OPERAND_ACC
)
251 else if (oper
->flags
& OPERAND_FLAG
)
253 for (i
=0;i
<reg_name_cnt();i
++)
255 if (val
== pre_defined_registers
[i
].value
)
257 if (pre_defined_registers
[i
].pname
)
258 (*info
->fprintf_func
) (info
->stream
, "%s",pre_defined_registers
[i
].pname
);
260 (*info
->fprintf_func
) (info
->stream
, "%s",pre_defined_registers
[i
].name
);
267 /* this would only get executed if a register was not in the
269 (*info
->fprintf_func
) (info
->stream
, "<unknown register %d>",val
& 0x3F);
272 else if (insn
->op
->reloc_flag
== RELOC_PCREL
)
276 max
= (1 << (oper
->bits
- 1));
279 if (oper
->bits
== 32)
282 val
= -val
& ((1 << oper
->bits
)-1);
286 (*info
->print_address_func
) ((memaddr
- val
) & PC_MASK
, info
);
288 (*info
->print_address_func
) ((memaddr
+ val
) & PC_MASK
, info
);
290 else if (insn
->op
->reloc_flag
== RELOC_ABS
)
292 (*info
->print_address_func
) (val
, info
);
296 if (oper
->flags
& OPERAND_SIGNED
)
298 int max
= (1 << (oper
->bits
- 1));
301 val
= -val
& ((1 << oper
->bits
) - 1);
302 (*info
->fprintf_func
) (info
->stream
, "-");
305 (*info
->fprintf_func
) (info
->stream
, "0x%x",val
);
307 /* if there is another operand, then write a comma and space */
308 if (insn
->form
->operands
[opind
] && !(found_control
&& opind
== 2))
312 (*info
->fprintf_func
) (info
->stream
, ")");
318 extract_value (num
, oper
, is_long
)
320 struct d30v_operand
*oper
;
324 int shift
= 12 - oper
->position
;
325 int mask
= (0xFFFFFFFF >> (32 - oper
->bits
));
329 if (oper
->bits
== 32)
331 /* piece together 32-bit constant */
332 val
= num
& 0x3FFFF | (num
& 0xFF00000) >> 2 |
333 (num
& 0x3F00000000LL
) >> 6;
336 val
= (num
>> (32 + shift
)) & mask
;
339 val
= (num
>> shift
) & mask
;
341 if (oper
->flags
& OPERAND_SHIFT
)
This page took 0.038683 seconds and 4 git commands to generate.