Mercurial > vba-linux
comparison src/gba/thumb.h @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 #ifdef C_CORE | |
2 #define NEG(i) ((i) >> 31) | |
3 #define POS(i) ((~(i)) >> 31) | |
4 #define ADDCARRY(a, b, c) \ | |
5 C_FLAG = ((NEG(a) & NEG(b)) | \ | |
6 (NEG(a) & POS(c)) | \ | |
7 (NEG(b) & POS(c))) ? true : false; | |
8 #define ADDOVERFLOW(a, b, c) \ | |
9 V_FLAG = ((NEG(a) & NEG(b) & POS(c)) | \ | |
10 (POS(a) & POS(b) & NEG(c))) ? true : false; | |
11 #define SUBCARRY(a, b, c) \ | |
12 C_FLAG = ((NEG(a) & POS(b)) | \ | |
13 (NEG(a) & POS(c)) | \ | |
14 (POS(b) & POS(c))) ? true : false; | |
15 #define SUBOVERFLOW(a, b, c) \ | |
16 V_FLAG = ((NEG(a) & POS(b) & POS(c)) | \ | |
17 (POS(a) & NEG(b) & NEG(c))) ? true : false; | |
18 #define ADD_RD_RS_RN \ | |
19 { \ | |
20 u32 lhs = reg[source].I; \ | |
21 u32 rhs = value; \ | |
22 u32 res = lhs + rhs; \ | |
23 reg[dest].I = res; \ | |
24 Z_FLAG = (res == 0) ? true : false; \ | |
25 N_FLAG = NEG(res) ? true : false; \ | |
26 ADDCARRY(lhs, rhs, res); \ | |
27 ADDOVERFLOW(lhs, rhs, res); \ | |
28 } | |
29 #define ADD_RD_RS_O3 \ | |
30 { \ | |
31 u32 lhs = reg[source].I; \ | |
32 u32 rhs = value; \ | |
33 u32 res = lhs + rhs; \ | |
34 reg[dest].I = res; \ | |
35 Z_FLAG = (res == 0) ? true : false; \ | |
36 N_FLAG = NEG(res) ? true : false; \ | |
37 ADDCARRY(lhs, rhs, res); \ | |
38 ADDOVERFLOW(lhs, rhs, res); \ | |
39 } | |
40 #define ADD_RN_O8(d) \ | |
41 { \ | |
42 u32 lhs = reg[(d)].I; \ | |
43 u32 rhs = (opcode & 255); \ | |
44 u32 res = lhs + rhs; \ | |
45 reg[(d)].I = res; \ | |
46 Z_FLAG = (res == 0) ? true : false; \ | |
47 N_FLAG = NEG(res) ? true : false; \ | |
48 ADDCARRY(lhs, rhs, res); \ | |
49 ADDOVERFLOW(lhs, rhs, res); \ | |
50 } | |
51 #define CMN_RD_RS \ | |
52 { \ | |
53 u32 lhs = reg[dest].I; \ | |
54 u32 rhs = value; \ | |
55 u32 res = lhs + rhs; \ | |
56 Z_FLAG = (res == 0) ? true : false; \ | |
57 N_FLAG = NEG(res) ? true : false; \ | |
58 ADDCARRY(lhs, rhs, res); \ | |
59 ADDOVERFLOW(lhs, rhs, res); \ | |
60 } | |
61 #define ADC_RD_RS \ | |
62 { \ | |
63 u32 lhs = reg[dest].I; \ | |
64 u32 rhs = value; \ | |
65 u32 res = lhs + rhs + (u32)C_FLAG; \ | |
66 reg[dest].I = res; \ | |
67 Z_FLAG = (res == 0) ? true : false; \ | |
68 N_FLAG = NEG(res) ? true : false; \ | |
69 ADDCARRY(lhs, rhs, res); \ | |
70 ADDOVERFLOW(lhs, rhs, res); \ | |
71 } | |
72 #define SUB_RD_RS_RN \ | |
73 { \ | |
74 u32 lhs = reg[source].I; \ | |
75 u32 rhs = value; \ | |
76 u32 res = lhs - rhs; \ | |
77 reg[dest].I = res; \ | |
78 Z_FLAG = (res == 0) ? true : false; \ | |
79 N_FLAG = NEG(res) ? true : false; \ | |
80 SUBCARRY(lhs, rhs, res); \ | |
81 SUBOVERFLOW(lhs, rhs, res); \ | |
82 } | |
83 #define SUB_RD_RS_O3 \ | |
84 { \ | |
85 u32 lhs = reg[source].I; \ | |
86 u32 rhs = value; \ | |
87 u32 res = lhs - rhs; \ | |
88 reg[dest].I = res; \ | |
89 Z_FLAG = (res == 0) ? true : false; \ | |
90 N_FLAG = NEG(res) ? true : false; \ | |
91 SUBCARRY(lhs, rhs, res); \ | |
92 SUBOVERFLOW(lhs, rhs, res); \ | |
93 } | |
94 #define SUB_RN_O8(d) \ | |
95 { \ | |
96 u32 lhs = reg[(d)].I; \ | |
97 u32 rhs = (opcode & 255); \ | |
98 u32 res = lhs - rhs; \ | |
99 reg[(d)].I = res; \ | |
100 Z_FLAG = (res == 0) ? true : false; \ | |
101 N_FLAG = NEG(res) ? true : false; \ | |
102 SUBCARRY(lhs, rhs, res); \ | |
103 SUBOVERFLOW(lhs, rhs, res); \ | |
104 } | |
105 #define CMP_RN_O8(d) \ | |
106 { \ | |
107 u32 lhs = reg[(d)].I; \ | |
108 u32 rhs = (opcode & 255); \ | |
109 u32 res = lhs - rhs; \ | |
110 Z_FLAG = (res == 0) ? true : false; \ | |
111 N_FLAG = NEG(res) ? true : false; \ | |
112 SUBCARRY(lhs, rhs, res); \ | |
113 SUBOVERFLOW(lhs, rhs, res); \ | |
114 } | |
115 #define SBC_RD_RS \ | |
116 { \ | |
117 u32 lhs = reg[dest].I; \ | |
118 u32 rhs = value; \ | |
119 u32 res = lhs - rhs - !((u32)C_FLAG); \ | |
120 reg[dest].I = res; \ | |
121 Z_FLAG = (res == 0) ? true : false; \ | |
122 N_FLAG = NEG(res) ? true : false; \ | |
123 SUBCARRY(lhs, rhs, res); \ | |
124 SUBOVERFLOW(lhs, rhs, res); \ | |
125 } | |
126 #define LSL_RD_RM_I5 \ | |
127 { \ | |
128 C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false; \ | |
129 value = reg[source].I << shift; \ | |
130 } | |
131 #define LSL_RD_RS \ | |
132 { \ | |
133 C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false; \ | |
134 value = reg[dest].I << value; \ | |
135 } | |
136 #define LSR_RD_RM_I5 \ | |
137 { \ | |
138 C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false; \ | |
139 value = reg[source].I >> shift; \ | |
140 } | |
141 #define LSR_RD_RS \ | |
142 { \ | |
143 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \ | |
144 value = reg[dest].I >> value; \ | |
145 } | |
146 #define ASR_RD_RM_I5 \ | |
147 { \ | |
148 C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false; \ | |
149 value = (s32)reg[source].I >> (int)shift; \ | |
150 } | |
151 #define ASR_RD_RS \ | |
152 { \ | |
153 C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false; \ | |
154 value = (s32)reg[dest].I >> (int)value; \ | |
155 } | |
156 #define ROR_RD_RS \ | |
157 { \ | |
158 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \ | |
159 value = ((reg[dest].I << (32 - value)) | \ | |
160 (reg[dest].I >> value)); \ | |
161 } | |
162 #define NEG_RD_RS \ | |
163 { \ | |
164 u32 lhs = reg[source].I; \ | |
165 u32 rhs = 0; \ | |
166 u32 res = rhs - lhs; \ | |
167 reg[dest].I = res; \ | |
168 Z_FLAG = (res == 0) ? true : false; \ | |
169 N_FLAG = NEG(res) ? true : false; \ | |
170 SUBCARRY(rhs, lhs, res); \ | |
171 SUBOVERFLOW(rhs, lhs, res); \ | |
172 } | |
173 #define CMP_RD_RS \ | |
174 { \ | |
175 u32 lhs = reg[dest].I; \ | |
176 u32 rhs = value; \ | |
177 u32 res = lhs - rhs; \ | |
178 Z_FLAG = (res == 0) ? true : false; \ | |
179 N_FLAG = NEG(res) ? true : false; \ | |
180 SUBCARRY(lhs, rhs, res); \ | |
181 SUBOVERFLOW(lhs, rhs, res); \ | |
182 } | |
183 #else | |
184 #ifdef __GNUC__ | |
185 #ifdef __POWERPC__ | |
186 #define ADD_RD_RS_RN \ | |
187 { \ | |
188 register int Flags; \ | |
189 register int Result; \ | |
190 asm volatile ("addco. %0, %2, %3\n" \ | |
191 "mcrxr cr1\n" \ | |
192 "mfcr %1\n" \ | |
193 : "=r" (Result), \ | |
194 "=r" (Flags) \ | |
195 : "r" (reg[source].I), \ | |
196 "r" (value) \ | |
197 ); \ | |
198 reg[dest].I = Result; \ | |
199 Z_FLAG = (Flags >> 29) & 1; \ | |
200 N_FLAG = (Flags >> 31) & 1; \ | |
201 C_FLAG = (Flags >> 25) & 1; \ | |
202 V_FLAG = (Flags >> 26) & 1; \ | |
203 } | |
204 #define ADD_RD_RS_O3 ADD_RD_RS_RN | |
205 #define ADD_RN_O8(d) \ | |
206 { \ | |
207 register int Flags; \ | |
208 register int Result; \ | |
209 asm volatile ("addco. %0, %2, %3\n" \ | |
210 "mcrxr cr1\n" \ | |
211 "mfcr %1\n" \ | |
212 : "=r" (Result), \ | |
213 "=r" (Flags) \ | |
214 : "r" (reg[(d)].I), \ | |
215 "r" (opcode & 255) \ | |
216 ); \ | |
217 reg[(d)].I = Result; \ | |
218 Z_FLAG = (Flags >> 29) & 1; \ | |
219 N_FLAG = (Flags >> 31) & 1; \ | |
220 C_FLAG = (Flags >> 25) & 1; \ | |
221 V_FLAG = (Flags >> 26) & 1; \ | |
222 } | |
223 #define CMN_RD_RS \ | |
224 { \ | |
225 register int Flags; \ | |
226 register int Result; \ | |
227 asm volatile ("addco. %0, %2, %3\n" \ | |
228 "mcrxr cr1\n" \ | |
229 "mfcr %1\n" \ | |
230 : "=r" (Result), \ | |
231 "=r" (Flags) \ | |
232 : "r" (reg[dest].I), \ | |
233 "r" (value) \ | |
234 ); \ | |
235 Z_FLAG = (Flags >> 29) & 1; \ | |
236 N_FLAG = (Flags >> 31) & 1; \ | |
237 C_FLAG = (Flags >> 25) & 1; \ | |
238 V_FLAG = (Flags >> 26) & 1; \ | |
239 } | |
240 #define ADC_RD_RS \ | |
241 { \ | |
242 register int Flags; \ | |
243 register int Result; \ | |
244 asm volatile ("mtspr xer, %4\n" \ | |
245 "addeo. %0, %2, %3\n" \ | |
246 "mcrxr cr1\n" \ | |
247 "mfcr %1\n" \ | |
248 : "=r" (Result), \ | |
249 "=r" (Flags) \ | |
250 : "r" (reg[dest].I), \ | |
251 "r" (value), \ | |
252 "r" (C_FLAG << 29) \ | |
253 ); \ | |
254 reg[dest].I = Result; \ | |
255 Z_FLAG = (Flags >> 29) & 1; \ | |
256 N_FLAG = (Flags >> 31) & 1; \ | |
257 C_FLAG = (Flags >> 25) & 1; \ | |
258 V_FLAG = (Flags >> 26) & 1; \ | |
259 } | |
260 #define SUB_RD_RS_RN \ | |
261 { \ | |
262 register int Flags; \ | |
263 register int Result; \ | |
264 asm volatile ("subco. %0, %2, %3\n" \ | |
265 "mcrxr cr1\n" \ | |
266 "mfcr %1\n" \ | |
267 : "=r" (Result), \ | |
268 "=r" (Flags) \ | |
269 : "r" (reg[source].I), \ | |
270 "r" (value) \ | |
271 ); \ | |
272 reg[dest].I = Result; \ | |
273 Z_FLAG = (Flags >> 29) & 1; \ | |
274 N_FLAG = (Flags >> 31) & 1; \ | |
275 C_FLAG = (Flags >> 25) & 1; \ | |
276 V_FLAG = (Flags >> 26) & 1; \ | |
277 } | |
278 #define SUB_RD_RS_O3 SUB_RD_RS_RN | |
279 #define SUB_RN_O8(d) \ | |
280 { \ | |
281 register int Flags; \ | |
282 register int Result; \ | |
283 asm volatile ("subco. %0, %2, %3\n" \ | |
284 "mcrxr cr1\n" \ | |
285 "mfcr %1\n" \ | |
286 : "=r" (Result), \ | |
287 "=r" (Flags) \ | |
288 : "r" (reg[(d)].I), \ | |
289 "r" (opcode & 255) \ | |
290 ); \ | |
291 reg[(d)].I = Result; \ | |
292 Z_FLAG = (Flags >> 29) & 1; \ | |
293 N_FLAG = (Flags >> 31) & 1; \ | |
294 C_FLAG = (Flags >> 25) & 1; \ | |
295 V_FLAG = (Flags >> 26) & 1; \ | |
296 } | |
297 #define CMP_RN_O8(d) \ | |
298 { \ | |
299 register int Flags; \ | |
300 register int Result; \ | |
301 asm volatile ("subco. %0, %2, %3\n" \ | |
302 "mcrxr cr1\n" \ | |
303 "mfcr %1\n" \ | |
304 : "=r" (Result), \ | |
305 "=r" (Flags) \ | |
306 : "r" (reg[(d)].I), \ | |
307 "r" (opcode & 255) \ | |
308 ); \ | |
309 Z_FLAG = (Flags >> 29) & 1; \ | |
310 N_FLAG = (Flags >> 31) & 1; \ | |
311 C_FLAG = (Flags >> 25) & 1; \ | |
312 V_FLAG = (Flags >> 26) & 1; \ | |
313 } | |
314 #define SBC_RD_RS \ | |
315 { \ | |
316 register int Flags; \ | |
317 register int Result; \ | |
318 asm volatile ("mtspr xer, %4\n" \ | |
319 "subfeo. %0, %3, %2\n" \ | |
320 "mcrxr cr1\n" \ | |
321 "mfcr %1\n" \ | |
322 : "=r" (Result), \ | |
323 "=r" (Flags) \ | |
324 : "r" (reg[dest].I), \ | |
325 "r" (value), \ | |
326 "r" (C_FLAG << 29) \ | |
327 ); \ | |
328 reg[dest].I = Result; \ | |
329 Z_FLAG = (Flags >> 29) & 1; \ | |
330 N_FLAG = (Flags >> 31) & 1; \ | |
331 C_FLAG = (Flags >> 25) & 1; \ | |
332 V_FLAG = (Flags >> 26) & 1; \ | |
333 } | |
334 #define LSL_RD_RM_I5 \ | |
335 { \ | |
336 C_FLAG = (reg[source].I >> (32 - shift)) & 1 ? true : false; \ | |
337 value = reg[source].I << shift; \ | |
338 } | |
339 #define LSL_RD_RS \ | |
340 { \ | |
341 C_FLAG = (reg[dest].I >> (32 - value)) & 1 ? true : false; \ | |
342 value = reg[dest].I << value; \ | |
343 } | |
344 #define LSR_RD_RM_I5 \ | |
345 { \ | |
346 C_FLAG = (reg[source].I >> (shift - 1)) & 1 ? true : false; \ | |
347 value = reg[source].I >> shift; \ | |
348 } | |
349 #define LSR_RD_RS \ | |
350 { \ | |
351 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \ | |
352 value = reg[dest].I >> value; \ | |
353 } | |
354 #define ASR_RD_RM_I5 \ | |
355 { \ | |
356 C_FLAG = ((s32)reg[source].I >> (int)(shift - 1)) & 1 ? true : false; \ | |
357 value = (s32)reg[source].I >> (int)shift; \ | |
358 } | |
359 #define ASR_RD_RS \ | |
360 { \ | |
361 C_FLAG = ((s32)reg[dest].I >> (int)(value - 1)) & 1 ? true : false; \ | |
362 value = (s32)reg[dest].I >> (int)value; \ | |
363 } | |
364 #define ROR_RD_RS \ | |
365 { \ | |
366 C_FLAG = (reg[dest].I >> (value - 1)) & 1 ? true : false; \ | |
367 value = ((reg[dest].I << (32 - value)) | \ | |
368 (reg[dest].I >> value)); \ | |
369 } | |
370 #define NEG_RD_RS \ | |
371 { \ | |
372 register int Flags; \ | |
373 register int Result; \ | |
374 asm volatile ("subfco. %0, %2, %3\n" \ | |
375 "mcrxr cr1\n" \ | |
376 "mfcr %1\n" \ | |
377 : "=r" (Result), \ | |
378 "=r" (Flags) \ | |
379 : "r" (reg[source].I), \ | |
380 "r" (0) \ | |
381 ); \ | |
382 reg[dest].I = Result; \ | |
383 Z_FLAG = (Flags >> 29) & 1; \ | |
384 N_FLAG = (Flags >> 31) & 1; \ | |
385 C_FLAG = (Flags >> 25) & 1; \ | |
386 V_FLAG = (Flags >> 26) & 1; \ | |
387 } | |
388 #define CMP_RD_RS \ | |
389 { \ | |
390 register int Flags; \ | |
391 register int Result; \ | |
392 asm volatile ("subco. %0, %2, %3\n" \ | |
393 "mcrxr cr1\n" \ | |
394 "mfcr %1\n" \ | |
395 : "=r" (Result), \ | |
396 "=r" (Flags) \ | |
397 : "r" (reg[dest].I), \ | |
398 "r" (value) \ | |
399 ); \ | |
400 Z_FLAG = (Flags >> 29) & 1; \ | |
401 N_FLAG = (Flags >> 31) & 1; \ | |
402 C_FLAG = (Flags >> 25) & 1; \ | |
403 V_FLAG = (Flags >> 26) & 1; \ | |
404 } | |
405 #else | |
406 #define ADD_RD_RS_RN \ | |
407 asm ("add %1, %%ebx;" \ | |
408 "setsb N_FLAG;" \ | |
409 "setzb Z_FLAG;" \ | |
410 "setcb C_FLAG;" \ | |
411 "setob V_FLAG;" \ | |
412 : "=b" (reg[dest].I) \ | |
413 : "r" (value), "b" (reg[source].I)); | |
414 #define ADD_RD_RS_O3 \ | |
415 asm ("add %1, %%ebx;" \ | |
416 "setsb N_FLAG;" \ | |
417 "setzb Z_FLAG;" \ | |
418 "setcb C_FLAG;" \ | |
419 "setob V_FLAG;" \ | |
420 : "=b" (reg[dest].I) \ | |
421 : "r" (value), "b" (reg[source].I)); | |
422 #define ADD_RN_O8(d) \ | |
423 asm ("add %1, %%ebx;" \ | |
424 "setsb N_FLAG;" \ | |
425 "setzb Z_FLAG;" \ | |
426 "setcb C_FLAG;" \ | |
427 "setob V_FLAG;" \ | |
428 : "=b" (reg[(d)].I) \ | |
429 : "r" (opcode & 255), "b" (reg[(d)].I)); | |
430 #define CMN_RD_RS \ | |
431 asm ("add %0, %1;" \ | |
432 "setsb N_FLAG;" \ | |
433 "setzb Z_FLAG;" \ | |
434 "setcb C_FLAG;" \ | |
435 "setob V_FLAG;" \ | |
436 : \ | |
437 : "r" (value), "r" (reg[dest].I) : "1"); | |
438 #define ADC_RD_RS \ | |
439 asm ("bt $0, C_FLAG;" \ | |
440 "adc %1, %%ebx;" \ | |
441 "setsb N_FLAG;" \ | |
442 "setzb Z_FLAG;" \ | |
443 "setcb C_FLAG;" \ | |
444 "setob V_FLAG;" \ | |
445 : "=b" (reg[dest].I) \ | |
446 : "r" (value), "b" (reg[dest].I)); | |
447 #define SUB_RD_RS_RN \ | |
448 asm ("sub %1, %%ebx;" \ | |
449 "setsb N_FLAG;" \ | |
450 "setzb Z_FLAG;" \ | |
451 "setncb C_FLAG;" \ | |
452 "setob V_FLAG;" \ | |
453 : "=b" (reg[dest].I) \ | |
454 : "r" (value), "b" (reg[source].I)); | |
455 #define SUB_RD_RS_O3 \ | |
456 asm ("sub %1, %%ebx;" \ | |
457 "setsb N_FLAG;" \ | |
458 "setzb Z_FLAG;" \ | |
459 "setncb C_FLAG;" \ | |
460 "setob V_FLAG;" \ | |
461 : "=b" (reg[dest].I) \ | |
462 : "r" (value), "b" (reg[source].I)); | |
463 #define SUB_RN_O8(d) \ | |
464 asm ("sub %1, %%ebx;" \ | |
465 "setsb N_FLAG;" \ | |
466 "setzb Z_FLAG;" \ | |
467 "setncb C_FLAG;" \ | |
468 "setob V_FLAG;" \ | |
469 : "=b" (reg[(d)].I) \ | |
470 : "r" (opcode & 255), "b" (reg[(d)].I)); | |
471 #define CMP_RN_O8(d) \ | |
472 asm ("sub %0, %1;" \ | |
473 "setsb N_FLAG;" \ | |
474 "setzb Z_FLAG;" \ | |
475 "setncb C_FLAG;" \ | |
476 "setob V_FLAG;" \ | |
477 : \ | |
478 : "r" (opcode & 255), "r" (reg[(d)].I) : "1"); | |
479 #define SBC_RD_RS \ | |
480 asm volatile ("bt $0, C_FLAG;" \ | |
481 "cmc;" \ | |
482 "sbb %1, %%ebx;" \ | |
483 "setsb N_FLAG;" \ | |
484 "setzb Z_FLAG;" \ | |
485 "setncb C_FLAG;" \ | |
486 "setob V_FLAG;" \ | |
487 : "=b" (reg[dest].I) \ | |
488 : "r" (value), "b" (reg[dest].I) : "cc", "memory"); | |
489 #define LSL_RD_RM_I5 \ | |
490 asm ("shl %%cl, %%eax;" \ | |
491 "setcb C_FLAG;" \ | |
492 : "=a" (value) \ | |
493 : "a" (reg[source].I), "c" (shift)); | |
494 #define LSL_RD_RS \ | |
495 asm ("shl %%cl, %%eax;" \ | |
496 "setcb C_FLAG;" \ | |
497 : "=a" (value) \ | |
498 : "a" (reg[dest].I), "c" (value)); | |
499 #define LSR_RD_RM_I5 \ | |
500 asm ("shr %%cl, %%eax;" \ | |
501 "setcb C_FLAG;" \ | |
502 : "=a" (value) \ | |
503 : "a" (reg[source].I), "c" (shift)); | |
504 #define LSR_RD_RS \ | |
505 asm ("shr %%cl, %%eax;" \ | |
506 "setcb C_FLAG;" \ | |
507 : "=a" (value) \ | |
508 : "a" (reg[dest].I), "c" (value)); | |
509 #define ASR_RD_RM_I5 \ | |
510 asm ("sar %%cl, %%eax;" \ | |
511 "setcb C_FLAG;" \ | |
512 : "=a" (value) \ | |
513 : "a" (reg[source].I), "c" (shift)); | |
514 #define ASR_RD_RS \ | |
515 asm ("sar %%cl, %%eax;" \ | |
516 "setcb C_FLAG;" \ | |
517 : "=a" (value) \ | |
518 : "a" (reg[dest].I), "c" (value)); | |
519 #define ROR_RD_RS \ | |
520 asm ("ror %%cl, %%eax;" \ | |
521 "setcb C_FLAG;" \ | |
522 : "=a" (value) \ | |
523 : "a" (reg[dest].I), "c" (value)); | |
524 #define NEG_RD_RS \ | |
525 asm ("neg %%ebx;" \ | |
526 "setsb N_FLAG;" \ | |
527 "setzb Z_FLAG;" \ | |
528 "setncb C_FLAG;" \ | |
529 "setob V_FLAG;" \ | |
530 : "=b" (reg[dest].I) \ | |
531 : "b" (reg[source].I)); | |
532 #define CMP_RD_RS \ | |
533 asm ("sub %0, %1;" \ | |
534 "setsb N_FLAG;" \ | |
535 "setzb Z_FLAG;" \ | |
536 "setncb C_FLAG;" \ | |
537 "setob V_FLAG;" \ | |
538 : \ | |
539 : "r" (value), "r" (reg[dest].I) : "1"); | |
540 #endif | |
541 #else | |
542 #define ADD_RD_RS_RN \ | |
543 { \ | |
544 __asm mov eax, source \ | |
545 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \ | |
546 __asm add ebx, value \ | |
547 __asm mov eax, dest \ | |
548 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ | |
549 __asm sets byte ptr N_FLAG \ | |
550 __asm setz byte ptr Z_FLAG \ | |
551 __asm setc byte ptr C_FLAG \ | |
552 __asm seto byte ptr V_FLAG \ | |
553 } | |
554 #define ADD_RD_RS_O3 \ | |
555 { \ | |
556 __asm mov eax, source \ | |
557 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \ | |
558 __asm add ebx, value \ | |
559 __asm mov eax, dest \ | |
560 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ | |
561 __asm sets byte ptr N_FLAG \ | |
562 __asm setz byte ptr Z_FLAG \ | |
563 __asm setc byte ptr C_FLAG \ | |
564 __asm seto byte ptr V_FLAG \ | |
565 } | |
566 #define ADD_RN_O8(d) \ | |
567 { \ | |
568 __asm mov ebx, opcode \ | |
569 __asm and ebx, 255 \ | |
570 __asm add dword ptr [OFFSET reg + 4 * (d)], ebx \ | |
571 __asm sets byte ptr N_FLAG \ | |
572 __asm setz byte ptr Z_FLAG \ | |
573 __asm setc byte ptr C_FLAG \ | |
574 __asm seto byte ptr V_FLAG \ | |
575 } | |
576 #define CMN_RD_RS \ | |
577 { \ | |
578 __asm mov eax, dest \ | |
579 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \ | |
580 __asm add ebx, value \ | |
581 __asm sets byte ptr N_FLAG \ | |
582 __asm setz byte ptr Z_FLAG \ | |
583 __asm setc byte ptr C_FLAG \ | |
584 __asm seto byte ptr V_FLAG \ | |
585 } | |
586 #define ADC_RD_RS \ | |
587 { \ | |
588 __asm mov ebx, dest \ | |
589 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ | |
590 __asm bt word ptr C_FLAG, 0 \ | |
591 __asm adc ebx, value \ | |
592 __asm mov eax, dest \ | |
593 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ | |
594 __asm sets byte ptr N_FLAG \ | |
595 __asm setz byte ptr Z_FLAG \ | |
596 __asm setc byte ptr C_FLAG \ | |
597 __asm seto byte ptr V_FLAG \ | |
598 } | |
599 #define SUB_RD_RS_RN \ | |
600 { \ | |
601 __asm mov eax, source \ | |
602 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \ | |
603 __asm sub ebx, value \ | |
604 __asm mov eax, dest \ | |
605 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ | |
606 __asm sets byte ptr N_FLAG \ | |
607 __asm setz byte ptr Z_FLAG \ | |
608 __asm setnc byte ptr C_FLAG \ | |
609 __asm seto byte ptr V_FLAG \ | |
610 } | |
611 #define SUB_RD_RS_O3 \ | |
612 { \ | |
613 __asm mov eax, source \ | |
614 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \ | |
615 __asm sub ebx, value \ | |
616 __asm mov eax, dest \ | |
617 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ | |
618 __asm sets byte ptr N_FLAG \ | |
619 __asm setz byte ptr Z_FLAG \ | |
620 __asm setnc byte ptr C_FLAG \ | |
621 __asm seto byte ptr V_FLAG \ | |
622 } | |
623 #define SUB_RN_O8(d) \ | |
624 { \ | |
625 __asm mov ebx, opcode \ | |
626 __asm and ebx, 255 \ | |
627 __asm sub dword ptr [OFFSET reg + 4 * (d)], ebx \ | |
628 __asm sets byte ptr N_FLAG \ | |
629 __asm setz byte ptr Z_FLAG \ | |
630 __asm setnc byte ptr C_FLAG \ | |
631 __asm seto byte ptr V_FLAG \ | |
632 } | |
633 #define CMP_RN_O8(d) \ | |
634 { \ | |
635 __asm mov eax, dword ptr [OFFSET reg + 4 * (d)] \ | |
636 __asm mov ebx, opcode \ | |
637 __asm and ebx, 255 \ | |
638 __asm sub eax, ebx \ | |
639 __asm sets byte ptr N_FLAG \ | |
640 __asm setz byte ptr Z_FLAG \ | |
641 __asm setnc byte ptr C_FLAG \ | |
642 __asm seto byte ptr V_FLAG \ | |
643 } | |
644 #define SBC_RD_RS \ | |
645 { \ | |
646 __asm mov ebx, dest \ | |
647 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ | |
648 __asm mov eax, value \ | |
649 __asm bt word ptr C_FLAG, 0 \ | |
650 __asm cmc \ | |
651 __asm sbb ebx, eax \ | |
652 __asm mov eax, dest \ | |
653 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ | |
654 __asm sets byte ptr N_FLAG \ | |
655 __asm setz byte ptr Z_FLAG \ | |
656 __asm setnc byte ptr C_FLAG \ | |
657 __asm seto byte ptr V_FLAG \ | |
658 } | |
659 #define LSL_RD_RM_I5 \ | |
660 { \ | |
661 __asm mov eax, source \ | |
662 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ | |
663 __asm mov cl, byte ptr shift \ | |
664 __asm shl eax, cl \ | |
665 __asm mov value, eax \ | |
666 __asm setc byte ptr C_FLAG \ | |
667 } | |
668 #define LSL_RD_RS \ | |
669 { \ | |
670 __asm mov eax, dest \ | |
671 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ | |
672 __asm mov cl, byte ptr value \ | |
673 __asm shl eax, cl \ | |
674 __asm mov value, eax \ | |
675 __asm setc byte ptr C_FLAG \ | |
676 } | |
677 #define LSR_RD_RM_I5 \ | |
678 { \ | |
679 __asm mov eax, source \ | |
680 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ | |
681 __asm mov cl, byte ptr shift \ | |
682 __asm shr eax, cl \ | |
683 __asm mov value, eax \ | |
684 __asm setc byte ptr C_FLAG \ | |
685 } | |
686 #define LSR_RD_RS \ | |
687 { \ | |
688 __asm mov eax, dest \ | |
689 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ | |
690 __asm mov cl, byte ptr value \ | |
691 __asm shr eax, cl \ | |
692 __asm mov value, eax \ | |
693 __asm setc byte ptr C_FLAG \ | |
694 } | |
695 #define ASR_RD_RM_I5 \ | |
696 { \ | |
697 __asm mov eax, source \ | |
698 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ | |
699 __asm mov cl, byte ptr shift \ | |
700 __asm sar eax, cl \ | |
701 __asm mov value, eax \ | |
702 __asm setc byte ptr C_FLAG \ | |
703 } | |
704 #define ASR_RD_RS \ | |
705 { \ | |
706 __asm mov eax, dest \ | |
707 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ | |
708 __asm mov cl, byte ptr value \ | |
709 __asm sar eax, cl \ | |
710 __asm mov value, eax \ | |
711 __asm setc byte ptr C_FLAG \ | |
712 } | |
713 #define ROR_RD_RS \ | |
714 { \ | |
715 __asm mov eax, dest \ | |
716 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \ | |
717 __asm mov cl, byte ptr value \ | |
718 __asm ror eax, cl \ | |
719 __asm mov value, eax \ | |
720 __asm setc byte ptr C_FLAG \ | |
721 } | |
722 #define NEG_RD_RS \ | |
723 { \ | |
724 __asm mov ebx, source \ | |
725 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \ | |
726 __asm neg ebx \ | |
727 __asm mov eax, dest \ | |
728 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \ | |
729 __asm sets byte ptr N_FLAG \ | |
730 __asm setz byte ptr Z_FLAG \ | |
731 __asm setnc byte ptr C_FLAG \ | |
732 __asm seto byte ptr V_FLAG \ | |
733 } | |
734 #define CMP_RD_RS \ | |
735 { \ | |
736 __asm mov eax, dest \ | |
737 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \ | |
738 __asm sub ebx, value \ | |
739 __asm sets byte ptr N_FLAG \ | |
740 __asm setz byte ptr Z_FLAG \ | |
741 __asm setnc byte ptr C_FLAG \ | |
742 __asm seto byte ptr V_FLAG \ | |
743 } | |
744 #endif | |
745 #endif | |
746 | |
747 u32 opcode = CPUReadHalfWordQuick(armNextPC); | |
748 clockTicks = thumbCycles[opcode >> 8] + memoryWaitFetch[(armNextPC >> 24) & 15]; | |
749 #ifndef FINAL_VERSION | |
750 if (armNextPC == stop) | |
751 { | |
752 armNextPC = armNextPC++; | |
753 } | |
754 #endif | |
755 | |
756 armNextPC = reg[15].I; | |
757 reg[15].I += 2; | |
758 | |
759 switch (opcode >> 8) | |
760 { | |
761 case 0x00: | |
762 case 0x01: | |
763 case 0x02: | |
764 case 0x03: | |
765 case 0x04: | |
766 case 0x05: | |
767 case 0x06: | |
768 case 0x07: | |
769 { | |
770 // LSL Rd, Rm, #Imm 5 | |
771 int dest = opcode & 0x07; | |
772 int source = (opcode >> 3) & 0x07; | |
773 int shift = (opcode >> 6) & 0x1f; | |
774 u32 value; | |
775 | |
776 if (shift) | |
777 { | |
778 LSL_RD_RM_I5; | |
779 } | |
780 else | |
781 { | |
782 value = reg[source].I; | |
783 } | |
784 reg[dest].I = value; | |
785 // C_FLAG set above | |
786 N_FLAG = (value & 0x80000000 ? true : false); | |
787 Z_FLAG = (value ? false : true); | |
788 } | |
789 break; | |
790 case 0x08: | |
791 case 0x09: | |
792 case 0x0a: | |
793 case 0x0b: | |
794 case 0x0c: | |
795 case 0x0d: | |
796 case 0x0e: | |
797 case 0x0f: | |
798 { | |
799 // LSR Rd, Rm, #Imm 5 | |
800 int dest = opcode & 0x07; | |
801 int source = (opcode >> 3) & 0x07; | |
802 int shift = (opcode >> 6) & 0x1f; | |
803 u32 value; | |
804 | |
805 if (shift) | |
806 { | |
807 LSR_RD_RM_I5; | |
808 } | |
809 else | |
810 { | |
811 C_FLAG = reg[source].I & 0x80000000 ? true : false; | |
812 value = 0; | |
813 } | |
814 reg[dest].I = value; | |
815 // C_FLAG set above | |
816 N_FLAG = (value & 0x80000000 ? true : false); | |
817 Z_FLAG = (value ? false : true); | |
818 } | |
819 break; | |
820 case 0x10: | |
821 case 0x11: | |
822 case 0x12: | |
823 case 0x13: | |
824 case 0x14: | |
825 case 0x15: | |
826 case 0x16: | |
827 case 0x17: | |
828 { | |
829 // ASR Rd, Rm, #Imm 5 | |
830 int dest = opcode & 0x07; | |
831 int source = (opcode >> 3) & 0x07; | |
832 int shift = (opcode >> 6) & 0x1f; | |
833 u32 value; | |
834 | |
835 if (shift) | |
836 { | |
837 ASR_RD_RM_I5; | |
838 } | |
839 else | |
840 { | |
841 if (reg[source].I & 0x80000000) | |
842 { | |
843 value = 0xFFFFFFFF; | |
844 C_FLAG = true; | |
845 } | |
846 else | |
847 { | |
848 value = 0; | |
849 C_FLAG = false; | |
850 } | |
851 } | |
852 reg[dest].I = value; | |
853 // C_FLAG set above | |
854 N_FLAG = (value & 0x80000000 ? true : false); | |
855 Z_FLAG = (value ? false : true); | |
856 } | |
857 break; | |
858 case 0x18: | |
859 case 0x19: | |
860 { | |
861 // ADD Rd, Rs, Rn | |
862 int dest = opcode & 0x07; | |
863 int source = (opcode >> 3) & 0x07; | |
864 u32 value = reg[(opcode >> 6) & 0x07].I; | |
865 ADD_RD_RS_RN; | |
866 } | |
867 break; | |
868 case 0x1a: | |
869 case 0x1b: | |
870 { | |
871 // SUB Rd, Rs, Rn | |
872 int dest = opcode & 0x07; | |
873 int source = (opcode >> 3) & 0x07; | |
874 u32 value = reg[(opcode >> 6) & 0x07].I; | |
875 SUB_RD_RS_RN; | |
876 } | |
877 break; | |
878 case 0x1c: | |
879 case 0x1d: | |
880 { | |
881 // ADD Rd, Rs, #Offset3 | |
882 int dest = opcode & 0x07; | |
883 int source = (opcode >> 3) & 0x07; | |
884 u32 value = (opcode >> 6) & 7; | |
885 ADD_RD_RS_O3; | |
886 } | |
887 break; | |
888 case 0x1e: | |
889 case 0x1f: | |
890 { | |
891 // SUB Rd, Rs, #Offset3 | |
892 int dest = opcode & 0x07; | |
893 int source = (opcode >> 3) & 0x07; | |
894 u32 value = (opcode >> 6) & 7; | |
895 SUB_RD_RS_O3; | |
896 } | |
897 break; | |
898 case 0x20: | |
899 // MOV R0, #Offset8 | |
900 reg[0].I = opcode & 255; | |
901 N_FLAG = false; | |
902 Z_FLAG = (reg[0].I ? false : true); | |
903 break; | |
904 case 0x21: | |
905 // MOV R1, #Offset8 | |
906 reg[1].I = opcode & 255; | |
907 N_FLAG = false; | |
908 Z_FLAG = (reg[1].I ? false : true); | |
909 break; | |
910 case 0x22: | |
911 // MOV R2, #Offset8 | |
912 reg[2].I = opcode & 255; | |
913 N_FLAG = false; | |
914 Z_FLAG = (reg[2].I ? false : true); | |
915 break; | |
916 case 0x23: | |
917 // MOV R3, #Offset8 | |
918 reg[3].I = opcode & 255; | |
919 N_FLAG = false; | |
920 Z_FLAG = (reg[3].I ? false : true); | |
921 break; | |
922 case 0x24: | |
923 // MOV R4, #Offset8 | |
924 reg[4].I = opcode & 255; | |
925 N_FLAG = false; | |
926 Z_FLAG = (reg[4].I ? false : true); | |
927 break; | |
928 case 0x25: | |
929 // MOV R5, #Offset8 | |
930 reg[5].I = opcode & 255; | |
931 N_FLAG = false; | |
932 Z_FLAG = (reg[5].I ? false : true); | |
933 break; | |
934 case 0x26: | |
935 // MOV R6, #Offset8 | |
936 reg[6].I = opcode & 255; | |
937 N_FLAG = false; | |
938 Z_FLAG = (reg[6].I ? false : true); | |
939 break; | |
940 case 0x27: | |
941 // MOV R7, #Offset8 | |
942 reg[7].I = opcode & 255; | |
943 N_FLAG = false; | |
944 Z_FLAG = (reg[7].I ? false : true); | |
945 break; | |
946 case 0x28: | |
947 // CMP R0, #Offset8 | |
948 CMP_RN_O8(0); | |
949 break; | |
950 case 0x29: | |
951 // CMP R1, #Offset8 | |
952 CMP_RN_O8(1); | |
953 break; | |
954 case 0x2a: | |
955 // CMP R2, #Offset8 | |
956 CMP_RN_O8(2); | |
957 break; | |
958 case 0x2b: | |
959 // CMP R3, #Offset8 | |
960 CMP_RN_O8(3); | |
961 break; | |
962 case 0x2c: | |
963 // CMP R4, #Offset8 | |
964 CMP_RN_O8(4); | |
965 break; | |
966 case 0x2d: | |
967 // CMP R5, #Offset8 | |
968 CMP_RN_O8(5); | |
969 break; | |
970 case 0x2e: | |
971 // CMP R6, #Offset8 | |
972 CMP_RN_O8(6); | |
973 break; | |
974 case 0x2f: | |
975 // CMP R7, #Offset8 | |
976 CMP_RN_O8(7); | |
977 break; | |
978 case 0x30: | |
979 // ADD R0,#Offset8 | |
980 ADD_RN_O8(0); | |
981 break; | |
982 case 0x31: | |
983 // ADD R1,#Offset8 | |
984 ADD_RN_O8(1); | |
985 break; | |
986 case 0x32: | |
987 // ADD R2,#Offset8 | |
988 ADD_RN_O8(2); | |
989 break; | |
990 case 0x33: | |
991 // ADD R3,#Offset8 | |
992 ADD_RN_O8(3); | |
993 break; | |
994 case 0x34: | |
995 // ADD R4,#Offset8 | |
996 ADD_RN_O8(4); | |
997 break; | |
998 case 0x35: | |
999 // ADD R5,#Offset8 | |
1000 ADD_RN_O8(5); | |
1001 break; | |
1002 case 0x36: | |
1003 // ADD R6,#Offset8 | |
1004 ADD_RN_O8(6); | |
1005 break; | |
1006 case 0x37: | |
1007 // ADD R7,#Offset8 | |
1008 ADD_RN_O8(7); | |
1009 break; | |
1010 case 0x38: | |
1011 // SUB R0,#Offset8 | |
1012 SUB_RN_O8(0); | |
1013 break; | |
1014 case 0x39: | |
1015 // SUB R1,#Offset8 | |
1016 SUB_RN_O8(1); | |
1017 break; | |
1018 case 0x3a: | |
1019 // SUB R2,#Offset8 | |
1020 SUB_RN_O8(2); | |
1021 break; | |
1022 case 0x3b: | |
1023 // SUB R3,#Offset8 | |
1024 SUB_RN_O8(3); | |
1025 break; | |
1026 case 0x3c: | |
1027 // SUB R4,#Offset8 | |
1028 SUB_RN_O8(4); | |
1029 break; | |
1030 case 0x3d: | |
1031 // SUB R5,#Offset8 | |
1032 SUB_RN_O8(5); | |
1033 break; | |
1034 case 0x3e: | |
1035 // SUB R6,#Offset8 | |
1036 SUB_RN_O8(6); | |
1037 break; | |
1038 case 0x3f: | |
1039 // SUB R7,#Offset8 | |
1040 SUB_RN_O8(7); | |
1041 break; | |
1042 case 0x40: | |
1043 switch ((opcode >> 6) & 3) | |
1044 { | |
1045 case 0x00: | |
1046 { | |
1047 // AND Rd, Rs | |
1048 int dest = opcode & 7; | |
1049 reg[dest].I &= reg[(opcode >> 3) & 7].I; | |
1050 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1051 Z_FLAG = reg[dest].I ? false : true; | |
1052 #ifdef BKPT_SUPPORT | |
1053 #define THUMB_CONSOLE_OUTPUT(a, b) \ | |
1054 if ((opcode == 0x4000) && (reg[0].I == 0xC0DED00D)) { \ | |
1055 extern void (*dbgOutput)(char *, u32); \ | |
1056 dbgOutput((a), (b)); \ | |
1057 } | |
1058 #else | |
1059 #define THUMB_CONSOLE_OUTPUT(a, b) | |
1060 #endif | |
1061 THUMB_CONSOLE_OUTPUT(NULL, reg[2].I); | |
1062 } | |
1063 break; | |
1064 case 0x01: | |
1065 // EOR Rd, Rs | |
1066 { | |
1067 int dest = opcode & 7; | |
1068 reg[dest].I ^= reg[(opcode >> 3) & 7].I; | |
1069 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1070 Z_FLAG = reg[dest].I ? false : true; | |
1071 } | |
1072 break; | |
1073 case 0x02: | |
1074 // LSL Rd, Rs | |
1075 { | |
1076 int dest = opcode & 7; | |
1077 u32 value = reg[(opcode >> 3) & 7].B.B0; | |
1078 if (value) | |
1079 { | |
1080 if (value == 32) | |
1081 { | |
1082 value = 0; | |
1083 C_FLAG = (reg[dest].I & 1 ? true : false); | |
1084 } | |
1085 else if (value < 32) | |
1086 { | |
1087 LSL_RD_RS; | |
1088 } | |
1089 else | |
1090 { | |
1091 value = 0; | |
1092 C_FLAG = false; | |
1093 } | |
1094 reg[dest].I = value; | |
1095 } | |
1096 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1097 Z_FLAG = reg[dest].I ? false : true; | |
1098 clockTicks++; | |
1099 } | |
1100 break; | |
1101 case 0x03: | |
1102 { | |
1103 // LSR Rd, Rs | |
1104 int dest = opcode & 7; | |
1105 u32 value = reg[(opcode >> 3) & 7].B.B0; | |
1106 if (value) | |
1107 { | |
1108 if (value == 32) | |
1109 { | |
1110 value = 0; | |
1111 C_FLAG = (reg[dest].I & 0x80000000 ? true : false); | |
1112 } | |
1113 else if (value < 32) | |
1114 { | |
1115 LSR_RD_RS; | |
1116 } | |
1117 else | |
1118 { | |
1119 value = 0; | |
1120 C_FLAG = false; | |
1121 } | |
1122 reg[dest].I = value; | |
1123 } | |
1124 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1125 Z_FLAG = reg[dest].I ? false : true; | |
1126 clockTicks++; | |
1127 } | |
1128 break; | |
1129 } | |
1130 break; | |
1131 case 0x41: | |
1132 switch ((opcode >> 6) & 3) | |
1133 { | |
1134 case 0x00: | |
1135 { | |
1136 // ASR Rd, Rs | |
1137 int dest = opcode & 7; | |
1138 u32 value = reg[(opcode >> 3) & 7].B.B0; | |
1139 // ASR | |
1140 if (value) | |
1141 { | |
1142 if (value < 32) | |
1143 { | |
1144 ASR_RD_RS; | |
1145 reg[dest].I = value; | |
1146 } | |
1147 else | |
1148 { | |
1149 if (reg[dest].I & 0x80000000) | |
1150 { | |
1151 reg[dest].I = 0xFFFFFFFF; | |
1152 C_FLAG = true; | |
1153 } | |
1154 else | |
1155 { | |
1156 reg[dest].I = 0x00000000; | |
1157 C_FLAG = false; | |
1158 } | |
1159 } | |
1160 } | |
1161 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1162 Z_FLAG = reg[dest].I ? false : true; | |
1163 clockTicks++; | |
1164 } | |
1165 break; | |
1166 case 0x01: | |
1167 { | |
1168 // ADC Rd, Rs | |
1169 int dest = opcode & 0x07; | |
1170 u32 value = reg[(opcode >> 3) & 7].I; | |
1171 // ADC | |
1172 ADC_RD_RS; | |
1173 } | |
1174 break; | |
1175 case 0x02: | |
1176 { | |
1177 // SBC Rd, Rs | |
1178 int dest = opcode & 0x07; | |
1179 u32 value = reg[(opcode >> 3) & 7].I; | |
1180 | |
1181 // SBC | |
1182 SBC_RD_RS; | |
1183 } | |
1184 break; | |
1185 case 0x03: | |
1186 // ROR Rd, Rs | |
1187 { | |
1188 int dest = opcode & 7; | |
1189 u32 value = reg[(opcode >> 3) & 7].B.B0; | |
1190 | |
1191 if (value) | |
1192 { | |
1193 value = value & 0x1f; | |
1194 if (value == 0) | |
1195 { | |
1196 C_FLAG = (reg[dest].I & 0x80000000 ? true : false); | |
1197 } | |
1198 else | |
1199 { | |
1200 ROR_RD_RS; | |
1201 reg[dest].I = value; | |
1202 } | |
1203 } | |
1204 clockTicks++; | |
1205 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1206 Z_FLAG = reg[dest].I ? false : true; | |
1207 } | |
1208 break; | |
1209 } | |
1210 break; | |
1211 case 0x42: | |
1212 switch ((opcode >> 6) & 3) | |
1213 { | |
1214 case 0x00: | |
1215 { | |
1216 // TST Rd, Rs | |
1217 u32 value = reg[opcode & 7].I & reg[(opcode >> 3) & 7].I; | |
1218 N_FLAG = value & 0x80000000 ? true : false; | |
1219 Z_FLAG = value ? false : true; | |
1220 } | |
1221 break; | |
1222 case 0x01: | |
1223 { | |
1224 // NEG Rd, Rs | |
1225 int dest = opcode & 7; | |
1226 int source = (opcode >> 3) & 7; | |
1227 NEG_RD_RS; | |
1228 } | |
1229 break; | |
1230 case 0x02: | |
1231 { | |
1232 // CMP Rd, Rs | |
1233 int dest = opcode & 7; | |
1234 u32 value = reg[(opcode >> 3) & 7].I; | |
1235 CMP_RD_RS; | |
1236 } | |
1237 break; | |
1238 case 0x03: | |
1239 { | |
1240 // CMN Rd, Rs | |
1241 int dest = opcode & 7; | |
1242 u32 value = reg[(opcode >> 3) & 7].I; | |
1243 // CMN | |
1244 CMN_RD_RS; | |
1245 } | |
1246 break; | |
1247 } | |
1248 break; | |
1249 case 0x43: | |
1250 switch ((opcode >> 6) & 3) | |
1251 { | |
1252 case 0x00: | |
1253 { | |
1254 // ORR Rd, Rs | |
1255 int dest = opcode & 7; | |
1256 reg[dest].I |= reg[(opcode >> 3) & 7].I; | |
1257 Z_FLAG = reg[dest].I ? false : true; | |
1258 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1259 } | |
1260 break; | |
1261 case 0x01: | |
1262 { | |
1263 // MUL Rd, Rs | |
1264 int dest = opcode & 7; | |
1265 u32 rm = reg[(opcode >> 3) & 7].I; | |
1266 reg[dest].I = reg[dest].I * rm; | |
1267 if (((s32)rm) < 0) | |
1268 rm = ~rm; | |
1269 if ((rm & 0xFFFFFF00) == 0) | |
1270 clockTicks += 1; | |
1271 else if ((rm & 0xFFFF0000) == 0) | |
1272 clockTicks += 2; | |
1273 else if ((rm & 0xFF000000) == 0) | |
1274 clockTicks += 3; | |
1275 else | |
1276 clockTicks += 4; | |
1277 Z_FLAG = reg[dest].I ? false : true; | |
1278 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1279 } | |
1280 break; | |
1281 case 0x02: | |
1282 { | |
1283 // BIC Rd, Rs | |
1284 int dest = opcode & 7; | |
1285 reg[dest].I &= (~reg[(opcode >> 3) & 7].I); | |
1286 Z_FLAG = reg[dest].I ? false : true; | |
1287 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1288 } | |
1289 break; | |
1290 case 0x03: | |
1291 { | |
1292 // MVN Rd, Rs | |
1293 int dest = opcode & 7; | |
1294 reg[dest].I = ~reg[(opcode >> 3) & 7].I; | |
1295 Z_FLAG = reg[dest].I ? false : true; | |
1296 N_FLAG = reg[dest].I & 0x80000000 ? true : false; | |
1297 } | |
1298 break; | |
1299 } | |
1300 break; | |
1301 case 0x44: | |
1302 { | |
1303 int dest = opcode & 7; | |
1304 int base = (opcode >> 3) & 7; | |
1305 switch ((opcode >> 6) & 3) | |
1306 { | |
1307 default: | |
1308 goto unknown_thumb; | |
1309 case 1: | |
1310 // ADD Rd, Hs | |
1311 reg[dest].I += reg[base + 8].I; | |
1312 break; | |
1313 case 2: | |
1314 // ADD Hd, Rs | |
1315 reg[dest + 8].I += reg[base].I; | |
1316 if (dest == 7) | |
1317 { | |
1318 reg[15].I &= 0xFFFFFFFE; | |
1319 armNextPC = reg[15].I; | |
1320 reg[15].I += 2; | |
1321 clockTicks++; | |
1322 } | |
1323 break; | |
1324 case 3: | |
1325 // ADD Hd, Hs | |
1326 reg[dest + 8].I += reg[base + 8].I; | |
1327 if (dest == 7) | |
1328 { | |
1329 reg[15].I &= 0xFFFFFFFE; | |
1330 armNextPC = reg[15].I; | |
1331 reg[15].I += 2; | |
1332 clockTicks++; | |
1333 } | |
1334 break; | |
1335 } | |
1336 } | |
1337 break; | |
1338 case 0x45: | |
1339 { | |
1340 int dest = opcode & 7; | |
1341 int base = (opcode >> 3) & 7; | |
1342 u32 value; | |
1343 switch ((opcode >> 6) & 3) | |
1344 { | |
1345 case 0: | |
1346 // CMP Rd, Hs | |
1347 value = reg[base].I; | |
1348 CMP_RD_RS; | |
1349 break; | |
1350 case 1: | |
1351 // CMP Rd, Hs | |
1352 value = reg[base + 8].I; | |
1353 CMP_RD_RS; | |
1354 break; | |
1355 case 2: | |
1356 // CMP Hd, Rs | |
1357 value = reg[base].I; | |
1358 dest += 8; | |
1359 CMP_RD_RS; | |
1360 break; | |
1361 case 3: | |
1362 // CMP Hd, Hs | |
1363 value = reg[base + 8].I; | |
1364 dest += 8; | |
1365 CMP_RD_RS; | |
1366 break; | |
1367 } | |
1368 } | |
1369 break; | |
1370 case 0x46: | |
1371 { | |
1372 int dest = opcode & 7; | |
1373 int base = (opcode >> 3) & 7; | |
1374 switch ((opcode >> 6) & 3) | |
1375 { | |
1376 case 0: | |
1377 // this form should not be used... | |
1378 // MOV Rd, Rs | |
1379 reg[dest].I = reg[base].I; | |
1380 break; | |
1381 case 1: | |
1382 // MOV Rd, Hs | |
1383 reg[dest].I = reg[base + 8].I; | |
1384 break; | |
1385 case 2: | |
1386 // MOV Hd, Rs | |
1387 reg[dest + 8].I = reg[base].I; | |
1388 if (dest == 7) | |
1389 { | |
1390 reg[15].I &= 0xFFFFFFFE; | |
1391 armNextPC = reg[15].I; | |
1392 reg[15].I += 2; | |
1393 clockTicks++; | |
1394 } | |
1395 break; | |
1396 case 3: | |
1397 // MOV Hd, Hs | |
1398 reg[dest + 8].I = reg[base + 8].I; | |
1399 if (dest == 7) | |
1400 { | |
1401 reg[15].I &= 0xFFFFFFFE; | |
1402 armNextPC = reg[15].I; | |
1403 reg[15].I += 2; | |
1404 clockTicks++; | |
1405 } | |
1406 break; | |
1407 } | |
1408 } | |
1409 break; | |
1410 case 0x47: | |
1411 { | |
1412 int base = (opcode >> 3) & 7; | |
1413 switch ((opcode >> 6) & 3) | |
1414 { | |
1415 case 0: | |
1416 // BX Rs | |
1417 reg[15].I = (reg[base].I) & 0xFFFFFFFE; | |
1418 if (reg[base].I & 1) | |
1419 { | |
1420 armState = false; | |
1421 armNextPC = reg[15].I; | |
1422 reg[15].I += 2; | |
1423 } | |
1424 else | |
1425 { | |
1426 armState = true; | |
1427 reg[15].I &= 0xFFFFFFFC; | |
1428 armNextPC = reg[15].I; | |
1429 reg[15].I += 4; | |
1430 } | |
1431 break; | |
1432 case 1: | |
1433 // BX Hs | |
1434 reg[15].I = (reg[8 + base].I) & 0xFFFFFFFE; | |
1435 if (reg[8 + base].I & 1) | |
1436 { | |
1437 armState = false; | |
1438 armNextPC = reg[15].I; | |
1439 reg[15].I += 2; | |
1440 } | |
1441 else | |
1442 { | |
1443 armState = true; | |
1444 reg[15].I &= 0xFFFFFFFC; | |
1445 armNextPC = reg[15].I; | |
1446 reg[15].I += 4; | |
1447 } | |
1448 break; | |
1449 default: | |
1450 goto unknown_thumb; | |
1451 } | |
1452 } | |
1453 break; | |
1454 case 0x48: | |
1455 // LDR R0,[PC, #Imm] | |
1456 { | |
1457 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); | |
1458 reg[0].I = CPUReadMemoryQuick(address); | |
1459 clockTicks += CPUUpdateTicksAccess32(address); | |
1460 } | |
1461 break; | |
1462 case 0x49: | |
1463 // LDR R1,[PC, #Imm] | |
1464 { | |
1465 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); | |
1466 reg[1].I = CPUReadMemoryQuick(address); | |
1467 clockTicks += CPUUpdateTicksAccess32(address); | |
1468 } | |
1469 break; | |
1470 case 0x4a: | |
1471 // LDR R2,[PC, #Imm] | |
1472 { | |
1473 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); | |
1474 reg[2].I = CPUReadMemoryQuick(address); | |
1475 clockTicks += CPUUpdateTicksAccess32(address); | |
1476 } | |
1477 break; | |
1478 case 0x4b: | |
1479 // LDR R3,[PC, #Imm] | |
1480 { | |
1481 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); | |
1482 reg[3].I = CPUReadMemoryQuick(address); | |
1483 clockTicks += CPUUpdateTicksAccess32(address); | |
1484 } | |
1485 break; | |
1486 case 0x4c: | |
1487 // LDR R4,[PC, #Imm] | |
1488 { | |
1489 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); | |
1490 reg[4].I = CPUReadMemoryQuick(address); | |
1491 clockTicks += CPUUpdateTicksAccess32(address); | |
1492 } | |
1493 break; | |
1494 case 0x4d: | |
1495 // LDR R5,[PC, #Imm] | |
1496 { | |
1497 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); | |
1498 reg[5].I = CPUReadMemoryQuick(address); | |
1499 clockTicks += CPUUpdateTicksAccess32(address); | |
1500 } | |
1501 break; | |
1502 case 0x4e: | |
1503 // LDR R6,[PC, #Imm] | |
1504 { | |
1505 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); | |
1506 reg[6].I = CPUReadMemoryQuick(address); | |
1507 clockTicks += CPUUpdateTicksAccess32(address); | |
1508 } | |
1509 break; | |
1510 case 0x4f: | |
1511 // LDR R7,[PC, #Imm] | |
1512 { | |
1513 u32 address = (reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2); | |
1514 reg[7].I = CPUReadMemoryQuick(address); | |
1515 clockTicks += CPUUpdateTicksAccess32(address); | |
1516 } | |
1517 break; | |
1518 case 0x50: | |
1519 case 0x51: | |
1520 // STR Rd, [Rs, Rn] | |
1521 { | |
1522 u32 | |
1523 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I; | |
1524 CPUWriteMemory(address, | |
1525 reg[opcode & 7].I); | |
1526 clockTicks += CPUUpdateTicksAccess32(address); | |
1527 } | |
1528 break; | |
1529 case 0x52: | |
1530 case 0x53: | |
1531 // STRH Rd, [Rs, Rn] | |
1532 { | |
1533 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I; | |
1534 CPUWriteHalfWord(address, | |
1535 reg[opcode & 7].W.W0); | |
1536 clockTicks += CPUUpdateTicksAccess16(address); | |
1537 } | |
1538 break; | |
1539 case 0x54: | |
1540 case 0x55: | |
1541 // STRB Rd, [Rs, Rn] | |
1542 { | |
1543 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I; | |
1544 CPUWriteByte(address, | |
1545 reg[opcode & 7].B.B0); | |
1546 clockTicks += CPUUpdateTicksAccess16(address); | |
1547 } | |
1548 break; | |
1549 case 0x56: | |
1550 case 0x57: | |
1551 // LDSB Rd, [Rs, Rn] | |
1552 { | |
1553 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I; | |
1554 reg[opcode & 7].I = (s8)CPUReadByte(address); | |
1555 clockTicks += CPUUpdateTicksAccess16(address); | |
1556 } | |
1557 break; | |
1558 case 0x58: | |
1559 case 0x59: | |
1560 // LDR Rd, [Rs, Rn] | |
1561 { | |
1562 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I; | |
1563 reg[opcode & 7].I = CPUReadMemory(address); | |
1564 clockTicks += CPUUpdateTicksAccess32(address); | |
1565 } | |
1566 break; | |
1567 case 0x5a: | |
1568 case 0x5b: | |
1569 // LDRH Rd, [Rs, Rn] | |
1570 { | |
1571 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I; | |
1572 reg[opcode & 7].I = CPUReadHalfWord(address); | |
1573 clockTicks += CPUUpdateTicksAccess16(address); | |
1574 } | |
1575 break; | |
1576 case 0x5c: | |
1577 case 0x5d: | |
1578 // LDRB Rd, [Rs, Rn] | |
1579 { | |
1580 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I; | |
1581 reg[opcode & 7].I = CPUReadByte(address); | |
1582 clockTicks += CPUUpdateTicksAccess16(address); | |
1583 } | |
1584 break; | |
1585 case 0x5e: | |
1586 case 0x5f: | |
1587 // LDSH Rd, [Rs, Rn] | |
1588 { | |
1589 u32 address = reg[(opcode >> 3) & 7].I + reg[(opcode >> 6) & 7].I; | |
1590 reg[opcode & 7].I = (s16)CPUReadHalfWordSigned(address); | |
1591 clockTicks += CPUUpdateTicksAccess16(address); | |
1592 } | |
1593 break; | |
1594 case 0x60: | |
1595 case 0x61: | |
1596 case 0x62: | |
1597 case 0x63: | |
1598 case 0x64: | |
1599 case 0x65: | |
1600 case 0x66: | |
1601 case 0x67: | |
1602 // STR Rd, [Rs, #Imm] | |
1603 { | |
1604 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 2); | |
1605 CPUWriteMemory(address, | |
1606 reg[opcode & 7].I); | |
1607 clockTicks += CPUUpdateTicksAccess32(address); | |
1608 } | |
1609 break; | |
1610 case 0x68: | |
1611 case 0x69: | |
1612 case 0x6a: | |
1613 case 0x6b: | |
1614 case 0x6c: | |
1615 case 0x6d: | |
1616 case 0x6e: | |
1617 case 0x6f: | |
1618 // LDR Rd, [Rs, #Imm] | |
1619 { | |
1620 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 2); | |
1621 reg[opcode & 7].I = CPUReadMemory(address); | |
1622 clockTicks += CPUUpdateTicksAccess32(address); | |
1623 } | |
1624 break; | |
1625 case 0x70: | |
1626 case 0x71: | |
1627 case 0x72: | |
1628 case 0x73: | |
1629 case 0x74: | |
1630 case 0x75: | |
1631 case 0x76: | |
1632 case 0x77: | |
1633 // STRB Rd, [Rs, #Imm] | |
1634 { | |
1635 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31)); | |
1636 CPUWriteByte(address, | |
1637 reg[opcode & 7].B.B0); | |
1638 clockTicks += CPUUpdateTicksAccess16(address); | |
1639 } | |
1640 break; | |
1641 case 0x78: | |
1642 case 0x79: | |
1643 case 0x7a: | |
1644 case 0x7b: | |
1645 case 0x7c: | |
1646 case 0x7d: | |
1647 case 0x7e: | |
1648 case 0x7f: | |
1649 // LDRB Rd, [Rs, #Imm] | |
1650 { | |
1651 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31)); | |
1652 reg[opcode & 7].I = CPUReadByte(address); | |
1653 clockTicks += CPUUpdateTicksAccess16(address); | |
1654 } | |
1655 break; | |
1656 case 0x80: | |
1657 case 0x81: | |
1658 case 0x82: | |
1659 case 0x83: | |
1660 case 0x84: | |
1661 case 0x85: | |
1662 case 0x86: | |
1663 case 0x87: | |
1664 // STRH Rd, [Rs, #Imm] | |
1665 { | |
1666 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 1); | |
1667 CPUWriteHalfWord(address, | |
1668 reg[opcode & 7].W.W0); | |
1669 clockTicks += CPUUpdateTicksAccess16(address); | |
1670 } | |
1671 break; | |
1672 case 0x88: | |
1673 case 0x89: | |
1674 case 0x8a: | |
1675 case 0x8b: | |
1676 case 0x8c: | |
1677 case 0x8d: | |
1678 case 0x8e: | |
1679 case 0x8f: | |
1680 // LDRH Rd, [Rs, #Imm] | |
1681 { | |
1682 u32 address = reg[(opcode >> 3) & 7].I + (((opcode >> 6) & 31) << 1); | |
1683 reg[opcode & 7].I = CPUReadHalfWord(address); | |
1684 clockTicks += CPUUpdateTicksAccess16(address); | |
1685 } | |
1686 break; | |
1687 case 0x90: | |
1688 // STR R0, [SP, #Imm] | |
1689 { | |
1690 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1691 CPUWriteMemory(address, reg[0].I); | |
1692 clockTicks += CPUUpdateTicksAccess32(address); | |
1693 } | |
1694 break; | |
1695 case 0x91: | |
1696 // STR R1, [SP, #Imm] | |
1697 { | |
1698 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1699 CPUWriteMemory(address, reg[1].I); | |
1700 clockTicks += CPUUpdateTicksAccess32(address); | |
1701 } | |
1702 break; | |
1703 case 0x92: | |
1704 // STR R2, [SP, #Imm] | |
1705 { | |
1706 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1707 CPUWriteMemory(address, reg[2].I); | |
1708 clockTicks += CPUUpdateTicksAccess32(address); | |
1709 } | |
1710 break; | |
1711 case 0x93: | |
1712 // STR R3, [SP, #Imm] | |
1713 { | |
1714 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1715 CPUWriteMemory(address, reg[3].I); | |
1716 clockTicks += CPUUpdateTicksAccess32(address); | |
1717 } | |
1718 break; | |
1719 case 0x94: | |
1720 // STR R4, [SP, #Imm] | |
1721 { | |
1722 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1723 CPUWriteMemory(address, reg[4].I); | |
1724 clockTicks += CPUUpdateTicksAccess32(address); | |
1725 } | |
1726 break; | |
1727 case 0x95: | |
1728 // STR R5, [SP, #Imm] | |
1729 { | |
1730 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1731 CPUWriteMemory(address, reg[5].I); | |
1732 clockTicks += CPUUpdateTicksAccess32(address); | |
1733 } | |
1734 break; | |
1735 case 0x96: | |
1736 // STR R6, [SP, #Imm] | |
1737 { | |
1738 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1739 CPUWriteMemory(address, reg[6].I); | |
1740 clockTicks += CPUUpdateTicksAccess32(address); | |
1741 } | |
1742 break; | |
1743 case 0x97: | |
1744 // STR R7, [SP, #Imm] | |
1745 { | |
1746 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1747 CPUWriteMemory(address, reg[7].I); | |
1748 clockTicks += CPUUpdateTicksAccess32(address); | |
1749 } | |
1750 break; | |
1751 case 0x98: | |
1752 // LDR R0, [SP, #Imm] | |
1753 { | |
1754 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1755 reg[0].I = CPUReadMemoryQuick(address); | |
1756 clockTicks += CPUUpdateTicksAccess32(address); | |
1757 } | |
1758 break; | |
1759 case 0x99: | |
1760 // LDR R1, [SP, #Imm] | |
1761 { | |
1762 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1763 reg[1].I = CPUReadMemoryQuick(address); | |
1764 clockTicks += CPUUpdateTicksAccess32(address); | |
1765 } | |
1766 break; | |
1767 case 0x9a: | |
1768 // LDR R2, [SP, #Imm] | |
1769 { | |
1770 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1771 reg[2].I = CPUReadMemoryQuick(address); | |
1772 clockTicks += CPUUpdateTicksAccess32(address); | |
1773 } | |
1774 break; | |
1775 case 0x9b: | |
1776 // LDR R3, [SP, #Imm] | |
1777 { | |
1778 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1779 reg[3].I = CPUReadMemoryQuick(address); | |
1780 clockTicks += CPUUpdateTicksAccess32(address); | |
1781 } | |
1782 break; | |
1783 case 0x9c: | |
1784 // LDR R4, [SP, #Imm] | |
1785 { | |
1786 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1787 reg[4].I = CPUReadMemoryQuick(address); | |
1788 clockTicks += CPUUpdateTicksAccess32(address); | |
1789 } | |
1790 break; | |
1791 case 0x9d: | |
1792 // LDR R5, [SP, #Imm] | |
1793 { | |
1794 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1795 reg[5].I = CPUReadMemoryQuick(address); | |
1796 clockTicks += CPUUpdateTicksAccess32(address); | |
1797 } | |
1798 break; | |
1799 case 0x9e: | |
1800 // LDR R6, [SP, #Imm] | |
1801 { | |
1802 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1803 reg[6].I = CPUReadMemoryQuick(address); | |
1804 clockTicks += CPUUpdateTicksAccess32(address); | |
1805 } | |
1806 break; | |
1807 case 0x9f: | |
1808 // LDR R7, [SP, #Imm] | |
1809 { | |
1810 u32 address = reg[13].I + ((opcode & 255) << 2); | |
1811 reg[7].I = CPUReadMemoryQuick(address); | |
1812 clockTicks += CPUUpdateTicksAccess32(address); | |
1813 } | |
1814 break; | |
1815 case 0xa0: | |
1816 // ADD R0, PC, Imm | |
1817 reg[0].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2); | |
1818 break; | |
1819 case 0xa1: | |
1820 // ADD R1, PC, Imm | |
1821 reg[1].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2); | |
1822 break; | |
1823 case 0xa2: | |
1824 // ADD R2, PC, Imm | |
1825 reg[2].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2); | |
1826 break; | |
1827 case 0xa3: | |
1828 // ADD R3, PC, Imm | |
1829 reg[3].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2); | |
1830 break; | |
1831 case 0xa4: | |
1832 // ADD R4, PC, Imm | |
1833 reg[4].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2); | |
1834 break; | |
1835 case 0xa5: | |
1836 // ADD R5, PC, Imm | |
1837 reg[5].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2); | |
1838 break; | |
1839 case 0xa6: | |
1840 // ADD R6, PC, Imm | |
1841 reg[6].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2); | |
1842 break; | |
1843 case 0xa7: | |
1844 // ADD R7, PC, Imm | |
1845 reg[7].I = (reg[15].I & 0xFFFFFFFC) + ((opcode & 255) << 2); | |
1846 break; | |
1847 case 0xa8: | |
1848 // ADD R0, SP, Imm | |
1849 reg[0].I = reg[13].I + ((opcode & 255) << 2); | |
1850 break; | |
1851 case 0xa9: | |
1852 // ADD R1, SP, Imm | |
1853 reg[1].I = reg[13].I + ((opcode & 255) << 2); | |
1854 break; | |
1855 case 0xaa: | |
1856 // ADD R2, SP, Imm | |
1857 reg[2].I = reg[13].I + ((opcode & 255) << 2); | |
1858 break; | |
1859 case 0xab: | |
1860 // ADD R3, SP, Imm | |
1861 reg[3].I = reg[13].I + ((opcode & 255) << 2); | |
1862 break; | |
1863 case 0xac: | |
1864 // ADD R4, SP, Imm | |
1865 reg[4].I = reg[13].I + ((opcode & 255) << 2); | |
1866 break; | |
1867 case 0xad: | |
1868 // ADD R5, SP, Imm | |
1869 reg[5].I = reg[13].I + ((opcode & 255) << 2); | |
1870 break; | |
1871 case 0xae: | |
1872 // ADD R6, SP, Imm | |
1873 reg[6].I = reg[13].I + ((opcode & 255) << 2); | |
1874 break; | |
1875 case 0xaf: | |
1876 // ADD R7, SP, Imm | |
1877 reg[7].I = reg[13].I + ((opcode & 255) << 2); | |
1878 break; | |
1879 case 0xb0: | |
1880 { | |
1881 // ADD SP, Imm | |
1882 int offset = (opcode & 127) << 2; | |
1883 if (opcode & 0x80) | |
1884 offset = -offset; | |
1885 reg[13].I += offset; | |
1886 } | |
1887 break; | |
1888 #define PUSH_REG(val, r) \ | |
1889 if (opcode & (val)) { \ | |
1890 CPUWriteMemory(address, reg[(r)].I); \ | |
1891 if (offset) \ | |
1892 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \ | |
1893 else \ | |
1894 clockTicks += 1 + CPUUpdateTicksAccess32(address); \ | |
1895 offset = 1; \ | |
1896 address += 4; \ | |
1897 } | |
1898 case 0xb4: | |
1899 // PUSH {Rlist} | |
1900 { | |
1901 int offset = 0; | |
1902 u32 temp = reg[13].I - 4 * cpuBitsSet[opcode & 0xff]; | |
1903 u32 address = temp & 0xFFFFFFFC; | |
1904 PUSH_REG(1, 0); | |
1905 PUSH_REG(2, 1); | |
1906 PUSH_REG(4, 2); | |
1907 PUSH_REG(8, 3); | |
1908 PUSH_REG(16, 4); | |
1909 PUSH_REG(32, 5); | |
1910 PUSH_REG(64, 6); | |
1911 PUSH_REG(128, 7); | |
1912 reg[13].I = temp; | |
1913 } | |
1914 break; | |
1915 case 0xb5: | |
1916 // PUSH {Rlist, LR} | |
1917 { | |
1918 int offset = 0; | |
1919 u32 temp = reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff]; | |
1920 u32 address = temp & 0xFFFFFFFC; | |
1921 PUSH_REG(1, 0); | |
1922 PUSH_REG(2, 1); | |
1923 PUSH_REG(4, 2); | |
1924 PUSH_REG(8, 3); | |
1925 PUSH_REG(16, 4); | |
1926 PUSH_REG(32, 5); | |
1927 PUSH_REG(64, 6); | |
1928 PUSH_REG(128, 7); | |
1929 PUSH_REG(256, 14); | |
1930 reg[13].I = temp; | |
1931 } | |
1932 break; | |
1933 #define POP_REG(val, r) \ | |
1934 if (opcode & (val)) { \ | |
1935 reg[(r)].I = CPUReadMemory(address); \ | |
1936 if (offset) \ | |
1937 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); \ | |
1938 else \ | |
1939 clockTicks += 2 + CPUUpdateTicksAccess32(address); \ | |
1940 offset = 1; \ | |
1941 address += 4; \ | |
1942 } | |
1943 case 0xbc: | |
1944 // POP {Rlist} | |
1945 { | |
1946 int offset = 0; | |
1947 u32 address = reg[13].I & 0xFFFFFFFC; | |
1948 u32 temp = reg[13].I + 4 * cpuBitsSet[opcode & 0xFF]; | |
1949 POP_REG(1, 0); | |
1950 POP_REG(2, 1); | |
1951 POP_REG(4, 2); | |
1952 POP_REG(8, 3); | |
1953 POP_REG(16, 4); | |
1954 POP_REG(32, 5); | |
1955 POP_REG(64, 6); | |
1956 POP_REG(128, 7); | |
1957 reg[13].I = temp; | |
1958 } | |
1959 break; | |
1960 case 0xbd: | |
1961 // POP {Rlist, PC} | |
1962 { | |
1963 int offset = 0; | |
1964 u32 address = reg[13].I & 0xFFFFFFFC; | |
1965 u32 temp = reg[13].I + 4 + 4 * cpuBitsSet[opcode & 0xFF]; | |
1966 POP_REG(1, 0); | |
1967 POP_REG(2, 1); | |
1968 POP_REG(4, 2); | |
1969 POP_REG(8, 3); | |
1970 POP_REG(16, 4); | |
1971 POP_REG(32, 5); | |
1972 POP_REG(64, 6); | |
1973 POP_REG(128, 7); | |
1974 reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE); | |
1975 if (offset) | |
1976 clockTicks += CPUUpdateTicksAccessSeq32(address); | |
1977 else | |
1978 clockTicks += CPUUpdateTicksAccess32(address); | |
1979 armNextPC = reg[15].I; | |
1980 reg[15].I += 2; | |
1981 reg[13].I = temp; | |
1982 } | |
1983 break; | |
1984 #define THUMB_STM_REG(val, r, b) \ | |
1985 if (opcode & (val)) { \ | |
1986 CPUWriteMemory(address, reg[(r)].I); \ | |
1987 if (!offset) { \ | |
1988 reg[(b)].I = temp; \ | |
1989 clockTicks += 1 + CPUUpdateTicksAccess32(address); \ | |
1990 } else \ | |
1991 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \ | |
1992 offset = 1; \ | |
1993 address += 4; \ | |
1994 } | |
1995 case 0xc0: | |
1996 { | |
1997 // STM R0!, {Rlist} | |
1998 u32 address = reg[0].I & 0xFFFFFFFC; | |
1999 u32 temp = reg[0].I + 4 * cpuBitsSet[opcode & 0xff]; | |
2000 int offset = 0; | |
2001 // store | |
2002 THUMB_STM_REG(1, 0, 0); | |
2003 THUMB_STM_REG(2, 1, 0); | |
2004 THUMB_STM_REG(4, 2, 0); | |
2005 THUMB_STM_REG(8, 3, 0); | |
2006 THUMB_STM_REG(16, 4, 0); | |
2007 THUMB_STM_REG(32, 5, 0); | |
2008 THUMB_STM_REG(64, 6, 0); | |
2009 THUMB_STM_REG(128, 7, 0); | |
2010 } | |
2011 break; | |
2012 case 0xc1: | |
2013 { | |
2014 // STM R1!, {Rlist} | |
2015 u32 address = reg[1].I & 0xFFFFFFFC; | |
2016 u32 temp = reg[1].I + 4 * cpuBitsSet[opcode & 0xff]; | |
2017 int offset = 0; | |
2018 // store | |
2019 THUMB_STM_REG(1, 0, 1); | |
2020 THUMB_STM_REG(2, 1, 1); | |
2021 THUMB_STM_REG(4, 2, 1); | |
2022 THUMB_STM_REG(8, 3, 1); | |
2023 THUMB_STM_REG(16, 4, 1); | |
2024 THUMB_STM_REG(32, 5, 1); | |
2025 THUMB_STM_REG(64, 6, 1); | |
2026 THUMB_STM_REG(128, 7, 1); | |
2027 } | |
2028 break; | |
2029 case 0xc2: | |
2030 { | |
2031 // STM R2!, {Rlist} | |
2032 u32 address = reg[2].I & 0xFFFFFFFC; | |
2033 u32 temp = reg[2].I + 4 * cpuBitsSet[opcode & 0xff]; | |
2034 int offset = 0; | |
2035 // store | |
2036 THUMB_STM_REG(1, 0, 2); | |
2037 THUMB_STM_REG(2, 1, 2); | |
2038 THUMB_STM_REG(4, 2, 2); | |
2039 THUMB_STM_REG(8, 3, 2); | |
2040 THUMB_STM_REG(16, 4, 2); | |
2041 THUMB_STM_REG(32, 5, 2); | |
2042 THUMB_STM_REG(64, 6, 2); | |
2043 THUMB_STM_REG(128, 7, 2); | |
2044 } | |
2045 break; | |
2046 case 0xc3: | |
2047 { | |
2048 // STM R3!, {Rlist} | |
2049 u32 address = reg[3].I & 0xFFFFFFFC; | |
2050 u32 temp = reg[3].I + 4 * cpuBitsSet[opcode & 0xff]; | |
2051 int offset = 0; | |
2052 // store | |
2053 THUMB_STM_REG(1, 0, 3); | |
2054 THUMB_STM_REG(2, 1, 3); | |
2055 THUMB_STM_REG(4, 2, 3); | |
2056 THUMB_STM_REG(8, 3, 3); | |
2057 THUMB_STM_REG(16, 4, 3); | |
2058 THUMB_STM_REG(32, 5, 3); | |
2059 THUMB_STM_REG(64, 6, 3); | |
2060 THUMB_STM_REG(128, 7, 3); | |
2061 } | |
2062 break; | |
2063 case 0xc4: | |
2064 { | |
2065 // STM R4!, {Rlist} | |
2066 u32 address = reg[4].I & 0xFFFFFFFC; | |
2067 u32 temp = reg[4].I + 4 * cpuBitsSet[opcode & 0xff]; | |
2068 int offset = 0; | |
2069 // store | |
2070 THUMB_STM_REG(1, 0, 4); | |
2071 THUMB_STM_REG(2, 1, 4); | |
2072 THUMB_STM_REG(4, 2, 4); | |
2073 THUMB_STM_REG(8, 3, 4); | |
2074 THUMB_STM_REG(16, 4, 4); | |
2075 THUMB_STM_REG(32, 5, 4); | |
2076 THUMB_STM_REG(64, 6, 4); | |
2077 THUMB_STM_REG(128, 7, 4); | |
2078 } | |
2079 break; | |
2080 case 0xc5: | |
2081 { | |
2082 // STM R5!, {Rlist} | |
2083 u32 address = reg[5].I & 0xFFFFFFFC; | |
2084 u32 temp = reg[5].I + 4 * cpuBitsSet[opcode & 0xff]; | |
2085 int offset = 0; | |
2086 // store | |
2087 THUMB_STM_REG(1, 0, 5); | |
2088 THUMB_STM_REG(2, 1, 5); | |
2089 THUMB_STM_REG(4, 2, 5); | |
2090 THUMB_STM_REG(8, 3, 5); | |
2091 THUMB_STM_REG(16, 4, 5); | |
2092 THUMB_STM_REG(32, 5, 5); | |
2093 THUMB_STM_REG(64, 6, 5); | |
2094 THUMB_STM_REG(128, 7, 5); | |
2095 } | |
2096 break; | |
2097 case 0xc6: | |
2098 { | |
2099 // STM R6!, {Rlist} | |
2100 u32 address = reg[6].I & 0xFFFFFFFC; | |
2101 u32 temp = reg[6].I + 4 * cpuBitsSet[opcode & 0xff]; | |
2102 int offset = 0; | |
2103 // store | |
2104 THUMB_STM_REG(1, 0, 6); | |
2105 THUMB_STM_REG(2, 1, 6); | |
2106 THUMB_STM_REG(4, 2, 6); | |
2107 THUMB_STM_REG(8, 3, 6); | |
2108 THUMB_STM_REG(16, 4, 6); | |
2109 THUMB_STM_REG(32, 5, 6); | |
2110 THUMB_STM_REG(64, 6, 6); | |
2111 THUMB_STM_REG(128, 7, 6); | |
2112 } | |
2113 break; | |
2114 case 0xc7: | |
2115 { | |
2116 // STM R7!, {Rlist} | |
2117 u32 address = reg[7].I & 0xFFFFFFFC; | |
2118 u32 temp = reg[7].I + 4 * cpuBitsSet[opcode & 0xff]; | |
2119 int offset = 0; | |
2120 // store | |
2121 THUMB_STM_REG(1, 0, 7); | |
2122 THUMB_STM_REG(2, 1, 7); | |
2123 THUMB_STM_REG(4, 2, 7); | |
2124 THUMB_STM_REG(8, 3, 7); | |
2125 THUMB_STM_REG(16, 4, 7); | |
2126 THUMB_STM_REG(32, 5, 7); | |
2127 THUMB_STM_REG(64, 6, 7); | |
2128 THUMB_STM_REG(128, 7, 7); | |
2129 } | |
2130 break; | |
2131 #define THUMB_LDM_REG(val, r) \ | |
2132 if (opcode & (val)) { \ | |
2133 reg[(r)].I = CPUReadMemory(address); \ | |
2134 if (offset) \ | |
2135 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address); \ | |
2136 else \ | |
2137 clockTicks += 2 + CPUUpdateTicksAccess32(address); \ | |
2138 offset = 1; \ | |
2139 address += 4; \ | |
2140 } | |
2141 case 0xc8: | |
2142 { | |
2143 // LDM R0!, {Rlist} | |
2144 u32 address = reg[0].I & 0xFFFFFFFC; | |
2145 u32 temp = reg[0].I + 4 * cpuBitsSet[opcode & 0xFF]; | |
2146 int offset = 0; | |
2147 // load | |
2148 THUMB_LDM_REG(1, 0); | |
2149 THUMB_LDM_REG(2, 1); | |
2150 THUMB_LDM_REG(4, 2); | |
2151 THUMB_LDM_REG(8, 3); | |
2152 THUMB_LDM_REG(16, 4); | |
2153 THUMB_LDM_REG(32, 5); | |
2154 THUMB_LDM_REG(64, 6); | |
2155 THUMB_LDM_REG(128, 7); | |
2156 if (!(opcode & 1)) | |
2157 reg[0].I = temp; | |
2158 } | |
2159 break; | |
2160 case 0xc9: | |
2161 { | |
2162 // LDM R1!, {Rlist} | |
2163 u32 address = reg[1].I & 0xFFFFFFFC; | |
2164 u32 temp = reg[1].I + 4 * cpuBitsSet[opcode & 0xFF]; | |
2165 int offset = 0; | |
2166 // load | |
2167 THUMB_LDM_REG(1, 0); | |
2168 THUMB_LDM_REG(2, 1); | |
2169 THUMB_LDM_REG(4, 2); | |
2170 THUMB_LDM_REG(8, 3); | |
2171 THUMB_LDM_REG(16, 4); | |
2172 THUMB_LDM_REG(32, 5); | |
2173 THUMB_LDM_REG(64, 6); | |
2174 THUMB_LDM_REG(128, 7); | |
2175 if (!(opcode & 2)) | |
2176 reg[1].I = temp; | |
2177 } | |
2178 break; | |
2179 case 0xca: | |
2180 { | |
2181 // LDM R2!, {Rlist} | |
2182 u32 address = reg[2].I & 0xFFFFFFFC; | |
2183 u32 temp = reg[2].I + 4 * cpuBitsSet[opcode & 0xFF]; | |
2184 int offset = 0; | |
2185 // load | |
2186 THUMB_LDM_REG(1, 0); | |
2187 THUMB_LDM_REG(2, 1); | |
2188 THUMB_LDM_REG(4, 2); | |
2189 THUMB_LDM_REG(8, 3); | |
2190 THUMB_LDM_REG(16, 4); | |
2191 THUMB_LDM_REG(32, 5); | |
2192 THUMB_LDM_REG(64, 6); | |
2193 THUMB_LDM_REG(128, 7); | |
2194 if (!(opcode & 4)) | |
2195 reg[2].I = temp; | |
2196 } | |
2197 break; | |
2198 case 0xcb: | |
2199 { | |
2200 // LDM R3!, {Rlist} | |
2201 u32 address = reg[3].I & 0xFFFFFFFC; | |
2202 u32 temp = reg[3].I + 4 * cpuBitsSet[opcode & 0xFF]; | |
2203 int offset = 0; | |
2204 // load | |
2205 THUMB_LDM_REG(1, 0); | |
2206 THUMB_LDM_REG(2, 1); | |
2207 THUMB_LDM_REG(4, 2); | |
2208 THUMB_LDM_REG(8, 3); | |
2209 THUMB_LDM_REG(16, 4); | |
2210 THUMB_LDM_REG(32, 5); | |
2211 THUMB_LDM_REG(64, 6); | |
2212 THUMB_LDM_REG(128, 7); | |
2213 if (!(opcode & 8)) | |
2214 reg[3].I = temp; | |
2215 } | |
2216 break; | |
2217 case 0xcc: | |
2218 { | |
2219 // LDM R4!, {Rlist} | |
2220 u32 address = reg[4].I & 0xFFFFFFFC; | |
2221 u32 temp = reg[4].I + 4 * cpuBitsSet[opcode & 0xFF]; | |
2222 int offset = 0; | |
2223 // load | |
2224 THUMB_LDM_REG(1, 0); | |
2225 THUMB_LDM_REG(2, 1); | |
2226 THUMB_LDM_REG(4, 2); | |
2227 THUMB_LDM_REG(8, 3); | |
2228 THUMB_LDM_REG(16, 4); | |
2229 THUMB_LDM_REG(32, 5); | |
2230 THUMB_LDM_REG(64, 6); | |
2231 THUMB_LDM_REG(128, 7); | |
2232 if (!(opcode & 16)) | |
2233 reg[4].I = temp; | |
2234 } | |
2235 break; | |
2236 case 0xcd: | |
2237 { | |
2238 // LDM R5!, {Rlist} | |
2239 u32 address = reg[5].I & 0xFFFFFFFC; | |
2240 u32 temp = reg[5].I + 4 * cpuBitsSet[opcode & 0xFF]; | |
2241 int offset = 0; | |
2242 // load | |
2243 THUMB_LDM_REG(1, 0); | |
2244 THUMB_LDM_REG(2, 1); | |
2245 THUMB_LDM_REG(4, 2); | |
2246 THUMB_LDM_REG(8, 3); | |
2247 THUMB_LDM_REG(16, 4); | |
2248 THUMB_LDM_REG(32, 5); | |
2249 THUMB_LDM_REG(64, 6); | |
2250 THUMB_LDM_REG(128, 7); | |
2251 if (!(opcode & 32)) | |
2252 reg[5].I = temp; | |
2253 } | |
2254 break; | |
2255 case 0xce: | |
2256 { | |
2257 // LDM R6!, {Rlist} | |
2258 u32 address = reg[6].I & 0xFFFFFFFC; | |
2259 u32 temp = reg[6].I + 4 * cpuBitsSet[opcode & 0xFF]; | |
2260 int offset = 0; | |
2261 // load | |
2262 THUMB_LDM_REG(1, 0); | |
2263 THUMB_LDM_REG(2, 1); | |
2264 THUMB_LDM_REG(4, 2); | |
2265 THUMB_LDM_REG(8, 3); | |
2266 THUMB_LDM_REG(16, 4); | |
2267 THUMB_LDM_REG(32, 5); | |
2268 THUMB_LDM_REG(64, 6); | |
2269 THUMB_LDM_REG(128, 7); | |
2270 if (!(opcode & 64)) | |
2271 reg[6].I = temp; | |
2272 } | |
2273 break; | |
2274 case 0xcf: | |
2275 { | |
2276 // LDM R7!, {Rlist} | |
2277 u32 address = reg[7].I & 0xFFFFFFFC; | |
2278 u32 temp = reg[7].I + 4 * cpuBitsSet[opcode & 0xFF]; | |
2279 int offset = 0; | |
2280 // load | |
2281 THUMB_LDM_REG(1, 0); | |
2282 THUMB_LDM_REG(2, 1); | |
2283 THUMB_LDM_REG(4, 2); | |
2284 THUMB_LDM_REG(8, 3); | |
2285 THUMB_LDM_REG(16, 4); | |
2286 THUMB_LDM_REG(32, 5); | |
2287 THUMB_LDM_REG(64, 6); | |
2288 THUMB_LDM_REG(128, 7); | |
2289 if (!(opcode & 128)) | |
2290 reg[7].I = temp; | |
2291 } | |
2292 break; | |
2293 case 0xd0: | |
2294 // BEQ offset | |
2295 if (Z_FLAG) | |
2296 { | |
2297 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2298 armNextPC = reg[15].I; | |
2299 reg[15].I += 2; | |
2300 clockTicks = 3; | |
2301 } | |
2302 break; | |
2303 case 0xd1: | |
2304 // BNE offset | |
2305 if (!Z_FLAG) | |
2306 { | |
2307 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2308 armNextPC = reg[15].I; | |
2309 reg[15].I += 2; | |
2310 clockTicks = 3; | |
2311 } | |
2312 break; | |
2313 case 0xd2: | |
2314 // BCS offset | |
2315 if (C_FLAG) | |
2316 { | |
2317 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2318 armNextPC = reg[15].I; | |
2319 reg[15].I += 2; | |
2320 clockTicks = 3; | |
2321 } | |
2322 break; | |
2323 case 0xd3: | |
2324 // BCC offset | |
2325 if (!C_FLAG) | |
2326 { | |
2327 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2328 armNextPC = reg[15].I; | |
2329 reg[15].I += 2; | |
2330 clockTicks = 3; | |
2331 } | |
2332 break; | |
2333 case 0xd4: | |
2334 // BMI offset | |
2335 if (N_FLAG) | |
2336 { | |
2337 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2338 armNextPC = reg[15].I; | |
2339 reg[15].I += 2; | |
2340 clockTicks = 3; | |
2341 } | |
2342 break; | |
2343 case 0xd5: | |
2344 // BPL offset | |
2345 if (!N_FLAG) | |
2346 { | |
2347 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2348 armNextPC = reg[15].I; | |
2349 reg[15].I += 2; | |
2350 clockTicks = 3; | |
2351 } | |
2352 break; | |
2353 case 0xd6: | |
2354 // BVS offset | |
2355 if (V_FLAG) | |
2356 { | |
2357 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2358 armNextPC = reg[15].I; | |
2359 reg[15].I += 2; | |
2360 clockTicks = 3; | |
2361 } | |
2362 break; | |
2363 case 0xd7: | |
2364 // BVC offset | |
2365 if (!V_FLAG) | |
2366 { | |
2367 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2368 armNextPC = reg[15].I; | |
2369 reg[15].I += 2; | |
2370 clockTicks = 3; | |
2371 } | |
2372 break; | |
2373 case 0xd8: | |
2374 // BHI offset | |
2375 if (C_FLAG && !Z_FLAG) | |
2376 { | |
2377 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2378 armNextPC = reg[15].I; | |
2379 reg[15].I += 2; | |
2380 clockTicks = 3; | |
2381 } | |
2382 break; | |
2383 case 0xd9: | |
2384 // BLS offset | |
2385 if (!C_FLAG || Z_FLAG) | |
2386 { | |
2387 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2388 armNextPC = reg[15].I; | |
2389 reg[15].I += 2; | |
2390 clockTicks = 3; | |
2391 } | |
2392 break; | |
2393 case 0xda: | |
2394 // BGE offset | |
2395 if (N_FLAG == V_FLAG) | |
2396 { | |
2397 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2398 armNextPC = reg[15].I; | |
2399 reg[15].I += 2; | |
2400 clockTicks = 3; | |
2401 } | |
2402 break; | |
2403 case 0xdb: | |
2404 // BLT offset | |
2405 if (N_FLAG != V_FLAG) | |
2406 { | |
2407 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2408 armNextPC = reg[15].I; | |
2409 reg[15].I += 2; | |
2410 clockTicks = 3; | |
2411 } | |
2412 break; | |
2413 case 0xdc: | |
2414 // BGT offset | |
2415 if (!Z_FLAG && (N_FLAG == V_FLAG)) | |
2416 { | |
2417 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2418 armNextPC = reg[15].I; | |
2419 reg[15].I += 2; | |
2420 clockTicks = 3; | |
2421 } | |
2422 break; | |
2423 case 0xdd: | |
2424 // BLE offset | |
2425 if (Z_FLAG || (N_FLAG != V_FLAG)) | |
2426 { | |
2427 reg[15].I += ((s8)(opcode & 0xFF)) << 1; | |
2428 armNextPC = reg[15].I; | |
2429 reg[15].I += 2; | |
2430 clockTicks = 3; | |
2431 } | |
2432 break; | |
2433 case 0xdf: | |
2434 // SWI #comment | |
2435 CPUSoftwareInterrupt(opcode & 0xFF); | |
2436 break; | |
2437 case 0xe0: | |
2438 case 0xe1: | |
2439 case 0xe2: | |
2440 case 0xe3: | |
2441 case 0xe4: | |
2442 case 0xe5: | |
2443 case 0xe6: | |
2444 case 0xe7: | |
2445 { | |
2446 // B offset | |
2447 int offset = (opcode & 0x3FF) << 1; | |
2448 if (opcode & 0x0400) | |
2449 offset |= 0xFFFFF800; | |
2450 reg[15].I += offset; | |
2451 armNextPC = reg[15].I; | |
2452 reg[15].I += 2; | |
2453 } | |
2454 break; | |
2455 case 0xf0: | |
2456 case 0xf1: | |
2457 case 0xf2: | |
2458 case 0xf3: | |
2459 { | |
2460 // BLL #offset | |
2461 int offset = (opcode & 0x7FF); | |
2462 reg[14].I = reg[15].I + (offset << 12); | |
2463 } | |
2464 break; | |
2465 case 0xf4: | |
2466 case 0xf5: | |
2467 case 0xf6: | |
2468 case 0xf7: | |
2469 { | |
2470 // BLL #offset | |
2471 int offset = (opcode & 0x7FF); | |
2472 reg[14].I = reg[15].I + ((offset << 12) | 0xFF800000); | |
2473 } | |
2474 break; | |
2475 case 0xf8: | |
2476 case 0xf9: | |
2477 case 0xfa: | |
2478 case 0xfb: | |
2479 case 0xfc: | |
2480 case 0xfd: | |
2481 case 0xfe: | |
2482 case 0xff: | |
2483 { | |
2484 // BLH #offset | |
2485 int offset = (opcode & 0x7FF); | |
2486 u32 temp = reg[15].I - 2; | |
2487 reg[15].I = (reg[14].I + (offset << 1)) & 0xFFFFFFFE; | |
2488 armNextPC = reg[15].I; | |
2489 reg[15].I += 2; | |
2490 reg[14].I = temp | 1; | |
2491 } | |
2492 break; | |
2493 #ifdef BKPT_SUPPORT | |
2494 case 0xbe: | |
2495 // BKPT #comment | |
2496 extern void (*dbgSignal)(int, int); | |
2497 reg[15].I -= 2; | |
2498 armNextPC -= 2; | |
2499 dbgSignal(5, opcode & 255); | |
2500 return; | |
2501 #endif | |
2502 case 0xb1: | |
2503 case 0xb2: | |
2504 case 0xb3: | |
2505 case 0xb6: | |
2506 case 0xb7: | |
2507 case 0xb8: | |
2508 case 0xb9: | |
2509 case 0xba: | |
2510 case 0xbb: | |
2511 #ifndef BKPT_SUPPORT | |
2512 case 0xbe: | |
2513 #endif | |
2514 case 0xbf: | |
2515 case 0xde: | |
2516 default: | |
2517 unknown_thumb: | |
2518 #ifdef GBA_LOGGING | |
2519 if (systemVerbose & VERBOSE_UNDEFINED) | |
2520 log("Undefined THUMB instruction %04x at %08x\n", opcode, armNextPC - 2); | |
2521 #endif | |
2522 CPUUndefinedException(); | |
2523 break; | |
2524 } |