disas.c (7157B)
1/* 2 * AVR disassembler 3 * 4 * Copyright (c) 2019-2020 Richard Henderson <rth@twiddle.net> 5 * Copyright (c) 2019-2020 Michael Rolnik <mrolnik@gmail.com> 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 2 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, see <http://www.gnu.org/licenses/>. 19 */ 20 21#include "qemu/osdep.h" 22#include "cpu.h" 23 24typedef struct { 25 disassemble_info *info; 26 uint16_t next_word; 27 bool next_word_used; 28} DisasContext; 29 30static int to_regs_16_31_by_one(DisasContext *ctx, int indx) 31{ 32 return 16 + (indx % 16); 33} 34 35static int to_regs_16_23_by_one(DisasContext *ctx, int indx) 36{ 37 return 16 + (indx % 8); 38} 39 40static int to_regs_24_30_by_two(DisasContext *ctx, int indx) 41{ 42 return 24 + (indx % 4) * 2; 43} 44 45static int to_regs_00_30_by_two(DisasContext *ctx, int indx) 46{ 47 return (indx % 16) * 2; 48} 49 50static uint16_t next_word(DisasContext *ctx) 51{ 52 ctx->next_word_used = true; 53 return ctx->next_word; 54} 55 56static int append_16(DisasContext *ctx, int x) 57{ 58 return x << 16 | next_word(ctx); 59} 60 61/* Include the auto-generated decoder. */ 62static bool decode_insn(DisasContext *ctx, uint16_t insn); 63#include "decode-insn.c.inc" 64 65#define output(mnemonic, format, ...) \ 66 (pctx->info->fprintf_func(pctx->info->stream, "%-9s " format, \ 67 mnemonic, ##__VA_ARGS__)) 68 69int avr_print_insn(bfd_vma addr, disassemble_info *info) 70{ 71 DisasContext ctx; 72 DisasContext *pctx = &ctx; 73 bfd_byte buffer[4]; 74 uint16_t insn; 75 int status; 76 77 ctx.info = info; 78 79 status = info->read_memory_func(addr, buffer, 4, info); 80 if (status != 0) { 81 info->memory_error_func(status, addr, info); 82 return -1; 83 } 84 insn = bfd_getl16(buffer); 85 ctx.next_word = bfd_getl16(buffer + 2); 86 ctx.next_word_used = false; 87 88 if (!decode_insn(&ctx, insn)) { 89 output(".db", "0x%02x, 0x%02x", buffer[0], buffer[1]); 90 } 91 92 return ctx.next_word_used ? 4 : 2; 93} 94 95 96#define INSN(opcode, format, ...) \ 97static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \ 98{ \ 99 output(#opcode, format, ##__VA_ARGS__); \ 100 return true; \ 101} 102 103#define INSN_MNEMONIC(opcode, mnemonic, format, ...) \ 104static bool trans_##opcode(DisasContext *pctx, arg_##opcode * a) \ 105{ \ 106 output(mnemonic, format, ##__VA_ARGS__); \ 107 return true; \ 108} 109 110/* 111 * C Z N V S H T I 112 * 0 1 2 3 4 5 6 7 113 */ 114static const char brbc[][5] = { 115 "BRCC", "BRNE", "BRPL", "BRVC", "BRGE", "BRHC", "BRTC", "BRID" 116}; 117 118static const char brbs[][5] = { 119 "BRCS", "BREQ", "BRMI", "BRVS", "BRLT", "BRHS", "BRTS", "BRIE" 120}; 121 122static const char bset[][4] = { 123 "SEC", "SEZ", "SEN", "SEZ", "SES", "SEH", "SET", "SEI" 124}; 125 126static const char bclr[][4] = { 127 "CLC", "CLZ", "CLN", "CLZ", "CLS", "CLH", "CLT", "CLI" 128}; 129 130/* 131 * Arithmetic Instructions 132 */ 133INSN(ADD, "r%d, r%d", a->rd, a->rr) 134INSN(ADC, "r%d, r%d", a->rd, a->rr) 135INSN(ADIW, "r%d:r%d, %d", a->rd + 1, a->rd, a->imm) 136INSN(SUB, "r%d, r%d", a->rd, a->rr) 137INSN(SUBI, "r%d, %d", a->rd, a->imm) 138INSN(SBC, "r%d, r%d", a->rd, a->rr) 139INSN(SBCI, "r%d, %d", a->rd, a->imm) 140INSN(SBIW, "r%d:r%d, %d", a->rd + 1, a->rd, a->imm) 141INSN(AND, "r%d, r%d", a->rd, a->rr) 142INSN(ANDI, "r%d, %d", a->rd, a->imm) 143INSN(OR, "r%d, r%d", a->rd, a->rr) 144INSN(ORI, "r%d, %d", a->rd, a->imm) 145INSN(EOR, "r%d, r%d", a->rd, a->rr) 146INSN(COM, "r%d", a->rd) 147INSN(NEG, "r%d", a->rd) 148INSN(INC, "r%d", a->rd) 149INSN(DEC, "r%d", a->rd) 150INSN(MUL, "r%d, r%d", a->rd, a->rr) 151INSN(MULS, "r%d, r%d", a->rd, a->rr) 152INSN(MULSU, "r%d, r%d", a->rd, a->rr) 153INSN(FMUL, "r%d, r%d", a->rd, a->rr) 154INSN(FMULS, "r%d, r%d", a->rd, a->rr) 155INSN(FMULSU, "r%d, r%d", a->rd, a->rr) 156INSN(DES, "%d", a->imm) 157 158/* 159 * Branch Instructions 160 */ 161INSN(RJMP, ".%+d", a->imm * 2) 162INSN(IJMP, "") 163INSN(EIJMP, "") 164INSN(JMP, "0x%x", a->imm * 2) 165INSN(RCALL, ".%+d", a->imm * 2) 166INSN(ICALL, "") 167INSN(EICALL, "") 168INSN(CALL, "0x%x", a->imm * 2) 169INSN(RET, "") 170INSN(RETI, "") 171INSN(CPSE, "r%d, r%d", a->rd, a->rr) 172INSN(CP, "r%d, r%d", a->rd, a->rr) 173INSN(CPC, "r%d, r%d", a->rd, a->rr) 174INSN(CPI, "r%d, %d", a->rd, a->imm) 175INSN(SBRC, "r%d, %d", a->rr, a->bit) 176INSN(SBRS, "r%d, %d", a->rr, a->bit) 177INSN(SBIC, "$%d, %d", a->reg, a->bit) 178INSN(SBIS, "$%d, %d", a->reg, a->bit) 179INSN_MNEMONIC(BRBS, brbs[a->bit], ".%+d", a->imm * 2) 180INSN_MNEMONIC(BRBC, brbc[a->bit], ".%+d", a->imm * 2) 181 182/* 183 * Data Transfer Instructions 184 */ 185INSN(MOV, "r%d, r%d", a->rd, a->rr) 186INSN(MOVW, "r%d:r%d, r%d:r%d", a->rd + 1, a->rd, a->rr + 1, a->rr) 187INSN(LDI, "r%d, %d", a->rd, a->imm) 188INSN(LDS, "r%d, %d", a->rd, a->imm) 189INSN(LDX1, "r%d, X", a->rd) 190INSN(LDX2, "r%d, X+", a->rd) 191INSN(LDX3, "r%d, -X", a->rd) 192INSN(LDY2, "r%d, Y+", a->rd) 193INSN(LDY3, "r%d, -Y", a->rd) 194INSN(LDZ2, "r%d, Z+", a->rd) 195INSN(LDZ3, "r%d, -Z", a->rd) 196INSN(LDDY, "r%d, Y+%d", a->rd, a->imm) 197INSN(LDDZ, "r%d, Z+%d", a->rd, a->imm) 198INSN(STS, "%d, r%d", a->imm, a->rd) 199INSN(STX1, "X, r%d", a->rr) 200INSN(STX2, "X+, r%d", a->rr) 201INSN(STX3, "-X, r%d", a->rr) 202INSN(STY2, "Y+, r%d", a->rd) 203INSN(STY3, "-Y, r%d", a->rd) 204INSN(STZ2, "Z+, r%d", a->rd) 205INSN(STZ3, "-Z, r%d", a->rd) 206INSN(STDY, "Y+%d, r%d", a->imm, a->rd) 207INSN(STDZ, "Z+%d, r%d", a->imm, a->rd) 208INSN(LPM1, "") 209INSN(LPM2, "r%d, Z", a->rd) 210INSN(LPMX, "r%d, Z+", a->rd) 211INSN(ELPM1, "") 212INSN(ELPM2, "r%d, Z", a->rd) 213INSN(ELPMX, "r%d, Z+", a->rd) 214INSN(SPM, "") 215INSN(SPMX, "Z+") 216INSN(IN, "r%d, $%d", a->rd, a->imm) 217INSN(OUT, "$%d, r%d", a->imm, a->rd) 218INSN(PUSH, "r%d", a->rd) 219INSN(POP, "r%d", a->rd) 220INSN(XCH, "Z, r%d", a->rd) 221INSN(LAC, "Z, r%d", a->rd) 222INSN(LAS, "Z, r%d", a->rd) 223INSN(LAT, "Z, r%d", a->rd) 224 225/* 226 * Bit and Bit-test Instructions 227 */ 228INSN(LSR, "r%d", a->rd) 229INSN(ROR, "r%d", a->rd) 230INSN(ASR, "r%d", a->rd) 231INSN(SWAP, "r%d", a->rd) 232INSN(SBI, "$%d, %d", a->reg, a->bit) 233INSN(CBI, "%d, %d", a->reg, a->bit) 234INSN(BST, "r%d, %d", a->rd, a->bit) 235INSN(BLD, "r%d, %d", a->rd, a->bit) 236INSN_MNEMONIC(BSET, bset[a->bit], "") 237INSN_MNEMONIC(BCLR, bclr[a->bit], "") 238 239/* 240 * MCU Control Instructions 241 */ 242INSN(BREAK, "") 243INSN(NOP, "") 244INSN(SLEEP, "") 245INSN(WDR, "")