mirror of https://github.com/mgba-emu/mgba.git
Split out decoder files in preparation of ARM decoder
This commit is contained in:
parent
c8e1a9cd59
commit
9b2cd97505
|
@ -0,0 +1,168 @@
|
|||
#ifndef ARM_DECODER_INLINES_H
|
||||
#define ARM_DECODER_INLINES_H
|
||||
|
||||
#include "decoder.h"
|
||||
|
||||
#include "arm.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define ADVANCE(AMOUNT) \
|
||||
if (AMOUNT > blen) { \
|
||||
buffer[blen - 1] = '\0'; \
|
||||
return total; \
|
||||
} \
|
||||
total += AMOUNT; \
|
||||
buffer += AMOUNT; \
|
||||
blen -= AMOUNT;
|
||||
|
||||
static int _decodeRegister(int reg, char* buffer, int blen);
|
||||
static int _decodeRegisterList(int list, char* buffer, int blen);
|
||||
static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen);
|
||||
static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen);
|
||||
|
||||
static const char* _armConditions[] = {
|
||||
"eq",
|
||||
"ne",
|
||||
"cs",
|
||||
"cc",
|
||||
"mi",
|
||||
"pl",
|
||||
"vs",
|
||||
"vc",
|
||||
"hi",
|
||||
"ls",
|
||||
"ge",
|
||||
"lt",
|
||||
"gt",
|
||||
"le",
|
||||
"al",
|
||||
"nv"
|
||||
};
|
||||
|
||||
static int _decodeRegister(int reg, char* buffer, int blen) {
|
||||
switch (reg) {
|
||||
case ARM_SP:
|
||||
strncpy(buffer, "sp", blen);
|
||||
return 2;
|
||||
case ARM_LR:
|
||||
strncpy(buffer, "lr", blen);
|
||||
return 2;
|
||||
case ARM_PC:
|
||||
strncpy(buffer, "pc", blen);
|
||||
return 2;
|
||||
default:
|
||||
return snprintf(buffer, blen, "r%i", reg);
|
||||
}
|
||||
}
|
||||
|
||||
static int _decodeRegisterList(int list, char* buffer, int blen) {
|
||||
if (blen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int total = 0;
|
||||
strncpy(buffer, "{", blen);
|
||||
ADVANCE(1);
|
||||
int i;
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
int written;
|
||||
for (i = 0; i <= ARM_PC; ++i) {
|
||||
if (list & 1) {
|
||||
if (start < 0) {
|
||||
start = i;
|
||||
end = i;
|
||||
} else if (end + 1 == i) {
|
||||
end = i;
|
||||
} else {
|
||||
if (end > start) {
|
||||
written = _decodeRegister(start, buffer, blen);
|
||||
ADVANCE(written);
|
||||
strncpy(buffer, "-", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
written = _decodeRegister(end, buffer, blen);
|
||||
ADVANCE(written);
|
||||
strncpy(buffer, ",", blen);
|
||||
ADVANCE(1);
|
||||
start = i;
|
||||
end = i;
|
||||
}
|
||||
}
|
||||
list >>= 1;
|
||||
}
|
||||
if (start >= 0) {
|
||||
if (end > start) {
|
||||
written = _decodeRegister(start, buffer, blen);
|
||||
ADVANCE(written);
|
||||
strncpy(buffer, "-", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
written = _decodeRegister(end, buffer, blen);
|
||||
ADVANCE(written);
|
||||
}
|
||||
strncpy(buffer, "}", blen);
|
||||
ADVANCE(1);
|
||||
return total;
|
||||
}
|
||||
|
||||
static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) {
|
||||
return snprintf(buffer, blen, "$%08X", address + pc);
|
||||
}
|
||||
|
||||
static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) {
|
||||
if (blen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int total = 0;
|
||||
strncpy(buffer, "[", blen);
|
||||
ADVANCE(1);
|
||||
int written;
|
||||
if (memory.format & ARM_MEMORY_REGISTER_BASE) {
|
||||
if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
|
||||
written = _decodePCRelative(memory.offset.immediate, pc, buffer, blen);
|
||||
ADVANCE(written);
|
||||
} else {
|
||||
written = _decodeRegister(memory.baseReg, buffer, blen);
|
||||
ADVANCE(written);
|
||||
if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) {
|
||||
strncpy(buffer, ", ", blen);
|
||||
ADVANCE(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (memory.format & ARM_MEMORY_POST_INCREMENT) {
|
||||
strncpy(buffer, "], ", blen);
|
||||
ADVANCE(3);
|
||||
}
|
||||
if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
|
||||
if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
|
||||
written = snprintf(buffer, blen, "#-%i", memory.offset.immediate);
|
||||
ADVANCE(written);
|
||||
} else {
|
||||
written = snprintf(buffer, blen, "#%i", memory.offset.immediate);
|
||||
ADVANCE(written);
|
||||
}
|
||||
} else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
|
||||
if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
|
||||
strncpy(buffer, "-", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
written = _decodeRegister(memory.offset.reg, buffer, blen);
|
||||
ADVANCE(written);
|
||||
}
|
||||
// TODO: shifted registers
|
||||
|
||||
if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) {
|
||||
strncpy(buffer, "]", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
if (memory.format & ARM_MEMORY_PRE_INCREMENT) {
|
||||
strncpy(buffer, "!", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,6 +1,7 @@
|
|||
#include "decoder.h"
|
||||
|
||||
#include "arm.h"
|
||||
#include "decoder-inlines.h"
|
||||
#include "emitter-thumb.h"
|
||||
#include "isa-inlines.h"
|
||||
|
||||
|
@ -295,7 +296,7 @@ static const ThumbDecoder _thumbDecoderTable[0x400] = {
|
|||
DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode)
|
||||
};
|
||||
|
||||
void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info) {
|
||||
void _decodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info) {
|
||||
info->opcode = opcode;
|
||||
info->branches = 0;
|
||||
info->traps = 0;
|
||||
|
@ -306,160 +307,7 @@ void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info) {
|
|||
decoder(opcode, info);
|
||||
}
|
||||
|
||||
#define ADVANCE(AMOUNT) \
|
||||
if (AMOUNT > blen) { \
|
||||
buffer[blen - 1] = '\0'; \
|
||||
return total; \
|
||||
} \
|
||||
total += AMOUNT; \
|
||||
buffer += AMOUNT; \
|
||||
blen -= AMOUNT;
|
||||
|
||||
static int _decodeRegister(int reg, char* buffer, int blen) {
|
||||
switch (reg) {
|
||||
case ARM_SP:
|
||||
strncpy(buffer, "sp", blen);
|
||||
return 2;
|
||||
case ARM_LR:
|
||||
strncpy(buffer, "lr", blen);
|
||||
return 2;
|
||||
case ARM_PC:
|
||||
strncpy(buffer, "pc", blen);
|
||||
return 2;
|
||||
default:
|
||||
return snprintf(buffer, blen, "r%i", reg);
|
||||
}
|
||||
}
|
||||
|
||||
static int _decodeRegisterList(int list, char* buffer, int blen) {
|
||||
if (blen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int total = 0;
|
||||
strncpy(buffer, "{", blen);
|
||||
ADVANCE(1);
|
||||
int i;
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
int written;
|
||||
printf("%x\n", list);
|
||||
for (i = 0; i <= ARM_PC; ++i) {
|
||||
if (list & 1) {
|
||||
if (start < 0) {
|
||||
start = i;
|
||||
end = i;
|
||||
} else if (end + 1 == i) {
|
||||
end = i;
|
||||
} else {
|
||||
if (end > start) {
|
||||
written = _decodeRegister(start, buffer, blen);
|
||||
ADVANCE(written);
|
||||
strncpy(buffer, "-", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
written = _decodeRegister(end, buffer, blen);
|
||||
ADVANCE(written);
|
||||
strncpy(buffer, ",", blen);
|
||||
ADVANCE(1);
|
||||
start = i;
|
||||
end = i;
|
||||
}
|
||||
}
|
||||
list >>= 1;
|
||||
}
|
||||
if (start >= 0) {
|
||||
if (end > start) {
|
||||
written = _decodeRegister(start, buffer, blen);
|
||||
ADVANCE(written);
|
||||
strncpy(buffer, "-", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
written = _decodeRegister(end, buffer, blen);
|
||||
ADVANCE(written);
|
||||
}
|
||||
strncpy(buffer, "}", blen);
|
||||
ADVANCE(1);
|
||||
return total;
|
||||
}
|
||||
|
||||
static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) {
|
||||
return snprintf(buffer, blen, "$%08X", address + pc);
|
||||
}
|
||||
|
||||
static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) {
|
||||
if (blen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int total = 0;
|
||||
strncpy(buffer, "[", blen);
|
||||
ADVANCE(1);
|
||||
int written;
|
||||
if (memory.format & ARM_MEMORY_REGISTER_BASE) {
|
||||
if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
|
||||
written = _decodePCRelative(memory.offset.immediate, pc, buffer, blen);
|
||||
ADVANCE(written);
|
||||
} else {
|
||||
written = _decodeRegister(memory.baseReg, buffer, blen);
|
||||
ADVANCE(written);
|
||||
if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) {
|
||||
strncpy(buffer, ", ", blen);
|
||||
ADVANCE(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (memory.format & ARM_MEMORY_POST_INCREMENT) {
|
||||
strncpy(buffer, "], ", blen);
|
||||
ADVANCE(3);
|
||||
}
|
||||
if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
|
||||
if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
|
||||
written = snprintf(buffer, blen, "#-%i", memory.offset.immediate);
|
||||
ADVANCE(written);
|
||||
} else {
|
||||
written = snprintf(buffer, blen, "#%i", memory.offset.immediate);
|
||||
ADVANCE(written);
|
||||
}
|
||||
} else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
|
||||
if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
|
||||
strncpy(buffer, "-", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
written = _decodeRegister(memory.offset.reg, buffer, blen);
|
||||
ADVANCE(written);
|
||||
}
|
||||
// TODO: shifted registers
|
||||
|
||||
if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) {
|
||||
strncpy(buffer, "]", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
if (memory.format & ARM_MEMORY_PRE_INCREMENT) {
|
||||
strncpy(buffer, "!", blen);
|
||||
ADVANCE(1);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
static const char* _armConditions[] = {
|
||||
"eq",
|
||||
"ne",
|
||||
"cs",
|
||||
"cc",
|
||||
"mi",
|
||||
"pl",
|
||||
"vs",
|
||||
"vc",
|
||||
"hi",
|
||||
"ls",
|
||||
"ge",
|
||||
"lt",
|
||||
"gt",
|
||||
"le",
|
||||
"al",
|
||||
"nv"
|
||||
};
|
||||
|
||||
static const char* _thumbMnemonicStrings[] = {
|
||||
const char* thumbMnemonicStrings[] = {
|
||||
"ill",
|
||||
"adc",
|
||||
"add",
|
||||
|
@ -502,8 +350,8 @@ static const char* _thumbMnemonicStrings[] = {
|
|||
|
||||
int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen) {
|
||||
struct ThumbInstructionInfo info;
|
||||
ARMDecodeThumb(opcode, &info);
|
||||
const char* mnemonic = _thumbMnemonicStrings[info.mnemonic];
|
||||
_decodeThumb(opcode, &info);
|
||||
const char* mnemonic = thumbMnemonicStrings[info.mnemonic];
|
||||
int written;
|
||||
int total = 0;
|
||||
const char* cond = "";
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
// Bit 3: the destination of this operand is affected by this opcode
|
||||
// Bit 4: this operand is shifted by a register
|
||||
// Bit 5: this operand is shifted by an immediate
|
||||
// Bit 6: this operand is added or subtracted to the base register
|
||||
enum ARMOperandFormat {
|
||||
ARM_OPERAND_NONE = 0x00000000,
|
||||
ARM_OPERAND_REGISTER_1 = 0x00000001,
|
||||
|
|
Loading…
Reference in New Issue