Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmeteor/source/interpreter_arm.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
#ifndef __INTERPRETER_ARM_H__
18
#define __INTERPRETER_ARM_H__
19
20
/*
21
22
- From GBATEK -
23
24
ARM Binary Opcode Format
25
26
|..3 ..................2 ..................1 ..................0|
27
|1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0_9_8_7_6_5_4_3_2_1_0|
28
|_Cond__|0_0_0|___Op__|S|__Rn___|__Rd___|__Shift__|Typ|0|__Rm___| DataProc
29
|_Cond__|0_0_0|___Op__|S|__Rn___|__Rd___|__Rs___|0|Typ|1|__Rm___| DataProc
30
|_Cond__|0_0_1|___Op__|S|__Rn___|__Rd___|_Shift_|___Immediate___| DataProc
31
|_Cond__|0_0_1_1_0|P|1|0|_Field_|__Rd___|_Shift_|___Immediate___| PSR Imm
32
|_Cond__|0_0_0_1_0|P|L|0|_Field_|__Rd___|0_0_0_0|0_0_0_0|__Rm___| PSR Reg
33
|_Cond__|0_0_0_1_0_0_1_0_1_1_1_1_1_1_1_1_1_1_1_1|0_0|L|1|__Rn___| BX,BLX
34
|1_1_1_0|0_0_0_1_0_0_1_0|_____immediate_________|0_1_1_1|_immed_| BKPT ARM9
35
|_Cond__|0_0_0_1_0_1_1_0_1_1_1_1|__Rd___|1_1_1_1|0_0_0_1|__Rm___| CLZ ARM9
36
|_Cond__|0_0_0_1_0|Op_|0|__Rn___|__Rd___|0_0_0_0|0_1_0_1|__Rm___| QALU ARM9
37
|_Cond__|0_0_0_0_0_0|A|S|__Rd___|__Rn___|__Rs___|1_0_0_1|__Rm___| Multiply
38
|_Cond__|0_0_0_0_1|U|A|S|_RdHi__|_RdLo__|__Rs___|1_0_0_1|__Rm___| MulLong
39
|_Cond__|0_0_0_1_0|Op_|0|Rd/RdHi|Rn/RdLo|__Rs___|1|y|x|0|__Rm___| MulHalf
40
|_Cond__|0_0_0_1_0|B|0_0|__Rn___|__Rd___|0_0_0_0|1_0_0_1|__Rm___| TransSwp12
41
|_Cond__|0_0_0|P|U|0|W|L|__Rn___|__Rd___|0_0_0_0|1|S|H|1|__Rm___| TransReg10
42
|_Cond__|0_0_0|P|U|1|W|L|__Rn___|__Rd___|OffsetH|1|S|H|1|OffsetL| TransImm10
43
|_Cond__|0_1_0|P|U|B|W|L|__Rn___|__Rd___|_________Offset________| TransImm9
44
|_Cond__|0_1_1|P|U|B|W|L|__Rn___|__Rd___|__Shift__|Typ|0|__Rm___| TransReg9
45
|_Cond__|0_1_1|________________xxx____________________|1|__xxx__| Undefined
46
|_Cond__|1_0_0|P|U|S|W|L|__Rn___|__________Register_List________| BlockTrans
47
|_Cond__|1_0_1|L|___________________Offset______________________| B,BL,BLX
48
|_Cond__|1_1_0|P|U|N|W|L|__Rn___|__CRd__|__CP#__|____Offset_____| CoDataTrans
49
|_Cond__|1_1_0_0_0_1_0|L|__Rn___|__Rd___|__CP#__|_CPopc_|__CRm__| CoRR ARM9
50
|_Cond__|1_1_1_0|_CPopc_|__CRn__|__CRd__|__CP#__|_CP__|0|__CRm__| CoDataOp
51
|_Cond__|1_1_1_0|CPopc|L|__CRn__|__Rd___|__CP#__|_CP__|1|__CRm__| CoRegTrans
52
|_Cond__|1_1_1_1|_____________Ignored_by_Processor______________| SWI
53
54
*/
55
56
#include "ameteor/interpreter.hpp"
57
#include "globals.hpp"
58
#include "cpu_globals.hpp"
59
#include "ameteor.hpp"
60
61
#include "debug.hpp"
62
63
#define Rn ((code >> 16) & 0xF)
64
#define Rd ((code >> 12) & 0xF)
65
#define Rs ((code >> 8) & 0xF)
66
#define Rm (code & 0xF)
67
68
// Load/Store immediate offset
69
#define LSOff (code & 0xFFF)
70
71
#ifdef METDEBUG
72
# define NOT_PC(reg) \
73
if (reg == 15) \
74
met_abort("Register is PC")
75
# define NOT_PC_ALL() \
76
NOT_PC(Rn); \
77
NOT_PC(Rd); \
78
NOT_PC(Rs); \
79
NOT_PC(Rm)
80
# define NOT_SAME2(reg1, reg2) \
81
if (reg1 == reg2) \
82
met_abort("Two same registers")
83
# define NOT_SAME3(reg1, reg2, reg3) \
84
NOT_SAME2(reg1, reg2); \
85
NOT_SAME2(reg2, reg3); \
86
NOT_SAME2(reg1, reg3)
87
#else
88
# define NOT_PC(reg) {}
89
# define NOT_PC_ALL() {}
90
# define NOT_SAME2(reg1, reg2) {}
91
# define NOT_SAME3(reg1, reg2, reg3) {}
92
#endif
93
94
#define ARM(name) \
95
inline void Interpreter::a##name ()
96
#define NIARM(name) \
97
void Interpreter::a##name ()
98
99
namespace AMeteor
100
{
101
// Branch and Exchange
102
ARM(BXBLX)
103
{
104
if ((code & 0x0FFFFF00) != 0x012FFF00)
105
met_abort("Bits 8-27 must be 0001 00101111 11111111 for BX/BLX instructions");
106
107
if (Rm == 15)
108
met_abort("Branching on PC is undefined");
109
110
if (code & (0x1 << 5)) // BLX
111
{
112
R(14) = R(15);
113
met_abort("BLX not completly implemented");
114
}
115
// else BX
116
117
if (R(Rm) & 0x1)
118
{
119
FLAG_T = 1;
120
R(15) = R(Rm) + 1;
121
CYCLES32NSeq(R(15), 3);
122
}
123
else
124
{
125
if (R(Rm) & 0x3)
126
met_abort("BX with ARM on non 32 bit aligned address");
127
R(15) = R(Rm)+4;
128
CYCLES32NSeq(R(15), 3);
129
}
130
}
131
132
// Branch and Branch with Link
133
ARM(BBL)
134
{
135
if (((code >> 25) & 0x7) != 0x5)
136
met_abort("Bits 25-27 must be 101 for B/BL/BLX instructions");
137
138
if (((code >> 28) & 0xF) == 0xF)
139
met_abort("BLX not implemented");
140
141
int32_t off = code & 0x00FFFFFF;
142
// Extend the sign bit
143
off <<= 8;
144
off >>= 8;
145
// off is in steps of 4
146
off *= 4;
147
148
if (code & (0x1 << 24)) // BL
149
{
150
// R(15) points two instructions later, R(14) should point to next
151
// instruction
152
// LR = PC + 4 and R15 = PC + 8
153
R(14) = R(15) - 4 ;
154
}
155
// else B
156
R(15) += off + 4;
157
CYCLES32NSeq(R(15), 3);
158
}
159
160
// Data Processing
161
NIARM(_DataProcShiftImm)
162
{
163
if ((code >> 26) & 0x3)
164
met_abort("Bits 26-27 must be 00 for DataProc instructions");
165
166
uint8_t shift;
167
uint32_t op2 = 0; // to avoid a warning
168
bool shiftcarry = FLAG_C;
169
uint8_t rd = Rd;
170
171
uint8_t rm = Rm;
172
if (rm == 15 && !(code & (0x1 << 20)) && (code & (0x1 << 4)))
173
met_abort("Rm = 15, not implemented");
174
175
shift = (code >> 7) & 0x1F;
176
switch ((code >> 5) & 0x3)
177
{
178
case 0: // Logical Shift Left
179
if (shift)
180
{
181
op2 = R(rm) << shift;
182
shiftcarry = (R(rm) >> (32-shift)) & 0x1;
183
}
184
else // LSL#0
185
op2 = R(rm);
186
break;
187
case 1: // Logical Shift Right
188
if (shift)
189
{
190
op2 = R(rm) >> shift;
191
shiftcarry = (R(rm) >> (shift-1)) & 0x1;
192
}
193
else // LSR#32
194
{
195
op2 = 0;
196
shiftcarry = R(rm) >> 31;
197
}
198
break;
199
case 2: // Arithmetic Shift Right
200
if (shift)
201
{
202
op2 = ((int32_t)R(rm)) >> shift;
203
shiftcarry = (((int32_t)R(rm)) >> (shift-1)) & 0x1;
204
}
205
else // ASR#32
206
{
207
op2 = ((int32_t)R(rm)) >> 31;
208
shiftcarry = op2 & 0x1;
209
}
210
break;
211
case 3: // ROtate Right
212
if (shift)
213
{
214
op2 = ROR(R(rm), shift);
215
shiftcarry = op2 >> 31;
216
}
217
else // RRX#1
218
{
219
shiftcarry = R(rm) & 0x1;
220
op2 = (FLAG_C << 31) | (R(rm) >> 1);
221
}
222
break;
223
}
224
225
a_DataProcCore(rd, R(Rn), op2, shiftcarry);
226
}
227
228
NIARM(_DataProcShiftReg)
229
{
230
if ((code >> 26) & 0x3)
231
met_abort("Bits 26-27 must be 00 for DataProc instructions");
232
if (code & (0x1 << 7))
233
met_abort("Bit 7 must be 0 for DataProc with shift by register instructions");
234
235
uint8_t shift;
236
uint32_t op1, op2 = 0; // to avoid a warning
237
bool shiftcarry = FLAG_C;
238
uint8_t rd = Rd;
239
240
uint8_t rm = Rm;
241
if (rm == 15 && !(code & (0x1 << 20)) && (code & (0x1 << 4)))
242
met_abort("Rm = 15, not implemented");
243
244
op1 = R(Rn);
245
246
NOT_PC(Rs);
247
ICYCLES(1);
248
if (Rn == 15)
249
op1 += 4;
250
251
shift = R(Rs) & 0xFF; // only first byte used
252
if (shift)
253
switch ((code >> 5) & 0x3)
254
{
255
case 0: // Logical Shift Left
256
if (shift == 32)
257
{
258
op2 = 0;
259
shiftcarry = R(rm) & 0x1;
260
}
261
else if (shift < 32)
262
{
263
op2 = R(rm) << shift;
264
shiftcarry = (R(rm) >> (32-shift)) & 0x1;
265
}
266
else
267
{
268
op2 = 0;
269
shiftcarry = 0;
270
}
271
break;
272
case 1: // Logical Shift Right
273
if (shift == 32)
274
{
275
op2 = 0;
276
shiftcarry = R(rm) >> 31;
277
}
278
else if (shift < 32)
279
{
280
op2 = R(rm) >> shift;
281
shiftcarry = (R(rm) >> (shift-1)) & 0x1;
282
}
283
else
284
{
285
op2 = 0;
286
shiftcarry = 0;
287
}
288
break;
289
case 2: // Arithmetic Shift Right
290
if (shift >= 32)
291
{
292
op2 = ((int32_t)R(rm)) >> 31;
293
shiftcarry = op2 & 0x1;
294
}
295
else
296
{
297
op2 = ((int32_t)R(rm)) >> shift;
298
shiftcarry = (((int32_t)R(rm)) >> (shift-1)) & 0x1;
299
}
300
break;
301
case 3: // ROtate Right
302
op2 = ROR(R(rm), shift % 32);
303
shiftcarry = op2 >> 31;
304
break;
305
}
306
else
307
op2 = R(rm);
308
309
a_DataProcCore(rd, op1, op2, shiftcarry);
310
}
311
312
NIARM(_DataProcImm)
313
{
314
if ((code >> 26) & 0x3)
315
met_abort("Bits 26-27 must be 00 for DataProc instructions");
316
317
uint32_t op2;
318
bool shiftcarry = FLAG_C;
319
uint8_t rd = Rd;
320
321
uint8_t shift = ((code >> 8) & 0xF);
322
if (shift)
323
{
324
op2 = ROR(code & 0xFF, shift * 2);
325
shiftcarry = op2 >> 31;
326
}
327
else
328
op2 = code & 0xFF;
329
330
a_DataProcCore(rd, R(Rn), op2, shiftcarry);
331
}
332
333
inline void Interpreter::a_DataProcCore(uint8_t rd,
334
uint32_t op1, uint32_t op2, bool shiftcarry)
335
{
336
uint8_t opcode = (code >> 21) & 0xF;
337
338
if (opcode < 0x8 || opcode > 0xB)
339
{
340
}
341
else if (!((code >> 20) & 0x1) || (rd != 0x0 && rd != 0xF))
342
met_abort("Set condition bit not set for test operation or Rd not acceptable for a test");
343
if ((opcode == 0xD || opcode == 0xF) && Rn)
344
met_abort("Rn not null for MOV or MVN");
345
346
#ifndef X86_ASM
347
uint32_t res;
348
#endif
349
350
if (code & (0x1 << 20)) // if set condition
351
{
352
switch (opcode)
353
{
354
case 0x0 : // AND
355
#ifdef X86_ASM
356
asm("andl %4, %3\n"
357
"setzb %1\n"
358
"setsb %2\n"
359
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N)
360
:"0"(op1), "r"(op2));
361
#else
362
res = R(rd) = op1 & op2;
363
FLAG_Z = !res;
364
FLAG_N = res >> 31;
365
#endif
366
FLAG_C = shiftcarry;
367
break;
368
case 0x1 : // EOR
369
#ifdef X86_ASM
370
asm("xorl %4, %3\n"
371
"setzb %1\n"
372
"setsb %2\n"
373
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N)
374
:"0"(op1), "r"(op2));
375
#else
376
res = R(rd) = op1 ^ op2;
377
FLAG_Z = !res;
378
FLAG_N = res >> 31;
379
#endif
380
FLAG_C = shiftcarry;
381
break;
382
case 0x2 : // SUB
383
#ifdef X86_ASM
384
asm("subl %6, %5\n"
385
"setzb %1\n"
386
"setsb %2\n"
387
"setncb %3\n"
388
"setob %4\n"
389
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C),
390
"=m"(FLAG_V)
391
:"0"(op1), "r"(op2));
392
#else
393
res = R(rd) = op1 - op2;
394
FLAG_Z = !res;
395
FLAG_N = res >> 31;
396
FLAG_C = SUBCARRY(op1, op2, res);
397
FLAG_V = SUBOVERFLOW(op1, op2, res);
398
#endif
399
break;
400
case 0x3 : // RSB
401
#ifdef X86_ASM
402
asm("subl %6, %5\n"
403
"setzb %1\n"
404
"setsb %2\n"
405
"setncb %3\n"
406
"setob %4\n"
407
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C),
408
"=m"(FLAG_V)
409
:"0"(op2), "r"(op1));
410
#else
411
res = R(rd) = op2 - op1;
412
FLAG_Z = !res;
413
FLAG_N = res >> 31;
414
FLAG_C = SUBCARRY(op1, op2, res);
415
FLAG_V = SUBOVERFLOW(op1, op2, res);
416
#endif
417
break;
418
case 0x4 : // ADD
419
#ifdef X86_ASM
420
asm("addl %6, %5\n"
421
"setzb %1\n"
422
"setsb %2\n"
423
"setcb %3\n"
424
"setob %4\n"
425
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C),
426
"=m"(FLAG_V)
427
:"0"(op1), "r"(op2));
428
#else
429
res = R(rd) = op1 + op2;
430
FLAG_Z = !res;
431
FLAG_N = res >> 31;
432
FLAG_C = ADDCARRY(op1, op2, res);
433
FLAG_V = ADDOVERFLOW(op1, op2, res);
434
#endif
435
break;
436
case 0x5 : // ADC
437
// TODO test on hardware how overflow and carry work for this
438
// instruction
439
#ifdef X86_ASM
440
asm("addl %6, %5\n"
441
"setzb %1\n"
442
"setsb %2\n"
443
"setcb %3\n"
444
"setob %4\n"
445
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C),
446
"=m"(FLAG_V)
447
:"0"(op1+FLAG_C), "r"(op2));
448
#else
449
res = R(rd) = op1 + op2 + FLAG_C;
450
FLAG_Z = !res;
451
FLAG_N = res >> 31;
452
FLAG_C = ADDCARRY(op1, op2, res);
453
FLAG_V = ADDOVERFLOW(op1, op2, res);
454
#endif
455
break;
456
case 0x6 : // SBC
457
// TODO test on hardware how overflow and carry work for this
458
// instruction
459
#ifdef X86_ASM
460
asm("subl %6, %5\n"
461
"setzb %1\n"
462
"setsb %2\n"
463
"setncb %3\n"
464
"setob %4\n"
465
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C),
466
"=m"(FLAG_V)
467
:"0"(op1+FLAG_C-1), "r"(op2));
468
#else
469
res = R(rd) = op1 - op2 + FLAG_C - 1;
470
FLAG_Z = !res;
471
FLAG_N = res >> 31;
472
FLAG_C = SUBCARRY(op1, op2, res);
473
FLAG_V = SUBOVERFLOW(op1, op2, res);
474
#endif
475
break;
476
case 0x7 : // RSC
477
#ifdef X86_ASM
478
asm("subl %6, %5\n"
479
"setzb %1\n"
480
"setsb %2\n"
481
"setncb %3\n"
482
"setob %4\n"
483
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C),
484
"=m"(FLAG_V)
485
:"0"(op2+FLAG_C-1), "r"(op1));
486
#else
487
res = R(rd) = op2 - op1 + FLAG_C - 1;
488
FLAG_Z = !res;
489
FLAG_N = res >> 31;
490
FLAG_C = SUBCARRY(op1, op2, res);
491
FLAG_V = SUBOVERFLOW(op1, op2, res);
492
#endif
493
break;
494
case 0x8 : // TST
495
#ifdef X86_ASM
496
asm("testl %3, %2\n"
497
"setzb %0\n"
498
"setsb %1\n"
499
:"=m"(FLAG_Z), "=m"(FLAG_N)
500
:"r"(op1), "r"(op2));
501
#else
502
res = op1 & op2;
503
FLAG_Z = !res;
504
FLAG_N = res >> 31;
505
#endif
506
SETFB(C, shiftcarry);
507
break;
508
case 0x9 : // TEQ
509
#ifdef X86_ASM
510
asm("xorl %3, %2\n"
511
"setzb %0\n"
512
"setsb %1\n"
513
:"=m"(FLAG_Z), "=m"(FLAG_N)
514
:"r"(op1), "r"(op2)
515
:"2");
516
#else
517
res = op1 ^ op2;
518
FLAG_Z = !res;
519
FLAG_N = res >> 31;
520
#endif
521
SETFB(C, shiftcarry);
522
break;
523
case 0xA : // CMP
524
#ifdef X86_ASM
525
asm("cmpl %5, %4\n"
526
"setzb %0\n"
527
"setsb %1\n"
528
"setncb %2\n"
529
"setob %3\n"
530
:"=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V)
531
:"r"(op1), "r"(op2));
532
#else
533
res = op1 - op2;
534
FLAG_Z = !res;
535
FLAG_N = res >> 31;
536
FLAG_C = SUBCARRY(op1, op2, res);
537
FLAG_V = SUBOVERFLOW(op1, op2, res);
538
#endif
539
break;
540
case 0xB : // CMN
541
#ifdef X86_ASM
542
asm("addl %5, %4\n"
543
"setzb %0\n"
544
"setsb %1\n"
545
"setcb %2\n"
546
"setob %3\n"
547
:"=m"(FLAG_Z), "=m"(FLAG_N), "=m"(FLAG_C), "=m"(FLAG_V)
548
:"r"(op1), "r"(op2)
549
:"4");
550
#else
551
res = op1 + op2;
552
FLAG_Z = !res;
553
FLAG_N = res >> 31;
554
FLAG_C = ADDCARRY(op1, op2, res);
555
FLAG_V = ADDOVERFLOW(op1, op2, res);
556
#endif
557
break;
558
case 0xC : // ORR
559
#ifdef X86_ASM
560
asm("orl %4, %3\n"
561
"setzb %1\n"
562
"setsb %2\n"
563
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N)
564
:"0"(op1), "r"(op2));
565
#else
566
res = R(rd) = op1 | op2;
567
FLAG_Z = !res;
568
FLAG_N = res >> 31;
569
#endif
570
FLAG_C = shiftcarry;
571
break;
572
case 0xD : // MOV
573
#ifdef X86_ASM
574
R(rd) = op2;
575
asm("testl %2, %2\n"
576
"setzb %0\n"
577
"setsb %1\n"
578
:"=m"(FLAG_Z), "=m"(FLAG_N)
579
:"r"(op2));
580
#else
581
res = R(rd) = op2;
582
FLAG_Z = !res;
583
FLAG_N = res >> 31;
584
#endif
585
FLAG_C = shiftcarry;
586
break;
587
case 0xE : // BIC
588
#ifdef X86_ASM
589
asm("not %3\n"
590
"andl %4, %3\n"
591
"setzb %1\n"
592
"setsb %2\n"
593
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N)
594
:"0"(op2), "r"(op1));
595
#else
596
res = R(rd) = op1 & ~op2;
597
FLAG_Z = !res;
598
FLAG_N = res >> 31;
599
#endif
600
FLAG_C = shiftcarry;
601
break;
602
case 0xF : // MVN
603
#ifdef X86_ASM
604
asm("xorl $0xffffffff, %3\n"
605
"setzb %1\n"
606
"setsb %2\n"
607
:"=r"(R(rd)), "=m"(FLAG_Z), "=m"(FLAG_N)
608
:"0"(op2));
609
#else
610
res = R(rd) = ~op2;
611
FLAG_Z = !res;
612
FLAG_N = res >> 31;
613
#endif
614
FLAG_C = shiftcarry;
615
break;
616
}
617
618
if (rd == 15)
619
CPU.SwitchModeBack();
620
}
621
else
622
switch (opcode)
623
{
624
case 0x0 : // AND
625
R(rd) = op1 & op2;
626
break;
627
case 0x1 : // EOR
628
R(rd) = op1 ^ op2;
629
break;
630
case 0x2 : // SUB
631
R(rd) = op1 - op2;
632
break;
633
case 0x3 : // RSB
634
R(rd) = op2 - op1;
635
break;
636
case 0x4 : // ADD
637
R(Rd) = op1 + op2;
638
break;
639
case 0x5 : // ADC
640
R(rd) = op1 + op2 + FLAG_C;
641
break;
642
case 0x6 : // SBC
643
R(rd) = op1 - op2 + FLAG_C - 1;
644
break;
645
case 0x7 : // RSC
646
R(rd) = op2 - op1 + FLAG_C - 1;
647
break;
648
case 0x8 : // TST
649
case 0x9 : // TEQ
650
case 0xA : // CMP
651
case 0xB : // CMN
652
met_abort("Comparison or test without set flags bit");
653
break;
654
case 0xC : // ORR
655
R(rd) = op1 | op2;
656
break;
657
case 0xD : // MOV
658
R(rd) = op2;
659
break;
660
case 0xE : // BIC
661
R(rd) = op1 & ~op2;
662
break;
663
case 0xF : // MVN
664
R(rd) = ~op2;
665
break;
666
}
667
668
if (rd == 15 && (opcode < 0x8 || opcode > 0xB))
669
{
670
if (FLAG_T)
671
{
672
CYCLES16NSeq(R(15), 3);
673
R(15) += 2;
674
}
675
else
676
{
677
CYCLES32NSeq(R(15), 3);
678
R(15) += 4;
679
}
680
}
681
else
682
CYCLES32Seq(R(15), 1);
683
684
if (opcode >= 0x8 && opcode <= 0xB && rd == 0xF)
685
met_abort("P test instruction (not implemented)");
686
}
687
688
// PSR Transfer (MRS, MSR)
689
ARM(PSR)
690
{
691
if ((code >> 26) & 0x3)
692
met_abort("Bits 26-27 must be 00 for PSR instructions");
693
if (((code >> 23) & 0x3) != 0x2)
694
met_abort("Bits 23-24 must be 10 for PSR instructions");
695
if (code & (0x1 << 20))
696
met_abort("Bit 20 must be 0 for PSR instructions");
697
698
bool oncpsr = !(code & (0x1 << 22));
699
if (oncpsr)
700
CPU.UpdateCpsr();
701
uint32_t& psr = oncpsr ? CPSR : SPSR;
702
703
if (code & (0x1 << 21)) // MSR
704
{
705
if (((code >> 12) & 0xF) != 0xF)
706
met_abort("Bits 12-15 must be 0xF for MSR instruction");
707
708
uint32_t val;
709
if (code & (0x1 << 25))
710
{
711
//val = ROR(code & 0xF, ((code >> 8) & 0x4) * 2);
712
val = ROR(code & 0xF, (code >> 7) & 0x6);
713
}
714
else
715
{
716
if ((code >> 4) & 0xFF)
717
met_abort("Bits 4-11 must be 0 for MSR instruction");
718
val = R(Rm);
719
}
720
if (!(code & (0x1 << 19)))
721
val = (val & 0x00FFFFFF) | (psr & 0xFF000000);
722
if (!(code & (0x1 << 18)))
723
val = (val & 0xFF00FFFF) | (psr & 0x00FF0000);
724
if (!(code & (0x1 << 17)))
725
val = (val & 0xFFFF00FF) | (psr & 0x0000FF00);
726
if (!(code & (0x1 << 16)))
727
val = (val & 0xFFFFFF00) | (psr & 0x000000FF);
728
else if (oncpsr &&
729
(psr & 0x1F) != (val & 0x1F)) // have we changed mode ?
730
CPU.SwitchToMode(val & 0x1F);
731
psr = val;
732
if (oncpsr)
733
{
734
CPU.UpdateICpsr();
735
CPU.CheckInterrupt();
736
}
737
}
738
else // MRS
739
{
740
if ((code >> 25) & 0x1)
741
met_abort("Bit 25 must be 0 for MRS instruction");
742
if (((code >> 16) & 0xF) != 0xF)
743
met_abort("Bits 16-19 must be 0xF for MRS instruction");
744
if (code & 0xFFF)
745
met_abort("Bits 0-11 must be 0 for MRS instruction");
746
R(Rd) = psr;
747
}
748
749
CYCLES32Seq(R(15), 1);
750
}
751
752
// Multiply and Multiply-Accumulate (MUL,MLA)
753
ARM(_Multiply)
754
{
755
// NOTE : In this instruction Rn and Rd are inverted
756
if ((code >> 25) & 0x7)
757
met_abort("Bits 25-27 must be 000 for Multiply instructions");
758
if (code & (0x1 << 24))
759
{
760
if (!(code & (0x1 << 7)))
761
met_abort("Bit 7 must be 1 for halfword multiply");
762
if (code & (0x1 << 4))
763
met_abort("Bit 7 must be 0 for halfword multiply");
764
}
765
else
766
{
767
if (((code >> 4) & 0xF) != 0x9)
768
met_abort("Bits 4-7 must be 1001 for non halfword multiplies");
769
}
770
NOT_PC_ALL();
771
772
switch ((code >> 21) & 0xF)
773
{
774
case 0x0 : // MUL
775
if (Rd != 0)
776
met_abort("Rd must be 0 for MUL instructions");
777
NOT_SAME2(Rn, Rm);
778
R(Rn) = R(Rm)*R(Rs);
779
if (code & (0x1 << 20))
780
{
781
FZ(R(Rn));
782
FN(R(Rn));
783
}
784
MULICYCLES(Rs);
785
CYCLES32Seq(R(15), 1);
786
break;
787
case 0x1 : // MLA
788
NOT_SAME2(Rn, Rm);
789
R(Rn) = R(Rm)*R(Rs)+R(Rd);
790
if (code & (0x1 << 20))
791
{
792
FZ(R(Rn));
793
FN(R(Rn));
794
}
795
MULICYCLES(Rs);
796
ICYCLES(1);
797
CYCLES32Seq(R(15), 1);
798
break;
799
case 0x4 : // UMULL
800
{
801
NOT_SAME3(Rn, Rd, Rm);
802
uint64_t out = ((uint64_t)R(Rm))*((uint64_t)R(Rs));
803
R(Rn) = out >> 32;
804
R(Rd) = out & 0xFFFFFFFF;
805
if (code & (0x1 << 20))
806
{
807
FZ(out);
808
FN(R(Rn));
809
}
810
}
811
MULICYCLES(Rs);
812
ICYCLES(1);
813
CYCLES32Seq(R(15), 1);
814
break;
815
case 0x5 : // UMLAL
816
{
817
NOT_SAME3(Rn, Rd, Rm);
818
uint64_t out =
819
((uint64_t)R(Rm)) * ((uint64_t)R(Rs)) +
820
((((uint64_t)R(Rn)) << 32) | ((uint64_t)R(Rd)));
821
R(Rn) = out >> 32;
822
R(Rd) = out & 0xFFFFFFFF;
823
if (code & (0x1 << 20))
824
{
825
FZ(out);
826
FN(R(Rn));
827
}
828
}
829
MULICYCLES(Rs);
830
ICYCLES(2);
831
CYCLES32Seq(R(15), 1);
832
break;
833
case 0x6 : // SMULL
834
{
835
NOT_SAME3(Rn, Rd, Rm);
836
int64_t out = ((int64_t)(int32_t)R(Rm)) * ((int64_t)(int32_t)R(Rs));
837
R(Rn) = out >> 32;
838
R(Rd) = out & 0xFFFFFFFF;
839
if (code & (0x1 << 20))
840
{
841
FZ(out);
842
FN(R(Rn));
843
}
844
}
845
MULICYCLES(Rs);
846
ICYCLES(1);
847
CYCLES32Seq(R(15), 1);
848
break;
849
case 0x7 : // SMLAL
850
{
851
NOT_SAME3(Rn, Rd, Rm);
852
int64_t out = ((int64_t)(int32_t)R(Rm)) * ((int64_t)(int32_t)R(Rs))
853
+ ((((int64_t)R(Rn)) << 32) | ((int64_t)R(Rd)));
854
R(Rn) = out >> 32;
855
R(Rd) = out & 0xFFFFFFFF;
856
if (code & (0x1 << 20))
857
{
858
FZ(out);
859
FN(R(Rn));
860
}
861
}
862
MULICYCLES(Rs);
863
ICYCLES(2);
864
CYCLES32Seq(R(15), 1);
865
break;
866
case 0x8 : // SMLAxy
867
case 0x9 : // SMLAW/SMULW
868
case 0xA : // SMLALxy
869
case 0xB : // SMULxy
870
default :
871
met_abort("Not implemented multiply instruction or unknown");
872
}
873
}
874
875
// Single Data Transfer (LDR, STR, PLD)
876
877
// Load and store
878
// FIXME : should this support Prepare Cache for Load instructions ?
879
ARM(LDRSTR)
880
{
881
if (((code >> 28) & 0xF) == 0xF)
882
met_abort("PLD instructions not implemented");
883
if (((code >> 26) & 0x3) != 0x1)
884
met_abort("Bits 26-27 must be 01 for LDR/STR instructions");
885
886
uint32_t offset;
887
888
if (code & (0x1 << 25)) // register offset
889
{
890
if (code & (0x1 << 4))
891
met_abort("Bit 4 must be 0 for LDR or STR instruction with register offset");
892
offset = (code >> 7) & 0x1F;
893
switch ((code >> 5) & 0x3)
894
{
895
case 0: // Logical Shift Left
896
if (offset)
897
offset = R(Rm) << offset;
898
else
899
offset = R(Rm);
900
break;
901
case 1: // Logical Shift Right
902
if (offset)
903
offset = R(Rm) >> offset;
904
else
905
offset = 0;
906
break;
907
case 2: // Arithmetic Shift Right
908
if (offset)
909
offset = ((int32_t)R(Rm)) >> offset;
910
else
911
{
912
if (R(Rm) >> 31)
913
offset = 0xFFFFFFFF;
914
else
915
offset = 0;
916
}
917
break;
918
case 3: // ROtate Right
919
if (offset)
920
offset = ROR(R(Rm), offset);
921
else
922
offset = (FLAG_C << 31) | (R(Rm) >> 1);
923
break;
924
}
925
}
926
else // immediate offset
927
{
928
offset = code & 0xFFF;
929
}
930
931
// bit 24 : 0 = add offset after and write-back, 1 = add offset before
932
uint32_t add = R(Rn);
933
if (code & (0x1 << 24))
934
{
935
if (code & (0x1 << 23))
936
add += offset;
937
else
938
add -= offset;
939
}
940
941
/* bit 22 : 0 = write word, 1 = write byte
942
* bit 20 : 0 = store, 1 = load */
943
if (code & (0x1 << 22))
944
{
945
if (code & (0x1 << 20)) // LDRB
946
{
947
R(Rd) = MEM.Read8(add);
948
if (Rd == 15)
949
met_abort("LDRB to R15 !");
950
CYCLES16NSeq(add, 1);
951
ICYCLES(1);
952
CYCLES32Seq(R(15), 1);
953
}
954
else // STRB
955
{
956
MEM.Write8(add, R(Rd));
957
CYCLES16NSeq(add, 1);
958
CYCLES32NSeq(R(15), 1);
959
}
960
}
961
else
962
{
963
if (code & (0x1 << 20)) // LDR
964
{
965
R(Rd) = MEM.Read32(add);
966
CYCLES32NSeq(add, 1);
967
ICYCLES(1);
968
if (Rd == 15)
969
{
970
CYCLES32NSeq(R(15), 3);
971
R(Rd) += 4;
972
}
973
else
974
CYCLES32Seq(R(15), 1);
975
}
976
else // STR
977
{
978
MEM.Write32(add, R(Rd));
979
CYCLES32NSeq(add, 1);
980
CYCLES32NSeq(R(15), 1);
981
}
982
}
983
984
// bit 21 if write before : 0 = nothing, 1 = write-back
985
if (!(code & (0x1 << 24))) // in post, writeback is always enabled
986
{
987
if (code & (0x1 << 23))
988
R(Rn) = add + offset;
989
else
990
R(Rn) = add - offset;
991
}
992
else if (code & (0x1 << 21))
993
R(Rn) = add;
994
}
995
996
// Halfword, Doubleword, and Signed Data Transfer
997
ARM(STRLDR_HD)
998
{
999
if ((code >> 25) & 0x7)
1000
met_abort("Bits 25-27 must be 000 for halfword transfer instructions");
1001
if (!(code & (0x1 << 7)) || !(code & (0x1 << 4)))
1002
met_abort("Bits 4 and 7 must be 1 for halfword transfer instructions");
1003
if (Rd == 15)
1004
met_abort("operation on r15, not implemented");
1005
1006
uint8_t rd = Rd;
1007
1008
uint32_t off;
1009
if (code & (0x1 << 22)) // immediate offset
1010
off = ((code >> 4) & 0xF0) | (code & 0xF);
1011
else // register offset
1012
{
1013
if ((code >> 8) & 0xF)
1014
met_abort("Bits 8-11 must be 0 for halfword transfer with register offset instructions");
1015
NOT_PC(Rm);
1016
off = R(Rm);
1017
}
1018
1019
uint32_t add = R(Rn);
1020
if (code & (0x1 << 24))
1021
{
1022
if (code & (0x1 << 23))
1023
add += off;
1024
else
1025
add -= off;
1026
}
1027
else if (code & (0x1 << 21))
1028
met_abort("Bit 21 must be 0 for post indexed halfword transfers instructions");
1029
1030
switch (((code >> 18) & 0x4) | ((code >> 5) & 0x3))
1031
{
1032
case 0x0:
1033
met_abort("Reserved for SWP instruction !");
1034
break;
1035
case 0x1: // STRH
1036
MEM.Write16(add, rd == 15 ? R(15) + 4 : R(rd));
1037
CYCLES16NSeq(add, 1);
1038
CYCLES32NSeq(R(15), 1);
1039
break;
1040
case 0x2: // LDRD
1041
if (rd % 2)
1042
met_abort("Register number not even for double word transfer");
1043
if (add % 8)
1044
met_abort("Address not double word aligned");
1045
if (rd == 15)
1046
met_abort("Rd is 15 for double word transfer !");
1047
R(rd) = MEM.Read32(add);
1048
R(rd+1) = MEM.Read32(add+4);
1049
CYCLES32NSeq(add, 2);
1050
ICYCLES(1);
1051
CYCLES32Seq(R(15), 1);
1052
break;
1053
case 0x3: // STRD
1054
if (rd % 2)
1055
met_abort("Register number not even for double word transfer");
1056
if (add % 8)
1057
met_abort("Address not double word aligned");
1058
if (rd == 15)
1059
met_abort("Rd is 15 for double word transfer !");
1060
MEM.Write32(add, R(rd));
1061
MEM.Write32(add + 4, rd == 14 ? R(15) + 4 : R(rd+1));
1062
CYCLES32NSeq(add, 2);
1063
CYCLES32NSeq(R(15), 1);
1064
break;
1065
case 0x4:
1066
met_abort("Reserved !");
1067
break;
1068
case 0x5: // LDRH
1069
R(rd) = MEM.Read16(add);
1070
CYCLES16NSeq(add, 1);
1071
ICYCLES(1);
1072
CYCLES32Seq(R(15), 1);
1073
break;
1074
case 0x6: // LDRSB
1075
R(rd) = MEM.Read8(add);
1076
// sign-extend
1077
R(rd) <<= 24;
1078
R(rd) = ((int32_t)R(rd)) >> 24;
1079
CYCLES16NSeq(add, 1);
1080
ICYCLES(1);
1081
CYCLES32Seq(R(15), 1);
1082
break;
1083
case 0x7: // LDRSH
1084
R(rd) = MEM.Read16(add);
1085
// sign-extend
1086
R(rd) <<= 16;
1087
R(rd) = ((int32_t)R(rd)) >> 16;
1088
CYCLES16NSeq(add, 1);
1089
ICYCLES(1);
1090
CYCLES32Seq(R(15), 1);
1091
break;
1092
}
1093
1094
if (!(code & (0x1 << 24))) // in post, writeback is always enabled
1095
{
1096
if (code & (0x1 << 23))
1097
R(Rn) = add + off;
1098
else
1099
R(Rn) = add - off;
1100
}
1101
else if (code & (0x1 << 21))
1102
R(Rn) = add;
1103
}
1104
1105
// Block Data Transfer (LDM,STM)
1106
ARM(LDMSTM)
1107
{
1108
if (((code >> 25) & 0x7) != 0x4)
1109
met_abort("Bits 25-27 must be 100 for LDM/STM instructions");
1110
if (code & (0x1 << 22))
1111
met_abort("not implemented");
1112
1113
static const uint8_t NumBits[] =
1114
{0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1115
1116
// Works like LDR and STR, look at above comments
1117
uint8_t numregs =
1118
NumBits[(code >> 12) & 0xF] +
1119
NumBits[(code >> 8) & 0xF] +
1120
NumBits[(code >> 4) & 0xF] +
1121
NumBits[ code & 0xF];
1122
uint16_t regs = code & 0xFFFF;
1123
1124
uint32_t add, baseadd;
1125
baseadd = add = R(Rn);
1126
if (code & (0x1 << 24))
1127
if (code & (0x1 << 23))
1128
add += 4; // increment before
1129
else
1130
add -= numregs * 4; // decrement before
1131
else
1132
if (!(code & (0x1 << 23)))
1133
add -= (numregs-1) * 4; // decrement after
1134
add &= 0xFFFFFFFC;
1135
1136
if (code & (0x1 << 20)) // LDM
1137
{
1138
CYCLES32NSeq(add, numregs);
1139
ICYCLES(1);
1140
for (register uint8_t n = 0; n < 16; ++n)
1141
if (regs & (0x1 << n))
1142
{
1143
R(n) = MEM.Read32 (add);
1144
if (n == 15)
1145
R(15) += 4;
1146
add += 4;
1147
}
1148
if (regs & (0x1 << 15))
1149
CYCLES32NSeq(R(15), 3);
1150
else
1151
CYCLES32Seq(R(15), 1);
1152
}
1153
else // STM
1154
{
1155
CYCLES32NSeq(add, numregs);
1156
CYCLES32NSeq(R(15), 1);
1157
1158
for (register uint8_t n = 0; n < 16; ++n)
1159
if (regs & (0x1 << n))
1160
{
1161
if (n == 15)
1162
MEM.Write32 (add, R(15) + 4);
1163
else
1164
MEM.Write32 (add, R(n));
1165
add += 4;
1166
}
1167
}
1168
1169
if (code & (0x1 << 21))
1170
if (code & (0x1 << 23))
1171
R(Rn) = baseadd + numregs * 4;
1172
else
1173
R(Rn) = baseadd - numregs * 4;
1174
}
1175
1176
// Single Data Swap (SWP)
1177
ARM(SWP)
1178
{
1179
if (((code >> 23) & 0x1F) != 0x02)
1180
met_abort("Bits 23-27 must be 00010 for SWP instructions");
1181
if ((code >> 20) & 0x3)
1182
met_abort("Bits 20-21 must be 00 for SWP instructions");
1183
if (((code >> 4) & 0xFF) != 0x09)
1184
met_abort("Bits 4-11 must be 00001001 for SWP instructions");
1185
1186
if (code & (0x1 << 22)) // SWPB
1187
{
1188
R(Rd) = MEM.Read8(R(Rn));
1189
MEM.Write8(R(Rn), R(Rm));
1190
}
1191
else // SWP
1192
{
1193
R(Rd) = MEM.Read32(R(Rn));
1194
MEM.Write32(R(Rn), R(Rm));
1195
}
1196
CYCLES32NSeq(R(Rn), 1);
1197
CYCLES32NSeq(R(Rn), 1);
1198
ICYCLES(1);
1199
CYCLES32Seq(R(15), 1);
1200
}
1201
1202
// Software Interrupt (SWI,BKPT)
1203
ARM(SWI)
1204
{
1205
if (((code >> 24) & 0xF) != 0xF)
1206
met_abort("Bits 24-27 must be 1111 for SWI instructions");
1207
1208
CPU.SoftwareInterrupt((code >> 16) & 0xFF);
1209
1210
// FIXME seems wrong !
1211
CYCLES32NSeq(0, 3);
1212
}
1213
1214
inline bool Interpreter::a_CheckCondition (uint8_t cond)
1215
{
1216
if (cond == 0xE)
1217
return true;
1218
1219
switch (cond)
1220
{
1221
case 0x0 : // EQ
1222
if (!FLAG_Z)
1223
return false;
1224
break;
1225
case 0x1 : // NE
1226
if (FLAG_Z)
1227
return false;
1228
break;
1229
case 0x2 : // CS
1230
if (!FLAG_C)
1231
return false;
1232
break;
1233
case 0x3 : // CC
1234
if (FLAG_C)
1235
return false;
1236
break;
1237
case 0x4 : // MI
1238
if (!FLAG_N)
1239
return false;
1240
break;
1241
case 0x5 : // PL
1242
if (FLAG_N)
1243
return false;
1244
break;
1245
case 0x6 : // VS
1246
if (!FLAG_V)
1247
return false;
1248
break;
1249
case 0x7 : // VC
1250
if (FLAG_V)
1251
return false;
1252
break;
1253
case 0x8 : // HI
1254
if (!FLAG_C || FLAG_Z)
1255
return false;
1256
break;
1257
case 0x9 : // LS
1258
if (FLAG_C && !FLAG_Z)
1259
return false;
1260
break;
1261
case 0xA : // GE
1262
if (FLAG_N != FLAG_V)
1263
return false;
1264
break;
1265
case 0xB : // LT
1266
if (FLAG_N == FLAG_V)
1267
return false;
1268
break;
1269
case 0xC : // GT
1270
if (FLAG_Z || FLAG_N != FLAG_V)
1271
return false;
1272
break;
1273
case 0xD : // LE
1274
if (!FLAG_Z && FLAG_N == FLAG_V)
1275
return false;
1276
break;
1277
case 0xE : // AL
1278
break;
1279
case 0xF : // reserved
1280
break;
1281
}
1282
1283
return true;
1284
}
1285
1286
NIARM(_Code)
1287
{
1288
if (!a_CheckCondition(code >> 28)) // condition failed
1289
CYCLES32Seq(R(15), 1);
1290
else
1291
switch ((code >> 25) & 0x7)
1292
{
1293
case 0x0:
1294
switch ((code >> 18) & 0x60 | (code >> 16) & 0x10 |
1295
(code >> 4) & 0x0F)
1296
{
1297
case 0x40:
1298
aPSR();
1299
break;
1300
case 0x00:
1301
case 0x02:
1302
case 0x04:
1303
case 0x06:
1304
case 0x08:
1305
case 0x0A:
1306
case 0x0C:
1307
case 0x0E:
1308
case 0x10:
1309
case 0x12:
1310
case 0x14:
1311
case 0x16:
1312
case 0x18:
1313
case 0x1A:
1314
case 0x1C:
1315
case 0x1E:
1316
case 0x20:
1317
case 0x22:
1318
case 0x24:
1319
case 0x26:
1320
case 0x28:
1321
case 0x2A:
1322
case 0x2C:
1323
case 0x2E:
1324
case 0x30:
1325
case 0x32:
1326
case 0x34:
1327
case 0x36:
1328
case 0x38:
1329
case 0x3A:
1330
case 0x3C:
1331
case 0x3E:
1332
case 0x50:
1333
case 0x52:
1334
case 0x54:
1335
case 0x56:
1336
case 0x58:
1337
case 0x5A:
1338
case 0x5C:
1339
case 0x5E:
1340
case 0x60:
1341
case 0x62:
1342
case 0x64:
1343
case 0x66:
1344
case 0x68:
1345
case 0x6A:
1346
case 0x6C:
1347
case 0x6E:
1348
case 0x70:
1349
case 0x72:
1350
case 0x74:
1351
case 0x76:
1352
case 0x78:
1353
case 0x7A:
1354
case 0x7C:
1355
case 0x7E:
1356
a_DataProcShiftImm();
1357
break;
1358
case 0x01:
1359
case 0x03:
1360
case 0x05:
1361
case 0x07:
1362
case 0x11:
1363
case 0x13:
1364
case 0x15:
1365
case 0x17:
1366
case 0x21:
1367
case 0x23:
1368
case 0x25:
1369
case 0x27:
1370
case 0x31:
1371
case 0x33:
1372
case 0x35:
1373
case 0x37:
1374
case 0x51:
1375
case 0x53:
1376
case 0x55:
1377
case 0x57:
1378
case 0x61:
1379
case 0x63:
1380
case 0x65:
1381
case 0x67:
1382
case 0x71:
1383
case 0x73:
1384
case 0x75:
1385
case 0x77:
1386
a_DataProcShiftReg();
1387
break;
1388
case 0x09:
1389
case 0x19:
1390
case 0x29:
1391
case 0x39:
1392
case 0x48:
1393
case 0x4A:
1394
case 0x4C:
1395
case 0x4E:
1396
a_Multiply();
1397
break;
1398
case 0x0B:
1399
case 0x0D:
1400
case 0x0F:
1401
case 0x1B:
1402
case 0x1D:
1403
case 0x1F:
1404
case 0x2B:
1405
case 0x2D:
1406
case 0x2F:
1407
case 0x3B:
1408
case 0x3D:
1409
case 0x3F:
1410
case 0x4B:
1411
case 0x4D:
1412
case 0x4F:
1413
case 0x5B:
1414
case 0x5D:
1415
case 0x5F:
1416
case 0x6B:
1417
case 0x6D:
1418
case 0x6F:
1419
case 0x7B:
1420
case 0x7D:
1421
case 0x7F:
1422
aSTRLDR_HD();
1423
break;
1424
case 0x49:
1425
aSWP();
1426
break;
1427
case 0x41:
1428
case 0x43:
1429
aBXBLX();
1430
break;
1431
default:
1432
met_abort("unknown");
1433
break;
1434
}
1435
break;
1436
case 0x1:
1437
// TODO PSR
1438
a_DataProcImm();
1439
break;
1440
case 0x2:
1441
case 0x3:
1442
aLDRSTR();
1443
break;
1444
case 0x4:
1445
aLDMSTM();
1446
break;
1447
case 0x5:
1448
aBBL();
1449
break;
1450
case 0x7:
1451
if (code & (0x1 << 24))
1452
aSWI();
1453
else
1454
met_abort("unknown");
1455
break;
1456
default:
1457
{ std::cerr << IOS_ADD << R(15)-8 << " : " << IOS_ADD << code << " : "; debug_bits(code); met_abort("not implemented"); }
1458
break;
1459
}
1460
}
1461
}
1462
1463
#undef Rn
1464
#undef Rd
1465
#undef Rs
1466
#undef Rm
1467
1468
#undef LSOff
1469
1470
#undef NOT_PC
1471
#undef NOT_PC_ALL
1472
#undef NOT_SAME2
1473
#undef NOT_SAME3
1474
1475
#undef ARM
1476
1477
#endif
1478
1479