annotate src/gba/arm-new.h @ 351:a6a123af22f6

mapped celadon store inventories.
author Robert McIntyre <rlm@mit.edu>
date Sun, 08 Apr 2012 21:12:07 -0500
parents f9f4f1b99eed
children
rev   line source
rlm@1 1 #ifdef BKPT_SUPPORT
rlm@1 2 #define CONSOLE_OUTPUT(a, b) \
rlm@1 3 extern void (*dbgOutput)(char *, u32); \
rlm@1 4 if ((opcode == 0xe0000000) && (reg[0].I == 0xC0DED00D)) { \
rlm@1 5 dbgOutput((a), (b)); \
rlm@1 6 }
rlm@1 7 #else
rlm@1 8 #define CONSOLE_OUTPUT(a, b)
rlm@1 9 #endif
rlm@1 10
rlm@1 11 #define OP_AND \
rlm@1 12 reg[dest].I = reg[(opcode >> 16) & 15].I & value; \
rlm@1 13 CONSOLE_OUTPUT(NULL, reg[2].I);
rlm@1 14
rlm@1 15 #define OP_ANDS \
rlm@1 16 reg[dest].I = reg[(opcode >> 16) & 15].I & value; \
rlm@1 17 \
rlm@1 18 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
rlm@1 19 Z_FLAG = (reg[dest].I) ? false : true; \
rlm@1 20 C_FLAG = C_OUT;
rlm@1 21
rlm@1 22 #define OP_EOR \
rlm@1 23 reg[dest].I = reg[(opcode >> 16) & 15].I ^ value;
rlm@1 24
rlm@1 25 #define OP_EORS \
rlm@1 26 reg[dest].I = reg[(opcode >> 16) & 15].I ^ value; \
rlm@1 27 \
rlm@1 28 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
rlm@1 29 Z_FLAG = (reg[dest].I) ? false : true; \
rlm@1 30 C_FLAG = C_OUT;
rlm@1 31 #ifdef C_CORE
rlm@1 32 #define NEG(i) ((i) >> 31)
rlm@1 33 #define POS(i) ((~(i)) >> 31)
rlm@1 34 #define ADDCARRY(a, b, c) \
rlm@1 35 C_FLAG = ((NEG(a) & NEG(b)) | \
rlm@1 36 (NEG(a) & POS(c)) | \
rlm@1 37 (NEG(b) & POS(c))) ? true : false;
rlm@1 38 #define ADDOVERFLOW(a, b, c) \
rlm@1 39 V_FLAG = ((NEG(a) & NEG(b) & POS(c)) | \
rlm@1 40 (POS(a) & POS(b) & NEG(c))) ? true : false;
rlm@1 41 #define SUBCARRY(a, b, c) \
rlm@1 42 C_FLAG = ((NEG(a) & POS(b)) | \
rlm@1 43 (NEG(a) & POS(c)) | \
rlm@1 44 (POS(b) & POS(c))) ? true : false;
rlm@1 45 #define SUBOVERFLOW(a, b, c) \
rlm@1 46 V_FLAG = ((NEG(a) & POS(b) & POS(c)) | \
rlm@1 47 (POS(a) & NEG(b) & NEG(c))) ? true : false;
rlm@1 48 #define OP_SUB \
rlm@1 49 { \
rlm@1 50 reg[dest].I = reg[base].I - value; \
rlm@1 51 }
rlm@1 52 #define OP_SUBS \
rlm@1 53 { \
rlm@1 54 u32 lhs = reg[base].I; \
rlm@1 55 u32 rhs = value; \
rlm@1 56 u32 res = lhs - rhs; \
rlm@1 57 reg[dest].I = res; \
rlm@1 58 Z_FLAG = (res == 0) ? true : false; \
rlm@1 59 N_FLAG = NEG(res) ? true : false; \
rlm@1 60 SUBCARRY(lhs, rhs, res); \
rlm@1 61 SUBOVERFLOW(lhs, rhs, res); \
rlm@1 62 }
rlm@1 63 #define OP_RSB \
rlm@1 64 { \
rlm@1 65 reg[dest].I = value - reg[base].I; \
rlm@1 66 }
rlm@1 67 #define OP_RSBS \
rlm@1 68 { \
rlm@1 69 u32 lhs = reg[base].I; \
rlm@1 70 u32 rhs = value; \
rlm@1 71 u32 res = rhs - lhs; \
rlm@1 72 reg[dest].I = res; \
rlm@1 73 Z_FLAG = (res == 0) ? true : false; \
rlm@1 74 N_FLAG = NEG(res) ? true : false; \
rlm@1 75 SUBCARRY(rhs, lhs, res); \
rlm@1 76 SUBOVERFLOW(rhs, lhs, res); \
rlm@1 77 }
rlm@1 78 #define OP_ADD \
rlm@1 79 { \
rlm@1 80 reg[dest].I = reg[base].I + value; \
rlm@1 81 }
rlm@1 82 #define OP_ADDS \
rlm@1 83 { \
rlm@1 84 u32 lhs = reg[base].I; \
rlm@1 85 u32 rhs = value; \
rlm@1 86 u32 res = lhs + rhs; \
rlm@1 87 reg[dest].I = res; \
rlm@1 88 Z_FLAG = (res == 0) ? true : false; \
rlm@1 89 N_FLAG = NEG(res) ? true : false; \
rlm@1 90 ADDCARRY(lhs, rhs, res); \
rlm@1 91 ADDOVERFLOW(lhs, rhs, res); \
rlm@1 92 }
rlm@1 93 #define OP_ADC \
rlm@1 94 { \
rlm@1 95 reg[dest].I = reg[base].I + value + (u32)C_FLAG; \
rlm@1 96 }
rlm@1 97 #define OP_ADCS \
rlm@1 98 { \
rlm@1 99 u32 lhs = reg[base].I; \
rlm@1 100 u32 rhs = value; \
rlm@1 101 u32 res = lhs + rhs + (u32)C_FLAG; \
rlm@1 102 reg[dest].I = res; \
rlm@1 103 Z_FLAG = (res == 0) ? true : false; \
rlm@1 104 N_FLAG = NEG(res) ? true : false; \
rlm@1 105 ADDCARRY(lhs, rhs, res); \
rlm@1 106 ADDOVERFLOW(lhs, rhs, res); \
rlm@1 107 }
rlm@1 108 #define OP_SBC \
rlm@1 109 { \
rlm@1 110 reg[dest].I = reg[base].I - value - !((u32)C_FLAG); \
rlm@1 111 }
rlm@1 112 #define OP_SBCS \
rlm@1 113 { \
rlm@1 114 u32 lhs = reg[base].I; \
rlm@1 115 u32 rhs = value; \
rlm@1 116 u32 res = lhs - rhs - !((u32)C_FLAG); \
rlm@1 117 reg[dest].I = res; \
rlm@1 118 Z_FLAG = (res == 0) ? true : false; \
rlm@1 119 N_FLAG = NEG(res) ? true : false; \
rlm@1 120 SUBCARRY(lhs, rhs, res); \
rlm@1 121 SUBOVERFLOW(lhs, rhs, res); \
rlm@1 122 }
rlm@1 123 #define OP_RSC \
rlm@1 124 { \
rlm@1 125 reg[dest].I = value - reg[base].I - !((u32)C_FLAG); \
rlm@1 126 }
rlm@1 127 #define OP_RSCS \
rlm@1 128 { \
rlm@1 129 u32 lhs = reg[base].I; \
rlm@1 130 u32 rhs = value; \
rlm@1 131 u32 res = rhs - lhs - !((u32)C_FLAG); \
rlm@1 132 reg[dest].I = res; \
rlm@1 133 Z_FLAG = (res == 0) ? true : false; \
rlm@1 134 N_FLAG = NEG(res) ? true : false; \
rlm@1 135 SUBCARRY(rhs, lhs, res); \
rlm@1 136 SUBOVERFLOW(rhs, lhs, res); \
rlm@1 137 }
rlm@1 138 #define OP_CMP \
rlm@1 139 { \
rlm@1 140 u32 lhs = reg[base].I; \
rlm@1 141 u32 rhs = value; \
rlm@1 142 u32 res = lhs - rhs; \
rlm@1 143 Z_FLAG = (res == 0) ? true : false; \
rlm@1 144 N_FLAG = NEG(res) ? true : false; \
rlm@1 145 SUBCARRY(lhs, rhs, res); \
rlm@1 146 SUBOVERFLOW(lhs, rhs, res); \
rlm@1 147 }
rlm@1 148 #define OP_CMN \
rlm@1 149 { \
rlm@1 150 u32 lhs = reg[base].I; \
rlm@1 151 u32 rhs = value; \
rlm@1 152 u32 res = lhs + rhs; \
rlm@1 153 Z_FLAG = (res == 0) ? true : false; \
rlm@1 154 N_FLAG = NEG(res) ? true : false; \
rlm@1 155 ADDCARRY(lhs, rhs, res); \
rlm@1 156 ADDOVERFLOW(lhs, rhs, res); \
rlm@1 157 }
rlm@1 158
rlm@1 159 #define LOGICAL_LSL_REG \
rlm@1 160 { \
rlm@1 161 u32 v = reg[opcode & 0x0f].I; \
rlm@1 162 C_OUT = (v >> (32 - shift)) & 1 ? true : false; \
rlm@1 163 value = v << shift; \
rlm@1 164 }
rlm@1 165 #define LOGICAL_LSR_REG \
rlm@1 166 { \
rlm@1 167 u32 v = reg[opcode & 0x0f].I; \
rlm@1 168 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
rlm@1 169 value = v >> shift; \
rlm@1 170 }
rlm@1 171 #define LOGICAL_ASR_REG \
rlm@1 172 { \
rlm@1 173 u32 v = reg[opcode & 0x0f].I; \
rlm@1 174 C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false; \
rlm@1 175 value = (s32)v >> (int)shift; \
rlm@1 176 }
rlm@1 177 #define LOGICAL_ROR_REG \
rlm@1 178 { \
rlm@1 179 u32 v = reg[opcode & 0x0f].I; \
rlm@1 180 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
rlm@1 181 value = ((v << (32 - shift)) | \
rlm@1 182 (v >> shift)); \
rlm@1 183 }
rlm@1 184 #define LOGICAL_RRX_REG \
rlm@1 185 { \
rlm@1 186 u32 v = reg[opcode & 0x0f].I; \
rlm@1 187 shift = (int)C_FLAG; \
rlm@1 188 C_OUT = (v & 1) ? true : false; \
rlm@1 189 value = ((v >> 1) | \
rlm@1 190 (shift << 31)); \
rlm@1 191 }
rlm@1 192 #define LOGICAL_ROR_IMM \
rlm@1 193 { \
rlm@1 194 u32 v = opcode & 0xff; \
rlm@1 195 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
rlm@1 196 value = ((v << (32 - shift)) | \
rlm@1 197 (v >> shift)); \
rlm@1 198 }
rlm@1 199 #define ARITHMETIC_LSL_REG \
rlm@1 200 { \
rlm@1 201 u32 v = reg[opcode & 0x0f].I; \
rlm@1 202 value = v << shift; \
rlm@1 203 }
rlm@1 204 #define ARITHMETIC_LSR_REG \
rlm@1 205 { \
rlm@1 206 u32 v = reg[opcode & 0x0f].I; \
rlm@1 207 value = v >> shift; \
rlm@1 208 }
rlm@1 209 #define ARITHMETIC_ASR_REG \
rlm@1 210 { \
rlm@1 211 u32 v = reg[opcode & 0x0f].I; \
rlm@1 212 value = (s32)v >> (int)shift; \
rlm@1 213 }
rlm@1 214 #define ARITHMETIC_ROR_REG \
rlm@1 215 { \
rlm@1 216 u32 v = reg[opcode & 0x0f].I; \
rlm@1 217 value = ((v << (32 - shift)) | \
rlm@1 218 (v >> shift)); \
rlm@1 219 }
rlm@1 220 #define ARITHMETIC_RRX_REG \
rlm@1 221 { \
rlm@1 222 u32 v = reg[opcode & 0x0f].I; \
rlm@1 223 shift = (int)C_FLAG; \
rlm@1 224 value = ((v >> 1) | \
rlm@1 225 (shift << 31)); \
rlm@1 226 }
rlm@1 227 #define ARITHMETIC_ROR_IMM \
rlm@1 228 { \
rlm@1 229 u32 v = opcode & 0xff; \
rlm@1 230 value = ((v << (32 - shift)) | \
rlm@1 231 (v >> shift)); \
rlm@1 232 }
rlm@1 233 #define ROR_IMM_MSR \
rlm@1 234 { \
rlm@1 235 u32 v = opcode & 0xff; \
rlm@1 236 value = ((v << (32 - shift)) | \
rlm@1 237 (v >> shift)); \
rlm@1 238 }
rlm@1 239 #define ROR_VALUE \
rlm@1 240 { \
rlm@1 241 value = ((value << (32 - shift)) | \
rlm@1 242 (value >> shift)); \
rlm@1 243 }
rlm@1 244 #define RCR_VALUE \
rlm@1 245 { \
rlm@1 246 shift = (int)C_FLAG; \
rlm@1 247 value = ((value >> 1) | \
rlm@1 248 (shift << 31)); \
rlm@1 249 }
rlm@1 250 #else
rlm@1 251 #ifdef __GNUC__
rlm@1 252 #ifdef __POWERPC__
rlm@1 253 #define OP_SUB \
rlm@1 254 { \
rlm@1 255 reg[dest].I = reg[base].I - value; \
rlm@1 256 }
rlm@1 257 #define OP_SUBS \
rlm@1 258 { \
rlm@1 259 register int Flags; \
rlm@1 260 register int Result; \
rlm@1 261 asm volatile ("subco. %0, %2, %3\n" \
rlm@1 262 "mcrxr cr1\n" \
rlm@1 263 "mfcr %1\n" \
rlm@1 264 : "=r" (Result), \
rlm@1 265 "=r" (Flags) \
rlm@1 266 : "r" (reg[base].I), \
rlm@1 267 "r" (value) \
rlm@1 268 ); \
rlm@1 269 reg[dest].I = Result; \
rlm@1 270 Z_FLAG = (Flags >> 29) & 1; \
rlm@1 271 N_FLAG = (Flags >> 31) & 1; \
rlm@1 272 C_FLAG = (Flags >> 25) & 1; \
rlm@1 273 V_FLAG = (Flags >> 26) & 1; \
rlm@1 274 }
rlm@1 275 #define OP_RSB \
rlm@1 276 { \
rlm@1 277 reg[dest].I = value - reg[base].I; \
rlm@1 278 }
rlm@1 279 #define OP_RSBS \
rlm@1 280 { \
rlm@1 281 register int Flags; \
rlm@1 282 register int Result; \
rlm@1 283 asm volatile ("subfco. %0, %2, %3\n" \
rlm@1 284 "mcrxr cr1\n" \
rlm@1 285 "mfcr %1\n" \
rlm@1 286 : "=r" (Result), \
rlm@1 287 "=r" (Flags) \
rlm@1 288 : "r" (reg[base].I), \
rlm@1 289 "r" (value) \
rlm@1 290 ); \
rlm@1 291 reg[dest].I = Result; \
rlm@1 292 Z_FLAG = (Flags >> 29) & 1; \
rlm@1 293 N_FLAG = (Flags >> 31) & 1; \
rlm@1 294 C_FLAG = (Flags >> 25) & 1; \
rlm@1 295 V_FLAG = (Flags >> 26) & 1; \
rlm@1 296 }
rlm@1 297 #define OP_ADD \
rlm@1 298 { \
rlm@1 299 reg[dest].I = reg[base].I + value; \
rlm@1 300 }
rlm@1 301
rlm@1 302 #define OP_ADDS \
rlm@1 303 { \
rlm@1 304 register int Flags; \
rlm@1 305 register int Result; \
rlm@1 306 asm volatile ("addco. %0, %2, %3\n" \
rlm@1 307 "mcrxr cr1\n" \
rlm@1 308 "mfcr %1\n" \
rlm@1 309 : "=r" (Result), \
rlm@1 310 "=r" (Flags) \
rlm@1 311 : "r" (reg[base].I), \
rlm@1 312 "r" (value) \
rlm@1 313 ); \
rlm@1 314 reg[dest].I = Result; \
rlm@1 315 Z_FLAG = (Flags >> 29) & 1; \
rlm@1 316 N_FLAG = (Flags >> 31) & 1; \
rlm@1 317 C_FLAG = (Flags >> 25) & 1; \
rlm@1 318 V_FLAG = (Flags >> 26) & 1; \
rlm@1 319 }
rlm@1 320 #define OP_ADC \
rlm@1 321 { \
rlm@1 322 reg[dest].I = reg[base].I + value + (u32)C_FLAG; \
rlm@1 323 }
rlm@1 324 #define OP_ADCS \
rlm@1 325 { \
rlm@1 326 register int Flags; \
rlm@1 327 register int Result; \
rlm@1 328 asm volatile ("mtspr xer, %4\n" \
rlm@1 329 "addeo. %0, %2, %3\n" \
rlm@1 330 "mcrxr cr1\n" \
rlm@1 331 "mfcr %1\n" \
rlm@1 332 : "=r" (Result), \
rlm@1 333 "=r" (Flags) \
rlm@1 334 : "r" (reg[base].I), \
rlm@1 335 "r" (value), \
rlm@1 336 "r" (C_FLAG << 29) \
rlm@1 337 ); \
rlm@1 338 reg[dest].I = Result; \
rlm@1 339 Z_FLAG = (Flags >> 29) & 1; \
rlm@1 340 N_FLAG = (Flags >> 31) & 1; \
rlm@1 341 C_FLAG = (Flags >> 25) & 1; \
rlm@1 342 V_FLAG = (Flags >> 26) & 1; \
rlm@1 343 }
rlm@1 344 #define OP_SBC \
rlm@1 345 { \
rlm@1 346 reg[dest].I = reg[base].I - value - (C_FLAG ^ 1); \
rlm@1 347 }
rlm@1 348 #define OP_SBCS \
rlm@1 349 { \
rlm@1 350 register int Flags; \
rlm@1 351 register int Result; \
rlm@1 352 asm volatile ("mtspr xer, %4\n" \
rlm@1 353 "subfeo. %0, %3, %2\n" \
rlm@1 354 "mcrxr cr1\n" \
rlm@1 355 "mfcr %1\n" \
rlm@1 356 : "=r" (Result), \
rlm@1 357 "=r" (Flags) \
rlm@1 358 : "r" (reg[base].I), \
rlm@1 359 "r" (value), \
rlm@1 360 "r" (C_FLAG << 29) \
rlm@1 361 ); \
rlm@1 362 reg[dest].I = Result; \
rlm@1 363 Z_FLAG = (Flags >> 29) & 1; \
rlm@1 364 N_FLAG = (Flags >> 31) & 1; \
rlm@1 365 C_FLAG = (Flags >> 25) & 1; \
rlm@1 366 V_FLAG = (Flags >> 26) & 1; \
rlm@1 367 }
rlm@1 368 #define OP_RSC \
rlm@1 369 { \
rlm@1 370 reg[dest].I = value - reg[base].I - (C_FLAG ^ 1); \
rlm@1 371 }
rlm@1 372 #define OP_RSCS \
rlm@1 373 { \
rlm@1 374 register int Flags; \
rlm@1 375 register int Result; \
rlm@1 376 asm volatile ("mtspr xer, %4\n" \
rlm@1 377 "subfeo. %0, %2, %3\n" \
rlm@1 378 "mcrxr cr1\n" \
rlm@1 379 "mfcr %1\n" \
rlm@1 380 : "=r" (Result), \
rlm@1 381 "=r" (Flags) \
rlm@1 382 : "r" (reg[base].I), \
rlm@1 383 "r" (value), \
rlm@1 384 "r" (C_FLAG << 29) \
rlm@1 385 ); \
rlm@1 386 reg[dest].I = Result; \
rlm@1 387 Z_FLAG = (Flags >> 29) & 1; \
rlm@1 388 N_FLAG = (Flags >> 31) & 1; \
rlm@1 389 C_FLAG = (Flags >> 25) & 1; \
rlm@1 390 V_FLAG = (Flags >> 26) & 1; \
rlm@1 391 }
rlm@1 392 #define OP_CMP \
rlm@1 393 { \
rlm@1 394 register int Flags; \
rlm@1 395 register int Result; \
rlm@1 396 asm volatile ("subco. %0, %2, %3\n" \
rlm@1 397 "mcrxr cr1\n" \
rlm@1 398 "mfcr %1\n" \
rlm@1 399 : "=r" (Result), \
rlm@1 400 "=r" (Flags) \
rlm@1 401 : "r" (reg[base].I), \
rlm@1 402 "r" (value) \
rlm@1 403 ); \
rlm@1 404 Z_FLAG = (Flags >> 29) & 1; \
rlm@1 405 N_FLAG = (Flags >> 31) & 1; \
rlm@1 406 C_FLAG = (Flags >> 25) & 1; \
rlm@1 407 V_FLAG = (Flags >> 26) & 1; \
rlm@1 408 }
rlm@1 409 #define OP_CMN \
rlm@1 410 { \
rlm@1 411 register int Flags; \
rlm@1 412 register int Result; \
rlm@1 413 asm volatile ("addco. %0, %2, %3\n" \
rlm@1 414 "mcrxr cr1\n" \
rlm@1 415 "mfcr %1\n" \
rlm@1 416 : "=r" (Result), \
rlm@1 417 "=r" (Flags) \
rlm@1 418 : "r" (reg[base].I), \
rlm@1 419 "r" (value) \
rlm@1 420 ); \
rlm@1 421 Z_FLAG = (Flags >> 29) & 1; \
rlm@1 422 N_FLAG = (Flags >> 31) & 1; \
rlm@1 423 C_FLAG = (Flags >> 25) & 1; \
rlm@1 424 V_FLAG = (Flags >> 26) & 1; \
rlm@1 425 }
rlm@1 426
rlm@1 427 #define LOGICAL_LSL_REG \
rlm@1 428 { \
rlm@1 429 u32 v = reg[opcode & 0x0f].I; \
rlm@1 430 C_OUT = (v >> (32 - shift)) & 1 ? true : false; \
rlm@1 431 value = v << shift; \
rlm@1 432 }
rlm@1 433 #define LOGICAL_LSR_REG \
rlm@1 434 { \
rlm@1 435 u32 v = reg[opcode & 0x0f].I; \
rlm@1 436 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
rlm@1 437 value = v >> shift; \
rlm@1 438 }
rlm@1 439 #define LOGICAL_ASR_REG \
rlm@1 440 { \
rlm@1 441 u32 v = reg[opcode & 0x0f].I; \
rlm@1 442 C_OUT = ((s32)v >> (int)(shift - 1)) & 1 ? true : false; \
rlm@1 443 value = (s32)v >> (int)shift; \
rlm@1 444 }
rlm@1 445 #define LOGICAL_ROR_REG \
rlm@1 446 { \
rlm@1 447 u32 v = reg[opcode & 0x0f].I; \
rlm@1 448 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
rlm@1 449 value = ((v << (32 - shift)) | \
rlm@1 450 (v >> shift)); \
rlm@1 451 }
rlm@1 452 #define LOGICAL_RRX_REG \
rlm@1 453 { \
rlm@1 454 u32 v = reg[opcode & 0x0f].I; \
rlm@1 455 shift = (int)C_FLAG; \
rlm@1 456 C_OUT = (v & 1) ? true : false; \
rlm@1 457 value = ((v >> 1) | \
rlm@1 458 (shift << 31)); \
rlm@1 459 }
rlm@1 460 #define LOGICAL_ROR_IMM \
rlm@1 461 { \
rlm@1 462 u32 v = opcode & 0xff; \
rlm@1 463 C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
rlm@1 464 value = ((v << (32 - shift)) | \
rlm@1 465 (v >> shift)); \
rlm@1 466 }
rlm@1 467 #define ARITHMETIC_LSL_REG \
rlm@1 468 { \
rlm@1 469 u32 v = reg[opcode & 0x0f].I; \
rlm@1 470 value = v << shift; \
rlm@1 471 }
rlm@1 472 #define ARITHMETIC_LSR_REG \
rlm@1 473 { \
rlm@1 474 u32 v = reg[opcode & 0x0f].I; \
rlm@1 475 value = v >> shift; \
rlm@1 476 }
rlm@1 477 #define ARITHMETIC_ASR_REG \
rlm@1 478 { \
rlm@1 479 u32 v = reg[opcode & 0x0f].I; \
rlm@1 480 value = (s32)v >> (int)shift; \
rlm@1 481 }
rlm@1 482 #define ARITHMETIC_ROR_REG \
rlm@1 483 { \
rlm@1 484 u32 v = reg[opcode & 0x0f].I; \
rlm@1 485 value = ((v << (32 - shift)) | \
rlm@1 486 (v >> shift)); \
rlm@1 487 }
rlm@1 488 #define ARITHMETIC_RRX_REG \
rlm@1 489 { \
rlm@1 490 u32 v = reg[opcode & 0x0f].I; \
rlm@1 491 shift = (int)C_FLAG; \
rlm@1 492 value = ((v >> 1) | \
rlm@1 493 (shift << 31)); \
rlm@1 494 }
rlm@1 495 #define ARITHMETIC_ROR_IMM \
rlm@1 496 { \
rlm@1 497 u32 v = opcode & 0xff; \
rlm@1 498 value = ((v << (32 - shift)) | \
rlm@1 499 (v >> shift)); \
rlm@1 500 }
rlm@1 501 #define ROR_IMM_MSR \
rlm@1 502 { \
rlm@1 503 u32 v = opcode & 0xff; \
rlm@1 504 value = ((v << (32 - shift)) | \
rlm@1 505 (v >> shift)); \
rlm@1 506 }
rlm@1 507 #define ROR_VALUE \
rlm@1 508 { \
rlm@1 509 value = ((value << (32 - shift)) | \
rlm@1 510 (value >> shift)); \
rlm@1 511 }
rlm@1 512 #define RCR_VALUE \
rlm@1 513 { \
rlm@1 514 shift = (int)C_FLAG; \
rlm@1 515 value = ((value >> 1) | \
rlm@1 516 (shift << 31)); \
rlm@1 517 }
rlm@1 518 #else
rlm@1 519 #define OP_SUB \
rlm@1 520 asm ("sub %1, %%ebx;" \
rlm@1 521 : "=b" (reg[dest].I) \
rlm@1 522 : "r" (value), "b" (reg[base].I));
rlm@1 523
rlm@1 524 #define OP_SUBS \
rlm@1 525 asm ("sub %1, %%ebx;" \
rlm@1 526 "setsb N_FLAG;" \
rlm@1 527 "setzb Z_FLAG;" \
rlm@1 528 "setncb C_FLAG;" \
rlm@1 529 "setob V_FLAG;" \
rlm@1 530 : "=b" (reg[dest].I) \
rlm@1 531 : "r" (value), "b" (reg[base].I));
rlm@1 532
rlm@1 533 #define OP_RSB \
rlm@1 534 asm ("sub %1, %%ebx;" \
rlm@1 535 : "=b" (reg[dest].I) \
rlm@1 536 : "r" (reg[base].I), "b" (value));
rlm@1 537
rlm@1 538 #define OP_RSBS \
rlm@1 539 asm ("sub %1, %%ebx;" \
rlm@1 540 "setsb N_FLAG;" \
rlm@1 541 "setzb Z_FLAG;" \
rlm@1 542 "setncb C_FLAG;" \
rlm@1 543 "setob V_FLAG;" \
rlm@1 544 : "=b" (reg[dest].I) \
rlm@1 545 : "r" (reg[base].I), "b" (value));
rlm@1 546
rlm@1 547 #define OP_ADD \
rlm@1 548 asm ("add %1, %%ebx;" \
rlm@1 549 : "=b" (reg[dest].I) \
rlm@1 550 : "r" (value), "b" (reg[base].I));
rlm@1 551
rlm@1 552 #define OP_ADDS \
rlm@1 553 asm ("add %1, %%ebx;" \
rlm@1 554 "setsb N_FLAG;" \
rlm@1 555 "setzb Z_FLAG;" \
rlm@1 556 "setcb C_FLAG;" \
rlm@1 557 "setob V_FLAG;" \
rlm@1 558 : "=b" (reg[dest].I) \
rlm@1 559 : "r" (value), "b" (reg[base].I));
rlm@1 560
rlm@1 561 #define OP_ADC \
rlm@1 562 asm ("bt $0, C_FLAG;" \
rlm@1 563 "adc %1, %%ebx;" \
rlm@1 564 : "=b" (reg[dest].I) \
rlm@1 565 : "r" (value), "b" (reg[base].I));
rlm@1 566
rlm@1 567 #define OP_ADCS \
rlm@1 568 asm ("bt $0, C_FLAG;" \
rlm@1 569 "adc %1, %%ebx;" \
rlm@1 570 "setsb N_FLAG;" \
rlm@1 571 "setzb Z_FLAG;" \
rlm@1 572 "setcb C_FLAG;" \
rlm@1 573 "setob V_FLAG;" \
rlm@1 574 : "=b" (reg[dest].I) \
rlm@1 575 : "r" (value), "b" (reg[base].I));
rlm@1 576
rlm@1 577 #define OP_SBC \
rlm@1 578 asm ("bt $0, C_FLAG;" \
rlm@1 579 "cmc;" \
rlm@1 580 "sbb %1, %%ebx;" \
rlm@1 581 : "=b" (reg[dest].I) \
rlm@1 582 : "r" (value), "b" (reg[base].I));
rlm@1 583
rlm@1 584 #define OP_SBCS \
rlm@1 585 asm ("bt $0, C_FLAG;" \
rlm@1 586 "cmc;" \
rlm@1 587 "sbb %1, %%ebx;" \
rlm@1 588 "setsb N_FLAG;" \
rlm@1 589 "setzb Z_FLAG;" \
rlm@1 590 "setncb C_FLAG;" \
rlm@1 591 "setob V_FLAG;" \
rlm@1 592 : "=b" (reg[dest].I) \
rlm@1 593 : "r" (value), "b" (reg[base].I));
rlm@1 594 #define OP_RSC \
rlm@1 595 asm ("bt $0, C_FLAG;" \
rlm@1 596 "cmc;" \
rlm@1 597 "sbb %1, %%ebx;" \
rlm@1 598 : "=b" (reg[dest].I) \
rlm@1 599 : "r" (reg[base].I), "b" (value));
rlm@1 600
rlm@1 601 #define OP_RSCS \
rlm@1 602 asm ("bt $0, C_FLAG;" \
rlm@1 603 "cmc;" \
rlm@1 604 "sbb %1, %%ebx;" \
rlm@1 605 "setsb N_FLAG;" \
rlm@1 606 "setzb Z_FLAG;" \
rlm@1 607 "setncb C_FLAG;" \
rlm@1 608 "setob V_FLAG;" \
rlm@1 609 : "=b" (reg[dest].I) \
rlm@1 610 : "r" (reg[base].I), "b" (value));
rlm@1 611 #define OP_CMP \
rlm@1 612 asm ("sub %0, %1;" \
rlm@1 613 "setsb N_FLAG;" \
rlm@1 614 "setzb Z_FLAG;" \
rlm@1 615 "setncb C_FLAG;" \
rlm@1 616 "setob V_FLAG;" \
rlm@1 617 : \
rlm@1 618 : "r" (value), "r" (reg[base].I));
rlm@1 619
rlm@1 620 #define OP_CMN \
rlm@1 621 asm ("add %0, %1;" \
rlm@1 622 "setsb N_FLAG;" \
rlm@1 623 "setzb Z_FLAG;" \
rlm@1 624 "setcb C_FLAG;" \
rlm@1 625 "setob V_FLAG;" \
rlm@1 626 : \
rlm@1 627 : "r" (value), "r" (reg[base].I));
rlm@1 628 #define LOGICAL_LSL_REG \
rlm@1 629 asm ("shl %%cl, %%eax;" \
rlm@1 630 "setcb %%cl;" \
rlm@1 631 : "=a" (value), "=c" (C_OUT) \
rlm@1 632 : "a" (reg[opcode & 0x0f].I), "c" (shift));
rlm@1 633
rlm@1 634 #define LOGICAL_LSR_REG \
rlm@1 635 asm ("shr %%cl, %%eax;" \
rlm@1 636 "setcb %%cl;" \
rlm@1 637 : "=a" (value), "=c" (C_OUT) \
rlm@1 638 : "a" (reg[opcode & 0x0f].I), "c" (shift));
rlm@1 639
rlm@1 640 #define LOGICAL_ASR_REG \
rlm@1 641 asm ("sar %%cl, %%eax;" \
rlm@1 642 "setcb %%cl;" \
rlm@1 643 : "=a" (value), "=c" (C_OUT) \
rlm@1 644 : "a" (reg[opcode & 0x0f].I), "c" (shift));
rlm@1 645
rlm@1 646 #define LOGICAL_ROR_REG \
rlm@1 647 asm ("ror %%cl, %%eax;" \
rlm@1 648 "setcb %%cl;" \
rlm@1 649 : "=a" (value), "=c" (C_OUT) \
rlm@1 650 : "a" (reg[opcode & 0x0f].I), "c" (shift));
rlm@1 651
rlm@1 652 #define LOGICAL_RRX_REG \
rlm@1 653 asm ("bt $0, C_FLAG;" \
rlm@1 654 "rcr $1, %%eax;" \
rlm@1 655 "setcb %%cl;" \
rlm@1 656 : "=a" (value), "=c" (C_OUT) \
rlm@1 657 : "a" (reg[opcode & 0x0f].I));
rlm@1 658
rlm@1 659 #define LOGICAL_ROR_IMM \
rlm@1 660 asm ("ror %%cl, %%eax;" \
rlm@1 661 "setcb %%cl;" \
rlm@1 662 : "=a" (value), "=c" (C_OUT) \
rlm@1 663 : "a" (opcode & 0xff), "c" (shift));
rlm@1 664 #define ARITHMETIC_LSL_REG \
rlm@1 665 asm ("\
rlm@1 666 shl %%cl, %%eax;" \
rlm@1 667 : "=a" (value) \
rlm@1 668 : "a" (reg[opcode & 0x0f].I), "c" (shift));
rlm@1 669
rlm@1 670 #define ARITHMETIC_LSR_REG \
rlm@1 671 asm ("\
rlm@1 672 shr %%cl, %%eax;" \
rlm@1 673 : "=a" (value) \
rlm@1 674 : "a" (reg[opcode & 0x0f].I), "c" (shift));
rlm@1 675
rlm@1 676 #define ARITHMETIC_ASR_REG \
rlm@1 677 asm ("\
rlm@1 678 sar %%cl, %%eax;" \
rlm@1 679 : "=a" (value) \
rlm@1 680 : "a" (reg[opcode & 0x0f].I), "c" (shift));
rlm@1 681
rlm@1 682 #define ARITHMETIC_ROR_REG \
rlm@1 683 asm ("\
rlm@1 684 ror %%cl, %%eax;" \
rlm@1 685 : "=a" (value) \
rlm@1 686 : "a" (reg[opcode & 0x0f].I), "c" (shift));
rlm@1 687
rlm@1 688 #define ARITHMETIC_RRX_REG \
rlm@1 689 asm ("\
rlm@1 690 bt $0, C_FLAG;\
rlm@1 691 rcr $1, %%eax;" \
rlm@1 692 : "=a" (value) \
rlm@1 693 : "a" (reg[opcode & 0x0f].I));
rlm@1 694
rlm@1 695 #define ARITHMETIC_ROR_IMM \
rlm@1 696 asm ("\
rlm@1 697 ror %%cl, %%eax;" \
rlm@1 698 : "=a" (value) \
rlm@1 699 : "a" (opcode & 0xff), "c" (shift));
rlm@1 700 #define ROR_IMM_MSR \
rlm@1 701 asm ("ror %%cl, %%eax;" \
rlm@1 702 : "=a" (value) \
rlm@1 703 : "a" (opcode & 0xFF), "c" (shift));
rlm@1 704 #define ROR_VALUE \
rlm@1 705 asm ("ror %%cl, %0" \
rlm@1 706 : "=r" (value) \
rlm@1 707 : "r" (value), "c" (shift));
rlm@1 708 #define RCR_VALUE \
rlm@1 709 asm ("bt $0, C_FLAG;" \
rlm@1 710 "rcr $1, %0" \
rlm@1 711 : "=r" (value) \
rlm@1 712 : "r" (value));
rlm@1 713 #endif
rlm@1 714 #else
rlm@1 715 #define OP_SUB \
rlm@1 716 { \
rlm@1 717 __asm mov ebx, base \
rlm@1 718 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 719 __asm sub ebx, value \
rlm@1 720 __asm mov eax, dest \
rlm@1 721 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 722 }
rlm@1 723
rlm@1 724 #define OP_SUBS \
rlm@1 725 { \
rlm@1 726 __asm mov ebx, base \
rlm@1 727 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 728 __asm sub ebx, value \
rlm@1 729 __asm mov eax, dest \
rlm@1 730 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 731 __asm sets byte ptr N_FLAG \
rlm@1 732 __asm setz byte ptr Z_FLAG \
rlm@1 733 __asm setnc byte ptr C_FLAG \
rlm@1 734 __asm seto byte ptr V_FLAG \
rlm@1 735 }
rlm@1 736
rlm@1 737 #define OP_RSB \
rlm@1 738 { \
rlm@1 739 __asm mov ebx, base \
rlm@1 740 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 741 __asm mov eax, value \
rlm@1 742 __asm sub eax, ebx \
rlm@1 743 __asm mov ebx, dest \
rlm@1 744 __asm mov dword ptr [OFFSET reg + 4 * ebx], eax \
rlm@1 745 }
rlm@1 746
rlm@1 747 #define OP_RSBS \
rlm@1 748 { \
rlm@1 749 __asm mov ebx, base \
rlm@1 750 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 751 __asm mov eax, value \
rlm@1 752 __asm sub eax, ebx \
rlm@1 753 __asm mov ebx, dest \
rlm@1 754 __asm mov dword ptr [OFFSET reg + 4 * ebx], eax \
rlm@1 755 __asm sets byte ptr N_FLAG \
rlm@1 756 __asm setz byte ptr Z_FLAG \
rlm@1 757 __asm setnc byte ptr C_FLAG \
rlm@1 758 __asm seto byte ptr V_FLAG \
rlm@1 759 }
rlm@1 760
rlm@1 761 #define OP_ADD \
rlm@1 762 { \
rlm@1 763 __asm mov ebx, base \
rlm@1 764 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 765 __asm add ebx, value \
rlm@1 766 __asm mov eax, dest \
rlm@1 767 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 768 }
rlm@1 769
rlm@1 770 #define OP_ADDS \
rlm@1 771 { \
rlm@1 772 __asm mov ebx, base \
rlm@1 773 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 774 __asm add ebx, value \
rlm@1 775 __asm mov eax, dest \
rlm@1 776 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 777 __asm sets byte ptr N_FLAG \
rlm@1 778 __asm setz byte ptr Z_FLAG \
rlm@1 779 __asm setc byte ptr C_FLAG \
rlm@1 780 __asm seto byte ptr V_FLAG \
rlm@1 781 }
rlm@1 782
rlm@1 783 #define OP_ADC \
rlm@1 784 { \
rlm@1 785 __asm mov ebx, base \
rlm@1 786 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 787 __asm bt word ptr C_FLAG, 0 \
rlm@1 788 __asm adc ebx, value \
rlm@1 789 __asm mov eax, dest \
rlm@1 790 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 791 }
rlm@1 792
rlm@1 793 #define OP_ADCS \
rlm@1 794 { \
rlm@1 795 __asm mov ebx, base \
rlm@1 796 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 797 __asm bt word ptr C_FLAG, 0 \
rlm@1 798 __asm adc ebx, value \
rlm@1 799 __asm mov eax, dest \
rlm@1 800 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 801 __asm sets byte ptr N_FLAG \
rlm@1 802 __asm setz byte ptr Z_FLAG \
rlm@1 803 __asm setc byte ptr C_FLAG \
rlm@1 804 __asm seto byte ptr V_FLAG \
rlm@1 805 }
rlm@1 806
rlm@1 807 #define OP_SBC \
rlm@1 808 { \
rlm@1 809 __asm mov ebx, base \
rlm@1 810 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 811 __asm mov eax, value \
rlm@1 812 __asm bt word ptr C_FLAG, 0 \
rlm@1 813 __asm cmc \
rlm@1 814 __asm sbb ebx, eax \
rlm@1 815 __asm mov eax, dest \
rlm@1 816 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 817 }
rlm@1 818
rlm@1 819 #define OP_SBCS \
rlm@1 820 { \
rlm@1 821 __asm mov ebx, base \
rlm@1 822 __asm mov ebx, dword ptr [OFFSET reg + 4 * ebx] \
rlm@1 823 __asm mov eax, value \
rlm@1 824 __asm bt word ptr C_FLAG, 0 \
rlm@1 825 __asm cmc \
rlm@1 826 __asm sbb ebx, eax \
rlm@1 827 __asm mov eax, dest \
rlm@1 828 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 829 __asm sets byte ptr N_FLAG \
rlm@1 830 __asm setz byte ptr Z_FLAG \
rlm@1 831 __asm setnc byte ptr C_FLAG \
rlm@1 832 __asm seto byte ptr V_FLAG \
rlm@1 833 }
rlm@1 834 #define OP_RSC \
rlm@1 835 { \
rlm@1 836 __asm mov ebx, value \
rlm@1 837 __asm mov eax, base \
rlm@1 838 __asm mov eax, dword ptr[OFFSET reg + 4 * eax] \
rlm@1 839 __asm bt word ptr C_FLAG, 0 \
rlm@1 840 __asm cmc \
rlm@1 841 __asm sbb ebx, eax \
rlm@1 842 __asm mov eax, dest \
rlm@1 843 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 844 }
rlm@1 845
rlm@1 846 #define OP_RSCS \
rlm@1 847 { \
rlm@1 848 __asm mov ebx, value \
rlm@1 849 __asm mov eax, base \
rlm@1 850 __asm mov eax, dword ptr[OFFSET reg + 4 * eax] \
rlm@1 851 __asm bt word ptr C_FLAG, 0 \
rlm@1 852 __asm cmc \
rlm@1 853 __asm sbb ebx, eax \
rlm@1 854 __asm mov eax, dest \
rlm@1 855 __asm mov dword ptr [OFFSET reg + 4 * eax], ebx \
rlm@1 856 __asm sets byte ptr N_FLAG \
rlm@1 857 __asm setz byte ptr Z_FLAG \
rlm@1 858 __asm setnc byte ptr C_FLAG \
rlm@1 859 __asm seto byte ptr V_FLAG \
rlm@1 860 }
rlm@1 861 #define OP_CMP \
rlm@1 862 { \
rlm@1 863 __asm mov eax, base \
rlm@1 864 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 865 __asm sub ebx, value \
rlm@1 866 __asm sets byte ptr N_FLAG \
rlm@1 867 __asm setz byte ptr Z_FLAG \
rlm@1 868 __asm setnc byte ptr C_FLAG \
rlm@1 869 __asm seto byte ptr V_FLAG \
rlm@1 870 }
rlm@1 871
rlm@1 872 #define OP_CMN \
rlm@1 873 { \
rlm@1 874 __asm mov eax, base \
rlm@1 875 __asm mov ebx, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 876 __asm add ebx, value \
rlm@1 877 __asm sets byte ptr N_FLAG \
rlm@1 878 __asm setz byte ptr Z_FLAG \
rlm@1 879 __asm setc byte ptr C_FLAG \
rlm@1 880 __asm seto byte ptr V_FLAG \
rlm@1 881 }
rlm@1 882 #define LOGICAL_LSL_REG \
rlm@1 883 __asm mov eax, opcode \
rlm@1 884 __asm and eax, 0x0f \
rlm@1 885 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 886 __asm mov cl, byte ptr shift \
rlm@1 887 __asm shl eax, cl \
rlm@1 888 __asm mov value, eax \
rlm@1 889 __asm setc byte ptr C_OUT
rlm@1 890
rlm@1 891 #define LOGICAL_LSR_REG \
rlm@1 892 __asm mov eax, opcode \
rlm@1 893 __asm and eax, 0x0f \
rlm@1 894 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 895 __asm mov cl, byte ptr shift \
rlm@1 896 __asm shr eax, cl \
rlm@1 897 __asm mov value, eax \
rlm@1 898 __asm setc byte ptr C_OUT
rlm@1 899
rlm@1 900 #define LOGICAL_ASR_REG \
rlm@1 901 __asm mov eax, opcode \
rlm@1 902 __asm and eax, 0x0f \
rlm@1 903 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 904 __asm mov cl, byte ptr shift \
rlm@1 905 __asm sar eax, cl \
rlm@1 906 __asm mov value, eax \
rlm@1 907 __asm setc byte ptr C_OUT
rlm@1 908
rlm@1 909 #define LOGICAL_ROR_REG \
rlm@1 910 __asm mov eax, opcode \
rlm@1 911 __asm and eax, 0x0F \
rlm@1 912 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 913 __asm mov cl, byte ptr shift \
rlm@1 914 __asm ror eax, cl \
rlm@1 915 __asm mov value, eax \
rlm@1 916 __asm setc byte ptr C_OUT
rlm@1 917
rlm@1 918 #define LOGICAL_RRX_REG \
rlm@1 919 __asm mov eax, opcode \
rlm@1 920 __asm and eax, 0x0F \
rlm@1 921 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 922 __asm bt word ptr C_OUT, 0 \
rlm@1 923 __asm rcr eax, 1 \
rlm@1 924 __asm mov value, eax \
rlm@1 925 __asm setc byte ptr C_OUT
rlm@1 926
rlm@1 927 #define LOGICAL_ROR_IMM \
rlm@1 928 __asm mov eax, opcode \
rlm@1 929 __asm and eax, 0xff \
rlm@1 930 __asm mov cl, byte ptr shift \
rlm@1 931 __asm ror eax, cl \
rlm@1 932 __asm mov value, eax \
rlm@1 933 __asm setc byte ptr C_OUT
rlm@1 934 #define ARITHMETIC_LSL_REG \
rlm@1 935 __asm mov eax, opcode \
rlm@1 936 __asm and eax, 0x0f \
rlm@1 937 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 938 __asm mov cl, byte ptr shift \
rlm@1 939 __asm shl eax, cl \
rlm@1 940 __asm mov value, eax
rlm@1 941
rlm@1 942 #define ARITHMETIC_LSR_REG \
rlm@1 943 __asm mov eax, opcode \
rlm@1 944 __asm and eax, 0x0f \
rlm@1 945 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 946 __asm mov cl, byte ptr shift \
rlm@1 947 __asm shr eax, cl \
rlm@1 948 __asm mov value, eax
rlm@1 949
rlm@1 950 #define ARITHMETIC_ASR_REG \
rlm@1 951 __asm mov eax, opcode \
rlm@1 952 __asm and eax, 0x0f \
rlm@1 953 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 954 __asm mov cl, byte ptr shift \
rlm@1 955 __asm sar eax, cl \
rlm@1 956 __asm mov value, eax
rlm@1 957
rlm@1 958 #define ARITHMETIC_ROR_REG \
rlm@1 959 __asm mov eax, opcode \
rlm@1 960 __asm and eax, 0x0F \
rlm@1 961 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 962 __asm mov cl, byte ptr shift \
rlm@1 963 __asm ror eax, cl \
rlm@1 964 __asm mov value, eax
rlm@1 965
rlm@1 966 #define ARITHMETIC_RRX_REG \
rlm@1 967 __asm mov eax, opcode \
rlm@1 968 __asm and eax, 0x0F \
rlm@1 969 __asm mov eax, dword ptr [OFFSET reg + 4 * eax] \
rlm@1 970 __asm bt word ptr C_FLAG, 0 \
rlm@1 971 __asm rcr eax, 1 \
rlm@1 972 __asm mov value, eax
rlm@1 973
rlm@1 974 #define ARITHMETIC_ROR_IMM \
rlm@1 975 __asm mov eax, opcode \
rlm@1 976 __asm and eax, 0xff \
rlm@1 977 __asm mov cl, byte ptr shift \
rlm@1 978 __asm ror eax, cl \
rlm@1 979 __asm mov value, eax
rlm@1 980 #define ROR_IMM_MSR \
rlm@1 981 { \
rlm@1 982 __asm mov eax, opcode \
rlm@1 983 __asm and eax, 0xff \
rlm@1 984 __asm mov cl, byte ptr shift \
rlm@1 985 __asm ror eax, CL \
rlm@1 986 __asm mov value, eax \
rlm@1 987 }
rlm@1 988 #define ROR_VALUE \
rlm@1 989 { \
rlm@1 990 __asm mov cl, byte ptr shift \
rlm@1 991 __asm ror dword ptr value, cl \
rlm@1 992 }
rlm@1 993 #define RCR_VALUE \
rlm@1 994 { \
rlm@1 995 __asm mov cl, byte ptr shift \
rlm@1 996 __asm bt word ptr C_FLAG, 0 \
rlm@1 997 __asm rcr dword ptr value, 1 \
rlm@1 998 }
rlm@1 999 #endif
rlm@1 1000 #endif
rlm@1 1001
rlm@1 1002 #define OP_TST \
rlm@1 1003 u32 res = reg[base].I & value; \
rlm@1 1004 N_FLAG = (res & 0x80000000) ? true : false; \
rlm@1 1005 Z_FLAG = (res) ? false : true; \
rlm@1 1006 C_FLAG = C_OUT;
rlm@1 1007
rlm@1 1008 #define OP_TEQ \
rlm@1 1009 u32 res = reg[base].I ^ value; \
rlm@1 1010 N_FLAG = (res & 0x80000000) ? true : false; \
rlm@1 1011 Z_FLAG = (res) ? false : true; \
rlm@1 1012 C_FLAG = C_OUT;
rlm@1 1013
rlm@1 1014 #define OP_ORR \
rlm@1 1015 reg[dest].I = reg[base].I | value;
rlm@1 1016
rlm@1 1017 #define OP_ORRS \
rlm@1 1018 reg[dest].I = reg[base].I | value; \
rlm@1 1019 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
rlm@1 1020 Z_FLAG = (reg[dest].I) ? false : true; \
rlm@1 1021 C_FLAG = C_OUT;
rlm@1 1022
rlm@1 1023 #define OP_MOV \
rlm@1 1024 reg[dest].I = value;
rlm@1 1025
rlm@1 1026 #define OP_MOVS \
rlm@1 1027 reg[dest].I = value; \
rlm@1 1028 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
rlm@1 1029 Z_FLAG = (reg[dest].I) ? false : true; \
rlm@1 1030 C_FLAG = C_OUT;
rlm@1 1031
rlm@1 1032 #define OP_BIC \
rlm@1 1033 reg[dest].I = reg[base].I & (~value);
rlm@1 1034
rlm@1 1035 #define OP_BICS \
rlm@1 1036 reg[dest].I = reg[base].I & (~value); \
rlm@1 1037 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
rlm@1 1038 Z_FLAG = (reg[dest].I) ? false : true; \
rlm@1 1039 C_FLAG = C_OUT;
rlm@1 1040
rlm@1 1041 #define OP_MVN \
rlm@1 1042 reg[dest].I = ~value;
rlm@1 1043
rlm@1 1044 #define OP_MVNS \
rlm@1 1045 reg[dest].I = ~value; \
rlm@1 1046 N_FLAG = (reg[dest].I & 0x80000000) ? true : false; \
rlm@1 1047 Z_FLAG = (reg[dest].I) ? false : true; \
rlm@1 1048 C_FLAG = C_OUT;
rlm@1 1049
rlm@1 1050 #define CASE_16(BASE) \
rlm@1 1051 case BASE: \
rlm@1 1052 case BASE + 1: \
rlm@1 1053 case BASE + 2: \
rlm@1 1054 case BASE + 3: \
rlm@1 1055 case BASE + 4: \
rlm@1 1056 case BASE + 5: \
rlm@1 1057 case BASE + 6: \
rlm@1 1058 case BASE + 7: \
rlm@1 1059 case BASE + 8: \
rlm@1 1060 case BASE + 9: \
rlm@1 1061 case BASE + 10: \
rlm@1 1062 case BASE + 11: \
rlm@1 1063 case BASE + 12: \
rlm@1 1064 case BASE + 13: \
rlm@1 1065 case BASE + 14: \
rlm@1 1066 case BASE + 15:
rlm@1 1067
rlm@1 1068 #define CASE_256(BASE) \
rlm@1 1069 CASE_16(BASE) \
rlm@1 1070 CASE_16(BASE + 0x10) \
rlm@1 1071 CASE_16(BASE + 0x20) \
rlm@1 1072 CASE_16(BASE + 0x30) \
rlm@1 1073 CASE_16(BASE + 0x40) \
rlm@1 1074 CASE_16(BASE + 0x50) \
rlm@1 1075 CASE_16(BASE + 0x60) \
rlm@1 1076 CASE_16(BASE + 0x70) \
rlm@1 1077 CASE_16(BASE + 0x80) \
rlm@1 1078 CASE_16(BASE + 0x90) \
rlm@1 1079 CASE_16(BASE + 0xa0) \
rlm@1 1080 CASE_16(BASE + 0xb0) \
rlm@1 1081 CASE_16(BASE + 0xc0) \
rlm@1 1082 CASE_16(BASE + 0xd0) \
rlm@1 1083 CASE_16(BASE + 0xe0) \
rlm@1 1084 CASE_16(BASE + 0xf0)
rlm@1 1085
rlm@1 1086 #define LOGICAL_DATA_OPCODE(OPCODE, OPCODE2, BASE) \
rlm@1 1087 case BASE: \
rlm@1 1088 case BASE + 8: \
rlm@1 1089 { \
rlm@1 1090 /* OP Rd,Rb,Rm LSL # */ \
rlm@1 1091 int base = (opcode >> 16) & 0x0F; \
rlm@1 1092 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1093 int dest = (opcode >> 12) & 15; \
rlm@1 1094 bool C_OUT = C_FLAG; \
rlm@1 1095 u32 value; \
rlm@1 1096 \
rlm@1 1097 if (shift) { \
rlm@1 1098 LOGICAL_LSL_REG \
rlm@1 1099 } else { \
rlm@1 1100 value = reg[opcode & 0x0F].I; \
rlm@1 1101 } \
rlm@1 1102 if (dest == 15) { \
rlm@1 1103 OPCODE2 \
rlm@1 1104 /* todo */ \
rlm@1 1105 if (opcode & 0x00100000) { \
rlm@1 1106 clockTicks++; \
rlm@1 1107 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1108 } \
rlm@1 1109 if (armState) { \
rlm@1 1110 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1111 armNextPC = reg[15].I; \
rlm@1 1112 reg[15].I += 4; \
rlm@1 1113 } else { \
rlm@1 1114 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1115 armNextPC = reg[15].I; \
rlm@1 1116 reg[15].I += 2; \
rlm@1 1117 } \
rlm@1 1118 } else { \
rlm@1 1119 OPCODE \
rlm@1 1120 } \
rlm@1 1121 } \
rlm@1 1122 break; \
rlm@1 1123 case BASE + 2: \
rlm@1 1124 case BASE + 10: \
rlm@1 1125 { \
rlm@1 1126 /* OP Rd,Rb,Rm LSR # */ \
rlm@1 1127 int base = (opcode >> 16) & 0x0F; \
rlm@1 1128 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1129 int dest = (opcode >> 12) & 15; \
rlm@1 1130 bool C_OUT = C_FLAG; \
rlm@1 1131 u32 value; \
rlm@1 1132 if (shift) { \
rlm@1 1133 LOGICAL_LSR_REG \
rlm@1 1134 } else { \
rlm@1 1135 value = 0; \
rlm@1 1136 C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false; \
rlm@1 1137 } \
rlm@1 1138 \
rlm@1 1139 if (dest == 15) { \
rlm@1 1140 OPCODE2 \
rlm@1 1141 /* todo */ \
rlm@1 1142 if (opcode & 0x00100000) { \
rlm@1 1143 clockTicks++; \
rlm@1 1144 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1145 } \
rlm@1 1146 if (armState) { \
rlm@1 1147 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1148 armNextPC = reg[15].I; \
rlm@1 1149 reg[15].I += 4; \
rlm@1 1150 } else { \
rlm@1 1151 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1152 armNextPC = reg[15].I; \
rlm@1 1153 reg[15].I += 2; \
rlm@1 1154 } \
rlm@1 1155 } else { \
rlm@1 1156 OPCODE \
rlm@1 1157 } \
rlm@1 1158 } \
rlm@1 1159 break; \
rlm@1 1160 case BASE + 4: \
rlm@1 1161 case BASE + 12: \
rlm@1 1162 { \
rlm@1 1163 /* OP Rd,Rb,Rm ASR # */ \
rlm@1 1164 int base = (opcode >> 16) & 0x0F; \
rlm@1 1165 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1166 int dest = (opcode >> 12) & 15; \
rlm@1 1167 bool C_OUT = C_FLAG; \
rlm@1 1168 u32 value; \
rlm@1 1169 if (shift) { \
rlm@1 1170 LOGICAL_ASR_REG \
rlm@1 1171 } else { \
rlm@1 1172 if (reg[opcode & 0x0F].I & 0x80000000) { \
rlm@1 1173 value = 0xFFFFFFFF; \
rlm@1 1174 C_OUT = true; \
rlm@1 1175 } else { \
rlm@1 1176 value = 0; \
rlm@1 1177 C_OUT = false; \
rlm@1 1178 } \
rlm@1 1179 } \
rlm@1 1180 \
rlm@1 1181 if (dest == 15) { \
rlm@1 1182 OPCODE2 \
rlm@1 1183 /* todo */ \
rlm@1 1184 if (opcode & 0x00100000) { \
rlm@1 1185 clockTicks++; \
rlm@1 1186 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1187 } \
rlm@1 1188 if (armState) { \
rlm@1 1189 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1190 armNextPC = reg[15].I; \
rlm@1 1191 reg[15].I += 4; \
rlm@1 1192 } else { \
rlm@1 1193 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1194 armNextPC = reg[15].I; \
rlm@1 1195 reg[15].I += 2; \
rlm@1 1196 } \
rlm@1 1197 } else { \
rlm@1 1198 OPCODE \
rlm@1 1199 } \
rlm@1 1200 } \
rlm@1 1201 break; \
rlm@1 1202 case BASE + 6: \
rlm@1 1203 case BASE + 14: \
rlm@1 1204 { \
rlm@1 1205 /* OP Rd,Rb,Rm ROR # */ \
rlm@1 1206 int base = (opcode >> 16) & 0x0F; \
rlm@1 1207 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1208 int dest = (opcode >> 12) & 15; \
rlm@1 1209 bool C_OUT = C_FLAG; \
rlm@1 1210 u32 value; \
rlm@1 1211 if (shift) { \
rlm@1 1212 LOGICAL_ROR_REG \
rlm@1 1213 } else { \
rlm@1 1214 LOGICAL_RRX_REG \
rlm@1 1215 } \
rlm@1 1216 if (dest == 15) { \
rlm@1 1217 OPCODE2 \
rlm@1 1218 /* todo */ \
rlm@1 1219 if (opcode & 0x00100000) { \
rlm@1 1220 clockTicks++; \
rlm@1 1221 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1222 } \
rlm@1 1223 if (armState) { \
rlm@1 1224 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1225 armNextPC = reg[15].I; \
rlm@1 1226 reg[15].I += 4; \
rlm@1 1227 } else { \
rlm@1 1228 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1229 armNextPC = reg[15].I; \
rlm@1 1230 reg[15].I += 2; \
rlm@1 1231 } \
rlm@1 1232 } else { \
rlm@1 1233 OPCODE \
rlm@1 1234 } \
rlm@1 1235 } \
rlm@1 1236 break; \
rlm@1 1237 case BASE + 1: \
rlm@1 1238 { \
rlm@1 1239 /* OP Rd,Rb,Rm LSL Rs */ \
rlm@1 1240 clockTicks++; \
rlm@1 1241 int base = (opcode >> 16) & 0x0F; \
rlm@1 1242 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 1243 int dest = (opcode >> 12) & 15; \
rlm@1 1244 bool C_OUT = C_FLAG; \
rlm@1 1245 u32 value; \
rlm@1 1246 if (shift) { \
rlm@1 1247 if (shift == 32) { \
rlm@1 1248 value = 0; \
rlm@1 1249 C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false); \
rlm@1 1250 } else if (shift < 32) { \
rlm@1 1251 LOGICAL_LSL_REG \
rlm@1 1252 } else { \
rlm@1 1253 value = 0; \
rlm@1 1254 C_OUT = false; \
rlm@1 1255 } \
rlm@1 1256 } else { \
rlm@1 1257 value = reg[opcode & 0x0F].I; \
rlm@1 1258 } \
rlm@1 1259 if (dest == 15) { \
rlm@1 1260 OPCODE2 \
rlm@1 1261 /* todo */ \
rlm@1 1262 if (opcode & 0x00100000) { \
rlm@1 1263 clockTicks++; \
rlm@1 1264 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1265 } \
rlm@1 1266 if (armState) { \
rlm@1 1267 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1268 armNextPC = reg[15].I; \
rlm@1 1269 reg[15].I += 4; \
rlm@1 1270 } else { \
rlm@1 1271 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1272 armNextPC = reg[15].I; \
rlm@1 1273 reg[15].I += 2; \
rlm@1 1274 } \
rlm@1 1275 } else { \
rlm@1 1276 OPCODE \
rlm@1 1277 } \
rlm@1 1278 } \
rlm@1 1279 break; \
rlm@1 1280 case BASE + 3: \
rlm@1 1281 { \
rlm@1 1282 /* OP Rd,Rb,Rm LSR Rs */ \
rlm@1 1283 clockTicks++; \
rlm@1 1284 int base = (opcode >> 16) & 0x0F; \
rlm@1 1285 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 1286 int dest = (opcode >> 12) & 15; \
rlm@1 1287 bool C_OUT = C_FLAG; \
rlm@1 1288 u32 value; \
rlm@1 1289 if (shift) { \
rlm@1 1290 if (shift == 32) { \
rlm@1 1291 value = 0; \
rlm@1 1292 C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false); \
rlm@1 1293 } else if (shift < 32) { \
rlm@1 1294 LOGICAL_LSR_REG \
rlm@1 1295 } else { \
rlm@1 1296 value = 0; \
rlm@1 1297 C_OUT = false; \
rlm@1 1298 } \
rlm@1 1299 } else { \
rlm@1 1300 value = reg[opcode & 0x0F].I; \
rlm@1 1301 } \
rlm@1 1302 if (dest == 15) { \
rlm@1 1303 OPCODE2 \
rlm@1 1304 /* todo */ \
rlm@1 1305 if (opcode & 0x00100000) { \
rlm@1 1306 clockTicks++; \
rlm@1 1307 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1308 } \
rlm@1 1309 if (armState) { \
rlm@1 1310 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1311 armNextPC = reg[15].I; \
rlm@1 1312 reg[15].I += 4; \
rlm@1 1313 } else { \
rlm@1 1314 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1315 armNextPC = reg[15].I; \
rlm@1 1316 reg[15].I += 2; \
rlm@1 1317 } \
rlm@1 1318 } else { \
rlm@1 1319 OPCODE \
rlm@1 1320 } \
rlm@1 1321 } \
rlm@1 1322 break; \
rlm@1 1323 case BASE + 5: \
rlm@1 1324 { \
rlm@1 1325 /* OP Rd,Rb,Rm ASR Rs */ \
rlm@1 1326 clockTicks++; \
rlm@1 1327 int base = (opcode >> 16) & 0x0F; \
rlm@1 1328 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 1329 int dest = (opcode >> 12) & 15; \
rlm@1 1330 bool C_OUT = C_FLAG; \
rlm@1 1331 u32 value; \
rlm@1 1332 if (shift < 32) { \
rlm@1 1333 if (shift) { \
rlm@1 1334 LOGICAL_ASR_REG \
rlm@1 1335 } else { \
rlm@1 1336 value = reg[opcode & 0x0F].I; \
rlm@1 1337 } \
rlm@1 1338 } else { \
rlm@1 1339 if (reg[opcode & 0x0F].I & 0x80000000) { \
rlm@1 1340 value = 0xFFFFFFFF; \
rlm@1 1341 C_OUT = true; \
rlm@1 1342 } else { \
rlm@1 1343 value = 0; \
rlm@1 1344 C_OUT = false; \
rlm@1 1345 } \
rlm@1 1346 } \
rlm@1 1347 if (dest == 15) { \
rlm@1 1348 OPCODE2 \
rlm@1 1349 /* todo */ \
rlm@1 1350 if (opcode & 0x00100000) { \
rlm@1 1351 clockTicks++; \
rlm@1 1352 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1353 } \
rlm@1 1354 if (armState) { \
rlm@1 1355 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1356 armNextPC = reg[15].I; \
rlm@1 1357 reg[15].I += 4; \
rlm@1 1358 } else { \
rlm@1 1359 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1360 armNextPC = reg[15].I; \
rlm@1 1361 reg[15].I += 2; \
rlm@1 1362 } \
rlm@1 1363 } else { \
rlm@1 1364 OPCODE \
rlm@1 1365 } \
rlm@1 1366 } \
rlm@1 1367 break; \
rlm@1 1368 case BASE + 7: \
rlm@1 1369 { \
rlm@1 1370 /* OP Rd,Rb,Rm ROR Rs */ \
rlm@1 1371 clockTicks++; \
rlm@1 1372 int base = (opcode >> 16) & 0x0F; \
rlm@1 1373 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 1374 int dest = (opcode >> 12) & 15; \
rlm@1 1375 bool C_OUT = C_FLAG; \
rlm@1 1376 u32 value; \
rlm@1 1377 if (shift) { \
rlm@1 1378 shift &= 0x1f; \
rlm@1 1379 if (shift) { \
rlm@1 1380 LOGICAL_ROR_REG \
rlm@1 1381 } else { \
rlm@1 1382 value = reg[opcode & 0x0F].I; \
rlm@1 1383 C_OUT = (value & 0x80000000 ? true : false); \
rlm@1 1384 } \
rlm@1 1385 } else { \
rlm@1 1386 value = reg[opcode & 0x0F].I; \
rlm@1 1387 C_OUT = (value & 0x80000000 ? true : false); \
rlm@1 1388 } \
rlm@1 1389 if (dest == 15) { \
rlm@1 1390 OPCODE2 \
rlm@1 1391 /* todo */ \
rlm@1 1392 if (opcode & 0x00100000) { \
rlm@1 1393 clockTicks++; \
rlm@1 1394 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1395 } \
rlm@1 1396 if (armState) { \
rlm@1 1397 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1398 armNextPC = reg[15].I; \
rlm@1 1399 reg[15].I += 4; \
rlm@1 1400 } else { \
rlm@1 1401 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1402 armNextPC = reg[15].I; \
rlm@1 1403 reg[15].I += 2; \
rlm@1 1404 } \
rlm@1 1405 } else { \
rlm@1 1406 OPCODE \
rlm@1 1407 } \
rlm@1 1408 } \
rlm@1 1409 break; \
rlm@1 1410 case BASE + 0x200: \
rlm@1 1411 case BASE + 0x201: \
rlm@1 1412 case BASE + 0x202: \
rlm@1 1413 case BASE + 0x203: \
rlm@1 1414 case BASE + 0x204: \
rlm@1 1415 case BASE + 0x205: \
rlm@1 1416 case BASE + 0x206: \
rlm@1 1417 case BASE + 0x207: \
rlm@1 1418 case BASE + 0x208: \
rlm@1 1419 case BASE + 0x209: \
rlm@1 1420 case BASE + 0x20a: \
rlm@1 1421 case BASE + 0x20b: \
rlm@1 1422 case BASE + 0x20c: \
rlm@1 1423 case BASE + 0x20d: \
rlm@1 1424 case BASE + 0x20e: \
rlm@1 1425 case BASE + 0x20f: \
rlm@1 1426 { \
rlm@1 1427 int shift = (opcode & 0xF00) >> 7; \
rlm@1 1428 int base = (opcode >> 16) & 0x0F; \
rlm@1 1429 int dest = (opcode >> 12) & 0x0F; \
rlm@1 1430 bool C_OUT = C_FLAG; \
rlm@1 1431 u32 value; \
rlm@1 1432 if (shift) { \
rlm@1 1433 LOGICAL_ROR_IMM \
rlm@1 1434 } else { \
rlm@1 1435 value = opcode & 0xff; \
rlm@1 1436 } \
rlm@1 1437 if (dest == 15) { \
rlm@1 1438 OPCODE2 \
rlm@1 1439 /* todo */ \
rlm@1 1440 if (opcode & 0x00100000) { \
rlm@1 1441 clockTicks++; \
rlm@1 1442 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1443 } \
rlm@1 1444 if (armState) { \
rlm@1 1445 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1446 armNextPC = reg[15].I; \
rlm@1 1447 reg[15].I += 4; \
rlm@1 1448 } else { \
rlm@1 1449 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1450 armNextPC = reg[15].I; \
rlm@1 1451 reg[15].I += 2; \
rlm@1 1452 } \
rlm@1 1453 } else { \
rlm@1 1454 OPCODE \
rlm@1 1455 } \
rlm@1 1456 } \
rlm@1 1457 break;
rlm@1 1458
rlm@1 1459 #define LOGICAL_DATA_OPCODE_WITHOUT_base(OPCODE, OPCODE2, BASE) \
rlm@1 1460 case BASE: \
rlm@1 1461 case BASE + 8: \
rlm@1 1462 { \
rlm@1 1463 /* OP Rd,Rb,Rm LSL # */ \
rlm@1 1464 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1465 int dest = (opcode >> 12) & 15; \
rlm@1 1466 bool C_OUT = C_FLAG; \
rlm@1 1467 u32 value; \
rlm@1 1468 \
rlm@1 1469 if (shift) { \
rlm@1 1470 LOGICAL_LSL_REG \
rlm@1 1471 } else { \
rlm@1 1472 value = reg[opcode & 0x0F].I; \
rlm@1 1473 } \
rlm@1 1474 if (dest == 15) { \
rlm@1 1475 OPCODE2 \
rlm@1 1476 /* todo */ \
rlm@1 1477 if (opcode & 0x00100000) { \
rlm@1 1478 clockTicks++; \
rlm@1 1479 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1480 } \
rlm@1 1481 if (armState) { \
rlm@1 1482 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1483 armNextPC = reg[15].I; \
rlm@1 1484 reg[15].I += 4; \
rlm@1 1485 } else { \
rlm@1 1486 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1487 armNextPC = reg[15].I; \
rlm@1 1488 reg[15].I += 2; \
rlm@1 1489 } \
rlm@1 1490 } else { \
rlm@1 1491 OPCODE \
rlm@1 1492 } \
rlm@1 1493 } \
rlm@1 1494 break; \
rlm@1 1495 case BASE + 2: \
rlm@1 1496 case BASE + 10: \
rlm@1 1497 { \
rlm@1 1498 /* OP Rd,Rb,Rm LSR # */ \
rlm@1 1499 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1500 int dest = (opcode >> 12) & 15; \
rlm@1 1501 bool C_OUT = C_FLAG; \
rlm@1 1502 u32 value; \
rlm@1 1503 if (shift) { \
rlm@1 1504 LOGICAL_LSR_REG \
rlm@1 1505 } else { \
rlm@1 1506 value = 0; \
rlm@1 1507 C_OUT = (reg[opcode & 0x0F].I & 0x80000000) ? true : false; \
rlm@1 1508 } \
rlm@1 1509 \
rlm@1 1510 if (dest == 15) { \
rlm@1 1511 OPCODE2 \
rlm@1 1512 /* todo */ \
rlm@1 1513 if (opcode & 0x00100000) { \
rlm@1 1514 clockTicks++; \
rlm@1 1515 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1516 } \
rlm@1 1517 if (armState) { \
rlm@1 1518 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1519 armNextPC = reg[15].I; \
rlm@1 1520 reg[15].I += 4; \
rlm@1 1521 } else { \
rlm@1 1522 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1523 armNextPC = reg[15].I; \
rlm@1 1524 reg[15].I += 2; \
rlm@1 1525 } \
rlm@1 1526 } else { \
rlm@1 1527 OPCODE \
rlm@1 1528 } \
rlm@1 1529 } \
rlm@1 1530 break; \
rlm@1 1531 case BASE + 4: \
rlm@1 1532 case BASE + 12: \
rlm@1 1533 { \
rlm@1 1534 /* OP Rd,Rb,Rm ASR # */ \
rlm@1 1535 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1536 int dest = (opcode >> 12) & 15; \
rlm@1 1537 bool C_OUT = C_FLAG; \
rlm@1 1538 u32 value; \
rlm@1 1539 if (shift) { \
rlm@1 1540 LOGICAL_ASR_REG \
rlm@1 1541 } else { \
rlm@1 1542 if (reg[opcode & 0x0F].I & 0x80000000) { \
rlm@1 1543 value = 0xFFFFFFFF; \
rlm@1 1544 C_OUT = true; \
rlm@1 1545 } else { \
rlm@1 1546 value = 0; \
rlm@1 1547 C_OUT = false; \
rlm@1 1548 } \
rlm@1 1549 } \
rlm@1 1550 \
rlm@1 1551 if (dest == 15) { \
rlm@1 1552 OPCODE2 \
rlm@1 1553 /* todo */ \
rlm@1 1554 if (opcode & 0x00100000) { \
rlm@1 1555 clockTicks++; \
rlm@1 1556 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1557 } \
rlm@1 1558 if (armState) { \
rlm@1 1559 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1560 armNextPC = reg[15].I; \
rlm@1 1561 reg[15].I += 4; \
rlm@1 1562 } else { \
rlm@1 1563 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1564 armNextPC = reg[15].I; \
rlm@1 1565 reg[15].I += 2; \
rlm@1 1566 } \
rlm@1 1567 } else { \
rlm@1 1568 OPCODE \
rlm@1 1569 } \
rlm@1 1570 } \
rlm@1 1571 break; \
rlm@1 1572 case BASE + 6: \
rlm@1 1573 case BASE + 14: \
rlm@1 1574 { \
rlm@1 1575 /* OP Rd,Rb,Rm ROR # */ \
rlm@1 1576 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1577 int dest = (opcode >> 12) & 15; \
rlm@1 1578 bool C_OUT = C_FLAG; \
rlm@1 1579 u32 value; \
rlm@1 1580 if (shift) { \
rlm@1 1581 LOGICAL_ROR_REG \
rlm@1 1582 } else { \
rlm@1 1583 LOGICAL_RRX_REG \
rlm@1 1584 } \
rlm@1 1585 if (dest == 15) { \
rlm@1 1586 OPCODE2 \
rlm@1 1587 /* todo */ \
rlm@1 1588 if (opcode & 0x00100000) { \
rlm@1 1589 clockTicks++; \
rlm@1 1590 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1591 } \
rlm@1 1592 if (armState) { \
rlm@1 1593 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1594 armNextPC = reg[15].I; \
rlm@1 1595 reg[15].I += 4; \
rlm@1 1596 } else { \
rlm@1 1597 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1598 armNextPC = reg[15].I; \
rlm@1 1599 reg[15].I += 2; \
rlm@1 1600 } \
rlm@1 1601 } else { \
rlm@1 1602 OPCODE \
rlm@1 1603 } \
rlm@1 1604 } \
rlm@1 1605 break; \
rlm@1 1606 case BASE + 1: \
rlm@1 1607 { \
rlm@1 1608 /* OP Rd,Rb,Rm LSL Rs */ \
rlm@1 1609 clockTicks++; \
rlm@1 1610 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 1611 int dest = (opcode >> 12) & 15; \
rlm@1 1612 bool C_OUT = C_FLAG; \
rlm@1 1613 u32 value; \
rlm@1 1614 if (shift) { \
rlm@1 1615 if (shift == 32) { \
rlm@1 1616 value = 0; \
rlm@1 1617 C_OUT = (reg[opcode & 0x0F].I & 1 ? true : false); \
rlm@1 1618 } else if (shift < 32) { \
rlm@1 1619 LOGICAL_LSL_REG \
rlm@1 1620 } else { \
rlm@1 1621 value = 0; \
rlm@1 1622 C_OUT = false; \
rlm@1 1623 } \
rlm@1 1624 } else { \
rlm@1 1625 value = reg[opcode & 0x0F].I; \
rlm@1 1626 } \
rlm@1 1627 if (dest == 15) { \
rlm@1 1628 OPCODE2 \
rlm@1 1629 /* todo */ \
rlm@1 1630 if (opcode & 0x00100000) { \
rlm@1 1631 clockTicks++; \
rlm@1 1632 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1633 } \
rlm@1 1634 if (armState) { \
rlm@1 1635 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1636 armNextPC = reg[15].I; \
rlm@1 1637 reg[15].I += 4; \
rlm@1 1638 } else { \
rlm@1 1639 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1640 armNextPC = reg[15].I; \
rlm@1 1641 reg[15].I += 2; \
rlm@1 1642 } \
rlm@1 1643 } else { \
rlm@1 1644 OPCODE \
rlm@1 1645 } \
rlm@1 1646 } \
rlm@1 1647 break; \
rlm@1 1648 case BASE + 3: \
rlm@1 1649 { \
rlm@1 1650 /* OP Rd,Rb,Rm LSR Rs */ \
rlm@1 1651 clockTicks++; \
rlm@1 1652 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 1653 int dest = (opcode >> 12) & 15; \
rlm@1 1654 bool C_OUT = C_FLAG; \
rlm@1 1655 u32 value; \
rlm@1 1656 if (shift) { \
rlm@1 1657 if (shift == 32) { \
rlm@1 1658 value = 0; \
rlm@1 1659 C_OUT = (reg[opcode & 0x0F].I & 0x80000000 ? true : false); \
rlm@1 1660 } else if (shift < 32) { \
rlm@1 1661 LOGICAL_LSR_REG \
rlm@1 1662 } else { \
rlm@1 1663 value = 0; \
rlm@1 1664 C_OUT = false; \
rlm@1 1665 } \
rlm@1 1666 } else { \
rlm@1 1667 value = reg[opcode & 0x0F].I; \
rlm@1 1668 } \
rlm@1 1669 if (dest == 15) { \
rlm@1 1670 OPCODE2 \
rlm@1 1671 /* todo */ \
rlm@1 1672 if (opcode & 0x00100000) { \
rlm@1 1673 clockTicks++; \
rlm@1 1674 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1675 } \
rlm@1 1676 if (armState) { \
rlm@1 1677 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1678 armNextPC = reg[15].I; \
rlm@1 1679 reg[15].I += 4; \
rlm@1 1680 } else { \
rlm@1 1681 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1682 armNextPC = reg[15].I; \
rlm@1 1683 reg[15].I += 2; \
rlm@1 1684 } \
rlm@1 1685 } else { \
rlm@1 1686 OPCODE \
rlm@1 1687 } \
rlm@1 1688 } \
rlm@1 1689 break; \
rlm@1 1690 case BASE + 5: \
rlm@1 1691 { \
rlm@1 1692 /* OP Rd,Rb,Rm ASR Rs */ \
rlm@1 1693 clockTicks++; \
rlm@1 1694 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 1695 int dest = (opcode >> 12) & 15; \
rlm@1 1696 bool C_OUT = C_FLAG; \
rlm@1 1697 u32 value; \
rlm@1 1698 if (shift < 32) { \
rlm@1 1699 if (shift) { \
rlm@1 1700 LOGICAL_ASR_REG \
rlm@1 1701 } else { \
rlm@1 1702 value = reg[opcode & 0x0F].I; \
rlm@1 1703 } \
rlm@1 1704 } else { \
rlm@1 1705 if (reg[opcode & 0x0F].I & 0x80000000) { \
rlm@1 1706 value = 0xFFFFFFFF; \
rlm@1 1707 C_OUT = true; \
rlm@1 1708 } else { \
rlm@1 1709 value = 0; \
rlm@1 1710 C_OUT = false; \
rlm@1 1711 } \
rlm@1 1712 } \
rlm@1 1713 if (dest == 15) { \
rlm@1 1714 OPCODE2 \
rlm@1 1715 /* todo */ \
rlm@1 1716 if (opcode & 0x00100000) { \
rlm@1 1717 clockTicks++; \
rlm@1 1718 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1719 } \
rlm@1 1720 if (armState) { \
rlm@1 1721 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1722 armNextPC = reg[15].I; \
rlm@1 1723 reg[15].I += 4; \
rlm@1 1724 } else { \
rlm@1 1725 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1726 armNextPC = reg[15].I; \
rlm@1 1727 reg[15].I += 2; \
rlm@1 1728 } \
rlm@1 1729 } else { \
rlm@1 1730 OPCODE \
rlm@1 1731 } \
rlm@1 1732 } \
rlm@1 1733 break; \
rlm@1 1734 case BASE + 7: \
rlm@1 1735 { \
rlm@1 1736 /* OP Rd,Rb,Rm ROR Rs */ \
rlm@1 1737 clockTicks++; \
rlm@1 1738 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 1739 int dest = (opcode >> 12) & 15; \
rlm@1 1740 bool C_OUT = C_FLAG; \
rlm@1 1741 u32 value; \
rlm@1 1742 if (shift) { \
rlm@1 1743 shift &= 0x1f; \
rlm@1 1744 if (shift) { \
rlm@1 1745 LOGICAL_ROR_REG \
rlm@1 1746 } else { \
rlm@1 1747 value = reg[opcode & 0x0F].I; \
rlm@1 1748 C_OUT = (value & 0x80000000 ? true : false); \
rlm@1 1749 } \
rlm@1 1750 } else { \
rlm@1 1751 value = reg[opcode & 0x0F].I; \
rlm@1 1752 C_OUT = (value & 0x80000000 ? true : false); \
rlm@1 1753 } \
rlm@1 1754 if (dest == 15) { \
rlm@1 1755 OPCODE2 \
rlm@1 1756 /* todo */ \
rlm@1 1757 if (opcode & 0x00100000) { \
rlm@1 1758 clockTicks++; \
rlm@1 1759 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1760 } \
rlm@1 1761 if (armState) { \
rlm@1 1762 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1763 armNextPC = reg[15].I; \
rlm@1 1764 reg[15].I += 4; \
rlm@1 1765 } else { \
rlm@1 1766 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1767 armNextPC = reg[15].I; \
rlm@1 1768 reg[15].I += 2; \
rlm@1 1769 } \
rlm@1 1770 } else { \
rlm@1 1771 OPCODE \
rlm@1 1772 } \
rlm@1 1773 } \
rlm@1 1774 break; \
rlm@1 1775 case BASE + 0x200: \
rlm@1 1776 case BASE + 0x201: \
rlm@1 1777 case BASE + 0x202: \
rlm@1 1778 case BASE + 0x203: \
rlm@1 1779 case BASE + 0x204: \
rlm@1 1780 case BASE + 0x205: \
rlm@1 1781 case BASE + 0x206: \
rlm@1 1782 case BASE + 0x207: \
rlm@1 1783 case BASE + 0x208: \
rlm@1 1784 case BASE + 0x209: \
rlm@1 1785 case BASE + 0x20a: \
rlm@1 1786 case BASE + 0x20b: \
rlm@1 1787 case BASE + 0x20c: \
rlm@1 1788 case BASE + 0x20d: \
rlm@1 1789 case BASE + 0x20e: \
rlm@1 1790 case BASE + 0x20f: \
rlm@1 1791 { \
rlm@1 1792 int shift = (opcode & 0xF00) >> 7; \
rlm@1 1793 int dest = (opcode >> 12) & 0x0F; \
rlm@1 1794 bool C_OUT = C_FLAG; \
rlm@1 1795 u32 value; \
rlm@1 1796 if (shift) { \
rlm@1 1797 LOGICAL_ROR_IMM \
rlm@1 1798 } else { \
rlm@1 1799 value = opcode & 0xff; \
rlm@1 1800 } \
rlm@1 1801 if (dest == 15) { \
rlm@1 1802 OPCODE2 \
rlm@1 1803 /* todo */ \
rlm@1 1804 if (opcode & 0x00100000) { \
rlm@1 1805 clockTicks++; \
rlm@1 1806 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1807 } \
rlm@1 1808 if (armState) { \
rlm@1 1809 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1810 armNextPC = reg[15].I; \
rlm@1 1811 reg[15].I += 4; \
rlm@1 1812 } else { \
rlm@1 1813 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1814 armNextPC = reg[15].I; \
rlm@1 1815 reg[15].I += 2; \
rlm@1 1816 } \
rlm@1 1817 } else { \
rlm@1 1818 OPCODE \
rlm@1 1819 } \
rlm@1 1820 } \
rlm@1 1821 break;
rlm@1 1822
rlm@1 1823 #define ARITHMETIC_DATA_OPCODE(OPCODE, OPCODE2, BASE) \
rlm@1 1824 case BASE: \
rlm@1 1825 case BASE + 8: \
rlm@1 1826 { \
rlm@1 1827 /* OP Rd,Rb,Rm LSL # */ \
rlm@1 1828 int base = (opcode >> 16) & 0x0F; \
rlm@1 1829 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1830 int dest = (opcode >> 12) & 15; \
rlm@1 1831 u32 value; \
rlm@1 1832 if (shift) { \
rlm@1 1833 ARITHMETIC_LSL_REG \
rlm@1 1834 } else { \
rlm@1 1835 value = reg[opcode & 0x0F].I; \
rlm@1 1836 } \
rlm@1 1837 if (dest == 15) { \
rlm@1 1838 OPCODE2 \
rlm@1 1839 /* todo */ \
rlm@1 1840 if (opcode & 0x00100000) { \
rlm@1 1841 clockTicks++; \
rlm@1 1842 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1843 } \
rlm@1 1844 if (armState) { \
rlm@1 1845 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1846 armNextPC = reg[15].I; \
rlm@1 1847 reg[15].I += 4; \
rlm@1 1848 } else { \
rlm@1 1849 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1850 armNextPC = reg[15].I; \
rlm@1 1851 reg[15].I += 2; \
rlm@1 1852 } \
rlm@1 1853 } else { \
rlm@1 1854 OPCODE \
rlm@1 1855 } \
rlm@1 1856 } \
rlm@1 1857 break; \
rlm@1 1858 case BASE + 2: \
rlm@1 1859 case BASE + 10: \
rlm@1 1860 { \
rlm@1 1861 /* OP Rd,Rb,Rm LSR # */ \
rlm@1 1862 int base = (opcode >> 16) & 0x0F; \
rlm@1 1863 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1864 int dest = (opcode >> 12) & 15; \
rlm@1 1865 u32 value; \
rlm@1 1866 if (shift) { \
rlm@1 1867 ARITHMETIC_LSR_REG \
rlm@1 1868 } else { \
rlm@1 1869 value = 0; \
rlm@1 1870 } \
rlm@1 1871 if (dest == 15) { \
rlm@1 1872 OPCODE2 \
rlm@1 1873 /* todo */ \
rlm@1 1874 if (opcode & 0x00100000) { \
rlm@1 1875 clockTicks++; \
rlm@1 1876 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1877 } \
rlm@1 1878 if (armState) { \
rlm@1 1879 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1880 armNextPC = reg[15].I; \
rlm@1 1881 reg[15].I += 4; \
rlm@1 1882 } else { \
rlm@1 1883 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1884 armNextPC = reg[15].I; \
rlm@1 1885 reg[15].I += 2; \
rlm@1 1886 } \
rlm@1 1887 } else { \
rlm@1 1888 OPCODE \
rlm@1 1889 } \
rlm@1 1890 } \
rlm@1 1891 break; \
rlm@1 1892 case BASE + 4: \
rlm@1 1893 case BASE + 12: \
rlm@1 1894 { \
rlm@1 1895 /* OP Rd,Rb,Rm ASR # */ \
rlm@1 1896 int base = (opcode >> 16) & 0x0F; \
rlm@1 1897 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1898 int dest = (opcode >> 12) & 15; \
rlm@1 1899 u32 value; \
rlm@1 1900 if (shift) { \
rlm@1 1901 ARITHMETIC_ASR_REG \
rlm@1 1902 } else { \
rlm@1 1903 if (reg[opcode & 0x0F].I & 0x80000000) { \
rlm@1 1904 value = 0xFFFFFFFF; \
rlm@1 1905 } else value = 0; \
rlm@1 1906 } \
rlm@1 1907 if (dest == 15) { \
rlm@1 1908 OPCODE2 \
rlm@1 1909 /* todo */ \
rlm@1 1910 if (opcode & 0x00100000) { \
rlm@1 1911 clockTicks++; \
rlm@1 1912 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1913 } \
rlm@1 1914 if (armState) { \
rlm@1 1915 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1916 armNextPC = reg[15].I; \
rlm@1 1917 reg[15].I += 4; \
rlm@1 1918 } else { \
rlm@1 1919 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1920 armNextPC = reg[15].I; \
rlm@1 1921 reg[15].I += 2; \
rlm@1 1922 } \
rlm@1 1923 } else { \
rlm@1 1924 OPCODE \
rlm@1 1925 } \
rlm@1 1926 } \
rlm@1 1927 break; \
rlm@1 1928 case BASE + 6: \
rlm@1 1929 case BASE + 14: \
rlm@1 1930 { \
rlm@1 1931 /* OP Rd,Rb,Rm ROR # */ \
rlm@1 1932 int base = (opcode >> 16) & 0x0F; \
rlm@1 1933 int shift = (opcode >> 7) & 0x1F; \
rlm@1 1934 int dest = (opcode >> 12) & 15; \
rlm@1 1935 u32 value; \
rlm@1 1936 if (shift) { \
rlm@1 1937 ARITHMETIC_ROR_REG \
rlm@1 1938 } else { \
rlm@1 1939 ARITHMETIC_RRX_REG \
rlm@1 1940 } \
rlm@1 1941 if (dest == 15) { \
rlm@1 1942 OPCODE2 \
rlm@1 1943 /* todo */ \
rlm@1 1944 if (opcode & 0x00100000) { \
rlm@1 1945 clockTicks++; \
rlm@1 1946 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1947 } \
rlm@1 1948 if (armState) { \
rlm@1 1949 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1950 armNextPC = reg[15].I; \
rlm@1 1951 reg[15].I += 4; \
rlm@1 1952 } else { \
rlm@1 1953 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1954 armNextPC = reg[15].I; \
rlm@1 1955 reg[15].I += 2; \
rlm@1 1956 } \
rlm@1 1957 } else { \
rlm@1 1958 OPCODE \
rlm@1 1959 } \
rlm@1 1960 } \
rlm@1 1961 break; \
rlm@1 1962 case BASE + 1: \
rlm@1 1963 { \
rlm@1 1964 /* OP Rd,Rb,Rm LSL Rs */ \
rlm@1 1965 clockTicks++; \
rlm@1 1966 int base = (opcode >> 16) & 0x0F; \
rlm@1 1967 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 1968 int dest = (opcode >> 12) & 15; \
rlm@1 1969 u32 value; \
rlm@1 1970 if (shift) { \
rlm@1 1971 if (shift == 32) { \
rlm@1 1972 value = 0; \
rlm@1 1973 } else if (shift < 32) { \
rlm@1 1974 ARITHMETIC_LSL_REG \
rlm@1 1975 } else value = 0; \
rlm@1 1976 } else { \
rlm@1 1977 value = reg[opcode & 0x0F].I; \
rlm@1 1978 } \
rlm@1 1979 if (dest == 15) { \
rlm@1 1980 OPCODE2 \
rlm@1 1981 /* todo */ \
rlm@1 1982 if (opcode & 0x00100000) { \
rlm@1 1983 clockTicks++; \
rlm@1 1984 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 1985 } \
rlm@1 1986 if (armState) { \
rlm@1 1987 reg[15].I &= 0xFFFFFFFC; \
rlm@1 1988 armNextPC = reg[15].I; \
rlm@1 1989 reg[15].I += 4; \
rlm@1 1990 } else { \
rlm@1 1991 reg[15].I &= 0xFFFFFFFE; \
rlm@1 1992 armNextPC = reg[15].I; \
rlm@1 1993 reg[15].I += 2; \
rlm@1 1994 } \
rlm@1 1995 } else { \
rlm@1 1996 OPCODE \
rlm@1 1997 } \
rlm@1 1998 } \
rlm@1 1999 break; \
rlm@1 2000 case BASE + 3: \
rlm@1 2001 { \
rlm@1 2002 /* OP Rd,Rb,Rm LSR Rs */ \
rlm@1 2003 clockTicks++; \
rlm@1 2004 int base = (opcode >> 16) & 0x0F; \
rlm@1 2005 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 2006 int dest = (opcode >> 12) & 15; \
rlm@1 2007 u32 value; \
rlm@1 2008 if (shift) { \
rlm@1 2009 if (shift == 32) { \
rlm@1 2010 value = 0; \
rlm@1 2011 } else if (shift < 32) { \
rlm@1 2012 ARITHMETIC_LSR_REG \
rlm@1 2013 } else value = 0; \
rlm@1 2014 } else { \
rlm@1 2015 value = reg[opcode & 0x0F].I; \
rlm@1 2016 } \
rlm@1 2017 if (dest == 15) { \
rlm@1 2018 OPCODE2 \
rlm@1 2019 /* todo */ \
rlm@1 2020 if (opcode & 0x00100000) { \
rlm@1 2021 clockTicks++; \
rlm@1 2022 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 2023 } \
rlm@1 2024 if (armState) { \
rlm@1 2025 reg[15].I &= 0xFFFFFFFC; \
rlm@1 2026 armNextPC = reg[15].I; \
rlm@1 2027 reg[15].I += 4; \
rlm@1 2028 } else { \
rlm@1 2029 reg[15].I &= 0xFFFFFFFE; \
rlm@1 2030 armNextPC = reg[15].I; \
rlm@1 2031 reg[15].I += 2; \
rlm@1 2032 } \
rlm@1 2033 } else { \
rlm@1 2034 OPCODE \
rlm@1 2035 } \
rlm@1 2036 } \
rlm@1 2037 break; \
rlm@1 2038 case BASE + 5: \
rlm@1 2039 { \
rlm@1 2040 /* OP Rd,Rb,Rm ASR Rs */ \
rlm@1 2041 clockTicks++; \
rlm@1 2042 int base = (opcode >> 16) & 0x0F; \
rlm@1 2043 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 2044 int dest = (opcode >> 12) & 15; \
rlm@1 2045 u32 value; \
rlm@1 2046 if (shift < 32) { \
rlm@1 2047 if (shift) { \
rlm@1 2048 ARITHMETIC_ASR_REG \
rlm@1 2049 } else { \
rlm@1 2050 value = reg[opcode & 0x0F].I; \
rlm@1 2051 } \
rlm@1 2052 } else { \
rlm@1 2053 if (reg[opcode & 0x0F].I & 0x80000000) { \
rlm@1 2054 value = 0xFFFFFFFF; \
rlm@1 2055 } else value = 0; \
rlm@1 2056 } \
rlm@1 2057 if (dest == 15) { \
rlm@1 2058 OPCODE2 \
rlm@1 2059 /* todo */ \
rlm@1 2060 if (opcode & 0x00100000) { \
rlm@1 2061 clockTicks++; \
rlm@1 2062 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 2063 } \
rlm@1 2064 if (armState) { \
rlm@1 2065 reg[15].I &= 0xFFFFFFFC; \
rlm@1 2066 armNextPC = reg[15].I; \
rlm@1 2067 reg[15].I += 4; \
rlm@1 2068 } else { \
rlm@1 2069 reg[15].I &= 0xFFFFFFFE; \
rlm@1 2070 armNextPC = reg[15].I; \
rlm@1 2071 reg[15].I += 2; \
rlm@1 2072 } \
rlm@1 2073 } else { \
rlm@1 2074 OPCODE \
rlm@1 2075 } \
rlm@1 2076 } \
rlm@1 2077 break; \
rlm@1 2078 case BASE + 7: \
rlm@1 2079 { \
rlm@1 2080 /* OP Rd,Rb,Rm ROR Rs */ \
rlm@1 2081 clockTicks++; \
rlm@1 2082 int base = (opcode >> 16) & 0x0F; \
rlm@1 2083 int shift = reg[(opcode >> 8) & 15].B.B0; \
rlm@1 2084 int dest = (opcode >> 12) & 15; \
rlm@1 2085 u32 value; \
rlm@1 2086 if (shift) { \
rlm@1 2087 shift &= 0x1f; \
rlm@1 2088 if (shift) { \
rlm@1 2089 ARITHMETIC_ROR_REG \
rlm@1 2090 } else { \
rlm@1 2091 value = reg[opcode & 0x0F].I; \
rlm@1 2092 } \
rlm@1 2093 } else { \
rlm@1 2094 value = reg[opcode & 0x0F].I; \
rlm@1 2095 } \
rlm@1 2096 if (dest == 15) { \
rlm@1 2097 OPCODE2 \
rlm@1 2098 /* todo */ \
rlm@1 2099 if (opcode & 0x00100000) { \
rlm@1 2100 clockTicks++; \
rlm@1 2101 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 2102 } \
rlm@1 2103 if (armState) { \
rlm@1 2104 reg[15].I &= 0xFFFFFFFC; \
rlm@1 2105 armNextPC = reg[15].I; \
rlm@1 2106 reg[15].I += 4; \
rlm@1 2107 } else { \
rlm@1 2108 reg[15].I &= 0xFFFFFFFE; \
rlm@1 2109 armNextPC = reg[15].I; \
rlm@1 2110 reg[15].I += 2; \
rlm@1 2111 } \
rlm@1 2112 } else { \
rlm@1 2113 OPCODE \
rlm@1 2114 } \
rlm@1 2115 } \
rlm@1 2116 break; \
rlm@1 2117 case BASE + 0x200: \
rlm@1 2118 case BASE + 0x201: \
rlm@1 2119 case BASE + 0x202: \
rlm@1 2120 case BASE + 0x203: \
rlm@1 2121 case BASE + 0x204: \
rlm@1 2122 case BASE + 0x205: \
rlm@1 2123 case BASE + 0x206: \
rlm@1 2124 case BASE + 0x207: \
rlm@1 2125 case BASE + 0x208: \
rlm@1 2126 case BASE + 0x209: \
rlm@1 2127 case BASE + 0x20a: \
rlm@1 2128 case BASE + 0x20b: \
rlm@1 2129 case BASE + 0x20c: \
rlm@1 2130 case BASE + 0x20d: \
rlm@1 2131 case BASE + 0x20e: \
rlm@1 2132 case BASE + 0x20f: \
rlm@1 2133 { \
rlm@1 2134 int shift = (opcode & 0xF00) >> 7; \
rlm@1 2135 int base = (opcode >> 16) & 0x0F; \
rlm@1 2136 int dest = (opcode >> 12) & 0x0F; \
rlm@1 2137 u32 value; \
rlm@1 2138 { \
rlm@1 2139 ARITHMETIC_ROR_IMM \
rlm@1 2140 } \
rlm@1 2141 if (dest == 15) { \
rlm@1 2142 OPCODE2 \
rlm@1 2143 /* todo */ \
rlm@1 2144 if (opcode & 0x00100000) { \
rlm@1 2145 clockTicks++; \
rlm@1 2146 CPUSwitchMode(reg[17].I & 0x1f, false); \
rlm@1 2147 } \
rlm@1 2148 if (armState) { \
rlm@1 2149 reg[15].I &= 0xFFFFFFFC; \
rlm@1 2150 armNextPC = reg[15].I; \
rlm@1 2151 reg[15].I += 4; \
rlm@1 2152 } else { \
rlm@1 2153 reg[15].I &= 0xFFFFFFFE; \
rlm@1 2154 armNextPC = reg[15].I; \
rlm@1 2155 reg[15].I += 2; \
rlm@1 2156 } \
rlm@1 2157 } else { \
rlm@1 2158 OPCODE \
rlm@1 2159 } \
rlm@1 2160 } \
rlm@1 2161 break;
rlm@1 2162
rlm@1 2163 u32 opcode = CPUReadMemoryQuick(armNextPC);
rlm@1 2164
rlm@1 2165 clockTicks = memoryWaitFetch32[(armNextPC >> 24) & 15];
rlm@1 2166
rlm@1 2167 #ifndef FINAL_VERSION
rlm@1 2168 if (armNextPC == stop)
rlm@1 2169 {
rlm@1 2170 armNextPC++;
rlm@1 2171 }
rlm@1 2172 #endif
rlm@1 2173
rlm@1 2174 armNextPC = reg[15].I;
rlm@1 2175 reg[15].I += 4;
rlm@1 2176 int cond = opcode >> 28;
rlm@1 2177 // suggested optimization for frequent cases
rlm@1 2178 bool cond_res;
rlm@1 2179 if (cond == 0x0e)
rlm@1 2180 {
rlm@1 2181 cond_res = true;
rlm@1 2182 }
rlm@1 2183 else
rlm@1 2184 {
rlm@1 2185 switch (cond)
rlm@1 2186 {
rlm@1 2187 case 0x00: // EQ
rlm@1 2188 cond_res = Z_FLAG;
rlm@1 2189 break;
rlm@1 2190 case 0x01: // NE
rlm@1 2191 cond_res = !Z_FLAG;
rlm@1 2192 break;
rlm@1 2193 case 0x02: // CS
rlm@1 2194 cond_res = C_FLAG;
rlm@1 2195 break;
rlm@1 2196 case 0x03: // CC
rlm@1 2197 cond_res = !C_FLAG;
rlm@1 2198 break;
rlm@1 2199 case 0x04: // MI
rlm@1 2200 cond_res = N_FLAG;
rlm@1 2201 break;
rlm@1 2202 case 0x05: // PL
rlm@1 2203 cond_res = !N_FLAG;
rlm@1 2204 break;
rlm@1 2205 case 0x06: // VS
rlm@1 2206 cond_res = V_FLAG;
rlm@1 2207 break;
rlm@1 2208 case 0x07: // VC
rlm@1 2209 cond_res = !V_FLAG;
rlm@1 2210 break;
rlm@1 2211 case 0x08: // HI
rlm@1 2212 cond_res = C_FLAG && !Z_FLAG;
rlm@1 2213 break;
rlm@1 2214 case 0x09: // LS
rlm@1 2215 cond_res = !C_FLAG || Z_FLAG;
rlm@1 2216 break;
rlm@1 2217 case 0x0A: // GE
rlm@1 2218 cond_res = N_FLAG == V_FLAG;
rlm@1 2219 break;
rlm@1 2220 case 0x0B: // LT
rlm@1 2221 cond_res = N_FLAG != V_FLAG;
rlm@1 2222 break;
rlm@1 2223 case 0x0C: // GT
rlm@1 2224 cond_res = !Z_FLAG && (N_FLAG == V_FLAG);
rlm@1 2225 break;
rlm@1 2226 case 0x0D: // LE
rlm@1 2227 cond_res = Z_FLAG || (N_FLAG != V_FLAG);
rlm@1 2228 break;
rlm@1 2229 case 0x0E:
rlm@1 2230 cond_res = true;
rlm@1 2231 break;
rlm@1 2232 case 0x0F:
rlm@1 2233 default:
rlm@1 2234 // ???
rlm@1 2235 cond_res = false;
rlm@1 2236 break;
rlm@1 2237 }
rlm@1 2238 }
rlm@1 2239
rlm@1 2240 if (cond_res)
rlm@1 2241 {
rlm@1 2242 switch (((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x0F))
rlm@1 2243 {
rlm@1 2244 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_AND, OP_AND, 0x000);
rlm@1 2245 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_ANDS, OP_AND, 0x010);
rlm@1 2246 case 0x009:
rlm@1 2247 {
rlm@1 2248 // MUL Rd, Rm, Rs
rlm@1 2249 int dest = (opcode >> 16) & 0x0F;
rlm@1 2250 int mult = (opcode & 0x0F);
rlm@1 2251 u32 rs = reg[(opcode >> 8) & 0x0F].I;
rlm@1 2252 reg[dest].I = reg[mult].I * rs;
rlm@1 2253 if (((s32)rs) < 0)
rlm@1 2254 rs = ~rs;
rlm@1 2255 if ((rs & 0xFFFFFF00) == 0)
rlm@1 2256 clockTicks += 2;
rlm@1 2257 else if ((rs & 0xFFFF0000) == 0)
rlm@1 2258 clockTicks += 3;
rlm@1 2259 else if ((rs & 0xFF000000) == 0)
rlm@1 2260 clockTicks += 4;
rlm@1 2261 else
rlm@1 2262 clockTicks += 5;
rlm@1 2263 }
rlm@1 2264 break;
rlm@1 2265 case 0x019:
rlm@1 2266 {
rlm@1 2267 // MULS Rd, Rm, Rs
rlm@1 2268 int dest = (opcode >> 16) & 0x0F;
rlm@1 2269 int mult = (opcode & 0x0F);
rlm@1 2270 u32 rs = reg[(opcode >> 8) & 0x0F].I;
rlm@1 2271 reg[dest].I = reg[mult].I * rs;
rlm@1 2272 N_FLAG = (reg[dest].I & 0x80000000) ? true : false;
rlm@1 2273 Z_FLAG = (reg[dest].I) ? false : true;
rlm@1 2274 if (((s32)rs) < 0)
rlm@1 2275 rs = ~rs;
rlm@1 2276 if ((rs & 0xFFFFFF00) == 0)
rlm@1 2277 clockTicks += 2;
rlm@1 2278 else if ((rs & 0xFFFF0000) == 0)
rlm@1 2279 clockTicks += 3;
rlm@1 2280 else if ((rs & 0xFF000000) == 0)
rlm@1 2281 clockTicks += 4;
rlm@1 2282 else
rlm@1 2283 clockTicks += 5;
rlm@1 2284 }
rlm@1 2285 break;
rlm@1 2286 case 0x00b:
rlm@1 2287 case 0x02b:
rlm@1 2288 {
rlm@1 2289 // STRH Rd, [Rn], -Rm
rlm@1 2290 int base = (opcode >> 16) & 0x0F;
rlm@1 2291 int dest = (opcode >> 12) & 0x0F;
rlm@1 2292 u32 address = reg[base].I;
rlm@1 2293 int offset = reg[opcode & 0x0F].I;
rlm@1 2294 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2295 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2296 address -= offset;
rlm@1 2297 reg[base].I = address;
rlm@1 2298 }
rlm@1 2299 break;
rlm@1 2300 case 0x04b:
rlm@1 2301 case 0x06b:
rlm@1 2302 {
rlm@1 2303 // STRH Rd, [Rn], #-offset
rlm@1 2304 int base = (opcode >> 16) & 0x0F;
rlm@1 2305 int dest = (opcode >> 12) & 0x0F;
rlm@1 2306 u32 address = reg[base].I;
rlm@1 2307 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
rlm@1 2308 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2309 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2310 address -= offset;
rlm@1 2311 reg[base].I = address;
rlm@1 2312 }
rlm@1 2313 break;
rlm@1 2314 case 0x08b:
rlm@1 2315 case 0x0ab:
rlm@1 2316 {
rlm@1 2317 // STRH Rd, [Rn], Rm
rlm@1 2318 int base = (opcode >> 16) & 0x0F;
rlm@1 2319 int dest = (opcode >> 12) & 0x0F;
rlm@1 2320 u32 address = reg[base].I;
rlm@1 2321 int offset = reg[opcode & 0x0F].I;
rlm@1 2322 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2323 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2324 address += offset;
rlm@1 2325 reg[base].I = address;
rlm@1 2326 }
rlm@1 2327 break;
rlm@1 2328 case 0x0cb:
rlm@1 2329 case 0x0eb:
rlm@1 2330 {
rlm@1 2331 // STRH Rd, [Rn], #offset
rlm@1 2332 int base = (opcode >> 16) & 0x0F;
rlm@1 2333 int dest = (opcode >> 12) & 0x0F;
rlm@1 2334 u32 address = reg[base].I;
rlm@1 2335 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
rlm@1 2336 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2337 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2338 address += offset;
rlm@1 2339 reg[base].I = address;
rlm@1 2340 }
rlm@1 2341 break;
rlm@1 2342 case 0x10b:
rlm@1 2343 {
rlm@1 2344 // STRH Rd, [Rn, -Rm]
rlm@1 2345 int base = (opcode >> 16) & 0x0F;
rlm@1 2346 int dest = (opcode >> 12) & 0x0F;
rlm@1 2347 u32 address = reg[base].I - reg[opcode & 0x0F].I;
rlm@1 2348 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2349 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2350 }
rlm@1 2351 break;
rlm@1 2352 case 0x12b:
rlm@1 2353 {
rlm@1 2354 // STRH Rd, [Rn, -Rm]!
rlm@1 2355 int base = (opcode >> 16) & 0x0F;
rlm@1 2356 int dest = (opcode >> 12) & 0x0F;
rlm@1 2357 u32 address = reg[base].I - reg[opcode & 0x0F].I;
rlm@1 2358 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2359 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2360 reg[base].I = address;
rlm@1 2361 }
rlm@1 2362 break;
rlm@1 2363 case 0x14b:
rlm@1 2364 {
rlm@1 2365 // STRH Rd, [Rn, -#offset]
rlm@1 2366 int base = (opcode >> 16) & 0x0F;
rlm@1 2367 int dest = (opcode >> 12) & 0x0F;
rlm@1 2368 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2369 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2370 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2371 }
rlm@1 2372 break;
rlm@1 2373 case 0x16b:
rlm@1 2374 {
rlm@1 2375 // STRH Rd, [Rn, -#offset]!
rlm@1 2376 int base = (opcode >> 16) & 0x0F;
rlm@1 2377 int dest = (opcode >> 12) & 0x0F;
rlm@1 2378 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2379 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2380 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2381 reg[base].I = address;
rlm@1 2382 }
rlm@1 2383 break;
rlm@1 2384 case 0x18b:
rlm@1 2385 {
rlm@1 2386 // STRH Rd, [Rn, Rm]
rlm@1 2387 int base = (opcode >> 16) & 0x0F;
rlm@1 2388 int dest = (opcode >> 12) & 0x0F;
rlm@1 2389 u32 address = reg[base].I + reg[opcode & 0x0F].I;
rlm@1 2390 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2391 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2392 }
rlm@1 2393 break;
rlm@1 2394 case 0x1ab:
rlm@1 2395 {
rlm@1 2396 // STRH Rd, [Rn, Rm]!
rlm@1 2397 int base = (opcode >> 16) & 0x0F;
rlm@1 2398 int dest = (opcode >> 12) & 0x0F;
rlm@1 2399 u32 address = reg[base].I + reg[opcode & 0x0F].I;
rlm@1 2400 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2401 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2402 reg[base].I = address;
rlm@1 2403 }
rlm@1 2404 break;
rlm@1 2405 case 0x1cb:
rlm@1 2406 {
rlm@1 2407 // STRH Rd, [Rn, #offset]
rlm@1 2408 int base = (opcode >> 16) & 0x0F;
rlm@1 2409 int dest = (opcode >> 12) & 0x0F;
rlm@1 2410 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2411 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2412 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2413 }
rlm@1 2414 break;
rlm@1 2415 case 0x1eb:
rlm@1 2416 {
rlm@1 2417 // STRH Rd, [Rn, #offset]!
rlm@1 2418 int base = (opcode >> 16) & 0x0F;
rlm@1 2419 int dest = (opcode >> 12) & 0x0F;
rlm@1 2420 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2421 clockTicks += 4 + CPUUpdateTicksAccess16(address);
rlm@1 2422 CPUWriteHalfWord(address, reg[dest].W.W0);
rlm@1 2423 reg[base].I = address;
rlm@1 2424 }
rlm@1 2425 break;
rlm@1 2426 case 0x01b:
rlm@1 2427 case 0x03b:
rlm@1 2428 {
rlm@1 2429 // LDRH Rd, [Rn], -Rm
rlm@1 2430 int base = (opcode >> 16) & 0x0F;
rlm@1 2431 int dest = (opcode >> 12) & 0x0F;
rlm@1 2432 u32 address = reg[base].I;
rlm@1 2433 int offset = reg[opcode & 0x0F].I;
rlm@1 2434 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2435 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2436 if (dest != base)
rlm@1 2437 {
rlm@1 2438 address -= offset;
rlm@1 2439 reg[base].I = address;
rlm@1 2440 }
rlm@1 2441 }
rlm@1 2442 break;
rlm@1 2443 case 0x05b:
rlm@1 2444 case 0x07b:
rlm@1 2445 {
rlm@1 2446 // LDRH Rd, [Rn], #-offset
rlm@1 2447 int base = (opcode >> 16) & 0x0F;
rlm@1 2448 int dest = (opcode >> 12) & 0x0F;
rlm@1 2449 u32 address = reg[base].I;
rlm@1 2450 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
rlm@1 2451 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2452 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2453 if (dest != base)
rlm@1 2454 {
rlm@1 2455 address -= offset;
rlm@1 2456 reg[base].I = address;
rlm@1 2457 }
rlm@1 2458 }
rlm@1 2459 break;
rlm@1 2460 case 0x09b:
rlm@1 2461 case 0x0bb:
rlm@1 2462 {
rlm@1 2463 // LDRH Rd, [Rn], Rm
rlm@1 2464 int base = (opcode >> 16) & 0x0F;
rlm@1 2465 int dest = (opcode >> 12) & 0x0F;
rlm@1 2466 u32 address = reg[base].I;
rlm@1 2467 int offset = reg[opcode & 0x0F].I;
rlm@1 2468 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2469 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2470 if (dest != base)
rlm@1 2471 {
rlm@1 2472 address += offset;
rlm@1 2473 reg[base].I = address;
rlm@1 2474 }
rlm@1 2475 }
rlm@1 2476 break;
rlm@1 2477 case 0x0db:
rlm@1 2478 case 0x0fb:
rlm@1 2479 {
rlm@1 2480 // LDRH Rd, [Rn], #offset
rlm@1 2481 int base = (opcode >> 16) & 0x0F;
rlm@1 2482 int dest = (opcode >> 12) & 0x0F;
rlm@1 2483 u32 address = reg[base].I;
rlm@1 2484 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
rlm@1 2485 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2486 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2487 if (dest != base)
rlm@1 2488 {
rlm@1 2489 address += offset;
rlm@1 2490 reg[base].I = address;
rlm@1 2491 }
rlm@1 2492 }
rlm@1 2493 break;
rlm@1 2494 case 0x11b:
rlm@1 2495 {
rlm@1 2496 // LDRH Rd, [Rn, -Rm]
rlm@1 2497 int base = (opcode >> 16) & 0x0F;
rlm@1 2498 int dest = (opcode >> 12) & 0x0F;
rlm@1 2499 u32 address = reg[base].I - reg[opcode & 0x0F].I;
rlm@1 2500 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2501 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2502 }
rlm@1 2503 break;
rlm@1 2504 case 0x13b:
rlm@1 2505 {
rlm@1 2506 // LDRH Rd, [Rn, -Rm]!
rlm@1 2507 int base = (opcode >> 16) & 0x0F;
rlm@1 2508 int dest = (opcode >> 12) & 0x0F;
rlm@1 2509 u32 address = reg[base].I - reg[opcode & 0x0F].I;
rlm@1 2510 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2511 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2512 if (dest != base)
rlm@1 2513 reg[base].I = address;
rlm@1 2514 }
rlm@1 2515 break;
rlm@1 2516 case 0x15b:
rlm@1 2517 {
rlm@1 2518 // LDRH Rd, [Rn, -#offset]
rlm@1 2519 int base = (opcode >> 16) & 0x0F;
rlm@1 2520 int dest = (opcode >> 12) & 0x0F;
rlm@1 2521 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2522 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2523 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2524 }
rlm@1 2525 break;
rlm@1 2526 case 0x17b:
rlm@1 2527 {
rlm@1 2528 // LDRH Rd, [Rn, -#offset]!
rlm@1 2529 int base = (opcode >> 16) & 0x0F;
rlm@1 2530 int dest = (opcode >> 12) & 0x0F;
rlm@1 2531 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2532 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2533 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2534 if (dest != base)
rlm@1 2535 reg[base].I = address;
rlm@1 2536 }
rlm@1 2537 break;
rlm@1 2538 case 0x19b:
rlm@1 2539 {
rlm@1 2540 // LDRH Rd, [Rn, Rm]
rlm@1 2541 int base = (opcode >> 16) & 0x0F;
rlm@1 2542 int dest = (opcode >> 12) & 0x0F;
rlm@1 2543 u32 address = reg[base].I + reg[opcode & 0x0F].I;
rlm@1 2544 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2545 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2546 }
rlm@1 2547 break;
rlm@1 2548 case 0x1bb:
rlm@1 2549 {
rlm@1 2550 // LDRH Rd, [Rn, Rm]!
rlm@1 2551 int base = (opcode >> 16) & 0x0F;
rlm@1 2552 int dest = (opcode >> 12) & 0x0F;
rlm@1 2553 u32 address = reg[base].I + reg[opcode & 0x0F].I;
rlm@1 2554 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2555 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2556 if (dest != base)
rlm@1 2557 reg[base].I = address;
rlm@1 2558 }
rlm@1 2559 break;
rlm@1 2560 case 0x1db:
rlm@1 2561 {
rlm@1 2562 // LDRH Rd, [Rn, #offset]
rlm@1 2563 int base = (opcode >> 16) & 0x0F;
rlm@1 2564 int dest = (opcode >> 12) & 0x0F;
rlm@1 2565 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2566 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2567 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2568 }
rlm@1 2569 break;
rlm@1 2570 case 0x1fb:
rlm@1 2571 {
rlm@1 2572 // LDRH Rd, [Rn, #offset]!
rlm@1 2573 int base = (opcode >> 16) & 0x0F;
rlm@1 2574 int dest = (opcode >> 12) & 0x0F;
rlm@1 2575 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2576 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2577 reg[dest].I = CPUReadHalfWord(address);
rlm@1 2578 if (dest != base)
rlm@1 2579 reg[base].I = address;
rlm@1 2580 }
rlm@1 2581 break;
rlm@1 2582 case 0x01d:
rlm@1 2583 case 0x03d:
rlm@1 2584 {
rlm@1 2585 // LDRSB Rd, [Rn], -Rm
rlm@1 2586 int base = (opcode >> 16) & 0x0F;
rlm@1 2587 int dest = (opcode >> 12) & 0x0F;
rlm@1 2588 u32 address = reg[base].I;
rlm@1 2589 int offset = reg[opcode & 0x0F].I;
rlm@1 2590 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2591 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2592 if (dest != base)
rlm@1 2593 {
rlm@1 2594 address -= offset;
rlm@1 2595 reg[base].I = address;
rlm@1 2596 }
rlm@1 2597 }
rlm@1 2598 break;
rlm@1 2599 case 0x05d:
rlm@1 2600 case 0x07d:
rlm@1 2601 {
rlm@1 2602 // LDRSB Rd, [Rn], #-offset
rlm@1 2603 int base = (opcode >> 16) & 0x0F;
rlm@1 2604 int dest = (opcode >> 12) & 0x0F;
rlm@1 2605 u32 address = reg[base].I;
rlm@1 2606 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
rlm@1 2607 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2608 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2609 if (dest != base)
rlm@1 2610 {
rlm@1 2611 address -= offset;
rlm@1 2612 reg[base].I = address;
rlm@1 2613 }
rlm@1 2614 }
rlm@1 2615 break;
rlm@1 2616 case 0x09d:
rlm@1 2617 case 0x0bd:
rlm@1 2618 {
rlm@1 2619 // LDRSB Rd, [Rn], Rm
rlm@1 2620 int base = (opcode >> 16) & 0x0F;
rlm@1 2621 int dest = (opcode >> 12) & 0x0F;
rlm@1 2622 u32 address = reg[base].I;
rlm@1 2623 int offset = reg[opcode & 0x0F].I;
rlm@1 2624 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2625 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2626 if (dest != base)
rlm@1 2627 {
rlm@1 2628 address += offset;
rlm@1 2629 reg[base].I = address;
rlm@1 2630 }
rlm@1 2631 }
rlm@1 2632 break;
rlm@1 2633 case 0x0dd:
rlm@1 2634 case 0x0fd:
rlm@1 2635 {
rlm@1 2636 // LDRSB Rd, [Rn], #offset
rlm@1 2637 int base = (opcode >> 16) & 0x0F;
rlm@1 2638 int dest = (opcode >> 12) & 0x0F;
rlm@1 2639 u32 address = reg[base].I;
rlm@1 2640 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
rlm@1 2641 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2642 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2643 if (dest != base)
rlm@1 2644 {
rlm@1 2645 address += offset;
rlm@1 2646 reg[base].I = address;
rlm@1 2647 }
rlm@1 2648 }
rlm@1 2649 break;
rlm@1 2650 case 0x11d:
rlm@1 2651 {
rlm@1 2652 // LDRSB Rd, [Rn, -Rm]
rlm@1 2653 int base = (opcode >> 16) & 0x0F;
rlm@1 2654 int dest = (opcode >> 12) & 0x0F;
rlm@1 2655 u32 address = reg[base].I - reg[opcode & 0x0F].I;
rlm@1 2656 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2657 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2658 }
rlm@1 2659 break;
rlm@1 2660 case 0x13d:
rlm@1 2661 {
rlm@1 2662 // LDRSB Rd, [Rn, -Rm]!
rlm@1 2663 int base = (opcode >> 16) & 0x0F;
rlm@1 2664 int dest = (opcode >> 12) & 0x0F;
rlm@1 2665 u32 address = reg[base].I - reg[opcode & 0x0F].I;
rlm@1 2666 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2667 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2668 if (dest != base)
rlm@1 2669 reg[base].I = address;
rlm@1 2670 }
rlm@1 2671 break;
rlm@1 2672 case 0x15d:
rlm@1 2673 {
rlm@1 2674 // LDRSB Rd, [Rn, -#offset]
rlm@1 2675 int base = (opcode >> 16) & 0x0F;
rlm@1 2676 int dest = (opcode >> 12) & 0x0F;
rlm@1 2677 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2678 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2679 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2680 }
rlm@1 2681 break;
rlm@1 2682 case 0x17d:
rlm@1 2683 {
rlm@1 2684 // LDRSB Rd, [Rn, -#offset]!
rlm@1 2685 int base = (opcode >> 16) & 0x0F;
rlm@1 2686 int dest = (opcode >> 12) & 0x0F;
rlm@1 2687 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2688 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2689 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2690 if (dest != base)
rlm@1 2691 reg[base].I = address;
rlm@1 2692 }
rlm@1 2693 break;
rlm@1 2694 case 0x19d:
rlm@1 2695 {
rlm@1 2696 // LDRSB Rd, [Rn, Rm]
rlm@1 2697 int base = (opcode >> 16) & 0x0F;
rlm@1 2698 int dest = (opcode >> 12) & 0x0F;
rlm@1 2699 u32 address = reg[base].I + reg[opcode & 0x0F].I;
rlm@1 2700 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2701 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2702 }
rlm@1 2703 break;
rlm@1 2704 case 0x1bd:
rlm@1 2705 {
rlm@1 2706 // LDRSB Rd, [Rn, Rm]!
rlm@1 2707 int base = (opcode >> 16) & 0x0F;
rlm@1 2708 int dest = (opcode >> 12) & 0x0F;
rlm@1 2709 u32 address = reg[base].I + reg[opcode & 0x0F].I;
rlm@1 2710 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2711 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2712 if (dest != base)
rlm@1 2713 reg[base].I = address;
rlm@1 2714 }
rlm@1 2715 break;
rlm@1 2716 case 0x1dd:
rlm@1 2717 {
rlm@1 2718 // LDRSB Rd, [Rn, #offset]
rlm@1 2719 int base = (opcode >> 16) & 0x0F;
rlm@1 2720 int dest = (opcode >> 12) & 0x0F;
rlm@1 2721 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2722 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2723 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2724 }
rlm@1 2725 break;
rlm@1 2726 case 0x1fd:
rlm@1 2727 {
rlm@1 2728 // LDRSB Rd, [Rn, #offset]!
rlm@1 2729 int base = (opcode >> 16) & 0x0F;
rlm@1 2730 int dest = (opcode >> 12) & 0x0F;
rlm@1 2731 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2732 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2733 reg[dest].I = (s8)CPUReadByte(address);
rlm@1 2734 if (dest != base)
rlm@1 2735 reg[base].I = address;
rlm@1 2736 }
rlm@1 2737 break;
rlm@1 2738 case 0x01f:
rlm@1 2739 case 0x03f:
rlm@1 2740 {
rlm@1 2741 // LDRSH Rd, [Rn], -Rm
rlm@1 2742 int base = (opcode >> 16) & 0x0F;
rlm@1 2743 int dest = (opcode >> 12) & 0x0F;
rlm@1 2744 u32 address = reg[base].I;
rlm@1 2745 int offset = reg[opcode & 0x0F].I;
rlm@1 2746 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2747 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2748 if (dest != base)
rlm@1 2749 {
rlm@1 2750 address -= offset;
rlm@1 2751 reg[base].I = address;
rlm@1 2752 }
rlm@1 2753 }
rlm@1 2754 break;
rlm@1 2755 case 0x05f:
rlm@1 2756 case 0x07f:
rlm@1 2757 {
rlm@1 2758 // LDRSH Rd, [Rn], #-offset
rlm@1 2759 int base = (opcode >> 16) & 0x0F;
rlm@1 2760 int dest = (opcode >> 12) & 0x0F;
rlm@1 2761 u32 address = reg[base].I;
rlm@1 2762 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
rlm@1 2763 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2764 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2765 if (dest != base)
rlm@1 2766 {
rlm@1 2767 address -= offset;
rlm@1 2768 reg[base].I = address;
rlm@1 2769 }
rlm@1 2770 }
rlm@1 2771 break;
rlm@1 2772 case 0x09f:
rlm@1 2773 case 0x0bf:
rlm@1 2774 {
rlm@1 2775 // LDRSH Rd, [Rn], Rm
rlm@1 2776 int base = (opcode >> 16) & 0x0F;
rlm@1 2777 int dest = (opcode >> 12) & 0x0F;
rlm@1 2778 u32 address = reg[base].I;
rlm@1 2779 int offset = reg[opcode & 0x0F].I;
rlm@1 2780 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2781 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2782 if (dest != base)
rlm@1 2783 {
rlm@1 2784 address += offset;
rlm@1 2785 reg[base].I = address;
rlm@1 2786 }
rlm@1 2787 }
rlm@1 2788 break;
rlm@1 2789 case 0x0df:
rlm@1 2790 case 0x0ff:
rlm@1 2791 {
rlm@1 2792 // LDRSH Rd, [Rn], #offset
rlm@1 2793 int base = (opcode >> 16) & 0x0F;
rlm@1 2794 int dest = (opcode >> 12) & 0x0F;
rlm@1 2795 u32 address = reg[base].I;
rlm@1 2796 int offset = (opcode & 0x0F) | ((opcode >> 4) & 0xF0);
rlm@1 2797 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2798 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2799 if (dest != base)
rlm@1 2800 {
rlm@1 2801 address += offset;
rlm@1 2802 reg[base].I = address;
rlm@1 2803 }
rlm@1 2804 }
rlm@1 2805 break;
rlm@1 2806 case 0x11f:
rlm@1 2807 {
rlm@1 2808 // LDRSH Rd, [Rn, -Rm]
rlm@1 2809 int base = (opcode >> 16) & 0x0F;
rlm@1 2810 int dest = (opcode >> 12) & 0x0F;
rlm@1 2811 u32 address = reg[base].I - reg[opcode & 0x0F].I;
rlm@1 2812 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2813 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2814 }
rlm@1 2815 break;
rlm@1 2816 case 0x13f:
rlm@1 2817 {
rlm@1 2818 // LDRSH Rd, [Rn, -Rm]!
rlm@1 2819 int base = (opcode >> 16) & 0x0F;
rlm@1 2820 int dest = (opcode >> 12) & 0x0F;
rlm@1 2821 u32 address = reg[base].I - reg[opcode & 0x0F].I;
rlm@1 2822 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2823 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2824 if (dest != base)
rlm@1 2825 reg[base].I = address;
rlm@1 2826 }
rlm@1 2827 break;
rlm@1 2828 case 0x15f:
rlm@1 2829 {
rlm@1 2830 // LDRSH Rd, [Rn, -#offset]
rlm@1 2831 int base = (opcode >> 16) & 0x0F;
rlm@1 2832 int dest = (opcode >> 12) & 0x0F;
rlm@1 2833 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2834 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2835 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2836 }
rlm@1 2837 break;
rlm@1 2838 case 0x17f:
rlm@1 2839 {
rlm@1 2840 // LDRSH Rd, [Rn, -#offset]!
rlm@1 2841 int base = (opcode >> 16) & 0x0F;
rlm@1 2842 int dest = (opcode >> 12) & 0x0F;
rlm@1 2843 u32 address = reg[base].I - ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2844 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2845 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2846 if (dest != base)
rlm@1 2847 reg[base].I = address;
rlm@1 2848 }
rlm@1 2849 break;
rlm@1 2850 case 0x19f:
rlm@1 2851 {
rlm@1 2852 // LDRSH Rd, [Rn, Rm]
rlm@1 2853 int base = (opcode >> 16) & 0x0F;
rlm@1 2854 int dest = (opcode >> 12) & 0x0F;
rlm@1 2855 u32 address = reg[base].I + reg[opcode & 0x0F].I;
rlm@1 2856 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2857 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2858 }
rlm@1 2859 break;
rlm@1 2860 case 0x1bf:
rlm@1 2861 {
rlm@1 2862 // LDRSH Rd, [Rn, Rm]!
rlm@1 2863 int base = (opcode >> 16) & 0x0F;
rlm@1 2864 int dest = (opcode >> 12) & 0x0F;
rlm@1 2865 u32 address = reg[base].I + reg[opcode & 0x0F].I;
rlm@1 2866 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2867 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2868 if (dest != base)
rlm@1 2869 reg[base].I = address;
rlm@1 2870 }
rlm@1 2871 break;
rlm@1 2872 case 0x1df:
rlm@1 2873 {
rlm@1 2874 // LDRSH Rd, [Rn, #offset]
rlm@1 2875 int base = (opcode >> 16) & 0x0F;
rlm@1 2876 int dest = (opcode >> 12) & 0x0F;
rlm@1 2877 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2878 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2879 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2880 }
rlm@1 2881 break;
rlm@1 2882 case 0x1ff:
rlm@1 2883 {
rlm@1 2884 // LDRSH Rd, [Rn, #offset]!
rlm@1 2885 int base = (opcode >> 16) & 0x0F;
rlm@1 2886 int dest = (opcode >> 12) & 0x0F;
rlm@1 2887 u32 address = reg[base].I + ((opcode & 0x0F) | ((opcode >> 4) & 0xF0));
rlm@1 2888 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 2889 reg[dest].I = (s16)CPUReadHalfWordSigned(address);
rlm@1 2890 if (dest != base)
rlm@1 2891 reg[base].I = address;
rlm@1 2892 }
rlm@1 2893 break;
rlm@1 2894 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EOR, OP_EOR, 0x020);
rlm@1 2895 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_EORS, OP_EOR, 0x030);
rlm@1 2896 case 0x029:
rlm@1 2897 {
rlm@1 2898 // MLA Rd, Rm, Rs, Rn
rlm@1 2899 int dest = (opcode >> 16) & 0x0F;
rlm@1 2900 int mult = (opcode & 0x0F);
rlm@1 2901 u32 rs = reg[(opcode >> 8) & 0x0F].I;
rlm@1 2902 reg[dest].I = reg[mult].I * rs + reg[(opcode >> 12) & 0x0f].I;
rlm@1 2903 if (((s32)rs) < 0)
rlm@1 2904 rs = ~rs;
rlm@1 2905 if ((rs & 0xFFFFFF00) == 0)
rlm@1 2906 clockTicks += 3;
rlm@1 2907 else if ((rs & 0xFFFF0000) == 0)
rlm@1 2908 clockTicks += 4;
rlm@1 2909 else if ((rs & 0xFF000000) == 0)
rlm@1 2910 clockTicks += 5;
rlm@1 2911 else
rlm@1 2912 clockTicks += 6;
rlm@1 2913 }
rlm@1 2914 break;
rlm@1 2915 case 0x039:
rlm@1 2916 {
rlm@1 2917 // MLAS Rd, Rm, Rs, Rn
rlm@1 2918 int dest = (opcode >> 16) & 0x0F;
rlm@1 2919 int mult = (opcode & 0x0F);
rlm@1 2920 u32 rs = reg[(opcode >> 8) & 0x0F].I;
rlm@1 2921 reg[dest].I = reg[mult].I * rs + reg[(opcode >> 12) & 0x0f].I;
rlm@1 2922 N_FLAG = (reg[dest].I & 0x80000000) ? true : false;
rlm@1 2923 Z_FLAG = (reg[dest].I) ? false : true;
rlm@1 2924 if (((s32)rs) < 0)
rlm@1 2925 rs = ~rs;
rlm@1 2926 if ((rs & 0xFFFFFF00) == 0)
rlm@1 2927 clockTicks += 3;
rlm@1 2928 else if ((rs & 0xFFFF0000) == 0)
rlm@1 2929 clockTicks += 4;
rlm@1 2930 else if ((rs & 0xFF000000) == 0)
rlm@1 2931 clockTicks += 5;
rlm@1 2932 else
rlm@1 2933 clockTicks += 6;
rlm@1 2934 }
rlm@1 2935 break;
rlm@1 2936 ARITHMETIC_DATA_OPCODE(OP_SUB, OP_SUB, 0x040);
rlm@1 2937 ARITHMETIC_DATA_OPCODE(OP_SUBS, OP_SUB, 0x050);
rlm@1 2938 ARITHMETIC_DATA_OPCODE(OP_RSB, OP_RSB, 0x060);
rlm@1 2939 ARITHMETIC_DATA_OPCODE(OP_RSBS, OP_RSB, 0x070);
rlm@1 2940 ARITHMETIC_DATA_OPCODE(OP_ADD, OP_ADD, 0x080);
rlm@1 2941 ARITHMETIC_DATA_OPCODE(OP_ADDS, OP_ADD, 0x090);
rlm@1 2942 case 0x089:
rlm@1 2943 {
rlm@1 2944 // UMULL RdLo, RdHi, Rn, Rs
rlm@1 2945 u32 umult = reg[(opcode & 0x0F)].I;
rlm@1 2946 u32 usource = reg[(opcode >> 8) & 0x0F].I;
rlm@1 2947 int destLo = (opcode >> 12) & 0x0F;
rlm@1 2948 int destHi = (opcode >> 16) & 0x0F;
rlm@1 2949 u64 uTemp = ((u64)umult) * ((u64)usource);
rlm@1 2950 reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF);
rlm@1 2951 reg[destHi].I = (u32)(uTemp >> 32);
rlm@1 2952 if ((usource & 0xFFFFFF00) == 0)
rlm@1 2953 clockTicks += 2;
rlm@1 2954 else if ((usource & 0xFFFF0000) == 0)
rlm@1 2955 clockTicks += 3;
rlm@1 2956 else if ((usource & 0xFF000000) == 0)
rlm@1 2957 clockTicks += 4;
rlm@1 2958 else
rlm@1 2959 clockTicks += 5;
rlm@1 2960 }
rlm@1 2961 break;
rlm@1 2962 case 0x099:
rlm@1 2963 {
rlm@1 2964 // UMULLS RdLo, RdHi, Rn, Rs
rlm@1 2965 u32 umult = reg[(opcode & 0x0F)].I;
rlm@1 2966 u32 usource = reg[(opcode >> 8) & 0x0F].I;
rlm@1 2967 int destLo = (opcode >> 12) & 0x0F;
rlm@1 2968 int destHi = (opcode >> 16) & 0x0F;
rlm@1 2969 u64 uTemp = ((u64)umult) * ((u64)usource);
rlm@1 2970 reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF);
rlm@1 2971 reg[destHi].I = (u32)(uTemp >> 32);
rlm@1 2972 Z_FLAG = (uTemp) ? false : true;
rlm@1 2973 N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
rlm@1 2974 if ((usource & 0xFFFFFF00) == 0)
rlm@1 2975 clockTicks += 2;
rlm@1 2976 else if ((usource & 0xFFFF0000) == 0)
rlm@1 2977 clockTicks += 3;
rlm@1 2978 else if ((usource & 0xFF000000) == 0)
rlm@1 2979 clockTicks += 4;
rlm@1 2980 else
rlm@1 2981 clockTicks += 5;
rlm@1 2982 }
rlm@1 2983 break;
rlm@1 2984 ARITHMETIC_DATA_OPCODE(OP_ADC, OP_ADC, 0x0a0);
rlm@1 2985 ARITHMETIC_DATA_OPCODE(OP_ADCS, OP_ADC, 0x0b0);
rlm@1 2986 case 0x0a9:
rlm@1 2987 {
rlm@1 2988 // UMLAL RdLo, RdHi, Rn, Rs
rlm@1 2989 u32 umult = reg[(opcode & 0x0F)].I;
rlm@1 2990 u32 usource = reg[(opcode >> 8) & 0x0F].I;
rlm@1 2991 int destLo = (opcode >> 12) & 0x0F;
rlm@1 2992 int destHi = (opcode >> 16) & 0x0F;
rlm@1 2993 u64 uTemp = (u64)reg[destHi].I;
rlm@1 2994 uTemp <<= 32;
rlm@1 2995 uTemp |= (u64)reg[destLo].I;
rlm@1 2996 uTemp += ((u64)umult) * ((u64)usource);
rlm@1 2997 reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF);
rlm@1 2998 reg[destHi].I = (u32)(uTemp >> 32);
rlm@1 2999 if ((usource & 0xFFFFFF00) == 0)
rlm@1 3000 clockTicks += 3;
rlm@1 3001 else if ((usource & 0xFFFF0000) == 0)
rlm@1 3002 clockTicks += 4;
rlm@1 3003 else if ((usource & 0xFF000000) == 0)
rlm@1 3004 clockTicks += 5;
rlm@1 3005 else
rlm@1 3006 clockTicks += 6;
rlm@1 3007 }
rlm@1 3008 break;
rlm@1 3009 case 0x0b9:
rlm@1 3010 {
rlm@1 3011 // UMLALS RdLo, RdHi, Rn, Rs
rlm@1 3012 u32 umult = reg[(opcode & 0x0F)].I;
rlm@1 3013 u32 usource = reg[(opcode >> 8) & 0x0F].I;
rlm@1 3014 int destLo = (opcode >> 12) & 0x0F;
rlm@1 3015 int destHi = (opcode >> 16) & 0x0F;
rlm@1 3016 u64 uTemp = (u64)reg[destHi].I;
rlm@1 3017 uTemp <<= 32;
rlm@1 3018 uTemp |= (u64)reg[destLo].I;
rlm@1 3019 uTemp += ((u64)umult) * ((u64)usource);
rlm@1 3020 reg[destLo].I = (u32)(uTemp & 0xFFFFFFFF);
rlm@1 3021 reg[destHi].I = (u32)(uTemp >> 32);
rlm@1 3022 Z_FLAG = (uTemp) ? false : true;
rlm@1 3023 N_FLAG = (reg[destHi].I & 0x80000000) ? true : false;
rlm@1 3024 if ((usource & 0xFFFFFF00) == 0)
rlm@1 3025 clockTicks += 3;
rlm@1 3026 else if ((usource & 0xFFFF0000) == 0)
rlm@1 3027 clockTicks += 4;
rlm@1 3028 else if ((usource & 0xFF000000) == 0)
rlm@1 3029 clockTicks += 5;
rlm@1 3030 else
rlm@1 3031 clockTicks += 6;
rlm@1 3032 }
rlm@1 3033 break;
rlm@1 3034 ARITHMETIC_DATA_OPCODE(OP_SBC, OP_SBC, 0x0c0);
rlm@1 3035 ARITHMETIC_DATA_OPCODE(OP_SBCS, OP_SBC, 0x0d0);
rlm@1 3036 case 0x0c9:
rlm@1 3037 {
rlm@1 3038 // SMULL RdLo, RdHi, Rm, Rs
rlm@1 3039 int destLo = (opcode >> 12) & 0x0F;
rlm@1 3040 int destHi = (opcode >> 16) & 0x0F;
rlm@1 3041 u32 rs = reg[(opcode >> 8) & 0x0F].I;
rlm@1 3042 s64 m = (s32)reg[(opcode & 0x0F)].I;
rlm@1 3043 s64 s = (s32)rs;
rlm@1 3044 s64 sTemp = m * s;
rlm@1 3045 reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF);
rlm@1 3046 reg[destHi].I = (u32)(sTemp >> 32);
rlm@1 3047 if (((s32)rs) < 0)
rlm@1 3048 rs = ~rs;
rlm@1 3049 if ((rs & 0xFFFFFF00) == 0)
rlm@1 3050 clockTicks += 2;
rlm@1 3051 else if ((rs & 0xFFFF0000) == 0)
rlm@1 3052 clockTicks += 3;
rlm@1 3053 else if ((rs & 0xFF000000) == 0)
rlm@1 3054 clockTicks += 4;
rlm@1 3055 else
rlm@1 3056 clockTicks += 5;
rlm@1 3057 }
rlm@1 3058 break;
rlm@1 3059 case 0x0d9:
rlm@1 3060 {
rlm@1 3061 // SMULLS RdLo, RdHi, Rm, Rs
rlm@1 3062 int destLo = (opcode >> 12) & 0x0F;
rlm@1 3063 int destHi = (opcode >> 16) & 0x0F;
rlm@1 3064 u32 rs = reg[(opcode >> 8) & 0x0F].I;
rlm@1 3065 s64 m = (s32)reg[(opcode & 0x0F)].I;
rlm@1 3066 s64 s = (s32)rs;
rlm@1 3067 s64 sTemp = m * s;
rlm@1 3068 reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF);
rlm@1 3069 reg[destHi].I = (u32)(sTemp >> 32);
rlm@1 3070 Z_FLAG = (sTemp) ? false : true;
rlm@1 3071 N_FLAG = (sTemp < 0) ? true : false;
rlm@1 3072 if (((s32)rs) < 0)
rlm@1 3073 rs = ~rs;
rlm@1 3074 if ((rs & 0xFFFFFF00) == 0)
rlm@1 3075 clockTicks += 2;
rlm@1 3076 else if ((rs & 0xFFFF0000) == 0)
rlm@1 3077 clockTicks += 3;
rlm@1 3078 else if ((rs & 0xFF000000) == 0)
rlm@1 3079 clockTicks += 4;
rlm@1 3080 else
rlm@1 3081 clockTicks += 5;
rlm@1 3082 }
rlm@1 3083 break;
rlm@1 3084 ARITHMETIC_DATA_OPCODE(OP_RSC, OP_RSC, 0x0e0);
rlm@1 3085 ARITHMETIC_DATA_OPCODE(OP_RSCS, OP_RSC, 0x0f0);
rlm@1 3086 case 0x0e9:
rlm@1 3087 {
rlm@1 3088 // SMLAL RdLo, RdHi, Rm, Rs
rlm@1 3089 int destLo = (opcode >> 12) & 0x0F;
rlm@1 3090 int destHi = (opcode >> 16) & 0x0F;
rlm@1 3091 u32 rs = reg[(opcode >> 8) & 0x0F].I;
rlm@1 3092 s64 m = (s32)reg[(opcode & 0x0F)].I;
rlm@1 3093 s64 s = (s32)rs;
rlm@1 3094 s64 sTemp = (u64)reg[destHi].I;
rlm@1 3095 sTemp <<= 32;
rlm@1 3096 sTemp |= (u64)reg[destLo].I;
rlm@1 3097 sTemp += m * s;
rlm@1 3098 reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF);
rlm@1 3099 reg[destHi].I = (u32)(sTemp >> 32);
rlm@1 3100 if (((s32)rs) < 0)
rlm@1 3101 rs = ~rs;
rlm@1 3102 if ((rs & 0xFFFFFF00) == 0)
rlm@1 3103 clockTicks += 3;
rlm@1 3104 else if ((rs & 0xFFFF0000) == 0)
rlm@1 3105 clockTicks += 4;
rlm@1 3106 else if ((rs & 0xFF000000) == 0)
rlm@1 3107 clockTicks += 5;
rlm@1 3108 else
rlm@1 3109 clockTicks += 6;
rlm@1 3110 }
rlm@1 3111 break;
rlm@1 3112 case 0x0f9:
rlm@1 3113 {
rlm@1 3114 // SMLALS RdLo, RdHi, Rm, Rs
rlm@1 3115 int destLo = (opcode >> 12) & 0x0F;
rlm@1 3116 int destHi = (opcode >> 16) & 0x0F;
rlm@1 3117 u32 rs = reg[(opcode >> 8) & 0x0F].I;
rlm@1 3118 s64 m = (s32)reg[(opcode & 0x0F)].I;
rlm@1 3119 s64 s = (s32)rs;
rlm@1 3120 s64 sTemp = (u64)reg[destHi].I;
rlm@1 3121 sTemp <<= 32;
rlm@1 3122 sTemp |= (u64)reg[destLo].I;
rlm@1 3123 sTemp += m * s;
rlm@1 3124 reg[destLo].I = (u32)(sTemp & 0xFFFFFFFF);
rlm@1 3125 reg[destHi].I = (u32)(sTemp >> 32);
rlm@1 3126 Z_FLAG = (sTemp) ? false : true;
rlm@1 3127 N_FLAG = (sTemp < 0) ? true : false;
rlm@1 3128 if (((s32)rs) < 0)
rlm@1 3129 rs = ~rs;
rlm@1 3130 if ((rs & 0xFFFFFF00) == 0)
rlm@1 3131 clockTicks += 3;
rlm@1 3132 else if ((rs & 0xFFFF0000) == 0)
rlm@1 3133 clockTicks += 4;
rlm@1 3134 else if ((rs & 0xFF000000) == 0)
rlm@1 3135 clockTicks += 5;
rlm@1 3136 else
rlm@1 3137 clockTicks += 6;
rlm@1 3138 }
rlm@1 3139 break;
rlm@1 3140 LOGICAL_DATA_OPCODE(OP_TST, OP_TST, 0x110);
rlm@1 3141 case 0x100:
rlm@1 3142 // MRS Rd, CPSR
rlm@1 3143 // TODO: check if right instruction....
rlm@1 3144 CPUUpdateCPSR();
rlm@1 3145 reg[(opcode >> 12) & 0x0F].I = reg[16].I;
rlm@1 3146 break;
rlm@1 3147 case 0x109:
rlm@1 3148 {
rlm@1 3149 // SWP Rd, Rm, [Rn]
rlm@1 3150 u32 address = reg[(opcode >> 16) & 15].I;
rlm@1 3151 u32 temp = CPUReadMemory(address);
rlm@1 3152 CPUWriteMemory(address, reg[opcode & 15].I);
rlm@1 3153 reg[(opcode >> 12) & 15].I = temp;
rlm@1 3154 }
rlm@1 3155 break;
rlm@1 3156 LOGICAL_DATA_OPCODE(OP_TEQ, OP_TEQ, 0x130);
rlm@1 3157 case 0x120:
rlm@1 3158 {
rlm@1 3159 // MSR CPSR_fields, Rm
rlm@1 3160 CPUUpdateCPSR();
rlm@1 3161 u32 value = reg[opcode & 15].I;
rlm@1 3162 u32 newValue = reg[16].I;
rlm@1 3163 if (armMode > 0x10)
rlm@1 3164 {
rlm@1 3165 if (opcode & 0x00010000)
rlm@1 3166 newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
rlm@1 3167 if (opcode & 0x00020000)
rlm@1 3168 newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
rlm@1 3169 if (opcode & 0x00040000)
rlm@1 3170 newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
rlm@1 3171 }
rlm@1 3172 if (opcode & 0x00080000)
rlm@1 3173 newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
rlm@1 3174 newValue |= 0x10;
rlm@1 3175 CPUSwitchMode(newValue & 0x1f, false);
rlm@1 3176 reg[16].I = newValue;
rlm@1 3177 CPUUpdateFlags();
rlm@1 3178 }
rlm@1 3179 break;
rlm@1 3180 case 0x121:
rlm@1 3181 {
rlm@1 3182 // BX Rm
rlm@1 3183 // TODO: check if right instruction...
rlm@1 3184 clockTicks += 3;
rlm@1 3185 int base = opcode & 0x0F;
rlm@1 3186 armState = reg[base].I & 1 ? false : true;
rlm@1 3187 if (armState)
rlm@1 3188 {
rlm@1 3189 reg[15].I = reg[base].I & 0xFFFFFFFC;
rlm@1 3190 armNextPC = reg[15].I;
rlm@1 3191 reg[15].I += 4;
rlm@1 3192 }
rlm@1 3193 else
rlm@1 3194 {
rlm@1 3195 reg[15].I = reg[base].I & 0xFFFFFFFE;
rlm@1 3196 armNextPC = reg[15].I;
rlm@1 3197 reg[15].I += 2;
rlm@1 3198 }
rlm@1 3199 }
rlm@1 3200 break;
rlm@1 3201 ARITHMETIC_DATA_OPCODE(OP_CMP, OP_CMP, 0x150);
rlm@1 3202 case 0x140:
rlm@1 3203 // MRS Rd, SPSR
rlm@1 3204 // TODO: check if right instruction...
rlm@1 3205 reg[(opcode >> 12) & 0x0F].I = reg[17].I;
rlm@1 3206 break;
rlm@1 3207 case 0x149:
rlm@1 3208 {
rlm@1 3209 // SWPB Rd, Rm, [Rn]
rlm@1 3210 u32 address = reg[(opcode >> 16) & 15].I;
rlm@1 3211 u32 temp = CPUReadByte(address);
rlm@1 3212 CPUWriteByte(address, reg[opcode & 15].B.B0);
rlm@1 3213 reg[(opcode >> 12) & 15].I = temp;
rlm@1 3214 }
rlm@1 3215 break;
rlm@1 3216 ARITHMETIC_DATA_OPCODE(OP_CMN, OP_CMN, 0x170);
rlm@1 3217 case 0x160:
rlm@1 3218 {
rlm@1 3219 // MSR SPSR_fields, Rm
rlm@1 3220 u32 value = reg[opcode & 15].I;
rlm@1 3221 if (armMode > 0x10 && armMode < 0x1f)
rlm@1 3222 {
rlm@1 3223 if (opcode & 0x00010000)
rlm@1 3224 reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
rlm@1 3225 if (opcode & 0x00020000)
rlm@1 3226 reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
rlm@1 3227 if (opcode & 0x00040000)
rlm@1 3228 reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
rlm@1 3229 if (opcode & 0x00080000)
rlm@1 3230 reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
rlm@1 3231 }
rlm@1 3232 }
rlm@1 3233 break;
rlm@1 3234 LOGICAL_DATA_OPCODE(OP_ORR, OP_ORR, 0x180);
rlm@1 3235 LOGICAL_DATA_OPCODE(OP_ORRS, OP_ORR, 0x190);
rlm@1 3236 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOV, OP_MOV, 0x1a0);
rlm@1 3237 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MOVS, OP_MOV, 0x1b0);
rlm@1 3238 LOGICAL_DATA_OPCODE(OP_BIC, OP_BIC, 0x1c0);
rlm@1 3239 LOGICAL_DATA_OPCODE(OP_BICS, OP_BIC, 0x1d0);
rlm@1 3240 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVN, OP_MVN, 0x1e0);
rlm@1 3241 LOGICAL_DATA_OPCODE_WITHOUT_base(OP_MVNS, OP_MVN, 0x1f0);
rlm@1 3242 #ifdef BKPT_SUPPORT
rlm@1 3243 case 0x127:
rlm@1 3244 case 0x7ff: // for GDB support
rlm@1 3245 extern void (*dbgSignal)(int, int);
rlm@1 3246 reg[15].I -= 4;
rlm@1 3247 armNextPC -= 4;
rlm@1 3248 dbgSignal(5, (opcode & 0x0f) | ((opcode >> 4) & 0xfff0));
rlm@1 3249 return;
rlm@1 3250 #endif
rlm@1 3251 case 0x320:
rlm@1 3252 case 0x321:
rlm@1 3253 case 0x322:
rlm@1 3254 case 0x323:
rlm@1 3255 case 0x324:
rlm@1 3256 case 0x325:
rlm@1 3257 case 0x326:
rlm@1 3258 case 0x327:
rlm@1 3259 case 0x328:
rlm@1 3260 case 0x329:
rlm@1 3261 case 0x32a:
rlm@1 3262 case 0x32b:
rlm@1 3263 case 0x32c:
rlm@1 3264 case 0x32d:
rlm@1 3265 case 0x32e:
rlm@1 3266 case 0x32f:
rlm@1 3267 {
rlm@1 3268 // MSR CPSR_fields, #
rlm@1 3269 CPUUpdateCPSR();
rlm@1 3270 u32 value = opcode & 0xFF;
rlm@1 3271 int shift = (opcode & 0xF00) >> 7;
rlm@1 3272 if (shift)
rlm@1 3273 {
rlm@1 3274 ROR_IMM_MSR;
rlm@1 3275 }
rlm@1 3276 u32 newValue = reg[16].I;
rlm@1 3277 if (armMode > 0x10)
rlm@1 3278 {
rlm@1 3279 if (opcode & 0x00010000)
rlm@1 3280 newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
rlm@1 3281 if (opcode & 0x00020000)
rlm@1 3282 newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
rlm@1 3283 if (opcode & 0x00040000)
rlm@1 3284 newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
rlm@1 3285 }
rlm@1 3286 if (opcode & 0x00080000)
rlm@1 3287 newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
rlm@1 3288
rlm@1 3289 newValue |= 0x10;
rlm@1 3290
rlm@1 3291 CPUSwitchMode(newValue & 0x1f, false);
rlm@1 3292 reg[16].I = newValue;
rlm@1 3293 CPUUpdateFlags();
rlm@1 3294 }
rlm@1 3295 break;
rlm@1 3296 case 0x360:
rlm@1 3297 case 0x361:
rlm@1 3298 case 0x362:
rlm@1 3299 case 0x363:
rlm@1 3300 case 0x364:
rlm@1 3301 case 0x365:
rlm@1 3302 case 0x366:
rlm@1 3303 case 0x367:
rlm@1 3304 case 0x368:
rlm@1 3305 case 0x369:
rlm@1 3306 case 0x36a:
rlm@1 3307 case 0x36b:
rlm@1 3308 case 0x36c:
rlm@1 3309 case 0x36d:
rlm@1 3310 case 0x36e:
rlm@1 3311 case 0x36f:
rlm@1 3312 {
rlm@1 3313 // MSR SPSR_fields, #
rlm@1 3314 if (armMode > 0x10 && armMode < 0x1f)
rlm@1 3315 {
rlm@1 3316 u32 value = opcode & 0xFF;
rlm@1 3317 int shift = (opcode & 0xF00) >> 7;
rlm@1 3318 if (shift)
rlm@1 3319 {
rlm@1 3320 ROR_IMM_MSR;
rlm@1 3321 }
rlm@1 3322 if (opcode & 0x00010000)
rlm@1 3323 reg[17].I = (reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
rlm@1 3324 if (opcode & 0x00020000)
rlm@1 3325 reg[17].I = (reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
rlm@1 3326 if (opcode & 0x00040000)
rlm@1 3327 reg[17].I = (reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
rlm@1 3328 if (opcode & 0x00080000)
rlm@1 3329 reg[17].I = (reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
rlm@1 3330 }
rlm@1 3331 }
rlm@1 3332 break;
rlm@1 3333 CASE_16(0x400)
rlm@1 3334 // T versions shouldn't be different on GBA
rlm@1 3335 CASE_16(0x420)
rlm@1 3336 {
rlm@1 3337 // STR Rd, [Rn], -#
rlm@1 3338 int offset = opcode & 0xFFF;
rlm@1 3339 int dest = (opcode >> 12) & 15;
rlm@1 3340 int base = (opcode >> 16) & 15;
rlm@1 3341 u32 address = reg[base].I;
rlm@1 3342 CPUWriteMemory(address, reg[dest].I);
rlm@1 3343 reg[base].I = address - offset;
rlm@1 3344 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3345 }
rlm@1 3346 break;
rlm@1 3347 CASE_16(0x480)
rlm@1 3348 // T versions shouldn't be different on GBA
rlm@1 3349 CASE_16(0x4a0)
rlm@1 3350 {
rlm@1 3351 // STR Rd, [Rn], #
rlm@1 3352 int offset = opcode & 0xFFF;
rlm@1 3353 int dest = (opcode >> 12) & 15;
rlm@1 3354 int base = (opcode >> 16) & 15;
rlm@1 3355 u32 address = reg[base].I;
rlm@1 3356 CPUWriteMemory(address, reg[dest].I);
rlm@1 3357 reg[base].I = address + offset;
rlm@1 3358 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3359 }
rlm@1 3360 break;
rlm@1 3361 CASE_16(0x500)
rlm@1 3362 {
rlm@1 3363 // STR Rd, [Rn, -#]
rlm@1 3364 int offset = opcode & 0xFFF;
rlm@1 3365 int dest = (opcode >> 12) & 15;
rlm@1 3366 int base = (opcode >> 16) & 15;
rlm@1 3367 u32 address = reg[base].I - offset;
rlm@1 3368 CPUWriteMemory(address, reg[dest].I);
rlm@1 3369 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3370 }
rlm@1 3371 break;
rlm@1 3372 CASE_16(0x520)
rlm@1 3373 {
rlm@1 3374 // STR Rd, [Rn, -#]!
rlm@1 3375 int offset = opcode & 0xFFF;
rlm@1 3376 int dest = (opcode >> 12) & 15;
rlm@1 3377 int base = (opcode >> 16) & 15;
rlm@1 3378 u32 address = reg[base].I - offset;
rlm@1 3379 reg[base].I = address;
rlm@1 3380 CPUWriteMemory(address, reg[dest].I);
rlm@1 3381 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3382 }
rlm@1 3383 break;
rlm@1 3384 CASE_16(0x580)
rlm@1 3385 {
rlm@1 3386 // STR Rd, [Rn, #]
rlm@1 3387 int offset = opcode & 0xFFF;
rlm@1 3388 int dest = (opcode >> 12) & 15;
rlm@1 3389 int base = (opcode >> 16) & 15;
rlm@1 3390 u32 address = reg[base].I + offset;
rlm@1 3391 CPUWriteMemory(address, reg[dest].I);
rlm@1 3392 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3393 }
rlm@1 3394 break;
rlm@1 3395 CASE_16(0x5a0)
rlm@1 3396 {
rlm@1 3397 // STR Rd, [Rn, #]!
rlm@1 3398 int offset = opcode & 0xFFF;
rlm@1 3399 int dest = (opcode >> 12) & 15;
rlm@1 3400 int base = (opcode >> 16) & 15;
rlm@1 3401 u32 address = reg[base].I + offset;
rlm@1 3402 reg[base].I = address;
rlm@1 3403 CPUWriteMemory(address, reg[dest].I);
rlm@1 3404 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3405 }
rlm@1 3406 break;
rlm@1 3407 CASE_16(0x410)
rlm@1 3408 {
rlm@1 3409 // LDR Rd, [Rn], -#
rlm@1 3410 int offset = opcode & 0xFFF;
rlm@1 3411 int dest = (opcode >> 12) & 15;
rlm@1 3412 int base = (opcode >> 16) & 15;
rlm@1 3413 u32 address = reg[base].I;
rlm@1 3414 reg[dest].I = CPUReadMemory(address);
rlm@1 3415 if (dest != base)
rlm@1 3416 reg[base].I -= offset;
rlm@1 3417 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 3418 if (dest == 15)
rlm@1 3419 {
rlm@1 3420 clockTicks += 2;
rlm@1 3421 reg[15].I &= 0xFFFFFFFC;
rlm@1 3422 armNextPC = reg[15].I;
rlm@1 3423 reg[15].I += 4;
rlm@1 3424 }
rlm@1 3425 }
rlm@1 3426 break;
rlm@1 3427 CASE_16(0x430)
rlm@1 3428 {
rlm@1 3429 // LDRT Rd, [Rn], -#
rlm@1 3430 int offset = opcode & 0xFFF;
rlm@1 3431 int dest = (opcode >> 12) & 15;
rlm@1 3432 int base = (opcode >> 16) & 15;
rlm@1 3433 u32 address = reg[base].I;
rlm@1 3434 reg[dest].I = CPUReadMemory(address);
rlm@1 3435 if (dest != base)
rlm@1 3436 reg[base].I -= offset;
rlm@1 3437 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 3438 }
rlm@1 3439 break;
rlm@1 3440 CASE_16(0x490)
rlm@1 3441 {
rlm@1 3442 // LDR Rd, [Rn], #
rlm@1 3443 int offset = opcode & 0xFFF;
rlm@1 3444 int dest = (opcode >> 12) & 15;
rlm@1 3445 int base = (opcode >> 16) & 15;
rlm@1 3446 u32 address = reg[base].I;
rlm@1 3447 reg[dest].I = CPUReadMemory(address);
rlm@1 3448 if (dest != base)
rlm@1 3449 reg[base].I += offset;
rlm@1 3450 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 3451 if (dest == 15)
rlm@1 3452 {
rlm@1 3453 clockTicks += 2;
rlm@1 3454 reg[15].I &= 0xFFFFFFFC;
rlm@1 3455 armNextPC = reg[15].I;
rlm@1 3456 reg[15].I += 4;
rlm@1 3457 }
rlm@1 3458 }
rlm@1 3459 break;
rlm@1 3460 CASE_16(0x4b0)
rlm@1 3461 {
rlm@1 3462 // LDRT Rd, [Rn], #
rlm@1 3463 int offset = opcode & 0xFFF;
rlm@1 3464 int dest = (opcode >> 12) & 15;
rlm@1 3465 int base = (opcode >> 16) & 15;
rlm@1 3466 u32 address = reg[base].I;
rlm@1 3467 reg[dest].I = CPUReadMemory(address);
rlm@1 3468 if (dest != base)
rlm@1 3469 reg[base].I += offset;
rlm@1 3470 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 3471 }
rlm@1 3472 break;
rlm@1 3473 CASE_16(0x510)
rlm@1 3474 {
rlm@1 3475 // LDR Rd, [Rn, -#]
rlm@1 3476 int offset = opcode & 0xFFF;
rlm@1 3477 int dest = (opcode >> 12) & 15;
rlm@1 3478 int base = (opcode >> 16) & 15;
rlm@1 3479 u32 address = reg[base].I - offset;
rlm@1 3480 reg[dest].I = CPUReadMemory(address);
rlm@1 3481 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 3482 if (dest == 15)
rlm@1 3483 {
rlm@1 3484 clockTicks += 2;
rlm@1 3485 reg[15].I &= 0xFFFFFFFC;
rlm@1 3486 armNextPC = reg[15].I;
rlm@1 3487 reg[15].I += 4;
rlm@1 3488 }
rlm@1 3489 }
rlm@1 3490 break;
rlm@1 3491 CASE_16(0x530)
rlm@1 3492 {
rlm@1 3493 // LDR Rd, [Rn, -#]!
rlm@1 3494 int offset = opcode & 0xFFF;
rlm@1 3495 int dest = (opcode >> 12) & 15;
rlm@1 3496 int base = (opcode >> 16) & 15;
rlm@1 3497 u32 address = reg[base].I - offset;
rlm@1 3498 reg[dest].I = CPUReadMemory(address);
rlm@1 3499 if (dest != base)
rlm@1 3500 reg[base].I = address;
rlm@1 3501 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 3502 if (dest == 15)
rlm@1 3503 {
rlm@1 3504 clockTicks += 2;
rlm@1 3505 reg[15].I &= 0xFFFFFFFC;
rlm@1 3506 armNextPC = reg[15].I;
rlm@1 3507 reg[15].I += 4;
rlm@1 3508 }
rlm@1 3509 }
rlm@1 3510 break;
rlm@1 3511 CASE_16(0x590)
rlm@1 3512 {
rlm@1 3513 // LDR Rd, [Rn, #]
rlm@1 3514 int offset = opcode & 0xFFF;
rlm@1 3515 int dest = (opcode >> 12) & 15;
rlm@1 3516 int base = (opcode >> 16) & 15;
rlm@1 3517 u32 address = reg[base].I + offset;
rlm@1 3518 reg[dest].I = CPUReadMemory(address);
rlm@1 3519 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 3520 if (dest == 15)
rlm@1 3521 {
rlm@1 3522 clockTicks += 2;
rlm@1 3523 reg[15].I &= 0xFFFFFFFC;
rlm@1 3524 armNextPC = reg[15].I;
rlm@1 3525 reg[15].I += 4;
rlm@1 3526 }
rlm@1 3527 }
rlm@1 3528 break;
rlm@1 3529 CASE_16(0x5b0)
rlm@1 3530 {
rlm@1 3531 // LDR Rd, [Rn, #]!
rlm@1 3532 int offset = opcode & 0xFFF;
rlm@1 3533 int dest = (opcode >> 12) & 15;
rlm@1 3534 int base = (opcode >> 16) & 15;
rlm@1 3535 u32 address = reg[base].I + offset;
rlm@1 3536 reg[dest].I = CPUReadMemory(address);
rlm@1 3537 if (dest != base)
rlm@1 3538 reg[base].I = address;
rlm@1 3539 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 3540 if (dest == 15)
rlm@1 3541 {
rlm@1 3542 clockTicks += 2;
rlm@1 3543 reg[15].I &= 0xFFFFFFFC;
rlm@1 3544 armNextPC = reg[15].I;
rlm@1 3545 reg[15].I += 4;
rlm@1 3546 }
rlm@1 3547 }
rlm@1 3548 break;
rlm@1 3549 CASE_16(0x440)
rlm@1 3550 // T versions shouldn't be different on GBA
rlm@1 3551 CASE_16(0x460)
rlm@1 3552 {
rlm@1 3553 // STRB Rd, [Rn], -#
rlm@1 3554 int offset = opcode & 0xFFF;
rlm@1 3555 int dest = (opcode >> 12) & 15;
rlm@1 3556 int base = (opcode >> 16) & 15;
rlm@1 3557 u32 address = reg[base].I;
rlm@1 3558 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 3559 reg[base].I = address - offset;
rlm@1 3560 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 3561 }
rlm@1 3562 break;
rlm@1 3563 CASE_16(0x4c0)
rlm@1 3564 // T versions shouldn't be different on GBA
rlm@1 3565 CASE_16(0x4e0)
rlm@1 3566 // STRB Rd, [Rn], #
rlm@1 3567 {
rlm@1 3568 int offset = opcode & 0xFFF;
rlm@1 3569 int dest = (opcode >> 12) & 15;
rlm@1 3570 int base = (opcode >> 16) & 15;
rlm@1 3571 u32 address = reg[base].I;
rlm@1 3572 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 3573 reg[base].I = address + offset;
rlm@1 3574 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 3575 }
rlm@1 3576 break;
rlm@1 3577 CASE_16(0x540)
rlm@1 3578 {
rlm@1 3579 // STRB Rd, [Rn, -#]
rlm@1 3580 int offset = opcode & 0xFFF;
rlm@1 3581 int dest = (opcode >> 12) & 15;
rlm@1 3582 int base = (opcode >> 16) & 15;
rlm@1 3583 u32 address = reg[base].I - offset;
rlm@1 3584 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 3585 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 3586 }
rlm@1 3587 break;
rlm@1 3588 CASE_16(0x560)
rlm@1 3589 {
rlm@1 3590 // STRB Rd, [Rn, -#]!
rlm@1 3591 int offset = opcode & 0xFFF;
rlm@1 3592 int dest = (opcode >> 12) & 15;
rlm@1 3593 int base = (opcode >> 16) & 15;
rlm@1 3594 u32 address = reg[base].I - offset;
rlm@1 3595 reg[base].I = address;
rlm@1 3596 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 3597 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 3598 }
rlm@1 3599 break;
rlm@1 3600 CASE_16(0x5c0)
rlm@1 3601 {
rlm@1 3602 // STRB Rd, [Rn, #]
rlm@1 3603 int offset = opcode & 0xFFF;
rlm@1 3604 int dest = (opcode >> 12) & 15;
rlm@1 3605 int base = (opcode >> 16) & 15;
rlm@1 3606 u32 address = reg[base].I + offset;
rlm@1 3607 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 3608 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 3609 }
rlm@1 3610 break;
rlm@1 3611 CASE_16(0x5e0)
rlm@1 3612 {
rlm@1 3613 // STRB Rd, [Rn, #]!
rlm@1 3614 int offset = opcode & 0xFFF;
rlm@1 3615 int dest = (opcode >> 12) & 15;
rlm@1 3616 int base = (opcode >> 16) & 15;
rlm@1 3617 u32 address = reg[base].I + offset;
rlm@1 3618 reg[base].I = address;
rlm@1 3619 CPUWriteByte(address, reg[dest].I);
rlm@1 3620 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 3621 }
rlm@1 3622 break;
rlm@1 3623 CASE_16(0x450)
rlm@1 3624 // T versions shouldn't be different
rlm@1 3625 CASE_16(0x470)
rlm@1 3626 {
rlm@1 3627 // LDRB Rd, [Rn], -#
rlm@1 3628 int offset = opcode & 0xFFF;
rlm@1 3629 int dest = (opcode >> 12) & 15;
rlm@1 3630 int base = (opcode >> 16) & 15;
rlm@1 3631 u32 address = reg[base].I;
rlm@1 3632 reg[dest].I = CPUReadByte(address);
rlm@1 3633 if (dest != base)
rlm@1 3634 reg[base].I -= offset;
rlm@1 3635 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 3636 }
rlm@1 3637 break;
rlm@1 3638 CASE_16(0x4d0)
rlm@1 3639 CASE_16(0x4f0) // T versions should not be different
rlm@1 3640 {
rlm@1 3641 // LDRB Rd, [Rn], #
rlm@1 3642 int offset = opcode & 0xFFF;
rlm@1 3643 int dest = (opcode >> 12) & 15;
rlm@1 3644 int base = (opcode >> 16) & 15;
rlm@1 3645 u32 address = reg[base].I;
rlm@1 3646 reg[dest].I = CPUReadByte(address);
rlm@1 3647 if (dest != base)
rlm@1 3648 reg[base].I += offset;
rlm@1 3649 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 3650 }
rlm@1 3651 break;
rlm@1 3652 CASE_16(0x550)
rlm@1 3653 {
rlm@1 3654 // LDRB Rd, [Rn, -#]
rlm@1 3655 int offset = opcode & 0xFFF;
rlm@1 3656 int dest = (opcode >> 12) & 15;
rlm@1 3657 int base = (opcode >> 16) & 15;
rlm@1 3658 u32 address = reg[base].I - offset;
rlm@1 3659 reg[dest].I = CPUReadByte(address);
rlm@1 3660 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 3661 }
rlm@1 3662 break;
rlm@1 3663 CASE_16(0x570)
rlm@1 3664 {
rlm@1 3665 // LDRB Rd, [Rn, -#]!
rlm@1 3666 int offset = opcode & 0xFFF;
rlm@1 3667 int dest = (opcode >> 12) & 15;
rlm@1 3668 int base = (opcode >> 16) & 15;
rlm@1 3669 u32 address = reg[base].I - offset;
rlm@1 3670 reg[dest].I = CPUReadByte(address);
rlm@1 3671 if (dest != base)
rlm@1 3672 reg[base].I = address;
rlm@1 3673 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 3674 }
rlm@1 3675 break;
rlm@1 3676 CASE_16(0x5d0)
rlm@1 3677 {
rlm@1 3678 // LDRB Rd, [Rn, #]
rlm@1 3679 int offset = opcode & 0xFFF;
rlm@1 3680 int dest = (opcode >> 12) & 15;
rlm@1 3681 int base = (opcode >> 16) & 15;
rlm@1 3682 u32 address = reg[base].I + offset;
rlm@1 3683 reg[dest].I = CPUReadByte(address);
rlm@1 3684 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 3685 }
rlm@1 3686 break;
rlm@1 3687 CASE_16(0x5f0)
rlm@1 3688 {
rlm@1 3689 // LDRB Rd, [Rn, #]!
rlm@1 3690 int offset = opcode & 0xFFF;
rlm@1 3691 int dest = (opcode >> 12) & 15;
rlm@1 3692 int base = (opcode >> 16) & 15;
rlm@1 3693 u32 address = reg[base].I + offset;
rlm@1 3694 reg[dest].I = CPUReadByte(address);
rlm@1 3695 if (dest != base)
rlm@1 3696 reg[base].I = address;
rlm@1 3697 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 3698 }
rlm@1 3699 break;
rlm@1 3700 case 0x600:
rlm@1 3701 case 0x608:
rlm@1 3702 // T versions are the same
rlm@1 3703 case 0x620:
rlm@1 3704 case 0x628:
rlm@1 3705 {
rlm@1 3706 // STR Rd, [Rn], -Rm, LSL #
rlm@1 3707 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 3708 int dest = (opcode >> 12) & 15;
rlm@1 3709 int base = (opcode >> 16) & 15;
rlm@1 3710 u32 address = reg[base].I;
rlm@1 3711 CPUWriteMemory(address, reg[dest].I);
rlm@1 3712 reg[base].I = address - offset;
rlm@1 3713 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3714 }
rlm@1 3715 break;
rlm@1 3716 case 0x602:
rlm@1 3717 case 0x60a:
rlm@1 3718 // T versions are the same
rlm@1 3719 case 0x622:
rlm@1 3720 case 0x62a:
rlm@1 3721 {
rlm@1 3722 // STR Rd, [Rn], -Rm, LSR #
rlm@1 3723 int shift = (opcode >> 7) & 31;
rlm@1 3724 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 3725 int dest = (opcode >> 12) & 15;
rlm@1 3726 int base = (opcode >> 16) & 15;
rlm@1 3727 u32 address = reg[base].I;
rlm@1 3728 CPUWriteMemory(address, reg[dest].I);
rlm@1 3729 reg[base].I = address - offset;
rlm@1 3730 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3731 }
rlm@1 3732 break;
rlm@1 3733 case 0x604:
rlm@1 3734 case 0x60c:
rlm@1 3735 // T versions are the same
rlm@1 3736 case 0x624:
rlm@1 3737 case 0x62c:
rlm@1 3738 {
rlm@1 3739 // STR Rd, [Rn], -Rm, ASR #
rlm@1 3740 int shift = (opcode >> 7) & 31;
rlm@1 3741 int offset;
rlm@1 3742 if (shift)
rlm@1 3743 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 3744 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 3745 offset = 0xFFFFFFFF;
rlm@1 3746 else
rlm@1 3747 offset = 0;
rlm@1 3748 int dest = (opcode >> 12) & 15;
rlm@1 3749 int base = (opcode >> 16) & 15;
rlm@1 3750 u32 address = reg[base].I;
rlm@1 3751 CPUWriteMemory(address, reg[dest].I);
rlm@1 3752 reg[base].I = address - offset;
rlm@1 3753 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3754 }
rlm@1 3755 break;
rlm@1 3756 case 0x606:
rlm@1 3757 case 0x60e:
rlm@1 3758 // T versions are the same
rlm@1 3759 case 0x626:
rlm@1 3760 case 0x62e:
rlm@1 3761 {
rlm@1 3762 // STR Rd, [Rn], -Rm, ROR #
rlm@1 3763 int shift = (opcode >> 7) & 31;
rlm@1 3764 u32 value = reg[opcode & 15].I;
rlm@1 3765 if (shift)
rlm@1 3766 {
rlm@1 3767 ROR_VALUE;
rlm@1 3768 }
rlm@1 3769 else
rlm@1 3770 {
rlm@1 3771 RCR_VALUE;
rlm@1 3772 }
rlm@1 3773 int dest = (opcode >> 12) & 15;
rlm@1 3774 int base = (opcode >> 16) & 15;
rlm@1 3775 u32 address = reg[base].I;
rlm@1 3776 CPUWriteMemory(address, reg[dest].I);
rlm@1 3777 reg[base].I = address - value;
rlm@1 3778 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3779 }
rlm@1 3780 break;
rlm@1 3781 case 0x680:
rlm@1 3782 case 0x688:
rlm@1 3783 // T versions are the same
rlm@1 3784 case 0x6a0:
rlm@1 3785 case 0x6a8:
rlm@1 3786 {
rlm@1 3787 // STR Rd, [Rn], Rm, LSL #
rlm@1 3788 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 3789 int dest = (opcode >> 12) & 15;
rlm@1 3790 int base = (opcode >> 16) & 15;
rlm@1 3791 u32 address = reg[base].I;
rlm@1 3792 CPUWriteMemory(address, reg[dest].I);
rlm@1 3793 reg[base].I = address + offset;
rlm@1 3794 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3795 }
rlm@1 3796 break;
rlm@1 3797 case 0x682:
rlm@1 3798 case 0x68a:
rlm@1 3799 // T versions are the same
rlm@1 3800 case 0x6a2:
rlm@1 3801 case 0x6aa:
rlm@1 3802 {
rlm@1 3803 // STR Rd, [Rn], Rm, LSR #
rlm@1 3804 int shift = (opcode >> 7) & 31;
rlm@1 3805 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 3806 int dest = (opcode >> 12) & 15;
rlm@1 3807 int base = (opcode >> 16) & 15;
rlm@1 3808 u32 address = reg[base].I;
rlm@1 3809 CPUWriteMemory(address, reg[dest].I);
rlm@1 3810 reg[base].I = address + offset;
rlm@1 3811 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3812 }
rlm@1 3813 break;
rlm@1 3814 case 0x684:
rlm@1 3815 case 0x68c:
rlm@1 3816 // T versions are the same
rlm@1 3817 case 0x6a4:
rlm@1 3818 case 0x6ac:
rlm@1 3819 {
rlm@1 3820 // STR Rd, [Rn], Rm, ASR #
rlm@1 3821 int shift = (opcode >> 7) & 31;
rlm@1 3822 int offset;
rlm@1 3823 if (shift)
rlm@1 3824 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 3825 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 3826 offset = 0xFFFFFFFF;
rlm@1 3827 else
rlm@1 3828 offset = 0;
rlm@1 3829 int dest = (opcode >> 12) & 15;
rlm@1 3830 int base = (opcode >> 16) & 15;
rlm@1 3831 u32 address = reg[base].I;
rlm@1 3832 CPUWriteMemory(address, reg[dest].I);
rlm@1 3833 reg[base].I = address + offset;
rlm@1 3834 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3835 }
rlm@1 3836 break;
rlm@1 3837 case 0x686:
rlm@1 3838 case 0x68e:
rlm@1 3839 // T versions are the same
rlm@1 3840 case 0x6a6:
rlm@1 3841 case 0x6ae:
rlm@1 3842 {
rlm@1 3843 // STR Rd, [Rn], Rm, ROR #
rlm@1 3844 int shift = (opcode >> 7) & 31;
rlm@1 3845 u32 value = reg[opcode & 15].I;
rlm@1 3846 if (shift)
rlm@1 3847 {
rlm@1 3848 ROR_VALUE;
rlm@1 3849 }
rlm@1 3850 else
rlm@1 3851 {
rlm@1 3852 RCR_VALUE;
rlm@1 3853 }
rlm@1 3854 int dest = (opcode >> 12) & 15;
rlm@1 3855 int base = (opcode >> 16) & 15;
rlm@1 3856 u32 address = reg[base].I;
rlm@1 3857 CPUWriteMemory(address, reg[dest].I);
rlm@1 3858 reg[base].I = address + value;
rlm@1 3859 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3860 }
rlm@1 3861 break;
rlm@1 3862 case 0x700:
rlm@1 3863 case 0x708:
rlm@1 3864 {
rlm@1 3865 // STR Rd, [Rn, -Rm, LSL #]
rlm@1 3866 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 3867 int dest = (opcode >> 12) & 15;
rlm@1 3868 int base = (opcode >> 16) & 15;
rlm@1 3869 u32 address = reg[base].I - offset;
rlm@1 3870 CPUWriteMemory(address, reg[dest].I);
rlm@1 3871 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3872 }
rlm@1 3873 break;
rlm@1 3874 case 0x702:
rlm@1 3875 case 0x70a:
rlm@1 3876 {
rlm@1 3877 // STR Rd, [Rn, -Rm, LSR #]
rlm@1 3878 int shift = (opcode >> 7) & 31;
rlm@1 3879 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 3880 int dest = (opcode >> 12) & 15;
rlm@1 3881 int base = (opcode >> 16) & 15;
rlm@1 3882 u32 address = reg[base].I - offset;
rlm@1 3883 CPUWriteMemory(address, reg[dest].I);
rlm@1 3884 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3885 }
rlm@1 3886 break;
rlm@1 3887 case 0x704:
rlm@1 3888 case 0x70c:
rlm@1 3889 {
rlm@1 3890 // STR Rd, [Rn, -Rm, ASR #]
rlm@1 3891 int shift = (opcode >> 7) & 31;
rlm@1 3892 int offset;
rlm@1 3893 if (shift)
rlm@1 3894 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 3895 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 3896 offset = 0xFFFFFFFF;
rlm@1 3897 else
rlm@1 3898 offset = 0;
rlm@1 3899 int dest = (opcode >> 12) & 15;
rlm@1 3900 int base = (opcode >> 16) & 15;
rlm@1 3901 u32 address = reg[base].I - offset;
rlm@1 3902 CPUWriteMemory(address, reg[dest].I);
rlm@1 3903 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3904 }
rlm@1 3905 break;
rlm@1 3906 case 0x706:
rlm@1 3907 case 0x70e:
rlm@1 3908 {
rlm@1 3909 // STR Rd, [Rn, -Rm, ROR #]
rlm@1 3910 int shift = (opcode >> 7) & 31;
rlm@1 3911 u32 value = reg[opcode & 15].I;
rlm@1 3912 if (shift)
rlm@1 3913 {
rlm@1 3914 ROR_VALUE;
rlm@1 3915 }
rlm@1 3916 else
rlm@1 3917 {
rlm@1 3918 RCR_VALUE;
rlm@1 3919 }
rlm@1 3920 int dest = (opcode >> 12) & 15;
rlm@1 3921 int base = (opcode >> 16) & 15;
rlm@1 3922 u32 address = reg[base].I - value;
rlm@1 3923 CPUWriteMemory(address, reg[dest].I);
rlm@1 3924 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3925 }
rlm@1 3926 break;
rlm@1 3927 case 0x720:
rlm@1 3928 case 0x728:
rlm@1 3929 {
rlm@1 3930 // STR Rd, [Rn, -Rm, LSL #]!
rlm@1 3931 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 3932 int dest = (opcode >> 12) & 15;
rlm@1 3933 int base = (opcode >> 16) & 15;
rlm@1 3934 u32 address = reg[base].I - offset;
rlm@1 3935 reg[base].I = address;
rlm@1 3936 CPUWriteMemory(address, reg[dest].I);
rlm@1 3937 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3938 }
rlm@1 3939 break;
rlm@1 3940 case 0x722:
rlm@1 3941 case 0x72a:
rlm@1 3942 {
rlm@1 3943 // STR Rd, [Rn, -Rm, LSR #]!
rlm@1 3944 int shift = (opcode >> 7) & 31;
rlm@1 3945 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 3946 int dest = (opcode >> 12) & 15;
rlm@1 3947 int base = (opcode >> 16) & 15;
rlm@1 3948 u32 address = reg[base].I - offset;
rlm@1 3949 reg[base].I = address;
rlm@1 3950 CPUWriteMemory(address, reg[dest].I);
rlm@1 3951 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3952 }
rlm@1 3953 break;
rlm@1 3954 case 0x724:
rlm@1 3955 case 0x72c:
rlm@1 3956 {
rlm@1 3957 // STR Rd, [Rn, -Rm, ASR #]!
rlm@1 3958 int shift = (opcode >> 7) & 31;
rlm@1 3959 int offset;
rlm@1 3960 if (shift)
rlm@1 3961 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 3962 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 3963 offset = 0xFFFFFFFF;
rlm@1 3964 else
rlm@1 3965 offset = 0;
rlm@1 3966 int dest = (opcode >> 12) & 15;
rlm@1 3967 int base = (opcode >> 16) & 15;
rlm@1 3968 u32 address = reg[base].I - offset;
rlm@1 3969 reg[base].I = address;
rlm@1 3970 CPUWriteMemory(address, reg[dest].I);
rlm@1 3971 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3972 }
rlm@1 3973 break;
rlm@1 3974 case 0x726:
rlm@1 3975 case 0x72e:
rlm@1 3976 {
rlm@1 3977 // STR Rd, [Rn, -Rm, ROR #]!
rlm@1 3978 int shift = (opcode >> 7) & 31;
rlm@1 3979 u32 value = reg[opcode & 15].I;
rlm@1 3980 if (shift)
rlm@1 3981 {
rlm@1 3982 ROR_VALUE;
rlm@1 3983 }
rlm@1 3984 else
rlm@1 3985 {
rlm@1 3986 RCR_VALUE;
rlm@1 3987 }
rlm@1 3988 int dest = (opcode >> 12) & 15;
rlm@1 3989 int base = (opcode >> 16) & 15;
rlm@1 3990 u32 address = reg[base].I - value;
rlm@1 3991 reg[base].I = address;
rlm@1 3992 CPUWriteMemory(address, reg[dest].I);
rlm@1 3993 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 3994 }
rlm@1 3995 break;
rlm@1 3996 case 0x780:
rlm@1 3997 case 0x788:
rlm@1 3998 {
rlm@1 3999 // STR Rd, [Rn, Rm, LSL #]
rlm@1 4000 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4001 int dest = (opcode >> 12) & 15;
rlm@1 4002 int base = (opcode >> 16) & 15;
rlm@1 4003 u32 address = reg[base].I + offset;
rlm@1 4004 CPUWriteMemory(address, reg[dest].I);
rlm@1 4005 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 4006 }
rlm@1 4007 break;
rlm@1 4008 case 0x782:
rlm@1 4009 case 0x78a:
rlm@1 4010 {
rlm@1 4011 // STR Rd, [Rn, Rm, LSR #]
rlm@1 4012 int shift = (opcode >> 7) & 31;
rlm@1 4013 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4014 int dest = (opcode >> 12) & 15;
rlm@1 4015 int base = (opcode >> 16) & 15;
rlm@1 4016 u32 address = reg[base].I + offset;
rlm@1 4017 CPUWriteMemory(address, reg[dest].I);
rlm@1 4018 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 4019 }
rlm@1 4020 break;
rlm@1 4021 case 0x784:
rlm@1 4022 case 0x78c:
rlm@1 4023 {
rlm@1 4024 // STR Rd, [Rn, Rm, ASR #]
rlm@1 4025 int shift = (opcode >> 7) & 31;
rlm@1 4026 int offset;
rlm@1 4027 if (shift)
rlm@1 4028 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4029 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4030 offset = 0xFFFFFFFF;
rlm@1 4031 else
rlm@1 4032 offset = 0;
rlm@1 4033 int dest = (opcode >> 12) & 15;
rlm@1 4034 int base = (opcode >> 16) & 15;
rlm@1 4035 u32 address = reg[base].I + offset;
rlm@1 4036 CPUWriteMemory(address, reg[dest].I);
rlm@1 4037 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 4038 }
rlm@1 4039 break;
rlm@1 4040 case 0x786:
rlm@1 4041 case 0x78e:
rlm@1 4042 {
rlm@1 4043 // STR Rd, [Rn, Rm, ROR #]
rlm@1 4044 int shift = (opcode >> 7) & 31;
rlm@1 4045 u32 value = reg[opcode & 15].I;
rlm@1 4046 if (shift)
rlm@1 4047 {
rlm@1 4048 ROR_VALUE;
rlm@1 4049 }
rlm@1 4050 else
rlm@1 4051 {
rlm@1 4052 RCR_VALUE;
rlm@1 4053 }
rlm@1 4054 int dest = (opcode >> 12) & 15;
rlm@1 4055 int base = (opcode >> 16) & 15;
rlm@1 4056 u32 address = reg[base].I + value;
rlm@1 4057 CPUWriteMemory(address, reg[dest].I);
rlm@1 4058 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 4059 }
rlm@1 4060 break;
rlm@1 4061 case 0x7a0:
rlm@1 4062 case 0x7a8:
rlm@1 4063 {
rlm@1 4064 // STR Rd, [Rn, Rm, LSL #]!
rlm@1 4065 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4066 int dest = (opcode >> 12) & 15;
rlm@1 4067 int base = (opcode >> 16) & 15;
rlm@1 4068 u32 address = reg[base].I + offset;
rlm@1 4069 reg[base].I = address;
rlm@1 4070 CPUWriteMemory(address, reg[dest].I);
rlm@1 4071 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 4072 }
rlm@1 4073 break;
rlm@1 4074 case 0x7a2:
rlm@1 4075 case 0x7aa:
rlm@1 4076 {
rlm@1 4077 // STR Rd, [Rn, Rm, LSR #]!
rlm@1 4078 int shift = (opcode >> 7) & 31;
rlm@1 4079 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4080 int dest = (opcode >> 12) & 15;
rlm@1 4081 int base = (opcode >> 16) & 15;
rlm@1 4082 u32 address = reg[base].I + offset;
rlm@1 4083 reg[base].I = address;
rlm@1 4084 CPUWriteMemory(address, reg[dest].I);
rlm@1 4085 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 4086 }
rlm@1 4087 break;
rlm@1 4088 case 0x7a4:
rlm@1 4089 case 0x7ac:
rlm@1 4090 {
rlm@1 4091 // STR Rd, [Rn, Rm, ASR #]!
rlm@1 4092 int shift = (opcode >> 7) & 31;
rlm@1 4093 int offset;
rlm@1 4094 if (shift)
rlm@1 4095 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4096 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4097 offset = 0xFFFFFFFF;
rlm@1 4098 else
rlm@1 4099 offset = 0;
rlm@1 4100 int dest = (opcode >> 12) & 15;
rlm@1 4101 int base = (opcode >> 16) & 15;
rlm@1 4102 u32 address = reg[base].I + offset;
rlm@1 4103 reg[base].I = address;
rlm@1 4104 CPUWriteMemory(address, reg[dest].I);
rlm@1 4105 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 4106 }
rlm@1 4107 break;
rlm@1 4108 case 0x7a6:
rlm@1 4109 case 0x7ae:
rlm@1 4110 {
rlm@1 4111 // STR Rd, [Rn, Rm, ROR #]!
rlm@1 4112 int shift = (opcode >> 7) & 31;
rlm@1 4113 u32 value = reg[opcode & 15].I;
rlm@1 4114 if (shift)
rlm@1 4115 {
rlm@1 4116 ROR_VALUE;
rlm@1 4117 }
rlm@1 4118 else
rlm@1 4119 {
rlm@1 4120 RCR_VALUE;
rlm@1 4121 }
rlm@1 4122 int dest = (opcode >> 12) & 15;
rlm@1 4123 int base = (opcode >> 16) & 15;
rlm@1 4124 u32 address = reg[base].I + value;
rlm@1 4125 reg[base].I = address;
rlm@1 4126 CPUWriteMemory(address, reg[dest].I);
rlm@1 4127 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 4128 }
rlm@1 4129 break;
rlm@1 4130 case 0x610:
rlm@1 4131 case 0x618:
rlm@1 4132 // T versions are the same
rlm@1 4133 case 0x630:
rlm@1 4134 case 0x638:
rlm@1 4135 {
rlm@1 4136 // LDR Rd, [Rn], -Rm, LSL #
rlm@1 4137 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4138 int dest = (opcode >> 12) & 15;
rlm@1 4139 int base = (opcode >> 16) & 15;
rlm@1 4140 u32 address = reg[base].I;
rlm@1 4141 reg[dest].I = CPUReadMemory(address);
rlm@1 4142 if (dest != base)
rlm@1 4143 reg[base].I = address - offset;
rlm@1 4144 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4145 if (dest == 15)
rlm@1 4146 {
rlm@1 4147 clockTicks += 2;
rlm@1 4148 reg[15].I &= 0xFFFFFFFC;
rlm@1 4149 armNextPC = reg[15].I;
rlm@1 4150 reg[15].I += 4;
rlm@1 4151 }
rlm@1 4152 }
rlm@1 4153 break;
rlm@1 4154 case 0x612:
rlm@1 4155 case 0x61a:
rlm@1 4156 // T versions are the same
rlm@1 4157 case 0x632:
rlm@1 4158 case 0x63a:
rlm@1 4159 {
rlm@1 4160 // LDR Rd, [Rn], -Rm, LSR #
rlm@1 4161 int shift = (opcode >> 7) & 31;
rlm@1 4162 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4163 int dest = (opcode >> 12) & 15;
rlm@1 4164 int base = (opcode >> 16) & 15;
rlm@1 4165 u32 address = reg[base].I;
rlm@1 4166 reg[dest].I = CPUReadMemory(address);
rlm@1 4167 if (dest != base)
rlm@1 4168 reg[base].I = address - offset;
rlm@1 4169 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4170 if (dest == 15)
rlm@1 4171 {
rlm@1 4172 clockTicks += 2;
rlm@1 4173 reg[15].I &= 0xFFFFFFFC;
rlm@1 4174 armNextPC = reg[15].I;
rlm@1 4175 reg[15].I += 4;
rlm@1 4176 }
rlm@1 4177 }
rlm@1 4178 break;
rlm@1 4179 case 0x614:
rlm@1 4180 case 0x61c:
rlm@1 4181 // T versions are the same
rlm@1 4182 case 0x634:
rlm@1 4183 case 0x63c:
rlm@1 4184 {
rlm@1 4185 // LDR Rd, [Rn], -Rm, ASR #
rlm@1 4186 int shift = (opcode >> 7) & 31;
rlm@1 4187 int offset;
rlm@1 4188 if (shift)
rlm@1 4189 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4190 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4191 offset = 0xFFFFFFFF;
rlm@1 4192 else
rlm@1 4193 offset = 0;
rlm@1 4194 int dest = (opcode >> 12) & 15;
rlm@1 4195 int base = (opcode >> 16) & 15;
rlm@1 4196 u32 address = reg[base].I;
rlm@1 4197 reg[dest].I = CPUReadMemory(address);
rlm@1 4198 if (dest != base)
rlm@1 4199 reg[base].I = address - offset;
rlm@1 4200 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4201 if (dest == 15)
rlm@1 4202 {
rlm@1 4203 clockTicks += 2;
rlm@1 4204 reg[15].I &= 0xFFFFFFFC;
rlm@1 4205 armNextPC = reg[15].I;
rlm@1 4206 reg[15].I += 4;
rlm@1 4207 }
rlm@1 4208 }
rlm@1 4209 break;
rlm@1 4210 case 0x616:
rlm@1 4211 case 0x61e:
rlm@1 4212 // T versions are the same
rlm@1 4213 case 0x636:
rlm@1 4214 case 0x63e:
rlm@1 4215 {
rlm@1 4216 // LDR Rd, [Rn], -Rm, ROR #
rlm@1 4217 int shift = (opcode >> 7) & 31;
rlm@1 4218 u32 value = reg[opcode & 15].I;
rlm@1 4219 if (shift)
rlm@1 4220 {
rlm@1 4221 ROR_VALUE;
rlm@1 4222 }
rlm@1 4223 else
rlm@1 4224 {
rlm@1 4225 RCR_VALUE;
rlm@1 4226 }
rlm@1 4227 int dest = (opcode >> 12) & 15;
rlm@1 4228 int base = (opcode >> 16) & 15;
rlm@1 4229 u32 address = reg[base].I;
rlm@1 4230 reg[dest].I = CPUReadMemory(address);
rlm@1 4231 if (dest != base)
rlm@1 4232 reg[base].I = address - value;
rlm@1 4233 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4234 if (dest == 15)
rlm@1 4235 {
rlm@1 4236 clockTicks += 2;
rlm@1 4237 reg[15].I &= 0xFFFFFFFC;
rlm@1 4238 armNextPC = reg[15].I;
rlm@1 4239 reg[15].I += 4;
rlm@1 4240 }
rlm@1 4241 }
rlm@1 4242 break;
rlm@1 4243 case 0x690:
rlm@1 4244 case 0x698:
rlm@1 4245 // T versions are the same
rlm@1 4246 case 0x6b0:
rlm@1 4247 case 0x6b8:
rlm@1 4248 {
rlm@1 4249 // LDR Rd, [Rn], Rm, LSL #
rlm@1 4250 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4251 int dest = (opcode >> 12) & 15;
rlm@1 4252 int base = (opcode >> 16) & 15;
rlm@1 4253 u32 address = reg[base].I;
rlm@1 4254 reg[dest].I = CPUReadMemory(address);
rlm@1 4255 if (dest != base)
rlm@1 4256 reg[base].I = address + offset;
rlm@1 4257 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4258 if (dest == 15)
rlm@1 4259 {
rlm@1 4260 clockTicks += 2;
rlm@1 4261 reg[15].I &= 0xFFFFFFFC;
rlm@1 4262 armNextPC = reg[15].I;
rlm@1 4263 reg[15].I += 4;
rlm@1 4264 }
rlm@1 4265 }
rlm@1 4266 break;
rlm@1 4267 case 0x692:
rlm@1 4268 case 0x69a:
rlm@1 4269 // T versions are the same
rlm@1 4270 case 0x6b2:
rlm@1 4271 case 0x6ba:
rlm@1 4272 {
rlm@1 4273 // LDR Rd, [Rn], Rm, LSR #
rlm@1 4274 int shift = (opcode >> 7) & 31;
rlm@1 4275 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4276 int dest = (opcode >> 12) & 15;
rlm@1 4277 int base = (opcode >> 16) & 15;
rlm@1 4278 u32 address = reg[base].I;
rlm@1 4279 reg[dest].I = CPUReadMemory(address);
rlm@1 4280 if (dest != base)
rlm@1 4281 reg[base].I = address + offset;
rlm@1 4282 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4283 if (dest == 15)
rlm@1 4284 {
rlm@1 4285 clockTicks += 2;
rlm@1 4286 reg[15].I &= 0xFFFFFFFC;
rlm@1 4287 armNextPC = reg[15].I;
rlm@1 4288 reg[15].I += 4;
rlm@1 4289 }
rlm@1 4290 }
rlm@1 4291 break;
rlm@1 4292 case 0x694:
rlm@1 4293 case 0x69c:
rlm@1 4294 // T versions are the same
rlm@1 4295 case 0x6b4:
rlm@1 4296 case 0x6bc:
rlm@1 4297 {
rlm@1 4298 // LDR Rd, [Rn], Rm, ASR #
rlm@1 4299 int shift = (opcode >> 7) & 31;
rlm@1 4300 int offset;
rlm@1 4301 if (shift)
rlm@1 4302 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4303 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4304 offset = 0xFFFFFFFF;
rlm@1 4305 else
rlm@1 4306 offset = 0;
rlm@1 4307 int dest = (opcode >> 12) & 15;
rlm@1 4308 int base = (opcode >> 16) & 15;
rlm@1 4309 u32 address = reg[base].I;
rlm@1 4310 reg[dest].I = CPUReadMemory(address);
rlm@1 4311 if (dest != base)
rlm@1 4312 reg[base].I = address + offset;
rlm@1 4313 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4314 if (dest == 15)
rlm@1 4315 {
rlm@1 4316 clockTicks += 2;
rlm@1 4317 reg[15].I &= 0xFFFFFFFC;
rlm@1 4318 armNextPC = reg[15].I;
rlm@1 4319 reg[15].I += 4;
rlm@1 4320 }
rlm@1 4321 }
rlm@1 4322 break;
rlm@1 4323 case 0x696:
rlm@1 4324 case 0x69e:
rlm@1 4325 // T versions are the same
rlm@1 4326 case 0x6b6:
rlm@1 4327 case 0x6be:
rlm@1 4328 {
rlm@1 4329 // LDR Rd, [Rn], Rm, ROR #
rlm@1 4330 int shift = (opcode >> 7) & 31;
rlm@1 4331 u32 value = reg[opcode & 15].I;
rlm@1 4332 if (shift)
rlm@1 4333 {
rlm@1 4334 ROR_VALUE;
rlm@1 4335 }
rlm@1 4336 else
rlm@1 4337 {
rlm@1 4338 RCR_VALUE;
rlm@1 4339 }
rlm@1 4340 int dest = (opcode >> 12) & 15;
rlm@1 4341 int base = (opcode >> 16) & 15;
rlm@1 4342 u32 address = reg[base].I;
rlm@1 4343 reg[dest].I = CPUReadMemory(address);
rlm@1 4344 if (dest != base)
rlm@1 4345 reg[base].I = address + value;
rlm@1 4346 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4347 if (dest == 15)
rlm@1 4348 {
rlm@1 4349 clockTicks += 2;
rlm@1 4350 reg[15].I &= 0xFFFFFFFC;
rlm@1 4351 armNextPC = reg[15].I;
rlm@1 4352 reg[15].I += 4;
rlm@1 4353 }
rlm@1 4354 }
rlm@1 4355 break;
rlm@1 4356 case 0x710:
rlm@1 4357 case 0x718:
rlm@1 4358 {
rlm@1 4359 // LDR Rd, [Rn, -Rm, LSL #]
rlm@1 4360 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4361 int dest = (opcode >> 12) & 15;
rlm@1 4362 int base = (opcode >> 16) & 15;
rlm@1 4363 u32 address = reg[base].I - offset;
rlm@1 4364 reg[dest].I = CPUReadMemory(address);
rlm@1 4365 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4366 if (dest == 15)
rlm@1 4367 {
rlm@1 4368 clockTicks += 2;
rlm@1 4369 reg[15].I &= 0xFFFFFFFC;
rlm@1 4370 armNextPC = reg[15].I;
rlm@1 4371 reg[15].I += 4;
rlm@1 4372 }
rlm@1 4373 }
rlm@1 4374 break;
rlm@1 4375 case 0x712:
rlm@1 4376 case 0x71a:
rlm@1 4377 {
rlm@1 4378 // LDR Rd, [Rn, -Rm, LSR #]
rlm@1 4379 int shift = (opcode >> 7) & 31;
rlm@1 4380 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4381 int dest = (opcode >> 12) & 15;
rlm@1 4382 int base = (opcode >> 16) & 15;
rlm@1 4383 u32 address = reg[base].I - offset;
rlm@1 4384 reg[dest].I = CPUReadMemory(address);
rlm@1 4385 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4386 if (dest == 15)
rlm@1 4387 {
rlm@1 4388 clockTicks += 2;
rlm@1 4389 reg[15].I &= 0xFFFFFFFC;
rlm@1 4390 armNextPC = reg[15].I;
rlm@1 4391 reg[15].I += 4;
rlm@1 4392 }
rlm@1 4393 }
rlm@1 4394 break;
rlm@1 4395 case 0x714:
rlm@1 4396 case 0x71c:
rlm@1 4397 {
rlm@1 4398 // LDR Rd, [Rn, -Rm, ASR #]
rlm@1 4399 int shift = (opcode >> 7) & 31;
rlm@1 4400 int offset;
rlm@1 4401 if (shift)
rlm@1 4402 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4403 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4404 offset = 0xFFFFFFFF;
rlm@1 4405 else
rlm@1 4406 offset = 0;
rlm@1 4407 int dest = (opcode >> 12) & 15;
rlm@1 4408 int base = (opcode >> 16) & 15;
rlm@1 4409 u32 address = reg[base].I - offset;
rlm@1 4410 reg[dest].I = CPUReadMemory(address);
rlm@1 4411 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4412 if (dest == 15)
rlm@1 4413 {
rlm@1 4414 clockTicks += 2;
rlm@1 4415 reg[15].I &= 0xFFFFFFFC;
rlm@1 4416 armNextPC = reg[15].I;
rlm@1 4417 reg[15].I += 4;
rlm@1 4418 }
rlm@1 4419 }
rlm@1 4420 break;
rlm@1 4421 case 0x716:
rlm@1 4422 case 0x71e:
rlm@1 4423 {
rlm@1 4424 // LDR Rd, [Rn, -Rm, ROR #]
rlm@1 4425 int shift = (opcode >> 7) & 31;
rlm@1 4426 u32 value = reg[opcode & 15].I;
rlm@1 4427 if (shift)
rlm@1 4428 {
rlm@1 4429 ROR_VALUE;
rlm@1 4430 }
rlm@1 4431 else
rlm@1 4432 {
rlm@1 4433 RCR_VALUE;
rlm@1 4434 }
rlm@1 4435 int dest = (opcode >> 12) & 15;
rlm@1 4436 int base = (opcode >> 16) & 15;
rlm@1 4437 u32 address = reg[base].I - value;
rlm@1 4438 reg[dest].I = CPUReadMemory(address);
rlm@1 4439 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4440 if (dest == 15)
rlm@1 4441 {
rlm@1 4442 clockTicks += 2;
rlm@1 4443 reg[15].I &= 0xFFFFFFFC;
rlm@1 4444 armNextPC = reg[15].I;
rlm@1 4445 reg[15].I += 4;
rlm@1 4446 }
rlm@1 4447 }
rlm@1 4448 break;
rlm@1 4449 case 0x730:
rlm@1 4450 case 0x738:
rlm@1 4451 {
rlm@1 4452 // LDR Rd, [Rn, -Rm, LSL #]!
rlm@1 4453 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4454 int dest = (opcode >> 12) & 15;
rlm@1 4455 int base = (opcode >> 16) & 15;
rlm@1 4456 u32 address = reg[base].I - offset;
rlm@1 4457 reg[dest].I = CPUReadMemory(address);
rlm@1 4458 if (dest != base)
rlm@1 4459 reg[base].I = address;
rlm@1 4460 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4461 if (dest == 15)
rlm@1 4462 {
rlm@1 4463 clockTicks += 2;
rlm@1 4464 reg[15].I &= 0xFFFFFFFC;
rlm@1 4465 armNextPC = reg[15].I;
rlm@1 4466 reg[15].I += 4;
rlm@1 4467 }
rlm@1 4468 }
rlm@1 4469 break;
rlm@1 4470 case 0x732:
rlm@1 4471 case 0x73a:
rlm@1 4472 {
rlm@1 4473 // LDR Rd, [Rn, -Rm, LSR #]!
rlm@1 4474 int shift = (opcode >> 7) & 31;
rlm@1 4475 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4476 int dest = (opcode >> 12) & 15;
rlm@1 4477 int base = (opcode >> 16) & 15;
rlm@1 4478 u32 address = reg[base].I - offset;
rlm@1 4479 reg[dest].I = CPUReadMemory(address);
rlm@1 4480 if (dest != base)
rlm@1 4481 reg[base].I = address;
rlm@1 4482 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4483 if (dest == 15)
rlm@1 4484 {
rlm@1 4485 clockTicks += 2;
rlm@1 4486 reg[15].I &= 0xFFFFFFFC;
rlm@1 4487 armNextPC = reg[15].I;
rlm@1 4488 reg[15].I += 4;
rlm@1 4489 }
rlm@1 4490 }
rlm@1 4491 break;
rlm@1 4492 case 0x734:
rlm@1 4493 case 0x73c:
rlm@1 4494 {
rlm@1 4495 // LDR Rd, [Rn, -Rm, ASR #]!
rlm@1 4496 int shift = (opcode >> 7) & 31;
rlm@1 4497 int offset;
rlm@1 4498 if (shift)
rlm@1 4499 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4500 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4501 offset = 0xFFFFFFFF;
rlm@1 4502 else
rlm@1 4503 offset = 0;
rlm@1 4504 int dest = (opcode >> 12) & 15;
rlm@1 4505 int base = (opcode >> 16) & 15;
rlm@1 4506 u32 address = reg[base].I - offset;
rlm@1 4507 reg[dest].I = CPUReadMemory(address);
rlm@1 4508 if (dest != base)
rlm@1 4509 reg[base].I = address;
rlm@1 4510 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4511 if (dest == 15)
rlm@1 4512 {
rlm@1 4513 clockTicks += 2;
rlm@1 4514 reg[15].I &= 0xFFFFFFFC;
rlm@1 4515 armNextPC = reg[15].I;
rlm@1 4516 reg[15].I += 4;
rlm@1 4517 }
rlm@1 4518 }
rlm@1 4519 break;
rlm@1 4520 case 0x736:
rlm@1 4521 case 0x73e:
rlm@1 4522 {
rlm@1 4523 // LDR Rd, [Rn, -Rm, ROR #]!
rlm@1 4524 int shift = (opcode >> 7) & 31;
rlm@1 4525 u32 value = reg[opcode & 15].I;
rlm@1 4526 if (shift)
rlm@1 4527 {
rlm@1 4528 ROR_VALUE;
rlm@1 4529 }
rlm@1 4530 else
rlm@1 4531 {
rlm@1 4532 RCR_VALUE;
rlm@1 4533 }
rlm@1 4534 int dest = (opcode >> 12) & 15;
rlm@1 4535 int base = (opcode >> 16) & 15;
rlm@1 4536 u32 address = reg[base].I - value;
rlm@1 4537 reg[dest].I = CPUReadMemory(address);
rlm@1 4538 if (dest != base)
rlm@1 4539 reg[base].I = address;
rlm@1 4540 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4541 if (dest == 15)
rlm@1 4542 {
rlm@1 4543 clockTicks += 2;
rlm@1 4544 reg[15].I &= 0xFFFFFFFC;
rlm@1 4545 armNextPC = reg[15].I;
rlm@1 4546 reg[15].I += 4;
rlm@1 4547 }
rlm@1 4548 }
rlm@1 4549 break;
rlm@1 4550 case 0x790:
rlm@1 4551 case 0x798:
rlm@1 4552 {
rlm@1 4553 // LDR Rd, [Rn, Rm, LSL #]
rlm@1 4554 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4555 int dest = (opcode >> 12) & 15;
rlm@1 4556 int base = (opcode >> 16) & 15;
rlm@1 4557 u32 address = reg[base].I + offset;
rlm@1 4558 reg[dest].I = CPUReadMemory(address);
rlm@1 4559 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4560 if (dest == 15)
rlm@1 4561 {
rlm@1 4562 clockTicks += 2;
rlm@1 4563 reg[15].I &= 0xFFFFFFFC;
rlm@1 4564 armNextPC = reg[15].I;
rlm@1 4565 reg[15].I += 4;
rlm@1 4566 }
rlm@1 4567 }
rlm@1 4568 break;
rlm@1 4569 case 0x792:
rlm@1 4570 case 0x79a:
rlm@1 4571 {
rlm@1 4572 // LDR Rd, [Rn, Rm, LSR #]
rlm@1 4573 int shift = (opcode >> 7) & 31;
rlm@1 4574 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4575 int dest = (opcode >> 12) & 15;
rlm@1 4576 int base = (opcode >> 16) & 15;
rlm@1 4577 u32 address = reg[base].I + offset;
rlm@1 4578 reg[dest].I = CPUReadMemory(address);
rlm@1 4579 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4580 if (dest == 15)
rlm@1 4581 {
rlm@1 4582 clockTicks += 2;
rlm@1 4583 reg[15].I &= 0xFFFFFFFC;
rlm@1 4584 armNextPC = reg[15].I;
rlm@1 4585 reg[15].I += 4;
rlm@1 4586 }
rlm@1 4587 }
rlm@1 4588 break;
rlm@1 4589 case 0x794:
rlm@1 4590 case 0x79c:
rlm@1 4591 {
rlm@1 4592 // LDR Rd, [Rn, Rm, ASR #]
rlm@1 4593 int shift = (opcode >> 7) & 31;
rlm@1 4594 int offset;
rlm@1 4595 if (shift)
rlm@1 4596 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4597 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4598 offset = 0xFFFFFFFF;
rlm@1 4599 else
rlm@1 4600 offset = 0;
rlm@1 4601 int dest = (opcode >> 12) & 15;
rlm@1 4602 int base = (opcode >> 16) & 15;
rlm@1 4603 u32 address = reg[base].I + offset;
rlm@1 4604 reg[dest].I = CPUReadMemory(address);
rlm@1 4605 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4606 if (dest == 15)
rlm@1 4607 {
rlm@1 4608 clockTicks += 2;
rlm@1 4609 reg[15].I &= 0xFFFFFFFC;
rlm@1 4610 armNextPC = reg[15].I;
rlm@1 4611 reg[15].I += 4;
rlm@1 4612 }
rlm@1 4613 }
rlm@1 4614 break;
rlm@1 4615 case 0x796:
rlm@1 4616 case 0x79e:
rlm@1 4617 {
rlm@1 4618 // LDR Rd, [Rn, Rm, ROR #]
rlm@1 4619 int shift = (opcode >> 7) & 31;
rlm@1 4620 u32 value = reg[opcode & 15].I;
rlm@1 4621 if (shift)
rlm@1 4622 {
rlm@1 4623 ROR_VALUE;
rlm@1 4624 }
rlm@1 4625 else
rlm@1 4626 {
rlm@1 4627 RCR_VALUE;
rlm@1 4628 }
rlm@1 4629 int dest = (opcode >> 12) & 15;
rlm@1 4630 int base = (opcode >> 16) & 15;
rlm@1 4631 u32 address = reg[base].I + value;
rlm@1 4632 reg[dest].I = CPUReadMemory(address);
rlm@1 4633 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4634 if (dest == 15)
rlm@1 4635 {
rlm@1 4636 clockTicks += 2;
rlm@1 4637 reg[15].I &= 0xFFFFFFFC;
rlm@1 4638 armNextPC = reg[15].I;
rlm@1 4639 reg[15].I += 4;
rlm@1 4640 }
rlm@1 4641 }
rlm@1 4642 break;
rlm@1 4643 case 0x7b0:
rlm@1 4644 case 0x7b8:
rlm@1 4645 {
rlm@1 4646 // LDR Rd, [Rn, Rm, LSL #]!
rlm@1 4647 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4648 int dest = (opcode >> 12) & 15;
rlm@1 4649 int base = (opcode >> 16) & 15;
rlm@1 4650 u32 address = reg[base].I + offset;
rlm@1 4651 reg[dest].I = CPUReadMemory(address);
rlm@1 4652 if (dest != base)
rlm@1 4653 reg[base].I = address;
rlm@1 4654 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4655 if (dest == 15)
rlm@1 4656 {
rlm@1 4657 clockTicks += 2;
rlm@1 4658 reg[15].I &= 0xFFFFFFFC;
rlm@1 4659 armNextPC = reg[15].I;
rlm@1 4660 reg[15].I += 4;
rlm@1 4661 }
rlm@1 4662 }
rlm@1 4663 break;
rlm@1 4664 case 0x7b2:
rlm@1 4665 case 0x7ba:
rlm@1 4666 {
rlm@1 4667 // LDR Rd, [Rn, Rm, LSR #]!
rlm@1 4668 int shift = (opcode >> 7) & 31;
rlm@1 4669 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4670 int dest = (opcode >> 12) & 15;
rlm@1 4671 int base = (opcode >> 16) & 15;
rlm@1 4672 u32 address = reg[base].I + offset;
rlm@1 4673 reg[dest].I = CPUReadMemory(address);
rlm@1 4674 if (dest != base)
rlm@1 4675 reg[base].I = address;
rlm@1 4676 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4677 if (dest == 15)
rlm@1 4678 {
rlm@1 4679 clockTicks += 2;
rlm@1 4680 reg[15].I &= 0xFFFFFFFC;
rlm@1 4681 armNextPC = reg[15].I;
rlm@1 4682 reg[15].I += 4;
rlm@1 4683 }
rlm@1 4684 }
rlm@1 4685 break;
rlm@1 4686 case 0x7b4:
rlm@1 4687 case 0x7bc:
rlm@1 4688 {
rlm@1 4689 // LDR Rd, [Rn, Rm, ASR #]!
rlm@1 4690 int shift = (opcode >> 7) & 31;
rlm@1 4691 int offset;
rlm@1 4692 if (shift)
rlm@1 4693 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4694 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4695 offset = 0xFFFFFFFF;
rlm@1 4696 else
rlm@1 4697 offset = 0;
rlm@1 4698 int dest = (opcode >> 12) & 15;
rlm@1 4699 int base = (opcode >> 16) & 15;
rlm@1 4700 u32 address = reg[base].I + offset;
rlm@1 4701 reg[dest].I = CPUReadMemory(address);
rlm@1 4702 if (dest != base)
rlm@1 4703 reg[base].I = address;
rlm@1 4704 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4705 if (dest == 15)
rlm@1 4706 {
rlm@1 4707 clockTicks += 2;
rlm@1 4708 reg[15].I &= 0xFFFFFFFC;
rlm@1 4709 armNextPC = reg[15].I;
rlm@1 4710 reg[15].I += 4;
rlm@1 4711 }
rlm@1 4712 }
rlm@1 4713 break;
rlm@1 4714 case 0x7b6:
rlm@1 4715 case 0x7be:
rlm@1 4716 {
rlm@1 4717 // LDR Rd, [Rn, Rm, ROR #]!
rlm@1 4718 int shift = (opcode >> 7) & 31;
rlm@1 4719 u32 value = reg[opcode & 15].I;
rlm@1 4720 if (shift)
rlm@1 4721 {
rlm@1 4722 ROR_VALUE;
rlm@1 4723 }
rlm@1 4724 else
rlm@1 4725 {
rlm@1 4726 RCR_VALUE;
rlm@1 4727 }
rlm@1 4728 int dest = (opcode >> 12) & 15;
rlm@1 4729 int base = (opcode >> 16) & 15;
rlm@1 4730 u32 address = reg[base].I + value;
rlm@1 4731 reg[dest].I = CPUReadMemory(address);
rlm@1 4732 if (dest != base)
rlm@1 4733 reg[base].I = address;
rlm@1 4734 clockTicks += 3 + CPUUpdateTicksAccess32(address);
rlm@1 4735 if (dest == 15)
rlm@1 4736 {
rlm@1 4737 clockTicks += 2;
rlm@1 4738 reg[15].I &= 0xFFFFFFFC;
rlm@1 4739 armNextPC = reg[15].I;
rlm@1 4740 reg[15].I += 4;
rlm@1 4741 }
rlm@1 4742 }
rlm@1 4743 break;
rlm@1 4744 case 0x640:
rlm@1 4745 case 0x648:
rlm@1 4746 // T versions are the same
rlm@1 4747 case 0x660:
rlm@1 4748 case 0x668:
rlm@1 4749 {
rlm@1 4750 // STRB Rd, [Rn], -Rm, LSL #
rlm@1 4751 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4752 int dest = (opcode >> 12) & 15;
rlm@1 4753 int base = (opcode >> 16) & 15;
rlm@1 4754 u32 address = reg[base].I;
rlm@1 4755 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4756 reg[base].I = address - offset;
rlm@1 4757 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4758 }
rlm@1 4759 break;
rlm@1 4760 case 0x642:
rlm@1 4761 case 0x64a:
rlm@1 4762 // T versions are the same
rlm@1 4763 case 0x662:
rlm@1 4764 case 0x66a:
rlm@1 4765 {
rlm@1 4766 // STRB Rd, [Rn], -Rm, LSR #
rlm@1 4767 int shift = (opcode >> 7) & 31;
rlm@1 4768 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4769 int dest = (opcode >> 12) & 15;
rlm@1 4770 int base = (opcode >> 16) & 15;
rlm@1 4771 u32 address = reg[base].I;
rlm@1 4772 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4773 reg[base].I = address - offset;
rlm@1 4774 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4775 }
rlm@1 4776 break;
rlm@1 4777 case 0x644:
rlm@1 4778 case 0x64c:
rlm@1 4779 // T versions are the same
rlm@1 4780 case 0x664:
rlm@1 4781 case 0x66c:
rlm@1 4782 {
rlm@1 4783 // STRB Rd, [Rn], -Rm, ASR #
rlm@1 4784 int shift = (opcode >> 7) & 31;
rlm@1 4785 int offset;
rlm@1 4786 if (shift)
rlm@1 4787 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4788 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4789 offset = 0xFFFFFFFF;
rlm@1 4790 else
rlm@1 4791 offset = 0;
rlm@1 4792 int dest = (opcode >> 12) & 15;
rlm@1 4793 int base = (opcode >> 16) & 15;
rlm@1 4794 u32 address = reg[base].I;
rlm@1 4795 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4796 reg[base].I = address - offset;
rlm@1 4797 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4798 }
rlm@1 4799 break;
rlm@1 4800 case 0x646:
rlm@1 4801 case 0x64e:
rlm@1 4802 // T versions are the same
rlm@1 4803 case 0x666:
rlm@1 4804 case 0x66e:
rlm@1 4805 {
rlm@1 4806 // STRB Rd, [Rn], -Rm, ROR #
rlm@1 4807 int shift = (opcode >> 7) & 31;
rlm@1 4808 u32 value = reg[opcode & 15].I;
rlm@1 4809 if (shift)
rlm@1 4810 {
rlm@1 4811 ROR_VALUE;
rlm@1 4812 }
rlm@1 4813 else
rlm@1 4814 {
rlm@1 4815 RCR_VALUE;
rlm@1 4816 }
rlm@1 4817 int dest = (opcode >> 12) & 15;
rlm@1 4818 int base = (opcode >> 16) & 15;
rlm@1 4819 u32 address = reg[base].I;
rlm@1 4820 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4821 reg[base].I = address - value;
rlm@1 4822 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4823 }
rlm@1 4824 break;
rlm@1 4825 case 0x6c0:
rlm@1 4826 case 0x6c8:
rlm@1 4827 // T versions are the same
rlm@1 4828 case 0x6e0:
rlm@1 4829 case 0x6e8:
rlm@1 4830 {
rlm@1 4831 // STRB Rd, [Rn], Rm, LSL #
rlm@1 4832 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4833 int dest = (opcode >> 12) & 15;
rlm@1 4834 int base = (opcode >> 16) & 15;
rlm@1 4835 u32 address = reg[base].I;
rlm@1 4836 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4837 reg[base].I = address + offset;
rlm@1 4838 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4839 }
rlm@1 4840 break;
rlm@1 4841 case 0x6c2:
rlm@1 4842 case 0x6ca:
rlm@1 4843 // T versions are the same
rlm@1 4844 case 0x6e2:
rlm@1 4845 case 0x6ea:
rlm@1 4846 {
rlm@1 4847 // STRB Rd, [Rn], Rm, LSR #
rlm@1 4848 int shift = (opcode >> 7) & 31;
rlm@1 4849 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4850 int dest = (opcode >> 12) & 15;
rlm@1 4851 int base = (opcode >> 16) & 15;
rlm@1 4852 u32 address = reg[base].I;
rlm@1 4853 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4854 reg[base].I = address + offset;
rlm@1 4855 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4856 }
rlm@1 4857 break;
rlm@1 4858 case 0x6c4:
rlm@1 4859 case 0x6cc:
rlm@1 4860 // T versions are the same
rlm@1 4861 case 0x6e4:
rlm@1 4862 case 0x6ec:
rlm@1 4863 {
rlm@1 4864 // STR Rd, [Rn], Rm, ASR #
rlm@1 4865 int shift = (opcode >> 7) & 31;
rlm@1 4866 int offset;
rlm@1 4867 if (shift)
rlm@1 4868 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4869 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4870 offset = 0xFFFFFFFF;
rlm@1 4871 else
rlm@1 4872 offset = 0;
rlm@1 4873 int dest = (opcode >> 12) & 15;
rlm@1 4874 int base = (opcode >> 16) & 15;
rlm@1 4875 u32 address = reg[base].I;
rlm@1 4876 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4877 reg[base].I = address + offset;
rlm@1 4878 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4879 }
rlm@1 4880 break;
rlm@1 4881 case 0x6c6:
rlm@1 4882 case 0x6ce:
rlm@1 4883 // T versions are the same
rlm@1 4884 case 0x6e6:
rlm@1 4885 case 0x6ee:
rlm@1 4886 {
rlm@1 4887 // STRB Rd, [Rn], Rm, ROR #
rlm@1 4888 int shift = (opcode >> 7) & 31;
rlm@1 4889 u32 value = reg[opcode & 15].I;
rlm@1 4890 if (shift)
rlm@1 4891 {
rlm@1 4892 ROR_VALUE;
rlm@1 4893 }
rlm@1 4894 else
rlm@1 4895 {
rlm@1 4896 RCR_VALUE;
rlm@1 4897 }
rlm@1 4898 int dest = (opcode >> 12) & 15;
rlm@1 4899 int base = (opcode >> 16) & 15;
rlm@1 4900 u32 address = reg[base].I;
rlm@1 4901 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4902 reg[base].I = address + value;
rlm@1 4903 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4904 }
rlm@1 4905 break;
rlm@1 4906 case 0x740:
rlm@1 4907 case 0x748:
rlm@1 4908 {
rlm@1 4909 // STRB Rd, [Rn, -Rm, LSL #]
rlm@1 4910 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4911 int dest = (opcode >> 12) & 15;
rlm@1 4912 int base = (opcode >> 16) & 15;
rlm@1 4913 u32 address = reg[base].I - offset;
rlm@1 4914 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4915 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4916 }
rlm@1 4917 break;
rlm@1 4918 case 0x742:
rlm@1 4919 case 0x74a:
rlm@1 4920 {
rlm@1 4921 // STRB Rd, [Rn, -Rm, LSR #]
rlm@1 4922 int shift = (opcode >> 7) & 31;
rlm@1 4923 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4924 int dest = (opcode >> 12) & 15;
rlm@1 4925 int base = (opcode >> 16) & 15;
rlm@1 4926 u32 address = reg[base].I - offset;
rlm@1 4927 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4928 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4929 }
rlm@1 4930 break;
rlm@1 4931 case 0x744:
rlm@1 4932 case 0x74c:
rlm@1 4933 {
rlm@1 4934 // STRB Rd, [Rn, -Rm, ASR #]
rlm@1 4935 int shift = (opcode >> 7) & 31;
rlm@1 4936 int offset;
rlm@1 4937 if (shift)
rlm@1 4938 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 4939 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 4940 offset = 0xFFFFFFFF;
rlm@1 4941 else
rlm@1 4942 offset = 0;
rlm@1 4943 int dest = (opcode >> 12) & 15;
rlm@1 4944 int base = (opcode >> 16) & 15;
rlm@1 4945 u32 address = reg[base].I - offset;
rlm@1 4946 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4947 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4948 }
rlm@1 4949 break;
rlm@1 4950 case 0x746:
rlm@1 4951 case 0x74e:
rlm@1 4952 {
rlm@1 4953 // STRB Rd, [Rn, -Rm, ROR #]
rlm@1 4954 int shift = (opcode >> 7) & 31;
rlm@1 4955 u32 value = reg[opcode & 15].I;
rlm@1 4956 if (shift)
rlm@1 4957 {
rlm@1 4958 ROR_VALUE;
rlm@1 4959 }
rlm@1 4960 else
rlm@1 4961 {
rlm@1 4962 RCR_VALUE;
rlm@1 4963 }
rlm@1 4964 int dest = (opcode >> 12) & 15;
rlm@1 4965 int base = (opcode >> 16) & 15;
rlm@1 4966 u32 address = reg[base].I - value;
rlm@1 4967 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4968 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4969 }
rlm@1 4970 break;
rlm@1 4971 case 0x760:
rlm@1 4972 case 0x768:
rlm@1 4973 {
rlm@1 4974 // STRB Rd, [Rn, -Rm, LSL #]!
rlm@1 4975 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 4976 int dest = (opcode >> 12) & 15;
rlm@1 4977 int base = (opcode >> 16) & 15;
rlm@1 4978 u32 address = reg[base].I - offset;
rlm@1 4979 reg[base].I = address;
rlm@1 4980 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4981 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4982 }
rlm@1 4983 break;
rlm@1 4984 case 0x762:
rlm@1 4985 case 0x76a:
rlm@1 4986 {
rlm@1 4987 // STRB Rd, [Rn, -Rm, LSR #]!
rlm@1 4988 int shift = (opcode >> 7) & 31;
rlm@1 4989 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 4990 int dest = (opcode >> 12) & 15;
rlm@1 4991 int base = (opcode >> 16) & 15;
rlm@1 4992 u32 address = reg[base].I - offset;
rlm@1 4993 reg[base].I = address;
rlm@1 4994 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 4995 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 4996 }
rlm@1 4997 break;
rlm@1 4998 case 0x764:
rlm@1 4999 case 0x76c:
rlm@1 5000 {
rlm@1 5001 // STRB Rd, [Rn, -Rm, ASR #]!
rlm@1 5002 int shift = (opcode >> 7) & 31;
rlm@1 5003 int offset;
rlm@1 5004 if (shift)
rlm@1 5005 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 5006 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 5007 offset = 0xFFFFFFFF;
rlm@1 5008 else
rlm@1 5009 offset = 0;
rlm@1 5010 int dest = (opcode >> 12) & 15;
rlm@1 5011 int base = (opcode >> 16) & 15;
rlm@1 5012 u32 address = reg[base].I - offset;
rlm@1 5013 reg[base].I = address;
rlm@1 5014 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5015 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5016 }
rlm@1 5017 break;
rlm@1 5018 case 0x766:
rlm@1 5019 case 0x76e:
rlm@1 5020 {
rlm@1 5021 // STRB Rd, [Rn, -Rm, ROR #]!
rlm@1 5022 int shift = (opcode >> 7) & 31;
rlm@1 5023 u32 value = reg[opcode & 15].I;
rlm@1 5024 if (shift)
rlm@1 5025 {
rlm@1 5026 ROR_VALUE;
rlm@1 5027 }
rlm@1 5028 else
rlm@1 5029 {
rlm@1 5030 RCR_VALUE;
rlm@1 5031 }
rlm@1 5032 int dest = (opcode >> 12) & 15;
rlm@1 5033 int base = (opcode >> 16) & 15;
rlm@1 5034 u32 address = reg[base].I - value;
rlm@1 5035 reg[base].I = address;
rlm@1 5036 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5037 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5038 }
rlm@1 5039 break;
rlm@1 5040 case 0x7c0:
rlm@1 5041 case 0x7c8:
rlm@1 5042 {
rlm@1 5043 // STRB Rd, [Rn, Rm, LSL #]
rlm@1 5044 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 5045 int dest = (opcode >> 12) & 15;
rlm@1 5046 int base = (opcode >> 16) & 15;
rlm@1 5047 u32 address = reg[base].I + offset;
rlm@1 5048 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5049 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5050 }
rlm@1 5051 break;
rlm@1 5052 case 0x7c2:
rlm@1 5053 case 0x7ca:
rlm@1 5054 {
rlm@1 5055 // STRB Rd, [Rn, Rm, LSR #]
rlm@1 5056 int shift = (opcode >> 7) & 31;
rlm@1 5057 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 5058 int dest = (opcode >> 12) & 15;
rlm@1 5059 int base = (opcode >> 16) & 15;
rlm@1 5060 u32 address = reg[base].I + offset;
rlm@1 5061 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5062 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5063 }
rlm@1 5064 break;
rlm@1 5065 case 0x7c4:
rlm@1 5066 case 0x7cc:
rlm@1 5067 {
rlm@1 5068 // STRB Rd, [Rn, Rm, ASR #]
rlm@1 5069 int shift = (opcode >> 7) & 31;
rlm@1 5070 int offset;
rlm@1 5071 if (shift)
rlm@1 5072 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 5073 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 5074 offset = 0xFFFFFFFF;
rlm@1 5075 else
rlm@1 5076 offset = 0;
rlm@1 5077 int dest = (opcode >> 12) & 15;
rlm@1 5078 int base = (opcode >> 16) & 15;
rlm@1 5079 u32 address = reg[base].I + offset;
rlm@1 5080 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5081 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5082 }
rlm@1 5083 break;
rlm@1 5084 case 0x7c6:
rlm@1 5085 case 0x7ce:
rlm@1 5086 {
rlm@1 5087 // STRB Rd, [Rn, Rm, ROR #]
rlm@1 5088 int shift = (opcode >> 7) & 31;
rlm@1 5089 u32 value = reg[opcode & 15].I;
rlm@1 5090 if (shift)
rlm@1 5091 {
rlm@1 5092 ROR_VALUE;
rlm@1 5093 }
rlm@1 5094 else
rlm@1 5095 {
rlm@1 5096 RCR_VALUE;
rlm@1 5097 }
rlm@1 5098 int dest = (opcode >> 12) & 15;
rlm@1 5099 int base = (opcode >> 16) & 15;
rlm@1 5100 u32 address = reg[base].I + value;
rlm@1 5101 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5102 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5103 }
rlm@1 5104 break;
rlm@1 5105 case 0x7e0:
rlm@1 5106 case 0x7e8:
rlm@1 5107 {
rlm@1 5108 // STRB Rd, [Rn, Rm, LSL #]!
rlm@1 5109 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 5110 int dest = (opcode >> 12) & 15;
rlm@1 5111 int base = (opcode >> 16) & 15;
rlm@1 5112 u32 address = reg[base].I + offset;
rlm@1 5113 reg[base].I = address;
rlm@1 5114 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5115 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5116 }
rlm@1 5117 break;
rlm@1 5118 case 0x7e2:
rlm@1 5119 case 0x7ea:
rlm@1 5120 {
rlm@1 5121 // STRB Rd, [Rn, Rm, LSR #]!
rlm@1 5122 int shift = (opcode >> 7) & 31;
rlm@1 5123 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 5124 int dest = (opcode >> 12) & 15;
rlm@1 5125 int base = (opcode >> 16) & 15;
rlm@1 5126 u32 address = reg[base].I + offset;
rlm@1 5127 reg[base].I = address;
rlm@1 5128 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5129 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5130 }
rlm@1 5131 break;
rlm@1 5132 case 0x7e4:
rlm@1 5133 case 0x7ec:
rlm@1 5134 {
rlm@1 5135 // STRB Rd, [Rn, Rm, ASR #]!
rlm@1 5136 int shift = (opcode >> 7) & 31;
rlm@1 5137 int offset;
rlm@1 5138 if (shift)
rlm@1 5139 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 5140 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 5141 offset = 0xFFFFFFFF;
rlm@1 5142 else
rlm@1 5143 offset = 0;
rlm@1 5144 int dest = (opcode >> 12) & 15;
rlm@1 5145 int base = (opcode >> 16) & 15;
rlm@1 5146 u32 address = reg[base].I + offset;
rlm@1 5147 reg[base].I = address;
rlm@1 5148 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5149 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5150 }
rlm@1 5151 break;
rlm@1 5152 case 0x7e6:
rlm@1 5153 case 0x7ee:
rlm@1 5154 {
rlm@1 5155 // STRB Rd, [Rn, Rm, ROR #]!
rlm@1 5156 int shift = (opcode >> 7) & 31;
rlm@1 5157 u32 value = reg[opcode & 15].I;
rlm@1 5158 if (shift)
rlm@1 5159 {
rlm@1 5160 ROR_VALUE;
rlm@1 5161 }
rlm@1 5162 else
rlm@1 5163 {
rlm@1 5164 RCR_VALUE;
rlm@1 5165 }
rlm@1 5166 int dest = (opcode >> 12) & 15;
rlm@1 5167 int base = (opcode >> 16) & 15;
rlm@1 5168 u32 address = reg[base].I + value;
rlm@1 5169 reg[base].I = address;
rlm@1 5170 CPUWriteByte(address, reg[dest].B.B0);
rlm@1 5171 clockTicks += 2 + CPUUpdateTicksAccess16(address);
rlm@1 5172 }
rlm@1 5173 break;
rlm@1 5174 case 0x650:
rlm@1 5175 case 0x658:
rlm@1 5176 // T versions are the same
rlm@1 5177 case 0x670:
rlm@1 5178 case 0x678:
rlm@1 5179 {
rlm@1 5180 // LDRB Rd, [Rn], -Rm, LSL #
rlm@1 5181 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 5182 int dest = (opcode >> 12) & 15;
rlm@1 5183 int base = (opcode >> 16) & 15;
rlm@1 5184 u32 address = reg[base].I;
rlm@1 5185 reg[dest].I = CPUReadByte(address);
rlm@1 5186 if (dest != base)
rlm@1 5187 reg[base].I = address - offset;
rlm@1 5188 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5189 }
rlm@1 5190 break;
rlm@1 5191 case 0x652:
rlm@1 5192 case 0x65a:
rlm@1 5193 // T versions are the same
rlm@1 5194 case 0x672:
rlm@1 5195 case 0x67a:
rlm@1 5196 {
rlm@1 5197 // LDRB Rd, [Rn], -Rm, LSR #
rlm@1 5198 int shift = (opcode >> 7) & 31;
rlm@1 5199 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 5200 int dest = (opcode >> 12) & 15;
rlm@1 5201 int base = (opcode >> 16) & 15;
rlm@1 5202 u32 address = reg[base].I;
rlm@1 5203 reg[dest].I = CPUReadByte(address);
rlm@1 5204 if (dest != base)
rlm@1 5205 reg[base].I = address - offset;
rlm@1 5206 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5207 }
rlm@1 5208 break;
rlm@1 5209 case 0x654:
rlm@1 5210 case 0x65c:
rlm@1 5211 // T versions are the same
rlm@1 5212 case 0x674:
rlm@1 5213 case 0x67c:
rlm@1 5214 {
rlm@1 5215 // LDRB Rd, [Rn], -Rm, ASR #
rlm@1 5216 int shift = (opcode >> 7) & 31;
rlm@1 5217 int offset;
rlm@1 5218 if (shift)
rlm@1 5219 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 5220 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 5221 offset = 0xFFFFFFFF;
rlm@1 5222 else
rlm@1 5223 offset = 0;
rlm@1 5224 int dest = (opcode >> 12) & 15;
rlm@1 5225 int base = (opcode >> 16) & 15;
rlm@1 5226 u32 address = reg[base].I;
rlm@1 5227 reg[dest].I = CPUReadByte(address);
rlm@1 5228 if (dest != base)
rlm@1 5229 reg[base].I = address - offset;
rlm@1 5230 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5231 }
rlm@1 5232 break;
rlm@1 5233 case 0x656:
rlm@1 5234 case 0x65e:
rlm@1 5235 // T versions are the same
rlm@1 5236 case 0x676:
rlm@1 5237 case 0x67e:
rlm@1 5238 {
rlm@1 5239 // LDRB Rd, [Rn], -Rm, ROR #
rlm@1 5240 int shift = (opcode >> 7) & 31;
rlm@1 5241 u32 value = reg[opcode & 15].I;
rlm@1 5242 if (shift)
rlm@1 5243 {
rlm@1 5244 ROR_VALUE;
rlm@1 5245 }
rlm@1 5246 else
rlm@1 5247 {
rlm@1 5248 RCR_VALUE;
rlm@1 5249 }
rlm@1 5250 int dest = (opcode >> 12) & 15;
rlm@1 5251 int base = (opcode >> 16) & 15;
rlm@1 5252 u32 address = reg[base].I;
rlm@1 5253 reg[dest].I = CPUReadByte(address);
rlm@1 5254 if (dest != base)
rlm@1 5255 reg[base].I = address - value;
rlm@1 5256 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5257 }
rlm@1 5258 break;
rlm@1 5259 case 0x6d0:
rlm@1 5260 case 0x6d8:
rlm@1 5261 // T versions are the same
rlm@1 5262 case 0x6f0:
rlm@1 5263 case 0x6f8:
rlm@1 5264 {
rlm@1 5265 // LDRB Rd, [Rn], Rm, LSL #
rlm@1 5266 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 5267 int dest = (opcode >> 12) & 15;
rlm@1 5268 int base = (opcode >> 16) & 15;
rlm@1 5269 u32 address = reg[base].I;
rlm@1 5270 reg[dest].I = CPUReadByte(address);
rlm@1 5271 if (dest != base)
rlm@1 5272 reg[base].I = address + offset;
rlm@1 5273 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5274 }
rlm@1 5275 break;
rlm@1 5276 case 0x6d2:
rlm@1 5277 case 0x6da:
rlm@1 5278 // T versions are the same
rlm@1 5279 case 0x6f2:
rlm@1 5280 case 0x6fa:
rlm@1 5281 {
rlm@1 5282 // LDRB Rd, [Rn], Rm, LSR #
rlm@1 5283 int shift = (opcode >> 7) & 31;
rlm@1 5284 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 5285 int dest = (opcode >> 12) & 15;
rlm@1 5286 int base = (opcode >> 16) & 15;
rlm@1 5287 u32 address = reg[base].I;
rlm@1 5288 reg[dest].I = CPUReadByte(address);
rlm@1 5289 if (dest != base)
rlm@1 5290 reg[base].I = address + offset;
rlm@1 5291 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5292 }
rlm@1 5293 break;
rlm@1 5294 case 0x6d4:
rlm@1 5295 case 0x6dc:
rlm@1 5296 // T versions are the same
rlm@1 5297 case 0x6f4:
rlm@1 5298 case 0x6fc:
rlm@1 5299 {
rlm@1 5300 // LDRB Rd, [Rn], Rm, ASR #
rlm@1 5301 int shift = (opcode >> 7) & 31;
rlm@1 5302 int offset;
rlm@1 5303 if (shift)
rlm@1 5304 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 5305 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 5306 offset = 0xFFFFFFFF;
rlm@1 5307 else
rlm@1 5308 offset = 0;
rlm@1 5309 int dest = (opcode >> 12) & 15;
rlm@1 5310 int base = (opcode >> 16) & 15;
rlm@1 5311 u32 address = reg[base].I;
rlm@1 5312 reg[dest].I = CPUReadByte(address);
rlm@1 5313 if (dest != base)
rlm@1 5314 reg[base].I = address + offset;
rlm@1 5315 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5316 }
rlm@1 5317 break;
rlm@1 5318 case 0x6d6:
rlm@1 5319 case 0x6de:
rlm@1 5320 // T versions are the same
rlm@1 5321 case 0x6f6:
rlm@1 5322 case 0x6fe:
rlm@1 5323 {
rlm@1 5324 // LDRB Rd, [Rn], Rm, ROR #
rlm@1 5325 int shift = (opcode >> 7) & 31;
rlm@1 5326 u32 value = reg[opcode & 15].I;
rlm@1 5327 if (shift)
rlm@1 5328 {
rlm@1 5329 ROR_VALUE;
rlm@1 5330 }
rlm@1 5331 else
rlm@1 5332 {
rlm@1 5333 RCR_VALUE;
rlm@1 5334 }
rlm@1 5335 int dest = (opcode >> 12) & 15;
rlm@1 5336 int base = (opcode >> 16) & 15;
rlm@1 5337 u32 address = reg[base].I;
rlm@1 5338 reg[dest].I = CPUReadByte(address);
rlm@1 5339 if (dest != base)
rlm@1 5340 reg[base].I = address + value;
rlm@1 5341 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5342 }
rlm@1 5343 break;
rlm@1 5344 case 0x750:
rlm@1 5345 case 0x758:
rlm@1 5346 {
rlm@1 5347 // LDRB Rd, [Rn, -Rm, LSL #]
rlm@1 5348 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 5349 int dest = (opcode >> 12) & 15;
rlm@1 5350 int base = (opcode >> 16) & 15;
rlm@1 5351 u32 address = reg[base].I - offset;
rlm@1 5352 reg[dest].I = CPUReadByte(address);
rlm@1 5353 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5354 }
rlm@1 5355 break;
rlm@1 5356 case 0x752:
rlm@1 5357 case 0x75a:
rlm@1 5358 {
rlm@1 5359 // LDRB Rd, [Rn, -Rm, LSR #]
rlm@1 5360 int shift = (opcode >> 7) & 31;
rlm@1 5361 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 5362 int dest = (opcode >> 12) & 15;
rlm@1 5363 int base = (opcode >> 16) & 15;
rlm@1 5364 u32 address = reg[base].I - offset;
rlm@1 5365 reg[dest].I = CPUReadByte(address);
rlm@1 5366 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5367 }
rlm@1 5368 break;
rlm@1 5369 case 0x754:
rlm@1 5370 case 0x75c:
rlm@1 5371 {
rlm@1 5372 // LDRB Rd, [Rn, -Rm, ASR #]
rlm@1 5373 int shift = (opcode >> 7) & 31;
rlm@1 5374 int offset;
rlm@1 5375 if (shift)
rlm@1 5376 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 5377 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 5378 offset = 0xFFFFFFFF;
rlm@1 5379 else
rlm@1 5380 offset = 0;
rlm@1 5381 int dest = (opcode >> 12) & 15;
rlm@1 5382 int base = (opcode >> 16) & 15;
rlm@1 5383 u32 address = reg[base].I - offset;
rlm@1 5384 reg[dest].I = CPUReadByte(address);
rlm@1 5385 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5386 }
rlm@1 5387 break;
rlm@1 5388 case 0x756:
rlm@1 5389 case 0x75e:
rlm@1 5390 {
rlm@1 5391 // LDRB Rd, [Rn, -Rm, ROR #]
rlm@1 5392 int shift = (opcode >> 7) & 31;
rlm@1 5393 u32 value = reg[opcode & 15].I;
rlm@1 5394 if (shift)
rlm@1 5395 {
rlm@1 5396 ROR_VALUE;
rlm@1 5397 }
rlm@1 5398 else
rlm@1 5399 {
rlm@1 5400 RCR_VALUE;
rlm@1 5401 }
rlm@1 5402 int dest = (opcode >> 12) & 15;
rlm@1 5403 int base = (opcode >> 16) & 15;
rlm@1 5404 u32 address = reg[base].I - value;
rlm@1 5405 reg[dest].I = CPUReadByte(address);
rlm@1 5406 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5407 }
rlm@1 5408 break;
rlm@1 5409 case 0x770:
rlm@1 5410 case 0x778:
rlm@1 5411 {
rlm@1 5412 // LDRB Rd, [Rn, -Rm, LSL #]!
rlm@1 5413 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 5414 int dest = (opcode >> 12) & 15;
rlm@1 5415 int base = (opcode >> 16) & 15;
rlm@1 5416 u32 address = reg[base].I - offset;
rlm@1 5417 reg[dest].I = CPUReadByte(address);
rlm@1 5418 if (dest != base)
rlm@1 5419 reg[base].I = address;
rlm@1 5420 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5421 }
rlm@1 5422 break;
rlm@1 5423 case 0x772:
rlm@1 5424 case 0x77a:
rlm@1 5425 {
rlm@1 5426 // LDRB Rd, [Rn, -Rm, LSR #]!
rlm@1 5427 int shift = (opcode >> 7) & 31;
rlm@1 5428 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 5429 int dest = (opcode >> 12) & 15;
rlm@1 5430 int base = (opcode >> 16) & 15;
rlm@1 5431 u32 address = reg[base].I - offset;
rlm@1 5432 reg[dest].I = CPUReadByte(address);
rlm@1 5433 if (dest != base)
rlm@1 5434 reg[base].I = address;
rlm@1 5435 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5436 }
rlm@1 5437 break;
rlm@1 5438 case 0x774:
rlm@1 5439 case 0x77c:
rlm@1 5440 {
rlm@1 5441 // LDRB Rd, [Rn, -Rm, ASR #]!
rlm@1 5442 int shift = (opcode >> 7) & 31;
rlm@1 5443 int offset;
rlm@1 5444 if (shift)
rlm@1 5445 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 5446 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 5447 offset = 0xFFFFFFFF;
rlm@1 5448 else
rlm@1 5449 offset = 0;
rlm@1 5450 int dest = (opcode >> 12) & 15;
rlm@1 5451 int base = (opcode >> 16) & 15;
rlm@1 5452 u32 address = reg[base].I - offset;
rlm@1 5453 reg[dest].I = CPUReadByte(address);
rlm@1 5454 if (dest != base)
rlm@1 5455 reg[base].I = address;
rlm@1 5456 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5457 }
rlm@1 5458 break;
rlm@1 5459 case 0x776:
rlm@1 5460 case 0x77e:
rlm@1 5461 {
rlm@1 5462 // LDRB Rd, [Rn, -Rm, ROR #]!
rlm@1 5463 int shift = (opcode >> 7) & 31;
rlm@1 5464 u32 value = reg[opcode & 15].I;
rlm@1 5465 if (shift)
rlm@1 5466 {
rlm@1 5467 ROR_VALUE;
rlm@1 5468 }
rlm@1 5469 else
rlm@1 5470 {
rlm@1 5471 RCR_VALUE;
rlm@1 5472 }
rlm@1 5473 int dest = (opcode >> 12) & 15;
rlm@1 5474 int base = (opcode >> 16) & 15;
rlm@1 5475 u32 address = reg[base].I - value;
rlm@1 5476 reg[dest].I = CPUReadByte(address);
rlm@1 5477 if (dest != base)
rlm@1 5478 reg[base].I = address;
rlm@1 5479 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5480 }
rlm@1 5481 break;
rlm@1 5482 case 0x7d0:
rlm@1 5483 case 0x7d8:
rlm@1 5484 {
rlm@1 5485 // LDRB Rd, [Rn, Rm, LSL #]
rlm@1 5486 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 5487 int dest = (opcode >> 12) & 15;
rlm@1 5488 int base = (opcode >> 16) & 15;
rlm@1 5489 u32 address = reg[base].I + offset;
rlm@1 5490 reg[dest].I = CPUReadByte(address);
rlm@1 5491 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5492 }
rlm@1 5493 break;
rlm@1 5494 case 0x7d2:
rlm@1 5495 case 0x7da:
rlm@1 5496 {
rlm@1 5497 // LDRB Rd, [Rn, Rm, LSR #]
rlm@1 5498 int shift = (opcode >> 7) & 31;
rlm@1 5499 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 5500 int dest = (opcode >> 12) & 15;
rlm@1 5501 int base = (opcode >> 16) & 15;
rlm@1 5502 u32 address = reg[base].I + offset;
rlm@1 5503 reg[dest].I = CPUReadByte(address);
rlm@1 5504 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5505 }
rlm@1 5506 break;
rlm@1 5507 case 0x7d4:
rlm@1 5508 case 0x7dc:
rlm@1 5509 {
rlm@1 5510 // LDRB Rd, [Rn, Rm, ASR #]
rlm@1 5511 int shift = (opcode >> 7) & 31;
rlm@1 5512 int offset;
rlm@1 5513 if (shift)
rlm@1 5514 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 5515 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 5516 offset = 0xFFFFFFFF;
rlm@1 5517 else
rlm@1 5518 offset = 0;
rlm@1 5519 int dest = (opcode >> 12) & 15;
rlm@1 5520 int base = (opcode >> 16) & 15;
rlm@1 5521 u32 address = reg[base].I + offset;
rlm@1 5522 reg[dest].I = CPUReadByte(address);
rlm@1 5523 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5524 }
rlm@1 5525 break;
rlm@1 5526 case 0x7d6:
rlm@1 5527 case 0x7de:
rlm@1 5528 {
rlm@1 5529 // LDRB Rd, [Rn, Rm, ROR #]
rlm@1 5530 int shift = (opcode >> 7) & 31;
rlm@1 5531 u32 value = reg[opcode & 15].I;
rlm@1 5532 if (shift)
rlm@1 5533 {
rlm@1 5534 ROR_VALUE;
rlm@1 5535 }
rlm@1 5536 else
rlm@1 5537 {
rlm@1 5538 RCR_VALUE;
rlm@1 5539 }
rlm@1 5540 int dest = (opcode >> 12) & 15;
rlm@1 5541 int base = (opcode >> 16) & 15;
rlm@1 5542 u32 address = reg[base].I + value;
rlm@1 5543 reg[dest].I = CPUReadByte(address);
rlm@1 5544 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5545 }
rlm@1 5546 break;
rlm@1 5547 case 0x7f0:
rlm@1 5548 case 0x7f8:
rlm@1 5549 {
rlm@1 5550 // LDRB Rd, [Rn, Rm, LSL #]!
rlm@1 5551 int offset = reg[opcode & 15].I << ((opcode >> 7) & 31);
rlm@1 5552 int dest = (opcode >> 12) & 15;
rlm@1 5553 int base = (opcode >> 16) & 15;
rlm@1 5554 u32 address = reg[base].I + offset;
rlm@1 5555 reg[dest].I = CPUReadByte(address);
rlm@1 5556 if (dest != base)
rlm@1 5557 reg[base].I = address;
rlm@1 5558 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5559 }
rlm@1 5560 break;
rlm@1 5561 case 0x7f2:
rlm@1 5562 case 0x7fa:
rlm@1 5563 {
rlm@1 5564 // LDRB Rd, [Rn, Rm, LSR #]!
rlm@1 5565 int shift = (opcode >> 7) & 31;
rlm@1 5566 int offset = shift ? reg[opcode & 15].I >> shift : 0;
rlm@1 5567 int dest = (opcode >> 12) & 15;
rlm@1 5568 int base = (opcode >> 16) & 15;
rlm@1 5569 u32 address = reg[base].I + offset;
rlm@1 5570 reg[dest].I = CPUReadByte(address);
rlm@1 5571 if (dest != base)
rlm@1 5572 reg[base].I = address;
rlm@1 5573 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5574 }
rlm@1 5575 break;
rlm@1 5576 case 0x7f4:
rlm@1 5577 case 0x7fc:
rlm@1 5578 {
rlm@1 5579 // LDRB Rd, [Rn, Rm, ASR #]!
rlm@1 5580 int shift = (opcode >> 7) & 31;
rlm@1 5581 int offset;
rlm@1 5582 if (shift)
rlm@1 5583 offset = (int)((s32)reg[opcode & 15].I >> shift);
rlm@1 5584 else if (reg[opcode & 15].I & 0x80000000)
rlm@1 5585 offset = 0xFFFFFFFF;
rlm@1 5586 else
rlm@1 5587 offset = 0;
rlm@1 5588 int dest = (opcode >> 12) & 15;
rlm@1 5589 int base = (opcode >> 16) & 15;
rlm@1 5590 u32 address = reg[base].I + offset;
rlm@1 5591 reg[dest].I = CPUReadByte(address);
rlm@1 5592 if (dest != base)
rlm@1 5593 reg[base].I = address;
rlm@1 5594 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5595 }
rlm@1 5596 break;
rlm@1 5597 case 0x7f6:
rlm@1 5598 case 0x7fe:
rlm@1 5599 {
rlm@1 5600 // LDRB Rd, [Rn, Rm, ROR #]!
rlm@1 5601 int shift = (opcode >> 7) & 31;
rlm@1 5602 u32 value = reg[opcode & 15].I;
rlm@1 5603 if (shift)
rlm@1 5604 {
rlm@1 5605 ROR_VALUE;
rlm@1 5606 }
rlm@1 5607 else
rlm@1 5608 {
rlm@1 5609 RCR_VALUE;
rlm@1 5610 }
rlm@1 5611 int dest = (opcode >> 12) & 15;
rlm@1 5612 int base = (opcode >> 16) & 15;
rlm@1 5613 u32 address = reg[base].I + value;
rlm@1 5614 reg[dest].I = CPUReadByte(address);
rlm@1 5615 if (dest != base)
rlm@1 5616 reg[base].I = address;
rlm@1 5617 clockTicks += 3 + CPUUpdateTicksAccess16(address);
rlm@1 5618 }
rlm@1 5619 break;
rlm@1 5620 #define STMW_REG(val, num) \
rlm@1 5621 if (opcode & (val)) { \
rlm@1 5622 CPUWriteMemory(address, reg[(num)].I); \
rlm@1 5623 if (!offset) { \
rlm@1 5624 reg[base].I = temp; \
rlm@1 5625 clockTicks += 1 + CPUUpdateTicksAccess32(address); \
rlm@1 5626 offset = 1; \
rlm@1 5627 } else { \
rlm@1 5628 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
rlm@1 5629 } \
rlm@1 5630 address += 4; \
rlm@1 5631 }
rlm@1 5632 #define STM_REG(val, num) \
rlm@1 5633 if (opcode & (val)) { \
rlm@1 5634 CPUWriteMemory(address, reg[(num)].I); \
rlm@1 5635 if (!offset) { \
rlm@1 5636 clockTicks += 1 + CPUUpdateTicksAccess32(address); \
rlm@1 5637 offset = 1; \
rlm@1 5638 } else { \
rlm@1 5639 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
rlm@1 5640 } \
rlm@1 5641 address += 4; \
rlm@1 5642 }
rlm@1 5643
rlm@1 5644 CASE_16(0x800)
rlm@1 5645 // STMDA Rn, {Rlist}
rlm@1 5646 {
rlm@1 5647 int base = (opcode & 0x000F0000) >> 16;
rlm@1 5648 u32 temp = reg[base].I -
rlm@1 5649 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 5650 u32 address = (temp + 4) & 0xFFFFFFFC;
rlm@1 5651 clockTicks += 2;
rlm@1 5652 int offset = 0;
rlm@1 5653 STM_REG(1, 0);
rlm@1 5654 STM_REG(2, 1);
rlm@1 5655 STM_REG(4, 2);
rlm@1 5656 STM_REG(8, 3);
rlm@1 5657 STM_REG(16, 4);
rlm@1 5658 STM_REG(32, 5);
rlm@1 5659 STM_REG(64, 6);
rlm@1 5660 STM_REG(128, 7);
rlm@1 5661 STM_REG(256, 8);
rlm@1 5662 STM_REG(512, 9);
rlm@1 5663 STM_REG(1024, 10);
rlm@1 5664 STM_REG(2048, 11);
rlm@1 5665 STM_REG(4096, 12);
rlm@1 5666 STM_REG(8192, 13);
rlm@1 5667 STM_REG(16384, 14);
rlm@1 5668 if (opcode & 32768)
rlm@1 5669 {
rlm@1 5670 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 5671 if (!offset)
rlm@1 5672 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 5673 else
rlm@1 5674 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 5675 }
rlm@1 5676 }
rlm@1 5677 break;
rlm@1 5678 CASE_16(0x820)
rlm@1 5679 {
rlm@1 5680 // STMDA Rn!, {Rlist}
rlm@1 5681 int base = (opcode & 0x000F0000) >> 16;
rlm@1 5682 u32 temp = reg[base].I -
rlm@1 5683 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 5684 u32 address = (temp + 4) & 0xFFFFFFFC;
rlm@1 5685 clockTicks += 2;
rlm@1 5686 int offset = 0;
rlm@1 5687
rlm@1 5688 STMW_REG(1, 0);
rlm@1 5689 STMW_REG(2, 1);
rlm@1 5690 STMW_REG(4, 2);
rlm@1 5691 STMW_REG(8, 3);
rlm@1 5692 STMW_REG(16, 4);
rlm@1 5693 STMW_REG(32, 5);
rlm@1 5694 STMW_REG(64, 6);
rlm@1 5695 STMW_REG(128, 7);
rlm@1 5696 STMW_REG(256, 8);
rlm@1 5697 STMW_REG(512, 9);
rlm@1 5698 STMW_REG(1024, 10);
rlm@1 5699 STMW_REG(2048, 11);
rlm@1 5700 STMW_REG(4096, 12);
rlm@1 5701 STMW_REG(8192, 13);
rlm@1 5702 STMW_REG(16384, 14);
rlm@1 5703 if (opcode & 32768)
rlm@1 5704 {
rlm@1 5705 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 5706 if (!offset)
rlm@1 5707 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 5708 else
rlm@1 5709 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 5710 reg[base].I = temp;
rlm@1 5711 }
rlm@1 5712 }
rlm@1 5713 break;
rlm@1 5714 CASE_16(0x840)
rlm@1 5715 {
rlm@1 5716 // STMDA Rn, {Rlist}^
rlm@1 5717 int base = (opcode & 0x000F0000) >> 16;
rlm@1 5718 u32 temp = reg[base].I -
rlm@1 5719 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 5720 u32 address = (temp + 4) & 0xFFFFFFFC;
rlm@1 5721 clockTicks += 2;
rlm@1 5722 int offset = 0;
rlm@1 5723
rlm@1 5724 STM_REG(1, 0);
rlm@1 5725 STM_REG(2, 1);
rlm@1 5726 STM_REG(4, 2);
rlm@1 5727 STM_REG(8, 3);
rlm@1 5728 STM_REG(16, 4);
rlm@1 5729 STM_REG(32, 5);
rlm@1 5730 STM_REG(64, 6);
rlm@1 5731 STM_REG(128, 7);
rlm@1 5732
rlm@1 5733 if (armMode == 0x11)
rlm@1 5734 {
rlm@1 5735 STM_REG(256, R8_FIQ);
rlm@1 5736 STM_REG(512, R9_FIQ);
rlm@1 5737 STM_REG(1024, R10_FIQ);
rlm@1 5738 STM_REG(2048, R11_FIQ);
rlm@1 5739 STM_REG(4096, R12_FIQ);
rlm@1 5740 }
rlm@1 5741 else
rlm@1 5742 {
rlm@1 5743 STM_REG(256, 8);
rlm@1 5744 STM_REG(512, 9);
rlm@1 5745 STM_REG(1024, 10);
rlm@1 5746 STM_REG(2048, 11);
rlm@1 5747 STM_REG(4096, 12);
rlm@1 5748 }
rlm@1 5749
rlm@1 5750 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 5751 {
rlm@1 5752 STM_REG(8192, R13_USR);
rlm@1 5753 STM_REG(16384, R14_USR);
rlm@1 5754 }
rlm@1 5755 else
rlm@1 5756 {
rlm@1 5757 STM_REG(8192, 13);
rlm@1 5758 STM_REG(16384, 14);
rlm@1 5759 }
rlm@1 5760
rlm@1 5761 if (opcode & 32768)
rlm@1 5762 {
rlm@1 5763 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 5764 if (!offset)
rlm@1 5765 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 5766 else
rlm@1 5767 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 5768 }
rlm@1 5769 }
rlm@1 5770 break;
rlm@1 5771 CASE_16(0x860)
rlm@1 5772 {
rlm@1 5773 // STMDA Rn!, {Rlist}^
rlm@1 5774 int base = (opcode & 0x000F0000) >> 16;
rlm@1 5775 u32 temp = reg[base].I -
rlm@1 5776 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 5777 u32 address = (temp + 4) & 0xFFFFFFFC;
rlm@1 5778 clockTicks += 2;
rlm@1 5779 int offset = 0;
rlm@1 5780
rlm@1 5781 STMW_REG(1, 0);
rlm@1 5782 STMW_REG(2, 1);
rlm@1 5783 STMW_REG(4, 2);
rlm@1 5784 STMW_REG(8, 3);
rlm@1 5785 STMW_REG(16, 4);
rlm@1 5786 STMW_REG(32, 5);
rlm@1 5787 STMW_REG(64, 6);
rlm@1 5788 STMW_REG(128, 7);
rlm@1 5789
rlm@1 5790 if (armMode == 0x11)
rlm@1 5791 {
rlm@1 5792 STMW_REG(256, R8_FIQ);
rlm@1 5793 STMW_REG(512, R9_FIQ);
rlm@1 5794 STMW_REG(1024, R10_FIQ);
rlm@1 5795 STMW_REG(2048, R11_FIQ);
rlm@1 5796 STMW_REG(4096, R12_FIQ);
rlm@1 5797 }
rlm@1 5798 else
rlm@1 5799 {
rlm@1 5800 STMW_REG(256, 8);
rlm@1 5801 STMW_REG(512, 9);
rlm@1 5802 STMW_REG(1024, 10);
rlm@1 5803 STMW_REG(2048, 11);
rlm@1 5804 STMW_REG(4096, 12);
rlm@1 5805 }
rlm@1 5806
rlm@1 5807 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 5808 {
rlm@1 5809 STMW_REG(8192, R13_USR);
rlm@1 5810 STMW_REG(16384, R14_USR);
rlm@1 5811 }
rlm@1 5812 else
rlm@1 5813 {
rlm@1 5814 STMW_REG(8192, 13);
rlm@1 5815 STMW_REG(16384, 14);
rlm@1 5816 }
rlm@1 5817
rlm@1 5818 if (opcode & 32768)
rlm@1 5819 {
rlm@1 5820 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 5821 if (!offset)
rlm@1 5822 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 5823 else
rlm@1 5824 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 5825 reg[base].I = temp;
rlm@1 5826 }
rlm@1 5827 }
rlm@1 5828 break;
rlm@1 5829
rlm@1 5830 CASE_16(0x880)
rlm@1 5831 {
rlm@1 5832 // STMIA Rn, {Rlist}
rlm@1 5833 int base = (opcode & 0x000F0000) >> 16;
rlm@1 5834 u32 address = reg[base].I & 0xFFFFFFFC;
rlm@1 5835 clockTicks += 2;
rlm@1 5836 int offset = 0;
rlm@1 5837 STM_REG(1, 0);
rlm@1 5838 STM_REG(2, 1);
rlm@1 5839 STM_REG(4, 2);
rlm@1 5840 STM_REG(8, 3);
rlm@1 5841 STM_REG(16, 4);
rlm@1 5842 STM_REG(32, 5);
rlm@1 5843 STM_REG(64, 6);
rlm@1 5844 STM_REG(128, 7);
rlm@1 5845 STM_REG(256, 8);
rlm@1 5846 STM_REG(512, 9);
rlm@1 5847 STM_REG(1024, 10);
rlm@1 5848 STM_REG(2048, 11);
rlm@1 5849 STM_REG(4096, 12);
rlm@1 5850 STM_REG(8192, 13);
rlm@1 5851 STM_REG(16384, 14);
rlm@1 5852 if (opcode & 32768)
rlm@1 5853 {
rlm@1 5854 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 5855 if (!offset)
rlm@1 5856 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 5857 else
rlm@1 5858 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 5859 }
rlm@1 5860 }
rlm@1 5861 break;
rlm@1 5862 CASE_16(0x8a0)
rlm@1 5863 {
rlm@1 5864 // STMIA Rn!, {Rlist}
rlm@1 5865 int base = (opcode & 0x000F0000) >> 16;
rlm@1 5866 u32 address = reg[base].I & 0xFFFFFFFC;
rlm@1 5867 clockTicks += 2;
rlm@1 5868 int offset = 0;
rlm@1 5869 u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] +
rlm@1 5870 cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 5871 STMW_REG(1, 0);
rlm@1 5872 STMW_REG(2, 1);
rlm@1 5873 STMW_REG(4, 2);
rlm@1 5874 STMW_REG(8, 3);
rlm@1 5875 STMW_REG(16, 4);
rlm@1 5876 STMW_REG(32, 5);
rlm@1 5877 STMW_REG(64, 6);
rlm@1 5878 STMW_REG(128, 7);
rlm@1 5879 STMW_REG(256, 8);
rlm@1 5880 STMW_REG(512, 9);
rlm@1 5881 STMW_REG(1024, 10);
rlm@1 5882 STMW_REG(2048, 11);
rlm@1 5883 STMW_REG(4096, 12);
rlm@1 5884 STMW_REG(8192, 13);
rlm@1 5885 STMW_REG(16384, 14);
rlm@1 5886 if (opcode & 32768)
rlm@1 5887 {
rlm@1 5888 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 5889 if (!offset)
rlm@1 5890 {
rlm@1 5891 reg[base].I = temp;
rlm@1 5892 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 5893 }
rlm@1 5894 else
rlm@1 5895 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 5896 }
rlm@1 5897 }
rlm@1 5898 break;
rlm@1 5899 CASE_16(0x8c0)
rlm@1 5900 {
rlm@1 5901 // STMIA Rn, {Rlist}^
rlm@1 5902 int base = (opcode & 0x000F0000) >> 16;
rlm@1 5903 u32 address = reg[base].I & 0xFFFFFFFC;
rlm@1 5904 clockTicks += 2;
rlm@1 5905 int offset = 0;
rlm@1 5906 STM_REG(1, 0);
rlm@1 5907 STM_REG(2, 1);
rlm@1 5908 STM_REG(4, 2);
rlm@1 5909 STM_REG(8, 3);
rlm@1 5910 STM_REG(16, 4);
rlm@1 5911 STM_REG(32, 5);
rlm@1 5912 STM_REG(64, 6);
rlm@1 5913 STM_REG(128, 7);
rlm@1 5914 if (armMode == 0x11)
rlm@1 5915 {
rlm@1 5916 STM_REG(256, R8_FIQ);
rlm@1 5917 STM_REG(512, R9_FIQ);
rlm@1 5918 STM_REG(1024, R10_FIQ);
rlm@1 5919 STM_REG(2048, R11_FIQ);
rlm@1 5920 STM_REG(4096, R12_FIQ);
rlm@1 5921 }
rlm@1 5922 else
rlm@1 5923 {
rlm@1 5924 STM_REG(256, 8);
rlm@1 5925 STM_REG(512, 9);
rlm@1 5926 STM_REG(1024, 10);
rlm@1 5927 STM_REG(2048, 11);
rlm@1 5928 STM_REG(4096, 12);
rlm@1 5929 }
rlm@1 5930 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 5931 {
rlm@1 5932 STM_REG(8192, R13_USR);
rlm@1 5933 STM_REG(16384, R14_USR);
rlm@1 5934 }
rlm@1 5935 else
rlm@1 5936 {
rlm@1 5937 STM_REG(8192, 13);
rlm@1 5938 STM_REG(16384, 14);
rlm@1 5939 }
rlm@1 5940 if (opcode & 32768)
rlm@1 5941 {
rlm@1 5942 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 5943 if (!offset)
rlm@1 5944 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 5945 else
rlm@1 5946 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 5947 }
rlm@1 5948 }
rlm@1 5949 break;
rlm@1 5950 CASE_16(0x8e0)
rlm@1 5951 {
rlm@1 5952 // STMIA Rn!, {Rlist}^
rlm@1 5953 int base = (opcode & 0x000F0000) >> 16;
rlm@1 5954 u32 address = reg[base].I & 0xFFFFFFFC;
rlm@1 5955 clockTicks += 2;
rlm@1 5956 int offset = 0;
rlm@1 5957 u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] +
rlm@1 5958 cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 5959 STMW_REG(1, 0);
rlm@1 5960 STMW_REG(2, 1);
rlm@1 5961 STMW_REG(4, 2);
rlm@1 5962 STMW_REG(8, 3);
rlm@1 5963 STMW_REG(16, 4);
rlm@1 5964 STMW_REG(32, 5);
rlm@1 5965 STMW_REG(64, 6);
rlm@1 5966 STMW_REG(128, 7);
rlm@1 5967 if (armMode == 0x11)
rlm@1 5968 {
rlm@1 5969 STMW_REG(256, R8_FIQ);
rlm@1 5970 STMW_REG(512, R9_FIQ);
rlm@1 5971 STMW_REG(1024, R10_FIQ);
rlm@1 5972 STMW_REG(2048, R11_FIQ);
rlm@1 5973 STMW_REG(4096, R12_FIQ);
rlm@1 5974 }
rlm@1 5975 else
rlm@1 5976 {
rlm@1 5977 STMW_REG(256, 8);
rlm@1 5978 STMW_REG(512, 9);
rlm@1 5979 STMW_REG(1024, 10);
rlm@1 5980 STMW_REG(2048, 11);
rlm@1 5981 STMW_REG(4096, 12);
rlm@1 5982 }
rlm@1 5983 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 5984 {
rlm@1 5985 STMW_REG(8192, R13_USR);
rlm@1 5986 STMW_REG(16384, R14_USR);
rlm@1 5987 }
rlm@1 5988 else
rlm@1 5989 {
rlm@1 5990 STMW_REG(8192, 13);
rlm@1 5991 STMW_REG(16384, 14);
rlm@1 5992 }
rlm@1 5993 if (opcode & 32768)
rlm@1 5994 {
rlm@1 5995 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 5996 if (!offset)
rlm@1 5997 {
rlm@1 5998 reg[base].I = temp;
rlm@1 5999 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 6000 }
rlm@1 6001 else
rlm@1 6002 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6003 }
rlm@1 6004 }
rlm@1 6005 break;
rlm@1 6006
rlm@1 6007 CASE_16(0x900)
rlm@1 6008 {
rlm@1 6009 // STMDB Rn, {Rlist}
rlm@1 6010 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6011 u32 temp = reg[base].I -
rlm@1 6012 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6013 u32 address = temp & 0xFFFFFFFC;
rlm@1 6014 clockTicks += 2;
rlm@1 6015 int offset = 0;
rlm@1 6016 STM_REG(1, 0);
rlm@1 6017 STM_REG(2, 1);
rlm@1 6018 STM_REG(4, 2);
rlm@1 6019 STM_REG(8, 3);
rlm@1 6020 STM_REG(16, 4);
rlm@1 6021 STM_REG(32, 5);
rlm@1 6022 STM_REG(64, 6);
rlm@1 6023 STM_REG(128, 7);
rlm@1 6024 STM_REG(256, 8);
rlm@1 6025 STM_REG(512, 9);
rlm@1 6026 STM_REG(1024, 10);
rlm@1 6027 STM_REG(2048, 11);
rlm@1 6028 STM_REG(4096, 12);
rlm@1 6029 STM_REG(8192, 13);
rlm@1 6030 STM_REG(16384, 14);
rlm@1 6031 if (opcode & 32768)
rlm@1 6032 {
rlm@1 6033 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 6034 if (!offset)
rlm@1 6035 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 6036 else
rlm@1 6037 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6038 }
rlm@1 6039 }
rlm@1 6040 break;
rlm@1 6041 CASE_16(0x920)
rlm@1 6042 {
rlm@1 6043 // STMDB Rn!, {Rlist}
rlm@1 6044 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6045 u32 temp = reg[base].I -
rlm@1 6046 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6047 u32 address = temp & 0xFFFFFFFC;
rlm@1 6048 clockTicks += 2;
rlm@1 6049 int offset = 0;
rlm@1 6050
rlm@1 6051 STMW_REG(1, 0);
rlm@1 6052 STMW_REG(2, 1);
rlm@1 6053 STMW_REG(4, 2);
rlm@1 6054 STMW_REG(8, 3);
rlm@1 6055 STMW_REG(16, 4);
rlm@1 6056 STMW_REG(32, 5);
rlm@1 6057 STMW_REG(64, 6);
rlm@1 6058 STMW_REG(128, 7);
rlm@1 6059 STMW_REG(256, 8);
rlm@1 6060 STMW_REG(512, 9);
rlm@1 6061 STMW_REG(1024, 10);
rlm@1 6062 STMW_REG(2048, 11);
rlm@1 6063 STMW_REG(4096, 12);
rlm@1 6064 STMW_REG(8192, 13);
rlm@1 6065 STMW_REG(16384, 14);
rlm@1 6066 if (opcode & 32768)
rlm@1 6067 {
rlm@1 6068 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 6069 if (!offset)
rlm@1 6070 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 6071 else
rlm@1 6072 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6073 reg[base].I = temp;
rlm@1 6074 }
rlm@1 6075 }
rlm@1 6076 break;
rlm@1 6077 CASE_16(0x940)
rlm@1 6078 {
rlm@1 6079 // STMDB Rn, {Rlist}^
rlm@1 6080 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6081 u32 temp = reg[base].I -
rlm@1 6082 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6083 u32 address = temp & 0xFFFFFFFC;
rlm@1 6084 clockTicks += 2;
rlm@1 6085 int offset = 0;
rlm@1 6086
rlm@1 6087 STM_REG(1, 0);
rlm@1 6088 STM_REG(2, 1);
rlm@1 6089 STM_REG(4, 2);
rlm@1 6090 STM_REG(8, 3);
rlm@1 6091 STM_REG(16, 4);
rlm@1 6092 STM_REG(32, 5);
rlm@1 6093 STM_REG(64, 6);
rlm@1 6094 STM_REG(128, 7);
rlm@1 6095
rlm@1 6096 if (armMode == 0x11)
rlm@1 6097 {
rlm@1 6098 STM_REG(256, R8_FIQ);
rlm@1 6099 STM_REG(512, R9_FIQ);
rlm@1 6100 STM_REG(1024, R10_FIQ);
rlm@1 6101 STM_REG(2048, R11_FIQ);
rlm@1 6102 STM_REG(4096, R12_FIQ);
rlm@1 6103 }
rlm@1 6104 else
rlm@1 6105 {
rlm@1 6106 STM_REG(256, 8);
rlm@1 6107 STM_REG(512, 9);
rlm@1 6108 STM_REG(1024, 10);
rlm@1 6109 STM_REG(2048, 11);
rlm@1 6110 STM_REG(4096, 12);
rlm@1 6111 }
rlm@1 6112
rlm@1 6113 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 6114 {
rlm@1 6115 STM_REG(8192, R13_USR);
rlm@1 6116 STM_REG(16384, R14_USR);
rlm@1 6117 }
rlm@1 6118 else
rlm@1 6119 {
rlm@1 6120 STM_REG(8192, 13);
rlm@1 6121 STM_REG(16384, 14);
rlm@1 6122 }
rlm@1 6123
rlm@1 6124 if (opcode & 32768)
rlm@1 6125 {
rlm@1 6126 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 6127 if (!offset)
rlm@1 6128 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 6129 else
rlm@1 6130 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6131 }
rlm@1 6132 }
rlm@1 6133 break;
rlm@1 6134 CASE_16(0x960)
rlm@1 6135 {
rlm@1 6136 // STMDB Rn!, {Rlist}^
rlm@1 6137 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6138 u32 temp = reg[base].I -
rlm@1 6139 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6140 u32 address = temp & 0xFFFFFFFC;
rlm@1 6141 clockTicks += 2;
rlm@1 6142 int offset = 0;
rlm@1 6143
rlm@1 6144 STMW_REG(1, 0);
rlm@1 6145 STMW_REG(2, 1);
rlm@1 6146 STMW_REG(4, 2);
rlm@1 6147 STMW_REG(8, 3);
rlm@1 6148 STMW_REG(16, 4);
rlm@1 6149 STMW_REG(32, 5);
rlm@1 6150 STMW_REG(64, 6);
rlm@1 6151 STMW_REG(128, 7);
rlm@1 6152
rlm@1 6153 if (armMode == 0x11)
rlm@1 6154 {
rlm@1 6155 STMW_REG(256, R8_FIQ);
rlm@1 6156 STMW_REG(512, R9_FIQ);
rlm@1 6157 STMW_REG(1024, R10_FIQ);
rlm@1 6158 STMW_REG(2048, R11_FIQ);
rlm@1 6159 STMW_REG(4096, R12_FIQ);
rlm@1 6160 }
rlm@1 6161 else
rlm@1 6162 {
rlm@1 6163 STMW_REG(256, 8);
rlm@1 6164 STMW_REG(512, 9);
rlm@1 6165 STMW_REG(1024, 10);
rlm@1 6166 STMW_REG(2048, 11);
rlm@1 6167 STMW_REG(4096, 12);
rlm@1 6168 }
rlm@1 6169
rlm@1 6170 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 6171 {
rlm@1 6172 STMW_REG(8192, R13_USR);
rlm@1 6173 STMW_REG(16384, R14_USR);
rlm@1 6174 }
rlm@1 6175 else
rlm@1 6176 {
rlm@1 6177 STMW_REG(8192, 13);
rlm@1 6178 STMW_REG(16384, 14);
rlm@1 6179 }
rlm@1 6180
rlm@1 6181 if (opcode & 32768)
rlm@1 6182 {
rlm@1 6183 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 6184 if (!offset)
rlm@1 6185 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 6186 else
rlm@1 6187 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6188 reg[base].I = temp;
rlm@1 6189 }
rlm@1 6190 }
rlm@1 6191 break;
rlm@1 6192
rlm@1 6193 CASE_16(0x980)
rlm@1 6194 // STMIB Rn, {Rlist}
rlm@1 6195 {
rlm@1 6196 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6197 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
rlm@1 6198 clockTicks += 2;
rlm@1 6199 int offset = 0;
rlm@1 6200 STM_REG(1, 0);
rlm@1 6201 STM_REG(2, 1);
rlm@1 6202 STM_REG(4, 2);
rlm@1 6203 STM_REG(8, 3);
rlm@1 6204 STM_REG(16, 4);
rlm@1 6205 STM_REG(32, 5);
rlm@1 6206 STM_REG(64, 6);
rlm@1 6207 STM_REG(128, 7);
rlm@1 6208 STM_REG(256, 8);
rlm@1 6209 STM_REG(512, 9);
rlm@1 6210 STM_REG(1024, 10);
rlm@1 6211 STM_REG(2048, 11);
rlm@1 6212 STM_REG(4096, 12);
rlm@1 6213 STM_REG(8192, 13);
rlm@1 6214 STM_REG(16384, 14);
rlm@1 6215 if (opcode & 32768)
rlm@1 6216 {
rlm@1 6217 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 6218 if (!offset)
rlm@1 6219 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 6220 else
rlm@1 6221 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6222 }
rlm@1 6223 }
rlm@1 6224 break;
rlm@1 6225 CASE_16(0x9a0)
rlm@1 6226 {
rlm@1 6227 // STMIB Rn!, {Rlist}
rlm@1 6228 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6229 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
rlm@1 6230 clockTicks += 2;
rlm@1 6231 int offset = 0;
rlm@1 6232 u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] +
rlm@1 6233 cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6234 STMW_REG(1, 0);
rlm@1 6235 STMW_REG(2, 1);
rlm@1 6236 STMW_REG(4, 2);
rlm@1 6237 STMW_REG(8, 3);
rlm@1 6238 STMW_REG(16, 4);
rlm@1 6239 STMW_REG(32, 5);
rlm@1 6240 STMW_REG(64, 6);
rlm@1 6241 STMW_REG(128, 7);
rlm@1 6242 STMW_REG(256, 8);
rlm@1 6243 STMW_REG(512, 9);
rlm@1 6244 STMW_REG(1024, 10);
rlm@1 6245 STMW_REG(2048, 11);
rlm@1 6246 STMW_REG(4096, 12);
rlm@1 6247 STMW_REG(8192, 13);
rlm@1 6248 STMW_REG(16384, 14);
rlm@1 6249 if (opcode & 32768)
rlm@1 6250 {
rlm@1 6251 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 6252 if (!offset)
rlm@1 6253 {
rlm@1 6254 reg[base].I = temp;
rlm@1 6255 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 6256 }
rlm@1 6257 else
rlm@1 6258 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6259 }
rlm@1 6260 }
rlm@1 6261 break;
rlm@1 6262 CASE_16(0x9c0)
rlm@1 6263 {
rlm@1 6264 // STMIB Rn, {Rlist}^
rlm@1 6265 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6266 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
rlm@1 6267 clockTicks += 2;
rlm@1 6268 int offset = 0;
rlm@1 6269 STM_REG(1, 0);
rlm@1 6270 STM_REG(2, 1);
rlm@1 6271 STM_REG(4, 2);
rlm@1 6272 STM_REG(8, 3);
rlm@1 6273 STM_REG(16, 4);
rlm@1 6274 STM_REG(32, 5);
rlm@1 6275 STM_REG(64, 6);
rlm@1 6276 STM_REG(128, 7);
rlm@1 6277 if (armMode == 0x11)
rlm@1 6278 {
rlm@1 6279 STM_REG(256, R8_FIQ);
rlm@1 6280 STM_REG(512, R9_FIQ);
rlm@1 6281 STM_REG(1024, R10_FIQ);
rlm@1 6282 STM_REG(2048, R11_FIQ);
rlm@1 6283 STM_REG(4096, R12_FIQ);
rlm@1 6284 }
rlm@1 6285 else
rlm@1 6286 {
rlm@1 6287 STM_REG(256, 8);
rlm@1 6288 STM_REG(512, 9);
rlm@1 6289 STM_REG(1024, 10);
rlm@1 6290 STM_REG(2048, 11);
rlm@1 6291 STM_REG(4096, 12);
rlm@1 6292 }
rlm@1 6293 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 6294 {
rlm@1 6295 STM_REG(8192, R13_USR);
rlm@1 6296 STM_REG(16384, R14_USR);
rlm@1 6297 }
rlm@1 6298 else
rlm@1 6299 {
rlm@1 6300 STM_REG(8192, 13);
rlm@1 6301 STM_REG(16384, 14);
rlm@1 6302 }
rlm@1 6303 if (opcode & 32768)
rlm@1 6304 {
rlm@1 6305 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 6306 if (!offset)
rlm@1 6307 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 6308 else
rlm@1 6309 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6310 }
rlm@1 6311 }
rlm@1 6312 break;
rlm@1 6313 CASE_16(0x9e0)
rlm@1 6314 {
rlm@1 6315 // STMIB Rn!, {Rlist}^
rlm@1 6316 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6317 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
rlm@1 6318 clockTicks += 2;
rlm@1 6319 int offset = 0;
rlm@1 6320 u32 temp = reg[base].I + 4 * (cpuBitsSet[opcode & 0xFF] +
rlm@1 6321 cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6322 STMW_REG(1, 0);
rlm@1 6323 STMW_REG(2, 1);
rlm@1 6324 STMW_REG(4, 2);
rlm@1 6325 STMW_REG(8, 3);
rlm@1 6326 STMW_REG(16, 4);
rlm@1 6327 STMW_REG(32, 5);
rlm@1 6328 STMW_REG(64, 6);
rlm@1 6329 STMW_REG(128, 7);
rlm@1 6330 if (armMode == 0x11)
rlm@1 6331 {
rlm@1 6332 STMW_REG(256, R8_FIQ);
rlm@1 6333 STMW_REG(512, R9_FIQ);
rlm@1 6334 STMW_REG(1024, R10_FIQ);
rlm@1 6335 STMW_REG(2048, R11_FIQ);
rlm@1 6336 STMW_REG(4096, R12_FIQ);
rlm@1 6337 }
rlm@1 6338 else
rlm@1 6339 {
rlm@1 6340 STMW_REG(256, 8);
rlm@1 6341 STMW_REG(512, 9);
rlm@1 6342 STMW_REG(1024, 10);
rlm@1 6343 STMW_REG(2048, 11);
rlm@1 6344 STMW_REG(4096, 12);
rlm@1 6345 }
rlm@1 6346 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 6347 {
rlm@1 6348 STMW_REG(8192, R13_USR);
rlm@1 6349 STMW_REG(16384, R14_USR);
rlm@1 6350 }
rlm@1 6351 else
rlm@1 6352 {
rlm@1 6353 STMW_REG(8192, 13);
rlm@1 6354 STMW_REG(16384, 14);
rlm@1 6355 }
rlm@1 6356 if (opcode & 32768)
rlm@1 6357 {
rlm@1 6358 CPUWriteMemory(address, reg[15].I + 4);
rlm@1 6359 if (!offset)
rlm@1 6360 {
rlm@1 6361 reg[base].I = temp;
rlm@1 6362 clockTicks += 1 + CPUUpdateTicksAccess32(address);
rlm@1 6363 }
rlm@1 6364 else
rlm@1 6365 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6366 }
rlm@1 6367 }
rlm@1 6368 break;
rlm@1 6369
rlm@1 6370 #define LDM_REG(val, num) \
rlm@1 6371 if (opcode & (val)) { \
rlm@1 6372 reg[(num)].I = CPUReadMemory(address); \
rlm@1 6373 if (offset) \
rlm@1 6374 clockTicks += 1 + CPUUpdateTicksAccessSeq32(address); \
rlm@1 6375 else { \
rlm@1 6376 clockTicks += 1 + CPUUpdateTicksAccess32(address); \
rlm@1 6377 offset = 1; \
rlm@1 6378 } \
rlm@1 6379 address += 4; \
rlm@1 6380 }
rlm@1 6381
rlm@1 6382 CASE_16(0x810)
rlm@1 6383 {
rlm@1 6384 // LDMDA Rn, {Rlist}
rlm@1 6385 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6386 u32 temp = reg[base].I -
rlm@1 6387 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6388 u32 address = (temp + 4) & 0xFFFFFFFC;
rlm@1 6389 clockTicks += 2;
rlm@1 6390 int offset = 0;
rlm@1 6391 LDM_REG(1, 0);
rlm@1 6392 LDM_REG(2, 1);
rlm@1 6393 LDM_REG(4, 2);
rlm@1 6394 LDM_REG(8, 3);
rlm@1 6395 LDM_REG(16, 4);
rlm@1 6396 LDM_REG(32, 5);
rlm@1 6397 LDM_REG(64, 6);
rlm@1 6398 LDM_REG(128, 7);
rlm@1 6399 LDM_REG(256, 8);
rlm@1 6400 LDM_REG(512, 9);
rlm@1 6401 LDM_REG(1024, 10);
rlm@1 6402 LDM_REG(2048, 11);
rlm@1 6403 LDM_REG(4096, 12);
rlm@1 6404 LDM_REG(8192, 13);
rlm@1 6405 LDM_REG(16384, 14);
rlm@1 6406 if (opcode & 32768)
rlm@1 6407 {
rlm@1 6408 reg[15].I = CPUReadMemory(address);
rlm@1 6409 if (!offset)
rlm@1 6410 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6411 else
rlm@1 6412 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6413 armNextPC = reg[15].I;
rlm@1 6414 reg[15].I += 4;
rlm@1 6415 }
rlm@1 6416 }
rlm@1 6417 break;
rlm@1 6418 CASE_16(0x830)
rlm@1 6419 {
rlm@1 6420 // LDMDA Rn!, {Rlist}
rlm@1 6421 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6422 u32 temp = reg[base].I -
rlm@1 6423 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6424 u32 address = (temp + 4) & 0xFFFFFFFC;
rlm@1 6425 clockTicks += 2;
rlm@1 6426 int offset = 0;
rlm@1 6427 LDM_REG(1, 0);
rlm@1 6428 LDM_REG(2, 1);
rlm@1 6429 LDM_REG(4, 2);
rlm@1 6430 LDM_REG(8, 3);
rlm@1 6431 LDM_REG(16, 4);
rlm@1 6432 LDM_REG(32, 5);
rlm@1 6433 LDM_REG(64, 6);
rlm@1 6434 LDM_REG(128, 7);
rlm@1 6435 LDM_REG(256, 8);
rlm@1 6436 LDM_REG(512, 9);
rlm@1 6437 LDM_REG(1024, 10);
rlm@1 6438 LDM_REG(2048, 11);
rlm@1 6439 LDM_REG(4096, 12);
rlm@1 6440 LDM_REG(8192, 13);
rlm@1 6441 LDM_REG(16384, 14);
rlm@1 6442 if (opcode & 32768)
rlm@1 6443 {
rlm@1 6444 reg[15].I = CPUReadMemory(address);
rlm@1 6445 if (!offset)
rlm@1 6446 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6447 else
rlm@1 6448 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6449 armNextPC = reg[15].I;
rlm@1 6450 reg[15].I += 4;
rlm@1 6451 }
rlm@1 6452 if (!(opcode & (1 << base)))
rlm@1 6453 reg[base].I = temp;
rlm@1 6454 }
rlm@1 6455 break;
rlm@1 6456 CASE_16(0x850)
rlm@1 6457 {
rlm@1 6458 // LDMDA Rn, {Rlist}^
rlm@1 6459 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6460 u32 temp = reg[base].I -
rlm@1 6461 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6462 u32 address = (temp + 4) & 0xFFFFFFFC;
rlm@1 6463 clockTicks += 2;
rlm@1 6464 int offset = 0;
rlm@1 6465 if (opcode & 0x8000)
rlm@1 6466 {
rlm@1 6467 LDM_REG(1, 0);
rlm@1 6468 LDM_REG(2, 1);
rlm@1 6469 LDM_REG(4, 2);
rlm@1 6470 LDM_REG(8, 3);
rlm@1 6471 LDM_REG(16, 4);
rlm@1 6472 LDM_REG(32, 5);
rlm@1 6473 LDM_REG(64, 6);
rlm@1 6474 LDM_REG(128, 7);
rlm@1 6475 LDM_REG(256, 8);
rlm@1 6476 LDM_REG(512, 9);
rlm@1 6477 LDM_REG(1024, 10);
rlm@1 6478 LDM_REG(2048, 11);
rlm@1 6479 LDM_REG(4096, 12);
rlm@1 6480 LDM_REG(8192, 13);
rlm@1 6481 LDM_REG(16384, 14);
rlm@1 6482
rlm@1 6483 reg[15].I = CPUReadMemory(address);
rlm@1 6484 if (!offset)
rlm@1 6485 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6486 else
rlm@1 6487 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6488
rlm@1 6489 CPUSwitchMode(reg[17].I & 0x1f, false);
rlm@1 6490 if (armState)
rlm@1 6491 {
rlm@1 6492 armNextPC = reg[15].I & 0xFFFFFFFC;
rlm@1 6493 reg[15].I = armNextPC + 4;
rlm@1 6494 }
rlm@1 6495 else
rlm@1 6496 {
rlm@1 6497 armNextPC = reg[15].I & 0xFFFFFFFE;
rlm@1 6498 reg[15].I = armNextPC + 2;
rlm@1 6499 }
rlm@1 6500 }
rlm@1 6501 else
rlm@1 6502 {
rlm@1 6503 LDM_REG(1, 0);
rlm@1 6504 LDM_REG(2, 1);
rlm@1 6505 LDM_REG(4, 2);
rlm@1 6506 LDM_REG(8, 3);
rlm@1 6507 LDM_REG(16, 4);
rlm@1 6508 LDM_REG(32, 5);
rlm@1 6509 LDM_REG(64, 6);
rlm@1 6510 LDM_REG(128, 7);
rlm@1 6511
rlm@1 6512 if (armMode == 0x11)
rlm@1 6513 {
rlm@1 6514 LDM_REG(256, R8_FIQ);
rlm@1 6515 LDM_REG(512, R9_FIQ);
rlm@1 6516 LDM_REG(1024, R10_FIQ);
rlm@1 6517 LDM_REG(2048, R11_FIQ);
rlm@1 6518 LDM_REG(4096, R12_FIQ);
rlm@1 6519 }
rlm@1 6520 else
rlm@1 6521 {
rlm@1 6522 LDM_REG(256, 8);
rlm@1 6523 LDM_REG(512, 9);
rlm@1 6524 LDM_REG(1024, 10);
rlm@1 6525 LDM_REG(2048, 11);
rlm@1 6526 LDM_REG(4096, 12);
rlm@1 6527 }
rlm@1 6528
rlm@1 6529 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 6530 {
rlm@1 6531 LDM_REG(8192, R13_USR);
rlm@1 6532 LDM_REG(16384, R14_USR);
rlm@1 6533 }
rlm@1 6534 else
rlm@1 6535 {
rlm@1 6536 LDM_REG(8192, 13);
rlm@1 6537 LDM_REG(16384, 14);
rlm@1 6538 }
rlm@1 6539 }
rlm@1 6540 }
rlm@1 6541 break;
rlm@1 6542 CASE_16(0x870)
rlm@1 6543 {
rlm@1 6544 // LDMDA Rn!, {Rlist}^
rlm@1 6545 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6546 u32 temp = reg[base].I -
rlm@1 6547 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6548 u32 address = (temp + 4) & 0xFFFFFFFC;
rlm@1 6549 clockTicks += 2;
rlm@1 6550 int offset = 0;
rlm@1 6551 if (opcode & 0x8000)
rlm@1 6552 {
rlm@1 6553 LDM_REG(1, 0);
rlm@1 6554 LDM_REG(2, 1);
rlm@1 6555 LDM_REG(4, 2);
rlm@1 6556 LDM_REG(8, 3);
rlm@1 6557 LDM_REG(16, 4);
rlm@1 6558 LDM_REG(32, 5);
rlm@1 6559 LDM_REG(64, 6);
rlm@1 6560 LDM_REG(128, 7);
rlm@1 6561 LDM_REG(256, 8);
rlm@1 6562 LDM_REG(512, 9);
rlm@1 6563 LDM_REG(1024, 10);
rlm@1 6564 LDM_REG(2048, 11);
rlm@1 6565 LDM_REG(4096, 12);
rlm@1 6566 LDM_REG(8192, 13);
rlm@1 6567 LDM_REG(16384, 14);
rlm@1 6568
rlm@1 6569 reg[15].I = CPUReadMemory(address);
rlm@1 6570 if (!offset)
rlm@1 6571 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6572 else
rlm@1 6573 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6574
rlm@1 6575 if (!(opcode & (1 << base)))
rlm@1 6576 reg[base].I = temp;
rlm@1 6577
rlm@1 6578 CPUSwitchMode(reg[17].I & 0x1f, false);
rlm@1 6579 if (armState)
rlm@1 6580 {
rlm@1 6581 armNextPC = reg[15].I & 0xFFFFFFFC;
rlm@1 6582 reg[15].I = armNextPC + 4;
rlm@1 6583 }
rlm@1 6584 else
rlm@1 6585 {
rlm@1 6586 armNextPC = reg[15].I & 0xFFFFFFFE;
rlm@1 6587 reg[15].I = armNextPC + 2;
rlm@1 6588 }
rlm@1 6589 }
rlm@1 6590 else
rlm@1 6591 {
rlm@1 6592 LDM_REG(1, 0);
rlm@1 6593 LDM_REG(2, 1);
rlm@1 6594 LDM_REG(4, 2);
rlm@1 6595 LDM_REG(8, 3);
rlm@1 6596 LDM_REG(16, 4);
rlm@1 6597 LDM_REG(32, 5);
rlm@1 6598 LDM_REG(64, 6);
rlm@1 6599 LDM_REG(128, 7);
rlm@1 6600
rlm@1 6601 if (armMode == 0x11)
rlm@1 6602 {
rlm@1 6603 LDM_REG(256, R8_FIQ);
rlm@1 6604 LDM_REG(512, R9_FIQ);
rlm@1 6605 LDM_REG(1024, R10_FIQ);
rlm@1 6606 LDM_REG(2048, R11_FIQ);
rlm@1 6607 LDM_REG(4096, R12_FIQ);
rlm@1 6608 }
rlm@1 6609 else
rlm@1 6610 {
rlm@1 6611 LDM_REG(256, 8);
rlm@1 6612 LDM_REG(512, 9);
rlm@1 6613 LDM_REG(1024, 10);
rlm@1 6614 LDM_REG(2048, 11);
rlm@1 6615 LDM_REG(4096, 12);
rlm@1 6616 }
rlm@1 6617
rlm@1 6618 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 6619 {
rlm@1 6620 LDM_REG(8192, R13_USR);
rlm@1 6621 LDM_REG(16384, R14_USR);
rlm@1 6622 }
rlm@1 6623 else
rlm@1 6624 {
rlm@1 6625 LDM_REG(8192, 13);
rlm@1 6626 LDM_REG(16384, 14);
rlm@1 6627 }
rlm@1 6628
rlm@1 6629 if (!(opcode & (1 << base)))
rlm@1 6630 reg[base].I = temp;
rlm@1 6631 }
rlm@1 6632 }
rlm@1 6633 break;
rlm@1 6634
rlm@1 6635 CASE_16(0x890)
rlm@1 6636 {
rlm@1 6637 // LDMIA Rn, {Rlist}
rlm@1 6638 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6639 u32 address = reg[base].I & 0xFFFFFFFC;
rlm@1 6640 clockTicks += 2;
rlm@1 6641 int offset = 0;
rlm@1 6642 LDM_REG(1, 0);
rlm@1 6643 LDM_REG(2, 1);
rlm@1 6644 LDM_REG(4, 2);
rlm@1 6645 LDM_REG(8, 3);
rlm@1 6646 LDM_REG(16, 4);
rlm@1 6647 LDM_REG(32, 5);
rlm@1 6648 LDM_REG(64, 6);
rlm@1 6649 LDM_REG(128, 7);
rlm@1 6650 LDM_REG(256, 8);
rlm@1 6651 LDM_REG(512, 9);
rlm@1 6652 LDM_REG(1024, 10);
rlm@1 6653 LDM_REG(2048, 11);
rlm@1 6654 LDM_REG(4096, 12);
rlm@1 6655 LDM_REG(8192, 13);
rlm@1 6656 LDM_REG(16384, 14);
rlm@1 6657 if (opcode & 32768)
rlm@1 6658 {
rlm@1 6659 reg[15].I = CPUReadMemory(address);
rlm@1 6660 if (!offset)
rlm@1 6661 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6662 else
rlm@1 6663 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6664 armNextPC = reg[15].I;
rlm@1 6665 reg[15].I += 4;
rlm@1 6666 }
rlm@1 6667 }
rlm@1 6668 break;
rlm@1 6669 CASE_16(0x8b0)
rlm@1 6670 {
rlm@1 6671 // LDMIA Rn!, {Rlist}
rlm@1 6672 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6673 u32 temp = reg[base].I +
rlm@1 6674 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6675 u32 address = reg[base].I & 0xFFFFFFFC;
rlm@1 6676 clockTicks += 2;
rlm@1 6677 int offset = 0;
rlm@1 6678 LDM_REG(1, 0);
rlm@1 6679 LDM_REG(2, 1);
rlm@1 6680 LDM_REG(4, 2);
rlm@1 6681 LDM_REG(8, 3);
rlm@1 6682 LDM_REG(16, 4);
rlm@1 6683 LDM_REG(32, 5);
rlm@1 6684 LDM_REG(64, 6);
rlm@1 6685 LDM_REG(128, 7);
rlm@1 6686 LDM_REG(256, 8);
rlm@1 6687 LDM_REG(512, 9);
rlm@1 6688 LDM_REG(1024, 10);
rlm@1 6689 LDM_REG(2048, 11);
rlm@1 6690 LDM_REG(4096, 12);
rlm@1 6691 LDM_REG(8192, 13);
rlm@1 6692 LDM_REG(16384, 14);
rlm@1 6693 if (opcode & 32768)
rlm@1 6694 {
rlm@1 6695 reg[15].I = CPUReadMemory(address);
rlm@1 6696 if (!offset)
rlm@1 6697 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6698 else
rlm@1 6699 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6700 armNextPC = reg[15].I;
rlm@1 6701 reg[15].I += 4;
rlm@1 6702 }
rlm@1 6703 if (!(opcode & (1 << base)))
rlm@1 6704 reg[base].I = temp;
rlm@1 6705 }
rlm@1 6706 break;
rlm@1 6707 CASE_16(0x8d0)
rlm@1 6708 {
rlm@1 6709 // LDMIA Rn, {Rlist}^
rlm@1 6710 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6711 u32 address = reg[base].I & 0xFFFFFFFC;
rlm@1 6712 clockTicks += 2;
rlm@1 6713 int offset = 0;
rlm@1 6714 if (opcode & 0x8000)
rlm@1 6715 {
rlm@1 6716 LDM_REG(1, 0);
rlm@1 6717 LDM_REG(2, 1);
rlm@1 6718 LDM_REG(4, 2);
rlm@1 6719 LDM_REG(8, 3);
rlm@1 6720 LDM_REG(16, 4);
rlm@1 6721 LDM_REG(32, 5);
rlm@1 6722 LDM_REG(64, 6);
rlm@1 6723 LDM_REG(128, 7);
rlm@1 6724 LDM_REG(256, 8);
rlm@1 6725 LDM_REG(512, 9);
rlm@1 6726 LDM_REG(1024, 10);
rlm@1 6727 LDM_REG(2048, 11);
rlm@1 6728 LDM_REG(4096, 12);
rlm@1 6729 LDM_REG(8192, 13);
rlm@1 6730 LDM_REG(16384, 14);
rlm@1 6731
rlm@1 6732 reg[15].I = CPUReadMemory(address);
rlm@1 6733 if (!offset)
rlm@1 6734 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6735 else
rlm@1 6736 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6737
rlm@1 6738 CPUSwitchMode(reg[17].I & 0x1f, false);
rlm@1 6739 if (armState)
rlm@1 6740 {
rlm@1 6741 armNextPC = reg[15].I & 0xFFFFFFFC;
rlm@1 6742 reg[15].I = armNextPC + 4;
rlm@1 6743 }
rlm@1 6744 else
rlm@1 6745 {
rlm@1 6746 armNextPC = reg[15].I & 0xFFFFFFFE;
rlm@1 6747 reg[15].I = armNextPC + 2;
rlm@1 6748 }
rlm@1 6749 }
rlm@1 6750 else
rlm@1 6751 {
rlm@1 6752 LDM_REG(1, 0);
rlm@1 6753 LDM_REG(2, 1);
rlm@1 6754 LDM_REG(4, 2);
rlm@1 6755 LDM_REG(8, 3);
rlm@1 6756 LDM_REG(16, 4);
rlm@1 6757 LDM_REG(32, 5);
rlm@1 6758 LDM_REG(64, 6);
rlm@1 6759 LDM_REG(128, 7);
rlm@1 6760
rlm@1 6761 if (armMode == 0x11)
rlm@1 6762 {
rlm@1 6763 LDM_REG(256, R8_FIQ);
rlm@1 6764 LDM_REG(512, R9_FIQ);
rlm@1 6765 LDM_REG(1024, R10_FIQ);
rlm@1 6766 LDM_REG(2048, R11_FIQ);
rlm@1 6767 LDM_REG(4096, R12_FIQ);
rlm@1 6768 }
rlm@1 6769 else
rlm@1 6770 {
rlm@1 6771 LDM_REG(256, 8);
rlm@1 6772 LDM_REG(512, 9);
rlm@1 6773 LDM_REG(1024, 10);
rlm@1 6774 LDM_REG(2048, 11);
rlm@1 6775 LDM_REG(4096, 12);
rlm@1 6776 }
rlm@1 6777
rlm@1 6778 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 6779 {
rlm@1 6780 LDM_REG(8192, R13_USR);
rlm@1 6781 LDM_REG(16384, R14_USR);
rlm@1 6782 }
rlm@1 6783 else
rlm@1 6784 {
rlm@1 6785 LDM_REG(8192, 13);
rlm@1 6786 LDM_REG(16384, 14);
rlm@1 6787 }
rlm@1 6788 }
rlm@1 6789 }
rlm@1 6790 break;
rlm@1 6791 CASE_16(0x8f0)
rlm@1 6792 {
rlm@1 6793 // LDMIA Rn!, {Rlist}^
rlm@1 6794 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6795 u32 temp = reg[base].I +
rlm@1 6796 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6797 u32 address = reg[base].I & 0xFFFFFFFC;
rlm@1 6798 clockTicks += 2;
rlm@1 6799 int offset = 0;
rlm@1 6800 if (opcode & 0x8000)
rlm@1 6801 {
rlm@1 6802 LDM_REG(1, 0);
rlm@1 6803 LDM_REG(2, 1);
rlm@1 6804 LDM_REG(4, 2);
rlm@1 6805 LDM_REG(8, 3);
rlm@1 6806 LDM_REG(16, 4);
rlm@1 6807 LDM_REG(32, 5);
rlm@1 6808 LDM_REG(64, 6);
rlm@1 6809 LDM_REG(128, 7);
rlm@1 6810 LDM_REG(256, 8);
rlm@1 6811 LDM_REG(512, 9);
rlm@1 6812 LDM_REG(1024, 10);
rlm@1 6813 LDM_REG(2048, 11);
rlm@1 6814 LDM_REG(4096, 12);
rlm@1 6815 LDM_REG(8192, 13);
rlm@1 6816 LDM_REG(16384, 14);
rlm@1 6817
rlm@1 6818 reg[15].I = CPUReadMemory(address);
rlm@1 6819 if (!offset)
rlm@1 6820 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6821 else
rlm@1 6822 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6823
rlm@1 6824 if (!(opcode & (1 << base)))
rlm@1 6825 reg[base].I = temp;
rlm@1 6826
rlm@1 6827 CPUSwitchMode(reg[17].I & 0x1f, false);
rlm@1 6828 if (armState)
rlm@1 6829 {
rlm@1 6830 armNextPC = reg[15].I & 0xFFFFFFFC;
rlm@1 6831 reg[15].I = armNextPC + 4;
rlm@1 6832 }
rlm@1 6833 else
rlm@1 6834 {
rlm@1 6835 armNextPC = reg[15].I & 0xFFFFFFFE;
rlm@1 6836 reg[15].I = armNextPC + 2;
rlm@1 6837 }
rlm@1 6838 }
rlm@1 6839 else
rlm@1 6840 {
rlm@1 6841 LDM_REG(1, 0);
rlm@1 6842 LDM_REG(2, 1);
rlm@1 6843 LDM_REG(4, 2);
rlm@1 6844 LDM_REG(8, 3);
rlm@1 6845 LDM_REG(16, 4);
rlm@1 6846 LDM_REG(32, 5);
rlm@1 6847 LDM_REG(64, 6);
rlm@1 6848 LDM_REG(128, 7);
rlm@1 6849
rlm@1 6850 if (armMode == 0x11)
rlm@1 6851 {
rlm@1 6852 LDM_REG(256, R8_FIQ);
rlm@1 6853 LDM_REG(512, R9_FIQ);
rlm@1 6854 LDM_REG(1024, R10_FIQ);
rlm@1 6855 LDM_REG(2048, R11_FIQ);
rlm@1 6856 LDM_REG(4096, R12_FIQ);
rlm@1 6857 }
rlm@1 6858 else
rlm@1 6859 {
rlm@1 6860 LDM_REG(256, 8);
rlm@1 6861 LDM_REG(512, 9);
rlm@1 6862 LDM_REG(1024, 10);
rlm@1 6863 LDM_REG(2048, 11);
rlm@1 6864 LDM_REG(4096, 12);
rlm@1 6865 }
rlm@1 6866
rlm@1 6867 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 6868 {
rlm@1 6869 LDM_REG(8192, R13_USR);
rlm@1 6870 LDM_REG(16384, R14_USR);
rlm@1 6871 }
rlm@1 6872 else
rlm@1 6873 {
rlm@1 6874 LDM_REG(8192, 13);
rlm@1 6875 LDM_REG(16384, 14);
rlm@1 6876 }
rlm@1 6877
rlm@1 6878 if (!(opcode & (1 << base)))
rlm@1 6879 reg[base].I = temp;
rlm@1 6880 }
rlm@1 6881 }
rlm@1 6882 break;
rlm@1 6883
rlm@1 6884 CASE_16(0x910)
rlm@1 6885 {
rlm@1 6886 // LDMDB Rn, {Rlist}
rlm@1 6887 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6888 u32 temp = reg[base].I -
rlm@1 6889 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6890 u32 address = temp & 0xFFFFFFFC;
rlm@1 6891 clockTicks += 2;
rlm@1 6892 int offset = 0;
rlm@1 6893 LDM_REG(1, 0);
rlm@1 6894 LDM_REG(2, 1);
rlm@1 6895 LDM_REG(4, 2);
rlm@1 6896 LDM_REG(8, 3);
rlm@1 6897 LDM_REG(16, 4);
rlm@1 6898 LDM_REG(32, 5);
rlm@1 6899 LDM_REG(64, 6);
rlm@1 6900 LDM_REG(128, 7);
rlm@1 6901 LDM_REG(256, 8);
rlm@1 6902 LDM_REG(512, 9);
rlm@1 6903 LDM_REG(1024, 10);
rlm@1 6904 LDM_REG(2048, 11);
rlm@1 6905 LDM_REG(4096, 12);
rlm@1 6906 LDM_REG(8192, 13);
rlm@1 6907 LDM_REG(16384, 14);
rlm@1 6908 if (opcode & 32768)
rlm@1 6909 {
rlm@1 6910 reg[15].I = CPUReadMemory(address);
rlm@1 6911 if (!offset)
rlm@1 6912 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6913 else
rlm@1 6914 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6915 armNextPC = reg[15].I;
rlm@1 6916 reg[15].I += 4;
rlm@1 6917 }
rlm@1 6918 }
rlm@1 6919 break;
rlm@1 6920 CASE_16(0x930)
rlm@1 6921 {
rlm@1 6922 // LDMDB Rn!, {Rlist}
rlm@1 6923 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6924 u32 temp = reg[base].I -
rlm@1 6925 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6926 u32 address = temp & 0xFFFFFFFC;
rlm@1 6927 clockTicks += 2;
rlm@1 6928 int offset = 0;
rlm@1 6929 LDM_REG(1, 0);
rlm@1 6930 LDM_REG(2, 1);
rlm@1 6931 LDM_REG(4, 2);
rlm@1 6932 LDM_REG(8, 3);
rlm@1 6933 LDM_REG(16, 4);
rlm@1 6934 LDM_REG(32, 5);
rlm@1 6935 LDM_REG(64, 6);
rlm@1 6936 LDM_REG(128, 7);
rlm@1 6937 LDM_REG(256, 8);
rlm@1 6938 LDM_REG(512, 9);
rlm@1 6939 LDM_REG(1024, 10);
rlm@1 6940 LDM_REG(2048, 11);
rlm@1 6941 LDM_REG(4096, 12);
rlm@1 6942 LDM_REG(8192, 13);
rlm@1 6943 LDM_REG(16384, 14);
rlm@1 6944 if (opcode & 32768)
rlm@1 6945 {
rlm@1 6946 reg[15].I = CPUReadMemory(address);
rlm@1 6947 if (!offset)
rlm@1 6948 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6949 else
rlm@1 6950 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6951 armNextPC = reg[15].I;
rlm@1 6952 reg[15].I += 4;
rlm@1 6953 }
rlm@1 6954 if (!(opcode & (1 << base)))
rlm@1 6955 reg[base].I = temp;
rlm@1 6956 }
rlm@1 6957 break;
rlm@1 6958 CASE_16(0x950)
rlm@1 6959 {
rlm@1 6960 // LDMDB Rn, {Rlist}^
rlm@1 6961 int base = (opcode & 0x000F0000) >> 16;
rlm@1 6962 u32 temp = reg[base].I -
rlm@1 6963 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 6964 u32 address = temp & 0xFFFFFFFC;
rlm@1 6965 clockTicks += 2;
rlm@1 6966 int offset = 0;
rlm@1 6967 if (opcode & 0x8000)
rlm@1 6968 {
rlm@1 6969 LDM_REG(1, 0);
rlm@1 6970 LDM_REG(2, 1);
rlm@1 6971 LDM_REG(4, 2);
rlm@1 6972 LDM_REG(8, 3);
rlm@1 6973 LDM_REG(16, 4);
rlm@1 6974 LDM_REG(32, 5);
rlm@1 6975 LDM_REG(64, 6);
rlm@1 6976 LDM_REG(128, 7);
rlm@1 6977 LDM_REG(256, 8);
rlm@1 6978 LDM_REG(512, 9);
rlm@1 6979 LDM_REG(1024, 10);
rlm@1 6980 LDM_REG(2048, 11);
rlm@1 6981 LDM_REG(4096, 12);
rlm@1 6982 LDM_REG(8192, 13);
rlm@1 6983 LDM_REG(16384, 14);
rlm@1 6984
rlm@1 6985 reg[15].I = CPUReadMemory(address);
rlm@1 6986 if (!offset)
rlm@1 6987 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 6988 else
rlm@1 6989 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 6990
rlm@1 6991 CPUSwitchMode(reg[17].I & 0x1f, false);
rlm@1 6992 if (armState)
rlm@1 6993 {
rlm@1 6994 armNextPC = reg[15].I & 0xFFFFFFFC;
rlm@1 6995 reg[15].I = armNextPC + 4;
rlm@1 6996 }
rlm@1 6997 else
rlm@1 6998 {
rlm@1 6999 armNextPC = reg[15].I & 0xFFFFFFFE;
rlm@1 7000 reg[15].I = armNextPC + 2;
rlm@1 7001 }
rlm@1 7002 }
rlm@1 7003 else
rlm@1 7004 {
rlm@1 7005 LDM_REG(1, 0);
rlm@1 7006 LDM_REG(2, 1);
rlm@1 7007 LDM_REG(4, 2);
rlm@1 7008 LDM_REG(8, 3);
rlm@1 7009 LDM_REG(16, 4);
rlm@1 7010 LDM_REG(32, 5);
rlm@1 7011 LDM_REG(64, 6);
rlm@1 7012 LDM_REG(128, 7);
rlm@1 7013
rlm@1 7014 if (armMode == 0x11)
rlm@1 7015 {
rlm@1 7016 LDM_REG(256, R8_FIQ);
rlm@1 7017 LDM_REG(512, R9_FIQ);
rlm@1 7018 LDM_REG(1024, R10_FIQ);
rlm@1 7019 LDM_REG(2048, R11_FIQ);
rlm@1 7020 LDM_REG(4096, R12_FIQ);
rlm@1 7021 }
rlm@1 7022 else
rlm@1 7023 {
rlm@1 7024 LDM_REG(256, 8);
rlm@1 7025 LDM_REG(512, 9);
rlm@1 7026 LDM_REG(1024, 10);
rlm@1 7027 LDM_REG(2048, 11);
rlm@1 7028 LDM_REG(4096, 12);
rlm@1 7029 }
rlm@1 7030
rlm@1 7031 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 7032 {
rlm@1 7033 LDM_REG(8192, R13_USR);
rlm@1 7034 LDM_REG(16384, R14_USR);
rlm@1 7035 }
rlm@1 7036 else
rlm@1 7037 {
rlm@1 7038 LDM_REG(8192, 13);
rlm@1 7039 LDM_REG(16384, 14);
rlm@1 7040 }
rlm@1 7041 }
rlm@1 7042 }
rlm@1 7043 break;
rlm@1 7044 CASE_16(0x970)
rlm@1 7045 {
rlm@1 7046 // LDMDB Rn!, {Rlist}^
rlm@1 7047 int base = (opcode & 0x000F0000) >> 16;
rlm@1 7048 u32 temp = reg[base].I -
rlm@1 7049 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 7050 u32 address = temp & 0xFFFFFFFC;
rlm@1 7051 clockTicks += 2;
rlm@1 7052 int offset = 0;
rlm@1 7053 if (opcode & 0x8000)
rlm@1 7054 {
rlm@1 7055 LDM_REG(1, 0);
rlm@1 7056 LDM_REG(2, 1);
rlm@1 7057 LDM_REG(4, 2);
rlm@1 7058 LDM_REG(8, 3);
rlm@1 7059 LDM_REG(16, 4);
rlm@1 7060 LDM_REG(32, 5);
rlm@1 7061 LDM_REG(64, 6);
rlm@1 7062 LDM_REG(128, 7);
rlm@1 7063 LDM_REG(256, 8);
rlm@1 7064 LDM_REG(512, 9);
rlm@1 7065 LDM_REG(1024, 10);
rlm@1 7066 LDM_REG(2048, 11);
rlm@1 7067 LDM_REG(4096, 12);
rlm@1 7068 LDM_REG(8192, 13);
rlm@1 7069 LDM_REG(16384, 14);
rlm@1 7070
rlm@1 7071 reg[15].I = CPUReadMemory(address);
rlm@1 7072 if (!offset)
rlm@1 7073 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 7074 else
rlm@1 7075 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 7076
rlm@1 7077 if (!(opcode & (1 << base)))
rlm@1 7078 reg[base].I = temp;
rlm@1 7079
rlm@1 7080 CPUSwitchMode(reg[17].I & 0x1f, false);
rlm@1 7081 if (armState)
rlm@1 7082 {
rlm@1 7083 armNextPC = reg[15].I & 0xFFFFFFFC;
rlm@1 7084 reg[15].I = armNextPC + 4;
rlm@1 7085 }
rlm@1 7086 else
rlm@1 7087 {
rlm@1 7088 armNextPC = reg[15].I & 0xFFFFFFFE;
rlm@1 7089 reg[15].I = armNextPC + 2;
rlm@1 7090 }
rlm@1 7091 }
rlm@1 7092 else
rlm@1 7093 {
rlm@1 7094 LDM_REG(1, 0);
rlm@1 7095 LDM_REG(2, 1);
rlm@1 7096 LDM_REG(4, 2);
rlm@1 7097 LDM_REG(8, 3);
rlm@1 7098 LDM_REG(16, 4);
rlm@1 7099 LDM_REG(32, 5);
rlm@1 7100 LDM_REG(64, 6);
rlm@1 7101 LDM_REG(128, 7);
rlm@1 7102
rlm@1 7103 if (armMode == 0x11)
rlm@1 7104 {
rlm@1 7105 LDM_REG(256, R8_FIQ);
rlm@1 7106 LDM_REG(512, R9_FIQ);
rlm@1 7107 LDM_REG(1024, R10_FIQ);
rlm@1 7108 LDM_REG(2048, R11_FIQ);
rlm@1 7109 LDM_REG(4096, R12_FIQ);
rlm@1 7110 }
rlm@1 7111 else
rlm@1 7112 {
rlm@1 7113 LDM_REG(256, 8);
rlm@1 7114 LDM_REG(512, 9);
rlm@1 7115 LDM_REG(1024, 10);
rlm@1 7116 LDM_REG(2048, 11);
rlm@1 7117 LDM_REG(4096, 12);
rlm@1 7118 }
rlm@1 7119
rlm@1 7120 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 7121 {
rlm@1 7122 LDM_REG(8192, R13_USR);
rlm@1 7123 LDM_REG(16384, R14_USR);
rlm@1 7124 }
rlm@1 7125 else
rlm@1 7126 {
rlm@1 7127 LDM_REG(8192, 13);
rlm@1 7128 LDM_REG(16384, 14);
rlm@1 7129 }
rlm@1 7130
rlm@1 7131 if (!(opcode & (1 << base)))
rlm@1 7132 reg[base].I = temp;
rlm@1 7133 }
rlm@1 7134 }
rlm@1 7135 break;
rlm@1 7136
rlm@1 7137 CASE_16(0x990)
rlm@1 7138 {
rlm@1 7139 // LDMIB Rn, {Rlist}
rlm@1 7140 int base = (opcode & 0x000F0000) >> 16;
rlm@1 7141 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
rlm@1 7142 clockTicks += 2;
rlm@1 7143 int offset = 0;
rlm@1 7144 LDM_REG(1, 0);
rlm@1 7145 LDM_REG(2, 1);
rlm@1 7146 LDM_REG(4, 2);
rlm@1 7147 LDM_REG(8, 3);
rlm@1 7148 LDM_REG(16, 4);
rlm@1 7149 LDM_REG(32, 5);
rlm@1 7150 LDM_REG(64, 6);
rlm@1 7151 LDM_REG(128, 7);
rlm@1 7152 LDM_REG(256, 8);
rlm@1 7153 LDM_REG(512, 9);
rlm@1 7154 LDM_REG(1024, 10);
rlm@1 7155 LDM_REG(2048, 11);
rlm@1 7156 LDM_REG(4096, 12);
rlm@1 7157 LDM_REG(8192, 13);
rlm@1 7158 LDM_REG(16384, 14);
rlm@1 7159 if (opcode & 32768)
rlm@1 7160 {
rlm@1 7161 reg[15].I = CPUReadMemory(address);
rlm@1 7162 if (!offset)
rlm@1 7163 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 7164 else
rlm@1 7165 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 7166 armNextPC = reg[15].I;
rlm@1 7167 reg[15].I += 4;
rlm@1 7168 }
rlm@1 7169 }
rlm@1 7170 break;
rlm@1 7171 CASE_16(0x9b0)
rlm@1 7172 {
rlm@1 7173 // LDMIB Rn!, {Rlist}
rlm@1 7174 int base = (opcode & 0x000F0000) >> 16;
rlm@1 7175 u32 temp = reg[base].I +
rlm@1 7176 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 7177 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
rlm@1 7178 clockTicks += 2;
rlm@1 7179 int offset = 0;
rlm@1 7180 LDM_REG(1, 0);
rlm@1 7181 LDM_REG(2, 1);
rlm@1 7182 LDM_REG(4, 2);
rlm@1 7183 LDM_REG(8, 3);
rlm@1 7184 LDM_REG(16, 4);
rlm@1 7185 LDM_REG(32, 5);
rlm@1 7186 LDM_REG(64, 6);
rlm@1 7187 LDM_REG(128, 7);
rlm@1 7188 LDM_REG(256, 8);
rlm@1 7189 LDM_REG(512, 9);
rlm@1 7190 LDM_REG(1024, 10);
rlm@1 7191 LDM_REG(2048, 11);
rlm@1 7192 LDM_REG(4096, 12);
rlm@1 7193 LDM_REG(8192, 13);
rlm@1 7194 LDM_REG(16384, 14);
rlm@1 7195 if (opcode & 32768)
rlm@1 7196 {
rlm@1 7197 reg[15].I = CPUReadMemory(address);
rlm@1 7198 if (!offset)
rlm@1 7199 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 7200 else
rlm@1 7201 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 7202 armNextPC = reg[15].I;
rlm@1 7203 reg[15].I += 4;
rlm@1 7204 }
rlm@1 7205 if (!(opcode & (1 << base)))
rlm@1 7206 reg[base].I = temp;
rlm@1 7207 }
rlm@1 7208 break;
rlm@1 7209 CASE_16(0x9d0)
rlm@1 7210 {
rlm@1 7211 // LDMIB Rn, {Rlist}^
rlm@1 7212 int base = (opcode & 0x000F0000) >> 16;
rlm@1 7213 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
rlm@1 7214 clockTicks += 2;
rlm@1 7215 int offset = 0;
rlm@1 7216 if (opcode & 0x8000)
rlm@1 7217 {
rlm@1 7218 LDM_REG(1, 0);
rlm@1 7219 LDM_REG(2, 1);
rlm@1 7220 LDM_REG(4, 2);
rlm@1 7221 LDM_REG(8, 3);
rlm@1 7222 LDM_REG(16, 4);
rlm@1 7223 LDM_REG(32, 5);
rlm@1 7224 LDM_REG(64, 6);
rlm@1 7225 LDM_REG(128, 7);
rlm@1 7226 LDM_REG(256, 8);
rlm@1 7227 LDM_REG(512, 9);
rlm@1 7228 LDM_REG(1024, 10);
rlm@1 7229 LDM_REG(2048, 11);
rlm@1 7230 LDM_REG(4096, 12);
rlm@1 7231 LDM_REG(8192, 13);
rlm@1 7232 LDM_REG(16384, 14);
rlm@1 7233
rlm@1 7234 reg[15].I = CPUReadMemory(address);
rlm@1 7235 if (!offset)
rlm@1 7236 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 7237 else
rlm@1 7238 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 7239
rlm@1 7240 CPUSwitchMode(reg[17].I & 0x1f, false);
rlm@1 7241 if (armState)
rlm@1 7242 {
rlm@1 7243 armNextPC = reg[15].I & 0xFFFFFFFC;
rlm@1 7244 reg[15].I = armNextPC + 4;
rlm@1 7245 }
rlm@1 7246 else
rlm@1 7247 {
rlm@1 7248 armNextPC = reg[15].I & 0xFFFFFFFE;
rlm@1 7249 reg[15].I = armNextPC + 2;
rlm@1 7250 }
rlm@1 7251 }
rlm@1 7252 else
rlm@1 7253 {
rlm@1 7254 LDM_REG(1, 0);
rlm@1 7255 LDM_REG(2, 1);
rlm@1 7256 LDM_REG(4, 2);
rlm@1 7257 LDM_REG(8, 3);
rlm@1 7258 LDM_REG(16, 4);
rlm@1 7259 LDM_REG(32, 5);
rlm@1 7260 LDM_REG(64, 6);
rlm@1 7261 LDM_REG(128, 7);
rlm@1 7262
rlm@1 7263 if (armMode == 0x11)
rlm@1 7264 {
rlm@1 7265 LDM_REG(256, R8_FIQ);
rlm@1 7266 LDM_REG(512, R9_FIQ);
rlm@1 7267 LDM_REG(1024, R10_FIQ);
rlm@1 7268 LDM_REG(2048, R11_FIQ);
rlm@1 7269 LDM_REG(4096, R12_FIQ);
rlm@1 7270 }
rlm@1 7271 else
rlm@1 7272 {
rlm@1 7273 LDM_REG(256, 8);
rlm@1 7274 LDM_REG(512, 9);
rlm@1 7275 LDM_REG(1024, 10);
rlm@1 7276 LDM_REG(2048, 11);
rlm@1 7277 LDM_REG(4096, 12);
rlm@1 7278 }
rlm@1 7279
rlm@1 7280 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 7281 {
rlm@1 7282 LDM_REG(8192, R13_USR);
rlm@1 7283 LDM_REG(16384, R14_USR);
rlm@1 7284 }
rlm@1 7285 else
rlm@1 7286 {
rlm@1 7287 LDM_REG(8192, 13);
rlm@1 7288 LDM_REG(16384, 14);
rlm@1 7289 }
rlm@1 7290 }
rlm@1 7291 }
rlm@1 7292 break;
rlm@1 7293 CASE_16(0x9f0)
rlm@1 7294 {
rlm@1 7295 // LDMIB Rn!, {Rlist}^
rlm@1 7296 int base = (opcode & 0x000F0000) >> 16;
rlm@1 7297 u32 temp = reg[base].I +
rlm@1 7298 4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
rlm@1 7299 u32 address = (reg[base].I + 4) & 0xFFFFFFFC;
rlm@1 7300 clockTicks += 2;
rlm@1 7301 int offset = 0;
rlm@1 7302 if (opcode & 0x8000)
rlm@1 7303 {
rlm@1 7304 LDM_REG(1, 0);
rlm@1 7305 LDM_REG(2, 1);
rlm@1 7306 LDM_REG(4, 2);
rlm@1 7307 LDM_REG(8, 3);
rlm@1 7308 LDM_REG(16, 4);
rlm@1 7309 LDM_REG(32, 5);
rlm@1 7310 LDM_REG(64, 6);
rlm@1 7311 LDM_REG(128, 7);
rlm@1 7312 LDM_REG(256, 8);
rlm@1 7313 LDM_REG(512, 9);
rlm@1 7314 LDM_REG(1024, 10);
rlm@1 7315 LDM_REG(2048, 11);
rlm@1 7316 LDM_REG(4096, 12);
rlm@1 7317 LDM_REG(8192, 13);
rlm@1 7318 LDM_REG(16384, 14);
rlm@1 7319
rlm@1 7320 reg[15].I = CPUReadMemory(address);
rlm@1 7321 if (!offset)
rlm@1 7322 clockTicks += 2 + CPUUpdateTicksAccess32(address);
rlm@1 7323 else
rlm@1 7324 clockTicks += 2 + CPUUpdateTicksAccessSeq32(address);
rlm@1 7325
rlm@1 7326 if (!(opcode & (1 << base)))
rlm@1 7327 reg[base].I = temp;
rlm@1 7328
rlm@1 7329 CPUSwitchMode(reg[17].I & 0x1f, false);
rlm@1 7330 if (armState)
rlm@1 7331 {
rlm@1 7332 armNextPC = reg[15].I & 0xFFFFFFFC;
rlm@1 7333 reg[15].I = armNextPC + 4;
rlm@1 7334 }
rlm@1 7335 else
rlm@1 7336 {
rlm@1 7337 armNextPC = reg[15].I & 0xFFFFFFFE;
rlm@1 7338 reg[15].I = armNextPC + 2;
rlm@1 7339 }
rlm@1 7340 }
rlm@1 7341 else
rlm@1 7342 {
rlm@1 7343 LDM_REG(1, 0);
rlm@1 7344 LDM_REG(2, 1);
rlm@1 7345 LDM_REG(4, 2);
rlm@1 7346 LDM_REG(8, 3);
rlm@1 7347 LDM_REG(16, 4);
rlm@1 7348 LDM_REG(32, 5);
rlm@1 7349 LDM_REG(64, 6);
rlm@1 7350 LDM_REG(128, 7);
rlm@1 7351
rlm@1 7352 if (armMode == 0x11)
rlm@1 7353 {
rlm@1 7354 LDM_REG(256, R8_FIQ);
rlm@1 7355 LDM_REG(512, R9_FIQ);
rlm@1 7356 LDM_REG(1024, R10_FIQ);
rlm@1 7357 LDM_REG(2048, R11_FIQ);
rlm@1 7358 LDM_REG(4096, R12_FIQ);
rlm@1 7359 }
rlm@1 7360 else
rlm@1 7361 {
rlm@1 7362 LDM_REG(256, 8);
rlm@1 7363 LDM_REG(512, 9);
rlm@1 7364 LDM_REG(1024, 10);
rlm@1 7365 LDM_REG(2048, 11);
rlm@1 7366 LDM_REG(4096, 12);
rlm@1 7367 }
rlm@1 7368
rlm@1 7369 if (armMode != 0x10 && armMode != 0x1f)
rlm@1 7370 {
rlm@1 7371 LDM_REG(8192, R13_USR);
rlm@1 7372 LDM_REG(16384, R14_USR);
rlm@1 7373 }
rlm@1 7374 else
rlm@1 7375 {
rlm@1 7376 LDM_REG(8192, 13);
rlm@1 7377 LDM_REG(16384, 14);
rlm@1 7378 }
rlm@1 7379
rlm@1 7380 if (!(opcode & (1 << base)))
rlm@1 7381 reg[base].I = temp;
rlm@1 7382 }
rlm@1 7383 }
rlm@1 7384 break;
rlm@1 7385 CASE_256(0xa00)
rlm@1 7386 {
rlm@1 7387 // B <offset>
rlm@1 7388 clockTicks += 3;
rlm@1 7389 int offset = opcode & 0x00FFFFFF;
rlm@1 7390 if (offset & 0x00800000)
rlm@1 7391 {
rlm@1 7392 offset |= 0xFF000000;
rlm@1 7393 }
rlm@1 7394 offset <<= 2;
rlm@1 7395 reg[15].I += offset;
rlm@1 7396 armNextPC = reg[15].I;
rlm@1 7397 reg[15].I += 4;
rlm@1 7398 }
rlm@1 7399 break;
rlm@1 7400 CASE_256(0xb00)
rlm@1 7401 {
rlm@1 7402 // BL <offset>
rlm@1 7403 clockTicks += 3;
rlm@1 7404 int offset = opcode & 0x00FFFFFF;
rlm@1 7405 if (offset & 0x00800000)
rlm@1 7406 {
rlm@1 7407 offset |= 0xFF000000;
rlm@1 7408 }
rlm@1 7409 offset <<= 2;
rlm@1 7410 reg[14].I = reg[15].I - 4;
rlm@1 7411 reg[15].I += offset;
rlm@1 7412 armNextPC = reg[15].I;
rlm@1 7413 reg[15].I += 4;
rlm@1 7414 }
rlm@1 7415 break;
rlm@1 7416 CASE_256(0xf00)
rlm@1 7417 // SWI <comment>
rlm@1 7418 clockTicks += 3;
rlm@1 7419 CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
rlm@1 7420 break;
rlm@1 7421 #ifdef GP_SUPPORT
rlm@1 7422 case 0xe11:
rlm@1 7423 case 0xe13:
rlm@1 7424 case 0xe15:
rlm@1 7425 case 0xe17:
rlm@1 7426 case 0xe19:
rlm@1 7427 case 0xe1b:
rlm@1 7428 case 0xe1d:
rlm@1 7429 case 0xe1f:
rlm@1 7430 // MRC
rlm@1 7431 break;
rlm@1 7432 case 0xe01:
rlm@1 7433 case 0xe03:
rlm@1 7434 case 0xe05:
rlm@1 7435 case 0xe07:
rlm@1 7436 case 0xe09:
rlm@1 7437 case 0xe0b:
rlm@1 7438 case 0xe0d:
rlm@1 7439 case 0xe0f:
rlm@1 7440 // MRC
rlm@1 7441 break;
rlm@1 7442 #endif
rlm@1 7443 default:
rlm@1 7444 #ifdef GBA_LOGGING
rlm@1 7445 if (systemVerbose & VERBOSE_UNDEFINED)
rlm@1 7446 log("Undefined ARM instruction %08x at %08x\n", opcode,
rlm@1 7447 armNextPC - 4);
rlm@1 7448 #endif
rlm@1 7449 CPUUndefinedException();
rlm@1 7450 break;
rlm@1 7451 // END
rlm@1 7452 }
rlm@1 7453 }