Split out decoder files in preparation of ARM decoder

This commit is contained in:
Jeffrey Pfau 2013-11-02 00:34:49 -07:00
parent c8e1a9cd59
commit 9b2cd97505
3 changed files with 173 additions and 158 deletions

168
src/arm/decoder-inlines.h Normal file
View File

@ -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

View File

@ -1,6 +1,7 @@
#include "decoder.h" #include "decoder.h"
#include "arm.h" #include "arm.h"
#include "decoder-inlines.h"
#include "emitter-thumb.h" #include "emitter-thumb.h"
#include "isa-inlines.h" #include "isa-inlines.h"
@ -295,7 +296,7 @@ static const ThumbDecoder _thumbDecoderTable[0x400] = {
DECLARE_THUMB_EMITTER_BLOCK(_ThumbDecode) 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->opcode = opcode;
info->branches = 0; info->branches = 0;
info->traps = 0; info->traps = 0;
@ -306,160 +307,7 @@ void ARMDecodeThumb(uint16_t opcode, struct ThumbInstructionInfo* info) {
decoder(opcode, info); decoder(opcode, info);
} }
#define ADVANCE(AMOUNT) \ const char* thumbMnemonicStrings[] = {
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[] = {
"ill", "ill",
"adc", "adc",
"add", "add",
@ -502,8 +350,8 @@ static const char* _thumbMnemonicStrings[] = {
int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen) { int ARMDisassembleThumb(uint16_t opcode, uint32_t pc, char* buffer, int blen) {
struct ThumbInstructionInfo info; struct ThumbInstructionInfo info;
ARMDecodeThumb(opcode, &info); _decodeThumb(opcode, &info);
const char* mnemonic = _thumbMnemonicStrings[info.mnemonic]; const char* mnemonic = thumbMnemonicStrings[info.mnemonic];
int written; int written;
int total = 0; int total = 0;
const char* cond = ""; const char* cond = "";

View File

@ -9,7 +9,6 @@
// Bit 3: the destination of this operand is affected by this opcode // Bit 3: the destination of this operand is affected by this opcode
// Bit 4: this operand is shifted by a register // Bit 4: this operand is shifted by a register
// Bit 5: this operand is shifted by an immediate // Bit 5: this operand is shifted by an immediate
// Bit 6: this operand is added or subtracted to the base register
enum ARMOperandFormat { enum ARMOperandFormat {
ARM_OPERAND_NONE = 0x00000000, ARM_OPERAND_NONE = 0x00000000,
ARM_OPERAND_REGISTER_1 = 0x00000001, ARM_OPERAND_REGISTER_1 = 0x00000001,