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