1 /* Disassembler for the i860. 2 Copyright 2000, 2003 Free Software Foundation, Inc. 3 4 Contributed by Jason Eckhardt <jle@cygnus.com>. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19 20 #include "dis-asm.h" 21 #include "opcode/i860.h" 22 23 /* Later we should probably choose the prefix based on which OS flavor. */ 24 #define I860_REG_PREFIX "%" 25 26 /* Integer register names (encoded as 0..31 in the instruction). */ 27 static const char *const grnames[] = 28 {"r0", "r1", "sp", "fp", "r4", "r5", "r6", "r7", 29 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 30 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 31 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"}; 32 33 /* FP register names (encoded as 0..31 in the instruction). */ 34 static const char *const frnames[] = 35 {"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 36 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", 37 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", 38 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"}; 39 40 /* Control/status register names (encoded as 0..11 in the instruction). 41 Registers bear, ccr, p0, p1, p2 and p3 are XP only. */ 42 static const char *const crnames[] = 43 {"fir", "psr", "dirbase", "db", "fsr", "epsr", "bear", "ccr", 44 "p0", "p1", "p2", "p3", "--", "--", "--", "--" }; 45 46 47 48 /* True if opcode is xor, xorh, and, andh, or, orh, andnot, andnoth. */ 49 #define BITWISE_OP(op) ((op) == 0x30 || (op) == 0x31 \ 50 || (op) == 0x34 || (op) == 0x35 \ 51 || (op) == 0x38 || (op) == 0x39 \ 52 || (op) == 0x3c || (op) == 0x3d \ 53 || (op) == 0x33 || (op) == 0x37 \ 54 || (op) == 0x3b || (op) == 0x3f) 55 56 57 /* Sign extend N-bit number. */ 58 static int 59 sign_ext (unsigned int x, int n) 60 { 61 int t; 62 t = x >> (n - 1); 63 t = ((-t) << n) | x; 64 return t; 65 } 66 67 68 /* Print a PC-relative branch offset. VAL is the sign extended value 69 from the branch instruction. */ 70 static void 71 print_br_address (disassemble_info *info, bfd_vma memaddr, long val) 72 { 73 74 long adj = (long)memaddr + 4 + (val << 2); 75 76 (*info->fprintf_func) (info->stream, "0x%08x", adj); 77 78 /* Attempt to obtain a symbol for the target address. */ 79 80 if (info->print_address_func && adj != 0) 81 { 82 (*info->fprintf_func) (info->stream, "\t// "); 83 (*info->print_address_func) (adj, info); 84 } 85 } 86 87 88 /* Print one instruction. */ 89 int 90 print_insn_i860 (bfd_vma memaddr, disassemble_info *info) 91 { 92 bfd_byte buff[4]; 93 unsigned int insn, i; 94 int status; 95 const struct i860_opcode *opcode = 0; 96 97 status = (*info->read_memory_func) (memaddr, buff, sizeof (buff), info); 98 if (status != 0) 99 { 100 (*info->memory_error_func) (status, memaddr, info); 101 return -1; 102 } 103 104 /* Note that i860 instructions are always accessed as little endian 105 data, regardless of the endian mode of the i860. */ 106 insn = bfd_getl32 (buff); 107 108 status = 0; 109 i = 0; 110 while (i860_opcodes[i].name != NULL) 111 { 112 opcode = &i860_opcodes[i]; 113 if ((insn & opcode->match) == opcode->match 114 && (insn & opcode->lose) == 0) 115 { 116 status = 1; 117 break; 118 } 119 ++i; 120 } 121 122 if (status == 0) 123 { 124 /* Instruction not in opcode table. */ 125 (*info->fprintf_func) (info->stream, ".long %#08x", insn); 126 } 127 else 128 { 129 const char *s; 130 int val; 131 132 /* If this a flop (or a shrd) and its dual bit is set, 133 prefix with 'd.'. */ 134 if (((insn & 0xfc000000) == 0x48000000 135 || (insn & 0xfc000000) == 0xb0000000) 136 && (insn & 0x200)) 137 (*info->fprintf_func) (info->stream, "d.%s\t", opcode->name); 138 else 139 (*info->fprintf_func) (info->stream, "%s\t", opcode->name); 140 141 for (s = opcode->args; *s; s++) 142 { 143 switch (*s) 144 { 145 /* Integer register (src1). */ 146 case '1': 147 (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, 148 grnames[(insn >> 11) & 0x1f]); 149 break; 150 151 /* Integer register (src2). */ 152 case '2': 153 (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, 154 grnames[(insn >> 21) & 0x1f]); 155 break; 156 157 /* Integer destination register. */ 158 case 'd': 159 (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, 160 grnames[(insn >> 16) & 0x1f]); 161 break; 162 163 /* Floating-point register (src1). */ 164 case 'e': 165 (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, 166 frnames[(insn >> 11) & 0x1f]); 167 break; 168 169 /* Floating-point register (src2). */ 170 case 'f': 171 (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, 172 frnames[(insn >> 21) & 0x1f]); 173 break; 174 175 /* Floating-point destination register. */ 176 case 'g': 177 (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, 178 frnames[(insn >> 16) & 0x1f]); 179 break; 180 181 /* Control register. */ 182 case 'c': 183 (*info->fprintf_func) (info->stream, "%s%s", I860_REG_PREFIX, 184 crnames[(insn >> 21) & 0xf]); 185 break; 186 187 /* 16-bit immediate (sign extend, except for bitwise ops). */ 188 case 'i': 189 if (BITWISE_OP ((insn & 0xfc000000) >> 26)) 190 (*info->fprintf_func) (info->stream, "0x%04x", 191 (unsigned int) (insn & 0xffff)); 192 else 193 (*info->fprintf_func) (info->stream, "%d", 194 sign_ext ((insn & 0xffff), 16)); 195 break; 196 197 /* 16-bit immediate, aligned (2^0, ld.b). */ 198 case 'I': 199 (*info->fprintf_func) (info->stream, "%d", 200 sign_ext ((insn & 0xffff), 16)); 201 break; 202 203 /* 16-bit immediate, aligned (2^1, ld.s). */ 204 case 'J': 205 (*info->fprintf_func) (info->stream, "%d", 206 sign_ext ((insn & 0xfffe), 16)); 207 break; 208 209 /* 16-bit immediate, aligned (2^2, ld.l, {p}fld.l, fst.l). */ 210 case 'K': 211 (*info->fprintf_func) (info->stream, "%d", 212 sign_ext ((insn & 0xfffc), 16)); 213 break; 214 215 /* 16-bit immediate, aligned (2^3, {p}fld.d, fst.d). */ 216 case 'L': 217 (*info->fprintf_func) (info->stream, "%d", 218 sign_ext ((insn & 0xfff8), 16)); 219 break; 220 221 /* 16-bit immediate, aligned (2^4, {p}fld.q, fst.q). */ 222 case 'M': 223 (*info->fprintf_func) (info->stream, "%d", 224 sign_ext ((insn & 0xfff0), 16)); 225 break; 226 227 /* 5-bit immediate (zero extend). */ 228 case '5': 229 (*info->fprintf_func) (info->stream, "%d", 230 ((insn >> 11) & 0x1f)); 231 break; 232 233 /* Split 16 bit immediate (20..16:10..0). */ 234 case 's': 235 val = ((insn >> 5) & 0xf800) | (insn & 0x07ff); 236 (*info->fprintf_func) (info->stream, "%d", 237 sign_ext (val, 16)); 238 break; 239 240 /* Split 16 bit immediate, aligned. (2^0, st.b). */ 241 case 'S': 242 val = ((insn >> 5) & 0xf800) | (insn & 0x07ff); 243 (*info->fprintf_func) (info->stream, "%d", 244 sign_ext (val, 16)); 245 break; 246 247 /* Split 16 bit immediate, aligned. (2^1, st.s). */ 248 case 'T': 249 val = ((insn >> 5) & 0xf800) | (insn & 0x07fe); 250 (*info->fprintf_func) (info->stream, "%d", 251 sign_ext (val, 16)); 252 break; 253 254 /* Split 16 bit immediate, aligned. (2^2, st.l). */ 255 case 'U': 256 val = ((insn >> 5) & 0xf800) | (insn & 0x07fc); 257 (*info->fprintf_func) (info->stream, "%d", 258 sign_ext (val, 16)); 259 break; 260 261 /* 26-bit PC relative immediate (lbroff). */ 262 case 'l': 263 val = sign_ext ((insn & 0x03ffffff), 26); 264 print_br_address (info, memaddr, val); 265 break; 266 267 /* 16-bit PC relative immediate (sbroff). */ 268 case 'r': 269 val = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); 270 print_br_address (info, memaddr, val); 271 break; 272 273 default: 274 (*info->fprintf_func) (info->stream, "%c", *s); 275 break; 276 } 277 } 278 } 279 280 return sizeof (insn); 281 } 282 283