annotate src/gba/thumb.h @ 268:82ee2704c973

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