2 * Copyright (C) 2014-2020 Paul Cercueil <paul@crapouillou.net>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
17 #if ENABLE_DISASSEMBLER
25 #include "disassembler.h"
26 #include "lightrec-private.h"
27 #include "memmanager.h"
29 static bool is_unconditional_jump(const struct opcode *op)
33 return op->r.op == OP_SPECIAL_JR || op->r.op == OP_SPECIAL_JALR;
39 return op->i.rs == op->i.rt;
41 return (op->r.rt == OP_REGIMM_BGEZ ||
42 op->r.rt == OP_REGIMM_BGEZAL) && op->i.rs == 0;
48 static bool is_syscall(const struct opcode *op)
50 return (op->i.op == OP_SPECIAL && (op->r.op == OP_SPECIAL_SYSCALL ||
51 op->r.op == OP_SPECIAL_BREAK)) ||
52 (op->i.op == OP_CP0 && (op->r.rs == OP_CP0_MTC0 ||
53 op->r.rs == OP_CP0_CTC0) &&
54 (op->r.rd == 12 || op->r.rd == 13));
57 void lightrec_free_opcode_list(struct lightrec_state *state, struct opcode *list)
63 lightrec_free(state, MEM_FOR_IR, sizeof(*list), list);
68 struct opcode * lightrec_disassemble(struct lightrec_state *state,
69 const u32 *src, unsigned int *len)
71 struct opcode *head = NULL;
72 bool stop_next = false;
73 struct opcode *curr, *last;
76 for (i = 0, last = NULL; ; i++, last = curr) {
77 curr = lightrec_calloc(state, MEM_FOR_IR, sizeof(*curr));
79 pr_err("Unable to allocate memory\n");
80 lightrec_free_opcode_list(state, head);
89 /* TODO: Take care of endianness */
90 curr->opcode = LE32TOH(*src++);
93 /* NOTE: The block disassembly ends after the opcode that
94 * follows an unconditional jump (delay slot) */
95 if (stop_next || is_syscall(curr))
97 else if (is_unconditional_jump(curr))
102 *len = (i + 1) * sizeof(u32);
107 unsigned int lightrec_cycles_of_opcode(union code code)
110 case OP_META_REG_UNLOAD:
118 #if ENABLE_DISASSEMBLER
119 void lightrec_print_disassembly(const struct block *block,
120 const u32 *code, unsigned int length)
122 struct disassemble_info info;
125 memset(&info, 0, sizeof(info));
126 init_disassemble_info(&info, stdout, (fprintf_ftype) fprintf);
128 info.buffer = (bfd_byte *) code;
129 info.buffer_vma = (bfd_vma)(uintptr_t) code;
130 info.buffer_length = length;
131 info.flavour = bfd_target_unknown_flavour;
132 info.arch = bfd_arch_mips;
133 info.mach = bfd_mach_mips3000;
134 disassemble_init_for_target(&info);
136 for (i = 0; i < length; i += 4) {
137 void print_insn_little_mips(bfd_vma, struct disassemble_info *);
139 print_insn_little_mips((bfd_vma)(uintptr_t) code++, &info);