1 /* gameplaySP
2 *
3 * Copyright (C) 2006 Exophase <exophase@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 // Important todo:
21 // - stm reglist writeback when base is in the list needs adjustment
22 // - block memory needs psr swapping and user mode reg swapping
23
24 #include "common.h"
25
26 u32 memory_region_access_read_u8[16];
27 u32 memory_region_access_read_s8[16];
28 u32 memory_region_access_read_u16[16];
29 u32 memory_region_access_read_s16[16];
30 u32 memory_region_access_read_u32[16];
31 u32 memory_region_access_write_u8[16];
32 u32 memory_region_access_write_u16[16];
33 u32 memory_region_access_write_u32[16];
34 u32 memory_reads_u8;
35 u32 memory_reads_s8;
36 u32 memory_reads_u16;
37 u32 memory_reads_s16;
38 u32 memory_reads_u32;
39 u32 memory_writes_u8;
40 u32 memory_writes_u16;
41 u32 memory_writes_u32;
42
43 const u8 bit_count[256] =
44 {
45 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3,
46 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4,
47 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2,
48 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
49 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4,
50 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3,
51 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2,
52 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
53 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5,
54 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5,
55 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6,
56 7, 7, 8
57 };
58
59
60 #ifdef REGISTER_USAGE_ANALYZE
61
62 u64 instructions_total = 0;
63
64 u64 arm_reg_freq[16];
65 u64 arm_reg_access_total = 0;
66 u64 arm_instructions_total = 0;
67
68 u64 thumb_reg_freq[16];
69 u64 thumb_reg_access_total = 0;
70 u64 thumb_instructions_total = 0;
71
72 // mla/long mla's addition operand are not counted yet.
73
74 #define using_register(instruction_set, register, type) \
75 instruction_set##_reg_freq[register]++; \
76 instruction_set##_reg_access_total++ \
77
78 #define using_register_list(instruction_set, rlist, count) \
79 { \
80 u32 i; \
81 for(i = 0; i < count; i++) \
82 { \
83 if((reg_list >> i) & 0x01) \
84 { \
85 using_register(instruction_set, i, memory_target); \
86 } \
87 } \
88 } \
89
90 #define using_instruction(instruction_set) \
91 instruction_set##_instructions_total++; \
92 instructions_total++ \
93
sort_tagged_element(const void * _a,const void * _b)94 int sort_tagged_element(const void *_a, const void *_b)
95 {
96 const u64 *a = _a;
97 const u64 *b = _b;
98
99 return (int)(b[1] - a[1]);
100 }
101
print_register_usage(void)102 void print_register_usage(void)
103 {
104 u32 i;
105 u64 arm_reg_freq_tagged[32];
106 u64 thumb_reg_freq_tagged[32];
107 double percent;
108 double percent_total = 0.0;
109
110 for(i = 0; i < 16; i++)
111 {
112 arm_reg_freq_tagged[i * 2] = i;
113 arm_reg_freq_tagged[(i * 2) + 1] = arm_reg_freq[i];
114 thumb_reg_freq_tagged[i * 2] = i;
115 thumb_reg_freq_tagged[(i * 2) + 1] = thumb_reg_freq[i];
116 }
117
118 qsort(arm_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
119 qsort(thumb_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
120
121 printf("ARM register usage (%lf%% ARM instructions):\n",
122 (arm_instructions_total * 100.0) / instructions_total);
123 for(i = 0; i < 16; i++)
124 {
125 percent = (arm_reg_freq_tagged[(i * 2) + 1] * 100.0) /
126 arm_reg_access_total;
127 percent_total += percent;
128 printf("r%02d: %lf%% (-- %lf%%)\n",
129 (u32)arm_reg_freq_tagged[(i * 2)], percent, percent_total);
130 }
131
132 percent_total = 0.0;
133
134 printf("\nThumb register usage (%lf%% Thumb instructions):\n",
135 (thumb_instructions_total * 100.0) / instructions_total);
136 for(i = 0; i < 16; i++)
137 {
138 percent = (thumb_reg_freq_tagged[(i * 2) + 1] * 100.0) /
139 thumb_reg_access_total;
140 percent_total += percent;
141 printf("r%02d: %lf%% (-- %lf%%)\n",
142 (u32)thumb_reg_freq_tagged[(i * 2)], percent, percent_total);
143 }
144
145 memset(arm_reg_freq, 0, sizeof(u64) * 16);
146 memset(thumb_reg_freq, 0, sizeof(u64) * 16);
147 arm_reg_access_total = 0;
148 thumb_reg_access_total = 0;
149 }
150
151 #else
152
153 #define using_register(instruction_set, register, type) \
154
155 #define using_register_list(instruction_set, rlist, count) \
156
157 #define using_instruction(instruction_set) \
158
159 #endif
160
161
162 #define arm_decode_data_proc_reg(opcode) \
163 u32 rn = (opcode >> 16) & 0x0F; \
164 u32 rd = (opcode >> 12) & 0x0F; \
165 u32 rm = opcode & 0x0F; \
166 (void)rd; \
167 (void)rn; \
168 using_register(arm, rd, op_dest); \
169 using_register(arm, rn, op_src); \
170 using_register(arm, rm, op_src) \
171
172 #define arm_decode_data_proc_imm(opcode) \
173 u32 imm; \
174 u32 rn = (opcode >> 16) & 0x0F; \
175 u32 rd = (opcode >> 12) & 0x0F; \
176 (void)rd; \
177 (void)rn; \
178 ror(imm, opcode & 0xFF, ((opcode >> 8) & 0x0F) * 2); \
179 using_register(arm, rd, op_dest); \
180 using_register(arm, rn, op_src) \
181
182 #define arm_decode_psr_reg(opcode) \
183 u32 psr_field = (opcode >> 16) & 0x0F; \
184 u32 rd = (opcode >> 12) & 0x0F; \
185 u32 rm = opcode & 0x0F; \
186 (void)rd; \
187 (void)rm; \
188 (void)psr_field; \
189 using_register(arm, rd, op_dest); \
190 using_register(arm, rm, op_src) \
191
192 #define arm_decode_psr_imm(opcode) \
193 u32 imm; \
194 u32 psr_field = (opcode >> 16) & 0x0F; \
195 u32 rd = (opcode >> 12) & 0x0F; \
196 (void)rd; \
197 ror(imm, opcode & 0xFF, ((opcode >> 8) & 0x0F) * 2); \
198 using_register(arm, rd, op_dest) \
199
200 #define arm_decode_branchx(opcode) \
201 u32 rn = opcode & 0x0F; \
202 using_register(arm, rn, branch_target) \
203
204 #define arm_decode_multiply() \
205 u32 rd = (opcode >> 16) & 0x0F; \
206 u32 rn = (opcode >> 12) & 0x0F; \
207 u32 rs = (opcode >> 8) & 0x0F; \
208 u32 rm = opcode & 0x0F; \
209 (void)rn; \
210 using_register(arm, rd, op_dest); \
211 using_register(arm, rn, op_src); \
212 using_register(arm, rm, op_src) \
213
214 #define arm_decode_multiply_long() \
215 u32 rdhi = (opcode >> 16) & 0x0F; \
216 u32 rdlo = (opcode >> 12) & 0x0F; \
217 u32 rn = (opcode >> 8) & 0x0F; \
218 u32 rm = opcode & 0x0F; \
219 using_register(arm, rdhi, op_dest); \
220 using_register(arm, rdlo, op_dest); \
221 using_register(arm, rn, op_src); \
222 using_register(arm, rm, op_src) \
223
224 #define arm_decode_swap() \
225 u32 rn = (opcode >> 16) & 0x0F; \
226 u32 rd = (opcode >> 12) & 0x0F; \
227 u32 rm = opcode & 0x0F; \
228 using_register(arm, rd, memory_target); \
229 using_register(arm, rn, memory_base); \
230 using_register(arm, rm, memory_target) \
231
232 #define arm_decode_half_trans_r() \
233 u32 rn = (opcode >> 16) & 0x0F; \
234 u32 rd = (opcode >> 12) & 0x0F; \
235 u32 rm = opcode & 0x0F; \
236 using_register(arm, rd, memory_target); \
237 using_register(arm, rn, memory_base); \
238 using_register(arm, rm, memory_offset) \
239
240 #define arm_decode_half_trans_of() \
241 u32 rn = (opcode >> 16) & 0x0F; \
242 u32 rd = (opcode >> 12) & 0x0F; \
243 u32 offset = ((opcode >> 4) & 0xF0) | (opcode & 0x0F); \
244 using_register(arm, rd, memory_target); \
245 using_register(arm, rn, memory_base) \
246
247 #define arm_decode_data_trans_imm() \
248 u32 rn = (opcode >> 16) & 0x0F; \
249 u32 rd = (opcode >> 12) & 0x0F; \
250 u32 offset = opcode & 0x0FFF; \
251 using_register(arm, rd, memory_target); \
252 using_register(arm, rn, memory_base) \
253
254 #define arm_decode_data_trans_reg() \
255 u32 rn = (opcode >> 16) & 0x0F; \
256 u32 rd = (opcode >> 12) & 0x0F; \
257 u32 rm = opcode & 0x0F; \
258 using_register(arm, rd, memory_target); \
259 using_register(arm, rn, memory_base); \
260 using_register(arm, rm, memory_offset) \
261
262 #define arm_decode_block_trans() \
263 u32 rn = (opcode >> 16) & 0x0F; \
264 u32 reg_list = opcode & 0xFFFF; \
265 using_register(arm, rn, memory_base); \
266 using_register_list(arm, reg_list, 16) \
267
268 #define arm_decode_branch() \
269 s32 offset = ((s32)(opcode & 0xFFFFFF) << 8) >> 6 \
270
271
272 #define thumb_decode_shift() \
273 u32 imm = (opcode >> 6) & 0x1F; \
274 u32 rs = (opcode >> 3) & 0x07; \
275 u32 rd = opcode & 0x07; \
276 using_register(thumb, rd, op_dest); \
277 using_register(thumb, rs, op_shift) \
278
279 #define thumb_decode_add_sub() \
280 u32 rn = (opcode >> 6) & 0x07; \
281 u32 rs = (opcode >> 3) & 0x07; \
282 u32 rd = opcode & 0x07; \
283 using_register(thumb, rd, op_dest); \
284 using_register(thumb, rn, op_src); \
285 using_register(thumb, rn, op_src) \
286
287 #define thumb_decode_add_sub_imm() \
288 u32 imm = (opcode >> 6) & 0x07; \
289 u32 rs = (opcode >> 3) & 0x07; \
290 u32 rd = opcode & 0x07; \
291 using_register(thumb, rd, op_src_dest); \
292 using_register(thumb, rs, op_src) \
293
294 #define thumb_decode_imm() \
295 u32 imm = opcode & 0xFF; \
296 using_register(thumb, ((opcode >> 8) & 0x07), op_dest) \
297
298 #define thumb_decode_alu_op() \
299 u32 rs = (opcode >> 3) & 0x07; \
300 u32 rd = opcode & 0x07; \
301 using_register(thumb, rd, op_src_dest); \
302 using_register(thumb, rs, op_src) \
303
304 #define thumb_decode_hireg_op() \
305 u32 rs = (opcode >> 3) & 0x0F; \
306 u32 rd = ((opcode >> 4) & 0x08) | (opcode & 0x07); \
307 (void)rd; \
308 using_register(thumb, rd, op_src_dest); \
309 using_register(thumb, rs, op_src) \
310
311
312 #define thumb_decode_mem_reg() \
313 u32 ro = (opcode >> 6) & 0x07; \
314 u32 rb = (opcode >> 3) & 0x07; \
315 u32 rd = opcode & 0x07; \
316 using_register(thumb, rd, memory_target); \
317 using_register(thumb, rb, memory_base); \
318 using_register(thumb, ro, memory_offset) \
319
320
321 #define thumb_decode_mem_imm() \
322 u32 imm = (opcode >> 6) & 0x1F; \
323 u32 rb = (opcode >> 3) & 0x07; \
324 u32 rd = opcode & 0x07; \
325 using_register(thumb, rd, memory_target); \
326 using_register(thumb, rb, memory_base) \
327
328
329 #define thumb_decode_add_sp() \
330 u32 imm = opcode & 0x7F; \
331 using_register(thumb, REG_SP, op_dest) \
332
333 #define thumb_decode_rlist() \
334 u32 reg_list = opcode & 0xFF; \
335 using_register_list(thumb, rlist, 8) \
336
337 #define thumb_decode_branch_cond() \
338 s32 offset = (s8)(opcode & 0xFF) \
339
340 #define thumb_decode_swi() \
341 u32 comment = opcode & 0xFF \
342
343 #define thumb_decode_branch() \
344 u32 offset = opcode & 0x07FF \
345
346
347 #define get_shift_register(dest) \
348 u32 shift = reg[(opcode >> 8) & 0x0F]; \
349 using_register(arm, ((opcode >> 8) & 0x0F), op_shift); \
350 dest = reg[rm]; \
351 if(rm == 15) \
352 dest += 4 \
353
354
355 #define calculate_z_flag(dest) \
356 z_flag = (dest == 0) \
357
358 #define calculate_n_flag(dest) \
359 n_flag = ((signed)dest < 0) \
360
361 #define calculate_c_flag_sub(dest, src_a, src_b) \
362 c_flag = ((unsigned)src_b <= (unsigned)src_a) \
363
364 #define calculate_v_flag_sub(dest, src_a, src_b) \
365 v_flag = ((signed)src_b > (signed)src_a) != ((signed)dest < 0) \
366
367 #define calculate_c_flag_add(dest, src_a, src_b) \
368 c_flag = ((unsigned)dest < (unsigned)src_a) \
369
370 #define calculate_v_flag_add(dest, src_a, src_b) \
371 v_flag = ((signed)dest < (signed)src_a) != ((signed)src_b < 0) \
372
373
374 #define calculate_reg_sh() \
375 u32 reg_sh = 0; \
376 switch((opcode >> 4) & 0x07) \
377 { \
378 /* LSL imm */ \
379 case 0x0: \
380 { \
381 reg_sh = reg[rm] << ((opcode >> 7) & 0x1F); \
382 break; \
383 } \
384 \
385 /* LSL reg */ \
386 case 0x1: \
387 { \
388 get_shift_register(reg_sh); \
389 if(shift <= 31) \
390 reg_sh = reg_sh << shift; \
391 else \
392 reg_sh = 0; \
393 break; \
394 } \
395 \
396 /* LSR imm */ \
397 case 0x2: \
398 { \
399 u32 imm = (opcode >> 7) & 0x1F; \
400 if(imm == 0) \
401 reg_sh = 0; \
402 else \
403 reg_sh = reg[rm] >> imm; \
404 break; \
405 } \
406 \
407 /* LSR reg */ \
408 case 0x3: \
409 { \
410 get_shift_register(reg_sh); \
411 if(shift <= 31) \
412 reg_sh = reg_sh >> shift; \
413 else \
414 reg_sh = 0; \
415 break; \
416 } \
417 \
418 /* ASR imm */ \
419 case 0x4: \
420 { \
421 u32 imm = (opcode >> 7) & 0x1F; \
422 reg_sh = reg[rm]; \
423 \
424 if(imm == 0) \
425 reg_sh = (s32)reg_sh >> 31; \
426 else \
427 reg_sh = (s32)reg_sh >> imm; \
428 break; \
429 } \
430 \
431 /* ASR reg */ \
432 case 0x5: \
433 { \
434 get_shift_register(reg_sh); \
435 if(shift <= 31) \
436 reg_sh = (s32)reg_sh >> shift; \
437 else \
438 reg_sh = (s32)reg_sh >> 31; \
439 break; \
440 } \
441 \
442 /* ROR imm */ \
443 case 0x6: \
444 { \
445 u32 imm = (opcode >> 7) & 0x1F; \
446 \
447 if(imm == 0) \
448 reg_sh = (reg[rm] >> 1) | (c_flag << 31); \
449 else \
450 ror(reg_sh, reg[rm], imm); \
451 break; \
452 } \
453 \
454 /* ROR reg */ \
455 case 0x7: \
456 { \
457 get_shift_register(reg_sh); \
458 ror(reg_sh, reg_sh, shift); \
459 break; \
460 } \
461 } \
462
463 #define calculate_reg_sh_flags() \
464 u32 reg_sh = 0; \
465 switch((opcode >> 4) & 0x07) \
466 { \
467 /* LSL imm */ \
468 case 0x0: \
469 { \
470 u32 imm = (opcode >> 7) & 0x1F; \
471 reg_sh = reg[rm]; \
472 \
473 if(imm != 0) \
474 { \
475 c_flag = (reg_sh >> (32 - imm)) & 0x01; \
476 reg_sh <<= imm; \
477 } \
478 \
479 break; \
480 } \
481 \
482 /* LSL reg */ \
483 case 0x1: \
484 { \
485 get_shift_register(reg_sh); \
486 if(shift != 0) \
487 { \
488 if(shift > 31) \
489 { \
490 if(shift == 32) \
491 c_flag = reg_sh & 0x01; \
492 else \
493 c_flag = 0; \
494 reg_sh = 0; \
495 } \
496 else \
497 { \
498 c_flag = (reg_sh >> (32 - shift)) & 0x01; \
499 reg_sh <<= shift; \
500 } \
501 } \
502 break; \
503 } \
504 \
505 /* LSR imm */ \
506 case 0x2: \
507 { \
508 u32 imm = (opcode >> 7) & 0x1F; \
509 reg_sh = reg[rm]; \
510 if(imm == 0) \
511 { \
512 c_flag = reg_sh >> 31; \
513 reg_sh = 0; \
514 } \
515 else \
516 { \
517 c_flag = (reg_sh >> (imm - 1)) & 0x01; \
518 reg_sh >>= imm; \
519 } \
520 break; \
521 } \
522 \
523 /* LSR reg */ \
524 case 0x3: \
525 { \
526 get_shift_register(reg_sh); \
527 if(shift != 0) \
528 { \
529 if(shift > 31) \
530 { \
531 if(shift == 32) \
532 c_flag = (reg_sh >> 31) & 0x01; \
533 else \
534 c_flag = 0; \
535 reg_sh = 0; \
536 } \
537 else \
538 { \
539 c_flag = (reg_sh >> (shift - 1)) & 0x01; \
540 reg_sh >>= shift; \
541 } \
542 } \
543 break; \
544 } \
545 \
546 /* ASR imm */ \
547 case 0x4: \
548 { \
549 u32 imm = (opcode >> 7) & 0x1F; \
550 reg_sh = reg[rm]; \
551 if(imm == 0) \
552 { \
553 reg_sh = (s32)reg_sh >> 31; \
554 c_flag = reg_sh & 0x01; \
555 } \
556 else \
557 { \
558 c_flag = (reg_sh >> (imm - 1)) & 0x01; \
559 reg_sh = (s32)reg_sh >> imm; \
560 } \
561 break; \
562 } \
563 \
564 /* ASR reg */ \
565 case 0x5: \
566 { \
567 get_shift_register(reg_sh); \
568 if(shift != 0) \
569 { \
570 if(shift > 31) \
571 { \
572 reg_sh = (s32)reg_sh >> 31; \
573 c_flag = reg_sh & 0x01; \
574 } \
575 else \
576 { \
577 c_flag = (reg_sh >> (shift - 1)) & 0x01; \
578 reg_sh = (s32)reg_sh >> shift; \
579 } \
580 } \
581 break; \
582 } \
583 \
584 /* ROR imm */ \
585 case 0x6: \
586 { \
587 u32 imm = (opcode >> 7) & 0x1F; \
588 reg_sh = reg[rm]; \
589 if(imm == 0) \
590 { \
591 u32 old_c_flag = c_flag; \
592 c_flag = reg_sh & 0x01; \
593 reg_sh = (reg_sh >> 1) | (old_c_flag << 31); \
594 } \
595 else \
596 { \
597 c_flag = (reg_sh >> (imm - 1)) & 0x01; \
598 ror(reg_sh, reg_sh, imm); \
599 } \
600 break; \
601 } \
602 \
603 /* ROR reg */ \
604 case 0x7: \
605 { \
606 get_shift_register(reg_sh); \
607 if(shift != 0) \
608 { \
609 c_flag = (reg_sh >> (shift - 1)) & 0x01; \
610 ror(reg_sh, reg_sh, shift); \
611 } \
612 break; \
613 } \
614 } \
615
616 #define calculate_reg_offset() \
617 u32 reg_offset = 0; \
618 switch((opcode >> 5) & 0x03) \
619 { \
620 /* LSL imm */ \
621 case 0x0: \
622 { \
623 reg_offset = reg[rm] << ((opcode >> 7) & 0x1F); \
624 break; \
625 } \
626 \
627 /* LSR imm */ \
628 case 0x1: \
629 { \
630 u32 imm = (opcode >> 7) & 0x1F; \
631 if(imm == 0) \
632 reg_offset = 0; \
633 else \
634 reg_offset = reg[rm] >> imm; \
635 break; \
636 } \
637 \
638 /* ASR imm */ \
639 case 0x2: \
640 { \
641 u32 imm = (opcode >> 7) & 0x1F; \
642 if(imm == 0) \
643 reg_offset = (s32)reg[rm] >> 31; \
644 else \
645 reg_offset = (s32)reg[rm] >> imm; \
646 break; \
647 } \
648 \
649 /* ROR imm */ \
650 case 0x3: \
651 { \
652 u32 imm = (opcode >> 7) & 0x1F; \
653 if(imm == 0) \
654 reg_offset = (reg[rm] >> 1) | (c_flag << 31); \
655 else \
656 ror(reg_offset, reg[rm], imm); \
657 break; \
658 } \
659 } \
660
661 #define calculate_flags_add(dest, src_a, src_b) \
662 calculate_z_flag(dest); \
663 calculate_n_flag(dest); \
664 calculate_c_flag_add(dest, src_a, src_b); \
665 calculate_v_flag_add(dest, src_a, src_b) \
666
667 #define calculate_flags_sub(dest, src_a, src_b) \
668 calculate_z_flag(dest); \
669 calculate_n_flag(dest); \
670 calculate_c_flag_sub(dest, src_a, src_b); \
671 calculate_v_flag_sub(dest, src_a, src_b) \
672
673 #define calculate_flags_logic(dest) \
674 calculate_z_flag(dest); \
675 calculate_n_flag(dest) \
676
677 #define extract_flags() \
678 n_flag = reg[REG_CPSR] >> 31; \
679 z_flag = (reg[REG_CPSR] >> 30) & 0x01; \
680 c_flag = (reg[REG_CPSR] >> 29) & 0x01; \
681 v_flag = (reg[REG_CPSR] >> 28) & 0x01; \
682
683 #define collapse_flags() \
684 reg[REG_CPSR] = (n_flag << 31) | (z_flag << 30) | (c_flag << 29) | \
685 (v_flag << 28) | (reg[REG_CPSR] & 0xFF) \
686
687 #define memory_region(r_dest, l_dest, address) \
688 r_dest = memory_regions[address >> 24]; \
689 l_dest = memory_limits[address >> 24] \
690
691
692 #define pc_region() \
693 memory_region(pc_region, pc_limit, pc) \
694
695 #define check_pc_region() \
696 new_pc_region = (pc >> 15); \
697 if(new_pc_region != pc_region) \
698 { \
699 pc_region = new_pc_region; \
700 pc_address_block = memory_map_read[new_pc_region]; \
701 \
702 if(!pc_address_block) \
703 pc_address_block = load_gamepak_page(pc_region & 0x3FF); \
704 } \
705
706 u32 branch_targets = 0;
707 u32 high_frequency_branch_targets = 0;
708
709 #define BRANCH_ACTIVITY_THRESHOLD 50
710
711 #define arm_update_pc() \
712 pc = reg[REG_PC] \
713
714 #define arm_pc_offset(val) \
715 pc += val; \
716 reg[REG_PC] = pc \
717
718 #define arm_pc_offset_update(val) \
719 pc += val; \
720 reg[REG_PC] = pc \
721
722 #define arm_pc_offset_update_direct(val) \
723 pc = val; \
724 reg[REG_PC] = pc \
725
726
727 // It should be okay to still generate result flags, spsr will overwrite them.
728 // This is pretty infrequent (returning from interrupt handlers, et al) so
729 // probably not worth optimizing for.
730
731 #define check_for_interrupts() \
732 if((io_registers[REG_IE] & io_registers[REG_IF]) && \
733 io_registers[REG_IME] && ((reg[REG_CPSR] & 0x80) == 0)) \
734 { \
735 reg_mode[MODE_IRQ][6] = reg[REG_PC] + 4; \
736 spsr[MODE_IRQ] = reg[REG_CPSR]; \
737 reg[REG_CPSR] = 0xD2; \
738 reg[REG_PC] = 0x00000018; \
739 arm_update_pc(); \
740 set_cpu_mode(MODE_IRQ); \
741 goto arm_loop; \
742 } \
743
744 #define arm_spsr_restore() \
745 if(rd == 15) \
746 { \
747 if(reg[CPU_MODE] != MODE_USER) \
748 { \
749 reg[REG_CPSR] = spsr[reg[CPU_MODE]]; \
750 extract_flags(); \
751 set_cpu_mode(cpu_modes[reg[REG_CPSR] & 0x1F]); \
752 check_for_interrupts(); \
753 } \
754 arm_update_pc(); \
755 \
756 if(reg[REG_CPSR] & 0x20) \
757 goto thumb_loop; \
758 } \
759
760 #define arm_data_proc_flags_reg() \
761 arm_decode_data_proc_reg(opcode); \
762 calculate_reg_sh_flags() \
763
764 #define arm_data_proc_reg() \
765 arm_decode_data_proc_reg(opcode); \
766 calculate_reg_sh() \
767
768 #define arm_data_proc_flags_imm() \
769 arm_decode_data_proc_imm(opcode) \
770
771 #define arm_data_proc_imm() \
772 arm_decode_data_proc_imm(opcode) \
773
774 #define arm_data_proc(expr, type) \
775 { \
776 u32 dest; \
777 arm_pc_offset(8); \
778 arm_data_proc_##type(); \
779 dest = expr; \
780 arm_pc_offset(-4); \
781 reg[rd] = dest; \
782 \
783 if(rd == 15) \
784 { \
785 arm_update_pc(); \
786 } \
787 } \
788
789 #define flags_vars(src_a, src_b) \
790 u32 dest; \
791 const u32 _sa = src_a; \
792 const u32 _sb = src_b \
793
794 #define arm_data_proc_logic_flags(expr, type) \
795 { \
796 arm_pc_offset(8); \
797 arm_data_proc_flags_##type(); \
798 u32 dest = expr; \
799 calculate_flags_logic(dest); \
800 arm_pc_offset(-4); \
801 reg[rd] = dest; \
802 arm_spsr_restore(); \
803 } \
804
805 #define arm_data_proc_add_flags(src_a, src_b, type) \
806 { \
807 arm_pc_offset(8); \
808 arm_data_proc_##type(); \
809 flags_vars(src_a, src_b); \
810 dest = _sa + _sb; \
811 calculate_flags_add(dest, _sa, _sb); \
812 arm_pc_offset(-4); \
813 reg[rd] = dest; \
814 arm_spsr_restore(); \
815 }
816
817 #define arm_data_proc_sub_flags(src_a, src_b, type) \
818 { \
819 arm_pc_offset(8); \
820 arm_data_proc_##type(); \
821 flags_vars(src_a, src_b); \
822 dest = _sa - _sb; \
823 calculate_flags_sub(dest, _sa, _sb); \
824 arm_pc_offset(-4); \
825 reg[rd] = dest; \
826 arm_spsr_restore(); \
827 } \
828
829 #define arm_data_proc_test_logic(expr, type) \
830 { \
831 arm_pc_offset(8); \
832 arm_data_proc_flags_##type(); \
833 u32 dest = expr; \
834 calculate_flags_logic(dest); \
835 arm_pc_offset(-4); \
836 } \
837
838 #define arm_data_proc_test_add(src_a, src_b, type) \
839 { \
840 arm_pc_offset(8); \
841 arm_data_proc_##type(); \
842 flags_vars(src_a, src_b); \
843 dest = _sa + _sb; \
844 calculate_flags_add(dest, _sa, _sb); \
845 arm_pc_offset(-4); \
846 } \
847
848 #define arm_data_proc_test_sub(src_a, src_b, type) \
849 { \
850 arm_pc_offset(8); \
851 arm_data_proc_##type(); \
852 flags_vars(src_a, src_b); \
853 dest = _sa - _sb; \
854 calculate_flags_sub(dest, _sa, _sb); \
855 arm_pc_offset(-4); \
856 } \
857
858 #define arm_multiply_flags_yes(_dest) \
859 calculate_z_flag(_dest); \
860 calculate_n_flag(_dest); \
861
862 #define arm_multiply_flags_no(_dest) \
863
864 #define arm_multiply_long_flags_yes(_dest_lo, _dest_hi) \
865 z_flag = (_dest_lo == 0) & (_dest_hi == 0); \
866 calculate_n_flag(_dest_hi) \
867
868 #define arm_multiply_long_flags_no(_dest_lo, _dest_hi) \
869
870 #define arm_multiply(add_op, flags) \
871 { \
872 u32 dest; \
873 arm_decode_multiply(); \
874 dest = (reg[rm] * reg[rs]) add_op; \
875 arm_multiply_flags_##flags(dest); \
876 reg[rd] = dest; \
877 arm_pc_offset(4); \
878 } \
879
880 #define arm_multiply_long_addop(type) \
881 + ((type##64)((((type##64)reg[rdhi]) << 32) | reg[rdlo])); \
882
883 #define arm_multiply_long(add_op, flags, type) \
884 { \
885 type##64 dest; \
886 u32 dest_lo; \
887 u32 dest_hi; \
888 arm_decode_multiply_long(); \
889 dest = ((type##64)((type##32)reg[rm]) * \
890 (type##64)((type##32)reg[rn])) add_op; \
891 dest_lo = (u32)dest; \
892 dest_hi = (u32)(dest >> 32); \
893 arm_multiply_long_flags_##flags(dest_lo, dest_hi); \
894 reg[rdlo] = dest_lo; \
895 reg[rdhi] = dest_hi; \
896 arm_pc_offset(4); \
897 } \
898
899 const u32 psr_masks[16] =
900 {
901 0x00000000, 0x000000FF, 0x0000FF00, 0x0000FFFF, 0x00FF0000,
902 0x00FF00FF, 0x00FFFF00, 0x00FFFFFF, 0xFF000000, 0xFF0000FF,
903 0xFF00FF00, 0xFF00FFFF, 0xFFFF0000, 0xFFFF00FF, 0xFFFFFF00,
904 0xFFFFFFFF
905 };
906
907 #define arm_psr_read(dummy, psr_reg) \
908 collapse_flags(); \
909 reg[rd] = psr_reg \
910
911 #define arm_psr_store_cpsr(source) \
912 reg[REG_CPSR] = (source & store_mask) | (reg[REG_CPSR] & (~store_mask)); \
913 extract_flags(); \
914 if(store_mask & 0xFF) \
915 { \
916 set_cpu_mode(cpu_modes[reg[REG_CPSR] & 0x1F]); \
917 check_for_interrupts(); \
918 } \
919
920 #define arm_psr_store_spsr(source) \
921 u32 _psr = spsr[reg[CPU_MODE]]; \
922 spsr[reg[CPU_MODE]] = (source & store_mask) | (_psr & (~store_mask)) \
923
924 #define arm_psr_store(source, psr_reg) \
925 const u32 store_mask = psr_masks[psr_field]; \
926 arm_psr_store_##psr_reg(source) \
927
928 #define arm_psr_src_reg reg[rm]
929
930 #define arm_psr_src_imm imm
931
932 #define arm_psr(op_type, transfer_type, psr_reg) \
933 { \
934 arm_decode_psr_##op_type(opcode); \
935 arm_pc_offset(4); \
936 arm_psr_##transfer_type(arm_psr_src_##op_type, psr_reg); \
937 } \
938
939 #define arm_data_trans_reg() \
940 arm_decode_data_trans_reg(); \
941 calculate_reg_offset() \
942
943 #define arm_data_trans_imm() \
944 arm_decode_data_trans_imm() \
945
946 #define arm_data_trans_half_reg() \
947 arm_decode_half_trans_r() \
948
949 #define arm_data_trans_half_imm() \
950 arm_decode_half_trans_of() \
951
952 #define aligned_address_mask8 0xF0000000
953 #define aligned_address_mask16 0xF0000001
954 #define aligned_address_mask32 0xF0000003
955
956 #define fast_read_memory(size, type, address, dest) \
957 { \
958 u8 *map; \
959 u32 _address = address; \
960 \
961 if(_address < 0x10000000) \
962 { \
963 memory_region_access_read_##type[_address >> 24]++; \
964 memory_reads_##type++; \
965 } \
966 if(((_address >> 24) == 0) && (pc >= 0x4000)) \
967 { \
968 dest = *((type *)((u8 *)&bios_read_protect + (_address & 0x03))); \
969 } \
970 else \
971 \
972 if(((_address & aligned_address_mask##size) == 0) && \
973 (map = memory_map_read[_address >> 15])) \
974 { \
975 dest = *((type *)((u8 *)map + (_address & 0x7FFF))); \
976 } \
977 else \
978 { \
979 dest = (type)read_memory##size(_address); \
980 } \
981 } \
982
983 #define fast_read_memory_s16(address, dest) \
984 { \
985 u8 *map; \
986 u32 _address = address; \
987 if(_address < 0x10000000) \
988 { \
989 memory_region_access_read_s16[_address >> 24]++; \
990 memory_reads_s16++; \
991 } \
992 if(((_address & aligned_address_mask16) == 0) && \
993 (map = memory_map_read[_address >> 15])) \
994 { \
995 dest = *((s16 *)((u8 *)map + (_address & 0x7FFF))); \
996 } \
997 else \
998 { \
999 dest = (s16)read_memory16_signed(_address); \
1000 } \
1001 } \
1002
1003
1004 #define fast_write_memory(size, type, address, value) \
1005 { \
1006 u8 *map; \
1007 u32 _address = (address) & ~(aligned_address_mask##size & 0x03); \
1008 if(_address < 0x10000000) \
1009 { \
1010 memory_region_access_write_##type[_address >> 24]++; \
1011 memory_writes_##type++; \
1012 } \
1013 \
1014 if(((_address & aligned_address_mask##size) == 0) && \
1015 (map = memory_map_write[_address >> 15])) \
1016 { \
1017 *((type *)((u8 *)map + (_address & 0x7FFF))) = value; \
1018 } \
1019 else \
1020 { \
1021 cpu_alert = write_memory##size(_address, value); \
1022 if(cpu_alert) \
1023 goto alert; \
1024 } \
1025 } \
1026
1027 #define load_aligned32(address, dest) \
1028 { \
1029 u32 _address = address; \
1030 u8 *map = memory_map_read[_address >> 15]; \
1031 if(_address < 0x10000000) \
1032 { \
1033 memory_region_access_read_u32[_address >> 24]++; \
1034 memory_reads_u32++; \
1035 } \
1036 if(map) \
1037 { \
1038 dest = address32(map, _address & 0x7FFF); \
1039 } \
1040 else \
1041 { \
1042 dest = read_memory32(_address); \
1043 } \
1044 } \
1045
1046 #define store_aligned32(address, value) \
1047 { \
1048 u32 _address = address; \
1049 u8 *map = memory_map_write[_address >> 15]; \
1050 if(_address < 0x10000000) \
1051 { \
1052 memory_region_access_write_u32[_address >> 24]++; \
1053 memory_writes_u32++; \
1054 } \
1055 if(map) \
1056 { \
1057 address32(map, _address & 0x7FFF) = value; \
1058 } \
1059 else \
1060 { \
1061 cpu_alert = write_memory32(_address, value); \
1062 if(cpu_alert) \
1063 goto alert; \
1064 } \
1065 } \
1066
1067 #define load_memory_u8(address, dest) \
1068 fast_read_memory(8, u8, address, dest) \
1069
1070 #define load_memory_u16(address, dest) \
1071 fast_read_memory(16, u16, address, dest) \
1072
1073 #define load_memory_u32(address, dest) \
1074 fast_read_memory(32, u32, address, dest) \
1075
1076 #define load_memory_s8(address, dest) \
1077 fast_read_memory(8, s8, address, dest) \
1078
1079 #define load_memory_s16(address, dest) \
1080 fast_read_memory_s16(address, dest) \
1081
1082 #define store_memory_u8(address, value) \
1083 fast_write_memory(8, u8, address, value) \
1084
1085 #define store_memory_u16(address, value) \
1086 fast_write_memory(16, u16, address, value) \
1087
1088 #define store_memory_u32(address, value) \
1089 fast_write_memory(32, u32, address, value) \
1090
1091 #define no_op \
1092
1093 #define arm_access_memory_writeback_yes(off_op) \
1094 reg[rn] = address off_op \
1095
1096 #define arm_access_memory_writeback_no(off_op) \
1097
1098 #define arm_access_memory_pc_preadjust_load() \
1099
1100 #define arm_access_memory_pc_preadjust_store() \
1101 u32 reg_op = reg[rd]; \
1102 if(rd == 15) \
1103 reg_op += 4 \
1104
1105 #define arm_access_memory_pc_postadjust_load() \
1106 arm_update_pc() \
1107
1108 #define arm_access_memory_pc_postadjust_store() \
1109
1110 #define load_reg_op reg[rd] \
1111
1112 #define store_reg_op reg_op \
1113
1114 #define arm_access_memory(access_type, off_op, off_type, mem_type, \
1115 wb, wb_off_op) \
1116 { \
1117 arm_pc_offset(8); \
1118 arm_data_trans_##off_type(); \
1119 u32 address = reg[rn] off_op; \
1120 arm_access_memory_pc_preadjust_##access_type(); \
1121 \
1122 arm_pc_offset(-4); \
1123 arm_access_memory_writeback_##wb(wb_off_op); \
1124 access_type##_memory_##mem_type(address, access_type##_reg_op); \
1125 arm_access_memory_pc_postadjust_##access_type(); \
1126 } \
1127
1128 #define word_bit_count(word) \
1129 (bit_count[word >> 8] + bit_count[word & 0xFF]) \
1130
1131 #define sprint_no(access_type, offset_type, writeback_type) \
1132
1133 #define sprint_yes(access_type, offset_type, writeback_type) \
1134 printf("sbit on %s %s %s\n", #access_type, #offset_type, #writeback_type) \
1135
1136 #define arm_block_writeback_load() \
1137 if(!((reg_list >> rn) & 0x01)) \
1138 { \
1139 reg[rn] = address; \
1140 } \
1141
1142 #define arm_block_writeback_store() \
1143 reg[rn] = address \
1144
1145 #define arm_block_writeback_yes(access_type) \
1146 arm_block_writeback_##access_type() \
1147
1148 #define arm_block_writeback_no(access_type) \
1149
1150 #define load_block_memory(address, dest) \
1151 dest = address32(address_region, (address + offset) & 0x7FFF) \
1152
1153 #define store_block_memory(address, dest) \
1154 address32(address_region, (address + offset) & 0x7FFF) = dest \
1155
1156 #define arm_block_memory_offset_down_a() \
1157 (base - (word_bit_count(reg_list) * 4) + 4) \
1158
1159 #define arm_block_memory_offset_down_b() \
1160 (base - (word_bit_count(reg_list) * 4)) \
1161
1162 #define arm_block_memory_offset_no() \
1163 (base) \
1164
1165 #define arm_block_memory_offset_up() \
1166 (base + 4) \
1167
1168 #define arm_block_memory_writeback_down() \
1169 reg[rn] = base - (word_bit_count(reg_list) * 4) \
1170
1171 #define arm_block_memory_writeback_up() \
1172 reg[rn] = base + (word_bit_count(reg_list) * 4) \
1173
1174 #define arm_block_memory_writeback_no() \
1175
1176 #define arm_block_memory_load_pc() \
1177 load_aligned32(address, pc); \
1178 reg[REG_PC] = pc \
1179
1180 #define arm_block_memory_store_pc() \
1181 store_aligned32(address, pc + 4) \
1182
1183 #define arm_block_memory(access_type, offset_type, writeback_type, s_bit) \
1184 { \
1185 arm_decode_block_trans(); \
1186 u32 base = reg[rn]; \
1187 u32 address = arm_block_memory_offset_##offset_type() & 0xFFFFFFFC; \
1188 u32 i; \
1189 \
1190 arm_block_memory_writeback_##writeback_type(); \
1191 \
1192 for(i = 0; i < 15; i++) \
1193 { \
1194 if((reg_list >> i) & 0x01) \
1195 { \
1196 access_type##_aligned32(address, reg[i]); \
1197 address += 4; \
1198 } \
1199 } \
1200 \
1201 arm_pc_offset(4); \
1202 if(reg_list & 0x8000) \
1203 { \
1204 arm_block_memory_##access_type##_pc(); \
1205 } \
1206 } \
1207
1208 #define arm_swap(type) \
1209 { \
1210 arm_decode_swap(); \
1211 u32 temp; \
1212 load_memory_##type(reg[rn], temp); \
1213 store_memory_##type(reg[rn], reg[rm]); \
1214 reg[rd] = temp; \
1215 arm_pc_offset(4); \
1216 } \
1217
1218 #define arm_next_instruction() \
1219 { \
1220 arm_pc_offset(4); \
1221 goto skip_instruction; \
1222 } \
1223
1224 #define thumb_update_pc() \
1225 pc = reg[REG_PC] \
1226
1227 #define thumb_pc_offset(val) \
1228 pc += val; \
1229 reg[REG_PC] = pc \
1230
1231 #define thumb_pc_offset_update(val) \
1232 pc += val; \
1233 reg[REG_PC] = pc \
1234
1235 #define thumb_pc_offset_update_direct(val) \
1236 pc = val; \
1237 reg[REG_PC] = pc \
1238
1239 // Types: add_sub, add_sub_imm, alu_op, imm
1240 // Affects N/Z/C/V flags
1241
1242 #define thumb_add(type, dest_reg, src_a, src_b) \
1243 { \
1244 thumb_decode_##type(); \
1245 const u32 _sa = src_a; \
1246 const u32 _sb = src_b; \
1247 u32 dest = _sa + _sb; \
1248 calculate_flags_add(dest, _sa, _sb); \
1249 reg[dest_reg] = dest; \
1250 thumb_pc_offset(2); \
1251 } \
1252
1253 #define thumb_add_noflags(type, dest_reg, src_a, src_b) \
1254 { \
1255 thumb_decode_##type(); \
1256 u32 dest = (src_a) + (src_b); \
1257 reg[dest_reg] = dest; \
1258 thumb_pc_offset(2); \
1259 } \
1260
1261 #define thumb_sub(type, dest_reg, src_a, src_b) \
1262 { \
1263 thumb_decode_##type(); \
1264 const u32 _sa = src_a; \
1265 const u32 _sb = src_b; \
1266 u32 dest = _sa - _sb; \
1267 calculate_flags_sub(dest, _sa, _sb); \
1268 reg[dest_reg] = dest; \
1269 thumb_pc_offset(2); \
1270 } \
1271
1272 // Affects N/Z flags
1273
1274 #define thumb_logic(type, dest_reg, expr) \
1275 { \
1276 thumb_decode_##type(); \
1277 u32 dest = expr; \
1278 calculate_flags_logic(dest); \
1279 reg[dest_reg] = dest; \
1280 thumb_pc_offset(2); \
1281 } \
1282
1283 // Decode types: shift, alu_op
1284 // Operation types: lsl, lsr, asr, ror
1285 // Affects N/Z/C flags
1286
1287 #define thumb_shift_lsl_reg() \
1288 u32 shift = reg[rs]; \
1289 u32 dest = reg[rd]; \
1290 if(shift != 0) \
1291 { \
1292 if(shift > 31) \
1293 { \
1294 if(shift == 32) \
1295 c_flag = dest & 0x01; \
1296 else \
1297 c_flag = 0; \
1298 dest = 0; \
1299 } \
1300 else \
1301 { \
1302 c_flag = (dest >> (32 - shift)) & 0x01; \
1303 dest <<= shift; \
1304 } \
1305 } \
1306
1307 #define thumb_shift_lsr_reg() \
1308 u32 shift = reg[rs]; \
1309 u32 dest = reg[rd]; \
1310 if(shift != 0) \
1311 { \
1312 if(shift > 31) \
1313 { \
1314 if(shift == 32) \
1315 c_flag = dest >> 31; \
1316 else \
1317 c_flag = 0; \
1318 dest = 0; \
1319 } \
1320 else \
1321 { \
1322 c_flag = (dest >> (shift - 1)) & 0x01; \
1323 dest >>= shift; \
1324 } \
1325 } \
1326
1327 #define thumb_shift_asr_reg() \
1328 u32 shift = reg[rs]; \
1329 u32 dest = reg[rd]; \
1330 if(shift != 0) \
1331 { \
1332 if(shift > 31) \
1333 { \
1334 dest = (s32)dest >> 31; \
1335 c_flag = dest & 0x01; \
1336 } \
1337 else \
1338 { \
1339 c_flag = (dest >> (shift - 1)) & 0x01; \
1340 dest = (s32)dest >> shift; \
1341 } \
1342 } \
1343
1344 #define thumb_shift_ror_reg() \
1345 u32 shift = reg[rs]; \
1346 u32 dest = reg[rd]; \
1347 if(shift != 0) \
1348 { \
1349 c_flag = (dest >> (shift - 1)) & 0x01; \
1350 ror(dest, dest, shift); \
1351 } \
1352
1353 #define thumb_shift_lsl_imm() \
1354 u32 dest = reg[rs]; \
1355 if(imm != 0) \
1356 { \
1357 c_flag = (dest >> (32 - imm)) & 0x01; \
1358 dest <<= imm; \
1359 } \
1360
1361 #define thumb_shift_lsr_imm() \
1362 u32 dest; \
1363 if(imm == 0) \
1364 { \
1365 dest = 0; \
1366 c_flag = reg[rs] >> 31; \
1367 } \
1368 else \
1369 { \
1370 dest = reg[rs]; \
1371 c_flag = (dest >> (imm - 1)) & 0x01; \
1372 dest >>= imm; \
1373 } \
1374
1375 #define thumb_shift_asr_imm() \
1376 u32 dest; \
1377 if(imm == 0) \
1378 { \
1379 dest = (s32)reg[rs] >> 31; \
1380 c_flag = dest & 0x01; \
1381 } \
1382 else \
1383 { \
1384 dest = reg[rs]; \
1385 c_flag = (dest >> (imm - 1)) & 0x01; \
1386 dest = (s32)dest >> imm; \
1387 } \
1388
1389 #define thumb_shift_ror_imm() \
1390 u32 dest = reg[rs]; \
1391 if(imm == 0) \
1392 { \
1393 u32 old_c_flag = c_flag; \
1394 c_flag = dest & 0x01; \
1395 dest = (dest >> 1) | (old_c_flag << 31); \
1396 } \
1397 else \
1398 { \
1399 c_flag = (dest >> (imm - 1)) & 0x01; \
1400 ror(dest, dest, imm); \
1401 } \
1402
1403 #define thumb_shift(decode_type, op_type, value_type) \
1404 { \
1405 thumb_decode_##decode_type(); \
1406 thumb_shift_##op_type##_##value_type(); \
1407 calculate_flags_logic(dest); \
1408 reg[rd] = dest; \
1409 thumb_pc_offset(2); \
1410 } \
1411
1412 #define thumb_test_add(type, src_a, src_b) \
1413 { \
1414 thumb_decode_##type(); \
1415 const u32 _sa = src_a; \
1416 const u32 _sb = src_b; \
1417 u32 dest = _sa + _sb; \
1418 calculate_flags_add(dest, src_a, src_b); \
1419 thumb_pc_offset(2); \
1420 } \
1421
1422 #define thumb_test_sub(type, src_a, src_b) \
1423 { \
1424 thumb_decode_##type(); \
1425 const u32 _sa = src_a; \
1426 const u32 _sb = src_b; \
1427 u32 dest = _sa - _sb; \
1428 calculate_flags_sub(dest, src_a, src_b); \
1429 thumb_pc_offset(2); \
1430 } \
1431
1432 #define thumb_test_logic(type, expr) \
1433 { \
1434 thumb_decode_##type(); \
1435 u32 dest = expr; \
1436 calculate_flags_logic(dest); \
1437 thumb_pc_offset(2); \
1438 }
1439
1440 #define thumb_hireg_op(expr) \
1441 { \
1442 thumb_pc_offset(4); \
1443 thumb_decode_hireg_op(); \
1444 u32 dest = expr; \
1445 thumb_pc_offset(-2); \
1446 if(rd == 15) \
1447 { \
1448 reg[REG_PC] = dest & ~0x01; \
1449 thumb_update_pc(); \
1450 } \
1451 else \
1452 { \
1453 reg[rd] = dest; \
1454 } \
1455 } \
1456
1457 // Operation types: imm, mem_reg, mem_imm
1458
1459 #define thumb_access_memory(access_type, op_type, address, reg_op, \
1460 mem_type) \
1461 { \
1462 thumb_decode_##op_type(); \
1463 access_type##_memory_##mem_type(address, reg_op); \
1464 thumb_pc_offset(2); \
1465 } \
1466
1467 #define thumb_block_address_preadjust_no_op() \
1468
1469 #define thumb_block_address_preadjust_up() \
1470 address += bit_count[reg_list] * 4 \
1471
1472 #define thumb_block_address_preadjust_down() \
1473 address -= bit_count[reg_list] * 4 \
1474
1475 #define thumb_block_address_preadjust_push_lr() \
1476 address -= (bit_count[reg_list] + 1) * 4 \
1477
1478 #define thumb_block_address_postadjust_no_op() \
1479
1480 #define thumb_block_address_postadjust_up() \
1481 address += offset \
1482
1483 #define thumb_block_address_postadjust_down() \
1484 address -= offset \
1485
1486 #define thumb_block_address_postadjust_pop_pc() \
1487 load_memory_u32(address + offset, pc); \
1488 pc &= ~0x01; \
1489 reg[REG_PC] = pc; \
1490 address += offset + 4 \
1491
1492 #define thumb_block_address_postadjust_push_lr() \
1493 store_memory_u32(address + offset, reg[REG_LR]); \
1494
1495 #define thumb_block_memory_wb_load(base_reg) \
1496 if(!((reg_list >> base_reg) & 0x01)) \
1497 { \
1498 reg[base_reg] = address; \
1499 } \
1500
1501 #define thumb_block_memory_wb_store(base_reg) \
1502 reg[base_reg] = address \
1503
1504 #define thumb_block_memory(access_type, pre_op, post_op, base_reg) \
1505 { \
1506 u32 i; \
1507 u32 offset = 0; \
1508 thumb_decode_rlist(); \
1509 using_register(thumb, base_reg, memory_base); \
1510 u32 address = reg[base_reg] & ~0x03; \
1511 thumb_block_address_preadjust_##pre_op(); \
1512 \
1513 for(i = 0; i < 8; i++) \
1514 { \
1515 if((reg_list >> i) & 1) \
1516 { \
1517 access_type##_aligned32(address + offset, reg[i]); \
1518 offset += 4; \
1519 } \
1520 } \
1521 \
1522 thumb_pc_offset(2); \
1523 \
1524 thumb_block_address_postadjust_##post_op(); \
1525 thumb_block_memory_wb_##access_type(base_reg); \
1526 } \
1527
1528 #define thumb_conditional_branch(condition) \
1529 { \
1530 thumb_decode_branch_cond(); \
1531 if(condition) \
1532 { \
1533 thumb_pc_offset((offset * 2) + 4); \
1534 } \
1535 else \
1536 { \
1537 thumb_pc_offset(2); \
1538 } \
1539 } \
1540
1541 // When a mode change occurs from non-FIQ to non-FIQ retire the current
1542 // reg[13] and reg[14] into reg_mode[cpu_mode][5] and reg_mode[cpu_mode][6]
1543 // respectively and load into reg[13] and reg[14] reg_mode[new_mode][5] and
1544 // reg_mode[new_mode][6]. When swapping to/from FIQ retire/load reg[8]
1545 // through reg[14] to/from reg_mode[MODE_FIQ][0] through reg_mode[MODE_FIQ][6].
1546
1547 u32 reg_mode[7][7];
1548
1549 u32 cpu_modes[32] =
1550 {
1551 MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID,
1552 MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID,
1553 MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID, MODE_INVALID,
1554 MODE_INVALID, MODE_USER, MODE_FIQ, MODE_IRQ, MODE_SUPERVISOR, MODE_INVALID,
1555 MODE_INVALID, MODE_INVALID, MODE_ABORT, MODE_INVALID, MODE_INVALID,
1556 MODE_INVALID, MODE_INVALID, MODE_UNDEFINED, MODE_INVALID, MODE_INVALID,
1557 MODE_USER
1558 };
1559
1560 u32 cpu_modes_cpsr[7] = { 0x10, 0x11, 0x12, 0x13, 0x17, 0x1B, 0x1F };
1561
1562 // When switching modes set spsr[new_mode] to cpsr. Modifying PC as the
1563 // target of a data proc instruction will set cpsr to spsr[cpu_mode].
1564
1565 u32 initial_reg[64];
1566 u32 *reg = initial_reg;
1567 u32 spsr[6];
1568
1569 // ARM/Thumb mode is stored in the flags directly, this is simpler than
1570 // shadowing it since it has a constant 1bit represenation.
1571
1572 char *reg_names[16] =
1573 {
1574 " r0", " r1", " r2", " r3", " r4", " r5", " r6", " r7",
1575 " r8", " r9", "r10", " fp", " ip", " sp", " lr", " pc"
1576 };
1577
1578 char *cpu_mode_names[] =
1579 {
1580 "user", "irq", "fiq", "svsr", "abrt", "undf", "invd"
1581 };
1582
1583 u32 instruction_count = 0;
1584
1585 u32 output_field = 0;
1586 const u32 num_output_fields = 2;
1587
1588 u32 last_instruction = 0;
1589
1590 u32 in_interrupt = 0;
1591
set_cpu_mode(cpu_mode_type new_mode)1592 void set_cpu_mode(cpu_mode_type new_mode)
1593 {
1594 u32 i;
1595 cpu_mode_type cpu_mode = reg[CPU_MODE];
1596
1597 if(cpu_mode == new_mode)
1598 return;
1599
1600 if(new_mode == MODE_FIQ)
1601 {
1602 for(i = 8; i < 15; i++)
1603 reg_mode[cpu_mode][i - 8] = reg[i];
1604 }
1605 else
1606 {
1607 reg_mode[cpu_mode][5] = reg[REG_SP];
1608 reg_mode[cpu_mode][6] = reg[REG_LR];
1609 }
1610
1611 if(cpu_mode == MODE_FIQ)
1612 {
1613 for(i = 8; i < 15; i++)
1614 reg[i] = reg_mode[new_mode][i - 8];
1615 }
1616 else
1617 {
1618 reg[REG_SP] = reg_mode[new_mode][5];
1619 reg[REG_LR] = reg_mode[new_mode][6];
1620 }
1621
1622 reg[CPU_MODE] = new_mode;
1623 }
1624
raise_interrupt(irq_type irq_raised)1625 void raise_interrupt(irq_type irq_raised)
1626 {
1627 // The specific IRQ must be enabled in IE, master IRQ enable must be on,
1628 // and it must be on in the flags.
1629 io_registers[REG_IF] |= irq_raised;
1630
1631 if((io_registers[REG_IE] & irq_raised) && io_registers[REG_IME] &&
1632 ((reg[REG_CPSR] & 0x80) == 0))
1633 {
1634 bios_read_protect = 0xe55ec002;
1635
1636 // Interrupt handler in BIOS
1637 reg_mode[MODE_IRQ][6] = reg[REG_PC] + 4;
1638 spsr[MODE_IRQ] = reg[REG_CPSR];
1639 reg[REG_CPSR] = 0xD2;
1640 reg[REG_PC] = 0x00000018;
1641
1642 bios_region_read_allow();
1643
1644 set_cpu_mode(MODE_IRQ);
1645 reg[CPU_HALT_STATE] = CPU_ACTIVE;
1646 reg[CHANGED_PC_STATUS] = 1;
1647 }
1648 }
1649
1650 #ifndef HAVE_DYNAREC
1651 u8 *memory_map_read [8 * 1024];
1652 u8 *memory_map_write[8 * 1024];
1653 #endif
1654
execute_arm(u32 cycles)1655 void execute_arm(u32 cycles)
1656 {
1657 u32 pc = reg[REG_PC];
1658 u32 opcode;
1659 u32 condition;
1660 u32 n_flag, z_flag, c_flag, v_flag;
1661 u32 pc_region = (pc >> 15);
1662 u8 *pc_address_block = memory_map_read[pc_region];
1663 u32 new_pc_region;
1664 s32 cycles_remaining;
1665 u32 cycles_per_instruction = global_cycles_per_instruction;
1666 cpu_alert_type cpu_alert;
1667
1668 u32 old_pc;
1669
1670 (void)old_pc;
1671
1672 if(!pc_address_block)
1673 pc_address_block = load_gamepak_page(pc_region & 0x3FF);
1674
1675 while(1)
1676 {
1677 cycles_remaining = cycles;
1678 pc = reg[REG_PC];
1679 extract_flags();
1680
1681 if(reg[REG_CPSR] & 0x20)
1682 goto thumb_loop;
1683
1684 do
1685 {
1686 arm_loop:
1687
1688 collapse_flags();
1689 cycles_per_instruction = global_cycles_per_instruction;
1690
1691 old_pc = pc;
1692
1693 /* Execute ARM instruction */
1694 using_instruction(arm);
1695 check_pc_region();
1696 pc &= ~0x03;
1697 opcode = address32(pc_address_block, (pc & 0x7FFF));
1698 condition = opcode >> 28;
1699
1700 switch(condition)
1701 {
1702 case 0x0:
1703 /* EQ */
1704 if(!z_flag)
1705 arm_next_instruction();
1706 break;
1707 case 0x1:
1708 /* NE */
1709 if(z_flag)
1710 arm_next_instruction();
1711 break;
1712 case 0x2:
1713 /* CS */
1714 if(!c_flag)
1715 arm_next_instruction();
1716 break;
1717 case 0x3:
1718 /* CC */
1719 if(c_flag)
1720 arm_next_instruction();
1721 break;
1722 case 0x4:
1723 /* MI */
1724 if(!n_flag)
1725 arm_next_instruction();
1726 break;
1727
1728 case 0x5:
1729 /* PL */
1730 if(n_flag)
1731 arm_next_instruction();
1732 break;
1733
1734 case 0x6:
1735 /* VS */
1736 if(!v_flag)
1737 arm_next_instruction();
1738 break;
1739
1740 case 0x7:
1741 /* VC */
1742 if(v_flag)
1743 arm_next_instruction();
1744 break;
1745
1746 case 0x8:
1747 /* HI */
1748 if((c_flag == 0) | z_flag)
1749 arm_next_instruction();
1750 break;
1751
1752 case 0x9:
1753 /* LS */
1754 if(c_flag & (z_flag ^ 1))
1755 arm_next_instruction();
1756 break;
1757
1758 case 0xA:
1759 /* GE */
1760 if(n_flag != v_flag)
1761 arm_next_instruction();
1762 break;
1763
1764 case 0xB:
1765 /* LT */
1766 if(n_flag == v_flag)
1767 arm_next_instruction();
1768 break;
1769
1770 case 0xC:
1771 /* GT */
1772 if(z_flag | (n_flag != v_flag))
1773 arm_next_instruction();
1774 break;
1775
1776 case 0xD:
1777 /* LE */
1778 if((z_flag == 0) & (n_flag == v_flag))
1779 arm_next_instruction();
1780 break;
1781
1782 case 0xE:
1783 /* AL */
1784 break;
1785
1786 case 0xF:
1787 /* Reserved - treat as "never" */
1788 arm_next_instruction();
1789 break;
1790 }
1791
1792 switch((opcode >> 20) & 0xFF)
1793 {
1794 case 0x00:
1795 if((opcode & 0x90) == 0x90)
1796 {
1797 if(opcode & 0x20)
1798 {
1799 /* STRH rd, [rn], -rm */
1800 arm_access_memory(store, no_op, half_reg, u16, yes, - reg[rm]);
1801 }
1802 else
1803 {
1804 /* MUL rd, rm, rs */
1805 arm_multiply(no_op, no);
1806 }
1807 }
1808 else
1809 {
1810 /* AND rd, rn, reg_op */
1811 arm_data_proc(reg[rn] & reg_sh, reg);
1812 }
1813 break;
1814
1815 case 0x01:
1816 if((opcode & 0x90) == 0x90)
1817 {
1818 switch((opcode >> 5) & 0x03)
1819 {
1820 case 0:
1821 /* MULS rd, rm, rs */
1822 arm_multiply(no_op, yes);
1823 break;
1824
1825 case 1:
1826 /* LDRH rd, [rn], -rm */
1827 arm_access_memory(load, no_op, half_reg, u16, yes, - reg[rm]);
1828 break;
1829
1830 case 2:
1831 /* LDRSB rd, [rn], -rm */
1832 arm_access_memory(load, no_op, half_reg, s8, yes, - reg[rm]);
1833 break;
1834
1835 case 3:
1836 /* LDRSH rd, [rn], -rm */
1837 arm_access_memory(load, no_op, half_reg, s16, yes, - reg[rm]);
1838 break;
1839 }
1840 }
1841 else
1842 {
1843 /* ANDS rd, rn, reg_op */
1844 arm_data_proc_logic_flags(reg[rn] & reg_sh, reg);
1845 }
1846 break;
1847
1848 case 0x02:
1849 if((opcode & 0x90) == 0x90)
1850 {
1851 if(opcode & 0x20)
1852 {
1853 /* STRH rd, [rn], -rm */
1854 arm_access_memory(store, no_op, half_reg, u16, yes, - reg[rm]);
1855 }
1856 else
1857 {
1858 /* MLA rd, rm, rs, rn */
1859 arm_multiply(+ reg[rn], no);
1860 }
1861 }
1862 else
1863 {
1864 /* EOR rd, rn, reg_op */
1865 arm_data_proc(reg[rn] ^ reg_sh, reg);
1866 }
1867 break;
1868
1869 case 0x03:
1870 if((opcode & 0x90) == 0x90)
1871 {
1872 switch((opcode >> 5) & 0x03)
1873 {
1874 case 0:
1875 /* MLAS rd, rm, rs, rn */
1876 arm_multiply(+ reg[rn], yes);
1877 break;
1878
1879 case 1:
1880 /* LDRH rd, [rn], -rm */
1881 arm_access_memory(load, no_op, half_reg, u16, yes, - reg[rm]);
1882 break;
1883
1884 case 2:
1885 /* LDRSB rd, [rn], -rm */
1886 arm_access_memory(load, no_op, half_reg, s8, yes, - reg[rm]);
1887 break;
1888
1889 case 3:
1890 /* LDRSH rd, [rn], -rm */
1891 arm_access_memory(load, no_op, half_reg, s16, yes, - reg[rm]);
1892 break;
1893 }
1894 }
1895 else
1896 {
1897 /* EORS rd, rn, reg_op */
1898 arm_data_proc_logic_flags(reg[rn] ^ reg_sh, reg);
1899 }
1900 break;
1901
1902 case 0x04:
1903 if((opcode & 0x90) == 0x90)
1904 {
1905 /* STRH rd, [rn], -imm */
1906 arm_access_memory(store, no_op, half_imm, u16, yes, - offset);
1907 }
1908 else
1909 {
1910 /* SUB rd, rn, reg_op */
1911 arm_data_proc(reg[rn] - reg_sh, reg);
1912 }
1913 break;
1914
1915 case 0x05:
1916 if((opcode & 0x90) == 0x90)
1917 {
1918 switch((opcode >> 5) & 0x03)
1919 {
1920 case 1:
1921 /* LDRH rd, [rn], -imm */
1922 arm_access_memory(load, no_op, half_imm, u16, yes, - offset);
1923 break;
1924
1925 case 2:
1926 /* LDRSB rd, [rn], -imm */
1927 arm_access_memory(load, no_op, half_imm, s8, yes, - offset);
1928 break;
1929
1930 case 3:
1931 /* LDRSH rd, [rn], -imm */
1932 arm_access_memory(load, no_op, half_imm, s16, yes, - offset);
1933 break;
1934 }
1935 }
1936 else
1937 {
1938 /* SUBS rd, rn, reg_op */
1939 arm_data_proc_sub_flags(reg[rn], reg_sh, reg);
1940 }
1941 break;
1942
1943 case 0x06:
1944 if((opcode & 0x90) == 0x90)
1945 {
1946 /* STRH rd, [rn], -imm */
1947 arm_access_memory(store, no_op, half_imm, u16, yes, - offset);
1948 }
1949 else
1950 {
1951 /* RSB rd, rn, reg_op */
1952 arm_data_proc(reg_sh - reg[rn], reg);
1953 }
1954 break;
1955
1956 case 0x07:
1957 if((opcode & 0x90) == 0x90)
1958 {
1959 switch((opcode >> 5) & 0x03)
1960 {
1961 case 1:
1962 /* LDRH rd, [rn], -imm */
1963 arm_access_memory(load, no_op, half_imm, u16, yes, - offset);
1964 break;
1965
1966 case 2:
1967 /* LDRSB rd, [rn], -imm */
1968 arm_access_memory(load, no_op, half_imm, s8, yes, - offset);
1969 break;
1970
1971 case 3:
1972 /* LDRSH rd, [rn], -imm */
1973 arm_access_memory(load, no_op, half_imm, s16, yes, - offset);
1974 break;
1975 }
1976 }
1977 else
1978 {
1979 /* RSBS rd, rn, reg_op */
1980 arm_data_proc_sub_flags(reg_sh, reg[rn], reg);
1981 }
1982 break;
1983
1984 case 0x08:
1985 if((opcode & 0x90) == 0x90)
1986 {
1987 if(opcode & 0x20)
1988 {
1989 /* STRH rd, [rn], +rm */
1990 arm_access_memory(store, no_op, half_reg, u16, yes, + reg[rm]);
1991 }
1992 else
1993 {
1994 /* UMULL rd, rm, rs */
1995 arm_multiply_long(no_op, no, u);
1996 }
1997 }
1998 else
1999 {
2000 /* ADD rd, rn, reg_op */
2001 arm_data_proc(reg[rn] + reg_sh, reg);
2002 }
2003 break;
2004
2005 case 0x09:
2006 if((opcode & 0x90) == 0x90)
2007 {
2008 switch((opcode >> 5) & 0x03)
2009 {
2010 case 0:
2011 /* UMULLS rdlo, rdhi, rm, rs */
2012 arm_multiply_long(no_op, yes, u);
2013 break;
2014
2015 case 1:
2016 /* LDRH rd, [rn], +rm */
2017 arm_access_memory(load, no_op, half_reg, u16, yes, + reg[rm]);
2018 break;
2019
2020 case 2:
2021 /* LDRSB rd, [rn], +rm */
2022 arm_access_memory(load, no_op, half_reg, s8, yes, + reg[rm]);
2023 break;
2024
2025 case 3:
2026 /* LDRSH rd, [rn], +rm */
2027 arm_access_memory(load, no_op, half_reg, s16, yes, + reg[rm]);
2028 break;
2029 }
2030 }
2031 else
2032 {
2033 /* ADDS rd, rn, reg_op */
2034 arm_data_proc_add_flags(reg[rn], reg_sh, reg);
2035 }
2036 break;
2037
2038 case 0x0A:
2039 if((opcode & 0x90) == 0x90)
2040 {
2041 if(opcode & 0x20)
2042 {
2043 /* STRH rd, [rn], +rm */
2044 arm_access_memory(store, no_op, half_reg, u16, yes, + reg[rm]);
2045 }
2046 else
2047 {
2048 /* UMLAL rd, rm, rs */
2049 arm_multiply_long(arm_multiply_long_addop(u), no, u);
2050 }
2051 }
2052 else
2053 {
2054 /* ADC rd, rn, reg_op */
2055 arm_data_proc(reg[rn] + reg_sh + c_flag, reg);
2056 }
2057 break;
2058
2059 case 0x0B:
2060 if((opcode & 0x90) == 0x90)
2061 {
2062 switch((opcode >> 5) & 0x03)
2063 {
2064 case 0:
2065 /* UMLALS rdlo, rdhi, rm, rs */
2066 arm_multiply_long(arm_multiply_long_addop(u), yes, u);
2067 break;
2068
2069 case 1:
2070 /* LDRH rd, [rn], +rm */
2071 arm_access_memory(load, no_op, half_reg, u16, yes, + reg[rm]);
2072 break;
2073
2074 case 2:
2075 /* LDRSB rd, [rn], +rm */
2076 arm_access_memory(load, no_op, half_reg, s8, yes, + reg[rm]);
2077 break;
2078
2079 case 3:
2080 /* LDRSH rd, [rn], +rm */
2081 arm_access_memory(load, no_op, half_reg, s16, yes, + reg[rm]);
2082 break;
2083 }
2084 }
2085 else
2086 {
2087 /* ADCS rd, rn, reg_op */
2088 arm_data_proc_add_flags(reg[rn], reg_sh + c_flag, reg);
2089 }
2090 break;
2091
2092 case 0x0C:
2093 if((opcode & 0x90) == 0x90)
2094 {
2095 if(opcode & 0x20)
2096 {
2097 /* STRH rd, [rn], +imm */
2098 arm_access_memory(store, no_op, half_imm, u16, yes, + offset);
2099 }
2100 else
2101 {
2102 /* SMULL rd, rm, rs */
2103 arm_multiply_long(no_op, no, s);
2104 }
2105 }
2106 else
2107 {
2108 /* SBC rd, rn, reg_op */
2109 arm_data_proc(reg[rn] - (reg_sh + (c_flag ^ 1)), reg);
2110 }
2111 break;
2112
2113 case 0x0D:
2114 if((opcode & 0x90) == 0x90)
2115 {
2116 switch((opcode >> 5) & 0x03)
2117 {
2118 case 0:
2119 /* SMULLS rdlo, rdhi, rm, rs */
2120 arm_multiply_long(no_op, yes, s);
2121 break;
2122
2123 case 1:
2124 /* LDRH rd, [rn], +imm */
2125 arm_access_memory(load, no_op, half_imm, u16, yes, + offset);
2126 break;
2127
2128 case 2:
2129 /* LDRSB rd, [rn], +imm */
2130 arm_access_memory(load, no_op, half_imm, s8, yes, + offset);
2131 break;
2132
2133 case 3:
2134 /* LDRSH rd, [rn], +imm */
2135 arm_access_memory(load, no_op, half_imm, s16, yes, + offset);
2136 break;
2137 }
2138 }
2139 else
2140 {
2141 /* SBCS rd, rn, reg_op */
2142 arm_data_proc_sub_flags(reg[rn], (reg_sh + (c_flag ^ 1)), reg);
2143 }
2144 break;
2145
2146 case 0x0E:
2147 if((opcode & 0x90) == 0x90)
2148 {
2149 if(opcode & 0x20)
2150 {
2151 /* STRH rd, [rn], +imm */
2152 arm_access_memory(store, no_op, half_imm, u16, yes, + offset);
2153 }
2154 else
2155 {
2156 /* SMLAL rd, rm, rs */
2157 arm_multiply_long(arm_multiply_long_addop(s), no, s);
2158 }
2159 }
2160 else
2161 {
2162 /* RSC rd, rn, reg_op */
2163 arm_data_proc(reg_sh - reg[rn] + c_flag - 1, reg);
2164 }
2165 break;
2166
2167 case 0x0F:
2168 if((opcode & 0x90) == 0x90)
2169 {
2170 switch((opcode >> 5) & 0x03)
2171 {
2172 case 0:
2173 /* SMLALS rdlo, rdhi, rm, rs */
2174 arm_multiply_long(arm_multiply_long_addop(s), yes, s);
2175 break;
2176
2177 case 1:
2178 /* LDRH rd, [rn], +imm */
2179 arm_access_memory(load, no_op, half_imm, u16, yes, + offset);
2180 break;
2181
2182 case 2:
2183 /* LDRSB rd, [rn], +imm */
2184 arm_access_memory(load, no_op, half_imm, s8, yes, + offset);
2185 break;
2186
2187 case 3:
2188 /* LDRSH rd, [rn], +imm */
2189 arm_access_memory(load, no_op, half_imm, s16, yes, + offset);
2190 break;
2191 }
2192 }
2193 else
2194 {
2195 /* RSCS rd, rn, reg_op */
2196 arm_data_proc_sub_flags((reg_sh + c_flag - 1), reg[rn], reg);
2197 }
2198 break;
2199
2200 case 0x10:
2201 if((opcode & 0x90) == 0x90)
2202 {
2203 if(opcode & 0x20)
2204 {
2205 /* STRH rd, [rn - rm] */
2206 arm_access_memory(store, - reg[rm], half_reg, u16, no, no_op);
2207 }
2208 else
2209 {
2210 /* SWP rd, rm, [rn] */
2211 arm_swap(u32);
2212 }
2213 }
2214 else
2215 {
2216 /* MRS rd, cpsr */
2217 arm_psr(reg, read, reg[REG_CPSR]);
2218 }
2219 break;
2220
2221 case 0x11:
2222 if((opcode & 0x90) == 0x90)
2223 {
2224 switch((opcode >> 5) & 0x03)
2225 {
2226 case 1:
2227 /* LDRH rd, [rn - rm] */
2228 arm_access_memory(load, - reg[rm], half_reg, u16, no, no_op);
2229 break;
2230
2231 case 2:
2232 /* LDRSB rd, [rn - rm] */
2233 arm_access_memory(load, - reg[rm], half_reg, s8, no, no_op);
2234 break;
2235
2236 case 3:
2237 /* LDRSH rd, [rn - rm] */
2238 arm_access_memory(load, - reg[rm], half_reg, s16, no, no_op);
2239 break;
2240 }
2241 }
2242 else
2243 {
2244 /* TST rd, rn, reg_op */
2245 arm_data_proc_test_logic(reg[rn] & reg_sh, reg);
2246 }
2247 break;
2248
2249 case 0x12:
2250 if((opcode & 0x90) == 0x90)
2251 {
2252 /* STRH rd, [rn - rm]! */
2253 arm_access_memory(store, - reg[rm], half_reg, u16, yes, no_op);
2254 }
2255 else
2256 {
2257 if(opcode & 0x10)
2258 {
2259 /* BX rn */
2260 arm_decode_branchx(opcode);
2261 u32 src = reg[rn];
2262 if(src & 0x01)
2263 {
2264 src -= 1;
2265 arm_pc_offset_update_direct(src);
2266 reg[REG_CPSR] |= 0x20;
2267 goto thumb_loop;
2268 }
2269 else
2270 {
2271 arm_pc_offset_update_direct(src);
2272 }
2273 }
2274 else
2275 {
2276 /* MSR cpsr, rm */
2277 arm_psr(reg, store, cpsr);
2278 }
2279 }
2280 break;
2281
2282 case 0x13:
2283 if((opcode & 0x90) == 0x90)
2284 {
2285 switch((opcode >> 5) & 0x03)
2286 {
2287 case 1:
2288 /* LDRH rd, [rn - rm]! */
2289 arm_access_memory(load, - reg[rm], half_reg, u16, yes, no_op);
2290 break;
2291
2292 case 2:
2293 /* LDRSB rd, [rn - rm]! */
2294 arm_access_memory(load, - reg[rm], half_reg, s8, yes, no_op);
2295 break;
2296
2297 case 3:
2298 /* LDRSH rd, [rn - rm]! */
2299 arm_access_memory(load, - reg[rm], half_reg, s16, yes, no_op);
2300 break;
2301 }
2302 }
2303 else
2304 {
2305 /* TEQ rd, rn, reg_op */
2306 arm_data_proc_test_logic(reg[rn] ^ reg_sh, reg);
2307 }
2308 break;
2309
2310 case 0x14:
2311 if((opcode & 0x90) == 0x90)
2312 {
2313 if(opcode & 0x20)
2314 {
2315 /* STRH rd, [rn - imm] */
2316 arm_access_memory(store, - offset, half_imm, u16, no, no_op);
2317 }
2318 else
2319 {
2320 /* SWPB rd, rm, [rn] */
2321 arm_swap(u8);
2322 }
2323 }
2324 else
2325 {
2326 /* MRS rd, spsr */
2327 arm_psr(reg, read, spsr[reg[CPU_MODE]]);
2328 }
2329 break;
2330
2331 case 0x15:
2332 if((opcode & 0x90) == 0x90)
2333 {
2334 switch((opcode >> 5) & 0x03)
2335 {
2336 case 1:
2337 /* LDRH rd, [rn - imm] */
2338 arm_access_memory(load, - offset, half_imm, u16, no, no_op);
2339 break;
2340
2341 case 2:
2342 /* LDRSB rd, [rn - imm] */
2343 arm_access_memory(load, - offset, half_imm, s8, no, no_op);
2344 break;
2345
2346 case 3:
2347 /* LDRSH rd, [rn - imm] */
2348 arm_access_memory(load, - offset, half_imm, s16, no, no_op);
2349 break;
2350 }
2351 }
2352 else
2353 {
2354 /* CMP rn, reg_op */
2355 arm_data_proc_test_sub(reg[rn], reg_sh, reg);
2356 }
2357 break;
2358
2359 case 0x16:
2360 if((opcode & 0x90) == 0x90)
2361 {
2362 /* STRH rd, [rn - imm]! */
2363 arm_access_memory(store, - offset, half_imm, u16, yes, no_op);
2364 }
2365 else
2366 {
2367 /* MSR spsr, rm */
2368 arm_psr(reg, store, spsr);
2369 }
2370 break;
2371
2372 case 0x17:
2373 if((opcode & 0x90) == 0x90)
2374 {
2375 switch((opcode >> 5) & 0x03)
2376 {
2377 case 1:
2378 /* LDRH rd, [rn - imm]! */
2379 arm_access_memory(load, - offset, half_imm, u16, yes, no_op);
2380 break;
2381
2382 case 2:
2383 /* LDRSB rd, [rn - imm]! */
2384 arm_access_memory(load, - offset, half_imm, s8, yes, no_op);
2385 break;
2386
2387 case 3:
2388 /* LDRSH rd, [rn - imm]! */
2389 arm_access_memory(load, - offset, half_imm, s16, yes, no_op);
2390 break;
2391 }
2392 }
2393 else
2394 {
2395 /* CMN rd, rn, reg_op */
2396 arm_data_proc_test_add(reg[rn], reg_sh, reg);
2397 }
2398 break;
2399
2400 case 0x18:
2401 if((opcode & 0x90) == 0x90)
2402 {
2403 /* STRH rd, [rn + rm] */
2404 arm_access_memory(store, + reg[rm], half_reg, u16, no, no_op);
2405 }
2406 else
2407 {
2408 /* ORR rd, rn, reg_op */
2409 arm_data_proc(reg[rn] | reg_sh, reg);
2410 }
2411 break;
2412
2413 case 0x19:
2414 if((opcode & 0x90) == 0x90)
2415 {
2416 switch((opcode >> 5) & 0x03)
2417 {
2418 case 1:
2419 /* LDRH rd, [rn + rm] */
2420 arm_access_memory(load, + reg[rm], half_reg, u16, no, no_op);
2421 break;
2422
2423 case 2:
2424 /* LDRSB rd, [rn + rm] */
2425 arm_access_memory(load, + reg[rm], half_reg, s8, no, no_op);
2426 break;
2427
2428 case 3:
2429 /* LDRSH rd, [rn + rm] */
2430 arm_access_memory(load, + reg[rm], half_reg, s16, no, no_op);
2431 break;
2432 }
2433 }
2434 else
2435 {
2436 /* ORRS rd, rn, reg_op */
2437 arm_data_proc_logic_flags(reg[rn] | reg_sh, reg);
2438 }
2439 break;
2440
2441 case 0x1A:
2442 if((opcode & 0x90) == 0x90)
2443 {
2444 /* STRH rd, [rn + rm]! */
2445 arm_access_memory(store, + reg[rm], half_reg, u16, yes, no_op);
2446 }
2447 else
2448 {
2449 /* MOV rd, reg_op */
2450 arm_data_proc(reg_sh, reg);
2451 }
2452 break;
2453
2454 case 0x1B:
2455 if((opcode & 0x90) == 0x90)
2456 {
2457 switch((opcode >> 5) & 0x03)
2458 {
2459 case 1:
2460 /* LDRH rd, [rn + rm]! */
2461 arm_access_memory(load, + reg[rm], half_reg, u16, yes, no_op);
2462 break;
2463
2464 case 2:
2465 /* LDRSB rd, [rn + rm]! */
2466 arm_access_memory(load, + reg[rm], half_reg, s8, yes, no_op);
2467 break;
2468
2469 case 3:
2470 /* LDRSH rd, [rn + rm]! */
2471 arm_access_memory(load, + reg[rm], half_reg, s16, yes, no_op);
2472 break;
2473 }
2474 }
2475 else
2476 {
2477 /* MOVS rd, reg_op */
2478 arm_data_proc_logic_flags(reg_sh, reg);
2479 }
2480 break;
2481
2482 case 0x1C:
2483 if((opcode & 0x90) == 0x90)
2484 {
2485 /* STRH rd, [rn + imm] */
2486 arm_access_memory(store, + offset, half_imm, u16, no, no_op);
2487 }
2488 else
2489 {
2490 /* BIC rd, rn, reg_op */
2491 arm_data_proc(reg[rn] & (~reg_sh), reg);
2492 }
2493 break;
2494
2495 case 0x1D:
2496 if((opcode & 0x90) == 0x90)
2497 {
2498 switch((opcode >> 5) & 0x03)
2499 {
2500 case 1:
2501 /* LDRH rd, [rn + imm] */
2502 arm_access_memory(load, + offset, half_imm, u16, no, no_op);
2503 break;
2504
2505 case 2:
2506 /* LDRSB rd, [rn + imm] */
2507 arm_access_memory(load, + offset, half_imm, s8, no, no_op);
2508 break;
2509
2510 case 3:
2511 /* LDRSH rd, [rn + imm] */
2512 arm_access_memory(load, + offset, half_imm, s16, no, no_op);
2513 break;
2514 }
2515 }
2516 else
2517 {
2518 /* BICS rd, rn, reg_op */
2519 arm_data_proc_logic_flags(reg[rn] & (~reg_sh), reg);
2520 }
2521 break;
2522
2523 case 0x1E:
2524 if((opcode & 0x90) == 0x90)
2525 {
2526 /* STRH rd, [rn + imm]! */
2527 arm_access_memory(store, + offset, half_imm, u16, yes, no_op);
2528 }
2529 else
2530 {
2531 /* MVN rd, reg_op */
2532 arm_data_proc(~reg_sh, reg);
2533 }
2534 break;
2535
2536 case 0x1F:
2537 if((opcode & 0x90) == 0x90)
2538 {
2539 switch((opcode >> 5) & 0x03)
2540 {
2541 case 1:
2542 /* LDRH rd, [rn + imm]! */
2543 arm_access_memory(load, + offset, half_imm, u16, yes, no_op);
2544 break;
2545
2546 case 2:
2547 /* LDRSB rd, [rn + imm]! */
2548 arm_access_memory(load, + offset, half_imm, s8, yes, no_op);
2549 break;
2550
2551 case 3:
2552 /* LDRSH rd, [rn + imm]! */
2553 arm_access_memory(load, + offset, half_imm, s16, yes, no_op);
2554 break;
2555 }
2556 }
2557 else
2558 {
2559 /* MVNS rd, rn, reg_op */
2560 arm_data_proc_logic_flags(~reg_sh, reg);
2561 }
2562 break;
2563
2564 case 0x20:
2565 /* AND rd, rn, imm */
2566 arm_data_proc(reg[rn] & imm, imm);
2567 break;
2568
2569 case 0x21:
2570 /* ANDS rd, rn, imm */
2571 arm_data_proc_logic_flags(reg[rn] & imm, imm);
2572 break;
2573
2574 case 0x22:
2575 /* EOR rd, rn, imm */
2576 arm_data_proc(reg[rn] ^ imm, imm);
2577 break;
2578
2579 case 0x23:
2580 /* EORS rd, rn, imm */
2581 arm_data_proc_logic_flags(reg[rn] ^ imm, imm);
2582 break;
2583
2584 case 0x24:
2585 /* SUB rd, rn, imm */
2586 arm_data_proc(reg[rn] - imm, imm);
2587 break;
2588
2589 case 0x25:
2590 /* SUBS rd, rn, imm */
2591 arm_data_proc_sub_flags(reg[rn], imm, imm);
2592 break;
2593
2594 case 0x26:
2595 /* RSB rd, rn, imm */
2596 arm_data_proc(imm - reg[rn], imm);
2597 break;
2598
2599 case 0x27:
2600 /* RSBS rd, rn, imm */
2601 arm_data_proc_sub_flags(imm, reg[rn], imm);
2602 break;
2603
2604 case 0x28:
2605 /* ADD rd, rn, imm */
2606 arm_data_proc(reg[rn] + imm, imm);
2607 break;
2608
2609 case 0x29:
2610 /* ADDS rd, rn, imm */
2611 arm_data_proc_add_flags(reg[rn], imm, imm);
2612 break;
2613
2614 case 0x2A:
2615 /* ADC rd, rn, imm */
2616 arm_data_proc(reg[rn] + imm + c_flag, imm);
2617 break;
2618
2619 case 0x2B:
2620 /* ADCS rd, rn, imm */
2621 arm_data_proc_add_flags(reg[rn] + imm, c_flag, imm);
2622 break;
2623
2624 case 0x2C:
2625 /* SBC rd, rn, imm */
2626 arm_data_proc(reg[rn] - imm + c_flag - 1, imm);
2627 break;
2628
2629 case 0x2D:
2630 /* SBCS rd, rn, imm */
2631 arm_data_proc_sub_flags(reg[rn], (imm + (c_flag ^ 1)), imm);
2632 break;
2633
2634 case 0x2E:
2635 /* RSC rd, rn, imm */
2636 arm_data_proc(imm - reg[rn] + c_flag - 1, imm);
2637 break;
2638
2639 case 0x2F:
2640 /* RSCS rd, rn, imm */
2641 arm_data_proc_sub_flags((imm + c_flag - 1), reg[rn], imm);
2642 break;
2643
2644 case 0x30:
2645 case 0x31:
2646 /* TST rn, imm */
2647 arm_data_proc_test_logic(reg[rn] & imm, imm);
2648 break;
2649
2650 case 0x32:
2651 /* MSR cpsr, imm */
2652 arm_psr(imm, store, cpsr);
2653 break;
2654
2655 case 0x33:
2656 /* TEQ rn, imm */
2657 arm_data_proc_test_logic(reg[rn] ^ imm, imm);
2658 break;
2659
2660 case 0x34:
2661 case 0x35:
2662 /* CMP rn, imm */
2663 arm_data_proc_test_sub(reg[rn], imm, imm);
2664 break;
2665
2666 case 0x36:
2667 /* MSR spsr, imm */
2668 arm_psr(imm, store, spsr);
2669 break;
2670
2671 case 0x37:
2672 /* CMN rn, imm */
2673 arm_data_proc_test_add(reg[rn], imm, imm);
2674 break;
2675
2676 case 0x38:
2677 /* ORR rd, rn, imm */
2678 arm_data_proc(reg[rn] | imm, imm);
2679 break;
2680
2681 case 0x39:
2682 /* ORRS rd, rn, imm */
2683 arm_data_proc_logic_flags(reg[rn] | imm, imm);
2684 break;
2685
2686 case 0x3A:
2687 /* MOV rd, imm */
2688 arm_data_proc(imm, imm);
2689 break;
2690
2691 case 0x3B:
2692 /* MOVS rd, imm */
2693 arm_data_proc_logic_flags(imm, imm);
2694 break;
2695
2696 case 0x3C:
2697 /* BIC rd, rn, imm */
2698 arm_data_proc(reg[rn] & (~imm), imm);
2699 break;
2700
2701 case 0x3D:
2702 /* BICS rd, rn, imm */
2703 arm_data_proc_logic_flags(reg[rn] & (~imm), imm);
2704 break;
2705
2706 case 0x3E:
2707 /* MVN rd, imm */
2708 arm_data_proc(~imm, imm);
2709 break;
2710
2711 case 0x3F:
2712 /* MVNS rd, imm */
2713 arm_data_proc_logic_flags(~imm, imm);
2714 break;
2715
2716 case 0x40:
2717 /* STR rd, [rn], -imm */
2718 arm_access_memory(store, no_op, imm, u32, yes, - offset);
2719 break;
2720
2721 case 0x41:
2722 /* LDR rd, [rn], -imm */
2723 arm_access_memory(load, no_op, imm, u32, yes, - offset);
2724 break;
2725
2726 case 0x42:
2727 /* STRT rd, [rn], -imm */
2728 arm_access_memory(store, no_op, imm, u32, yes, - offset);
2729 break;
2730
2731 case 0x43:
2732 /* LDRT rd, [rn], -imm */
2733 arm_access_memory(load, no_op, imm, u32, yes, - offset);
2734 break;
2735
2736 case 0x44:
2737 /* STRB rd, [rn], -imm */
2738 arm_access_memory(store, no_op, imm, u8, yes, - offset);
2739 break;
2740
2741 case 0x45:
2742 /* LDRB rd, [rn], -imm */
2743 arm_access_memory(load, no_op, imm, u8, yes, - offset);
2744 break;
2745
2746 case 0x46:
2747 /* STRBT rd, [rn], -imm */
2748 arm_access_memory(store, no_op, imm, u8, yes, - offset);
2749 break;
2750
2751 case 0x47:
2752 /* LDRBT rd, [rn], -imm */
2753 arm_access_memory(load, no_op, imm, u8, yes, - offset);
2754 break;
2755
2756 case 0x48:
2757 /* STR rd, [rn], +imm */
2758 arm_access_memory(store, no_op, imm, u32, yes, + offset);
2759 break;
2760
2761 case 0x49:
2762 /* LDR rd, [rn], +imm */
2763 arm_access_memory(load, no_op, imm, u32, yes, + offset);
2764 break;
2765
2766 case 0x4A:
2767 /* STRT rd, [rn], +imm */
2768 arm_access_memory(store, no_op, imm, u32, yes, + offset);
2769 break;
2770
2771 case 0x4B:
2772 /* LDRT rd, [rn], +imm */
2773 arm_access_memory(load, no_op, imm, u32, yes, + offset);
2774 break;
2775
2776 case 0x4C:
2777 /* STRB rd, [rn], +imm */
2778 arm_access_memory(store, no_op, imm, u8, yes, + offset);
2779 break;
2780
2781 case 0x4D:
2782 /* LDRB rd, [rn], +imm */
2783 arm_access_memory(load, no_op, imm, u8, yes, + offset);
2784 break;
2785
2786 case 0x4E:
2787 /* STRBT rd, [rn], +imm */
2788 arm_access_memory(store, no_op, imm, u8, yes, + offset);
2789 break;
2790
2791 case 0x4F:
2792 /* LDRBT rd, [rn], +imm */
2793 arm_access_memory(load, no_op, imm, u8, yes, + offset);
2794 break;
2795
2796 case 0x50:
2797 /* STR rd, [rn - imm] */
2798 arm_access_memory(store, - offset, imm, u32, no, no_op);
2799 break;
2800
2801 case 0x51:
2802 /* LDR rd, [rn - imm] */
2803 arm_access_memory(load, - offset, imm, u32, no, no_op);
2804 break;
2805
2806 case 0x52:
2807 /* STR rd, [rn - imm]! */
2808 arm_access_memory(store, - offset, imm, u32, yes, no_op);
2809 break;
2810
2811 case 0x53:
2812 /* LDR rd, [rn - imm]! */
2813 arm_access_memory(load, - offset, imm, u32, yes, no_op);
2814 break;
2815
2816 case 0x54:
2817 /* STRB rd, [rn - imm] */
2818 arm_access_memory(store, - offset, imm, u8, no, no_op);
2819 break;
2820
2821 case 0x55:
2822 /* LDRB rd, [rn - imm] */
2823 arm_access_memory(load, - offset, imm, u8, no, no_op);
2824 break;
2825
2826 case 0x56:
2827 /* STRB rd, [rn - imm]! */
2828 arm_access_memory(store, - offset, imm, u8, yes, no_op);
2829 break;
2830
2831 case 0x57:
2832 /* LDRB rd, [rn - imm]! */
2833 arm_access_memory(load, - offset, imm, u8, yes, no_op);
2834 break;
2835
2836 case 0x58:
2837 /* STR rd, [rn + imm] */
2838 arm_access_memory(store, + offset, imm, u32, no, no_op);
2839 break;
2840
2841 case 0x59:
2842 /* LDR rd, [rn + imm] */
2843 arm_access_memory(load, + offset, imm, u32, no, no_op);
2844 break;
2845
2846 case 0x5A:
2847 /* STR rd, [rn + imm]! */
2848 arm_access_memory(store, + offset, imm, u32, yes, no_op);
2849 break;
2850
2851 case 0x5B:
2852 /* LDR rd, [rn + imm]! */
2853 arm_access_memory(load, + offset, imm, u32, yes, no_op);
2854 break;
2855
2856 case 0x5C:
2857 /* STRB rd, [rn + imm] */
2858 arm_access_memory(store, + offset, imm, u8, no, no_op);
2859 break;
2860
2861 case 0x5D:
2862 /* LDRB rd, [rn + imm] */
2863 arm_access_memory(load, + offset, imm, u8, no, no_op);
2864 break;
2865
2866 case 0x5E:
2867 /* STRB rd, [rn + imm]! */
2868 arm_access_memory(store, + offset, imm, u8, yes, no_op);
2869 break;
2870
2871 case 0x5F:
2872 /* LDRBT rd, [rn + imm]! */
2873 arm_access_memory(load, + offset, imm, u8, yes, no_op);
2874 break;
2875
2876 case 0x60:
2877 /* STR rd, [rn], -reg_op */
2878 arm_access_memory(store, no_op, reg, u32, yes, - reg_offset);
2879 break;
2880
2881 case 0x61:
2882 /* LDR rd, [rn], -reg_op */
2883 arm_access_memory(load, no_op, reg, u32, yes, - reg_offset);
2884 break;
2885
2886 case 0x62:
2887 /* STRT rd, [rn], -reg_op */
2888 arm_access_memory(store, no_op, reg, u32, yes, - reg_offset);
2889 break;
2890
2891 case 0x63:
2892 /* LDRT rd, [rn], -reg_op */
2893 arm_access_memory(load, no_op, reg, u32, yes, - reg_offset);
2894 break;
2895
2896 case 0x64:
2897 /* STRB rd, [rn], -reg_op */
2898 arm_access_memory(store, no_op, reg, u8, yes, - reg_offset);
2899 break;
2900
2901 case 0x65:
2902 /* LDRB rd, [rn], -reg_op */
2903 arm_access_memory(load, no_op, reg, u8, yes, - reg_offset);
2904 break;
2905
2906 case 0x66:
2907 /* STRBT rd, [rn], -reg_op */
2908 arm_access_memory(store, no_op, reg, u8, yes, - reg_offset);
2909 break;
2910
2911 case 0x67:
2912 /* LDRBT rd, [rn], -reg_op */
2913 arm_access_memory(load, no_op, reg, u8, yes, - reg_offset);
2914 break;
2915
2916 case 0x68:
2917 /* STR rd, [rn], +reg_op */
2918 arm_access_memory(store, no_op, reg, u32, yes, + reg_offset);
2919 break;
2920
2921 case 0x69:
2922 /* LDR rd, [rn], +reg_op */
2923 arm_access_memory(load, no_op, reg, u32, yes, + reg_offset);
2924 break;
2925
2926 case 0x6A:
2927 /* STRT rd, [rn], +reg_op */
2928 arm_access_memory(store, no_op, reg, u32, yes, + reg_offset);
2929 break;
2930
2931 case 0x6B:
2932 /* LDRT rd, [rn], +reg_op */
2933 arm_access_memory(load, no_op, reg, u32, yes, + reg_offset);
2934 break;
2935
2936 case 0x6C:
2937 /* STRB rd, [rn], +reg_op */
2938 arm_access_memory(store, no_op, reg, u8, yes, + reg_offset);
2939 break;
2940
2941 case 0x6D:
2942 /* LDRB rd, [rn], +reg_op */
2943 arm_access_memory(load, no_op, reg, u8, yes, + reg_offset);
2944 break;
2945
2946 case 0x6E:
2947 /* STRBT rd, [rn], +reg_op */
2948 arm_access_memory(store, no_op, reg, u8, yes, + reg_offset);
2949 break;
2950
2951 case 0x6F:
2952 /* LDRBT rd, [rn], +reg_op */
2953 arm_access_memory(load, no_op, reg, u8, yes, + reg_offset);
2954 break;
2955
2956 case 0x70:
2957 /* STR rd, [rn - reg_op] */
2958 arm_access_memory(store, - reg_offset, reg, u32, no, no_op);
2959 break;
2960
2961 case 0x71:
2962 /* LDR rd, [rn - reg_op] */
2963 arm_access_memory(load, - reg_offset, reg, u32, no, no_op);
2964 break;
2965
2966 case 0x72:
2967 /* STR rd, [rn - reg_op]! */
2968 arm_access_memory(store, - reg_offset, reg, u32, yes, no_op);
2969 break;
2970
2971 case 0x73:
2972 /* LDR rd, [rn - reg_op]! */
2973 arm_access_memory(load, - reg_offset, reg, u32, yes, no_op);
2974 break;
2975
2976 case 0x74:
2977 /* STRB rd, [rn - reg_op] */
2978 arm_access_memory(store, - reg_offset, reg, u8, no, no_op);
2979 break;
2980
2981 case 0x75:
2982 /* LDRB rd, [rn - reg_op] */
2983 arm_access_memory(load, - reg_offset, reg, u8, no, no_op);
2984 break;
2985
2986 case 0x76:
2987 /* STRB rd, [rn - reg_op]! */
2988 arm_access_memory(store, - reg_offset, reg, u8, yes, no_op);
2989 break;
2990
2991 case 0x77:
2992 /* LDRB rd, [rn - reg_op]! */
2993 arm_access_memory(load, - reg_offset, reg, u8, yes, no_op);
2994 break;
2995
2996 case 0x78:
2997 /* STR rd, [rn + reg_op] */
2998 arm_access_memory(store, + reg_offset, reg, u32, no, no_op);
2999 break;
3000
3001 case 0x79:
3002 /* LDR rd, [rn + reg_op] */
3003 arm_access_memory(load, + reg_offset, reg, u32, no, no_op);
3004 break;
3005
3006 case 0x7A:
3007 /* STR rd, [rn + reg_op]! */
3008 arm_access_memory(store, + reg_offset, reg, u32, yes, no_op);
3009 break;
3010
3011 case 0x7B:
3012 /* LDR rd, [rn + reg_op]! */
3013 arm_access_memory(load, + reg_offset, reg, u32, yes, no_op);
3014 break;
3015
3016 case 0x7C:
3017 /* STRB rd, [rn + reg_op] */
3018 arm_access_memory(store, + reg_offset, reg, u8, no, no_op);
3019 break;
3020
3021 case 0x7D:
3022 /* LDRB rd, [rn + reg_op] */
3023 arm_access_memory(load, + reg_offset, reg, u8, no, no_op);
3024 break;
3025
3026 case 0x7E:
3027 /* STRB rd, [rn + reg_op]! */
3028 arm_access_memory(store, + reg_offset, reg, u8, yes, no_op);
3029 break;
3030
3031 case 0x7F:
3032 /* LDRBT rd, [rn + reg_op]! */
3033 arm_access_memory(load, + reg_offset, reg, u8, yes, no_op);
3034 break;
3035
3036 case 0x80:
3037 /* STMDA rn, rlist */
3038 arm_block_memory(store, down_a, no, no);
3039 break;
3040
3041 case 0x81:
3042 /* LDMDA rn, rlist */
3043 arm_block_memory(load, down_a, no, no);
3044 break;
3045
3046 case 0x82:
3047 /* STMDA rn!, rlist */
3048 arm_block_memory(store, down_a, down, no);
3049 break;
3050
3051 case 0x83:
3052 /* LDMDA rn!, rlist */
3053 arm_block_memory(load, down_a, down, no);
3054 break;
3055
3056 case 0x84:
3057 /* STMDA rn, rlist^ */
3058 arm_block_memory(store, down_a, no, yes);
3059 break;
3060
3061 case 0x85:
3062 /* LDMDA rn, rlist^ */
3063 arm_block_memory(load, down_a, no, yes);
3064 break;
3065
3066 case 0x86:
3067 /* STMDA rn!, rlist^ */
3068 arm_block_memory(store, down_a, down, yes);
3069 break;
3070
3071 case 0x87:
3072 /* LDMDA rn!, rlist^ */
3073 arm_block_memory(load, down_a, down, yes);
3074 break;
3075
3076 case 0x88:
3077 /* STMIA rn, rlist */
3078 arm_block_memory(store, no, no, no);
3079 break;
3080
3081 case 0x89:
3082 /* LDMIA rn, rlist */
3083 arm_block_memory(load, no, no, no);
3084 break;
3085
3086 case 0x8A:
3087 /* STMIA rn!, rlist */
3088 arm_block_memory(store, no, up, no);
3089 break;
3090
3091 case 0x8B:
3092 /* LDMIA rn!, rlist */
3093 arm_block_memory(load, no, up, no);
3094 break;
3095
3096 case 0x8C:
3097 /* STMIA rn, rlist^ */
3098 arm_block_memory(store, no, no, yes);
3099 break;
3100
3101 case 0x8D:
3102 /* LDMIA rn, rlist^ */
3103 arm_block_memory(load, no, no, yes);
3104 break;
3105
3106 case 0x8E:
3107 /* STMIA rn!, rlist^ */
3108 arm_block_memory(store, no, up, yes);
3109 break;
3110
3111 case 0x8F:
3112 /* LDMIA rn!, rlist^ */
3113 arm_block_memory(load, no, up, yes);
3114 break;
3115
3116 case 0x90:
3117 /* STMDB rn, rlist */
3118 arm_block_memory(store, down_b, no, no);
3119 break;
3120
3121 case 0x91:
3122 /* LDMDB rn, rlist */
3123 arm_block_memory(load, down_b, no, no);
3124 break;
3125
3126 case 0x92:
3127 /* STMDB rn!, rlist */
3128 arm_block_memory(store, down_b, down, no);
3129 break;
3130
3131 case 0x93:
3132 /* LDMDB rn!, rlist */
3133 arm_block_memory(load, down_b, down, no);
3134 break;
3135
3136 case 0x94:
3137 /* STMDB rn, rlist^ */
3138 arm_block_memory(store, down_b, no, yes);
3139 break;
3140
3141 case 0x95:
3142 /* LDMDB rn, rlist^ */
3143 arm_block_memory(load, down_b, no, yes);
3144 break;
3145
3146 case 0x96:
3147 /* STMDB rn!, rlist^ */
3148 arm_block_memory(store, down_b, down, yes);
3149 break;
3150
3151 case 0x97:
3152 /* LDMDB rn!, rlist^ */
3153 arm_block_memory(load, down_b, down, yes);
3154 break;
3155
3156 case 0x98:
3157 /* STMIB rn, rlist */
3158 arm_block_memory(store, up, no, no);
3159 break;
3160
3161 case 0x99:
3162 /* LDMIB rn, rlist */
3163 arm_block_memory(load, up, no, no);
3164 break;
3165
3166 case 0x9A:
3167 /* STMIB rn!, rlist */
3168 arm_block_memory(store, up, up, no);
3169 break;
3170
3171 case 0x9B:
3172 /* LDMIB rn!, rlist */
3173 arm_block_memory(load, up, up, no);
3174 break;
3175
3176 case 0x9C:
3177 /* STMIB rn, rlist^ */
3178 arm_block_memory(store, up, no, yes);
3179 break;
3180
3181 case 0x9D:
3182 /* LDMIB rn, rlist^ */
3183 arm_block_memory(load, up, no, yes);
3184 break;
3185
3186 case 0x9E:
3187 /* STMIB rn!, rlist^ */
3188 arm_block_memory(store, up, up, yes);
3189 break;
3190
3191 case 0x9F:
3192 /* LDMIB rn!, rlist^ */
3193 arm_block_memory(load, up, up, yes);
3194 break;
3195
3196 case 0xA0:
3197 case 0xA1:
3198 case 0xA2:
3199 case 0xA3:
3200 case 0xA4:
3201 case 0xA5:
3202 case 0xA6:
3203 case 0xA7:
3204 case 0xA8:
3205 case 0xA9:
3206 case 0xAA:
3207 case 0xAB:
3208 case 0xAC:
3209 case 0xAD:
3210 case 0xAE:
3211 case 0xAF:
3212 {
3213 /* B offset */
3214 arm_decode_branch();
3215 arm_pc_offset_update(offset + 8);
3216 break;
3217 }
3218
3219 case 0xB0:
3220 case 0xB1:
3221 case 0xB2:
3222 case 0xB3:
3223 case 0xB4:
3224 case 0xB5:
3225 case 0xB6:
3226 case 0xB7:
3227 case 0xB8:
3228 case 0xB9:
3229 case 0xBA:
3230 case 0xBB:
3231 case 0xBC:
3232 case 0xBD:
3233 case 0xBE:
3234 case 0xBF:
3235 {
3236 /* BL offset */
3237 arm_decode_branch();
3238 reg[REG_LR] = pc + 4;
3239 arm_pc_offset_update(offset + 8);
3240 break;
3241 }
3242
3243 #ifdef HAVE_UNUSED
3244 case 0xC0 ... 0xEF:
3245 /* coprocessor instructions, reserved on GBA */
3246 break;
3247 #endif
3248
3249 case 0xF0:
3250 case 0xF1:
3251 case 0xF2:
3252 case 0xF3:
3253 case 0xF4:
3254 case 0xF5:
3255 case 0xF6:
3256 case 0xF7:
3257 case 0xF8:
3258 case 0xF9:
3259 case 0xFA:
3260 case 0xFB:
3261 case 0xFC:
3262 case 0xFD:
3263 case 0xFE:
3264 case 0xFF:
3265 {
3266 /* SWI comment */
3267 u32 swi_comment = opcode & 0x00FFFFFF;
3268
3269 switch(swi_comment >> 16)
3270 {
3271 /* Jump to BIOS SWI handler */
3272 default:
3273 reg_mode[MODE_SUPERVISOR][6] = pc + 4;
3274 collapse_flags();
3275 spsr[MODE_SUPERVISOR] = reg[REG_CPSR];
3276 reg[REG_PC] = 0x00000008;
3277 arm_update_pc();
3278 reg[REG_CPSR] = (reg[REG_CPSR] & ~0x1F) | 0x13;
3279 set_cpu_mode(MODE_SUPERVISOR);
3280 break;
3281 }
3282 break;
3283 }
3284 }
3285
3286 skip_instruction:
3287
3288 /* End of Execute ARM instruction */
3289 cycles_remaining -= cycles_per_instruction;
3290
3291 if (pc == idle_loop_target_pc && cycles_remaining > 0) cycles_remaining = 0;
3292 } while(cycles_remaining > 0);
3293
3294 collapse_flags();
3295 cycles = update_gba();
3296 continue;
3297
3298 do
3299 {
3300 thumb_loop:
3301
3302 collapse_flags();
3303
3304 old_pc = pc;
3305
3306 /* Execute THUMB instruction */
3307
3308 using_instruction(thumb);
3309 check_pc_region();
3310 pc &= ~0x01;
3311 opcode = address16(pc_address_block, (pc & 0x7FFF));
3312
3313 switch((opcode >> 8) & 0xFF)
3314 {
3315 case 0x00:
3316 case 0x01:
3317 case 0x02:
3318 case 0x03:
3319 case 0x04:
3320 case 0x05:
3321 case 0x06:
3322 case 0x07:
3323 /* LSL rd, rs, offset */
3324 thumb_shift(shift, lsl, imm);
3325 break;
3326
3327 case 0x08:
3328 case 0x09:
3329 case 0x0A:
3330 case 0x0B:
3331 case 0x0C:
3332 case 0x0D:
3333 case 0x0E:
3334 case 0x0F:
3335 /* LSR rd, rs, offset */
3336 thumb_shift(shift, lsr, imm);
3337 break;
3338
3339 case 0x10:
3340 case 0x11:
3341 case 0x12:
3342 case 0x13:
3343 case 0x14:
3344 case 0x15:
3345 case 0x16:
3346 case 0x17:
3347 /* ASR rd, rs, offset */
3348 thumb_shift(shift, asr, imm);
3349 break;
3350
3351 case 0x18:
3352 case 0x19:
3353 /* ADD rd, rs, rn */
3354 thumb_add(add_sub, rd, reg[rs], reg[rn]);
3355 break;
3356
3357 case 0x1A:
3358 case 0x1B:
3359 /* SUB rd, rs, rn */
3360 thumb_sub(add_sub, rd, reg[rs], reg[rn]);
3361 break;
3362
3363 case 0x1C:
3364 case 0x1D:
3365 /* ADD rd, rs, imm */
3366 thumb_add(add_sub_imm, rd, reg[rs], imm);
3367 break;
3368
3369 case 0x1E:
3370 case 0x1F:
3371 /* SUB rd, rs, imm */
3372 thumb_sub(add_sub_imm, rd, reg[rs], imm);
3373 break;
3374
3375 case 0x20:
3376 /* MOV r0, imm */
3377 thumb_logic(imm, 0, imm);
3378 break;
3379
3380 case 0x21:
3381 /* MOV r1, imm */
3382 thumb_logic(imm, 1, imm);
3383 break;
3384
3385 case 0x22:
3386 /* MOV r2, imm */
3387 thumb_logic(imm, 2, imm);
3388 break;
3389
3390 case 0x23:
3391 /* MOV r3, imm */
3392 thumb_logic(imm, 3, imm);
3393 break;
3394
3395 case 0x24:
3396 /* MOV r4, imm */
3397 thumb_logic(imm, 4, imm);
3398 break;
3399
3400 case 0x25:
3401 /* MOV r5, imm */
3402 thumb_logic(imm, 5, imm);
3403 break;
3404
3405 case 0x26:
3406 /* MOV r6, imm */
3407 thumb_logic(imm, 6, imm);
3408 break;
3409
3410 case 0x27:
3411 /* MOV r7, imm */
3412 thumb_logic(imm, 7, imm);
3413 break;
3414
3415 case 0x28:
3416 /* CMP r0, imm */
3417 thumb_test_sub(imm, reg[0], imm);
3418 break;
3419
3420 case 0x29:
3421 /* CMP r1, imm */
3422 thumb_test_sub(imm, reg[1], imm);
3423 break;
3424
3425 case 0x2A:
3426 /* CMP r2, imm */
3427 thumb_test_sub(imm, reg[2], imm);
3428 break;
3429
3430 case 0x2B:
3431 /* CMP r3, imm */
3432 thumb_test_sub(imm, reg[3], imm);
3433 break;
3434
3435 case 0x2C:
3436 /* CMP r4, imm */
3437 thumb_test_sub(imm, reg[4], imm);
3438 break;
3439
3440 case 0x2D:
3441 /* CMP r5, imm */
3442 thumb_test_sub(imm, reg[5], imm);
3443 break;
3444
3445 case 0x2E:
3446 /* CMP r6, imm */
3447 thumb_test_sub(imm, reg[6], imm);
3448 break;
3449
3450 case 0x2F:
3451 /* CMP r7, imm */
3452 thumb_test_sub(imm, reg[7], imm);
3453 break;
3454
3455 case 0x30:
3456 /* ADD r0, imm */
3457 thumb_add(imm, 0, reg[0], imm);
3458 break;
3459
3460 case 0x31:
3461 /* ADD r1, imm */
3462 thumb_add(imm, 1, reg[1], imm);
3463 break;
3464
3465 case 0x32:
3466 /* ADD r2, imm */
3467 thumb_add(imm, 2, reg[2], imm);
3468 break;
3469
3470 case 0x33:
3471 /* ADD r3, imm */
3472 thumb_add(imm, 3, reg[3], imm);
3473 break;
3474
3475 case 0x34:
3476 /* ADD r4, imm */
3477 thumb_add(imm, 4, reg[4], imm);
3478 break;
3479
3480 case 0x35:
3481 /* ADD r5, imm */
3482 thumb_add(imm, 5, reg[5], imm);
3483 break;
3484
3485 case 0x36:
3486 /* ADD r6, imm */
3487 thumb_add(imm, 6, reg[6], imm);
3488 break;
3489
3490 case 0x37:
3491 /* ADD r7, imm */
3492 thumb_add(imm, 7, reg[7], imm);
3493 break;
3494
3495 case 0x38:
3496 /* SUB r0, imm */
3497 thumb_sub(imm, 0, reg[0], imm);
3498 break;
3499
3500 case 0x39:
3501 /* SUB r1, imm */
3502 thumb_sub(imm, 1, reg[1], imm);
3503 break;
3504
3505 case 0x3A:
3506 /* SUB r2, imm */
3507 thumb_sub(imm, 2, reg[2], imm);
3508 break;
3509
3510 case 0x3B:
3511 /* SUB r3, imm */
3512 thumb_sub(imm, 3, reg[3], imm);
3513 break;
3514
3515 case 0x3C:
3516 /* SUB r4, imm */
3517 thumb_sub(imm, 4, reg[4], imm);
3518 break;
3519
3520 case 0x3D:
3521 /* SUB r5, imm */
3522 thumb_sub(imm, 5, reg[5], imm);
3523 break;
3524
3525 case 0x3E:
3526 /* SUB r6, imm */
3527 thumb_sub(imm, 6, reg[6], imm);
3528 break;
3529
3530 case 0x3F:
3531 /* SUB r7, imm */
3532 thumb_sub(imm, 7, reg[7], imm);
3533 break;
3534
3535 case 0x40:
3536 switch((opcode >> 6) & 0x03)
3537 {
3538 case 0x00:
3539 /* AND rd, rs */
3540 thumb_logic(alu_op, rd, reg[rd] & reg[rs]);
3541 break;
3542
3543 case 0x01:
3544 /* EOR rd, rs */
3545 thumb_logic(alu_op, rd, reg[rd] ^ reg[rs]);
3546 break;
3547
3548 case 0x02:
3549 /* LSL rd, rs */
3550 thumb_shift(alu_op, lsl, reg);
3551 break;
3552
3553 case 0x03:
3554 /* LSR rd, rs */
3555 thumb_shift(alu_op, lsr, reg);
3556 break;
3557 }
3558 break;
3559
3560 case 0x41:
3561 switch((opcode >> 6) & 0x03)
3562 {
3563 case 0x00:
3564 /* ASR rd, rs */
3565 thumb_shift(alu_op, asr, reg);
3566 break;
3567
3568 case 0x01:
3569 /* ADC rd, rs */
3570 thumb_add(alu_op, rd, reg[rd] + reg[rs], c_flag);
3571 break;
3572
3573 case 0x02:
3574 /* SBC rd, rs */
3575 thumb_sub(alu_op, rd, reg[rd] - reg[rs], (c_flag ^ 1));
3576 break;
3577
3578 case 0x03:
3579 /* ROR rd, rs */
3580 thumb_shift(alu_op, ror, reg);
3581 break;
3582 }
3583 break;
3584
3585 case 0x42:
3586 switch((opcode >> 6) & 0x03)
3587 {
3588 case 0x00:
3589 /* TST rd, rs */
3590 thumb_test_logic(alu_op, reg[rd] & reg[rs]);
3591 break;
3592
3593 case 0x01:
3594 /* NEG rd, rs */
3595 thumb_sub(alu_op, rd, 0, reg[rs]);
3596 break;
3597
3598 case 0x02:
3599 /* CMP rd, rs */
3600 thumb_test_sub(alu_op, reg[rd], reg[rs]);
3601 break;
3602
3603 case 0x03:
3604 /* CMN rd, rs */
3605 thumb_test_add(alu_op, reg[rd], reg[rs]);
3606 break;
3607 }
3608 break;
3609
3610 case 0x43:
3611 switch((opcode >> 6) & 0x03)
3612 {
3613 case 0x00:
3614 /* ORR rd, rs */
3615 thumb_logic(alu_op, rd, reg[rd] | reg[rs]);
3616 break;
3617
3618 case 0x01:
3619 /* MUL rd, rs */
3620 thumb_logic(alu_op, rd, reg[rd] * reg[rs]);
3621 break;
3622
3623 case 0x02:
3624 /* BIC rd, rs */
3625 thumb_logic(alu_op, rd, reg[rd] & (~reg[rs]));
3626 break;
3627
3628 case 0x03:
3629 /* MVN rd, rs */
3630 thumb_logic(alu_op, rd, ~reg[rs]);
3631 break;
3632 }
3633 break;
3634
3635 case 0x44:
3636 /* ADD rd, rs */
3637 thumb_hireg_op(reg[rd] + reg[rs]);
3638 break;
3639
3640 case 0x45:
3641 /* CMP rd, rs */
3642 {
3643 thumb_pc_offset(4);
3644 thumb_decode_hireg_op();
3645 u32 _sa = reg[rd];
3646 u32 _sb = reg[rs];
3647 u32 dest = _sa - _sb;
3648 thumb_pc_offset(-2);
3649 calculate_flags_sub(dest, _sa, _sb);
3650 }
3651 break;
3652
3653 case 0x46:
3654 /* MOV rd, rs */
3655 thumb_hireg_op(reg[rs]);
3656 break;
3657
3658 case 0x47:
3659 /* BX rs */
3660 {
3661 thumb_decode_hireg_op();
3662 u32 src;
3663 thumb_pc_offset(4);
3664 src = reg[rs];
3665 if(src & 0x01)
3666 {
3667 src -= 1;
3668 thumb_pc_offset_update_direct(src);
3669 }
3670 else
3671 {
3672 /* Switch to ARM mode */
3673 thumb_pc_offset_update_direct(src);
3674 reg[REG_CPSR] &= ~0x20;
3675 collapse_flags();
3676 goto arm_loop;
3677 }
3678 }
3679 break;
3680
3681 case 0x48:
3682 /* LDR r0, [pc + imm] */
3683 thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[0], u32);
3684 break;
3685
3686 case 0x49:
3687 /* LDR r1, [pc + imm] */
3688 thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[1], u32);
3689 break;
3690
3691 case 0x4A:
3692 /* LDR r2, [pc + imm] */
3693 thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[2], u32);
3694 break;
3695
3696 case 0x4B:
3697 /* LDR r3, [pc + imm] */
3698 thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[3], u32);
3699 break;
3700
3701 case 0x4C:
3702 /* LDR r4, [pc + imm] */
3703 thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[4], u32);
3704 break;
3705
3706 case 0x4D:
3707 /* LDR r5, [pc + imm] */
3708 thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[5], u32);
3709 break;
3710
3711 case 0x4E:
3712 /* LDR r6, [pc + imm] */
3713 thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[6], u32);
3714 break;
3715
3716 case 0x4F:
3717 /* LDR r7, [pc + imm] */
3718 thumb_access_memory(load, imm, (pc & ~2) + (imm * 4) + 4, reg[7], u32);
3719 break;
3720
3721 case 0x50:
3722 case 0x51:
3723 /* STR rd, [rb + ro] */
3724 thumb_access_memory(store, mem_reg, reg[rb] + reg[ro], reg[rd], u32);
3725 break;
3726
3727 case 0x52:
3728 case 0x53:
3729 /* STRH rd, [rb + ro] */
3730 thumb_access_memory(store, mem_reg, reg[rb] + reg[ro], reg[rd], u16);
3731 break;
3732
3733 case 0x54:
3734 case 0x55:
3735 /* STRB rd, [rb + ro] */
3736 thumb_access_memory(store, mem_reg, reg[rb] + reg[ro], reg[rd], u8);
3737 break;
3738
3739 case 0x56:
3740 case 0x57:
3741 /* LDSB rd, [rb + ro] */
3742 thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], s8);
3743 break;
3744
3745 case 0x58:
3746 case 0x59:
3747 /* LDR rd, [rb + ro] */
3748 thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], u32);
3749 break;
3750
3751 case 0x5A:
3752 case 0x5B:
3753 /* LDRH rd, [rb + ro] */
3754 thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], u16);
3755 break;
3756
3757 case 0x5C:
3758 case 0x5D:
3759 /* LDRB rd, [rb + ro] */
3760 thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], u8);
3761 break;
3762
3763 case 0x5E:
3764 case 0x5F:
3765 /* LDSH rd, [rb + ro] */
3766 thumb_access_memory(load, mem_reg, reg[rb] + reg[ro], reg[rd], s16);
3767 break;
3768
3769 case 0x60:
3770 case 0x61:
3771 case 0x62:
3772 case 0x63:
3773 case 0x64:
3774 case 0x65:
3775 case 0x66:
3776 case 0x67:
3777 /* STR rd, [rb + imm] */
3778 thumb_access_memory(store, mem_imm, reg[rb] + (imm * 4), reg[rd], u32);
3779 break;
3780
3781 case 0x68:
3782 case 0x69:
3783 case 0x6A:
3784 case 0x6B:
3785 case 0x6C:
3786 case 0x6D:
3787 case 0x6E:
3788 case 0x6F:
3789 /* LDR rd, [rb + imm] */
3790 thumb_access_memory(load, mem_imm, reg[rb] + (imm * 4), reg[rd], u32);
3791 break;
3792
3793 case 0x70:
3794 case 0x71:
3795 case 0x72:
3796 case 0x73:
3797 case 0x74:
3798 case 0x75:
3799 case 0x76:
3800 case 0x77:
3801 /* STRB rd, [rb + imm] */
3802 thumb_access_memory(store, mem_imm, reg[rb] + imm, reg[rd], u8);
3803 break;
3804
3805 case 0x78:
3806 case 0x79:
3807 case 0x7A:
3808 case 0x7B:
3809 case 0x7C:
3810 case 0x7D:
3811 case 0x7E:
3812 case 0x7F:
3813 /* LDRB rd, [rb + imm] */
3814 thumb_access_memory(load, mem_imm, reg[rb] + imm, reg[rd], u8);
3815 break;
3816
3817 case 0x80:
3818 case 0x81:
3819 case 0x82:
3820 case 0x83:
3821 case 0x84:
3822 case 0x85:
3823 case 0x86:
3824 case 0x87:
3825 /* STRH rd, [rb + imm] */
3826 thumb_access_memory(store, mem_imm, reg[rb] + (imm * 2), reg[rd], u16);
3827 break;
3828
3829 case 0x88:
3830 case 0x89:
3831 case 0x8A:
3832 case 0x8B:
3833 case 0x8C:
3834 case 0x8D:
3835 case 0x8E:
3836 case 0x8F:
3837 /* LDRH rd, [rb + imm] */
3838 thumb_access_memory(load, mem_imm, reg[rb] + (imm * 2), reg[rd], u16);
3839 break;
3840
3841 case 0x90:
3842 /* STR r0, [sp + imm] */
3843 thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[0], u32);
3844 break;
3845
3846 case 0x91:
3847 /* STR r1, [sp + imm] */
3848 thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[1], u32);
3849 break;
3850
3851 case 0x92:
3852 /* STR r2, [sp + imm] */
3853 thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[2], u32);
3854 break;
3855
3856 case 0x93:
3857 /* STR r3, [sp + imm] */
3858 thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[3], u32);
3859 break;
3860
3861 case 0x94:
3862 /* STR r4, [sp + imm] */
3863 thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[4], u32);
3864 break;
3865
3866 case 0x95:
3867 /* STR r5, [sp + imm] */
3868 thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[5], u32);
3869 break;
3870
3871 case 0x96:
3872 /* STR r6, [sp + imm] */
3873 thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[6], u32);
3874 break;
3875
3876 case 0x97:
3877 /* STR r7, [sp + imm] */
3878 thumb_access_memory(store, imm, reg[REG_SP] + (imm * 4), reg[7], u32);
3879 break;
3880
3881 case 0x98:
3882 /* LDR r0, [sp + imm] */
3883 thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[0], u32);
3884 break;
3885
3886 case 0x99:
3887 /* LDR r1, [sp + imm] */
3888 thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[1], u32);
3889 break;
3890
3891 case 0x9A:
3892 /* LDR r2, [sp + imm] */
3893 thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[2], u32);
3894 break;
3895
3896 case 0x9B:
3897 /* LDR r3, [sp + imm] */
3898 thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[3], u32);
3899 break;
3900
3901 case 0x9C:
3902 /* LDR r4, [sp + imm] */
3903 thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[4], u32);
3904 break;
3905
3906 case 0x9D:
3907 /* LDR r5, [sp + imm] */
3908 thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[5], u32);
3909 break;
3910
3911 case 0x9E:
3912 /* LDR r6, [sp + imm] */
3913 thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[6], u32);
3914 break;
3915
3916 case 0x9F:
3917 /* LDR r7, [sp + imm] */
3918 thumb_access_memory(load, imm, reg[REG_SP] + (imm * 4), reg[7], u32);
3919 break;
3920
3921 case 0xA0:
3922 /* ADD r0, pc, +imm */
3923 thumb_add_noflags(imm, 0, (pc & ~2) + 4, (imm * 4));
3924 break;
3925
3926 case 0xA1:
3927 /* ADD r1, pc, +imm */
3928 thumb_add_noflags(imm, 1, (pc & ~2) + 4, (imm * 4));
3929 break;
3930
3931 case 0xA2:
3932 /* ADD r2, pc, +imm */
3933 thumb_add_noflags(imm, 2, (pc & ~2) + 4, (imm * 4));
3934 break;
3935
3936 case 0xA3:
3937 /* ADD r3, pc, +imm */
3938 thumb_add_noflags(imm, 3, (pc & ~2) + 4, (imm * 4));
3939 break;
3940
3941 case 0xA4:
3942 /* ADD r4, pc, +imm */
3943 thumb_add_noflags(imm, 4, (pc & ~2) + 4, (imm * 4));
3944 break;
3945
3946 case 0xA5:
3947 /* ADD r5, pc, +imm */
3948 thumb_add_noflags(imm, 5, (pc & ~2) + 4, (imm * 4));
3949 break;
3950
3951 case 0xA6:
3952 /* ADD r6, pc, +imm */
3953 thumb_add_noflags(imm, 6, (pc & ~2) + 4, (imm * 4));
3954 break;
3955
3956 case 0xA7:
3957 /* ADD r7, pc, +imm */
3958 thumb_add_noflags(imm, 7, (pc & ~2) + 4, (imm * 4));
3959 break;
3960
3961 case 0xA8:
3962 /* ADD r0, sp, +imm */
3963 thumb_add_noflags(imm, 0, reg[REG_SP], (imm * 4));
3964 break;
3965
3966 case 0xA9:
3967 /* ADD r1, sp, +imm */
3968 thumb_add_noflags(imm, 1, reg[REG_SP], (imm * 4));
3969 break;
3970
3971 case 0xAA:
3972 /* ADD r2, sp, +imm */
3973 thumb_add_noflags(imm, 2, reg[REG_SP], (imm * 4));
3974 break;
3975
3976 case 0xAB:
3977 /* ADD r3, sp, +imm */
3978 thumb_add_noflags(imm, 3, reg[REG_SP], (imm * 4));
3979 break;
3980
3981 case 0xAC:
3982 /* ADD r4, sp, +imm */
3983 thumb_add_noflags(imm, 4, reg[REG_SP], (imm * 4));
3984 break;
3985
3986 case 0xAD:
3987 /* ADD r5, sp, +imm */
3988 thumb_add_noflags(imm, 5, reg[REG_SP], (imm * 4));
3989 break;
3990
3991 case 0xAE:
3992 /* ADD r6, sp, +imm */
3993 thumb_add_noflags(imm, 6, reg[REG_SP], (imm * 4));
3994 break;
3995
3996 case 0xAF:
3997 /* ADD r7, sp, +imm */
3998 thumb_add_noflags(imm, 7, reg[REG_SP], (imm * 4));
3999 break;
4000
4001 case 0xB0:
4002 case 0xB1:
4003 case 0xB2:
4004 case 0xB3:
4005 if((opcode >> 7) & 0x01)
4006 {
4007 /* ADD sp, -imm */
4008 thumb_add_noflags(add_sp, 13, reg[REG_SP], -(imm * 4));
4009 }
4010 else
4011 {
4012 /* ADD sp, +imm */
4013 thumb_add_noflags(add_sp, 13, reg[REG_SP], (imm * 4));
4014 }
4015 break;
4016
4017 case 0xB4:
4018 /* PUSH rlist */
4019 thumb_block_memory(store, down, no_op, 13);
4020 break;
4021
4022 case 0xB5:
4023 /* PUSH rlist, lr */
4024 thumb_block_memory(store, push_lr, push_lr, 13);
4025 break;
4026
4027 case 0xBC:
4028 /* POP rlist */
4029 thumb_block_memory(load, no_op, up, 13);
4030 break;
4031
4032 case 0xBD:
4033 /* POP rlist, pc */
4034 thumb_block_memory(load, no_op, pop_pc, 13);
4035 break;
4036
4037 case 0xC0:
4038 /* STMIA r0!, rlist */
4039 thumb_block_memory(store, no_op, up, 0);
4040 break;
4041
4042 case 0xC1:
4043 /* STMIA r1!, rlist */
4044 thumb_block_memory(store, no_op, up, 1);
4045 break;
4046
4047 case 0xC2:
4048 /* STMIA r2!, rlist */
4049 thumb_block_memory(store, no_op, up, 2);
4050 break;
4051
4052 case 0xC3:
4053 /* STMIA r3!, rlist */
4054 thumb_block_memory(store, no_op, up, 3);
4055 break;
4056
4057 case 0xC4:
4058 /* STMIA r4!, rlist */
4059 thumb_block_memory(store, no_op, up, 4);
4060 break;
4061
4062 case 0xC5:
4063 /* STMIA r5!, rlist */
4064 thumb_block_memory(store, no_op, up, 5);
4065 break;
4066
4067 case 0xC6:
4068 /* STMIA r6!, rlist */
4069 thumb_block_memory(store, no_op, up, 6);
4070 break;
4071
4072 case 0xC7:
4073 /* STMIA r7!, rlist */
4074 thumb_block_memory(store, no_op, up, 7);
4075 break;
4076
4077 case 0xC8:
4078 /* LDMIA r0!, rlist */
4079 thumb_block_memory(load, no_op, up, 0);
4080 break;
4081
4082 case 0xC9:
4083 /* LDMIA r1!, rlist */
4084 thumb_block_memory(load, no_op, up, 1);
4085 break;
4086
4087 case 0xCA:
4088 /* LDMIA r2!, rlist */
4089 thumb_block_memory(load, no_op, up, 2);
4090 break;
4091
4092 case 0xCB:
4093 /* LDMIA r3!, rlist */
4094 thumb_block_memory(load, no_op, up, 3);
4095 break;
4096
4097 case 0xCC:
4098 /* LDMIA r4!, rlist */
4099 thumb_block_memory(load, no_op, up, 4);
4100 break;
4101
4102 case 0xCD:
4103 /* LDMIA r5!, rlist */
4104 thumb_block_memory(load, no_op, up, 5);
4105 break;
4106
4107 case 0xCE:
4108 /* LDMIA r6!, rlist */
4109 thumb_block_memory(load, no_op, up, 6);
4110 break;
4111
4112 case 0xCF:
4113 /* LDMIA r7!, rlist */
4114 thumb_block_memory(load, no_op, up, 7);
4115 break;
4116
4117 case 0xD0:
4118 /* BEQ label */
4119 thumb_conditional_branch(z_flag == 1);
4120 break;
4121
4122 case 0xD1:
4123 /* BNE label */
4124 thumb_conditional_branch(z_flag == 0);
4125 break;
4126
4127 case 0xD2:
4128 /* BCS label */
4129 thumb_conditional_branch(c_flag == 1);
4130 break;
4131
4132 case 0xD3:
4133 /* BCC label */
4134 thumb_conditional_branch(c_flag == 0);
4135 break;
4136
4137 case 0xD4:
4138 /* BMI label */
4139 thumb_conditional_branch(n_flag == 1);
4140 break;
4141
4142 case 0xD5:
4143 /* BPL label */
4144 thumb_conditional_branch(n_flag == 0);
4145 break;
4146
4147 case 0xD6:
4148 /* BVS label */
4149 thumb_conditional_branch(v_flag == 1);
4150 break;
4151
4152 case 0xD7:
4153 /* BVC label */
4154 thumb_conditional_branch(v_flag == 0);
4155 break;
4156
4157 case 0xD8:
4158 /* BHI label */
4159 thumb_conditional_branch(c_flag & (z_flag ^ 1));
4160 break;
4161
4162 case 0xD9:
4163 /* BLS label */
4164 thumb_conditional_branch((c_flag == 0) | z_flag);
4165 break;
4166
4167 case 0xDA:
4168 /* BGE label */
4169 thumb_conditional_branch(n_flag == v_flag);
4170 break;
4171
4172 case 0xDB:
4173 /* BLT label */
4174 thumb_conditional_branch(n_flag != v_flag);
4175 break;
4176
4177 case 0xDC:
4178 /* BGT label */
4179 thumb_conditional_branch((z_flag == 0) & (n_flag == v_flag));
4180 break;
4181
4182 case 0xDD:
4183 /* BLE label */
4184 thumb_conditional_branch(z_flag | (n_flag != v_flag));
4185 break;
4186
4187 case 0xDF:
4188 {
4189 /* SWI comment */
4190 u32 swi_comment = opcode & 0xFF;
4191
4192 switch(swi_comment)
4193 {
4194 default:
4195 reg_mode[MODE_SUPERVISOR][6] = pc + 2;
4196 spsr[MODE_SUPERVISOR] = reg[REG_CPSR];
4197 reg[REG_PC] = 0x00000008;
4198 thumb_update_pc();
4199 reg[REG_CPSR] = (reg[REG_CPSR] & ~0x3F) | 0x13;
4200 set_cpu_mode(MODE_SUPERVISOR);
4201 collapse_flags();
4202 goto arm_loop;
4203 }
4204 break;
4205 }
4206
4207 case 0xE0:
4208 case 0xE1:
4209 case 0xE2:
4210 case 0xE3:
4211 case 0xE4:
4212 case 0xE5:
4213 case 0xE6:
4214 case 0xE7:
4215 {
4216 /* B label */
4217 thumb_decode_branch();
4218 thumb_pc_offset_update(((s32)(offset << 21) >> 20) + 4);
4219 break;
4220 }
4221
4222 case 0xF0:
4223 case 0xF1:
4224 case 0xF2:
4225 case 0xF3:
4226 case 0xF4:
4227 case 0xF5:
4228 case 0xF6:
4229 case 0xF7:
4230 {
4231 /* (low word) BL label */
4232 thumb_decode_branch();
4233 reg[REG_LR] = pc + 4 + ((s32)(offset << 21) >> 9);
4234 thumb_pc_offset(2);
4235 break;
4236 }
4237
4238 case 0xF8:
4239 case 0xF9:
4240 case 0xFA:
4241 case 0xFB:
4242 case 0xFC:
4243 case 0xFD:
4244 case 0xFE:
4245 case 0xFF:
4246 {
4247 /* (high word) BL label */
4248 thumb_decode_branch();
4249 u32 lr = (pc + 2) | 0x01;
4250 pc = reg[REG_LR] + (offset * 2);
4251 reg[REG_LR] = lr;
4252 reg[REG_PC] = pc;
4253 break;
4254 }
4255 }
4256
4257 /* End of Execute THUMB instruction */
4258 cycles_remaining -= cycles_per_instruction;
4259
4260 if (pc == idle_loop_target_pc && cycles_remaining > 0) cycles_remaining = 0;
4261 } while(cycles_remaining > 0);
4262
4263 collapse_flags();
4264 cycles = update_gba();
4265 continue;
4266
4267 alert:
4268
4269 if(cpu_alert == CPU_ALERT_IRQ)
4270 cycles = cycles_remaining;
4271 else
4272 {
4273 collapse_flags();
4274
4275 while(reg[CPU_HALT_STATE] != CPU_ACTIVE)
4276 cycles = update_gba();
4277 }
4278 }
4279 }
4280
init_cpu(void)4281 void init_cpu(void)
4282 {
4283 u32 i;
4284
4285 for(i = 0; i < 16; i++)
4286 reg[i] = 0;
4287
4288 reg[REG_SP] = 0x03007F00;
4289 reg[REG_PC] = 0x08000000;
4290 reg[REG_CPSR] = 0x0000001F;
4291 reg[CPU_HALT_STATE] = CPU_ACTIVE;
4292 reg[CPU_MODE] = MODE_USER;
4293 reg[CHANGED_PC_STATUS] = 0;
4294
4295 reg_mode[MODE_USER][5] = 0x03007F00;
4296 reg_mode[MODE_IRQ][5] = 0x03007FA0;
4297 reg_mode[MODE_FIQ][5] = 0x03007FA0;
4298 reg_mode[MODE_SUPERVISOR][5] = 0x03007FE0;
4299 }
4300
move_reg(u32 * new_reg)4301 void move_reg(u32 *new_reg)
4302 {
4303 u32 i;
4304
4305 for(i = 0; i < 32; i++)
4306 new_reg[i] = reg[i];
4307
4308 reg = new_reg;
4309 }
4310
4311
4312 #define cpu_savestate_builder(type) \
4313 void cpu_##type##_savestate(void) \
4314 { \
4315 state_mem_##type(reg, 0x100); \
4316 state_mem_##type##_array(spsr); \
4317 state_mem_##type##_array(reg_mode); \
4318 }
4319
4320 cpu_savestate_builder(read)
4321 cpu_savestate_builder(write)
4322