diff options
| author | 2015-01-31 20:34:26 -0500 | |
|---|---|---|
| committer | 2015-01-31 20:43:03 -0500 | |
| commit | f44781fd7b0c5f99573e917ccdd92716a99a9b0d (patch) | |
| tree | ad31575f5653316488371cd654d961ce803e2c01 /src/core/arm/interpreter/armsupp.cpp | |
| parent | Merge pull request #512 from lioncash/assignment (diff) | |
| download | yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.gz yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.tar.xz yuzu-f44781fd7b0c5f99573e917ccdd92716a99a9b0d.zip | |
arm: Adios armemu
Diffstat (limited to 'src/core/arm/interpreter/armsupp.cpp')
| -rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 881 |
1 files changed, 12 insertions, 869 deletions
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index 5a8f09b22..fd90fb0a4 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp | |||
| @@ -20,395 +20,13 @@ | |||
| 20 | #include "core/arm/disassembler/arm_disasm.h" | 20 | #include "core/arm/disassembler/arm_disasm.h" |
| 21 | #include "core/mem_map.h" | 21 | #include "core/mem_map.h" |
| 22 | 22 | ||
| 23 | 23 | // Unsigned sum of absolute difference | |
| 24 | static ARMword ModeToBank (ARMword); | ||
| 25 | |||
| 26 | /* This routine returns the value of a register from a mode. */ | ||
| 27 | |||
| 28 | ARMword | ||
| 29 | ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg) | ||
| 30 | { | ||
| 31 | mode &= MODEBITS; | ||
| 32 | if (mode != state->Mode) | ||
| 33 | return (state->RegBank[ModeToBank ((ARMword) mode)][reg]); | ||
| 34 | else | ||
| 35 | return (state->Reg[reg]); | ||
| 36 | } | ||
| 37 | |||
| 38 | /* This routine sets the value of a register for a mode. */ | ||
| 39 | |||
| 40 | void | ||
| 41 | ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value) | ||
| 42 | { | ||
| 43 | mode &= MODEBITS; | ||
| 44 | if (mode != state->Mode) | ||
| 45 | state->RegBank[ModeToBank ((ARMword) mode)][reg] = value; | ||
| 46 | else | ||
| 47 | state->Reg[reg] = value; | ||
| 48 | } | ||
| 49 | |||
| 50 | /* This routine returns the value of the PC, mode independently. */ | ||
| 51 | |||
| 52 | ARMword | ||
| 53 | ARMul_GetPC (ARMul_State * state) | ||
| 54 | { | ||
| 55 | if (state->Mode > SVC26MODE) | ||
| 56 | return state->Reg[15]; | ||
| 57 | else | ||
| 58 | return R15PC; | ||
| 59 | } | ||
| 60 | |||
| 61 | /* This routine returns the value of the PC, mode independently. */ | ||
| 62 | |||
| 63 | ARMword | ||
| 64 | ARMul_GetNextPC (ARMul_State * state) | ||
| 65 | { | ||
| 66 | if (state->Mode > SVC26MODE) | ||
| 67 | return state->Reg[15] + INSN_SIZE; | ||
| 68 | else | ||
| 69 | return (state->Reg[15] + INSN_SIZE) & R15PCBITS; | ||
| 70 | } | ||
| 71 | |||
| 72 | /* This routine sets the value of the PC. */ | ||
| 73 | |||
| 74 | void | ||
| 75 | ARMul_SetPC (ARMul_State * state, ARMword value) | ||
| 76 | { | ||
| 77 | if (ARMul_MODE32BIT) | ||
| 78 | state->Reg[15] = value & PCBITS; | ||
| 79 | else | ||
| 80 | state->Reg[15] = R15CCINTMODE | (value & R15PCBITS); | ||
| 81 | FLUSHPIPE; | ||
| 82 | } | ||
| 83 | |||
| 84 | /* This routine returns the value of register 15, mode independently. */ | ||
| 85 | |||
| 86 | ARMword | ||
| 87 | ARMul_GetR15 (ARMul_State * state) | ||
| 88 | { | ||
| 89 | if (state->Mode > SVC26MODE) | ||
| 90 | return (state->Reg[15]); | ||
| 91 | else | ||
| 92 | return (R15PC | ECC | ER15INT | EMODE); | ||
| 93 | } | ||
| 94 | |||
| 95 | /* This routine sets the value of Register 15. */ | ||
| 96 | |||
| 97 | void | ||
| 98 | ARMul_SetR15 (ARMul_State * state, ARMword value) | ||
| 99 | { | ||
| 100 | if (ARMul_MODE32BIT) | ||
| 101 | state->Reg[15] = value & PCBITS; | ||
| 102 | else { | ||
| 103 | state->Reg[15] = value; | ||
| 104 | ARMul_R15Altered (state); | ||
| 105 | } | ||
| 106 | FLUSHPIPE; | ||
| 107 | } | ||
| 108 | |||
| 109 | /* This routine returns the value of the CPSR. */ | ||
| 110 | |||
| 111 | ARMword | ||
| 112 | ARMul_GetCPSR (ARMul_State * state) | ||
| 113 | { | ||
| 114 | //chy 2003-08-20: below is from gdb20030716, maybe isn't suitable for system simulator | ||
| 115 | //return (CPSR | state->Cpsr); for gdb20030716 | ||
| 116 | return (CPSR); //had be tested in old skyeye with gdb5.0-5.3 | ||
| 117 | } | ||
| 118 | |||
| 119 | /* This routine sets the value of the CPSR. */ | ||
| 120 | |||
| 121 | void | ||
| 122 | ARMul_SetCPSR (ARMul_State * state, ARMword value) | ||
| 123 | { | ||
| 124 | state->Cpsr = value; | ||
| 125 | ARMul_CPSRAltered (state); | ||
| 126 | } | ||
| 127 | |||
| 128 | /* This routine does all the nasty bits involved in a write to the CPSR, | ||
| 129 | including updating the register bank, given a MSR instruction. */ | ||
| 130 | |||
| 131 | void | ||
| 132 | ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) | ||
| 133 | { | ||
| 134 | state->Cpsr = ARMul_GetCPSR (state); | ||
| 135 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode | ||
| 136 | if (state->Mode != USER26MODE && state->Mode != USER32MODE ) { | ||
| 137 | /* In user mode, only write flags. */ | ||
| 138 | if (BIT (16)) | ||
| 139 | SETPSR_C (state->Cpsr, rhs); | ||
| 140 | if (BIT (17)) | ||
| 141 | SETPSR_X (state->Cpsr, rhs); | ||
| 142 | if (BIT (18)) | ||
| 143 | SETPSR_S (state->Cpsr, rhs); | ||
| 144 | } | ||
| 145 | if (BIT (19)) | ||
| 146 | SETPSR_F (state->Cpsr, rhs); | ||
| 147 | ARMul_CPSRAltered (state); | ||
| 148 | } | ||
| 149 | |||
| 150 | /* Get an SPSR from the specified mode. */ | ||
| 151 | |||
| 152 | ARMword | ||
| 153 | ARMul_GetSPSR (ARMul_State * state, ARMword mode) | ||
| 154 | { | ||
| 155 | ARMword bank = ModeToBank (mode & MODEBITS); | ||
| 156 | |||
| 157 | if (!BANK_CAN_ACCESS_SPSR (bank)) | ||
| 158 | return ARMul_GetCPSR (state); | ||
| 159 | |||
| 160 | return state->Spsr[bank]; | ||
| 161 | } | ||
| 162 | |||
| 163 | /* This routine does a write to an SPSR. */ | ||
| 164 | |||
| 165 | void | ||
| 166 | ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) | ||
| 167 | { | ||
| 168 | ARMword bank = ModeToBank (mode & MODEBITS); | ||
| 169 | |||
| 170 | if (BANK_CAN_ACCESS_SPSR (bank)) | ||
| 171 | state->Spsr[bank] = value; | ||
| 172 | } | ||
| 173 | |||
| 174 | /* This routine does a write to the current SPSR, given an MSR instruction. */ | ||
| 175 | |||
| 176 | void | ||
| 177 | ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs) | ||
| 178 | { | ||
| 179 | if (BANK_CAN_ACCESS_SPSR (state->Bank)) { | ||
| 180 | if (BIT (16)) | ||
| 181 | SETPSR_C (state->Spsr[state->Bank], rhs); | ||
| 182 | if (BIT (17)) | ||
| 183 | SETPSR_X (state->Spsr[state->Bank], rhs); | ||
| 184 | if (BIT (18)) | ||
| 185 | SETPSR_S (state->Spsr[state->Bank], rhs); | ||
| 186 | if (BIT (19)) | ||
| 187 | SETPSR_F (state->Spsr[state->Bank], rhs); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | /* This routine updates the state of the emulator after the Cpsr has been | ||
| 192 | changed. Both the processor flags and register bank are updated. */ | ||
| 193 | |||
| 194 | void | ||
| 195 | ARMul_CPSRAltered (ARMul_State * state) | ||
| 196 | { | ||
| 197 | ARMword oldmode; | ||
| 198 | |||
| 199 | if (state->prog32Sig == LOW) | ||
| 200 | state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS); | ||
| 201 | |||
| 202 | oldmode = state->Mode; | ||
| 203 | |||
| 204 | /*if (state->Mode != (state->Cpsr & MODEBITS)) { | ||
| 205 | state->Mode = | ||
| 206 | ARMul_SwitchMode (state, state->Mode, | ||
| 207 | state->Cpsr & MODEBITS); | ||
| 208 | |||
| 209 | state->NtransSig = (state->Mode & 3) ? HIGH : LOW; | ||
| 210 | }*/ | ||
| 211 | //state->Cpsr &= ~MODEBITS; | ||
| 212 | |||
| 213 | ASSIGNINT (state->Cpsr & INTBITS); | ||
| 214 | //state->Cpsr &= ~INTBITS; | ||
| 215 | ASSIGNN ((state->Cpsr & NBIT) != 0); | ||
| 216 | //state->Cpsr &= ~NBIT; | ||
| 217 | ASSIGNZ ((state->Cpsr & ZBIT) != 0); | ||
| 218 | //state->Cpsr &= ~ZBIT; | ||
| 219 | ASSIGNC ((state->Cpsr & CBIT) != 0); | ||
| 220 | //state->Cpsr &= ~CBIT; | ||
| 221 | ASSIGNV ((state->Cpsr & VBIT) != 0); | ||
| 222 | //state->Cpsr &= ~VBIT; | ||
| 223 | ASSIGNQ ((state->Cpsr & QBIT) != 0); | ||
| 224 | //state->Cpsr &= ~QBIT; | ||
| 225 | state->GEFlag = (state->Cpsr & 0x000F0000); | ||
| 226 | #ifdef MODET | ||
| 227 | ASSIGNT ((state->Cpsr & TBIT) != 0); | ||
| 228 | //state->Cpsr &= ~TBIT; | ||
| 229 | #endif | ||
| 230 | |||
| 231 | if (oldmode > SVC26MODE) { | ||
| 232 | if (state->Mode <= SVC26MODE) { | ||
| 233 | state->Emulate = CHANGEMODE; | ||
| 234 | state->Reg[15] = ECC | ER15INT | EMODE | R15PC; | ||
| 235 | } | ||
| 236 | } else { | ||
| 237 | if (state->Mode > SVC26MODE) { | ||
| 238 | state->Emulate = CHANGEMODE; | ||
| 239 | state->Reg[15] = R15PC; | ||
| 240 | } else | ||
| 241 | state->Reg[15] = ECC | ER15INT | EMODE | R15PC; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | /* This routine updates the state of the emulator after register 15 has | ||
| 246 | been changed. Both the processor flags and register bank are updated. | ||
| 247 | This routine should only be called from a 26 bit mode. */ | ||
| 248 | |||
| 249 | void | ||
| 250 | ARMul_R15Altered (ARMul_State * state) | ||
| 251 | { | ||
| 252 | if (state->Mode != R15MODE) { | ||
| 253 | state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE); | ||
| 254 | state->NtransSig = (state->Mode & 3) ? HIGH : LOW; | ||
| 255 | } | ||
| 256 | |||
| 257 | if (state->Mode > SVC26MODE) | ||
| 258 | state->Emulate = CHANGEMODE; | ||
| 259 | |||
| 260 | ASSIGNR15INT (R15INT); | ||
| 261 | |||
| 262 | ASSIGNN ((state->Reg[15] & NBIT) != 0); | ||
| 263 | ASSIGNZ ((state->Reg[15] & ZBIT) != 0); | ||
| 264 | ASSIGNC ((state->Reg[15] & CBIT) != 0); | ||
| 265 | ASSIGNV ((state->Reg[15] & VBIT) != 0); | ||
| 266 | } | ||
| 267 | |||
| 268 | /* This routine controls the saving and restoring of registers across mode | ||
| 269 | changes. The regbank matrix is largely unused, only rows 13 and 14 are | ||
| 270 | used across all modes, 8 to 14 are used for FIQ, all others use the USER | ||
| 271 | column. It's easier this way. old and new parameter are modes numbers. | ||
| 272 | Notice the side effect of changing the Bank variable. */ | ||
| 273 | |||
| 274 | ARMword | ||
| 275 | ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) | ||
| 276 | { | ||
| 277 | unsigned i; | ||
| 278 | ARMword oldbank; | ||
| 279 | ARMword newbank; | ||
| 280 | static int revision_value = 53; | ||
| 281 | |||
| 282 | oldbank = ModeToBank (oldmode); | ||
| 283 | newbank = state->Bank = ModeToBank (newmode); | ||
| 284 | |||
| 285 | /* Do we really need to do it? */ | ||
| 286 | if (oldbank != newbank) { | ||
| 287 | if (oldbank == 3 && newbank == 2) { | ||
| 288 | //printf("icounter is %d PC is %x MODE CHANGED : %d --> %d\n", state->NumInstrs, state->pc, oldbank, newbank); | ||
| 289 | if (state->NumInstrs >= 5832487) { | ||
| 290 | // printf("%d, ", state->NumInstrs + revision_value); | ||
| 291 | // printf("revision_value : %d\n", revision_value); | ||
| 292 | revision_value ++; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | /* Save away the old registers. */ | ||
| 296 | switch (oldbank) { | ||
| 297 | case USERBANK: | ||
| 298 | case IRQBANK: | ||
| 299 | case SVCBANK: | ||
| 300 | case ABORTBANK: | ||
| 301 | case UNDEFBANK: | ||
| 302 | if (newbank == FIQBANK) | ||
| 303 | for (i = 8; i < 13; i++) | ||
| 304 | state->RegBank[USERBANK][i] = | ||
| 305 | state->Reg[i]; | ||
| 306 | state->RegBank[oldbank][13] = state->Reg[13]; | ||
| 307 | state->RegBank[oldbank][14] = state->Reg[14]; | ||
| 308 | break; | ||
| 309 | case FIQBANK: | ||
| 310 | for (i = 8; i < 15; i++) | ||
| 311 | state->RegBank[FIQBANK][i] = state->Reg[i]; | ||
| 312 | break; | ||
| 313 | case DUMMYBANK: | ||
| 314 | for (i = 8; i < 15; i++) | ||
| 315 | state->RegBank[DUMMYBANK][i] = 0; | ||
| 316 | break; | ||
| 317 | default: | ||
| 318 | abort (); | ||
| 319 | } | ||
| 320 | |||
| 321 | /* Restore the new registers. */ | ||
| 322 | switch (newbank) { | ||
| 323 | case USERBANK: | ||
| 324 | case IRQBANK: | ||
| 325 | case SVCBANK: | ||
| 326 | case ABORTBANK: | ||
| 327 | case UNDEFBANK: | ||
| 328 | if (oldbank == FIQBANK) | ||
| 329 | for (i = 8; i < 13; i++) | ||
| 330 | state->Reg[i] = | ||
| 331 | state->RegBank[USERBANK][i]; | ||
| 332 | state->Reg[13] = state->RegBank[newbank][13]; | ||
| 333 | state->Reg[14] = state->RegBank[newbank][14]; | ||
| 334 | break; | ||
| 335 | case FIQBANK: | ||
| 336 | for (i = 8; i < 15; i++) | ||
| 337 | state->Reg[i] = state->RegBank[FIQBANK][i]; | ||
| 338 | break; | ||
| 339 | case DUMMYBANK: | ||
| 340 | for (i = 8; i < 15; i++) | ||
| 341 | state->Reg[i] = 0; | ||
| 342 | break; | ||
| 343 | default: | ||
| 344 | abort (); | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | return newmode; | ||
| 349 | } | ||
| 350 | |||
| 351 | /* Given a processor mode, this routine returns the | ||
| 352 | register bank that will be accessed in that mode. */ | ||
| 353 | |||
| 354 | static ARMword | ||
| 355 | ModeToBank (ARMword mode) | ||
| 356 | { | ||
| 357 | static ARMword bankofmode[] = { | ||
| 358 | USERBANK, FIQBANK, IRQBANK, SVCBANK, | ||
| 359 | DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, | ||
| 360 | DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, | ||
| 361 | DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, | ||
| 362 | USERBANK, FIQBANK, IRQBANK, SVCBANK, | ||
| 363 | DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK, | ||
| 364 | DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK, | ||
| 365 | DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK | ||
| 366 | }; | ||
| 367 | |||
| 368 | if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0]))) | ||
| 369 | return DUMMYBANK; | ||
| 370 | |||
| 371 | return bankofmode[mode]; | ||
| 372 | } | ||
| 373 | |||
| 374 | /* Returns the register number of the nth register in a reg list. */ | ||
| 375 | |||
| 376 | unsigned | ||
| 377 | ARMul_NthReg (ARMword instr, unsigned number) | ||
| 378 | { | ||
| 379 | unsigned bit, upto; | ||
| 380 | |||
| 381 | for (bit = 0, upto = 0; upto <= number; bit++) | ||
| 382 | if (BIT (bit)) | ||
| 383 | upto++; | ||
| 384 | |||
| 385 | return (bit - 1); | ||
| 386 | } | ||
| 387 | |||
| 388 | /* Unsigned sum of absolute difference */ | ||
| 389 | u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) | 24 | u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) |
| 390 | { | 25 | { |
| 391 | if (left > right) | 26 | if (left > right) |
| 392 | return left - right; | 27 | return left - right; |
| 393 | 28 | ||
| 394 | return right - left; | 29 | return right - left; |
| 395 | } | ||
| 396 | |||
| 397 | /* Assigns the N and Z flags depending on the value of result. */ | ||
| 398 | |||
| 399 | void | ||
| 400 | ARMul_NegZero (ARMul_State * state, ARMword result) | ||
| 401 | { | ||
| 402 | if (NEG (result)) { | ||
| 403 | SETN; | ||
| 404 | CLEARZ; | ||
| 405 | } else if (result == 0) { | ||
| 406 | CLEARN; | ||
| 407 | SETZ; | ||
| 408 | } else { | ||
| 409 | CLEARN; | ||
| 410 | CLEARZ; | ||
| 411 | } | ||
| 412 | } | 30 | } |
| 413 | 31 | ||
| 414 | // Add with carry, indicates if a carry-out or signed overflow occurred. | 32 | // Add with carry, indicates if a carry-out or signed overflow occurred. |
| @@ -441,23 +59,6 @@ bool SubOverflow(ARMword a, ARMword b, ARMword result) | |||
| 441 | (POS(a) && NEG(b) && NEG(result))); | 59 | (POS(a) && NEG(b) && NEG(result))); |
| 442 | } | 60 | } |
| 443 | 61 | ||
| 444 | /* Assigns the C flag after an addition of a and b to give result. */ | ||
| 445 | |||
| 446 | void | ||
| 447 | ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||
| 448 | { | ||
| 449 | ASSIGNC ((NEG (a) && NEG (b)) || | ||
| 450 | (NEG (a) && POS (result)) || (NEG (b) && POS (result))); | ||
| 451 | } | ||
| 452 | |||
| 453 | /* Assigns the V flag after an addition of a and b to give result. */ | ||
| 454 | |||
| 455 | void | ||
| 456 | ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||
| 457 | { | ||
| 458 | ASSIGNV (AddOverflow (a, b, result)); | ||
| 459 | } | ||
| 460 | |||
| 461 | // Returns true if the Q flag should be set as a result of overflow. | 62 | // Returns true if the Q flag should be set as a result of overflow. |
| 462 | bool ARMul_AddOverflowQ(ARMword a, ARMword b) | 63 | bool ARMul_AddOverflowQ(ARMword a, ARMword b) |
| 463 | { | 64 | { |
| @@ -468,24 +69,7 @@ bool ARMul_AddOverflowQ(ARMword a, ARMword b) | |||
| 468 | return false; | 69 | return false; |
| 469 | } | 70 | } |
| 470 | 71 | ||
| 471 | /* Assigns the C flag after an subtraction of a and b to give result. */ | 72 | // 8-bit signed saturated addition |
| 472 | |||
| 473 | void | ||
| 474 | ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||
| 475 | { | ||
| 476 | ASSIGNC ((NEG (a) && POS (b)) || | ||
| 477 | (NEG (a) && POS (result)) || (POS (b) && POS (result))); | ||
| 478 | } | ||
| 479 | |||
| 480 | /* Assigns the V flag after an subtraction of a and b to give result. */ | ||
| 481 | |||
| 482 | void | ||
| 483 | ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) | ||
| 484 | { | ||
| 485 | ASSIGNV (SubOverflow (a, b, result)); | ||
| 486 | } | ||
| 487 | |||
| 488 | /* 8-bit signed saturated addition */ | ||
| 489 | u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) | 73 | u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) |
| 490 | { | 74 | { |
| 491 | u8 result = left + right; | 75 | u8 result = left + right; |
| @@ -500,7 +84,7 @@ u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) | |||
| 500 | return result; | 84 | return result; |
| 501 | } | 85 | } |
| 502 | 86 | ||
| 503 | /* 8-bit signed saturated subtraction */ | 87 | // 8-bit signed saturated subtraction |
| 504 | u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) | 88 | u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) |
| 505 | { | 89 | { |
| 506 | u8 result = left - right; | 90 | u8 result = left - right; |
| @@ -515,7 +99,7 @@ u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) | |||
| 515 | return result; | 99 | return result; |
| 516 | } | 100 | } |
| 517 | 101 | ||
| 518 | /* 16-bit signed saturated addition */ | 102 | // 16-bit signed saturated addition |
| 519 | u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) | 103 | u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) |
| 520 | { | 104 | { |
| 521 | u16 result = left + right; | 105 | u16 result = left + right; |
| @@ -530,7 +114,7 @@ u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) | |||
| 530 | return result; | 114 | return result; |
| 531 | } | 115 | } |
| 532 | 116 | ||
| 533 | /* 16-bit signed saturated subtraction */ | 117 | // 16-bit signed saturated subtraction |
| 534 | u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) | 118 | u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) |
| 535 | { | 119 | { |
| 536 | u16 result = left - right; | 120 | u16 result = left - right; |
| @@ -545,7 +129,7 @@ u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) | |||
| 545 | return result; | 129 | return result; |
| 546 | } | 130 | } |
| 547 | 131 | ||
| 548 | /* 8-bit unsigned saturated addition */ | 132 | // 8-bit unsigned saturated addition |
| 549 | u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) | 133 | u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) |
| 550 | { | 134 | { |
| 551 | u8 result = left + right; | 135 | u8 result = left + right; |
| @@ -556,7 +140,7 @@ u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) | |||
| 556 | return result; | 140 | return result; |
| 557 | } | 141 | } |
| 558 | 142 | ||
| 559 | /* 16-bit unsigned saturated addition */ | 143 | // 16-bit unsigned saturated addition |
| 560 | u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) | 144 | u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) |
| 561 | { | 145 | { |
| 562 | u16 result = left + right; | 146 | u16 result = left + right; |
| @@ -567,7 +151,7 @@ u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) | |||
| 567 | return result; | 151 | return result; |
| 568 | } | 152 | } |
| 569 | 153 | ||
| 570 | /* 8-bit unsigned saturated subtraction */ | 154 | // 8-bit unsigned saturated subtraction |
| 571 | u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) | 155 | u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) |
| 572 | { | 156 | { |
| 573 | if (left <= right) | 157 | if (left <= right) |
| @@ -576,7 +160,7 @@ u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) | |||
| 576 | return left - right; | 160 | return left - right; |
| 577 | } | 161 | } |
| 578 | 162 | ||
| 579 | /* 16-bit unsigned saturated subtraction */ | 163 | // 16-bit unsigned saturated subtraction |
| 580 | u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) | 164 | u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) |
| 581 | { | 165 | { |
| 582 | if (left <= right) | 166 | if (left <= right) |
| @@ -620,444 +204,3 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | |||
| 620 | *saturation_occurred = false; | 204 | *saturation_occurred = false; |
| 621 | return (u32)value; | 205 | return (u32)value; |
| 622 | } | 206 | } |
| 623 | |||
| 624 | /* This function does the work of generating the addresses used in an | ||
| 625 | LDC instruction. The code here is always post-indexed, it's up to the | ||
| 626 | caller to get the input address correct and to handle base register | ||
| 627 | modification. It also handles the Busy-Waiting. */ | ||
| 628 | |||
| 629 | void | ||
| 630 | ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address) | ||
| 631 | { | ||
| 632 | unsigned cpab; | ||
| 633 | ARMword data; | ||
| 634 | |||
| 635 | UNDEF_LSCPCBaseWb; | ||
| 636 | //printf("SKYEYE ARMul_LDC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address); | ||
| 637 | /*chy 2004-05-23 should update this function in the future,should concern dataabort*/ | ||
| 638 | // chy 2004-05-25 , fix it now,so needn't printf | ||
| 639 | // printf("SKYEYE ARMul_LDC, should update this function!!!!!\n"); | ||
| 640 | //exit(-1); | ||
| 641 | |||
| 642 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 643 | if (!state->LDC[CPNum]) { | ||
| 644 | /* | ||
| 645 | printf | ||
| 646 | ("SKYEYE ARMul_LDC,NOT ALLOW, underinstr, CPnum is %x, instr %x, addr %x\n", | ||
| 647 | CPNum, instr, address); | ||
| 648 | */ | ||
| 649 | ARMul_UndefInstr (state, instr); | ||
| 650 | return; | ||
| 651 | } | ||
| 652 | |||
| 653 | /*if (ADDREXCEPT (address)) | ||
| 654 | INTERNALABORT (address);*/ | ||
| 655 | |||
| 656 | cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0); | ||
| 657 | while (cpab == ARMul_BUSY) { | ||
| 658 | ARMul_Icycles (state, 1, 0); | ||
| 659 | |||
| 660 | if (IntPending (state)) { | ||
| 661 | cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, | ||
| 662 | instr, 0); | ||
| 663 | return; | ||
| 664 | } else | ||
| 665 | cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, | ||
| 666 | 0); | ||
| 667 | } | ||
| 668 | if (cpab == ARMul_CANT) { | ||
| 669 | /* | ||
| 670 | printf | ||
| 671 | ("SKYEYE ARMul_LDC,NOT CAN, underinstr, CPnum is %x, instr %x, addr %x\n", | ||
| 672 | CPNum, instr, address); | ||
| 673 | */ | ||
| 674 | CPTAKEABORT; | ||
| 675 | return; | ||
| 676 | } | ||
| 677 | |||
| 678 | cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0); | ||
| 679 | data = ARMul_LoadWordN (state, address); | ||
| 680 | //chy 2004-05-25 | ||
| 681 | if (state->abortSig || state->Aborted) | ||
| 682 | goto L_ldc_takeabort; | ||
| 683 | |||
| 684 | BUSUSEDINCPCN; | ||
| 685 | //chy 2004-05-25 | ||
| 686 | /* | ||
| 687 | if (BIT (21)) | ||
| 688 | LSBase = state->Base; | ||
| 689 | */ | ||
| 690 | |||
| 691 | cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); | ||
| 692 | |||
| 693 | while (cpab == ARMul_INC) { | ||
| 694 | address += 4; | ||
| 695 | data = ARMul_LoadWordN (state, address); | ||
| 696 | //chy 2004-05-25 | ||
| 697 | if (state->abortSig || state->Aborted) | ||
| 698 | goto L_ldc_takeabort; | ||
| 699 | |||
| 700 | cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); | ||
| 701 | } | ||
| 702 | |||
| 703 | //chy 2004-05-25 | ||
| 704 | L_ldc_takeabort: | ||
| 705 | if (BIT (21)) { | ||
| 706 | if (! | ||
| 707 | ((state->abortSig || state->Aborted) | ||
| 708 | && state->lateabtSig == LOW)) | ||
| 709 | LSBase = state->Base; | ||
| 710 | } | ||
| 711 | |||
| 712 | if (state->abortSig || state->Aborted) | ||
| 713 | TAKEABORT; | ||
| 714 | } | ||
| 715 | |||
| 716 | /* This function does the work of generating the addresses used in an | ||
| 717 | STC instruction. The code here is always post-indexed, it's up to the | ||
| 718 | caller to get the input address correct and to handle base register | ||
| 719 | modification. It also handles the Busy-Waiting. */ | ||
| 720 | |||
| 721 | void | ||
| 722 | ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) | ||
| 723 | { | ||
| 724 | unsigned cpab; | ||
| 725 | ARMword data; | ||
| 726 | |||
| 727 | UNDEF_LSCPCBaseWb; | ||
| 728 | |||
| 729 | //printf("SKYEYE ARMul_STC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address); | ||
| 730 | /*chy 2004-05-23 should update this function in the future,should concern dataabort */ | ||
| 731 | // skyeye_instr_debug=0;printf("SKYEYE debug end!!!!\n"); | ||
| 732 | // chy 2004-05-25 , fix it now,so needn't printf | ||
| 733 | // printf("SKYEYE ARMul_STC, should update this function!!!!!\n"); | ||
| 734 | |||
| 735 | //exit(-1); | ||
| 736 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 737 | if (!state->STC[CPNum]) { | ||
| 738 | /* | ||
| 739 | printf | ||
| 740 | ("SKYEYE ARMul_STC,NOT ALLOW, undefinstr, CPnum is %x, instr %x, addr %x\n", | ||
| 741 | CPNum, instr, address); | ||
| 742 | */ | ||
| 743 | ARMul_UndefInstr (state, instr); | ||
| 744 | return; | ||
| 745 | } | ||
| 746 | |||
| 747 | /*if (ADDREXCEPT (address) || VECTORACCESS (address)) | ||
| 748 | INTERNALABORT (address);*/ | ||
| 749 | |||
| 750 | cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data); | ||
| 751 | while (cpab == ARMul_BUSY) { | ||
| 752 | ARMul_Icycles (state, 1, 0); | ||
| 753 | if (IntPending (state)) { | ||
| 754 | cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, | ||
| 755 | instr, 0); | ||
| 756 | return; | ||
| 757 | } else | ||
| 758 | cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, | ||
| 759 | &data); | ||
| 760 | } | ||
| 761 | |||
| 762 | if (cpab == ARMul_CANT) { | ||
| 763 | /* | ||
| 764 | printf | ||
| 765 | ("SKYEYE ARMul_STC,CANT, undefinstr, CPnum is %x, instr %x, addr %x\n", | ||
| 766 | CPNum, instr, address); | ||
| 767 | */ | ||
| 768 | CPTAKEABORT; | ||
| 769 | return; | ||
| 770 | } | ||
| 771 | /*#ifndef MODE32 | ||
| 772 | if (ADDREXCEPT (address) || VECTORACCESS (address)) | ||
| 773 | INTERNALABORT (address); | ||
| 774 | #endif*/ | ||
| 775 | BUSUSEDINCPCN; | ||
| 776 | //chy 2004-05-25 | ||
| 777 | /* | ||
| 778 | if (BIT (21)) | ||
| 779 | LSBase = state->Base; | ||
| 780 | */ | ||
| 781 | cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); | ||
| 782 | ARMul_StoreWordN (state, address, data); | ||
| 783 | //chy 2004-05-25 | ||
| 784 | if (state->abortSig || state->Aborted) | ||
| 785 | goto L_stc_takeabort; | ||
| 786 | |||
| 787 | while (cpab == ARMul_INC) { | ||
| 788 | address += 4; | ||
| 789 | cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); | ||
| 790 | ARMul_StoreWordN (state, address, data); | ||
| 791 | //chy 2004-05-25 | ||
| 792 | if (state->abortSig || state->Aborted) | ||
| 793 | goto L_stc_takeabort; | ||
| 794 | } | ||
| 795 | //chy 2004-05-25 | ||
| 796 | L_stc_takeabort: | ||
| 797 | if (BIT (21)) { | ||
| 798 | if (! | ||
| 799 | ((state->abortSig || state->Aborted) | ||
| 800 | && state->lateabtSig == LOW)) | ||
| 801 | LSBase = state->Base; | ||
| 802 | } | ||
| 803 | |||
| 804 | if (state->abortSig || state->Aborted) | ||
| 805 | TAKEABORT; | ||
| 806 | } | ||
| 807 | |||
| 808 | /* This function does the Busy-Waiting for an MCR instruction. */ | ||
| 809 | |||
| 810 | void | ||
| 811 | ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) | ||
| 812 | { | ||
| 813 | unsigned cpab; | ||
| 814 | int cm = BITS(0, 3) & 0xf; | ||
| 815 | int cp = BITS(5, 7) & 0x7; | ||
| 816 | int rd = BITS(12, 15) & 0xf; | ||
| 817 | int cn = BITS(16, 19) & 0xf; | ||
| 818 | int cpopc = BITS(21, 23) & 0x7; | ||
| 819 | |||
| 820 | if (CPNum == 15 && source == 0) //Cache flush | ||
| 821 | { | ||
| 822 | return; | ||
| 823 | } | ||
| 824 | |||
| 825 | //printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source); | ||
| 826 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 827 | if (!state->MCR[CPNum]) { | ||
| 828 | //chy 2004-07-19 should fix in the future ????!!!! | ||
| 829 | LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x",CPNum, source); | ||
| 830 | ARMul_UndefInstr (state, instr); | ||
| 831 | return; | ||
| 832 | } | ||
| 833 | |||
| 834 | //DEBUG("SKYEYE ARMul_MCR p%d, %d, r%d, c%d, c%d, %d\n", CPNum, cpopc, rd, cn, cm, cp); | ||
| 835 | //DEBUG("plutoo: MCR not implemented\n"); | ||
| 836 | //exit(1); | ||
| 837 | //return; | ||
| 838 | |||
| 839 | cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); | ||
| 840 | |||
| 841 | while (cpab == ARMul_BUSY) { | ||
| 842 | ARMul_Icycles (state, 1, 0); | ||
| 843 | |||
| 844 | if (IntPending (state)) { | ||
| 845 | cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, | ||
| 846 | instr, 0); | ||
| 847 | return; | ||
| 848 | } else | ||
| 849 | cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, | ||
| 850 | source); | ||
| 851 | } | ||
| 852 | |||
| 853 | if (cpab == ARMul_CANT) { | ||
| 854 | LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MCR, CANT, UndefinedInstr %x CPnum is %x, source %x", instr, CPNum, source); //ichfly todo | ||
| 855 | //ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 856 | } else { | ||
| 857 | BUSUSEDINCPCN; | ||
| 858 | ARMul_Ccycles (state, 1, 0); | ||
| 859 | } | ||
| 860 | } | ||
| 861 | |||
| 862 | /* This function does the Busy-Waiting for an MCRR instruction. */ | ||
| 863 | |||
| 864 | void | ||
| 865 | ARMul_MCRR (ARMul_State * state, ARMword instr, ARMword source1, ARMword source2) | ||
| 866 | { | ||
| 867 | unsigned cpab; | ||
| 868 | |||
| 869 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 870 | if (!state->MCRR[CPNum]) { | ||
| 871 | ARMul_UndefInstr (state, instr); | ||
| 872 | return; | ||
| 873 | } | ||
| 874 | |||
| 875 | cpab = (state->MCRR[CPNum]) (state, ARMul_FIRST, instr, source1, source2); | ||
| 876 | |||
| 877 | while (cpab == ARMul_BUSY) { | ||
| 878 | ARMul_Icycles (state, 1, 0); | ||
| 879 | |||
| 880 | if (IntPending (state)) { | ||
| 881 | cpab = (state->MCRR[CPNum]) (state, ARMul_INTERRUPT, | ||
| 882 | instr, 0, 0); | ||
| 883 | return; | ||
| 884 | } else | ||
| 885 | cpab = (state->MCRR[CPNum]) (state, ARMul_BUSY, instr, | ||
| 886 | source1, source2); | ||
| 887 | } | ||
| 888 | if (cpab == ARMul_CANT) { | ||
| 889 | printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x, source %x %x\n", __FUNCTION__, CPNum, instr, source1, source2); | ||
| 890 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 891 | } else { | ||
| 892 | BUSUSEDINCPCN; | ||
| 893 | ARMul_Ccycles (state, 1, 0); | ||
| 894 | } | ||
| 895 | } | ||
| 896 | |||
| 897 | /* This function does the Busy-Waiting for an MRC instruction. */ | ||
| 898 | |||
| 899 | ARMword ARMul_MRC (ARMul_State * state, ARMword instr) | ||
| 900 | { | ||
| 901 | int cm = BITS(0, 3) & 0xf; | ||
| 902 | int cp = BITS(5, 7) & 0x7; | ||
| 903 | int rd = BITS(12, 15) & 0xf; | ||
| 904 | int cn = BITS(16, 19) & 0xf; | ||
| 905 | int cpopc = BITS(21, 23) & 0x7; | ||
| 906 | |||
| 907 | if (cn == 13 && cm == 0 && cp == 3) { //c13,c0,3; returns CPU svc buffer | ||
| 908 | ARMword result = Memory::KERNEL_MEMORY_VADDR; | ||
| 909 | |||
| 910 | if (result != -1) { | ||
| 911 | return result; | ||
| 912 | } | ||
| 913 | } | ||
| 914 | |||
| 915 | //DEBUG("SKYEYE ARMul_MRC p%d, %d, r%d, c%d, c%d, %d\n", CPNum, cpopc, rd, cn, cm, cp); | ||
| 916 | //DEBUG("plutoo: MRC not implemented\n"); | ||
| 917 | //return; | ||
| 918 | |||
| 919 | unsigned cpab; | ||
| 920 | ARMword result = 0; | ||
| 921 | |||
| 922 | //printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr); | ||
| 923 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 924 | if (!state->MRC[CPNum]) { | ||
| 925 | //chy 2004-07-19 should fix in the future????!!!! | ||
| 926 | LOG_ERROR(Core_ARM11, "SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x", CPNum, instr); | ||
| 927 | ARMul_UndefInstr (state, instr); | ||
| 928 | return -1; | ||
| 929 | } | ||
| 930 | |||
| 931 | cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result); | ||
| 932 | while (cpab == ARMul_BUSY) { | ||
| 933 | ARMul_Icycles (state, 1, 0); | ||
| 934 | if (IntPending (state)) { | ||
| 935 | cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, | ||
| 936 | instr, 0); | ||
| 937 | return (0); | ||
| 938 | } else | ||
| 939 | cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, | ||
| 940 | &result); | ||
| 941 | } | ||
| 942 | if (cpab == ARMul_CANT) { | ||
| 943 | printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n", CPNum, instr); | ||
| 944 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 945 | /* Parent will destroy the flags otherwise. */ | ||
| 946 | result = ECC; | ||
| 947 | } else { | ||
| 948 | BUSUSEDINCPCN; | ||
| 949 | ARMul_Ccycles (state, 1, 0); | ||
| 950 | ARMul_Icycles (state, 1, 0); | ||
| 951 | } | ||
| 952 | |||
| 953 | return result; | ||
| 954 | } | ||
| 955 | |||
| 956 | /* This function does the Busy-Waiting for an MRRC instruction. (to verify) */ | ||
| 957 | |||
| 958 | void | ||
| 959 | ARMul_MRRC (ARMul_State * state, ARMword instr, ARMword * dest1, ARMword * dest2) | ||
| 960 | { | ||
| 961 | unsigned cpab; | ||
| 962 | ARMword result1 = 0; | ||
| 963 | ARMword result2 = 0; | ||
| 964 | |||
| 965 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 966 | if (!state->MRRC[CPNum]) { | ||
| 967 | ARMul_UndefInstr (state, instr); | ||
| 968 | return; | ||
| 969 | } | ||
| 970 | |||
| 971 | cpab = (state->MRRC[CPNum]) (state, ARMul_FIRST, instr, &result1, &result2); | ||
| 972 | while (cpab == ARMul_BUSY) { | ||
| 973 | ARMul_Icycles (state, 1, 0); | ||
| 974 | if (IntPending (state)) { | ||
| 975 | cpab = (state->MRRC[CPNum]) (state, ARMul_INTERRUPT, | ||
| 976 | instr, 0, 0); | ||
| 977 | return; | ||
| 978 | } else | ||
| 979 | cpab = (state->MRRC[CPNum]) (state, ARMul_BUSY, instr, | ||
| 980 | &result1, &result2); | ||
| 981 | } | ||
| 982 | if (cpab == ARMul_CANT) { | ||
| 983 | printf ("In %s, CoProcesscor returned CANT, CPnum is %x, instr %x\n", __FUNCTION__, CPNum, instr); | ||
| 984 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 985 | } else { | ||
| 986 | BUSUSEDINCPCN; | ||
| 987 | ARMul_Ccycles (state, 1, 0); | ||
| 988 | ARMul_Icycles (state, 1, 0); | ||
| 989 | } | ||
| 990 | |||
| 991 | *dest1 = result1; | ||
| 992 | *dest2 = result2; | ||
| 993 | } | ||
| 994 | |||
| 995 | /* This function does the Busy-Waiting for an CDP instruction. */ | ||
| 996 | |||
| 997 | void | ||
| 998 | ARMul_CDP (ARMul_State * state, ARMword instr) | ||
| 999 | { | ||
| 1000 | unsigned cpab; | ||
| 1001 | |||
| 1002 | //if (!CP_ACCESS_ALLOWED (state, CPNum)) { | ||
| 1003 | if (!state->CDP[CPNum]) { | ||
| 1004 | ARMul_UndefInstr (state, instr); | ||
| 1005 | return; | ||
| 1006 | } | ||
| 1007 | cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr); | ||
| 1008 | while (cpab == ARMul_BUSY) { | ||
| 1009 | ARMul_Icycles (state, 1, 0); | ||
| 1010 | if (IntPending (state)) { | ||
| 1011 | cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, | ||
| 1012 | instr); | ||
| 1013 | return; | ||
| 1014 | } else | ||
| 1015 | cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr); | ||
| 1016 | } | ||
| 1017 | if (cpab == ARMul_CANT) | ||
| 1018 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 1019 | else | ||
| 1020 | BUSUSEDN; | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | /* This function handles Undefined instructions, as CP isntruction. */ | ||
| 1024 | |||
| 1025 | void | ||
| 1026 | ARMul_UndefInstr (ARMul_State * state, ARMword instr) | ||
| 1027 | { | ||
| 1028 | std::string disasm = ARM_Disasm::Disassemble(state->pc, instr); | ||
| 1029 | LOG_ERROR(Core_ARM11, "Undefined instruction!! Disasm: %s Opcode: 0x%x", disasm.c_str(), instr); | ||
| 1030 | ARMul_Abort (state, ARMul_UndefinedInstrV); | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | /* Return TRUE if an interrupt is pending, FALSE otherwise. */ | ||
| 1034 | |||
| 1035 | unsigned | ||
| 1036 | IntPending (ARMul_State * state) | ||
| 1037 | { | ||
| 1038 | /* Any exceptions. */ | ||
| 1039 | if (state->NresetSig == LOW) { | ||
| 1040 | ARMul_Abort (state, ARMul_ResetV); | ||
| 1041 | return TRUE; | ||
| 1042 | } else if (!state->NfiqSig && !FFLAG) { | ||
| 1043 | ARMul_Abort (state, ARMul_FIQV); | ||
| 1044 | return TRUE; | ||
| 1045 | } else if (!state->NirqSig && !IFLAG) { | ||
| 1046 | ARMul_Abort (state, ARMul_IRQV); | ||
| 1047 | return TRUE; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | return FALSE; | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | /* Align a word access to a non word boundary. */ | ||
| 1054 | |||
| 1055 | ARMword | ||
| 1056 | ARMul_Align (ARMul_State* state, ARMword address, ARMword data) | ||
| 1057 | { | ||
| 1058 | /* This code assumes the address is really unaligned, | ||
| 1059 | as a shift by 32 is undefined in C. */ | ||
| 1060 | |||
| 1061 | address = (address & 3) << 3; /* Get the word address. */ | ||
| 1062 | return ((data >> address) | (data << (32 - address))); /* rot right */ | ||
| 1063 | } | ||