Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmeteor/source/disassembler/instruction.cpp
2 views
1
// Meteor - A Nintendo Gameboy Advance emulator
2
// Copyright (C) 2009-2011 Philippe Daouadi
3
//
4
// This program is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17
#include "ameteor/disassembler/instruction.hpp"
18
19
#include "ameteor/disassembler/argregister.hpp"
20
#include "ameteor/disassembler/argrelative.hpp"
21
#include "ameteor/disassembler/argimmediate.hpp"
22
#include "ameteor/disassembler/arguimmediate.hpp"
23
#include "ameteor/disassembler/argshift.hpp"
24
#include "ameteor/disassembler/argpsr.hpp"
25
#include "ameteor/disassembler/argmulregisters.hpp"
26
27
#include "../globals.hpp" // for ROR
28
29
namespace AMeteor
30
{
31
namespace Disassembler
32
{
33
void Instruction::Clear ()
34
{
35
m_operator.clear();
36
m_args.Clear();
37
}
38
39
#define Rn ((code >> 16) & 0xF)
40
#define Rd ((code >> 12) & 0xF)
41
#define Rs ((code >> 8) & 0xF)
42
#define Rm (code & 0xF)
43
44
void Instruction::ParseArm (uint32_t offset, uint32_t code)
45
{
46
Clear();
47
48
if ((code & 0x0FFFFFD0) == 0x12FFF10)
49
{
50
if (code & (0x1 << 5))
51
m_operator = "BLX";
52
else
53
m_operator = "BX";
54
m_args.AddArgument(ArgRegister(Rm));
55
ParseArmCondition(code);
56
}
57
else if (((code >> 25) & 0x7) == 0x5)
58
{
59
if (((code >> 28) & 0xF) == 0xF)
60
{
61
m_operator = "BLX";
62
m_args.AddArgument(ArgImmediate(offset + 8 +
63
(((code & (0x1 << 23)) ? 0xFF000000 | (code & 0x00FFFFFF)
64
: (code & 0x00FFFFFF)) << 2)
65
+ ((code & (0x1 << 24)) ? 2 : 0)));
66
}
67
else
68
{
69
if (code & (0x1 << 24))
70
m_operator = "BL";
71
else
72
m_operator = "B";
73
m_args.AddArgument(ArgImmediate(offset + 8 +
74
(((code & (0x1 << 23)) ? 0xFF000000 | (code & 0x00FFFFFF)
75
: (code & 0x00FFFFFF)) << 2)));
76
ParseArmCondition(code);
77
}
78
}
79
else if (((code >> 25) & 0x7) == 0x1)
80
{
81
ParseArmDataProc(code);
82
}
83
else if (((code >> 26) & 0x3) == 0x1)
84
{
85
if ((code & 0xF0100000) != 0xF0100000) // not PLD
86
m_args.AddArgument(ArgRegister(Rd));
87
if (code & (0x1 << 25)) // register offset
88
{
89
switch ((code >> 5) & 0x3)
90
{
91
case 0: // Logical Shift Left
92
m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm),
93
ArgImmediate((code >> 7) & 0x1F), SHIFT_LSL, false),
94
code & (0x1 << 24), code & (0x1 << 23),
95
code & (0x1 << 21)));
96
break;
97
case 1: // Logical Shift Right
98
if (code & (0x1F << 7))
99
m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm),
100
ArgImmediate((code >> 7) & 0x1F), SHIFT_LSR, false),
101
code & (0x1 << 24), code & (0x1 << 23),
102
code & (0x1 << 21)));
103
else
104
m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm),
105
ArgImmediate(32), SHIFT_LSR, false),
106
code & (0x1 << 24), code & (0x1 << 23),
107
code & (0x1 << 21)));
108
break;
109
case 2: // Arithmetic Shift Right
110
if (code & (0x1F << 7))
111
m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm),
112
ArgImmediate((code >> 7) & 0x1F), SHIFT_ASR, false),
113
code & (0x1 << 24), code & (0x1 << 23),
114
code & (0x1 << 21)));
115
else
116
m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm),
117
ArgImmediate(32), SHIFT_ASR, false),
118
code & (0x1 << 24), code & (0x1 << 23),
119
code & (0x1 << 21)));
120
break;
121
case 3: // ROtate Right
122
if (code & (0x1F << 7))
123
m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm),
124
ArgImmediate((code >> 7) & 0x1F), SHIFT_ROR, false),
125
code & (0x1 << 24), code & (0x1 << 23),
126
code & (0x1 << 21)));
127
else
128
m_args.AddArgument(ArgRelative(Rn, ArgShift(ArgRegister(Rm),
129
ArgImmediate(1), SHIFT_RRX, false),
130
code & (0x1 << 24), code & (0x1 << 23),
131
code & (0x1 << 21)));
132
break;
133
}
134
}
135
else // immediate offset
136
{
137
m_args.AddArgument(ArgRelative(Rn, ArgImmediate(code & 0xFFF),
138
code & (0x1 << 24), code & (0x1 << 23),
139
code & (0x1 << 21)));
140
}
141
142
if ((code & 0xF0100000) == 0xF0100000)
143
m_operator = "PLD";
144
else
145
{
146
if (code & (0x1 << 20))
147
m_operator = "LDR";
148
else
149
m_operator = "STR";
150
if (code & (0x1 << 22))
151
m_operator += "B";
152
153
ParseArmCondition(code);
154
}
155
}
156
else if (((code >> 25) & 0x7) == 0x4)
157
{
158
if (code & (0x1 << 20))
159
m_operator = "LDM";
160
else
161
m_operator = "STM";
162
163
if (code & (0x1 << 23))
164
m_operator += 'I';
165
else
166
m_operator += 'D';
167
168
if (code & (0x1 << 24))
169
m_operator += 'B';
170
else
171
m_operator += 'A';
172
173
m_args.AddArgument(ArgRegister(Rn, code & (0x1 << 21)));
174
175
ArgMulRegisters argRegs(code & (0x1 << 22));
176
for (register uint8_t n = 0; n < 16; ++n)
177
if (code & (0x1 << n))
178
argRegs.AddRegister(n);
179
m_args.AddArgument(argRegs);
180
181
ParseArmCondition(code);
182
}
183
else if (((code >> 25) & 0x7) == 0x0)
184
{
185
if ((code & 0x0FC000F0) == 0x00000090 ||
186
(code & 0x0F8000F0) == 0x00800090 ||
187
(code & 0x0F900090) == 0x01000080)
188
{
189
// NOTE : In this instruction Rn and Rd are inverted
190
static const char* Instructions[] = {"MUL", "MLA", "Reserved",
191
"Reserved", "UMULL", "UMLAL", "SMULL", "SMLAL", "SMLAxy",
192
"", // This is for SMLAWy and SMULWy
193
"SMLALxy", "SMULxy", "Reserved", "Reserved", "Reserved",
194
"Reserved"};
195
196
uint8_t opcode = (code >> 21) & 0xF;
197
if (opcode == 0x9)
198
m_operator = (code & (0x1 << 5)) ? "SMULWy" : "SMLAWy";
199
else
200
m_operator = Instructions[opcode];
201
if (!(opcode & (0x1 << 4)) && (code & (0x1 << 20)))
202
m_operator += 'S';
203
204
ParseArmCondition(code);
205
206
if ((opcode & 0xC) == 0x4 || opcode == 0xA)
207
m_args.AddArgument(ArgRegister(Rd));
208
m_args.AddArgument(ArgRegister(Rn));
209
m_args.AddArgument(ArgRegister(Rm));
210
m_args.AddArgument(ArgRegister(Rs));
211
if ((opcode & 0xE) == 0x8 || opcode == 0x1)
212
m_args.AddArgument(ArgRegister(Rd));
213
}
214
else if ((code & (0x1 << 7)) && (code & (0x1 << 4)))
215
{
216
if (((code >> 23) & 0x3) == 0x2 && ((code >> 20) & 0x3) == 0x0
217
&& ((code >> 4) & 0xFF) == 0x09)
218
{
219
if (code & (0x1 << 22)) // SWPB
220
m_operator = "SWPB";
221
else // SWP
222
m_operator = "SWP";
223
224
ParseArmCondition(code);
225
226
m_args.AddArgument(ArgRegister(Rd));
227
m_args.AddArgument(ArgRegister(Rm));
228
m_args.AddArgument(ArgRegister(Rn, false, false, true));
229
}
230
else
231
{
232
static const char* Instructions[] = {"Reserved", "STRH", "LDRD",
233
"STRD", "Reserved", "LDRH", "LDRSB", "LDRSH"};
234
235
m_operator = Instructions[((code >> 18) & 0x4)
236
| ((code >> 5) & 0x3)];
237
238
ParseArmCondition(code);
239
240
m_args.AddArgument(ArgRegister(Rd));
241
242
if (code & (0x1 << 22)) // immediate
243
{
244
m_args.AddArgument(ArgRelative(ArgRegister(Rn),
245
ArgImmediate(((code >> 4) & 0xF0) | (code & 0xF)),
246
code & (0x1 << 24), code & (0x1 << 23),
247
code & (0x1 << 21)));
248
}
249
else
250
{
251
m_args.AddArgument(ArgRelative(ArgRegister(Rn),
252
ArgRegister(code & 0xF),
253
code & (0x1 << 24), code & (0x1 << 23),
254
code & (0x1 << 21)));
255
}
256
}
257
}
258
else if (((code >> 23) & 0x3) == 0x2)
259
{
260
if (!((code >> 20) & 0x1))
261
{
262
if (code & (0x1 << 21))
263
{
264
m_operator = "MSR";
265
266
m_args.AddArgument(ArgPsr(code & (0x1 << 22),
267
(code >> 16) & 0xF));
268
269
if (code & (0x1 << 25)) // immediate
270
{
271
m_args.AddArgument(ArgUImmediate(
272
ROR(code & 0xFF, (code >> 8) & 0xF)));
273
}
274
else
275
{
276
m_args.AddArgument(ArgRegister(Rm));
277
}
278
}
279
else
280
{
281
m_operator = "MRS";
282
283
m_args.AddArgument(ArgRegister(Rd));
284
m_args.AddArgument(ArgPsr(code & (0x1 << 22)));
285
}
286
287
ParseArmCondition(code);
288
}
289
else
290
{
291
ParseArmDataProc(code);
292
}
293
}
294
else
295
{
296
ParseArmDataProc(code);
297
}
298
}
299
else
300
{
301
m_operator = "Unknown";
302
}
303
}
304
305
void Instruction::ParseArmDataProc (uint32_t code)
306
{
307
static const char* ops[] = {"AND", "EOR", "SUB", "RSB", "ADD", "ADC",
308
"SBC", "RSC", "TST", "TEQ", "CMP", "CMN", "ORR", "MOV", "BIC", "MVN"};
309
310
uint8_t opcode = (code >> 21) & 0xF;
311
312
if (opcode < 0x8 || opcode > 0xB)
313
m_args.AddArgument(ArgRegister(Rd));
314
if (opcode != 0xD && opcode != 0xF)
315
m_args.AddArgument(ArgRegister(Rn));
316
317
if (code & (0x1 << 25)) // Immediate operand 2
318
{
319
/*if (code & (0xF << 8))
320
m_args.AddArgument(ArgShift(ArgImmediate(code & 0xFF),
321
ArgImmediate(((code >> 8) & 0xF) << 1), SHIFT_ROR, false));
322
else
323
m_args.AddArgument(ArgImmediate(code & 0xFF));*/
324
m_args.AddArgument(ArgUImmediate(
325
ROR(code & 0xFF, (code >> 7) & 0x1E)));
326
}
327
else
328
{
329
switch ((code >> 5) & 0x3)
330
{
331
case 0: // Logical Shift Left
332
if (code & (0x1 << 4)) // Shift by register
333
{
334
m_args.AddArgument(ArgShift(ArgRegister(Rm),
335
ArgRegister(Rs), SHIFT_LSL, false));
336
}
337
else // Shift by immediate
338
{
339
if (code & (0x1F << 7))
340
m_args.AddArgument(ArgShift(ArgRegister(Rm),
341
ArgImmediate((code >> 7) & 0x1F), SHIFT_LSL, false));
342
else
343
m_args.AddArgument(ArgRegister(Rm));
344
}
345
break;
346
case 1: // Logical Shift Right
347
if (code & (0x1 << 4)) // Shift by register
348
{
349
m_args.AddArgument(ArgShift(ArgRegister(Rm),
350
ArgRegister(Rs), SHIFT_LSR, false));
351
}
352
else // Shift by immediate
353
{
354
if (code & (0x1F << 7))
355
m_args.AddArgument(ArgShift(ArgRegister(Rm),
356
ArgImmediate((code >> 7) & 0x1F), SHIFT_LSR, false));
357
else
358
m_args.AddArgument(ArgShift(ArgRegister(Rm),
359
ArgImmediate(32), SHIFT_LSR, false));
360
}
361
break;
362
case 2: // Arithmetic Shift Right
363
if (code & (0x1 << 4)) // Shift by register
364
{
365
m_args.AddArgument(ArgShift(ArgRegister(Rm),
366
ArgRegister(Rs), SHIFT_ASR, false));
367
}
368
else // Shift by immediate
369
{
370
if (code & (0x1F << 7))
371
m_args.AddArgument(ArgShift(ArgRegister(Rm),
372
ArgImmediate((code >> 7) & 0x1F), SHIFT_ASR, false));
373
else
374
m_args.AddArgument(ArgShift(ArgRegister(Rm),
375
ArgImmediate(32), SHIFT_ASR, false));
376
}
377
break;
378
case 3: // ROtate Right
379
if (code & (0x1 << 4)) // Shift by register
380
{
381
m_args.AddArgument(ArgShift(ArgRegister(Rm),
382
ArgRegister(Rs), SHIFT_ROR, false));
383
}
384
else // Shift by immediate
385
{
386
if (code & (0x1F << 7))
387
m_args.AddArgument(ArgShift(ArgRegister(Rm),
388
ArgImmediate((code >> 7) & 0x1F), SHIFT_ROR, false));
389
else
390
m_args.AddArgument(ArgShift(ArgRegister(Rm),
391
ArgImmediate(1), SHIFT_RRX, false));
392
}
393
break;
394
}
395
}
396
397
m_operator = ops[opcode];
398
399
if (code & (0x1 << 20) && (opcode < 0x8 || opcode > 0xB))
400
{
401
m_operator += "S";
402
}
403
ParseArmCondition(code);
404
}
405
406
void Instruction::ParseArmCondition (uint32_t code)
407
{
408
static const char* Conditions[] = {"EQ", "NE", "CS", "CC", "MI", "PL",
409
"VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"};
410
411
m_operator += Conditions[code >> 28];
412
}
413
414
#undef Rn
415
#undef Rd
416
#undef Rs
417
#undef Rm
418
419
#define Rb ((code >> 8) & 0x7)
420
#define Ro ((code >> 6) & 0x7)
421
#define Rs ((code >> 3) & 0x7)
422
#define Rd ((code ) & 0x7)
423
#define Imm (code & 0xFF)
424
#define Off ((code >> 6) & 0x1F)
425
426
#define HiRs ((code >> 3) & 0xF)
427
#define HiRd (((code & (0x1 << 7)) >> 4) | Rd)
428
429
void Instruction::ParseThumb (uint32_t offset, uint16_t code)
430
{
431
Clear ();
432
433
if ((code >> 12) == 0xB && ((code >> 9) & 0x3) == 0x2) // 1011x10
434
{
435
if (code & (0x1 << 11))
436
m_operator = "POP";
437
else
438
m_operator = "PUSH";
439
440
ArgMulRegisters argRegs(false);
441
for (register uint8_t n = 0; n < 8; ++n)
442
if (Imm & (0x1 << n))
443
argRegs.AddRegister(n);
444
445
if (code & (0x1 << 8))
446
{
447
if (code & (0x1 << 11))
448
argRegs.AddLastRegister(SPREG_PC);
449
else
450
argRegs.AddLastRegister(SPREG_LR);
451
}
452
m_args.AddArgument(argRegs);
453
}
454
else if ((code >> 11) == 0x9) // 01001
455
{
456
m_operator = "LDR";
457
458
m_args.AddArgument(ArgRegister(Rb));
459
m_args.AddArgument(ArgRelative(15, ArgImmediate(Imm << 2),
460
true, true, false));
461
}
462
else if ((code >> 12) == 0x8) // 1000
463
{
464
if (code & (0x1 << 11))
465
m_operator = "LDRH";
466
else
467
m_operator = "STRH";
468
469
m_args.AddArgument(ArgRegister(Rd));
470
m_args.AddArgument(ArgRelative(Rs, ArgImmediate(Off << 1),
471
true, true, false));
472
}
473
else if ((code >> 10) == 0x10) // 010000
474
{
475
static const char* Instructions[] = {"AND", "EOR", "LSL", "LSR", "ASR",
476
"ADC", "SBC", "ROR", "TST", "NEG", "CMP", "CMN", "ORR", "MUL", "BIC",
477
"MVN"};
478
479
m_operator = Instructions[(code >> 6) & 0xF];
480
481
m_args.AddArgument(ArgRegister(Rd));
482
m_args.AddArgument(ArgRegister(Rs));
483
}
484
else if ((code >> 10) == 0x11) // 010001
485
{
486
switch ((code >> 8) & 0x3)
487
{
488
case 0x0: // ADD
489
m_operator = "ADD";
490
m_args.AddArgument(ArgRegister(HiRd));
491
m_args.AddArgument(ArgRegister(HiRs));
492
break;
493
case 0x1: // CMP
494
m_operator = "CMP";
495
m_args.AddArgument(ArgRegister(HiRd));
496
m_args.AddArgument(ArgRegister(HiRs));
497
break;
498
case 0x2:
499
if (HiRd != 8 || HiRs != 8) // MOV
500
{
501
m_operator = "MOV";
502
m_args.AddArgument(ArgRegister(HiRd));
503
m_args.AddArgument(ArgRegister(HiRs));
504
}
505
else
506
m_operator = "NOP";
507
break;
508
case 0x3:
509
if (code & (0x1 << 7)) // BLX
510
{
511
m_operator = "BLX";
512
m_args.AddArgument(ArgRegister(HiRs));
513
}
514
else // BX
515
{
516
m_operator = "BX";
517
m_args.AddArgument(ArgRegister(HiRs));
518
}
519
break;
520
}
521
}
522
else if ((code >> 13) == 0x1) // 001
523
{
524
static const char* Instructions[] = {"MOV", "CMP", "ADD", "SUB"};
525
526
m_operator = Instructions[(code >> 11) & 0x3];
527
528
m_args.AddArgument(ArgRegister(Rb));
529
m_args.AddArgument(ArgImmediate(Imm));
530
}
531
else if ((code >> 13) == 0x3) // 011
532
{
533
static const char* Instructions[] = {"STR", "LDR", "STRB", "LDRB"};
534
535
m_operator = Instructions[(code >> 11) & 0x3];
536
537
m_args.AddArgument(ArgRegister(Rd));
538
if (code & (0x1 << 12))
539
m_args.AddArgument(ArgRelative(Rs, ArgImmediate(Off), true,
540
true, false));
541
else
542
m_args.AddArgument(ArgRelative(Rs, ArgImmediate(Off << 2), true,
543
true, false));
544
}
545
else if ((code >> 12) == 0xC) // 1100
546
{
547
if (code & (0x1 << 11))
548
m_operator = "LDMIA";
549
else
550
m_operator = "STMIA";
551
552
m_args.AddArgument(ArgRegister(Rb, true));
553
554
ArgMulRegisters argRegs(false);
555
for (register uint8_t n = 0; n < 8; ++n)
556
if (Imm & (0x1 << n))
557
argRegs.AddRegister(n);
558
m_args.AddArgument(argRegs);
559
}
560
else if ((code >> 13) == 0x0) // 000
561
{
562
if ((code >> 11) == 0x3) // 00011
563
{
564
if ((code >> 9) & 0x1)
565
m_operator = "SUB";
566
else
567
m_operator = "ADD";
568
569
m_args.AddArgument(ArgRegister(Rd));
570
m_args.AddArgument(ArgRegister(Rs));
571
572
if ((code >> 10) & 0x1) // imm
573
m_args.AddArgument(ArgImmediate(Ro));
574
else // reg
575
m_args.AddArgument(ArgRegister(Ro));
576
}
577
else // 000
578
{
579
static const char* Instructions[] = {"LSL", "LSR", "ASR", "Reserved"};
580
581
m_operator = Instructions[(code >> 11) & 0x3];
582
583
m_args.AddArgument(ArgRegister(Rd));
584
m_args.AddArgument(ArgRegister(Rs));
585
m_args.AddArgument(ArgImmediate(Off));
586
}
587
}
588
else if ((code >> 11) == 0x1E) // 11110
589
{
590
m_operator = "BL.W1";
591
592
m_args.AddArgument(ArgImmediate(offset + 4 + ((code & 0x7FF) << 12)));
593
}
594
else if ((code >> 13) == 0x7 && (code & (0x1 << 11))) // 111x1
595
{
596
m_operator = "BL.W2";
597
598
m_args.AddArgument(ArgImmediate((code & 0x7FF) << 1));
599
}
600
else if ((code >> 11) == 0x1C) // 11100
601
{
602
m_operator = "B";
603
604
if (code & (0x1 << 10))
605
m_args.AddArgument(ArgUImmediate(offset + 4 +
606
((int32_t)(((code & 0x3FF) << 1) | 0xFFFFF800))));
607
else
608
m_args.AddArgument(ArgUImmediate(offset + 4 + ((code & 0x3FF) << 1)));
609
}
610
else if ((code >> 12) == 0xD) // 1101
611
{
612
if (((code >> 8) & 0xF) == 0xF) // 11011111
613
{
614
m_operator = "SWI";
615
616
m_args.AddArgument(ArgImmediate(code & 0xFF));
617
}
618
else // 1101
619
{
620
static const char* Conditions[] = {"EQ", "NE", "CS", "CC", "MI", "PL",
621
"VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "__", "**"};
622
623
m_operator = "B";
624
m_operator += Conditions[(code >> 8) & 0xF];
625
626
m_args.AddArgument(ArgUImmediate(offset + 4 +
627
(((int32_t)(int8_t)Imm) << 1)));
628
}
629
}
630
else if ((code >> 8) == 0xB0) // 10110000
631
{
632
m_operator = "ADD";
633
634
m_args.AddArgument(ArgRegister(13, false, true));
635
if (code & (0x1 << 7)) // substract
636
m_args.AddArgument(ArgImmediate(-((code & 0x7F) << 2)));
637
else // add
638
m_args.AddArgument(ArgImmediate((code & 0x7F) << 2));
639
}
640
else if ((code >> 12) == 0x5) // 0101
641
{
642
if (code & (0x1 << 11))
643
m_operator = "LDR";
644
else
645
m_operator = "STR";
646
647
if (code & (0x1 << 10))
648
m_operator += 'B';
649
650
m_args.AddArgument(ArgRegister(Rd));
651
m_args.AddArgument(ArgRelative(Rs, ArgRegister(Ro), true, true, false));
652
}
653
else if ((code >> 12) == 0x9) // 1001
654
{
655
if (code & (0x1 << 11))
656
m_operator = "LDR";
657
else
658
m_operator = "STR";
659
660
m_args.AddArgument(ArgRegister(Rb));
661
m_args.AddArgument(ArgRelative(ArgRegister(13, false, true),
662
ArgImmediate(Imm << 2), true, true, false));
663
}
664
else if ((code >> 12) == 0xA) // 1010
665
{
666
m_operator = "ADD";
667
668
m_args.AddArgument(ArgRegister(Rb));
669
if (code & (0x1 << 11)) // with SP
670
m_args.AddArgument(ArgRegister(13, false, true));
671
else // with PC
672
m_args.AddArgument(ArgRegister(15, false, true));
673
m_args.AddArgument(ArgImmediate(Imm << 2));
674
}
675
else
676
{
677
m_operator = "Unknown";
678
}
679
}
680
681
#undef Rb
682
#undef Ro
683
#undef Rs
684
#undef Rd
685
#undef Imm
686
#undef Off
687
688
#undef HiRs
689
#undef HiRd
690
}
691
}
692
693