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