| 1 | /* NDS32-specific support for 32-bit ELF. |
| 2 | Copyright (C) 2012-2013 Free Software Foundation, Inc. |
| 3 | Contributed by Andes Technology Corporation. |
| 4 | |
| 5 | This file is part of BFD, the Binary File Descriptor library. |
| 6 | |
| 7 | This program is free software; you can redistribute it and/or modify |
| 8 | it under the terms of the GNU General Public License as published by |
| 9 | the Free Software Foundation; either version 3 of the License, or |
| 10 | (at your option) any later version. |
| 11 | |
| 12 | This program is distributed in the hope that it will be useful, |
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | GNU General Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License |
| 18 | along with this program; if not, write to the Free Software |
| 19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA |
| 20 | 02110-1301, USA.*/ |
| 21 | |
| 22 | |
| 23 | #include "sysdep.h" |
| 24 | #include <stdio.h> |
| 25 | #include "ansidecl.h" |
| 26 | #include "dis-asm.h" |
| 27 | #include "bfd.h" |
| 28 | #include "symcat.h" |
| 29 | #include "libiberty.h" |
| 30 | #include "opintl.h" |
| 31 | #include "bfd_stdint.h" |
| 32 | |
| 33 | #define __MF(v, off, bs) ((v & ((1 << (bs)) - 1)) << (off)) |
| 34 | #define __GF(v, off, bs) ((v >> (off)) & ((1 << (bs)) - 1)) |
| 35 | #define __PF(v, off, bs, val) do { v = __put_field (v, off, bs, val); } while (0) |
| 36 | /* #define __SEXT(v, bs) ((v ^ (1 << (bs - 1))) - (1 << (bs - 1))) */ |
| 37 | #define __SEXT(v, bs) (((v & ((1 << bs) - 1)) ^ (1 << (bs - 1))) - (1 << (bs - 1))) |
| 38 | #define __BIT(n) (1 << n) |
| 39 | |
| 40 | /* Get fields */ |
| 41 | #define OP6(insn) ((insn >> 25) & 0x3F) |
| 42 | #define RT5(insn) ((insn >> 20) & 0x1F) |
| 43 | #define RA5(insn) ((insn >> 15) & 0x1F) |
| 44 | #define RB5(insn) ((insn >> 10) & 0x1F) |
| 45 | #define RD5(insn) ((insn >> 5) & 0x1F) |
| 46 | #define SUB5(insn) ((insn >> 0) & 0x1F) |
| 47 | #define SUB10(insn) ((insn >> 0) & 0x3FF) |
| 48 | #define IMMU(insn, bs) (insn & ((1 << bs) - 1)) |
| 49 | #define IMMS(insn, bs) __SEXT ((insn & ((1 << bs) - 1)), bs) |
| 50 | #define IMM1U(insn) IMMU ((insn >> 10), 5) |
| 51 | #define IMM1S(insn) IMMS ((insn >> 10), 5) |
| 52 | #define IMM2U(insn) IMMU ((insn >> 5), 5) |
| 53 | #define IMM2S(insn) IMMS ((insn >> 5), 5) |
| 54 | |
| 55 | /* Default text to print if an instruction isn't recognized. */ |
| 56 | #define UNKNOWN_INSN_MSG _("*unknown*") |
| 57 | |
| 58 | static const char *mnemonic_op6[] = |
| 59 | { |
| 60 | "lbi", "lhi", "lwi", "ldi", "lbi.bi", "lhi.bi", "lwi.bi", "ldi.bi", |
| 61 | "sbi", "shi", "swi", "sdi", "sbi.bi", "shi.bi", "swi.bi", "sdi.bi", |
| 62 | "lbsi", "lhsi", "lwsi", "dprefi", "lbsi.bi", "lhsi.bi", "lwsi.bi", "lbgp", |
| 63 | "lwc", "swc", "ldc", "sdc", "mem", "lsmw", "hwgp", "sbgp", |
| 64 | "alu1", "alu2", "movi", "sethi", "ji", "jreg", "br1", "br2", |
| 65 | "addi", "subri", "andi", "xori", "ori", "br3", "slti", "sltsi", |
| 66 | "aext", "cext", "misc", "bitci", "op_64", "cop" |
| 67 | }; |
| 68 | |
| 69 | static const char *mnemonic_mem[] = |
| 70 | { |
| 71 | "lb", "lh", "lw", "ld", "lb.bi", "lh.bi", "lw.bi", "ld.bi", |
| 72 | "sb", "sh", "sw", "sd", "sb.bi", "sh.bi", "sw.bi", "sd.bi", |
| 73 | "lbs", "lhs", "lws", "dpref", "lbs.bi", "lhs.bi", "lws.bi", "27", |
| 74 | "llw", "scw", "32", "33", "34", "35", "36", "37", |
| 75 | "lbup", "41", "lwup", "43", "44", "45", "46", "47", |
| 76 | "sbup", "51", "swup" |
| 77 | }; |
| 78 | |
| 79 | static const char *mnemonic_alu1[] = |
| 80 | { |
| 81 | "add", "sub", "and", "xor", "or", "nor", "slt", "slts", |
| 82 | "slli", "srli", "srai", "rotri", "sll", "srl", "sra", "rotr", |
| 83 | "seb", "seh", "bitc", "zeh", "wsbh", "or_srli", "divsr", "divr", |
| 84 | "sva", "svs", "cmovz", "cmovn", "add_srli", "sub_srli", "and_srli", "xor_srli" |
| 85 | }; |
| 86 | |
| 87 | |
| 88 | static const char *mnemonic_alu20[] = |
| 89 | { |
| 90 | "max", "min", "ave", "abs", "clips", "clip", "clo", "clz", |
| 91 | "bset", "bclr", "btgl", "btst", "bse", "bsp", "ffb", "ffmism", |
| 92 | "add.sc", "sub.sc", "add.wc", "sub.wc", "24", "25", "26", "ffzmism", |
| 93 | "qadd", "qsub", "32", "33", "34", "35", "36", "37", |
| 94 | "mfusr", "mtusr", "42", "43", "mul", "45", "46", "47", |
| 95 | "mults64", "mult64", "madds64", "madd64", "msubs64", "msub64", "divs", "div", |
| 96 | "60", "mult32", "62", "madd32", "64", "msub32", "65", "66", |
| 97 | "dmadd", "dmaddc", "dmsub", "dmsubc", "rmfhi", "qmflo" |
| 98 | }; |
| 99 | |
| 100 | static const char *mnemonic_alu21[] = |
| 101 | { |
| 102 | "00", "01", "02", "03", "04", "05", "06", "07", |
| 103 | "10", "11", "12", "13", "14", "15", "ffbi", "flmism", |
| 104 | "20", "21", "22", "23", "24", "25", "26", "27", |
| 105 | "30", "31", "32", "33", "34", "35", "36", "37", |
| 106 | "40", "41", "42", "43", "44", "45", "46", "47", |
| 107 | "mulsr64", "mulr64", "52", "53", "54", "55", "56", "57", |
| 108 | "60", "61", "62", "maddr32", "64", "msubr32", "66", "67", |
| 109 | "70", "71", "72", "73", "74", "75", "76", "77" |
| 110 | }; |
| 111 | |
| 112 | static const char *mnemonic_br2[] = |
| 113 | { |
| 114 | "ifcall", "01", "beqz", "bnez", "bgez", "bltz", "bgtz", "blez", |
| 115 | "10", "11", "12", "13", "bgezal", "bltzal" |
| 116 | }; |
| 117 | |
| 118 | static const char *mnemonic_misc[] = |
| 119 | { |
| 120 | "standby", "cctl", "mfsr", "mtsr", "iret", "trap", "teqz", "tnez", |
| 121 | "dsb", "isb", "break", "syscall", "msync", "isync", "tlbop" |
| 122 | }; |
| 123 | |
| 124 | static const char *mnemonic_hwgp[] = |
| 125 | { |
| 126 | "lhi.gp", "lhi.gp", "lhsi.gp", "lhsi.gp", |
| 127 | "shi.gp", "shi.gp", "lwi.gp", "swi.gp" |
| 128 | }; |
| 129 | |
| 130 | static const char *keyword_dpref[] = |
| 131 | { |
| 132 | "SRD", "MRD", "SWR", "MWR", "PTE", "CLWR", "6", "7", |
| 133 | "8", "9", "10", "11", "12", "13", "14", "15" |
| 134 | }; |
| 135 | |
| 136 | static const char *mnemonic_alu[] = |
| 137 | { |
| 138 | "fadds", "fsubs", "fcpynss", "fcpyss", "fmadds", |
| 139 | "fmsubs", "fcmovns", "fcmovzs", "fnmadds", "fnmsubs", |
| 140 | "10", "11", "fmuls", "fdivs", "faddd", |
| 141 | "fsubd", "fcpynsd", "fcpysd", "fmaddd", "fmsubd", |
| 142 | "fcmovnd", "fcmovzd", "fnmaddd", "fnmsubd", "24", |
| 143 | "25", "fmuld", "fdivd" |
| 144 | }; |
| 145 | |
| 146 | static const char *mnemonic_fpu_2op[] = |
| 147 | { |
| 148 | "fs2d", "fsqrts", "2", "3", "4", "fabss", "6", "7", |
| 149 | "fui2s", "9", "10", "11", "fsi2s", "13", "14", "15", |
| 150 | "fs2ui", "17", "18", "19", "fs2ui.z", "21", "22", "23", |
| 151 | "fs2si", "25", "26", "27", "fs2si.z", "fd2s", "fsqrtd", "31", |
| 152 | "32", "33", "fabsd", "35", "36", "fui2d", "38", "39", |
| 153 | "40", "fsi2d", "42", "43", "44", "fd2ui", "46", "47", |
| 154 | "48", "fd2ui.z", "50", "51", "52", "fd2si", "54", "55", |
| 155 | "56", "fd2si.z" |
| 156 | }; |
| 157 | |
| 158 | static const char *mnemonic_fs2_cmp[] = |
| 159 | { |
| 160 | "fcmpeqs", "fcmpeqs.e", "fcmplts", "fcmplts.e", |
| 161 | "fcmples", "fcmples.e", "fcmpuns", "fcmpuns.e" |
| 162 | }; |
| 163 | |
| 164 | static const char *mnemonic_fd2_cmp[] = |
| 165 | { |
| 166 | "fcmpeqd", "fcmpeqd.e", "fcmpltd", "fcmpltd.e", |
| 167 | "fcmpled", "fcmpled.e", "fcmpund", "fcmpund.e" |
| 168 | }; |
| 169 | |
| 170 | /* Register name table. */ |
| 171 | /* General purpose register. */ |
| 172 | |
| 173 | static const char *gpr_map[] = |
| 174 | { |
| 175 | "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", |
| 176 | "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", |
| 177 | "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", |
| 178 | "$r24", "$r25", "$r26", "$r27", "$fp", "$gp", "$lp", "$sp" |
| 179 | }; |
| 180 | |
| 181 | /* User special register. */ |
| 182 | |
| 183 | static const char *usr_map[][32] = |
| 184 | { |
| 185 | { |
| 186 | "d0.lo", "d0.hi", "d1.lo", "d1.hi", "4", "5", "6", "7", |
| 187 | "8", "9", "10", "11", "12", "13", "14", "15", |
| 188 | "16", "17", "18", "19", "20", "21", "22", "23", |
| 189 | "24", "25", "26", "27", "28", "29", "30", "pc" |
| 190 | }, |
| 191 | { |
| 192 | "DMA_CFG", "DMA_GCSW", "DMA_CHNSEL", "DMA_ACT", "DMA_SETUP", |
| 193 | "DMA_ISADDR", "DMA_ESADDR", "DMA_TCNT", "DMA_STATUS", "DMA_2DSET", |
| 194 | "10", "11", "12", "13", "14", |
| 195 | "15", "16", "17", "18", "19", |
| 196 | "20", "21", "22", "23", "24", |
| 197 | "DMA_2DSCTL" |
| 198 | }, |
| 199 | { |
| 200 | "PFMC0", "PFMC1", "PFMC2", "3", "PFM_CTL" |
| 201 | } |
| 202 | }; |
| 203 | |
| 204 | /* System register. */ |
| 205 | /* Major Minor Extension. */ |
| 206 | static const char *sr_map[8][16][8] = |
| 207 | { |
| 208 | { |
| 209 | {"CPU_VER", "CORE_ID"}, |
| 210 | {"ICM_CFG"}, |
| 211 | {"DCM_CFG"}, |
| 212 | {"MMU_CFG"}, |
| 213 | {"MSC_CFG"} |
| 214 | }, |
| 215 | { |
| 216 | {"PSW", "IPSW", "P_IPSW"}, |
| 217 | {"0", "IVB", "INT_CTRL"}, |
| 218 | {"0", "EVA", "P_EVA"}, |
| 219 | {"0", "ITYPE", "P_ITYPE"}, |
| 220 | {"0", "MERR"}, |
| 221 | {"0", "IPC", "P_IPC", "OIPC"}, |
| 222 | {"0", "1", "P_P0"}, |
| 223 | {"0", "1", "P_P1"}, |
| 224 | {"INT_MASK", "INT_MASK2"}, |
| 225 | {"INT_PEND", "INT_PEND2", "2", "3", "INT_TRIGGER"}, |
| 226 | {"SP_USR", "SP_PRIV"}, |
| 227 | {"INT_PRI", "INT_PRI2"} |
| 228 | }, |
| 229 | { |
| 230 | {"MMU_CTL"}, |
| 231 | {"L1_PPTB"}, |
| 232 | {"TLB_VPN"}, |
| 233 | {"TLB_DATA"}, |
| 234 | {"TLB_MISC"}, |
| 235 | {"VLPT_IDX"}, |
| 236 | {"ILMB"}, |
| 237 | {"DLMB"}, |
| 238 | {"CACHE_CTL"}, |
| 239 | {"HSMP_SADDR", "HSMP_EADDR"}, |
| 240 | {"0"}, |
| 241 | {"0"}, |
| 242 | {"0"}, |
| 243 | {"0"}, |
| 244 | {"0"}, |
| 245 | {"SDZ_CTL", "MISC_CTL"} |
| 246 | }, |
| 247 | { |
| 248 | {"BPC0", "BPC1", "BPC2", "BPC3", "BPC4", "BPC5", "BPC6", "BPC7"}, |
| 249 | {"BPA0", "BPA1", "BPA2", "BPA3", "BPA4", "BPA5", "BPA6", "BPA7"}, |
| 250 | {"BPAM0", "BPAM1", "BPAM2", "BPAM3", "BPAM4", "BPAM5", "BPAM6", "BPAM7"}, |
| 251 | {"BPV0", "BPV1", "BPV2", "BPV3", "BPV4", "BPV5", "BPV6", "BPV7"}, |
| 252 | {"BPCID0", "BPCID1", "BPCID2", "BPCID3", "BPCID4", "BPCID5", "BPCID6", "BPCID7"}, |
| 253 | {"EDM_CFG"}, |
| 254 | {"EDMSW"}, |
| 255 | {"EDM_CTL"}, |
| 256 | {"EDM_DTR"}, |
| 257 | {"BPMTC"}, |
| 258 | {"DIMBR"}, |
| 259 | {"EDM_PROBE"}, |
| 260 | {"0"}, |
| 261 | {"0"}, |
| 262 | {"TECR0", "TECR1"} |
| 263 | }, |
| 264 | { |
| 265 | {"PFMC0", "PFMC1", "PFMC2"}, |
| 266 | {"PFM_CTL"}, |
| 267 | {"0"}, |
| 268 | {"0"}, |
| 269 | {"PRUSR_ACC_CTL"}, |
| 270 | {"FUCOP_CTL"} |
| 271 | }, |
| 272 | { |
| 273 | {"DMA_CFG"}, |
| 274 | {"DMA_GCSW"}, |
| 275 | {"DMA_CHNSEL"}, |
| 276 | {"DMA_ACT"}, |
| 277 | {"DMA_SETUP"}, |
| 278 | {"DMA_ISADDR"}, |
| 279 | {"DMA_ESADDR"}, |
| 280 | {"DMA_TCNT"}, |
| 281 | {"DMA_STATUS"}, |
| 282 | {"DMA_2DSET", "DMA_2DSCTL"} |
| 283 | } |
| 284 | }; |
| 285 | |
| 286 | static void |
| 287 | print_insn16 (bfd_vma pc, disassemble_info *info, uint32_t insn) |
| 288 | { |
| 289 | static char r4map[] = |
| 290 | { |
| 291 | 0, 1, 2, 3, 4, 5, 6, 7, |
| 292 | 8, 9, 10, 11, 16, 17, 18, 19 |
| 293 | }; |
| 294 | const int rt5 = __GF (insn, 5, 5); |
| 295 | const int ra5 = __GF (insn, 0, 5); |
| 296 | const int rt4 = r4map[__GF (insn, 5, 4)]; |
| 297 | const int imm5u = IMMU (insn, 5); |
| 298 | const int imm9u = IMMU (insn, 9); |
| 299 | const int rt3 = __GF (insn, 6, 3); |
| 300 | const int ra3 = __GF (insn, 3, 3); |
| 301 | const int rb3 = __GF (insn, 0, 3); |
| 302 | const int rt38 = __GF (insn, 8, 3); |
| 303 | const int imm3u = rb3; |
| 304 | fprintf_ftype func = info->fprintf_func; |
| 305 | void *stream = info->stream; |
| 306 | |
| 307 | static const char *mnemonic_96[] = |
| 308 | { |
| 309 | "0x1", "0x1", "0x2", "0x3", |
| 310 | "add45", "sub45", "addi45", "subi45", |
| 311 | "srai45", "srli45", "slli333", "0xb", |
| 312 | "add333", "sub333", "addi333", "subi333", |
| 313 | "lwi333", "lwi333.bi", "lhi333", "lbi333", |
| 314 | "swi333", "swi333.bi", "shi333", "sbi333", |
| 315 | "addri36.sp", "lwi45.fe", "lwi450", "swi450", |
| 316 | "0x1c", "0x1d", "0x1e", "0x1f", |
| 317 | "0x20", "0x21", "0x22", "0x23", |
| 318 | "0x24", "0x25", "0x26", "0x27", |
| 319 | "0x28", "0x29", "0x2a", "0x2b", |
| 320 | "0x2c", "0x2d", "0x2e", "0x2f", |
| 321 | "slts45", "slt45", "sltsi45", "slti45", |
| 322 | "0x34", "0x35", "0x36", "0x37", |
| 323 | "0x38", "0x39", "0x3a", "0x3b", |
| 324 | "ifcall9", "movpi45" |
| 325 | }; |
| 326 | |
| 327 | static const char *mnemonic_misc33[] = |
| 328 | { |
| 329 | "misc33_0", "misc33_1", "neg33", "not33", "mul33", "xor33", "and33", "or33", |
| 330 | }; |
| 331 | |
| 332 | static const char *mnemonic_0xb[] = |
| 333 | { |
| 334 | "zeb33", "zeh33", "seb33", "seh33", "xlsb33", "x11b33", "bmski33", "fexti33" |
| 335 | }; |
| 336 | |
| 337 | static const char *mnemonic_bnes38[] = |
| 338 | { |
| 339 | "jr5", "jral5", "ex9.it", "?", "ret5", "add5.pc" |
| 340 | }; |
| 341 | |
| 342 | switch (__GF (insn, 7, 8)) |
| 343 | { |
| 344 | case 0xf8: /* push25 */ |
| 345 | case 0xf9: /* pop25 */ |
| 346 | { |
| 347 | uint32_t res[] = { 6, 8, 10, 14 }; |
| 348 | uint32_t re = res[__GF (insn, 5, 2)]; |
| 349 | |
| 350 | func (stream, "%s\t%s, %d", (insn & __BIT (7)) ? "pop25" : "push25", |
| 351 | gpr_map[re], imm5u << 3); |
| 352 | } |
| 353 | return; |
| 354 | } |
| 355 | |
| 356 | if (__GF (insn, 8, 7) == 0x7d) /* movd44 */ |
| 357 | { |
| 358 | int rt5e = __GF (insn, 4, 4) << 1; |
| 359 | int ra5e = IMMU (insn, 4) << 1; |
| 360 | |
| 361 | func (stream, "movd44\t%s, %d", gpr_map[rt5e], ra5e); |
| 362 | return; |
| 363 | } |
| 364 | |
| 365 | switch (__GF (insn, 9, 6)) |
| 366 | { |
| 367 | case 0x4: /* add45 */ |
| 368 | case 0x5: /* sub45 */ |
| 369 | case 0x30: /* slts45 */ |
| 370 | case 0x31: /* slt45 */ |
| 371 | func (stream, "%s\t%s, %s", mnemonic_96[__GF (insn, 9, 6)], |
| 372 | gpr_map[rt4], gpr_map[ra5]); |
| 373 | return; |
| 374 | case 0x6: /* addi45 */ |
| 375 | case 0x7: /* subi45 */ |
| 376 | case 0x8: /* srai45 */ |
| 377 | case 0x9: /* srli45 */ |
| 378 | case 0x32: /* sltsi45 */ |
| 379 | case 0x33: /* slti45 */ |
| 380 | func (stream, "%s\t%s, %d", mnemonic_96[__GF (insn, 9, 6)], |
| 381 | gpr_map[rt4], ra5); |
| 382 | return; |
| 383 | case 0xc: /* add333 */ |
| 384 | case 0xd: /* sub333 */ |
| 385 | func (stream, "%s\t%s, %s, %s", mnemonic_96[__GF (insn, 9, 6)], |
| 386 | gpr_map[rt3], gpr_map[ra3], gpr_map[rb3]); |
| 387 | return; |
| 388 | case 0xa: /* slli333 */ |
| 389 | case 0xe: /* addi333 */ |
| 390 | case 0xf: /* subi333 */ |
| 391 | func (stream, "%s\t%s, %s, %d", mnemonic_96[__GF (insn, 9, 6)], |
| 392 | gpr_map[rt3], gpr_map[ra3], imm3u); |
| 393 | return; |
| 394 | case 0x10: /* lwi333 */ |
| 395 | case 0x14: /* swi333 */ |
| 396 | func (stream, "%s\t%s, [%s + %d]", mnemonic_96[__GF (insn, 9, 6)], |
| 397 | gpr_map[rt3], gpr_map[ra3], imm3u << 2); |
| 398 | return; |
| 399 | case 0x12: /* lhi333 */ |
| 400 | case 0x16: /* shi333 */ |
| 401 | func (stream, "%s\t%s, [%s + %d]", mnemonic_96[__GF (insn, 9, 6)], |
| 402 | gpr_map[rt3], gpr_map[ra3], imm3u << 1); |
| 403 | return; |
| 404 | case 0x13: /* lbi333 */ |
| 405 | case 0x17: /* sbi333 */ |
| 406 | func (stream, "%s\t%s, [%s + %d]", mnemonic_96[__GF (insn, 9, 6)], |
| 407 | gpr_map[rt3], gpr_map[ra3], imm3u); |
| 408 | return; |
| 409 | case 0x11: /* lwi333.bi */ |
| 410 | case 0x15: /* swi333.bi */ |
| 411 | func (stream, "%s\t%s, [%s], %d", mnemonic_96[__GF (insn, 9, 6)], |
| 412 | gpr_map[rt3], gpr_map[ra3], imm3u << 2); |
| 413 | return; |
| 414 | case 0x18: /* addri36.sp */ |
| 415 | func (stream, "%s\t%s, %d", mnemonic_96[__GF (insn, 9, 6)], |
| 416 | gpr_map[rt3], IMMU (insn, 6) << 2); |
| 417 | return; |
| 418 | case 0x19: /* lwi45.fe */ |
| 419 | func (stream, "%s\t%s, %d", mnemonic_96[__GF (insn, 9, 6)], |
| 420 | gpr_map[rt4], -((32 - imm5u) << 2)); |
| 421 | return; |
| 422 | case 0x1a: /* lwi450 */ |
| 423 | case 0x1b: /* swi450 */ |
| 424 | func (stream, "%s\t%s, [%s]", mnemonic_96[__GF (insn, 9, 6)], |
| 425 | gpr_map[rt4], gpr_map[ra5]); |
| 426 | return; |
| 427 | case 0x34: /* beqzs8, bnezs8 */ |
| 428 | func (stream, "%s\t", ((insn & __BIT (8)) ? "bnezs8" : "beqzs8")); |
| 429 | info->print_address_func ((IMMS (insn, 8) << 1) + pc, info); |
| 430 | return; |
| 431 | case 0x35: /* break16, ex9.it */ |
| 432 | /* FIXME: Check bfd_mach. */ |
| 433 | if (imm9u < 32) /* break16 */ |
| 434 | func (stream, "break16\t%d", imm9u); |
| 435 | else |
| 436 | func (stream, "ex9.it\t%d", imm9u); |
| 437 | return; |
| 438 | case 0x3c: /* ifcall9 */ |
| 439 | func (stream, "%s\t", mnemonic_96[__GF (insn, 9, 6)]); |
| 440 | info->print_address_func ((IMMU (insn, 9) << 1) + pc, info); |
| 441 | return; |
| 442 | case 0x3d: /* movpi45 */ |
| 443 | func (stream, "%s\t%s, %d", mnemonic_96[__GF (insn, 9, 6)], |
| 444 | gpr_map[rt4], ra5 + 16); |
| 445 | return; |
| 446 | case 0x3f: /* MISC33 */ |
| 447 | func (stream, "%s\t%s, %s", mnemonic_misc33[rb3], |
| 448 | gpr_map[rt3], gpr_map[ra3]); |
| 449 | return; |
| 450 | case 0xb: /* ... */ |
| 451 | func (stream, "%s\t%s, %s", mnemonic_0xb[rb3], |
| 452 | gpr_map[rt3], gpr_map[ra3]); |
| 453 | return; |
| 454 | } |
| 455 | |
| 456 | switch (__GF (insn, 10, 5)) |
| 457 | { |
| 458 | case 0x0: /* mov55 or ifret16 */ |
| 459 | /* FIXME: Check bfd_mach. */ |
| 460 | if (rt5 == ra5 && rt5 == 31) |
| 461 | func (stream, "ifret16"); |
| 462 | else |
| 463 | func (stream, "mov55\t%s, %s", gpr_map[rt5], gpr_map[ra5]); |
| 464 | return; |
| 465 | case 0x1: /* movi55 */ |
| 466 | func (stream, "movi55\t%s, %d", gpr_map[rt5], IMMS (insn, 5)); |
| 467 | return; |
| 468 | case 0x1b: /* addi10s (V2) */ |
| 469 | func (stream, "addi10s\t%d", IMMS (insn, 10)); |
| 470 | return; |
| 471 | } |
| 472 | |
| 473 | switch (__GF (insn, 11, 4)) |
| 474 | { |
| 475 | case 0x7: /* lwi37.fp/swi37.fp */ |
| 476 | func (stream, "%s\t%s, [$fp + 0x%x]", |
| 477 | ((insn & __BIT (7)) ? "swi37" : "lwi37"), |
| 478 | gpr_map[rt38], IMMU (insn, 7) << 2); |
| 479 | return; |
| 480 | case 0x8: /* beqz38 */ |
| 481 | case 0x9: /* bnez38 */ |
| 482 | func (stream, "%s\t%s, ", |
| 483 | ((__GF (insn, 11, 4) & 1) ? "bnez38" : "beqz38"), gpr_map[rt38]); |
| 484 | info->print_address_func ((IMMS (insn, 8) << 1) + pc, info); |
| 485 | return; |
| 486 | case 0xa: /* beqs38/j8, implied r5 */ |
| 487 | if (rt38 == 5) |
| 488 | { |
| 489 | func (stream, "j8\t"); |
| 490 | info->print_address_func ((IMMS (insn, 8) << 1) + pc, info); |
| 491 | } |
| 492 | else |
| 493 | { |
| 494 | func (stream, "beqs38\t%s, ", gpr_map[rt38]); |
| 495 | info->print_address_func ((IMMS (insn, 8) << 1) + pc, info); |
| 496 | } |
| 497 | return; |
| 498 | case 0xb: /* bnes38 and others */ |
| 499 | if (rt38 == 5) |
| 500 | { |
| 501 | switch (__GF (insn, 5, 3)) |
| 502 | { |
| 503 | case 0: /* jr5 */ |
| 504 | case 1: /* jral5 */ |
| 505 | case 4: /* ret5 */ |
| 506 | func (stream, "%s\t%s", mnemonic_bnes38[__GF (insn, 5, 3)], |
| 507 | gpr_map[ra5]); |
| 508 | return; |
| 509 | case 2: /* ex9.it imm5 */ |
| 510 | case 5: /* add5.pc */ |
| 511 | func (stream, "%s\t%d", mnemonic_bnes38[__GF (insn, 5, 3)], ra5); |
| 512 | return; |
| 513 | default: |
| 514 | func (stream, UNKNOWN_INSN_MSG); |
| 515 | return; |
| 516 | } |
| 517 | } |
| 518 | else |
| 519 | { |
| 520 | func (stream, "bnes38\t%s", gpr_map[rt3]); |
| 521 | info->print_address_func ((IMMS (insn, 8) << 1) + pc, info); |
| 522 | } |
| 523 | return; |
| 524 | case 0xe: /* lwi37/swi37 */ |
| 525 | func (stream, "%s\t%s, [+ 0x%x]", |
| 526 | ((insn & __BIT (7)) ? "swi37.sp" : "lwi37.sp"), |
| 527 | gpr_map[rt38], IMMU (insn, 7) << 2); |
| 528 | return; |
| 529 | } |
| 530 | } |
| 531 | |
| 532 | |
| 533 | static void |
| 534 | print_insn32_mem (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info, |
| 535 | uint32_t insn) |
| 536 | { |
| 537 | const int rt = RT5 (insn); |
| 538 | const int ra = RA5 (insn); |
| 539 | const int rb = RB5 (insn); |
| 540 | const int sv = __GF (insn, 8, 2); |
| 541 | const int op = insn & 0xFF; |
| 542 | fprintf_ftype func = info->fprintf_func; |
| 543 | void *stream = info->stream; |
| 544 | |
| 545 | switch (op) |
| 546 | { |
| 547 | case 0x0: /* lb */ |
| 548 | case 0x1: /* lh */ |
| 549 | case 0x2: /* lw */ |
| 550 | case 0x3: /* ld */ |
| 551 | case 0x8: /* sb */ |
| 552 | case 0x9: /* sh */ |
| 553 | case 0xa: /* sw */ |
| 554 | case 0xb: /* sd */ |
| 555 | case 0x10: /* lbs */ |
| 556 | case 0x11: /* lhs */ |
| 557 | case 0x12: /* lws */ |
| 558 | case 0x18: /* llw */ |
| 559 | case 0x19: /* scw */ |
| 560 | case 0x20: /* lbup */ |
| 561 | case 0x22: /* lwup */ |
| 562 | case 0x28: /* sbup */ |
| 563 | case 0x2a: /* swup */ |
| 564 | func (stream, "%s\t%s, [%s + (%s << %d)]", |
| 565 | mnemonic_mem[op], gpr_map[rt], gpr_map[ra], gpr_map[rb], sv); |
| 566 | break; |
| 567 | case 0x4: /* lb.bi */ |
| 568 | case 0x5: /* lh.bi */ |
| 569 | case 0x6: /* lw.bi */ |
| 570 | case 0x7: /* ld.bi */ |
| 571 | case 0xc: /* sb.bi */ |
| 572 | case 0xd: /* sh.bi */ |
| 573 | case 0xe: /* sw.bi */ |
| 574 | case 0xf: /* sd.bi */ |
| 575 | case 0x14: /* lbs.bi */ |
| 576 | case 0x15: /* lhs.bi */ |
| 577 | case 0x16: /* lws.bi */ |
| 578 | func (stream, "%s\t%s, [%s], (%s << %d)", |
| 579 | mnemonic_mem[op], gpr_map[rt], gpr_map[ra], gpr_map[rb], sv); |
| 580 | break; |
| 581 | case 0x13: /* dpref */ |
| 582 | { |
| 583 | const char *subtype = "???"; |
| 584 | |
| 585 | if ((rt & 0xf) < ARRAY_SIZE (keyword_dpref)) |
| 586 | subtype = keyword_dpref[rt & 0xf]; |
| 587 | |
| 588 | func (stream, "%s\t%s, [%s + (%s << %d)]", |
| 589 | "dpref", subtype, gpr_map[ra], gpr_map[rb], sv); |
| 590 | } |
| 591 | break; |
| 592 | default: |
| 593 | func (stream, UNKNOWN_INSN_MSG); |
| 594 | return; |
| 595 | } |
| 596 | } |
| 597 | |
| 598 | static void |
| 599 | print_insn32_alu1 (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info, uint32_t insn) |
| 600 | { |
| 601 | int op = insn & 0x1f; |
| 602 | const int rt = RT5 (insn); |
| 603 | const int ra = RA5 (insn); |
| 604 | const int rb = RB5 (insn); |
| 605 | const int rd = RD5 (insn); |
| 606 | fprintf_ftype func = info->fprintf_func; |
| 607 | void *stream = info->stream; |
| 608 | |
| 609 | switch (op) |
| 610 | { |
| 611 | case 0x0: /* add, add_slli */ |
| 612 | case 0x1: /* sub, sub_slli */ |
| 613 | case 0x2: /* and, add_slli */ |
| 614 | case 0x3: /* xor, xor_slli */ |
| 615 | case 0x4: /* or, or_slli */ |
| 616 | if (rd != 0) |
| 617 | { |
| 618 | func (stream, "%s_slli\t%s, %s, %s, #%d", |
| 619 | mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], gpr_map[rb], rd); |
| 620 | } |
| 621 | else |
| 622 | { |
| 623 | func (stream, "%s\t%s, %s, %s", |
| 624 | mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], gpr_map[rb]); |
| 625 | } |
| 626 | return; |
| 627 | case 0x1c: /* add_srli */ |
| 628 | case 0x1d: /* sub_srli */ |
| 629 | case 0x1e: /* and_srli */ |
| 630 | case 0x1f: /* xor_srli */ |
| 631 | case 0x15: /* or_srli */ |
| 632 | func (stream, "%s\t%s, %s, %s, #%d", |
| 633 | mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], gpr_map[rb], rd); |
| 634 | return; |
| 635 | case 0x5: /* nor */ |
| 636 | case 0x6: /* slt */ |
| 637 | case 0x7: /* slts */ |
| 638 | case 0xc: /* sll */ |
| 639 | case 0xd: /* srl */ |
| 640 | case 0xe: /* sra */ |
| 641 | case 0xf: /* rotr */ |
| 642 | case 0x12: /* bitc */ |
| 643 | case 0x18: /* sva */ |
| 644 | case 0x19: /* svs */ |
| 645 | case 0x1a: /* cmovz */ |
| 646 | case 0x1b: /* cmovn */ |
| 647 | func (stream, "%s\t%s, %s, %s", |
| 648 | mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], gpr_map[rb]); |
| 649 | return; |
| 650 | case 0x9: /* srli */ |
| 651 | if (ra ==0 && rb == 0 && rb==0) |
| 652 | { |
| 653 | func (stream, "nop"); |
| 654 | return; |
| 655 | } |
| 656 | case 0x8: /* slli */ |
| 657 | case 0xa: /* srai */ |
| 658 | case 0xb: /* rotri */ |
| 659 | func (stream, "%s\t%s, %s, #%d", |
| 660 | mnemonic_alu1[op], gpr_map[rt], gpr_map[ra], rb); |
| 661 | return; |
| 662 | case 0x10: /* seb */ |
| 663 | case 0x11: /* seh */ |
| 664 | case 0x13: /* zeh */ |
| 665 | case 0x14: /* wsbh */ |
| 666 | func (stream, "%s\t%s, %s", |
| 667 | mnemonic_alu1[op], gpr_map[rt], gpr_map[ra]); |
| 668 | return; |
| 669 | case 0x16: /* divsr */ |
| 670 | case 0x17: /* divr */ |
| 671 | func (stream, "%s\t%s, %s, %s, %s", |
| 672 | mnemonic_alu1[op], gpr_map[rt], gpr_map[rd], gpr_map[ra], gpr_map[rb]); |
| 673 | return; |
| 674 | default: |
| 675 | func (stream, UNKNOWN_INSN_MSG); |
| 676 | return; |
| 677 | } |
| 678 | |
| 679 | return; |
| 680 | } |
| 681 | |
| 682 | static void |
| 683 | print_insn32_alu2 (bfd_vma pc ATTRIBUTE_UNUSED, |
| 684 | disassemble_info *info, |
| 685 | uint32_t insn) |
| 686 | { |
| 687 | int op = insn & 0x3ff; |
| 688 | const int rt = RT5 (insn); |
| 689 | const int ra = RA5 (insn); |
| 690 | const int rb = RB5 (insn); |
| 691 | fprintf_ftype func = info->fprintf_func; |
| 692 | void *stream = info->stream; |
| 693 | |
| 694 | if ((insn & 0x7f) == 0x4e) /* ffbi */ |
| 695 | { |
| 696 | func (stream, "ffbi\t%s, %s, #0x%x", |
| 697 | gpr_map[rt], gpr_map[ra], __GF (insn, 7, 8)); |
| 698 | return; |
| 699 | } |
| 700 | |
| 701 | switch (op) |
| 702 | { |
| 703 | case 0x0: /* max */ |
| 704 | case 0x1: /* min */ |
| 705 | case 0x2: /* ave */ |
| 706 | case 0xc: /* bse */ |
| 707 | case 0xd: /* bsp */ |
| 708 | case 0xe: /* ffb */ |
| 709 | case 0xf: /* ffmism */ |
| 710 | case 0x17: /* ffzmism */ |
| 711 | case 0x24: /* mul */ |
| 712 | func (stream, "%s\t%s, %s, %s", mnemonic_alu20[op], |
| 713 | gpr_map[rt], gpr_map[ra], gpr_map[rb]); |
| 714 | return; |
| 715 | |
| 716 | case 0x3: /* abs */ |
| 717 | case 0x6: /* clo */ |
| 718 | case 0x7: /* clz */ |
| 719 | func (stream, "%s\t%s, %s", mnemonic_alu20[op], gpr_map[rt], gpr_map[ra]); |
| 720 | return; |
| 721 | |
| 722 | case 0x4: /* clips */ |
| 723 | case 0x5: /* clip */ |
| 724 | case 0x8: /* bset */ |
| 725 | case 0x9: /* bclr */ |
| 726 | case 0xa: /* btgl */ |
| 727 | case 0xb: /* btst */ |
| 728 | func (stream, "%s\t%s, %s, #%d", mnemonic_alu20[op], |
| 729 | gpr_map[rt], gpr_map[ra], IMM1U (insn)); |
| 730 | return; |
| 731 | |
| 732 | case 0x20: /* mfusr */ |
| 733 | case 0x21: /* mtusr */ |
| 734 | func (stream, "%s\t%s, $%s", mnemonic_alu20[op], |
| 735 | gpr_map[rt], usr_map[__GF (insn, 10, 5)][__GF (insn, 15, 5)]); |
| 736 | return; |
| 737 | case 0x28: /* mults64 */ |
| 738 | case 0x29: /* mult64 */ |
| 739 | case 0x2a: /* madds64 */ |
| 740 | case 0x2b: /* madd64 */ |
| 741 | case 0x2c: /* msubs64 */ |
| 742 | case 0x2d: /* msub64 */ |
| 743 | case 0x2e: /* divs */ |
| 744 | case 0x2f: /* div */ |
| 745 | case 0x31: /* mult32 */ |
| 746 | case 0x33: /* madd32 */ |
| 747 | case 0x35: /* msub32 */ |
| 748 | func (stream, "%s\t$d%d, %s, %s", mnemonic_alu20[op], |
| 749 | rt >> 1, gpr_map[ra], gpr_map[rb]); |
| 750 | return; |
| 751 | |
| 752 | case 0x4f: /* flmism */ |
| 753 | case 0x68: /* mulsr64 */ |
| 754 | case 0x69: /* mulr64 */ |
| 755 | case 0x73: /* maddr32 */ |
| 756 | case 0x75: /* msubr32 */ |
| 757 | op = insn & 0x3f; |
| 758 | func (stream, "%s\t%s, %s, %s", mnemonic_alu21[op], |
| 759 | gpr_map[rt], gpr_map[ra], gpr_map[rb]); |
| 760 | return; |
| 761 | default: |
| 762 | func (stream, UNKNOWN_INSN_MSG); |
| 763 | return; |
| 764 | } |
| 765 | } |
| 766 | |
| 767 | static void |
| 768 | print_insn32_jreg (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info, uint32_t insn) |
| 769 | { |
| 770 | int op = insn & 0xff; |
| 771 | const int rt = RT5 (insn); |
| 772 | const int rb = RB5 (insn); |
| 773 | const char *dtit_on[] = { "", ".iton", ".dton", ".ton" }; |
| 774 | const char *dtit_off[] = { "", ".itoff", ".dtoff", ".toff" }; |
| 775 | const char *mnemonic_jreg[] = { "jr", "jral", "jrnez", "jralnez" }; |
| 776 | const char *mnemonic_ret[] = { "jr", "ret", NULL, "ifret" }; |
| 777 | const int dtit = __GF (insn, 8, 2); |
| 778 | fprintf_ftype func = info->fprintf_func; |
| 779 | void *stream = info->stream; |
| 780 | |
| 781 | switch (op) |
| 782 | { |
| 783 | case 0: /* jr */ |
| 784 | func (stream, "%s%s\t%s", mnemonic_ret[op >> 5], |
| 785 | dtit_on[dtit], gpr_map[rb]); |
| 786 | return; |
| 787 | |
| 788 | case 0x20: /* ret */ |
| 789 | func (stream, "%s%s\t%s", mnemonic_ret[op >> 5], |
| 790 | dtit_off[dtit], gpr_map[rb]); |
| 791 | return; |
| 792 | case 0x60: /* ifret */ |
| 793 | break; |
| 794 | case 1: /* jral */ |
| 795 | case 2: /* jrnez */ |
| 796 | case 3: /* jralnez */ |
| 797 | func (stream, "%s%s\t%s, %s", mnemonic_jreg[op], |
| 798 | dtit_on[dtit], gpr_map[rt], gpr_map[rb]); |
| 799 | return; |
| 800 | default: /* unknown */ |
| 801 | func (stream, UNKNOWN_INSN_MSG); |
| 802 | break; |
| 803 | } |
| 804 | } |
| 805 | |
| 806 | static void |
| 807 | print_insn32_misc (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info, |
| 808 | uint32_t insn) |
| 809 | { |
| 810 | int op = insn & 0x1f; |
| 811 | int rt = RT5 (insn); |
| 812 | unsigned int id; |
| 813 | fprintf_ftype func = info->fprintf_func; |
| 814 | void *stream = info->stream; |
| 815 | |
| 816 | static const char *keyword_standby[] = |
| 817 | { |
| 818 | "no_wake_grant", "wake_grant", "wait_done", |
| 819 | }; |
| 820 | static const char *keyword_tlbop[] = |
| 821 | { |
| 822 | "TRD", "TWR", "RWR", "RWLK", "UNLK", "PB", "INV", "FLUA" |
| 823 | }; |
| 824 | |
| 825 | switch (op) |
| 826 | { |
| 827 | case 0x0: /* standby */ |
| 828 | id = __GF (insn, 5, 20); |
| 829 | if (id < ARRAY_SIZE (keyword_standby)) |
| 830 | func (stream, "standby\t%s", keyword_standby[id]); |
| 831 | else |
| 832 | func (stream, "standby\t%d", id); |
| 833 | return; |
| 834 | case 0x1: /* cctl */ |
| 835 | func (stream, "cctl\t!FIXME"); |
| 836 | return; |
| 837 | case 0x8: /* dsb */ |
| 838 | case 0x9: /* isb */ |
| 839 | case 0xd: /* isync */ |
| 840 | case 0xc: /* msync */ |
| 841 | case 0x4: /* iret */ |
| 842 | func (stream, "%s", mnemonic_misc[op]); |
| 843 | return; |
| 844 | case 0x5: /* trap */ |
| 845 | case 0xa: /* break */ |
| 846 | case 0xb: /* syscall */ |
| 847 | id = __GF (insn, 5, 15); |
| 848 | func (stream, "%s\t%d", mnemonic_misc[op], id); |
| 849 | return; |
| 850 | case 0x2: /* mfsr */ |
| 851 | case 0x3: /* mtsr */ |
| 852 | /* FIXME: setend, setgie. */ |
| 853 | func (stream, "%s\t%s, $%s", mnemonic_misc[op], gpr_map[rt], |
| 854 | sr_map[__GF(insn, 17, 3)][__GF(insn, 13, 4)][__GF(insn, 10, 3)]); |
| 855 | return; |
| 856 | case 0x6: /* teqz */ |
| 857 | case 0x7: /* tnez */ |
| 858 | id = __GF (insn, 5, 15); |
| 859 | func (stream, "%s\t%s, %d", mnemonic_misc[op], gpr_map[rt], id); |
| 860 | return; |
| 861 | case 0xe: /* tlbop */ |
| 862 | id = __GF (insn, 5, 5); |
| 863 | if (id < ARRAY_SIZE (keyword_tlbop)) |
| 864 | func (stream, "tlbop\t%s", keyword_tlbop[id]); |
| 865 | else |
| 866 | func (stream, "tlbop\t%d", id); |
| 867 | return; |
| 868 | } |
| 869 | } |
| 870 | |
| 871 | static void |
| 872 | print_insn32_fpu (bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info, |
| 873 | uint32_t insn) |
| 874 | { |
| 875 | int op = insn & 0xf; |
| 876 | int mask_sub_op = (insn & 0x3c0) >> 6; |
| 877 | int mask_bi = (insn & 0x80) >> 7; |
| 878 | int mask_cfg = (insn & 0x7c00) >> 10; |
| 879 | int mask_f2op = (insn & 0x7c00) >> 10; |
| 880 | int dp = 0; |
| 881 | int dp_insn = 0; |
| 882 | char wd = 's'; |
| 883 | const int rt = RT5 (insn); |
| 884 | const int ra = RA5 (insn); |
| 885 | const int rb = RB5 (insn); |
| 886 | const int sv = __GF (insn, 8, 2); |
| 887 | fprintf_ftype func = info->fprintf_func; |
| 888 | void *stream = info->stream; |
| 889 | |
| 890 | switch (op) |
| 891 | { |
| 892 | case 0x0: /* fs1 */ |
| 893 | case 0x8: /* fd1 */ |
| 894 | dp = (op & 0x8) ? 1 : 0; |
| 895 | if (dp) |
| 896 | { |
| 897 | wd = 'd'; |
| 898 | dp_insn = 14; |
| 899 | } |
| 900 | else |
| 901 | { |
| 902 | wd = 's'; |
| 903 | dp_insn = 0; |
| 904 | } |
| 905 | switch (mask_sub_op) |
| 906 | { |
| 907 | case 0x0: |
| 908 | case 0x1: |
| 909 | case 0x2: |
| 910 | case 0x3: |
| 911 | case 0x4: |
| 912 | case 0x5: |
| 913 | case 0x8: |
| 914 | case 0x9: |
| 915 | case 0xc: |
| 916 | case 0xd: |
| 917 | func (stream, "%s\t$f%c%d, $f%c%d, $f%c%d", |
| 918 | mnemonic_alu[mask_sub_op + dp_insn], |
| 919 | wd, rt, wd, ra, wd, rb); |
| 920 | return; |
| 921 | case 0x6: |
| 922 | case 0x7: |
| 923 | func (stream, "%s\t$f%c%d, $f%c%d, $fs%d", |
| 924 | mnemonic_alu[mask_sub_op + dp_insn], |
| 925 | wd, rt, wd, ra, rb); |
| 926 | return; |
| 927 | case 0xf: |
| 928 | if (dp) |
| 929 | { |
| 930 | wd = 'd'; |
| 931 | dp_insn = 0x1d; |
| 932 | } |
| 933 | else |
| 934 | { |
| 935 | wd = 's'; |
| 936 | dp_insn = 0; |
| 937 | } |
| 938 | |
| 939 | switch (mask_f2op) |
| 940 | { |
| 941 | case 0x0: |
| 942 | if (dp) |
| 943 | func (stream, "%s\t$fs%d, $fd%d", |
| 944 | mnemonic_fpu_2op[mask_f2op + dp_insn], rt, ra); |
| 945 | else |
| 946 | func (stream, "%s\t$fd%d, $fs%d", |
| 947 | mnemonic_fpu_2op[mask_f2op + dp_insn], rt, ra); |
| 948 | return; |
| 949 | case 0x1: |
| 950 | case 0x5: |
| 951 | func (stream, "%s\t$f%c%d, $f%c%d", |
| 952 | mnemonic_fpu_2op[mask_f2op + dp_insn], wd, rt, wd, ra); |
| 953 | return; |
| 954 | case 0x8: |
| 955 | case 0xc: |
| 956 | func (stream, "%s\t$f%c%d, $fs%d", |
| 957 | mnemonic_fpu_2op[mask_f2op + dp_insn], wd, rt, ra); |
| 958 | return; |
| 959 | case 0x10: |
| 960 | case 0x14: |
| 961 | case 0x18: |
| 962 | case 0x1c: |
| 963 | func (stream, "%s\t$fs%d, $f%c%d", |
| 964 | mnemonic_fpu_2op[mask_f2op + dp_insn], rt, wd, ra); |
| 965 | return; |
| 966 | } |
| 967 | } |
| 968 | case 0x1: /* mfcp */ |
| 969 | switch (mask_sub_op) |
| 970 | { |
| 971 | case 0x0: |
| 972 | func (stream, "fmfsr\t%s, $fs%d", gpr_map[rt], ra); |
| 973 | return; |
| 974 | case 0x1: |
| 975 | func (stream, "fmfdr\t%s, $fd%d", gpr_map[rt], ra); |
| 976 | return; |
| 977 | case 0xc: |
| 978 | if (mask_cfg) |
| 979 | func (stream, "fmfcsr\t%s", gpr_map[rt]); |
| 980 | else |
| 981 | func (stream, "fmfcfg\t%s", gpr_map[rt]); |
| 982 | return; |
| 983 | } |
| 984 | case 0x2: /* fls */ |
| 985 | if (mask_bi) |
| 986 | func (stream, "fls.bi\t$fs%d, [%s], (%s << %d)", |
| 987 | rt, gpr_map[ra], gpr_map[rb], sv); |
| 988 | else |
| 989 | func (stream, "fls\t$fs%d, [%s + (%s << %d)]", |
| 990 | rt, gpr_map[ra], gpr_map[rb], sv); |
| 991 | return; |
| 992 | case 0x3: /* fld */ |
| 993 | if (mask_bi) |
| 994 | func (stream, "fld.bi\t$fd%d, [%s], (%s << %d)", |
| 995 | rt, gpr_map[ra], gpr_map[rb], sv); |
| 996 | else |
| 997 | func (stream, "fld\t$fd%d, [%s + (%s << %d)]", |
| 998 | rt, gpr_map[ra], gpr_map[rb], sv); |
| 999 | return; |
| 1000 | case 0x4: /* fs2 */ |
| 1001 | func (stream, "%s\t$fs%d, $fs%d, $fs%d", |
| 1002 | mnemonic_fs2_cmp[mask_sub_op], rt, ra, rb); |
| 1003 | return; |
| 1004 | case 0x9: /* mtcp */ |
| 1005 | switch (mask_sub_op) |
| 1006 | { |
| 1007 | case 0x0: |
| 1008 | func (stream, "fmtsr\t%s, $fs%d", gpr_map[rt], ra); |
| 1009 | return; |
| 1010 | case 0x1: |
| 1011 | func (stream, "fmtdr\t%s, $fd%d", gpr_map[rt], ra); |
| 1012 | return; |
| 1013 | case 0xc: |
| 1014 | func (stream, "fmtcsr\t%s", gpr_map[rt]); |
| 1015 | return; |
| 1016 | } |
| 1017 | case 0xa: /* fss */ |
| 1018 | if (mask_bi) |
| 1019 | func (stream, "fss.bi\t$fs%d, [%s], (%s << %d)", |
| 1020 | rt, gpr_map[ra], gpr_map[rb], sv); |
| 1021 | else |
| 1022 | func (stream, "fss\t$fs%d, [%s + (%s << %d)]", |
| 1023 | rt, gpr_map[ra], gpr_map[rb], sv); |
| 1024 | return; |
| 1025 | case 0xb: /* fsd */ |
| 1026 | if (mask_bi) |
| 1027 | func (stream, "fsd.bi\t$fd%d, [%s], (%s << %d)", |
| 1028 | rt, gpr_map[ra], gpr_map[rb], sv); |
| 1029 | else |
| 1030 | func (stream, "fsd\t$fd%d, [%s + (%s << %d)]", |
| 1031 | rt, gpr_map[ra], gpr_map[rb], sv); |
| 1032 | return; |
| 1033 | case 0xc: /* fd2 */ |
| 1034 | func (stream, "%s\t$fs%d, $fd%d, $fd%d", |
| 1035 | mnemonic_fd2_cmp[mask_sub_op], rt, ra, rb); |
| 1036 | return; |
| 1037 | } |
| 1038 | } |
| 1039 | |
| 1040 | static void |
| 1041 | print_insn32 (bfd_vma pc, disassemble_info *info, uint32_t insn) |
| 1042 | { |
| 1043 | int op = OP6 (insn); |
| 1044 | const int rt = RT5 (insn); |
| 1045 | const int ra = RA5 (insn); |
| 1046 | const int rb = RB5 (insn); |
| 1047 | const int imm15s = IMMS (insn, 15); |
| 1048 | const int imm15u = IMMU (insn, 15); |
| 1049 | uint32_t shift; |
| 1050 | fprintf_ftype func = info->fprintf_func; |
| 1051 | void *stream = info->stream; |
| 1052 | |
| 1053 | switch (op) |
| 1054 | { |
| 1055 | case 0x0: /* lbi */ |
| 1056 | case 0x1: /* lhi */ |
| 1057 | case 0x2: /* lwi */ |
| 1058 | case 0x3: /* ldi */ |
| 1059 | case 0x8: /* sbi */ |
| 1060 | case 0x9: /* shi */ |
| 1061 | case 0xa: /* swi */ |
| 1062 | case 0xb: /* sdi */ |
| 1063 | case 0x10: /* lbsi */ |
| 1064 | case 0x11: /* lhsi */ |
| 1065 | case 0x12: /* lwsi */ |
| 1066 | shift = op & 0x3; |
| 1067 | func (stream, "%s\t%s, [%s + #%d]", |
| 1068 | mnemonic_op6[op], gpr_map[rt], gpr_map[ra], imm15s << shift); |
| 1069 | return; |
| 1070 | case 0x4: /* lbi.bi */ |
| 1071 | case 0x5: /* lhi.bi */ |
| 1072 | case 0x6: /* lwi.bi */ |
| 1073 | case 0x7: /* ldi.bi */ |
| 1074 | case 0xc: /* sbi.bi */ |
| 1075 | case 0xd: /* shi.bi */ |
| 1076 | case 0xe: /* swi.bi */ |
| 1077 | case 0xf: /* sdi.bi */ |
| 1078 | case 0x14: /* lbsi.bi */ |
| 1079 | case 0x15: /* lhsi.bi */ |
| 1080 | case 0x16: /* lwsi.bi */ |
| 1081 | shift = op & 0x3; |
| 1082 | func (stream, "%s\t%s, [%s], #%d", |
| 1083 | mnemonic_op6[op], gpr_map[rt], gpr_map[ra], imm15s << shift); |
| 1084 | return; |
| 1085 | case 0x13: /* dprefi */ |
| 1086 | { |
| 1087 | const char *subtype = "???"; |
| 1088 | char wd = 'w'; |
| 1089 | |
| 1090 | shift = 2; |
| 1091 | |
| 1092 | /* d-bit */ |
| 1093 | if (rt & 0x10) |
| 1094 | { |
| 1095 | wd = 'd'; |
| 1096 | shift = 3; |
| 1097 | } |
| 1098 | |
| 1099 | if ((rt & 0xf) < ARRAY_SIZE (keyword_dpref)) |
| 1100 | subtype = keyword_dpref[rt & 0xf]; |
| 1101 | |
| 1102 | func (stream, "%s.%c\t%s, [%s + #%d]", |
| 1103 | mnemonic_op6[op], wd, subtype, gpr_map[ra], imm15s << shift); |
| 1104 | } |
| 1105 | return; |
| 1106 | case 0x17: /* LBGP */ |
| 1107 | func (stream, "%s\t%s, [+ %d]", |
| 1108 | ((insn & __BIT (19)) ? "lbsi.gp" : "lbi.gp"), |
| 1109 | gpr_map[rt], IMMS (insn, 19)); |
| 1110 | return; |
| 1111 | case 0x18: /* LWC */ |
| 1112 | case 0x19: /* SWC */ |
| 1113 | case 0x1a: /* LDC */ |
| 1114 | case 0x1b: /* SDC */ |
| 1115 | if (__GF (insn, 13, 2) == 0) |
| 1116 | { |
| 1117 | char ls = (op & 1) ? 's' : 'l'; |
| 1118 | char wd = (op & 2) ? 'd' : 's'; |
| 1119 | |
| 1120 | if (insn & __BIT (12)) |
| 1121 | { |
| 1122 | func (stream, "f%c%ci.bi\t$f%c%d, [%s], %d", ls, wd, |
| 1123 | wd, rt, gpr_map[ra], IMMS (insn, 12) << 2); |
| 1124 | } |
| 1125 | else |
| 1126 | { |
| 1127 | func (stream, "f%c%ci\t$f%c%d, [%s + %d]", ls, wd, |
| 1128 | wd, rt, gpr_map[ra], IMMS (insn, 12) << 2); |
| 1129 | } |
| 1130 | } |
| 1131 | else |
| 1132 | { |
| 1133 | char ls = (op & 1) ? 's' : 'l'; |
| 1134 | char wd = (op & 2) ? 'd' : 'w'; |
| 1135 | int cp = __GF (insn, 13, 2); |
| 1136 | |
| 1137 | if (insn & __BIT (12)) |
| 1138 | { |
| 1139 | func (stream, "cp%c%ci\tcp%d, $cpr%d, [%s], %d", ls, wd, |
| 1140 | cp, rt, gpr_map[ra], IMMS (insn, 12) << 2); |
| 1141 | } |
| 1142 | else |
| 1143 | { |
| 1144 | func (stream, "cp%c%ci\tcp%d, $cpr%d, [%s + %d]", ls, wd, |
| 1145 | cp, rt, gpr_map[ra], IMMS (insn, 12) << 2); |
| 1146 | } |
| 1147 | } |
| 1148 | return; |
| 1149 | case 0x1c: /* MEM */ |
| 1150 | print_insn32_mem (pc, info, insn); |
| 1151 | return; |
| 1152 | case 0x1d: /* LSMW */ |
| 1153 | { |
| 1154 | int enb4 = __GF (insn, 6, 4); |
| 1155 | char ls = (insn & __BIT (5)) ? 's' : 'l'; |
| 1156 | char ab = (insn & __BIT (4)) ? 'a' : 'b'; |
| 1157 | char *di = (insn & __BIT (3)) ? "d" : "i"; |
| 1158 | char *m = (insn & __BIT (2)) ? "m" : ""; |
| 1159 | static const char *s[] = {"", "a", "zb", "?"}; |
| 1160 | |
| 1161 | /* lsmwzb only always increase. */ |
| 1162 | if ((insn & 0x3) == 2) |
| 1163 | di = ""; |
| 1164 | |
| 1165 | func (stream, "%cmw%s.%c%s%s\t%s, [%s], %s, 0x%x", |
| 1166 | ls, s[insn & 0x3], ab, di, m, gpr_map[rt], |
| 1167 | gpr_map[ra], gpr_map[rb], enb4); |
| 1168 | } |
| 1169 | return; |
| 1170 | case 0x1e: /* HWGP */ |
| 1171 | op = __GF (insn, 17, 3); |
| 1172 | switch (op) |
| 1173 | { |
| 1174 | case 0: case 1: /* lhi.gp */ |
| 1175 | case 2: case 3: /* lhsi.gp */ |
| 1176 | case 4: case 5: /* shi.gp */ |
| 1177 | func (stream, "%s\t%s, [+ %d]", |
| 1178 | mnemonic_hwgp[op], gpr_map[rt], IMMS (insn, 18) << 1); |
| 1179 | return; |
| 1180 | case 6: /* lwi.gp */ |
| 1181 | case 7: /* swi.gp */ |
| 1182 | func (stream, "%s\t%s, [+ %d]", |
| 1183 | mnemonic_hwgp[op], gpr_map[rt], IMMS (insn, 17) << 2); |
| 1184 | return; |
| 1185 | } |
| 1186 | return; |
| 1187 | case 0x1f: /* SBGP */ |
| 1188 | if (insn & __BIT (19)) |
| 1189 | func (stream, "addi.gp\t%s, %d", |
| 1190 | gpr_map[rt], IMMS (insn, 19)); |
| 1191 | else |
| 1192 | func (stream, "sbi.gp\t%s, [+ %d]", |
| 1193 | gpr_map[rt], IMMS (insn, 19)); |
| 1194 | return; |
| 1195 | case 0x20: /* ALU_1 */ |
| 1196 | print_insn32_alu1 (pc, info, insn); |
| 1197 | return; |
| 1198 | case 0x21: /* ALU_2 */ |
| 1199 | print_insn32_alu2 (pc, info, insn); |
| 1200 | return; |
| 1201 | case 0x22: /* movi */ |
| 1202 | func (stream, "movi\t%s, %d", gpr_map[rt], IMMS (insn, 20)); |
| 1203 | return; |
| 1204 | case 0x23: /* sethi */ |
| 1205 | func (stream, "sethi\t%s, 0x%x", gpr_map[rt], IMMU (insn, 20)); |
| 1206 | return; |
| 1207 | case 0x24: /* ji, jal */ |
| 1208 | /* FIXME: Handle relocation. */ |
| 1209 | if (info->flags & INSN_HAS_RELOC) |
| 1210 | pc = 0; |
| 1211 | func (stream, "%s\t", ((insn & __BIT (24)) ? "jal" : "j")); |
| 1212 | info->print_address_func ((IMMS (insn, 24) << 1) + pc, info); |
| 1213 | return; |
| 1214 | case 0x25: /* jreg */ |
| 1215 | print_insn32_jreg (pc, info, insn); |
| 1216 | return; |
| 1217 | case 0x26: /* br1 */ |
| 1218 | func (stream, "%s\t%s, %s, ", ((insn & __BIT (14)) ? "bne" : "beq"), |
| 1219 | gpr_map[rt], gpr_map[ra]); |
| 1220 | info->print_address_func ((IMMS (insn, 14) << 1) + pc, info); |
| 1221 | return; |
| 1222 | case 0x27: /* br2 */ |
| 1223 | func (stream, "%s\t%s, ", mnemonic_br2[__GF (insn, 16, 4)], |
| 1224 | gpr_map[rt]); |
| 1225 | info->print_address_func ((IMMS (insn, 16) << 1) + pc, info); |
| 1226 | return; |
| 1227 | case 0x28: /* addi */ |
| 1228 | case 0x2e: /* slti */ |
| 1229 | case 0x2f: /* sltsi */ |
| 1230 | case 0x29: /* subri */ |
| 1231 | func (stream, "%s\t%s, %s, %d", |
| 1232 | mnemonic_op6[op], gpr_map[rt], gpr_map[ra], imm15s); |
| 1233 | return; |
| 1234 | case 0x2a: /* andi */ |
| 1235 | case 0x2b: /* xori */ |
| 1236 | case 0x2c: /* ori */ |
| 1237 | case 0x33: /* bitci */ |
| 1238 | func (stream, "%s\t%s, %s, %d", |
| 1239 | mnemonic_op6[op], gpr_map[rt], gpr_map[ra], imm15u); |
| 1240 | return; |
| 1241 | case 0x2d: /* br3, beqc, bnec */ |
| 1242 | func (stream, "%s\t%s, %d, ", ((insn & __BIT (19)) ? "bnec" : "beqc"), |
| 1243 | gpr_map[rt], __SEXT (__GF (insn, 8, 11), 11)); |
| 1244 | info->print_address_func ((IMMS (insn, 8) << 1) + pc, info); |
| 1245 | return; |
| 1246 | case 0x32: /* misc */ |
| 1247 | print_insn32_misc (pc, info, insn); |
| 1248 | return; |
| 1249 | case 0x35: /* FPU */ |
| 1250 | print_insn32_fpu (pc, info, insn); |
| 1251 | return; |
| 1252 | } |
| 1253 | } |
| 1254 | |
| 1255 | int |
| 1256 | print_insn_nds32 (bfd_vma pc, disassemble_info *info) |
| 1257 | { |
| 1258 | int status; |
| 1259 | bfd_byte buf[4]; |
| 1260 | uint32_t insn; |
| 1261 | |
| 1262 | status = info->read_memory_func (pc, (bfd_byte *) buf, 2, info); |
| 1263 | if (status) |
| 1264 | return -1; |
| 1265 | |
| 1266 | /* 16-bit instruction. */ |
| 1267 | if (buf[0] & 0x80) |
| 1268 | { |
| 1269 | insn = bfd_getb16 (buf); |
| 1270 | print_insn16 (pc, info, insn); |
| 1271 | return 2; |
| 1272 | } |
| 1273 | |
| 1274 | /* 32-bit instructions. */ |
| 1275 | status = info->read_memory_func (pc + 2, (bfd_byte *) buf + 2, 2, info); |
| 1276 | if (status) |
| 1277 | return -1; |
| 1278 | |
| 1279 | insn = bfd_getb32 (buf); |
| 1280 | print_insn32 (pc, info, insn); |
| 1281 | |
| 1282 | return 4; |
| 1283 | } |