all repos — mgba @ 9b2cd97505f22e70fa89901f91defa3e844ce5f1

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