00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019
00020 #include "sysdep.h"
00021 #include "opcode/d10v.h"
00022 #include "dis-asm.h"
00023
00024
00025
00026 #define PC_MASK 0x0303FFFF
00027
00028 static void dis_2_short PARAMS ((unsigned long insn, bfd_vma memaddr,
00029 struct disassemble_info *info, int order));
00030 static void dis_long PARAMS ((unsigned long insn, bfd_vma memaddr,
00031 struct disassemble_info *info));
00032 static void print_operand
00033 PARAMS ((struct d10v_operand *, long unsigned int, struct d10v_opcode *,
00034 bfd_vma, struct disassemble_info *));
00035
00036 int
00037 print_insn_d10v (memaddr, info)
00038 bfd_vma memaddr;
00039 struct disassemble_info *info;
00040 {
00041 int status;
00042 bfd_byte buffer[4];
00043 unsigned long insn;
00044
00045 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
00046 if (status != 0)
00047 {
00048 (*info->memory_error_func) (status, memaddr, info);
00049 return -1;
00050 }
00051 insn = bfd_getb32 (buffer);
00052
00053 status = insn & FM11;
00054 switch (status)
00055 {
00056 case 0:
00057 dis_2_short (insn, memaddr, info, 2);
00058 break;
00059 case FM01:
00060 dis_2_short (insn, memaddr, info, 0);
00061 break;
00062 case FM10:
00063 dis_2_short (insn, memaddr, info, 1);
00064 break;
00065 case FM11:
00066 dis_long (insn, memaddr, info);
00067 break;
00068 }
00069 return 4;
00070 }
00071
00072 static void
00073 print_operand (oper, insn, op, memaddr, info)
00074 struct d10v_operand *oper;
00075 unsigned long insn;
00076 struct d10v_opcode *op;
00077 bfd_vma memaddr;
00078 struct disassemble_info *info;
00079 {
00080 int num, shift;
00081
00082 if (oper->flags == OPERAND_ATMINUS)
00083 {
00084 (*info->fprintf_func) (info->stream, "@-");
00085 return;
00086 }
00087 if (oper->flags == OPERAND_MINUS)
00088 {
00089 (*info->fprintf_func) (info->stream, "-");
00090 return;
00091 }
00092 if (oper->flags == OPERAND_PLUS)
00093 {
00094 (*info->fprintf_func) (info->stream, "+");
00095 return;
00096 }
00097 if (oper->flags == OPERAND_ATSIGN)
00098 {
00099 (*info->fprintf_func) (info->stream, "@");
00100 return;
00101 }
00102 if (oper->flags == OPERAND_ATPAR)
00103 {
00104 (*info->fprintf_func) (info->stream, "@(");
00105 return;
00106 }
00107
00108 shift = oper->shift;
00109
00110
00111 if (op->format == LONG_L && (oper->flags & OPERAND_REG))
00112 shift += 15;
00113
00114 num = (insn >> shift) & (0x7FFFFFFF >> (31 - oper->bits));
00115
00116 if (oper->flags & OPERAND_REG)
00117 {
00118 int i;
00119 int match = 0;
00120 num += (oper->flags
00121 & (OPERAND_GPR | OPERAND_FFLAG | OPERAND_CFLAG | OPERAND_CONTROL));
00122 if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
00123 num += num ? OPERAND_ACC1 : OPERAND_ACC0;
00124 for (i = 0; i < d10v_reg_name_cnt (); i++)
00125 {
00126 if (num == (d10v_predefined_registers[i].value & ~ OPERAND_SP))
00127 {
00128 if (d10v_predefined_registers[i].pname)
00129 (*info->fprintf_func) (info->stream, "%s",
00130 d10v_predefined_registers[i].pname);
00131 else
00132 (*info->fprintf_func) (info->stream, "%s",
00133 d10v_predefined_registers[i].name);
00134 match = 1;
00135 break;
00136 }
00137 }
00138 if (match == 0)
00139 {
00140
00141
00142 if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
00143 (*info->fprintf_func) (info->stream, "a");
00144 else if (oper->flags & OPERAND_CONTROL)
00145 (*info->fprintf_func) (info->stream, "cr");
00146 else if (oper->flags & OPERAND_REG)
00147 (*info->fprintf_func) (info->stream, "r");
00148 (*info->fprintf_func) (info->stream, "%d", num & REGISTER_MASK);
00149 }
00150 }
00151 else
00152 {
00153
00154 if (oper->flags & OPERAND_ADDR)
00155 {
00156 long max;
00157 int neg = 0;
00158 max = (1 << (oper->bits - 1));
00159 if (num & max)
00160 {
00161 num = -num & ((1 << oper->bits) - 1);
00162 neg = 1;
00163 }
00164 num = num << 2;
00165 if (info->flags & INSN_HAS_RELOC)
00166 (*info->print_address_func) (num & PC_MASK, info);
00167 else
00168 {
00169 if (neg)
00170 (*info->print_address_func) ((memaddr - num) & PC_MASK, info);
00171 else
00172 (*info->print_address_func) ((memaddr + num) & PC_MASK, info);
00173 }
00174 }
00175 else
00176 {
00177 if (oper->flags & OPERAND_SIGNED)
00178 {
00179 int max = (1 << (oper->bits - 1));
00180 if (num & max)
00181 {
00182 num = -num & ((1 << oper->bits) - 1);
00183 (*info->fprintf_func) (info->stream, "-");
00184 }
00185 }
00186 (*info->fprintf_func) (info->stream, "0x%x", num);
00187 }
00188 }
00189 }
00190
00191 static void
00192 dis_long (insn, memaddr, info)
00193 unsigned long insn;
00194 bfd_vma memaddr;
00195 struct disassemble_info *info;
00196 {
00197 int i;
00198 struct d10v_opcode *op = (struct d10v_opcode *) d10v_opcodes;
00199 struct d10v_operand *oper;
00200 int need_paren = 0;
00201 int match = 0;
00202
00203 while (op->name)
00204 {
00205 if ((op->format & LONG_OPCODE) && ((op->mask & insn) == (unsigned long) op->opcode))
00206 {
00207 match = 1;
00208 (*info->fprintf_func) (info->stream, "%s\t", op->name);
00209 for (i = 0; op->operands[i]; i++)
00210 {
00211 oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
00212 if (oper->flags == OPERAND_ATPAR)
00213 need_paren = 1;
00214 print_operand (oper, insn, op, memaddr, info);
00215 if (op->operands[i + 1] && oper->bits
00216 && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
00217 && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
00218 (*info->fprintf_func) (info->stream, ", ");
00219 }
00220 break;
00221 }
00222 op++;
00223 }
00224
00225 if (!match)
00226 (*info->fprintf_func) (info->stream, ".long\t0x%08x", insn);
00227
00228 if (need_paren)
00229 (*info->fprintf_func) (info->stream, ")");
00230 }
00231
00232 static void
00233 dis_2_short (insn, memaddr, info, order)
00234 unsigned long insn;
00235 bfd_vma memaddr;
00236 struct disassemble_info *info;
00237 int order;
00238 {
00239 int i, j;
00240 unsigned int ins[2];
00241 struct d10v_opcode *op;
00242 int match, num_match = 0;
00243 struct d10v_operand *oper;
00244 int need_paren = 0;
00245
00246 ins[0] = (insn & 0x3FFFFFFF) >> 15;
00247 ins[1] = insn & 0x00007FFF;
00248
00249 for (j = 0; j < 2; j++)
00250 {
00251 op = (struct d10v_opcode *) d10v_opcodes;
00252 match = 0;
00253 while (op->name)
00254 {
00255 if ((op->format & SHORT_OPCODE)
00256 && ((op->mask & ins[j]) == (unsigned long) op->opcode))
00257 {
00258 (*info->fprintf_func) (info->stream, "%s\t", op->name);
00259 for (i = 0; op->operands[i]; i++)
00260 {
00261 oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
00262 if (oper->flags == OPERAND_ATPAR)
00263 need_paren = 1;
00264 print_operand (oper, ins[j], op, memaddr, info);
00265 if (op->operands[i + 1] && oper->bits
00266 && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
00267 && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
00268 (*info->fprintf_func) (info->stream, ", ");
00269 }
00270 match = 1;
00271 num_match++;
00272 break;
00273 }
00274 op++;
00275 }
00276 if (!match)
00277 (*info->fprintf_func) (info->stream, "unknown");
00278
00279 switch (order)
00280 {
00281 case 0:
00282 (*info->fprintf_func) (info->stream, "\t->\t");
00283 order = -1;
00284 break;
00285 case 1:
00286 (*info->fprintf_func) (info->stream, "\t<-\t");
00287 order = -1;
00288 break;
00289 case 2:
00290 (*info->fprintf_func) (info->stream, "\t||\t");
00291 order = -1;
00292 break;
00293 default:
00294 break;
00295 }
00296 }
00297
00298 if (num_match == 0)
00299 (*info->fprintf_func) (info->stream, ".long\t0x%08x", insn);
00300
00301 if (need_paren)
00302 (*info->fprintf_func) (info->stream, ")");
00303 }