llvm.org GIT mirror llvm / d28c094
tools: support decoding ARM EHABI opcodes in readobj Add support to llvm-readobj to decode the actual opcodes. The ARM EHABI opcodes are a variable length instruction set that describe the operations required for properly unwinding stack frames. The primary motivation for this change is to ease the creation of tests for the ARM EHABI object emission as well as the unwinding directive handling in the ARM IAS. Thanks to Logan Chien for an extra test case! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199708 91177308-0d34-0410-b5e6-96231b3b80d8 Saleem Abdulrasool 6 years ago
3 changed file(s) with 451 addition(s) and 45 deletion(s). Raw diff Collapse all Expand all
6161 @ CHECK: Model: Compact (Inline)
6262 @ CHECK: PersonalityIndex: 0
6363 @ CHECK: Opcodes [
64 @ CHECK: Opcode: 0xB1
65 @ CHECK: Opcode: 0x1
66 @ CHECK: Opcode: 0xB0
64 @ CHECK: 0xB1 0x01 ; pop {r0}
65 @ CHECK: 0xB0 ; finish
6766 @ CHECK: ]
6867 @ CHECK: }
6968 @ CHECK: Entry {
7069 @ CHECK: Model: Compact (Inline)
7170 @ CHECK: PersonalityIndex: 0
7271 @ CHECK: Opcodes [
73 @ CHECK: Opcode: 0xB0
74 @ CHECK: Opcode: 0xB0
75 @ CHECK: Opcode: 0xB0
72 @ CHECK: 0xB0 ; finish
73 @ CHECK: 0xB0 ; finish
74 @ CHECK: 0xB0 ; finish
7675 @ CHECK: ]
7776 @ CHECK: }
7877 @ CHECK: Entry {
8079 @ CHECK: Model: Compact
8180 @ CHECK: PersonalityIndex: 1
8281 @ CHECK: Opcodes [
83 @ CHECK: Opcode: 0x9B
84 @ CHECK: Opcode: 0x40
85 @ CHECK: Opcode: 0x84
86 @ CHECK: Opcode: 0x80
87 @ CHECK: Opcode: 0xB0
88 @ CHECK: Opcode: 0xB0
82 @ CHECK: 0x9B ; vsp = r11
83 @ CHECK: 0x40 ; vsp = vsp - 4
84 @ CHECK: 0x84 0x80 ; pop {fp, lr}
85 @ CHECK: 0xB0 ; finish
86 @ CHECK: 0xB0 ; finish
8987 @ CHECK: ]
9088 @ CHECK: }
9189 @ CHECK: Entry {
9290 @ CHECK: Model: Compact (Inline)
9391 @ CHECK: PersonalityIndex: 0
9492 @ CHECK: Opcodes [
95 @ CHECK: Opcode: 0x80
96 @ CHECK: Opcode: 0x0
97 @ CHECK: Opcode: 0xB0
93 @ CHECK: 0x80 0x00 ; refuse to unwind
94 @ CHECK: 0xB0 ; finish
9895 @ CHECK: ]
9996 @ CHECK: }
10097 @ CHECK: Entry {
10198 @ CHECK: Model: Compact (Inline)
10299 @ CHECK: PersonalityIndex: 0
103100 @ CHECK: Opcodes [
104 @ CHECK: Opcode: 0x9B
105 @ CHECK: Opcode: 0x4D
106 @ CHECK: Opcode: 0xC2
101 @ CHECK: 0x9B ; vsp = r11
102 @ CHECK: 0x4D ; vsp = vsp - 56
103 @ CHECK: 0xC2 ; pop {wR10, wR11, wR12}
107104 @ CHECK: ]
108105 @ CHECK: }
109106 @ CHECK: ]
None @ RUN: llvm-mc -triple armv7-eabi -filetype obj -o - %s | llvm-readobj -u - \
1 @ RUN: | FileCheck %s
0 @ RUN: llvm-mc -triple armv7-linux-eabi -filetype obj -o - %s \
1 @ RUN: | llvm-readobj -u | FileCheck %s
22
33 .syntax unified
44
8181 bx lr
8282 .fnend
8383
84 .section .raw
85
86 .type raw,%function
87 .thumb_func
88 raw:
89 .fnstart
90 .unwind_raw 12, 0x02
91 .unwind_raw -12, 0x42
92 .unwind_raw 0, 0x80, 0x00
93 .unwind_raw 4, 0x81, 0x00
94 .unwind_raw 4, 0x80, 0x01
95 .unwind_raw 8, 0x80, 0xc0
96 .unwind_raw 12, 0x84, 0xc0
97 .unwind_raw 0, 0x91
98 .unwind_raw 8, 0xa1
99 .unwind_raw 12, 0xa9
100 .unwind_raw 0, 0xb0
101 .unwind_raw 4, 0xb1, 0x01
102 .unwind_raw 0xa04, 0xb2, 0x80, 0x04
103 .unwind_raw 24, 0xb3, 0x12
104 .unwind_raw 24, 0xba
105 .unwind_raw 24, 0xc2
106 .unwind_raw 24, 0xc6, 0x02
107 .unwind_raw 8, 0xc7, 0x03
108 .unwind_raw 24, 0xc8, 0x02
109 .unwind_raw 24, 0xc9, 0x02
110 .unwind_raw 64, 0xd7
111 .fnend
112
113 .section .spare
114
115 .type spare,%function
116 spare:
117 .fnstart
118 .unwind_raw 4, 0x00
119 .unwind_raw -4, 0x40
120 .unwind_raw 0, 0x80, 0x00
121 .unwind_raw 4, 0x88, 0x00
122 .unwind_raw 0, 0x91
123 .unwind_raw 0, 0x9d
124 .unwind_raw 0, 0x9f
125 .unwind_raw 0, 0xa0
126 .unwind_raw 0, 0xa8
127 .unwind_raw 0, 0xb0
128 .unwind_raw 0, 0xb1, 0x00
129 .unwind_raw 4, 0xb1, 0x01
130 .unwind_raw 0, 0xb1, 0x10
131 .unwind_raw 0x204, 0xb2, 0x00
132 .unwind_raw 16, 0xb3, 0x00
133 .unwind_raw 0, 0xb4
134 .unwind_raw 16, 0xb8
135 .unwind_raw 4, 0xc0
136 .unwind_raw 4, 0xc6, 0x00
137 .unwind_raw 4, 0xc7, 0x00
138 .unwind_raw 4, 0xc7, 0x01
139 .unwind_raw 0, 0xc7, 0x10
140 .unwind_raw 16, 0xc8, 0x00
141 .unwind_raw 16, 0xc9, 0x00
142 .unwind_raw 0, 0xca
143 .unwind_raw 16, 0xd0
144 .unwind_raw 0, 0xd8
145 .fnend
146
84147 @ CHECK: UnwindInformation {
85148 @ CHECK: UnwindIndexTable {
86149 @ CHECK: SectionName: .ARM.exidx.personality
91154 @ CHECK: Model: Compact (Inline)
92155 @ CHECK: PersonalityIndex: 0
93156 @ CHECK: Opcodes [
94 @ CHECK: Opcode: 0xB0
95 @ CHECK: Opcode: 0xB0
96 @ CHECK: Opcode: 0xB0
157 @ CHECK: 0xB0 ; finish
158 @ CHECK: 0xB0 ; finish
159 @ CHECK: 0xB0 ; finish
97160 @ CHECK: ]
98161 @ CHECK: }
99162 @ CHECK: ]
107170 @ CHECK: Model: Compact (Inline)
108171 @ CHECK: PersonalityIndex: 0
109172 @ CHECK: Opcodes [
110 @ CHECK: Opcode: 0xB0
111 @ CHECK: Opcode: 0xB0
112 @ CHECK: Opcode: 0xB0
173 @ CHECK: 0xB0 ; finish
174 @ CHECK: 0xB0 ; finish
175 @ CHECK: 0xB0 ; finish
113176 @ CHECK: ]
114177 @ CHECK: }
115178 @ CHECK: ]
125188 @ CHECK: Model: Compact
126189 @ CHECK: PersonalityIndex: 1
127190 @ CHECK: Opcodes [
128 @ CHECK: Opcode: 0xB1
129 @ CHECK: Opcode: 0xF
130 @ CHECK: Opcode: 0xA7
131 @ CHECK: Opcode: 0x3F
132 @ CHECK: Opcode: 0xB0
133 @ CHECK: Opcode: 0xB0
191 @ CHECK: 0xB1 0x0F ; pop {r0, r1, r2, r3}
192 @ CHECK: 0xA7 ; pop {r4, r5, r6, r7, r8, r9, r10, fp}
193 @ CHECK: 0x3F ; vsp = vsp + 256
194 @ CHECK: 0xB0 ; finish
195 @ CHECK: 0xB0 ; finish
134196 @ CHECK: ]
135197 @ CHECK: }
136198 @ CHECK: ]
157219 @ CHECK: Model: Compact (Inline)
158220 @ CHECK: PersonalityIndex: 0
159221 @ CHECK: Opcodes [
160 @ CHECK: Opcode: 0xC9
161 @ CHECK: Opcode: 0x84
162 @ CHECK: Opcode: 0xB0
222 @ CHECK: 0xC9 0x84 ; pop {d8, d9, d10, d11, d12}
223 @ CHECK: 0xB0 ; finish
163224 @ CHECK: ]
164225 @ CHECK: }
165226 @ CHECK: ]
173234 @ CHECK: Model: Compact (Inline)
174235 @ CHECK: PersonalityIndex: 0
175236 @ CHECK: Opcodes [
176 @ CHECK: Opcode: 0xB0
177 @ CHECK: Opcode: 0xB0
178 @ CHECK: Opcode: 0xB0
237 @ CHECK: 0xB0 ; finish
238 @ CHECK: 0xB0 ; finish
239 @ CHECK: 0xB0 ; finish
179240 @ CHECK: ]
180241 @ CHECK: }
181242 @ CHECK: Entry {
191252 @ CHECK: Model: Compact (Inline)
192253 @ CHECK: PersonalityIndex: 0
193254 @ CHECK: Opcodes [
194 @ CHECK: Opcode: 0xB0
195 @ CHECK: Opcode: 0xB0
196 @ CHECK: Opcode: 0xB0
197 @ CHECK: ]
198 @ CHECK: }
255 @ CHECK: 0xB0 ; finish
256 @ CHECK: 0xB0 ; finish
257 @ CHECK: 0xB0 ; finish
258 @ CHECK: ]
259 @ CHECK: }
260 @ CHECK: ]
261 @ CHECK: }
262 @ CHECK: UnwindIndexTable {
263 @ CHECK: SectionName: .ARM.exidx.raw
264 @ CHECK: Entries [
265 @ CHECK: Opcodes [
266 @ CHECK: 0xD7 ; pop {d8, d9, d10, d11, d12, d13, d14, d15}
267 @ CHECK: 0xC9 0x02 ; pop {d0, d1, d2}
268 @ CHECK: 0xC8 0x02 ; pop {d16, d17, d18}
269 @ CHECK: 0xC7 0x03 ; pop {wCGR0, wCGR1}
270 @ CHECK: 0xC6 0x02 ; pop {wR0, wR1, wR2}
271 @ CHECK: 0xC2 ; pop {wR10, wR11, wR12}
272 @ CHECK: 0xBA ; pop {d8, d9, d10}
273 @ CHECK: 0xB3 0x12 ; pop {d1, d2, d3}
274 @ CHECK: 0xB2 0x80 0x04 ; vsp = vsp + 2564
275 @ CHECK: 0xB1 0x01 ; pop {r0}
276 @ CHECK: 0xB0 ; finish
277 @ CHECK: 0xA9 ; pop {r4, r5, lr}
278 @ CHECK: 0xA1 ; pop {r4, r5}
279 @ CHECK: 0x91 ; vsp = r1
280 @ CHECK: 0x84 0xC0 ; pop {r10, fp, lr}
281 @ CHECK: 0x80 0xC0 ; pop {r10, fp}
282 @ CHECK: 0x80 0x01 ; pop {r4}
283 @ CHECK: 0x81 0x00 ; pop {ip}
284 @ CHECK: 0x80 0x00 ; refuse to unwind
285 @ CHECK: 0x42 ; vsp = vsp - 12
286 @ CHECK: 0x02 ; vsp = vsp + 12
287 @ CHECK: ]
288 @ CHECK: ]
289 @ CHECK: }
290 @ CHECK: UnwindIndexTable {
291 @ CHECK: SectionName: .ARM.exidx.spare
292 @ CHECK: Entries [
293 @ CHECK: Opcodes [
294 @ CHECK: 0xD8 ; spare
295 @ CHECK: 0xD0 ; pop {d8}
296 @ CHECK: 0xCA ; spare
297 @ CHECK: 0xC9 0x00 ; pop {d0}
298 @ CHECK: 0xC8 0x00 ; pop {d16}
299 @ CHECK: 0xC7 0x10 ; spare
300 @ CHECK: 0xC7 0x01 ; pop {wCGR0}
301 @ CHECK: 0xC7 0x00 ; spare
302 @ CHECK: 0xC6 0x00 ; pop {wR0}
303 @ CHECK: 0xC0 ; pop {wR10}
304 @ CHECK: 0xB8 ; pop {d8}
305 @ CHECK: 0xB4 ; spare
306 @ CHECK: 0xB3 0x00 ; pop {d0}
307 @ CHECK: 0xB2 0x00 ; vsp = vsp + 516
308 @ CHECK: 0xB1 0x10 ; spare
309 @ CHECK: 0xB1 0x01 ; pop {r0}
310 @ CHECK: 0xB1 0x00 ; spare
311 @ CHECK: 0xB0 ; finish
312 @ CHECK: 0xA8 ; pop {r4, lr}
313 @ CHECK: 0xA0 ; pop {r4}
314 @ CHECK: 0x9F ; reserved (WiMMX MOVrr)
315 @ CHECK: 0x9D ; reserved (ARM MOVrr)
316 @ CHECK: 0x91 ; vsp = r1
317 @ CHECK: 0x88 0x00 ; pop {pc}
318 @ CHECK: 0x80 0x00 ; refuse to unwind
319 @ CHECK: 0x40 ; vsp = vsp - 4
320 @ CHECK: 0x00 ; vsp = vsp + 4
321 @ CHECK: ]
199322 @ CHECK: ]
200323 @ CHECK: }
201324 @ CHECK: }
1414 #include "llvm/Object/ELF.h"
1515 #include "llvm/Object/ELFTypes.h"
1616 #include "llvm/Support/ARMEHABI.h"
17 #include "llvm/Support/Debug.h"
1718 #include "llvm/Support/Endian.h"
19 #include "llvm/Support/Format.h"
1820 #include "llvm/Support/type_traits.h"
21
22 namespace {
23 template
24 size_t countof(const type_ (&)[N]) {
25 return N;
26 }
27 }
1928
2029 namespace llvm {
2130 namespace ARM {
2231 namespace EHABI {
32
33 class OpcodeDecoder {
34 StreamWriter &SW;
35 raw_ostream &OS;
36
37 struct RingEntry {
38 uint8_t Mask;
39 uint8_t Value;
40 void (OpcodeDecoder::*Routine)(const uint8_t *Opcodes, unsigned &OI);
41 };
42 static const RingEntry Ring[];
43
44 void Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI);
45 void Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI);
46 void Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes, unsigned &OI);
47 void Decode_10011101(const uint8_t *Opcodes, unsigned &OI);
48 void Decode_10011111(const uint8_t *Opcodes, unsigned &OI);
49 void Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI);
50 void Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI);
51 void Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI);
52 void Decode_10110000(const uint8_t *Opcodes, unsigned &OI);
53 void Decode_10110001_0000iiii(const uint8_t *Opcodes, unsigned &OI);
54 void Decode_10110010_uleb128(const uint8_t *Opcodes, unsigned &OI);
55 void Decode_10110011_sssscccc(const uint8_t *Opcodes, unsigned &OI);
56 void Decode_101101nn(const uint8_t *Opcodes, unsigned &OI);
57 void Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI);
58 void Decode_11000110_sssscccc(const uint8_t *Opcodes, unsigned &OI);
59 void Decode_11000111_0000iiii(const uint8_t *Opcodes, unsigned &OI);
60 void Decode_11001000_sssscccc(const uint8_t *Opcodes, unsigned &OI);
61 void Decode_11001001_sssscccc(const uint8_t *Opcodes, unsigned &OI);
62 void Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI);
63 void Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI);
64 void Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI);
65 void Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI);
66
67 void PrintGPR(uint16_t GPRMask);
68 void PrintRegisters(uint32_t Mask, StringRef Prefix);
69
70 public:
71 OpcodeDecoder(StreamWriter &SW) : SW(SW), OS(SW.getOStream()) {}
72 void Decode(const uint8_t *Opcodes, off_t Offset, size_t Length);
73 };
74
75 const OpcodeDecoder::RingEntry OpcodeDecoder::Ring[] = {
76 { 0xc0, 0x00, &OpcodeDecoder::Decode_00xxxxxx },
77 { 0xc0, 0x40, &OpcodeDecoder::Decode_01xxxxxx },
78 { 0xf0, 0x80, &OpcodeDecoder::Decode_1000iiii_iiiiiiii },
79 { 0xff, 0x9d, &OpcodeDecoder::Decode_10011101 },
80 { 0xff, 0x9f, &OpcodeDecoder::Decode_10011111 },
81 { 0xf0, 0x90, &OpcodeDecoder::Decode_1001nnnn },
82 { 0xf8, 0xa0, &OpcodeDecoder::Decode_10100nnn },
83 { 0xf8, 0xa8, &OpcodeDecoder::Decode_10101nnn },
84 { 0xff, 0xb0, &OpcodeDecoder::Decode_10110000 },
85 { 0xff, 0xb1, &OpcodeDecoder::Decode_10110001_0000iiii },
86 { 0xff, 0xb2, &OpcodeDecoder::Decode_10110010_uleb128 },
87 { 0xff, 0xb3, &OpcodeDecoder::Decode_10110011_sssscccc },
88 { 0xfc, 0xb4, &OpcodeDecoder::Decode_101101nn },
89 { 0xf8, 0xb8, &OpcodeDecoder::Decode_10111nnn },
90 { 0xff, 0xc6, &OpcodeDecoder::Decode_11000110_sssscccc },
91 { 0xff, 0xc7, &OpcodeDecoder::Decode_11000111_0000iiii },
92 { 0xff, 0xc8, &OpcodeDecoder::Decode_11001000_sssscccc },
93 { 0xff, 0xc9, &OpcodeDecoder::Decode_11001001_sssscccc },
94 { 0xc8, 0xc8, &OpcodeDecoder::Decode_11001yyy },
95 { 0xf8, 0xc0, &OpcodeDecoder::Decode_11000nnn },
96 { 0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn },
97 { 0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy },
98 };
99
100 void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes, unsigned &OI) {
101 uint8_t Opcode = Opcodes[OI++ ^ 3];
102 SW.startLine() << format("0x%02X ; vsp = vsp + %u\n", Opcode,
103 ((Opcode & 0x3f) << 2) + 4);
104 }
105 void OpcodeDecoder::Decode_01xxxxxx(const uint8_t *Opcodes, unsigned &OI) {
106 uint8_t Opcode = Opcodes[OI++ ^ 3];
107 SW.startLine() << format("0x%02X ; vsp = vsp - %u\n", Opcode,
108 ((Opcode & 0x3f) << 2) + 4);
109 }
110 void OpcodeDecoder::Decode_1000iiii_iiiiiiii(const uint8_t *Opcodes,
111 unsigned &OI) {
112 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
113 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
114
115 uint16_t GPRMask = (Opcode1 << 4) | ((Opcode0 & 0x0f) << 12);
116 SW.startLine()
117 << format("0x%02X 0x%02X ; %s",
118 Opcode0, Opcode1, GPRMask ? "pop " : "refuse to unwind");
119 if (GPRMask)
120 PrintGPR(GPRMask);
121 OS << '\n';
122 }
123 void OpcodeDecoder::Decode_10011101(const uint8_t *Opcodes, unsigned &OI) {
124 uint8_t Opcode = Opcodes[OI++ ^ 3];
125 SW.startLine() << format("0x%02X ; reserved (ARM MOVrr)\n", Opcode);
126 }
127 void OpcodeDecoder::Decode_10011111(const uint8_t *Opcodes, unsigned &OI) {
128 uint8_t Opcode = Opcodes[OI++ ^ 3];
129 SW.startLine() << format("0x%02X ; reserved (WiMMX MOVrr)\n", Opcode);
130 }
131 void OpcodeDecoder::Decode_1001nnnn(const uint8_t *Opcodes, unsigned &OI) {
132 uint8_t Opcode = Opcodes[OI++ ^ 3];
133 SW.startLine() << format("0x%02X ; vsp = r%u\n", Opcode, (Opcode & 0x0f));
134 }
135 void OpcodeDecoder::Decode_10100nnn(const uint8_t *Opcodes, unsigned &OI) {
136 uint8_t Opcode = Opcodes[OI++ ^ 3];
137 SW.startLine() << format("0x%02X ; pop ", Opcode);
138 PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4));
139 OS << '\n';
140 }
141 void OpcodeDecoder::Decode_10101nnn(const uint8_t *Opcodes, unsigned &OI) {
142 uint8_t Opcode = Opcodes[OI++ ^ 3];
143 SW.startLine() << format("0x%02X ; pop ", Opcode);
144 PrintGPR((((1 << ((Opcode & 0x7) + 1)) - 1) << 4) | (1 << 14));
145 OS << '\n';
146 }
147 void OpcodeDecoder::Decode_10110000(const uint8_t *Opcodes, unsigned &OI) {
148 uint8_t Opcode = Opcodes[OI++ ^ 3];
149 SW.startLine() << format("0x%02X ; finish\n", Opcode);
150 }
151 void OpcodeDecoder::Decode_10110001_0000iiii(const uint8_t *Opcodes,
152 unsigned &OI) {
153 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
154 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
155
156 SW.startLine()
157 << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
158 ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
159 if (((Opcode1 & 0xf0) == 0x00) && Opcode1)
160 PrintGPR((Opcode1 & 0x0f));
161 OS << '\n';
162 }
163 void OpcodeDecoder::Decode_10110010_uleb128(const uint8_t *Opcodes,
164 unsigned &OI) {
165 uint8_t Opcode = Opcodes[OI++ ^ 3];
166 SW.startLine() << format("0x%02X ", Opcode);
167
168 SmallVector ULEB;
169 do { ULEB.push_back(Opcodes[OI ^ 3]); } while (Opcodes[OI++ ^ 3] & 0x80);
170
171 for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
172 OS << format("0x%02X ", ULEB[BI]);
173
174 uint64_t Value = 0;
175 for (unsigned BI = 0, BE = ULEB.size(); BI != BE; ++BI)
176 Value = Value | ((ULEB[BI] & 0x7f) << (7 * BI));
177
178 OS << format("; vsp = vsp + %u\n", 0x204 + (Value << 2));
179 }
180 void OpcodeDecoder::Decode_10110011_sssscccc(const uint8_t *Opcodes,
181 unsigned &OI) {
182 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
183 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
184 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
185 uint8_t Start = ((Opcode1 & 0xf0) >> 4);
186 uint8_t Count = ((Opcode1 & 0x0f) >> 0);
187 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
188 OS << '\n';
189 }
190 void OpcodeDecoder::Decode_101101nn(const uint8_t *Opcodes, unsigned &OI) {
191 uint8_t Opcode = Opcodes[OI++ ^ 3];
192 SW.startLine() << format("0x%02X ; spare\n", Opcode);
193 }
194 void OpcodeDecoder::Decode_10111nnn(const uint8_t *Opcodes, unsigned &OI) {
195 uint8_t Opcode = Opcodes[OI++ ^ 3];
196 SW.startLine() << format("0x%02X ; pop ", Opcode);
197 PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
198 OS << '\n';
199 }
200 void OpcodeDecoder::Decode_11000110_sssscccc(const uint8_t *Opcodes,
201 unsigned &OI) {
202 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
203 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
204 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
205 uint8_t Start = ((Opcode1 & 0xf0) >> 4);
206 uint8_t Count = ((Opcode1 & 0x0f) >> 0);
207 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "wR");
208 OS << '\n';
209 }
210 void OpcodeDecoder::Decode_11000111_0000iiii(const uint8_t *Opcodes,
211 unsigned &OI) {
212 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
213 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
214 SW.startLine()
215 << format("0x%02X 0x%02X ; %s", Opcode0, Opcode1,
216 ((Opcode1 & 0xf0) || Opcode1 == 0x00) ? "spare" : "pop ");
217 if ((Opcode1 & 0xf0) == 0x00 && Opcode1)
218 PrintRegisters(Opcode1 & 0x0f, "wCGR");
219 OS << '\n';
220 }
221 void OpcodeDecoder::Decode_11001000_sssscccc(const uint8_t *Opcodes,
222 unsigned &OI) {
223 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
224 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
225 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
226 uint8_t Start = 16 + ((Opcode1 & 0xf0) >> 4);
227 uint8_t Count = ((Opcode1 & 0x0f) >> 0);
228 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
229 OS << '\n';
230 }
231 void OpcodeDecoder::Decode_11001001_sssscccc(const uint8_t *Opcodes,
232 unsigned &OI) {
233 uint8_t Opcode0 = Opcodes[OI++ ^ 3];
234 uint8_t Opcode1 = Opcodes[OI++ ^ 3];
235 SW.startLine() << format("0x%02X 0x%02X ; pop ", Opcode0, Opcode1);
236 uint8_t Start = ((Opcode1 & 0xf0) >> 4);
237 uint8_t Count = ((Opcode1 & 0x0f) >> 0);
238 PrintRegisters((((1 << (Count + 1)) - 1) << Start), "d");
239 OS << '\n';
240 }
241 void OpcodeDecoder::Decode_11001yyy(const uint8_t *Opcodes, unsigned &OI) {
242 uint8_t Opcode = Opcodes[OI++ ^ 3];
243 SW.startLine() << format("0x%02X ; spare\n", Opcode);
244 }
245 void OpcodeDecoder::Decode_11000nnn(const uint8_t *Opcodes, unsigned &OI) {
246 uint8_t Opcode = Opcodes[OI++ ^ 3];
247 SW.startLine() << format("0x%02X ; pop ", Opcode);
248 PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 10), "wR");
249 OS << '\n';
250 }
251 void OpcodeDecoder::Decode_11010nnn(const uint8_t *Opcodes, unsigned &OI) {
252 uint8_t Opcode = Opcodes[OI++ ^ 3];
253 SW.startLine() << format("0x%02X ; pop ", Opcode);
254 PrintRegisters((((1 << ((Opcode & 0x07) + 1)) - 1) << 8), "d");
255 OS << '\n';
256 }
257 void OpcodeDecoder::Decode_11xxxyyy(const uint8_t *Opcodes, unsigned &OI) {
258 uint8_t Opcode = Opcodes[OI++ ^ 3];
259 SW.startLine() << format("0x%02X ; spare\n", Opcode);
260 }
261
262 void OpcodeDecoder::PrintGPR(uint16_t GPRMask) {
263 static const char *GPRRegisterNames[16] = {
264 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
265 "fp", "ip", "sp", "lr", "pc"
266 };
267
268 OS << '{';
269 bool Comma = false;
270 for (unsigned RI = 0, RE = 17; RI < RE; ++RI) {
271 if (GPRMask & (1 << RI)) {
272 if (Comma)
273 OS << ", ";
274 OS << GPRRegisterNames[RI];
275 Comma = true;
276 }
277 }
278 OS << '}';
279 }
280
281 void OpcodeDecoder::PrintRegisters(uint32_t VFPMask, StringRef Prefix) {
282 OS << '{';
283 bool Comma = false;
284 for (unsigned RI = 0, RE = 32; RI < RE; ++RI) {
285 if (VFPMask & (1 << RI)) {
286 if (Comma)
287 OS << ", ";
288 OS << Prefix << RI;
289 Comma = true;
290 }
291 }
292 OS << '}';
293 }
294
295 void OpcodeDecoder::Decode(const uint8_t *Opcodes, off_t Offset, size_t Length) {
296 for (unsigned OCI = Offset; OCI < Length + Offset; ) {
297 bool Decoded = false;
298 for (unsigned REI = 0, REE = countof(Ring); REI != REE && !Decoded; ++REI) {
299 if ((Opcodes[OCI ^ 3] & Ring[REI].Mask) == Ring[REI].Value) {
300 (this->*Ring[REI].Routine)(Opcodes, OCI);
301 Decoded = true;
302 break;
303 }
304 }
305 if (!Decoded)
306 SW.startLine() << format("0x%02X ; reserved\n", Opcodes[OCI++ ^ 3]);
307 }
308 }
309
23310 template
24311 class PrinterContext {
25312 StreamWriter &SW;
170457 void PrinterContext::PrintOpcodes(const uint8_t *Entry,
171458 size_t Length, off_t Offset) const {
172459 ListScope OCC(SW, "Opcodes");
173 for (unsigned OCI = Offset; OCI < Length + Offset; OCI++)
174 SW.printHex("Opcode", Entry[OCI ^ 0x3]);
460 OpcodeDecoder(OCC.W).Decode(Entry, Offset, Length);
175461 }
176462
177463 template