1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #include <stdio.h>
23:
24: #include "sysdep.h"
25: #include "opcode/d10v.h"
26: #include "dis-asm.h"
27:
28:
29:
30: #define PC_MASK 0x0303FFFF
31:
32: static void
33: print_operand (struct d10v_operand *oper,
34: unsigned long insn,
35: struct d10v_opcode *op,
36: bfd_vma memaddr,
37: struct disassemble_info *info)
38: {
39: int num, shift;
40:
41: if (oper->flags == OPERAND_ATMINUS)
42: {
43: (*info->fprintf_func) (info->stream, "@-");
44: return;
45: }
46: if (oper->flags == OPERAND_MINUS)
47: {
48: (*info->fprintf_func) (info->stream, "-");
49: return;
50: }
51: if (oper->flags == OPERAND_PLUS)
52: {
53: (*info->fprintf_func) (info->stream, "+");
54: return;
55: }
56: if (oper->flags == OPERAND_ATSIGN)
57: {
58: (*info->fprintf_func) (info->stream, "@");
59: return;
60: }
61: if (oper->flags == OPERAND_ATPAR)
62: {
63: (*info->fprintf_func) (info->stream, "@(");
64: return;
65: }
66:
67: shift = oper->shift;
68:
69:
70: if (op->format == LONG_L && (oper->flags & OPERAND_REG))
71: shift += 15;
72:
73: num = (insn >> shift) & (0x7FFFFFFF >> (31 - oper->bits));
74:
75: if (oper->flags & OPERAND_REG)
76: {
77: int i;
78: int match = 0;
79:
80: num += (oper->flags
81: & (OPERAND_GPR | OPERAND_FFLAG | OPERAND_CFLAG | OPERAND_CONTROL));
82: if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
83: num += num ? OPERAND_ACC1 : OPERAND_ACC0;
84: for (i = 0; i < d10v_reg_name_cnt (); i++)
85: {
86: if (num == (d10v_predefined_registers[i].value & ~ OPERAND_SP))
87: {
88: if (d10v_predefined_registers[i].pname)
89: (*info->fprintf_func) (info->stream, "%s",
90: d10v_predefined_registers[i].pname);
91: else
92: (*info->fprintf_func) (info->stream, "%s",
93: d10v_predefined_registers[i].name);
94: match = 1;
95: break;
96: }
97: }
98: if (match == 0)
99: {
100:
101:
102: if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
103: (*info->fprintf_func) (info->stream, "a");
104: else if (oper->flags & OPERAND_CONTROL)
105: (*info->fprintf_func) (info->stream, "cr");
106: else if (oper->flags & OPERAND_REG)
107: (*info->fprintf_func) (info->stream, "r");
108: (*info->fprintf_func) (info->stream, "%d", num & REGISTER_MASK);
109: }
110: }
111: else
112: {
113:
114: if (oper->flags & OPERAND_ADDR)
115: {
116: long max;
117: int neg = 0;
118:
119: max = (1 << (oper->bits - 1));
120: if (num & max)
121: {
122: num = -num & ((1 << oper->bits) - 1);
123: neg = 1;
124: }
125: num = num << 2;
126: if (info->flags & INSN_HAS_RELOC)
127: (*info->print_address_func) (num & PC_MASK, info);
128: else
129: {
130: if (neg)
131: (*info->print_address_func) ((memaddr - num) & PC_MASK, info);
132: else
133: (*info->print_address_func) ((memaddr + num) & PC_MASK, info);
134: }
135: }
136: else
137: {
138: if (oper->flags & OPERAND_SIGNED)
139: {
140: int max = (1 << (oper->bits - 1));
141: if (num & max)
142: {
143: num = -num & ((1 << oper->bits) - 1);
144: (*info->fprintf_func) (info->stream, "-");
145: }
146: }
147: (*info->fprintf_func) (info->stream, "0x%x", num);
148: }
149: }
150: }
151:
152: static void
153: dis_long (unsigned long insn,
154: bfd_vma memaddr,
155: struct disassemble_info *info)
156: {
157: int i;
158: struct d10v_opcode *op = (struct d10v_opcode *) d10v_opcodes;
159: struct d10v_operand *oper;
160: int need_paren = 0;
161: int match = 0;
162:
163: while (op->name)
164: {
165: if ((op->format & LONG_OPCODE)
166: && ((op->mask & insn) == (unsigned long) op->opcode))
167: {
168: match = 1;
169: (*info->fprintf_func) (info->stream, "%s\t", op->name);
170:
171: for (i = 0; op->operands[i]; i++)
172: {
173: oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
174: if (oper->flags == OPERAND_ATPAR)
175: need_paren = 1;
176: print_operand (oper, insn, op, memaddr, info);
177: if (op->operands[i + 1] && oper->bits
178: && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
179: && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
180: (*info->fprintf_func) (info->stream, ", ");
181: }
182: break;
183: }
184: op++;
185: }
186:
187: if (!match)
188: (*info->fprintf_func) (info->stream, ".long\t0x%08lx", insn);
189:
190: if (need_paren)
191: (*info->fprintf_func) (info->stream, ")");
192: }
193:
194: static void
195: dis_2_short (unsigned long insn,
196: bfd_vma memaddr,
197: struct disassemble_info *info,
198: int order)
199: {
200: int i, j;
201: unsigned int ins[2];
202: struct d10v_opcode *op;
203: int match, num_match = 0;
204: struct d10v_operand *oper;
205: int need_paren = 0;
206:
207: ins[0] = (insn & 0x3FFFFFFF) >> 15;
208: ins[1] = insn & 0x00007FFF;
209:
210: for (j = 0; j < 2; j++)
211: {
212: op = (struct d10v_opcode *) d10v_opcodes;
213: match = 0;
214: while (op->name)
215: {
216: if ((op->format & SHORT_OPCODE)
217: && ((((unsigned int) op->mask) & ins[j])
218: == (unsigned int) op->opcode))
219: {
220: (*info->fprintf_func) (info->stream, "%s\t", op->name);
221: for (i = 0; op->operands[i]; i++)
222: {
223: oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
224: if (oper->flags == OPERAND_ATPAR)
225: need_paren = 1;
226: print_operand (oper, ins[j], op, memaddr, info);
227: if (op->operands[i + 1] && oper->bits
228: && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
229: && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
230: (*info->fprintf_func) (info->stream, ", ");
231: }
232: match = 1;
233: num_match++;
234: break;
235: }
236: op++;
237: }
238: if (!match)
239: (*info->fprintf_func) (info->stream, "unknown");
240:
241: switch (order)
242: {
243: case 0:
244: (*info->fprintf_func) (info->stream, "\t->\t");
245: order = -1;
246: break;
247: case 1:
248: (*info->fprintf_func) (info->stream, "\t<-\t");
249: order = -1;
250: break;
251: case 2:
252: (*info->fprintf_func) (info->stream, "\t||\t");
253: order = -1;
254: break;
255: default:
256: break;
257: }
258: }
259:
260: if (num_match == 0)
261: (*info->fprintf_func) (info->stream, ".long\t0x%08lx", insn);
262:
263: if (need_paren)
264: (*info->fprintf_func) (info->stream, ")");
265: }
266:
267: int
268: print_insn_d10v (bfd_vma memaddr, struct disassemble_info *info)
269: {
270: int status;
271: bfd_byte buffer[4];
272: unsigned long insn;
273:
274: status = (*info->read_memory_func) (memaddr, buffer, 4, info);
275: if (status != 0)
276: {
277: (*info->memory_error_func) (status, memaddr, info);
278: return -1;
279: }
280: insn = bfd_getb32 (buffer);
281:
282: status = insn & FM11;
283: switch (status)
284: {
285: case 0:
286: dis_2_short (insn, memaddr, info, 2);
287: break;
288: case FM01:
289: dis_2_short (insn, memaddr, info, 0);
290: break;
291: case FM10:
292: dis_2_short (insn, memaddr, info, 1);
293: break;
294: case FM11:
295: dis_long (insn, memaddr, info);
296: break;
297: }
298: return 4;
299: }