1 1.1 christos /* armsupp.c -- ARMulator support code: ARM6 Instruction Emulator. 2 1.1 christos Copyright (C) 1994 Advanced RISC Machines Ltd. 3 1.5 christos 4 1.1 christos This program is free software; you can redistribute it and/or modify 5 1.1 christos it under the terms of the GNU General Public License as published by 6 1.1 christos the Free Software Foundation; either version 3 of the License, or 7 1.1 christos (at your option) any later version. 8 1.5 christos 9 1.1 christos This program is distributed in the hope that it will be useful, 10 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 11 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 1.1 christos GNU General Public License for more details. 13 1.5 christos 14 1.1 christos You should have received a copy of the GNU General Public License 15 1.1 christos along with this program; if not, see <http://www.gnu.org/licenses/>. */ 16 1.1 christos 17 1.8 christos /* This must come before any other includes. */ 18 1.8 christos #include "defs.h" 19 1.8 christos 20 1.1 christos #include "armdefs.h" 21 1.1 christos #include "armemu.h" 22 1.1 christos #include "ansidecl.h" 23 1.7 christos #include "libiberty.h" 24 1.5 christos #include <math.h> 25 1.1 christos 26 1.1 christos /* Definitions for the support routines. */ 27 1.1 christos 28 1.1 christos static ARMword ModeToBank (ARMword); 29 1.1 christos static void EnvokeList (ARMul_State *, unsigned long, unsigned long); 30 1.1 christos 31 1.1 christos struct EventNode 32 1.1 christos { /* An event list node. */ 33 1.1 christos unsigned (*func) (ARMul_State *); /* The function to call. */ 34 1.1 christos struct EventNode *next; 35 1.1 christos }; 36 1.1 christos 37 1.1 christos /* This routine returns the value of a register from a mode. */ 38 1.1 christos 39 1.1 christos ARMword 40 1.1 christos ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg) 41 1.1 christos { 42 1.1 christos mode &= MODEBITS; 43 1.1 christos if (mode != state->Mode) 44 1.1 christos return (state->RegBank[ModeToBank ((ARMword) mode)][reg]); 45 1.1 christos else 46 1.1 christos return (state->Reg[reg]); 47 1.1 christos } 48 1.1 christos 49 1.1 christos /* This routine sets the value of a register for a mode. */ 50 1.1 christos 51 1.1 christos void 52 1.1 christos ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value) 53 1.1 christos { 54 1.1 christos mode &= MODEBITS; 55 1.1 christos if (mode != state->Mode) 56 1.1 christos state->RegBank[ModeToBank ((ARMword) mode)][reg] = value; 57 1.1 christos else 58 1.1 christos state->Reg[reg] = value; 59 1.1 christos } 60 1.1 christos 61 1.1 christos /* This routine returns the value of the PC, mode independently. */ 62 1.1 christos 63 1.1 christos ARMword 64 1.1 christos ARMul_GetPC (ARMul_State * state) 65 1.1 christos { 66 1.1 christos if (state->Mode > SVC26MODE) 67 1.1 christos return state->Reg[15]; 68 1.1 christos else 69 1.1 christos return R15PC; 70 1.1 christos } 71 1.1 christos 72 1.1 christos /* This routine returns the value of the PC, mode independently. */ 73 1.1 christos 74 1.1 christos ARMword 75 1.1 christos ARMul_GetNextPC (ARMul_State * state) 76 1.1 christos { 77 1.1 christos if (state->Mode > SVC26MODE) 78 1.1 christos return state->Reg[15] + isize; 79 1.1 christos else 80 1.1 christos return (state->Reg[15] + isize) & R15PCBITS; 81 1.1 christos } 82 1.1 christos 83 1.1 christos /* This routine sets the value of the PC. */ 84 1.1 christos 85 1.1 christos void 86 1.1 christos ARMul_SetPC (ARMul_State * state, ARMword value) 87 1.1 christos { 88 1.1 christos if (ARMul_MODE32BIT) 89 1.1 christos state->Reg[15] = value & PCBITS; 90 1.1 christos else 91 1.1 christos state->Reg[15] = R15CCINTMODE | (value & R15PCBITS); 92 1.1 christos FLUSHPIPE; 93 1.1 christos } 94 1.1 christos 95 1.1 christos /* This routine returns the value of register 15, mode independently. */ 96 1.1 christos 97 1.1 christos ARMword 98 1.1 christos ARMul_GetR15 (ARMul_State * state) 99 1.1 christos { 100 1.1 christos if (state->Mode > SVC26MODE) 101 1.1 christos return (state->Reg[15]); 102 1.1 christos else 103 1.1 christos return (R15PC | ECC | ER15INT | EMODE); 104 1.1 christos } 105 1.1 christos 106 1.1 christos /* This routine sets the value of Register 15. */ 107 1.1 christos 108 1.1 christos void 109 1.1 christos ARMul_SetR15 (ARMul_State * state, ARMword value) 110 1.1 christos { 111 1.1 christos if (ARMul_MODE32BIT) 112 1.1 christos state->Reg[15] = value & PCBITS; 113 1.1 christos else 114 1.1 christos { 115 1.1 christos state->Reg[15] = value; 116 1.1 christos ARMul_R15Altered (state); 117 1.1 christos } 118 1.1 christos FLUSHPIPE; 119 1.1 christos } 120 1.1 christos 121 1.1 christos /* This routine returns the value of the CPSR. */ 122 1.1 christos 123 1.1 christos ARMword 124 1.1 christos ARMul_GetCPSR (ARMul_State * state) 125 1.1 christos { 126 1.1 christos return (CPSR | state->Cpsr); 127 1.1 christos } 128 1.1 christos 129 1.1 christos /* This routine sets the value of the CPSR. */ 130 1.1 christos 131 1.1 christos void 132 1.1 christos ARMul_SetCPSR (ARMul_State * state, ARMword value) 133 1.1 christos { 134 1.1 christos state->Cpsr = value; 135 1.1 christos ARMul_CPSRAltered (state); 136 1.1 christos } 137 1.1 christos 138 1.1 christos /* This routine does all the nasty bits involved in a write to the CPSR, 139 1.1 christos including updating the register bank, given a MSR instruction. */ 140 1.1 christos 141 1.1 christos void 142 1.1 christos ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) 143 1.1 christos { 144 1.1 christos state->Cpsr = ARMul_GetCPSR (state); 145 1.1 christos 146 1.1 christos if (state->Mode != USER26MODE 147 1.1 christos && state->Mode != USER32MODE) 148 1.1 christos { 149 1.1 christos /* In user mode, only write flags. */ 150 1.1 christos if (BIT (16)) 151 1.1 christos SETPSR_C (state->Cpsr, rhs); 152 1.1 christos if (BIT (17)) 153 1.1 christos SETPSR_X (state->Cpsr, rhs); 154 1.1 christos if (BIT (18)) 155 1.1 christos SETPSR_S (state->Cpsr, rhs); 156 1.1 christos } 157 1.1 christos if (BIT (19)) 158 1.1 christos SETPSR_F (state->Cpsr, rhs); 159 1.1 christos ARMul_CPSRAltered (state); 160 1.1 christos } 161 1.1 christos 162 1.1 christos /* Get an SPSR from the specified mode. */ 163 1.1 christos 164 1.1 christos ARMword 165 1.1 christos ARMul_GetSPSR (ARMul_State * state, ARMword mode) 166 1.1 christos { 167 1.1 christos ARMword bank = ModeToBank (mode & MODEBITS); 168 1.1 christos 169 1.1 christos if (! BANK_CAN_ACCESS_SPSR (bank)) 170 1.1 christos return ARMul_GetCPSR (state); 171 1.1 christos 172 1.1 christos return state->Spsr[bank]; 173 1.1 christos } 174 1.1 christos 175 1.1 christos /* This routine does a write to an SPSR. */ 176 1.1 christos 177 1.1 christos void 178 1.1 christos ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) 179 1.1 christos { 180 1.1 christos ARMword bank = ModeToBank (mode & MODEBITS); 181 1.5 christos 182 1.1 christos if (BANK_CAN_ACCESS_SPSR (bank)) 183 1.1 christos state->Spsr[bank] = value; 184 1.1 christos } 185 1.1 christos 186 1.1 christos /* This routine does a write to the current SPSR, given an MSR instruction. */ 187 1.1 christos 188 1.1 christos void 189 1.1 christos ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs) 190 1.1 christos { 191 1.1 christos if (BANK_CAN_ACCESS_SPSR (state->Bank)) 192 1.1 christos { 193 1.1 christos if (BIT (16)) 194 1.1 christos SETPSR_C (state->Spsr[state->Bank], rhs); 195 1.1 christos if (BIT (17)) 196 1.1 christos SETPSR_X (state->Spsr[state->Bank], rhs); 197 1.1 christos if (BIT (18)) 198 1.1 christos SETPSR_S (state->Spsr[state->Bank], rhs); 199 1.1 christos if (BIT (19)) 200 1.1 christos SETPSR_F (state->Spsr[state->Bank], rhs); 201 1.1 christos } 202 1.1 christos } 203 1.1 christos 204 1.1 christos /* This routine updates the state of the emulator after the Cpsr has been 205 1.1 christos changed. Both the processor flags and register bank are updated. */ 206 1.1 christos 207 1.1 christos void 208 1.1 christos ARMul_CPSRAltered (ARMul_State * state) 209 1.1 christos { 210 1.1 christos ARMword oldmode; 211 1.1 christos 212 1.1 christos if (state->prog32Sig == LOW) 213 1.1 christos state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS); 214 1.1 christos 215 1.1 christos oldmode = state->Mode; 216 1.5 christos 217 1.1 christos if (state->Mode != (state->Cpsr & MODEBITS)) 218 1.1 christos { 219 1.1 christos state->Mode = 220 1.1 christos ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS); 221 1.5 christos 222 1.1 christos state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 223 1.1 christos } 224 1.1 christos state->Cpsr &= ~MODEBITS; 225 1.1 christos 226 1.1 christos ASSIGNINT (state->Cpsr & INTBITS); 227 1.1 christos state->Cpsr &= ~INTBITS; 228 1.1 christos ASSIGNN ((state->Cpsr & NBIT) != 0); 229 1.1 christos state->Cpsr &= ~NBIT; 230 1.1 christos ASSIGNZ ((state->Cpsr & ZBIT) != 0); 231 1.1 christos state->Cpsr &= ~ZBIT; 232 1.1 christos ASSIGNC ((state->Cpsr & CBIT) != 0); 233 1.1 christos state->Cpsr &= ~CBIT; 234 1.1 christos ASSIGNV ((state->Cpsr & VBIT) != 0); 235 1.1 christos state->Cpsr &= ~VBIT; 236 1.1 christos ASSIGNS ((state->Cpsr & SBIT) != 0); 237 1.1 christos state->Cpsr &= ~SBIT; 238 1.1 christos #ifdef MODET 239 1.1 christos ASSIGNT ((state->Cpsr & TBIT) != 0); 240 1.1 christos state->Cpsr &= ~TBIT; 241 1.1 christos #endif 242 1.1 christos 243 1.1 christos if (oldmode > SVC26MODE) 244 1.1 christos { 245 1.1 christos if (state->Mode <= SVC26MODE) 246 1.1 christos { 247 1.1 christos state->Emulate = CHANGEMODE; 248 1.1 christos state->Reg[15] = ECC | ER15INT | EMODE | R15PC; 249 1.1 christos } 250 1.1 christos } 251 1.1 christos else 252 1.1 christos { 253 1.1 christos if (state->Mode > SVC26MODE) 254 1.1 christos { 255 1.1 christos state->Emulate = CHANGEMODE; 256 1.1 christos state->Reg[15] = R15PC; 257 1.1 christos } 258 1.1 christos else 259 1.1 christos state->Reg[15] = ECC | ER15INT | EMODE | R15PC; 260 1.1 christos } 261 1.1 christos } 262 1.1 christos 263 1.1 christos /* This routine updates the state of the emulator after register 15 has 264 1.1 christos been changed. Both the processor flags and register bank are updated. 265 1.1 christos This routine should only be called from a 26 bit mode. */ 266 1.1 christos 267 1.1 christos void 268 1.1 christos ARMul_R15Altered (ARMul_State * state) 269 1.1 christos { 270 1.1 christos if (state->Mode != R15MODE) 271 1.1 christos { 272 1.1 christos state->Mode = ARMul_SwitchMode (state, state->Mode, R15MODE); 273 1.1 christos state->NtransSig = (state->Mode & 3) ? HIGH : LOW; 274 1.1 christos } 275 1.1 christos 276 1.1 christos if (state->Mode > SVC26MODE) 277 1.1 christos state->Emulate = CHANGEMODE; 278 1.1 christos 279 1.1 christos ASSIGNR15INT (R15INT); 280 1.1 christos 281 1.1 christos ASSIGNN ((state->Reg[15] & NBIT) != 0); 282 1.1 christos ASSIGNZ ((state->Reg[15] & ZBIT) != 0); 283 1.1 christos ASSIGNC ((state->Reg[15] & CBIT) != 0); 284 1.1 christos ASSIGNV ((state->Reg[15] & VBIT) != 0); 285 1.1 christos } 286 1.1 christos 287 1.1 christos /* This routine controls the saving and restoring of registers across mode 288 1.1 christos changes. The regbank matrix is largely unused, only rows 13 and 14 are 289 1.1 christos used across all modes, 8 to 14 are used for FIQ, all others use the USER 290 1.1 christos column. It's easier this way. old and new parameter are modes numbers. 291 1.1 christos Notice the side effect of changing the Bank variable. */ 292 1.1 christos 293 1.1 christos ARMword 294 1.1 christos ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) 295 1.1 christos { 296 1.1 christos unsigned i; 297 1.1 christos ARMword oldbank; 298 1.1 christos ARMword newbank; 299 1.5 christos 300 1.1 christos oldbank = ModeToBank (oldmode); 301 1.1 christos newbank = state->Bank = ModeToBank (newmode); 302 1.5 christos 303 1.1 christos /* Do we really need to do it? */ 304 1.1 christos if (oldbank != newbank) 305 1.1 christos { 306 1.1 christos /* Save away the old registers. */ 307 1.1 christos switch (oldbank) 308 1.1 christos { 309 1.1 christos case USERBANK: 310 1.1 christos case IRQBANK: 311 1.1 christos case SVCBANK: 312 1.1 christos case ABORTBANK: 313 1.1 christos case UNDEFBANK: 314 1.1 christos if (newbank == FIQBANK) 315 1.1 christos for (i = 8; i < 13; i++) 316 1.1 christos state->RegBank[USERBANK][i] = state->Reg[i]; 317 1.1 christos state->RegBank[oldbank][13] = state->Reg[13]; 318 1.1 christos state->RegBank[oldbank][14] = state->Reg[14]; 319 1.1 christos break; 320 1.1 christos case FIQBANK: 321 1.1 christos for (i = 8; i < 15; i++) 322 1.1 christos state->RegBank[FIQBANK][i] = state->Reg[i]; 323 1.1 christos break; 324 1.1 christos case DUMMYBANK: 325 1.1 christos for (i = 8; i < 15; i++) 326 1.1 christos state->RegBank[DUMMYBANK][i] = 0; 327 1.1 christos break; 328 1.1 christos default: 329 1.1 christos abort (); 330 1.1 christos } 331 1.5 christos 332 1.1 christos /* Restore the new registers. */ 333 1.1 christos switch (newbank) 334 1.1 christos { 335 1.1 christos case USERBANK: 336 1.1 christos case IRQBANK: 337 1.1 christos case SVCBANK: 338 1.1 christos case ABORTBANK: 339 1.1 christos case UNDEFBANK: 340 1.1 christos if (oldbank == FIQBANK) 341 1.1 christos for (i = 8; i < 13; i++) 342 1.1 christos state->Reg[i] = state->RegBank[USERBANK][i]; 343 1.1 christos state->Reg[13] = state->RegBank[newbank][13]; 344 1.1 christos state->Reg[14] = state->RegBank[newbank][14]; 345 1.1 christos break; 346 1.1 christos case FIQBANK: 347 1.1 christos for (i = 8; i < 15; i++) 348 1.1 christos state->Reg[i] = state->RegBank[FIQBANK][i]; 349 1.1 christos break; 350 1.1 christos case DUMMYBANK: 351 1.1 christos for (i = 8; i < 15; i++) 352 1.1 christos state->Reg[i] = 0; 353 1.1 christos break; 354 1.1 christos default: 355 1.1 christos abort (); 356 1.1 christos } 357 1.1 christos } 358 1.5 christos 359 1.1 christos return newmode; 360 1.1 christos } 361 1.1 christos 362 1.1 christos /* Given a processor mode, this routine returns the 363 1.1 christos register bank that will be accessed in that mode. */ 364 1.1 christos 365 1.1 christos static ARMword 366 1.1 christos ModeToBank (ARMword mode) 367 1.1 christos { 368 1.1 christos static ARMword bankofmode[] = 369 1.1 christos { 370 1.1 christos USERBANK, FIQBANK, IRQBANK, SVCBANK, 371 1.1 christos DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, 372 1.1 christos DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, 373 1.1 christos DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, 374 1.1 christos USERBANK, FIQBANK, IRQBANK, SVCBANK, 375 1.1 christos DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK, 376 1.1 christos DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK, 377 1.1 christos DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK 378 1.1 christos }; 379 1.1 christos 380 1.7 christos if (mode >= ARRAY_SIZE (bankofmode)) 381 1.1 christos return DUMMYBANK; 382 1.1 christos 383 1.1 christos return bankofmode[mode]; 384 1.1 christos } 385 1.1 christos 386 1.1 christos /* Returns the register number of the nth register in a reg list. */ 387 1.1 christos 388 1.1 christos unsigned 389 1.1 christos ARMul_NthReg (ARMword instr, unsigned number) 390 1.1 christos { 391 1.9 christos unsigned bit, up_to; 392 1.1 christos 393 1.9 christos for (bit = 0, up_to = 0; up_to <= number; bit ++) 394 1.1 christos if (BIT (bit)) 395 1.9 christos up_to ++; 396 1.1 christos 397 1.1 christos return (bit - 1); 398 1.1 christos } 399 1.1 christos 400 1.1 christos /* Assigns the N and Z flags depending on the value of result. */ 401 1.1 christos 402 1.1 christos void 403 1.1 christos ARMul_NegZero (ARMul_State * state, ARMword result) 404 1.1 christos { 405 1.1 christos if (NEG (result)) 406 1.1 christos { 407 1.1 christos SETN; 408 1.1 christos CLEARZ; 409 1.1 christos } 410 1.1 christos else if (result == 0) 411 1.1 christos { 412 1.1 christos CLEARN; 413 1.1 christos SETZ; 414 1.1 christos } 415 1.1 christos else 416 1.1 christos { 417 1.1 christos CLEARN; 418 1.1 christos CLEARZ; 419 1.1 christos } 420 1.1 christos } 421 1.1 christos 422 1.1 christos /* Compute whether an addition of A and B, giving RESULT, overflowed. */ 423 1.1 christos 424 1.1 christos int 425 1.1 christos AddOverflow (ARMword a, ARMword b, ARMword result) 426 1.1 christos { 427 1.1 christos return ((NEG (a) && NEG (b) && POS (result)) 428 1.1 christos || (POS (a) && POS (b) && NEG (result))); 429 1.1 christos } 430 1.1 christos 431 1.1 christos /* Compute whether a subtraction of A and B, giving RESULT, overflowed. */ 432 1.1 christos 433 1.1 christos int 434 1.1 christos SubOverflow (ARMword a, ARMword b, ARMword result) 435 1.1 christos { 436 1.1 christos return ((NEG (a) && POS (b) && POS (result)) 437 1.1 christos || (POS (a) && NEG (b) && NEG (result))); 438 1.1 christos } 439 1.1 christos 440 1.1 christos /* Assigns the C flag after an addition of a and b to give result. */ 441 1.1 christos 442 1.1 christos void 443 1.1 christos ARMul_AddCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) 444 1.1 christos { 445 1.1 christos ASSIGNC ((NEG (a) && NEG (b)) || 446 1.1 christos (NEG (a) && POS (result)) || (NEG (b) && POS (result))); 447 1.1 christos } 448 1.1 christos 449 1.1 christos /* Assigns the V flag after an addition of a and b to give result. */ 450 1.1 christos 451 1.1 christos void 452 1.1 christos ARMul_AddOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) 453 1.1 christos { 454 1.1 christos ASSIGNV (AddOverflow (a, b, result)); 455 1.1 christos } 456 1.1 christos 457 1.1 christos /* Assigns the C flag after an subtraction of a and b to give result. */ 458 1.1 christos 459 1.1 christos void 460 1.1 christos ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result) 461 1.1 christos { 462 1.1 christos ASSIGNC ((NEG (a) && POS (b)) || 463 1.1 christos (NEG (a) && POS (result)) || (POS (b) && POS (result))); 464 1.1 christos } 465 1.1 christos 466 1.1 christos /* Assigns the V flag after an subtraction of a and b to give result. */ 467 1.1 christos 468 1.1 christos void 469 1.1 christos ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result) 470 1.1 christos { 471 1.1 christos ASSIGNV (SubOverflow (a, b, result)); 472 1.1 christos } 473 1.1 christos 474 1.5 christos static void 475 1.5 christos handle_VFP_xfer (ARMul_State * state, ARMword instr) 476 1.5 christos { 477 1.5 christos if (TOPBITS (28) == NV) 478 1.5 christos { 479 1.5 christos fprintf (stderr, "SIM: UNDEFINED VFP instruction\n"); 480 1.5 christos return; 481 1.5 christos } 482 1.5 christos 483 1.5 christos if (BITS (25, 27) != 0x6) 484 1.5 christos { 485 1.5 christos fprintf (stderr, "SIM: ISE: VFP handler called incorrectly\n"); 486 1.5 christos return; 487 1.5 christos } 488 1.5 christos 489 1.5 christos switch (BITS (20, 24)) 490 1.5 christos { 491 1.5 christos case 0x04: 492 1.5 christos case 0x05: 493 1.5 christos { 494 1.5 christos /* VMOV double precision to/from two ARM registers. */ 495 1.5 christos int vm = BITS (0, 3); 496 1.5 christos int rt1 = BITS (12, 15); 497 1.5 christos int rt2 = BITS (16, 19); 498 1.5 christos 499 1.5 christos /* FIXME: UNPREDICTABLE if rt1 == 15 or rt2 == 15. */ 500 1.5 christos if (BIT (20)) 501 1.5 christos { 502 1.5 christos /* Transfer to ARM. */ 503 1.5 christos /* FIXME: UPPREDICTABLE if rt1 == rt2. */ 504 1.5 christos state->Reg[rt1] = VFP_dword (vm) & 0xffffffff; 505 1.5 christos state->Reg[rt2] = VFP_dword (vm) >> 32; 506 1.5 christos } 507 1.5 christos else 508 1.5 christos { 509 1.5 christos VFP_dword (vm) = state->Reg[rt2]; 510 1.5 christos VFP_dword (vm) <<= 32; 511 1.5 christos VFP_dword (vm) |= (state->Reg[rt1] & 0xffffffff); 512 1.5 christos } 513 1.5 christos return; 514 1.5 christos } 515 1.5 christos 516 1.5 christos case 0x08: 517 1.5 christos case 0x0A: 518 1.5 christos case 0x0C: 519 1.5 christos case 0x0E: 520 1.5 christos { 521 1.5 christos /* VSTM with PUW=011 or PUW=010. */ 522 1.5 christos int n = BITS (16, 19); 523 1.5 christos int imm8 = BITS (0, 7); 524 1.5 christos 525 1.5 christos ARMword address = state->Reg[n]; 526 1.5 christos if (BIT (21)) 527 1.5 christos state->Reg[n] = address + (imm8 << 2); 528 1.5 christos 529 1.5 christos if (BIT (8)) 530 1.5 christos { 531 1.5 christos int src = (BIT (22) << 4) | BITS (12, 15); 532 1.5 christos imm8 >>= 1; 533 1.5 christos while (imm8--) 534 1.5 christos { 535 1.5 christos if (state->bigendSig) 536 1.5 christos { 537 1.5 christos ARMul_StoreWordN (state, address, VFP_dword (src) >> 32); 538 1.5 christos ARMul_StoreWordN (state, address + 4, VFP_dword (src)); 539 1.5 christos } 540 1.5 christos else 541 1.5 christos { 542 1.5 christos ARMul_StoreWordN (state, address, VFP_dword (src)); 543 1.5 christos ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32); 544 1.5 christos } 545 1.5 christos address += 8; 546 1.5 christos src += 1; 547 1.5 christos } 548 1.5 christos } 549 1.5 christos else 550 1.5 christos { 551 1.5 christos int src = (BITS (12, 15) << 1) | BIT (22); 552 1.5 christos while (imm8--) 553 1.5 christos { 554 1.5 christos ARMul_StoreWordN (state, address, VFP_uword (src)); 555 1.5 christos address += 4; 556 1.5 christos src += 1; 557 1.5 christos } 558 1.5 christos } 559 1.5 christos } 560 1.5 christos return; 561 1.5 christos 562 1.5 christos case 0x10: 563 1.5 christos case 0x14: 564 1.5 christos case 0x18: 565 1.5 christos case 0x1C: 566 1.5 christos { 567 1.5 christos /* VSTR */ 568 1.5 christos ARMword imm32 = BITS (0, 7) << 2; 569 1.5 christos int base = state->Reg[LHSReg]; 570 1.5 christos ARMword address; 571 1.5 christos int dest; 572 1.5 christos 573 1.5 christos if (LHSReg == 15) 574 1.5 christos base = (base + 3) & ~3; 575 1.5 christos 576 1.5 christos address = base + (BIT (23) ? imm32 : - imm32); 577 1.5 christos 578 1.5 christos if (CPNum == 10) 579 1.5 christos { 580 1.5 christos dest = (DESTReg << 1) + BIT (22); 581 1.5 christos 582 1.5 christos ARMul_StoreWordN (state, address, VFP_uword (dest)); 583 1.5 christos } 584 1.5 christos else 585 1.5 christos { 586 1.5 christos dest = (BIT (22) << 4) + DESTReg; 587 1.5 christos 588 1.5 christos if (state->bigendSig) 589 1.5 christos { 590 1.5 christos ARMul_StoreWordN (state, address, VFP_dword (dest) >> 32); 591 1.5 christos ARMul_StoreWordN (state, address + 4, VFP_dword (dest)); 592 1.5 christos } 593 1.5 christos else 594 1.5 christos { 595 1.5 christos ARMul_StoreWordN (state, address, VFP_dword (dest)); 596 1.5 christos ARMul_StoreWordN (state, address + 4, VFP_dword (dest) >> 32); 597 1.5 christos } 598 1.5 christos } 599 1.5 christos } 600 1.5 christos return; 601 1.5 christos 602 1.5 christos case 0x12: 603 1.5 christos case 0x16: 604 1.5 christos if (BITS (16, 19) == 13) 605 1.5 christos { 606 1.5 christos /* VPUSH */ 607 1.5 christos ARMword address = state->Reg[13] - (BITS (0, 7) << 2); 608 1.5 christos state->Reg[13] = address; 609 1.5 christos 610 1.5 christos if (BIT (8)) 611 1.5 christos { 612 1.5 christos int dreg = (BIT (22) << 4) | BITS (12, 15); 613 1.5 christos int num = BITS (0, 7) >> 1; 614 1.5 christos while (num--) 615 1.5 christos { 616 1.5 christos if (state->bigendSig) 617 1.5 christos { 618 1.5 christos ARMul_StoreWordN (state, address, VFP_dword (dreg) >> 32); 619 1.5 christos ARMul_StoreWordN (state, address + 4, VFP_dword (dreg)); 620 1.5 christos } 621 1.5 christos else 622 1.5 christos { 623 1.5 christos ARMul_StoreWordN (state, address, VFP_dword (dreg)); 624 1.5 christos ARMul_StoreWordN (state, address + 4, VFP_dword (dreg) >> 32); 625 1.5 christos } 626 1.5 christos address += 8; 627 1.5 christos dreg += 1; 628 1.5 christos } 629 1.5 christos } 630 1.5 christos else 631 1.5 christos { 632 1.5 christos int sreg = (BITS (12, 15) << 1) | BIT (22); 633 1.5 christos int num = BITS (0, 7); 634 1.5 christos while (num--) 635 1.5 christos { 636 1.5 christos ARMul_StoreWordN (state, address, VFP_uword (sreg)); 637 1.5 christos address += 4; 638 1.5 christos sreg += 1; 639 1.5 christos } 640 1.5 christos } 641 1.5 christos } 642 1.5 christos else if (BITS (9, 11) != 0x5) 643 1.5 christos break; 644 1.5 christos else 645 1.5 christos { 646 1.5 christos /* VSTM PUW=101 */ 647 1.5 christos int n = BITS (16, 19); 648 1.5 christos int imm8 = BITS (0, 7); 649 1.5 christos ARMword address = state->Reg[n] - (imm8 << 2); 650 1.5 christos state->Reg[n] = address; 651 1.5 christos 652 1.5 christos if (BIT (8)) 653 1.5 christos { 654 1.5 christos int src = (BIT (22) << 4) | BITS (12, 15); 655 1.5 christos 656 1.5 christos imm8 >>= 1; 657 1.5 christos while (imm8--) 658 1.5 christos { 659 1.5 christos if (state->bigendSig) 660 1.5 christos { 661 1.5 christos ARMul_StoreWordN (state, address, VFP_dword (src) >> 32); 662 1.5 christos ARMul_StoreWordN (state, address + 4, VFP_dword (src)); 663 1.5 christos } 664 1.5 christos else 665 1.5 christos { 666 1.5 christos ARMul_StoreWordN (state, address, VFP_dword (src)); 667 1.5 christos ARMul_StoreWordN (state, address + 4, VFP_dword (src) >> 32); 668 1.5 christos } 669 1.5 christos address += 8; 670 1.5 christos src += 1; 671 1.5 christos } 672 1.5 christos } 673 1.5 christos else 674 1.5 christos { 675 1.5 christos int src = (BITS (12, 15) << 1) | BIT (22); 676 1.5 christos 677 1.5 christos while (imm8--) 678 1.5 christos { 679 1.5 christos ARMul_StoreWordN (state, address, VFP_uword (src)); 680 1.5 christos address += 4; 681 1.5 christos src += 1; 682 1.5 christos } 683 1.5 christos } 684 1.5 christos } 685 1.5 christos return; 686 1.5 christos 687 1.5 christos case 0x13: 688 1.5 christos case 0x17: 689 1.5 christos /* VLDM PUW=101 */ 690 1.5 christos case 0x09: 691 1.5 christos case 0x0D: 692 1.5 christos /* VLDM PUW=010 */ 693 1.5 christos { 694 1.5 christos int n = BITS (16, 19); 695 1.5 christos int imm8 = BITS (0, 7); 696 1.5 christos 697 1.5 christos ARMword address = state->Reg[n]; 698 1.5 christos if (BIT (23) == 0) 699 1.5 christos address -= imm8 << 2; 700 1.5 christos if (BIT (21)) 701 1.5 christos state->Reg[n] = BIT (23) ? address + (imm8 << 2) : address; 702 1.5 christos 703 1.5 christos if (BIT (8)) 704 1.5 christos { 705 1.5 christos int dest = (BIT (22) << 4) | BITS (12, 15); 706 1.5 christos imm8 >>= 1; 707 1.5 christos while (imm8--) 708 1.5 christos { 709 1.5 christos if (state->bigendSig) 710 1.5 christos { 711 1.5 christos VFP_dword (dest) = ARMul_LoadWordN (state, address); 712 1.5 christos VFP_dword (dest) <<= 32; 713 1.5 christos VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4); 714 1.5 christos } 715 1.5 christos else 716 1.5 christos { 717 1.5 christos VFP_dword (dest) = ARMul_LoadWordN (state, address + 4); 718 1.5 christos VFP_dword (dest) <<= 32; 719 1.5 christos VFP_dword (dest) |= ARMul_LoadWordN (state, address); 720 1.5 christos } 721 1.5 christos 722 1.5 christos if (trace) 723 1.5 christos fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest)); 724 1.5 christos 725 1.5 christos address += 8; 726 1.5 christos dest += 1; 727 1.5 christos } 728 1.5 christos } 729 1.5 christos else 730 1.5 christos { 731 1.5 christos int dest = (BITS (12, 15) << 1) | BIT (22); 732 1.5 christos 733 1.5 christos while (imm8--) 734 1.5 christos { 735 1.5 christos VFP_uword (dest) = ARMul_LoadWordN (state, address); 736 1.5 christos address += 4; 737 1.5 christos dest += 1; 738 1.5 christos } 739 1.5 christos } 740 1.5 christos } 741 1.5 christos return; 742 1.5 christos 743 1.5 christos case 0x0B: 744 1.5 christos case 0x0F: 745 1.5 christos if (BITS (16, 19) == 13) 746 1.5 christos { 747 1.5 christos /* VPOP */ 748 1.5 christos ARMword address = state->Reg[13]; 749 1.5 christos state->Reg[13] = address + (BITS (0, 7) << 2); 750 1.5 christos 751 1.5 christos if (BIT (8)) 752 1.5 christos { 753 1.5 christos int dest = (BIT (22) << 4) | BITS (12, 15); 754 1.5 christos int num = BITS (0, 7) >> 1; 755 1.5 christos 756 1.5 christos while (num--) 757 1.5 christos { 758 1.5 christos if (state->bigendSig) 759 1.5 christos { 760 1.5 christos VFP_dword (dest) = ARMul_LoadWordN (state, address); 761 1.5 christos VFP_dword (dest) <<= 32; 762 1.5 christos VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4); 763 1.5 christos } 764 1.5 christos else 765 1.5 christos { 766 1.5 christos VFP_dword (dest) = ARMul_LoadWordN (state, address + 4); 767 1.5 christos VFP_dword (dest) <<= 32; 768 1.5 christos VFP_dword (dest) |= ARMul_LoadWordN (state, address); 769 1.5 christos } 770 1.5 christos 771 1.5 christos if (trace) 772 1.5 christos fprintf (stderr, " VFP: VPOP: D%d = %g\n", dest, VFP_dval (dest)); 773 1.5 christos 774 1.5 christos address += 8; 775 1.5 christos dest += 1; 776 1.5 christos } 777 1.5 christos } 778 1.5 christos else 779 1.5 christos { 780 1.5 christos int sreg = (BITS (12, 15) << 1) | BIT (22); 781 1.5 christos int num = BITS (0, 7); 782 1.5 christos 783 1.5 christos while (num--) 784 1.5 christos { 785 1.5 christos VFP_uword (sreg) = ARMul_LoadWordN (state, address); 786 1.5 christos address += 4; 787 1.5 christos sreg += 1; 788 1.5 christos } 789 1.5 christos } 790 1.5 christos } 791 1.5 christos else if (BITS (9, 11) != 0x5) 792 1.5 christos break; 793 1.5 christos else 794 1.5 christos { 795 1.5 christos /* VLDM PUW=011 */ 796 1.5 christos int n = BITS (16, 19); 797 1.5 christos int imm8 = BITS (0, 7); 798 1.5 christos ARMword address = state->Reg[n]; 799 1.5 christos state->Reg[n] += imm8 << 2; 800 1.5 christos 801 1.5 christos if (BIT (8)) 802 1.5 christos { 803 1.5 christos int dest = (BIT (22) << 4) | BITS (12, 15); 804 1.5 christos 805 1.5 christos imm8 >>= 1; 806 1.5 christos while (imm8--) 807 1.5 christos { 808 1.5 christos if (state->bigendSig) 809 1.5 christos { 810 1.5 christos VFP_dword (dest) = ARMul_LoadWordN (state, address); 811 1.5 christos VFP_dword (dest) <<= 32; 812 1.5 christos VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4); 813 1.5 christos } 814 1.5 christos else 815 1.5 christos { 816 1.5 christos VFP_dword (dest) = ARMul_LoadWordN (state, address + 4); 817 1.5 christos VFP_dword (dest) <<= 32; 818 1.5 christos VFP_dword (dest) |= ARMul_LoadWordN (state, address); 819 1.5 christos } 820 1.5 christos 821 1.5 christos if (trace) 822 1.5 christos fprintf (stderr, " VFP: VLDM: D%d = %g\n", dest, VFP_dval (dest)); 823 1.5 christos 824 1.5 christos address += 8; 825 1.5 christos dest += 1; 826 1.5 christos } 827 1.5 christos } 828 1.5 christos else 829 1.5 christos { 830 1.5 christos int dest = (BITS (12, 15) << 1) | BIT (22); 831 1.5 christos while (imm8--) 832 1.5 christos { 833 1.5 christos VFP_uword (dest) = ARMul_LoadWordN (state, address); 834 1.5 christos address += 4; 835 1.5 christos dest += 1; 836 1.5 christos } 837 1.5 christos } 838 1.5 christos } 839 1.5 christos return; 840 1.5 christos 841 1.5 christos case 0x11: 842 1.5 christos case 0x15: 843 1.5 christos case 0x19: 844 1.5 christos case 0x1D: 845 1.5 christos { 846 1.5 christos /* VLDR */ 847 1.5 christos ARMword imm32 = BITS (0, 7) << 2; 848 1.5 christos int base = state->Reg[LHSReg]; 849 1.5 christos ARMword address; 850 1.5 christos int dest; 851 1.5 christos 852 1.5 christos if (LHSReg == 15) 853 1.5 christos base = (base + 3) & ~3; 854 1.5 christos 855 1.5 christos address = base + (BIT (23) ? imm32 : - imm32); 856 1.5 christos 857 1.5 christos if (CPNum == 10) 858 1.5 christos { 859 1.5 christos dest = (DESTReg << 1) + BIT (22); 860 1.5 christos 861 1.5 christos VFP_uword (dest) = ARMul_LoadWordN (state, address); 862 1.5 christos } 863 1.5 christos else 864 1.5 christos { 865 1.5 christos dest = (BIT (22) << 4) + DESTReg; 866 1.5 christos 867 1.5 christos if (state->bigendSig) 868 1.5 christos { 869 1.5 christos VFP_dword (dest) = ARMul_LoadWordN (state, address); 870 1.5 christos VFP_dword (dest) <<= 32; 871 1.5 christos VFP_dword (dest) |= ARMul_LoadWordN (state, address + 4); 872 1.5 christos } 873 1.5 christos else 874 1.5 christos { 875 1.5 christos VFP_dword (dest) = ARMul_LoadWordN (state, address + 4); 876 1.5 christos VFP_dword (dest) <<= 32; 877 1.5 christos VFP_dword (dest) |= ARMul_LoadWordN (state, address); 878 1.5 christos } 879 1.5 christos 880 1.5 christos if (trace) 881 1.5 christos fprintf (stderr, " VFP: VLDR: D%d = %g\n", dest, VFP_dval (dest)); 882 1.5 christos } 883 1.5 christos } 884 1.5 christos return; 885 1.5 christos } 886 1.5 christos 887 1.5 christos fprintf (stderr, "SIM: VFP: Unimplemented: %0x\n", BITS (20, 24)); 888 1.5 christos } 889 1.5 christos 890 1.1 christos /* This function does the work of generating the addresses used in an 891 1.1 christos LDC instruction. The code here is always post-indexed, it's up to the 892 1.1 christos caller to get the input address correct and to handle base register 893 1.1 christos modification. It also handles the Busy-Waiting. */ 894 1.1 christos 895 1.1 christos void 896 1.1 christos ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address) 897 1.1 christos { 898 1.1 christos unsigned cpab; 899 1.1 christos ARMword data; 900 1.1 christos 901 1.5 christos if (CPNum == 10 || CPNum == 11) 902 1.5 christos { 903 1.5 christos handle_VFP_xfer (state, instr); 904 1.5 christos return; 905 1.5 christos } 906 1.5 christos 907 1.1 christos UNDEF_LSCPCBaseWb; 908 1.1 christos 909 1.1 christos if (! CP_ACCESS_ALLOWED (state, CPNum)) 910 1.1 christos { 911 1.1 christos ARMul_UndefInstr (state, instr); 912 1.1 christos return; 913 1.1 christos } 914 1.1 christos 915 1.1 christos if (ADDREXCEPT (address)) 916 1.1 christos INTERNALABORT (address); 917 1.1 christos 918 1.1 christos cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0); 919 1.1 christos while (cpab == ARMul_BUSY) 920 1.1 christos { 921 1.1 christos ARMul_Icycles (state, 1, 0); 922 1.1 christos 923 1.1 christos if (IntPending (state)) 924 1.1 christos { 925 1.1 christos cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0); 926 1.1 christos return; 927 1.1 christos } 928 1.1 christos else 929 1.1 christos cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0); 930 1.1 christos } 931 1.1 christos if (cpab == ARMul_CANT) 932 1.1 christos { 933 1.1 christos CPTAKEABORT; 934 1.1 christos return; 935 1.1 christos } 936 1.1 christos 937 1.1 christos cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0); 938 1.1 christos data = ARMul_LoadWordN (state, address); 939 1.1 christos BUSUSEDINCPCN; 940 1.1 christos 941 1.1 christos if (BIT (21)) 942 1.1 christos LSBase = state->Base; 943 1.1 christos cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); 944 1.1 christos 945 1.1 christos while (cpab == ARMul_INC) 946 1.1 christos { 947 1.1 christos address += 4; 948 1.1 christos data = ARMul_LoadWordN (state, address); 949 1.1 christos cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data); 950 1.1 christos } 951 1.1 christos 952 1.1 christos if (state->abortSig || state->Aborted) 953 1.1 christos TAKEABORT; 954 1.1 christos } 955 1.1 christos 956 1.1 christos /* This function does the work of generating the addresses used in an 957 1.1 christos STC instruction. The code here is always post-indexed, it's up to the 958 1.1 christos caller to get the input address correct and to handle base register 959 1.1 christos modification. It also handles the Busy-Waiting. */ 960 1.1 christos 961 1.1 christos void 962 1.1 christos ARMul_STC (ARMul_State * state, ARMword instr, ARMword address) 963 1.1 christos { 964 1.1 christos unsigned cpab; 965 1.1 christos ARMword data; 966 1.1 christos 967 1.5 christos if (CPNum == 10 || CPNum == 11) 968 1.5 christos { 969 1.5 christos handle_VFP_xfer (state, instr); 970 1.5 christos return; 971 1.5 christos } 972 1.5 christos 973 1.1 christos UNDEF_LSCPCBaseWb; 974 1.1 christos 975 1.1 christos if (! CP_ACCESS_ALLOWED (state, CPNum)) 976 1.1 christos { 977 1.1 christos ARMul_UndefInstr (state, instr); 978 1.1 christos return; 979 1.1 christos } 980 1.1 christos 981 1.1 christos if (ADDREXCEPT (address) || VECTORACCESS (address)) 982 1.1 christos INTERNALABORT (address); 983 1.1 christos 984 1.1 christos cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data); 985 1.1 christos while (cpab == ARMul_BUSY) 986 1.1 christos { 987 1.1 christos ARMul_Icycles (state, 1, 0); 988 1.1 christos if (IntPending (state)) 989 1.1 christos { 990 1.1 christos cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0); 991 1.1 christos return; 992 1.1 christos } 993 1.1 christos else 994 1.1 christos cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data); 995 1.1 christos } 996 1.1 christos 997 1.1 christos if (cpab == ARMul_CANT) 998 1.1 christos { 999 1.1 christos CPTAKEABORT; 1000 1.1 christos return; 1001 1.1 christos } 1002 1.1 christos #ifndef MODE32 1003 1.1 christos if (ADDREXCEPT (address) || VECTORACCESS (address)) 1004 1.1 christos INTERNALABORT (address); 1005 1.1 christos #endif 1006 1.1 christos BUSUSEDINCPCN; 1007 1.1 christos if (BIT (21)) 1008 1.1 christos LSBase = state->Base; 1009 1.1 christos cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); 1010 1.1 christos ARMul_StoreWordN (state, address, data); 1011 1.1 christos 1012 1.1 christos while (cpab == ARMul_INC) 1013 1.1 christos { 1014 1.1 christos address += 4; 1015 1.1 christos cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data); 1016 1.1 christos ARMul_StoreWordN (state, address, data); 1017 1.1 christos } 1018 1.1 christos 1019 1.1 christos if (state->abortSig || state->Aborted) 1020 1.1 christos TAKEABORT; 1021 1.1 christos } 1022 1.1 christos 1023 1.1 christos /* This function does the Busy-Waiting for an MCR instruction. */ 1024 1.1 christos 1025 1.1 christos void 1026 1.1 christos ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) 1027 1.1 christos { 1028 1.1 christos unsigned cpab; 1029 1.1 christos 1030 1.1 christos if (! CP_ACCESS_ALLOWED (state, CPNum)) 1031 1.1 christos { 1032 1.1 christos ARMul_UndefInstr (state, instr); 1033 1.1 christos return; 1034 1.1 christos } 1035 1.1 christos 1036 1.1 christos cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); 1037 1.1 christos 1038 1.1 christos while (cpab == ARMul_BUSY) 1039 1.1 christos { 1040 1.1 christos ARMul_Icycles (state, 1, 0); 1041 1.1 christos 1042 1.1 christos if (IntPending (state)) 1043 1.1 christos { 1044 1.1 christos cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0); 1045 1.1 christos return; 1046 1.1 christos } 1047 1.1 christos else 1048 1.1 christos cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source); 1049 1.1 christos } 1050 1.1 christos 1051 1.1 christos if (cpab == ARMul_CANT) 1052 1.1 christos ARMul_Abort (state, ARMul_UndefinedInstrV); 1053 1.1 christos else 1054 1.1 christos { 1055 1.1 christos BUSUSEDINCPCN; 1056 1.1 christos ARMul_Ccycles (state, 1, 0); 1057 1.1 christos } 1058 1.1 christos } 1059 1.1 christos 1060 1.1 christos /* This function does the Busy-Waiting for an MRC instruction. */ 1061 1.1 christos 1062 1.1 christos ARMword 1063 1.1 christos ARMul_MRC (ARMul_State * state, ARMword instr) 1064 1.1 christos { 1065 1.1 christos unsigned cpab; 1066 1.1 christos ARMword result = 0; 1067 1.1 christos 1068 1.1 christos if (! CP_ACCESS_ALLOWED (state, CPNum)) 1069 1.1 christos { 1070 1.1 christos ARMul_UndefInstr (state, instr); 1071 1.1 christos return result; 1072 1.1 christos } 1073 1.1 christos 1074 1.1 christos cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result); 1075 1.1 christos while (cpab == ARMul_BUSY) 1076 1.1 christos { 1077 1.1 christos ARMul_Icycles (state, 1, 0); 1078 1.1 christos if (IntPending (state)) 1079 1.1 christos { 1080 1.1 christos cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0); 1081 1.1 christos return (0); 1082 1.1 christos } 1083 1.1 christos else 1084 1.1 christos cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result); 1085 1.1 christos } 1086 1.1 christos if (cpab == ARMul_CANT) 1087 1.1 christos { 1088 1.1 christos ARMul_Abort (state, ARMul_UndefinedInstrV); 1089 1.1 christos /* Parent will destroy the flags otherwise. */ 1090 1.1 christos result = ECC; 1091 1.1 christos } 1092 1.1 christos else 1093 1.1 christos { 1094 1.1 christos BUSUSEDINCPCN; 1095 1.1 christos ARMul_Ccycles (state, 1, 0); 1096 1.1 christos ARMul_Icycles (state, 1, 0); 1097 1.1 christos } 1098 1.1 christos 1099 1.1 christos return result; 1100 1.1 christos } 1101 1.1 christos 1102 1.5 christos static void 1103 1.5 christos handle_VFP_op (ARMul_State * state, ARMword instr) 1104 1.5 christos { 1105 1.5 christos int dest; 1106 1.5 christos int srcN; 1107 1.5 christos int srcM; 1108 1.5 christos 1109 1.5 christos if (BITS (9, 11) != 0x5 || BIT (4) != 0) 1110 1.5 christos { 1111 1.5 christos fprintf (stderr, "SIM: VFP: Unimplemented: Float op: %08x\n", BITS (0,31)); 1112 1.5 christos return; 1113 1.5 christos } 1114 1.5 christos 1115 1.5 christos if (BIT (8)) 1116 1.5 christos { 1117 1.5 christos dest = BITS(12,15) + (BIT (22) << 4); 1118 1.5 christos srcN = LHSReg + (BIT (7) << 4); 1119 1.5 christos srcM = BITS (0,3) + (BIT (5) << 4); 1120 1.5 christos } 1121 1.5 christos else 1122 1.5 christos { 1123 1.5 christos dest = (BITS(12,15) << 1) + BIT (22); 1124 1.5 christos srcN = (LHSReg << 1) + BIT (7); 1125 1.5 christos srcM = (BITS (0,3) << 1) + BIT (5); 1126 1.5 christos } 1127 1.5 christos 1128 1.5 christos switch (BITS (20, 27)) 1129 1.5 christos { 1130 1.5 christos case 0xE0: 1131 1.5 christos case 0xE4: 1132 1.5 christos /* VMLA VMLS */ 1133 1.5 christos if (BIT (8)) 1134 1.5 christos { 1135 1.5 christos ARMdval val = VFP_dval (srcN) * VFP_dval (srcM); 1136 1.5 christos 1137 1.5 christos if (BIT (6)) 1138 1.5 christos { 1139 1.5 christos if (trace) 1140 1.5 christos fprintf (stderr, " VFP: VMLS: %g = %g - %g * %g\n", 1141 1.6 christos VFP_dval (dest) - val, 1142 1.5 christos VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM)); 1143 1.5 christos VFP_dval (dest) -= val; 1144 1.5 christos } 1145 1.5 christos else 1146 1.5 christos { 1147 1.5 christos if (trace) 1148 1.5 christos fprintf (stderr, " VFP: VMLA: %g = %g + %g * %g\n", 1149 1.6 christos VFP_dval (dest) + val, 1150 1.5 christos VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM)); 1151 1.5 christos VFP_dval (dest) += val; 1152 1.5 christos } 1153 1.5 christos } 1154 1.5 christos else 1155 1.5 christos { 1156 1.5 christos ARMfval val = VFP_fval (srcN) * VFP_fval (srcM); 1157 1.5 christos 1158 1.5 christos if (BIT (6)) 1159 1.5 christos { 1160 1.5 christos if (trace) 1161 1.5 christos fprintf (stderr, " VFP: VMLS: %g = %g - %g * %g\n", 1162 1.6 christos VFP_fval (dest) - val, 1163 1.5 christos VFP_fval (dest), VFP_fval (srcN), VFP_fval (srcM)); 1164 1.5 christos VFP_fval (dest) -= val; 1165 1.5 christos } 1166 1.5 christos else 1167 1.5 christos { 1168 1.5 christos if (trace) 1169 1.5 christos fprintf (stderr, " VFP: VMLA: %g = %g + %g * %g\n", 1170 1.6 christos VFP_fval (dest) + val, 1171 1.5 christos VFP_fval (dest), VFP_fval (srcN), VFP_fval (srcM)); 1172 1.5 christos VFP_fval (dest) += val; 1173 1.5 christos } 1174 1.5 christos } 1175 1.5 christos return; 1176 1.5 christos 1177 1.5 christos case 0xE1: 1178 1.5 christos case 0xE5: 1179 1.5 christos if (BIT (8)) 1180 1.5 christos { 1181 1.5 christos ARMdval product = VFP_dval (srcN) * VFP_dval (srcM); 1182 1.5 christos 1183 1.5 christos if (BIT (6)) 1184 1.5 christos { 1185 1.5 christos /* VNMLA */ 1186 1.5 christos if (trace) 1187 1.5 christos fprintf (stderr, " VFP: VNMLA: %g = -(%g + (%g * %g))\n", 1188 1.5 christos -(VFP_dval (dest) + product), 1189 1.5 christos VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM)); 1190 1.5 christos VFP_dval (dest) = -(product + VFP_dval (dest)); 1191 1.5 christos } 1192 1.5 christos else 1193 1.5 christos { 1194 1.5 christos /* VNMLS */ 1195 1.5 christos if (trace) 1196 1.5 christos fprintf (stderr, " VFP: VNMLS: %g = -(%g + (%g * %g))\n", 1197 1.5 christos -(VFP_dval (dest) + product), 1198 1.5 christos VFP_dval (dest), VFP_dval (srcN), VFP_dval (srcM)); 1199 1.5 christos VFP_dval (dest) = product - VFP_dval (dest); 1200 1.5 christos } 1201 1.5 christos } 1202 1.5 christos else 1203 1.5 christos { 1204 1.5 christos ARMfval product = VFP_fval (srcN) * VFP_fval (srcM); 1205 1.5 christos 1206 1.5 christos if (BIT (6)) 1207 1.5 christos /* VNMLA */ 1208 1.5 christos VFP_fval (dest) = -(product + VFP_fval (dest)); 1209 1.5 christos else 1210 1.5 christos /* VNMLS */ 1211 1.5 christos VFP_fval (dest) = product - VFP_fval (dest); 1212 1.5 christos } 1213 1.5 christos return; 1214 1.5 christos 1215 1.5 christos case 0xE2: 1216 1.5 christos case 0xE6: 1217 1.5 christos if (BIT (8)) 1218 1.5 christos { 1219 1.5 christos ARMdval product = VFP_dval (srcN) * VFP_dval (srcM); 1220 1.5 christos 1221 1.5 christos if (BIT (6)) 1222 1.5 christos { 1223 1.5 christos if (trace) 1224 1.5 christos fprintf (stderr, " VFP: VMUL: %g = %g * %g\n", 1225 1.5 christos - product, VFP_dval (srcN), VFP_dval (srcM)); 1226 1.5 christos /* VNMUL */ 1227 1.5 christos VFP_dval (dest) = - product; 1228 1.5 christos } 1229 1.5 christos else 1230 1.5 christos { 1231 1.5 christos if (trace) 1232 1.5 christos fprintf (stderr, " VFP: VMUL: %g = %g * %g\n", 1233 1.5 christos product, VFP_dval (srcN), VFP_dval (srcM)); 1234 1.5 christos /* VMUL */ 1235 1.5 christos VFP_dval (dest) = product; 1236 1.5 christos } 1237 1.5 christos } 1238 1.5 christos else 1239 1.5 christos { 1240 1.5 christos ARMfval product = VFP_fval (srcN) * VFP_fval (srcM); 1241 1.5 christos 1242 1.5 christos if (BIT (6)) 1243 1.5 christos { 1244 1.5 christos if (trace) 1245 1.5 christos fprintf (stderr, " VFP: VNMUL: %g = %g * %g\n", 1246 1.5 christos - product, VFP_fval (srcN), VFP_fval (srcM)); 1247 1.5 christos 1248 1.5 christos VFP_fval (dest) = - product; 1249 1.5 christos } 1250 1.5 christos else 1251 1.5 christos { 1252 1.5 christos if (trace) 1253 1.5 christos fprintf (stderr, " VFP: VMUL: %g = %g * %g\n", 1254 1.5 christos product, VFP_fval (srcN), VFP_fval (srcM)); 1255 1.5 christos 1256 1.5 christos VFP_fval (dest) = product; 1257 1.5 christos } 1258 1.5 christos } 1259 1.5 christos return; 1260 1.5 christos 1261 1.5 christos case 0xE3: 1262 1.5 christos case 0xE7: 1263 1.5 christos if (BIT (6) == 0) 1264 1.5 christos { 1265 1.5 christos /* VADD */ 1266 1.5 christos if (BIT(8)) 1267 1.5 christos { 1268 1.5 christos if (trace) 1269 1.5 christos fprintf (stderr, " VFP: VADD %g = %g + %g\n", 1270 1.5 christos VFP_dval (srcN) + VFP_dval (srcM), 1271 1.5 christos VFP_dval (srcN), 1272 1.5 christos VFP_dval (srcM)); 1273 1.5 christos VFP_dval (dest) = VFP_dval (srcN) + VFP_dval (srcM); 1274 1.5 christos } 1275 1.5 christos else 1276 1.5 christos VFP_fval (dest) = VFP_fval (srcN) + VFP_fval (srcM); 1277 1.5 christos 1278 1.5 christos } 1279 1.5 christos else 1280 1.5 christos { 1281 1.5 christos /* VSUB */ 1282 1.5 christos if (BIT(8)) 1283 1.5 christos { 1284 1.5 christos if (trace) 1285 1.5 christos fprintf (stderr, " VFP: VSUB %g = %g - %g\n", 1286 1.5 christos VFP_dval (srcN) - VFP_dval (srcM), 1287 1.5 christos VFP_dval (srcN), 1288 1.5 christos VFP_dval (srcM)); 1289 1.5 christos VFP_dval (dest) = VFP_dval (srcN) - VFP_dval (srcM); 1290 1.5 christos } 1291 1.5 christos else 1292 1.5 christos VFP_fval (dest) = VFP_fval (srcN) - VFP_fval (srcM); 1293 1.5 christos } 1294 1.5 christos return; 1295 1.5 christos 1296 1.5 christos case 0xE8: 1297 1.5 christos case 0xEC: 1298 1.5 christos if (BIT (6) == 1) 1299 1.5 christos break; 1300 1.5 christos 1301 1.5 christos /* VDIV */ 1302 1.5 christos if (BIT (8)) 1303 1.5 christos { 1304 1.5 christos ARMdval res = VFP_dval (srcN) / VFP_dval (srcM); 1305 1.5 christos if (trace) 1306 1.5 christos fprintf (stderr, " VFP: VDIV (64bit): %g = %g / %g\n", 1307 1.5 christos res, VFP_dval (srcN), VFP_dval (srcM)); 1308 1.5 christos VFP_dval (dest) = res; 1309 1.5 christos } 1310 1.5 christos else 1311 1.5 christos { 1312 1.5 christos if (trace) 1313 1.5 christos fprintf (stderr, " VFP: VDIV: %g = %g / %g\n", 1314 1.5 christos VFP_fval (srcN) / VFP_fval (srcM), 1315 1.5 christos VFP_fval (srcN), VFP_fval (srcM)); 1316 1.5 christos 1317 1.5 christos VFP_fval (dest) = VFP_fval (srcN) / VFP_fval (srcM); 1318 1.5 christos } 1319 1.5 christos return; 1320 1.5 christos 1321 1.5 christos case 0xEB: 1322 1.5 christos case 0xEF: 1323 1.5 christos if (BIT (6) != 1) 1324 1.5 christos break; 1325 1.5 christos 1326 1.5 christos switch (BITS (16, 19)) 1327 1.5 christos { 1328 1.5 christos case 0x0: 1329 1.5 christos if (BIT (7) == 0) 1330 1.5 christos { 1331 1.5 christos if (BIT (8)) 1332 1.5 christos { 1333 1.5 christos /* VMOV.F64 <Dd>, <Dm>. */ 1334 1.5 christos VFP_dval (dest) = VFP_dval (srcM); 1335 1.5 christos if (trace) 1336 1.5 christos fprintf (stderr, " VFP: VMOV d%d, d%d: %g\n", dest, srcM, VFP_dval (srcM)); 1337 1.5 christos } 1338 1.5 christos else 1339 1.5 christos { 1340 1.5 christos /* VMOV.F32 <Sd>, <Sm>. */ 1341 1.5 christos VFP_fval (dest) = VFP_fval (srcM); 1342 1.5 christos if (trace) 1343 1.5 christos fprintf (stderr, " VFP: VMOV s%d, s%d: %g\n", dest, srcM, VFP_fval (srcM)); 1344 1.5 christos } 1345 1.5 christos } 1346 1.5 christos else 1347 1.5 christos { 1348 1.5 christos /* VABS */ 1349 1.5 christos if (BIT (8)) 1350 1.5 christos { 1351 1.5 christos ARMdval src = VFP_dval (srcM); 1352 1.6 christos 1353 1.5 christos VFP_dval (dest) = fabs (src); 1354 1.5 christos if (trace) 1355 1.5 christos fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_dval (dest)); 1356 1.5 christos } 1357 1.5 christos else 1358 1.5 christos { 1359 1.5 christos ARMfval src = VFP_fval (srcM); 1360 1.5 christos 1361 1.5 christos VFP_fval (dest) = fabsf (src); 1362 1.5 christos if (trace) 1363 1.5 christos fprintf (stderr, " VFP: VABS (%g) = %g\n", src, VFP_fval (dest)); 1364 1.5 christos } 1365 1.5 christos } 1366 1.5 christos return; 1367 1.5 christos 1368 1.5 christos case 0x1: 1369 1.5 christos if (BIT (7) == 0) 1370 1.5 christos { 1371 1.5 christos /* VNEG */ 1372 1.5 christos if (BIT (8)) 1373 1.5 christos VFP_dval (dest) = - VFP_dval (srcM); 1374 1.5 christos else 1375 1.5 christos VFP_fval (dest) = - VFP_fval (srcM); 1376 1.5 christos } 1377 1.5 christos else 1378 1.5 christos { 1379 1.5 christos /* VSQRT */ 1380 1.5 christos if (BIT (8)) 1381 1.5 christos { 1382 1.5 christos if (trace) 1383 1.5 christos fprintf (stderr, " VFP: %g = root(%g)\n", 1384 1.5 christos sqrt (VFP_dval (srcM)), VFP_dval (srcM)); 1385 1.5 christos 1386 1.5 christos VFP_dval (dest) = sqrt (VFP_dval (srcM)); 1387 1.5 christos } 1388 1.5 christos else 1389 1.5 christos { 1390 1.5 christos if (trace) 1391 1.5 christos fprintf (stderr, " VFP: %g = root(%g)\n", 1392 1.5 christos sqrtf (VFP_fval (srcM)), VFP_fval (srcM)); 1393 1.5 christos 1394 1.5 christos VFP_fval (dest) = sqrtf (VFP_fval (srcM)); 1395 1.5 christos } 1396 1.5 christos } 1397 1.5 christos return; 1398 1.5 christos 1399 1.5 christos case 0x4: 1400 1.5 christos case 0x5: 1401 1.5 christos /* VCMP, VCMPE */ 1402 1.5 christos if (BIT(8)) 1403 1.5 christos { 1404 1.5 christos ARMdval res = VFP_dval (dest); 1405 1.5 christos 1406 1.5 christos if (BIT (16) == 0) 1407 1.5 christos { 1408 1.5 christos ARMdval src = VFP_dval (srcM); 1409 1.6 christos 1410 1.5 christos if (isinf (res) && isinf (src)) 1411 1.5 christos { 1412 1.5 christos if (res > 0.0 && src > 0.0) 1413 1.5 christos res = 0.0; 1414 1.5 christos else if (res < 0.0 && src < 0.0) 1415 1.5 christos res = 0.0; 1416 1.5 christos /* else leave res alone. */ 1417 1.5 christos } 1418 1.5 christos else 1419 1.5 christos res -= src; 1420 1.5 christos } 1421 1.5 christos 1422 1.5 christos /* FIXME: Add handling of signalling NaNs and the E bit. */ 1423 1.5 christos 1424 1.5 christos state->FPSCR &= 0x0FFFFFFF; 1425 1.5 christos if (res < 0.0) 1426 1.5 christos state->FPSCR |= NBIT; 1427 1.5 christos else 1428 1.5 christos state->FPSCR |= CBIT; 1429 1.5 christos if (res == 0.0) 1430 1.5 christos state->FPSCR |= ZBIT; 1431 1.5 christos if (isnan (res)) 1432 1.5 christos state->FPSCR |= VBIT; 1433 1.5 christos 1434 1.5 christos if (trace) 1435 1.5 christos fprintf (stderr, " VFP: VCMP (64bit) %g vs %g res %g, flags: %c%c%c%c\n", 1436 1.5 christos VFP_dval (dest), BIT (16) ? 0.0 : VFP_dval (srcM), res, 1437 1.5 christos state->FPSCR & NBIT ? 'N' : '-', 1438 1.5 christos state->FPSCR & ZBIT ? 'Z' : '-', 1439 1.5 christos state->FPSCR & CBIT ? 'C' : '-', 1440 1.5 christos state->FPSCR & VBIT ? 'V' : '-'); 1441 1.5 christos } 1442 1.5 christos else 1443 1.5 christos { 1444 1.5 christos ARMfval res = VFP_fval (dest); 1445 1.5 christos 1446 1.5 christos if (BIT (16) == 0) 1447 1.5 christos { 1448 1.5 christos ARMfval src = VFP_fval (srcM); 1449 1.6 christos 1450 1.5 christos if (isinf (res) && isinf (src)) 1451 1.5 christos { 1452 1.5 christos if (res > 0.0 && src > 0.0) 1453 1.5 christos res = 0.0; 1454 1.5 christos else if (res < 0.0 && src < 0.0) 1455 1.5 christos res = 0.0; 1456 1.5 christos /* else leave res alone. */ 1457 1.5 christos } 1458 1.5 christos else 1459 1.5 christos res -= src; 1460 1.5 christos } 1461 1.5 christos 1462 1.5 christos /* FIXME: Add handling of signalling NaNs and the E bit. */ 1463 1.5 christos 1464 1.5 christos state->FPSCR &= 0x0FFFFFFF; 1465 1.5 christos if (res < 0.0) 1466 1.5 christos state->FPSCR |= NBIT; 1467 1.5 christos else 1468 1.5 christos state->FPSCR |= CBIT; 1469 1.5 christos if (res == 0.0) 1470 1.5 christos state->FPSCR |= ZBIT; 1471 1.5 christos if (isnan (res)) 1472 1.5 christos state->FPSCR |= VBIT; 1473 1.5 christos 1474 1.5 christos if (trace) 1475 1.5 christos fprintf (stderr, " VFP: VCMP (32bit) %g vs %g res %g, flags: %c%c%c%c\n", 1476 1.5 christos VFP_fval (dest), BIT (16) ? 0.0 : VFP_fval (srcM), res, 1477 1.5 christos state->FPSCR & NBIT ? 'N' : '-', 1478 1.5 christos state->FPSCR & ZBIT ? 'Z' : '-', 1479 1.5 christos state->FPSCR & CBIT ? 'C' : '-', 1480 1.5 christos state->FPSCR & VBIT ? 'V' : '-'); 1481 1.5 christos } 1482 1.5 christos return; 1483 1.5 christos 1484 1.5 christos case 0x7: 1485 1.5 christos if (BIT (8)) 1486 1.5 christos { 1487 1.5 christos dest = (DESTReg << 1) + BIT (22); 1488 1.5 christos VFP_fval (dest) = VFP_dval (srcM); 1489 1.5 christos } 1490 1.5 christos else 1491 1.5 christos { 1492 1.5 christos dest = DESTReg + (BIT (22) << 4); 1493 1.5 christos VFP_dval (dest) = VFP_fval (srcM); 1494 1.5 christos } 1495 1.5 christos return; 1496 1.5 christos 1497 1.5 christos case 0x8: 1498 1.5 christos case 0xC: 1499 1.5 christos case 0xD: 1500 1.5 christos /* VCVT integer <-> FP */ 1501 1.5 christos if (BIT (18)) 1502 1.5 christos { 1503 1.5 christos /* To integer. */ 1504 1.5 christos if (BIT (8)) 1505 1.5 christos { 1506 1.5 christos dest = (BITS(12,15) << 1) + BIT (22); 1507 1.5 christos if (BIT (16)) 1508 1.5 christos VFP_sword (dest) = VFP_dval (srcM); 1509 1.5 christos else 1510 1.5 christos VFP_uword (dest) = VFP_dval (srcM); 1511 1.5 christos } 1512 1.5 christos else 1513 1.5 christos { 1514 1.5 christos if (BIT (16)) 1515 1.5 christos VFP_sword (dest) = VFP_fval (srcM); 1516 1.5 christos else 1517 1.5 christos VFP_uword (dest) = VFP_fval (srcM); 1518 1.5 christos } 1519 1.5 christos } 1520 1.5 christos else 1521 1.5 christos { 1522 1.5 christos /* From integer. */ 1523 1.5 christos if (BIT (8)) 1524 1.5 christos { 1525 1.5 christos srcM = (BITS (0,3) << 1) + BIT (5); 1526 1.5 christos if (BIT (7)) 1527 1.5 christos VFP_dval (dest) = VFP_sword (srcM); 1528 1.5 christos else 1529 1.5 christos VFP_dval (dest) = VFP_uword (srcM); 1530 1.5 christos } 1531 1.5 christos else 1532 1.5 christos { 1533 1.5 christos if (BIT (7)) 1534 1.5 christos VFP_fval (dest) = VFP_sword (srcM); 1535 1.5 christos else 1536 1.5 christos VFP_fval (dest) = VFP_uword (srcM); 1537 1.5 christos } 1538 1.5 christos } 1539 1.5 christos return; 1540 1.5 christos } 1541 1.5 christos 1542 1.5 christos fprintf (stderr, "SIM: VFP: Unimplemented: Float op3: %03x\n", BITS (16,27)); 1543 1.5 christos return; 1544 1.5 christos } 1545 1.5 christos 1546 1.5 christos fprintf (stderr, "SIM: VFP: Unimplemented: Float op2: %02x\n", BITS (20, 27)); 1547 1.5 christos return; 1548 1.5 christos } 1549 1.5 christos 1550 1.1 christos /* This function does the Busy-Waiting for an CDP instruction. */ 1551 1.1 christos 1552 1.1 christos void 1553 1.1 christos ARMul_CDP (ARMul_State * state, ARMword instr) 1554 1.1 christos { 1555 1.1 christos unsigned cpab; 1556 1.1 christos 1557 1.5 christos if (CPNum == 10 || CPNum == 11) 1558 1.5 christos { 1559 1.5 christos handle_VFP_op (state, instr); 1560 1.5 christos return; 1561 1.5 christos } 1562 1.5 christos 1563 1.1 christos if (! CP_ACCESS_ALLOWED (state, CPNum)) 1564 1.1 christos { 1565 1.1 christos ARMul_UndefInstr (state, instr); 1566 1.1 christos return; 1567 1.1 christos } 1568 1.1 christos 1569 1.1 christos cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr); 1570 1.1 christos while (cpab == ARMul_BUSY) 1571 1.1 christos { 1572 1.1 christos ARMul_Icycles (state, 1, 0); 1573 1.1 christos if (IntPending (state)) 1574 1.1 christos { 1575 1.1 christos cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr); 1576 1.1 christos return; 1577 1.1 christos } 1578 1.1 christos else 1579 1.1 christos cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr); 1580 1.1 christos } 1581 1.1 christos if (cpab == ARMul_CANT) 1582 1.1 christos ARMul_Abort (state, ARMul_UndefinedInstrV); 1583 1.1 christos else 1584 1.1 christos BUSUSEDN; 1585 1.1 christos } 1586 1.1 christos 1587 1.1 christos /* This function handles Undefined instructions, as CP isntruction. */ 1588 1.1 christos 1589 1.1 christos void 1590 1.1 christos ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED) 1591 1.1 christos { 1592 1.1 christos ARMul_Abort (state, ARMul_UndefinedInstrV); 1593 1.1 christos } 1594 1.1 christos 1595 1.1 christos /* Return TRUE if an interrupt is pending, FALSE otherwise. */ 1596 1.1 christos 1597 1.1 christos unsigned 1598 1.1 christos IntPending (ARMul_State * state) 1599 1.1 christos { 1600 1.1 christos if (state->Exception) 1601 1.1 christos { 1602 1.1 christos /* Any exceptions. */ 1603 1.1 christos if (state->NresetSig == LOW) 1604 1.1 christos { 1605 1.1 christos ARMul_Abort (state, ARMul_ResetV); 1606 1.1 christos return TRUE; 1607 1.1 christos } 1608 1.1 christos else if (!state->NfiqSig && !FFLAG) 1609 1.1 christos { 1610 1.1 christos ARMul_Abort (state, ARMul_FIQV); 1611 1.1 christos return TRUE; 1612 1.1 christos } 1613 1.1 christos else if (!state->NirqSig && !IFLAG) 1614 1.1 christos { 1615 1.1 christos ARMul_Abort (state, ARMul_IRQV); 1616 1.1 christos return TRUE; 1617 1.1 christos } 1618 1.1 christos } 1619 1.1 christos 1620 1.1 christos return FALSE; 1621 1.1 christos } 1622 1.1 christos 1623 1.1 christos /* Align a word access to a non word boundary. */ 1624 1.1 christos 1625 1.1 christos ARMword 1626 1.5 christos ARMul_Align (ARMul_State *state ATTRIBUTE_UNUSED, ARMword address, ARMword data) 1627 1.1 christos { 1628 1.1 christos /* This code assumes the address is really unaligned, 1629 1.1 christos as a shift by 32 is undefined in C. */ 1630 1.1 christos 1631 1.1 christos address = (address & 3) << 3; /* Get the word address. */ 1632 1.1 christos return ((data >> address) | (data << (32 - address))); /* rot right */ 1633 1.1 christos } 1634 1.1 christos 1635 1.1 christos /* This routine is used to call another routine after a certain number of 1636 1.1 christos cycles have been executed. The first parameter is the number of cycles 1637 1.1 christos delay before the function is called, the second argument is a pointer 1638 1.1 christos to the function. A delay of zero doesn't work, just call the function. */ 1639 1.1 christos 1640 1.1 christos void 1641 1.1 christos ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay, 1642 1.1 christos unsigned (*what) (ARMul_State *)) 1643 1.1 christos { 1644 1.1 christos unsigned long when; 1645 1.1 christos struct EventNode *event; 1646 1.1 christos 1647 1.1 christos if (state->EventSet++ == 0) 1648 1.1 christos state->Now = ARMul_Time (state); 1649 1.1 christos when = (state->Now + delay) % EVENTLISTSIZE; 1650 1.1 christos event = (struct EventNode *) malloc (sizeof (struct EventNode)); 1651 1.1 christos event->func = what; 1652 1.1 christos event->next = *(state->EventPtr + when); 1653 1.1 christos *(state->EventPtr + when) = event; 1654 1.1 christos } 1655 1.1 christos 1656 1.1 christos /* This routine is called at the beginning of 1657 1.1 christos every cycle, to envoke scheduled events. */ 1658 1.1 christos 1659 1.1 christos void 1660 1.1 christos ARMul_EnvokeEvent (ARMul_State * state) 1661 1.1 christos { 1662 1.1 christos static unsigned long then; 1663 1.1 christos 1664 1.1 christos then = state->Now; 1665 1.1 christos state->Now = ARMul_Time (state) % EVENTLISTSIZE; 1666 1.1 christos if (then < state->Now) 1667 1.1 christos /* Schedule events. */ 1668 1.1 christos EnvokeList (state, then, state->Now); 1669 1.1 christos else if (then > state->Now) 1670 1.1 christos { 1671 1.1 christos /* Need to wrap around the list. */ 1672 1.1 christos EnvokeList (state, then, EVENTLISTSIZE - 1L); 1673 1.1 christos EnvokeList (state, 0L, state->Now); 1674 1.1 christos } 1675 1.1 christos } 1676 1.1 christos 1677 1.1 christos /* Envokes all the entries in a range. */ 1678 1.1 christos 1679 1.1 christos static void 1680 1.1 christos EnvokeList (ARMul_State * state, unsigned long from, unsigned long to) 1681 1.1 christos { 1682 1.1 christos for (; from <= to; from++) 1683 1.1 christos { 1684 1.1 christos struct EventNode *anevent; 1685 1.1 christos 1686 1.1 christos anevent = *(state->EventPtr + from); 1687 1.1 christos while (anevent) 1688 1.1 christos { 1689 1.1 christos (anevent->func) (state); 1690 1.1 christos state->EventSet--; 1691 1.1 christos anevent = anevent->next; 1692 1.1 christos } 1693 1.1 christos *(state->EventPtr + from) = NULL; 1694 1.1 christos } 1695 1.1 christos } 1696 1.1 christos 1697 1.1 christos /* This routine is returns the number of clock ticks since the last reset. */ 1698 1.1 christos 1699 1.1 christos unsigned long 1700 1.1 christos ARMul_Time (ARMul_State * state) 1701 1.1 christos { 1702 1.1 christos return (state->NumScycles + state->NumNcycles + 1703 1.1 christos state->NumIcycles + state->NumCcycles + state->NumFcycles); 1704 1.1 christos } 1705