|  | /* | 
|  | * OpenRISC disassembler | 
|  | * | 
|  | * Copyright (c) 2018 Richard Henderson <rth@twiddle.net> | 
|  | * | 
|  | * This program is free software: you can redistribute it and/or modify | 
|  | * it under the terms of the GNU General Public License as published by | 
|  | * the Free Software Foundation, either version 2 of the License, or | 
|  | * (at your option) any later version. | 
|  | * | 
|  | * This program is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | * GNU General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License | 
|  | * along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
|  | */ | 
|  |  | 
|  | #include "qemu/osdep.h" | 
|  | #include "disas/dis-asm.h" | 
|  | #include "qemu/bitops.h" | 
|  | #include "cpu.h" | 
|  |  | 
|  | typedef disassemble_info DisasContext; | 
|  |  | 
|  | /* Include the auto-generated decoder.  */ | 
|  | #include "decode-insns.c.inc" | 
|  |  | 
|  | #define output(mnemonic, format, ...) \ | 
|  | (info->fprintf_func(info->stream, "%-9s " format, \ | 
|  | mnemonic, ##__VA_ARGS__)) | 
|  |  | 
|  | int print_insn_or1k(bfd_vma addr, disassemble_info *info) | 
|  | { | 
|  | bfd_byte buffer[4]; | 
|  | uint32_t insn; | 
|  | int status; | 
|  |  | 
|  | status = info->read_memory_func(addr, buffer, 4, info); | 
|  | if (status != 0) { | 
|  | info->memory_error_func(status, addr, info); | 
|  | return -1; | 
|  | } | 
|  | insn = bfd_getb32(buffer); | 
|  |  | 
|  | if (!decode(info, insn)) { | 
|  | output(".long", "%#08x", insn); | 
|  | } | 
|  | return 4; | 
|  | } | 
|  |  | 
|  | #define INSN(opcode, format, ...)                                       \ | 
|  | static bool trans_l_##opcode(disassemble_info *info, arg_l_##opcode *a) \ | 
|  | {                                                                       \ | 
|  | output("l." #opcode, format, ##__VA_ARGS__);                        \ | 
|  | return true;                                                        \ | 
|  | } | 
|  |  | 
|  | INSN(add,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(addc,   "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(sub,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(and,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(or,     "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(xor,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(sll,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(srl,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(sra,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(ror,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(exths,  "r%d, r%d", a->d, a->a) | 
|  | INSN(extbs,  "r%d, r%d", a->d, a->a) | 
|  | INSN(exthz,  "r%d, r%d", a->d, a->a) | 
|  | INSN(extbz,  "r%d, r%d", a->d, a->a) | 
|  | INSN(cmov,   "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(ff1,    "r%d, r%d", a->d, a->a) | 
|  | INSN(fl1,    "r%d, r%d", a->d, a->a) | 
|  | INSN(mul,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(mulu,   "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(div,    "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(divu,   "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | INSN(muld,   "r%d, r%d", a->a, a->b) | 
|  | INSN(muldu,  "r%d, r%d", a->a, a->b) | 
|  | INSN(j,      "%d", a->n) | 
|  | INSN(jal,    "%d", a->n) | 
|  | INSN(bf,     "%d", a->n) | 
|  | INSN(bnf,    "%d", a->n) | 
|  | INSN(jr,     "r%d", a->b) | 
|  | INSN(jalr,   "r%d", a->b) | 
|  | INSN(lwa,    "r%d, %d(r%d)", a->d, a->i, a->a) | 
|  | INSN(lwz,    "r%d, %d(r%d)", a->d, a->i, a->a) | 
|  | INSN(lws,    "r%d, %d(r%d)", a->d, a->i, a->a) | 
|  | INSN(lbz,    "r%d, %d(r%d)", a->d, a->i, a->a) | 
|  | INSN(lbs,    "r%d, %d(r%d)", a->d, a->i, a->a) | 
|  | INSN(lhz,    "r%d, %d(r%d)", a->d, a->i, a->a) | 
|  | INSN(lhs,    "r%d, %d(r%d)", a->d, a->i, a->a) | 
|  | INSN(swa,    "%d(r%d), r%d", a->i, a->a, a->b) | 
|  | INSN(sw,     "%d(r%d), r%d", a->i, a->a, a->b) | 
|  | INSN(sb,     "%d(r%d), r%d", a->i, a->a, a->b) | 
|  | INSN(sh,     "%d(r%d), r%d", a->i, a->a, a->b) | 
|  | INSN(nop,    "") | 
|  | INSN(adrp,   "r%d, %d", a->d, a->i) | 
|  | INSN(addi,   "r%d, r%d, %d", a->d, a->a, a->i) | 
|  | INSN(addic,  "r%d, r%d, %d", a->d, a->a, a->i) | 
|  | INSN(muli,   "r%d, r%d, %d", a->d, a->a, a->i) | 
|  | INSN(maci,   "r%d, %d", a->a, a->i) | 
|  | INSN(andi,   "r%d, r%d, %d", a->d, a->a, a->k) | 
|  | INSN(ori,    "r%d, r%d, %d", a->d, a->a, a->k) | 
|  | INSN(xori,   "r%d, r%d, %d", a->d, a->a, a->i) | 
|  | INSN(mfspr,  "r%d, r%d, %d", a->d, a->a, a->k) | 
|  | INSN(mtspr,  "r%d, r%d, %d", a->a, a->b, a->k) | 
|  | INSN(mac,    "r%d, r%d", a->a, a->b) | 
|  | INSN(msb,    "r%d, r%d", a->a, a->b) | 
|  | INSN(macu,   "r%d, r%d", a->a, a->b) | 
|  | INSN(msbu,   "r%d, r%d", a->a, a->b) | 
|  | INSN(slli,   "r%d, r%d, %d", a->d, a->a, a->l) | 
|  | INSN(srli,   "r%d, r%d, %d", a->d, a->a, a->l) | 
|  | INSN(srai,   "r%d, r%d, %d", a->d, a->a, a->l) | 
|  | INSN(rori,   "r%d, r%d, %d", a->d, a->a, a->l) | 
|  | INSN(movhi,  "r%d, %d", a->d, a->k) | 
|  | INSN(macrc,  "r%d", a->d) | 
|  | INSN(sfeq,   "r%d, r%d", a->a, a->b) | 
|  | INSN(sfne,   "r%d, r%d", a->a, a->b) | 
|  | INSN(sfgtu,  "r%d, r%d", a->a, a->b) | 
|  | INSN(sfgeu,  "r%d, r%d", a->a, a->b) | 
|  | INSN(sfltu,  "r%d, r%d", a->a, a->b) | 
|  | INSN(sfleu,  "r%d, r%d", a->a, a->b) | 
|  | INSN(sfgts,  "r%d, r%d", a->a, a->b) | 
|  | INSN(sfges,  "r%d, r%d", a->a, a->b) | 
|  | INSN(sflts,  "r%d, r%d", a->a, a->b) | 
|  | INSN(sfles,  "r%d, r%d", a->a, a->b) | 
|  | INSN(sfeqi,  "r%d, %d", a->a, a->i) | 
|  | INSN(sfnei,  "r%d, %d", a->a, a->i) | 
|  | INSN(sfgtui, "r%d, %d", a->a, a->i) | 
|  | INSN(sfgeui, "r%d, %d", a->a, a->i) | 
|  | INSN(sfltui, "r%d, %d", a->a, a->i) | 
|  | INSN(sfleui, "r%d, %d", a->a, a->i) | 
|  | INSN(sfgtsi, "r%d, %d", a->a, a->i) | 
|  | INSN(sfgesi, "r%d, %d", a->a, a->i) | 
|  | INSN(sfltsi, "r%d, %d", a->a, a->i) | 
|  | INSN(sflesi, "r%d, %d", a->a, a->i) | 
|  | INSN(sys,    "%d", a->k) | 
|  | INSN(trap,   "%d", a->k) | 
|  | INSN(msync,  "") | 
|  | INSN(psync,  "") | 
|  | INSN(csync,  "") | 
|  | INSN(rfe,    "") | 
|  |  | 
|  | #define FP_INSN(opcode, suffix, format, ...)                            \ | 
|  | static bool trans_lf_##opcode##_##suffix(disassemble_info *info,        \ | 
|  | arg_lf_##opcode##_##suffix *a) \ | 
|  | {                                                                       \ | 
|  | output("lf." #opcode "." #suffix, format, ##__VA_ARGS__);           \ | 
|  | return true;                                                        \ | 
|  | } | 
|  |  | 
|  | FP_INSN(add, s,  "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | FP_INSN(sub, s,  "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | FP_INSN(mul, s,  "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | FP_INSN(div, s,  "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | FP_INSN(rem, s,  "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | FP_INSN(itof, s, "r%d, r%d", a->d, a->a) | 
|  | FP_INSN(ftoi, s, "r%d, r%d", a->d, a->a) | 
|  | FP_INSN(madd, s, "r%d, r%d, r%d", a->d, a->a, a->b) | 
|  | FP_INSN(sfeq, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfne, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfgt, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfge, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sflt, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfle, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfun, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfueq, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfuge, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfugt, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfule, s, "r%d, r%d", a->a, a->b) | 
|  | FP_INSN(sfult, s, "r%d, r%d", a->a, a->b) | 
|  |  | 
|  | FP_INSN(add, d,  "r%d,r%d, r%d,r%d, r%d,r%d", | 
|  | a->d, a->d + a->dp + 1, | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sub, d,  "r%d,r%d, r%d,r%d, r%d,r%d", | 
|  | a->d, a->d + a->dp + 1, | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(mul, d,  "r%d,r%d, r%d,r%d, r%d,r%d", | 
|  | a->d, a->d + a->dp + 1, | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(div, d,  "r%d,r%d, r%d,r%d, r%d,r%d", | 
|  | a->d, a->d + a->dp + 1, | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(rem, d,  "r%d,r%d, r%d,r%d, r%d,r%d", | 
|  | a->d, a->d + a->dp + 1, | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(madd, d, "r%d,r%d, r%d,r%d, r%d,r%d", | 
|  | a->d, a->d + a->dp + 1, | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  |  | 
|  | FP_INSN(itof, d, "r%d,r%d, r%d,r%d", | 
|  | a->d, a->d + a->dp + 1, | 
|  | a->a, a->a + a->ap + 1) | 
|  | FP_INSN(ftoi, d, "r%d,r%d, r%d,r%d", | 
|  | a->d, a->d + a->dp + 1, | 
|  | a->a, a->a + a->ap + 1) | 
|  |  | 
|  | FP_INSN(stod, d, "r%d,r%d, r%d", | 
|  | a->d, a->d + a->dp + 1, a->a) | 
|  | FP_INSN(dtos, d, "r%d r%d,r%d", | 
|  | a->d, a->a, a->a + a->ap + 1) | 
|  |  | 
|  | FP_INSN(sfeq, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfne, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfgt, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfge, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sflt, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfle, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfun, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfueq, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfuge, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfugt, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfule, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) | 
|  | FP_INSN(sfult, d, "r%d,r%d, r%d,r%d", | 
|  | a->a, a->a + a->ap + 1, | 
|  | a->b, a->b + a->bp + 1) |