all repos — mgba @ ba4874f8b7f19b6c843a0d6ada709408452c8c0e

mGBA Game Boy Advance Emulator

src/arm/decoder-inlines.h (view raw)

  1#ifndef ARM_DECODER_INLINES_H
  2#define ARM_DECODER_INLINES_H
  3
  4#include "decoder.h"
  5
  6#include "arm.h"
  7
  8#include <stdio.h>
  9#include <string.h>
 10
 11#define ADVANCE(AMOUNT) \
 12	if (AMOUNT > blen) { \
 13		buffer[blen - 1] = '\0'; \
 14		return total; \
 15	} \
 16	total += AMOUNT; \
 17	buffer += AMOUNT; \
 18	blen -= AMOUNT;
 19
 20#define LOAD_CYCLES \
 21	info->iCycles = 1; \
 22	info->nDataCycles = 1;
 23
 24#define STORE_CYCLES \
 25	info->sInstructionCycles = 0; \
 26	info->nInstructionCycles = 1; \
 27	info->nDataCycles = 1;
 28
 29static int _decodeRegister(int reg, char* buffer, int blen);
 30static int _decodeRegisterList(int list, char* buffer, int blen);
 31static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen);
 32static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen);
 33
 34static const char* _armConditions[] = {
 35	"eq",
 36	"ne",
 37	"cs",
 38	"cc",
 39	"mi",
 40	"pl",
 41	"vs",
 42	"vc",
 43	"hi",
 44	"ls",
 45	"ge",
 46	"lt",
 47	"gt",
 48	"le",
 49	"al",
 50	"nv"
 51};
 52
 53static int _decodeRegister(int reg, char* buffer, int blen) {
 54	switch (reg) {
 55	case ARM_SP:
 56		strncpy(buffer, "sp", blen - 1);
 57		return 2;
 58	case ARM_LR:
 59		strncpy(buffer, "lr", blen - 1);
 60		return 2;
 61	case ARM_PC:
 62		strncpy(buffer, "pc", blen - 1);
 63		return 2;
 64	default:
 65		return snprintf(buffer, blen - 1, "r%i", reg);
 66	}
 67}
 68
 69static int _decodeRegisterList(int list, char* buffer, int blen) {
 70	if (blen <= 0) {
 71		return 0;
 72	}
 73	int total = 0;
 74	strncpy(buffer, "{", blen - 1);
 75	ADVANCE(1);
 76	int i;
 77	int start = -1;
 78	int end = -1;
 79	int written;
 80	for (i = 0; i <= ARM_PC; ++i) {
 81		if (list & 1) {
 82			if (start < 0) {
 83				start = i;
 84				end = i;
 85			} else if (end + 1 == i) {
 86				end = i;
 87			} else {
 88				if (end > start) {
 89					written = _decodeRegister(start, buffer, blen);
 90					ADVANCE(written);
 91					strncpy(buffer, "-", blen - 1);
 92					ADVANCE(1);
 93				}
 94				written = _decodeRegister(end, buffer, blen);
 95				ADVANCE(written);
 96				strncpy(buffer, ",", blen - 1);
 97				ADVANCE(1);
 98				start = i;
 99				end = i;
100			}
101		}
102		list >>= 1;
103	}
104	if (start >= 0) {
105		if (end > start) {
106			written = _decodeRegister(start, buffer, blen);
107			ADVANCE(written);
108			strncpy(buffer, "-", blen - 1);
109			ADVANCE(1);
110		}
111		written = _decodeRegister(end, buffer, blen);
112		ADVANCE(written);
113	}
114	strncpy(buffer, "}", blen - 1);
115	ADVANCE(1);
116	return total;
117}
118
119static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) {
120	return snprintf(buffer, blen - 1, "$%08X", address + pc);
121}
122
123static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) {
124	if (blen <= 1) {
125		return 0;
126	}
127	int total = 0;
128	strncpy(buffer, "[", blen - 1);
129	ADVANCE(1);
130	int written;
131	if (memory.format & ARM_MEMORY_REGISTER_BASE) {
132		if (memory.baseReg == ARM_PC && memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
133			written = _decodePCRelative(memory.offset.immediate, pc, buffer, blen);
134			ADVANCE(written);
135		} else {
136			written = _decodeRegister(memory.baseReg, buffer, blen);
137			ADVANCE(written);
138			if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) {
139				strncpy(buffer, ", ", blen - 1);
140				ADVANCE(2);
141			}
142		}
143	}
144	if (memory.format & ARM_MEMORY_POST_INCREMENT) {
145		strncpy(buffer, "], ", blen - 1);
146		ADVANCE(3);
147	}
148	if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) {
149		if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
150			written = snprintf(buffer, blen - 1, "#-%i", memory.offset.immediate);
151			ADVANCE(written);
152		} else {
153			written = snprintf(buffer, blen - 1, "#%i", memory.offset.immediate);
154			ADVANCE(written);
155		}
156	} else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) {
157		if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
158			strncpy(buffer, "-", blen - 1);
159			ADVANCE(1);
160		}
161		written = _decodeRegister(memory.offset.reg, buffer, blen);
162		ADVANCE(written);
163	}
164	// TODO: shifted registers
165
166	if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) {
167		strncpy(buffer, "]", blen - 1);
168		ADVANCE(1);
169	}
170	if (memory.format & ARM_MEMORY_PRE_INCREMENT) {
171		strncpy(buffer, "!", blen - 1);
172		ADVANCE(1);
173	}
174	return total;
175}
176
177#endif