new file mode 100644
@@ -0,0 +1,724 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2016 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+
+#include <stdint.h>
+#include "translate.h"
+
+
+uint32_t avr_decode(uint32_t pc, uint32_t *length, uint32_t code, translate_function_t *translate)
+{
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x0000d000) {
+ case 0x00000000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00002c00) {
+ case 0x00000000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000300) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_NOP;
+ break;
+ }
+ case 0x00000100: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_MOVW;
+ break;
+ }
+ case 0x00000200: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_MULS;
+ break;
+ }
+ case 0x00000300: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000088) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_MULSU;
+ break;
+ }
+ case 0x00000008: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_FMUL;
+ break;
+ }
+ case 0x00000080: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_FMULS;
+ break;
+ }
+ case 0x00000088: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_FMULSU;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000400: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_CPC;
+ break;
+ }
+ case 0x00000800: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SBC;
+ break;
+ }
+ case 0x00000c00: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ADD;
+ break;
+ }
+ case 0x00002000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_AND;
+ break;
+ }
+ case 0x00002400: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_EOR;
+ break;
+ }
+ case 0x00002800: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_OR;
+ break;
+ }
+ case 0x00002c00: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_MOV;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00001000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00002000) {
+ case 0x00000000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000c00) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_CPSE;
+ break;
+ }
+ case 0x00000400: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_CP;
+ break;
+ }
+ case 0x00000800: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SUB;
+ break;
+ }
+ case 0x00000c00: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ADC;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00002000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_CPI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00004000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00002000) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SBCI;
+ break;
+ }
+ case 0x00002000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ORI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00005000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00002000) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SUBI;
+ break;
+ }
+ case 0x00002000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ANDI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00008000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000208) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDDZ;
+ break;
+ }
+ case 0x00000008: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDDY;
+ break;
+ }
+ case 0x00000200: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_STDZ;
+ break;
+ }
+ case 0x00000208: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_STDY;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00009000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00002800) {
+ case 0x00000000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000600) {
+ case 0x00000000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x0000000f) {
+ case 0x00000000: {
+ *length = 32;
+ *translate = (translate_function_t)&avr_translate_LDS;
+ break;
+ }
+ case 0x00000001: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDZ2;
+ break;
+ }
+ case 0x00000002: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDZ3;
+ break;
+ }
+ case 0x00000003: {
+ break;
+ }
+ case 0x00000004: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LPM2;
+ break;
+ }
+ case 0x00000005: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LPMX;
+ break;
+ }
+ case 0x00000006: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ELPM2;
+ break;
+ }
+ case 0x00000007: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ELPMX;
+ break;
+ }
+ case 0x00000008: {
+ break;
+ }
+ case 0x00000009: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDY2;
+ break;
+ }
+ case 0x0000000a: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDY3;
+ break;
+ }
+ case 0x0000000b: {
+ break;
+ }
+ case 0x0000000c: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDX1;
+ break;
+ }
+ case 0x0000000d: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDX2;
+ break;
+ }
+ case 0x0000000e: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDX3;
+ break;
+ }
+ case 0x0000000f: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_POP;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000200: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x0000000f) {
+ case 0x00000000: {
+ *length = 32;
+ *translate = (translate_function_t)&avr_translate_STS;
+ break;
+ }
+ case 0x00000001: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_STZ2;
+ break;
+ }
+ case 0x00000002: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_STZ3;
+ break;
+ }
+ case 0x00000003: {
+ break;
+ }
+ case 0x00000004: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_XCH;
+ break;
+ }
+ case 0x00000005: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LAS;
+ break;
+ }
+ case 0x00000006: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LAC;
+ break;
+ }
+ case 0x00000007: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LAT;
+ break;
+ }
+ case 0x00000008: {
+ break;
+ }
+ case 0x00000009: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_STY2;
+ break;
+ }
+ case 0x0000000a: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_STY3;
+ break;
+ }
+ case 0x0000000b: {
+ break;
+ }
+ case 0x0000000c: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_STX1;
+ break;
+ }
+ case 0x0000000d: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_STX2;
+ break;
+ }
+ case 0x0000000e: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_STX3;
+ break;
+ }
+ case 0x0000000f: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_PUSH;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000400: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x0000000e) {
+ case 0x00000000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000001) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_COM;
+ break;
+ }
+ case 0x00000001: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_NEG;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000002: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000001) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SWAP;
+ break;
+ }
+ case 0x00000001: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_INC;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000004: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ASR;
+ break;
+ }
+ case 0x00000006: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000001) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LSR;
+ break;
+ }
+ case 0x00000001: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ROR;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000008: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000181) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_BSET;
+ break;
+ }
+ case 0x00000001: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000010) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_IJMP;
+ break;
+ }
+ case 0x00000010: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_EIJMP;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000080: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_BCLR;
+ break;
+ }
+ case 0x00000081: {
+ break;
+ }
+ case 0x00000100: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000010) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_RET;
+ break;
+ }
+ case 0x00000010: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_RETI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000101: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000010) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ICALL;
+ break;
+ }
+ case 0x00000010: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_EICALL;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000180: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000070) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SLEEP;
+ break;
+ }
+ case 0x00000010: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_BREAK;
+ break;
+ }
+ case 0x00000020: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_WDR;
+ break;
+ }
+ case 0x00000030: {
+ break;
+ }
+ case 0x00000040: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LPM1;
+ break;
+ }
+ case 0x00000050: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ELPM1;
+ break;
+ }
+ case 0x00000060: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SPM;
+ break;
+ }
+ case 0x00000070: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SPMX;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000181: {
+ break;
+ }
+ }
+ break;
+ }
+ case 0x0000000a: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000001) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_DEC;
+ break;
+ }
+ case 0x00000001: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_DES;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x0000000c: {
+ *length = 32;
+ *translate = (translate_function_t)&avr_translate_JMP;
+ break;
+ }
+ case 0x0000000e: {
+ *length = 32;
+ *translate = (translate_function_t)&avr_translate_CALL;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000600: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000100) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_ADIW;
+ break;
+ }
+ case 0x00000100: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SBIW;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000800: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000400) {
+ case 0x00000000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000300) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_CBI;
+ break;
+ }
+ case 0x00000100: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SBIC;
+ break;
+ }
+ case 0x00000200: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SBI;
+ break;
+ }
+ case 0x00000300: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SBIS;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000400: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_MUL;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00002000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_IN;
+ break;
+ }
+ case 0x00002800: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_OUT;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x0000c000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00002000) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_RJMP;
+ break;
+ }
+ case 0x00002000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_LDI;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x0000d000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00002000) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_RCALL;
+ break;
+ }
+ case 0x00002000: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000c00) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_BRBS;
+ break;
+ }
+ case 0x00000400: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_BRBC;
+ break;
+ }
+ case 0x00000800: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000200) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_BLD;
+ break;
+ }
+ case 0x00000200: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_BST;
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00000c00: {
+ uint32_t opcode = extract32(code, 0, 16);
+ switch (opcode & 0x00000200) {
+ case 0x00000000: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SBRC;
+ break;
+ }
+ case 0x00000200: {
+ *length = 16;
+ *translate = (translate_function_t)&avr_translate_SBRS;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
Signed-off-by: Michael Rolnik <mrolnik@gmail.com> --- target-avr/decode.c | 724 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 724 insertions(+) create mode 100644 target-avr/decode.c