diff options
Diffstat (limited to 'src/core/arm/interpreter/armcopro.cpp')
| -rw-r--r-- | src/core/arm/interpreter/armcopro.cpp | 842 |
1 files changed, 842 insertions, 0 deletions
diff --git a/src/core/arm/interpreter/armcopro.cpp b/src/core/arm/interpreter/armcopro.cpp new file mode 100644 index 000000000..6a75e6601 --- /dev/null +++ b/src/core/arm/interpreter/armcopro.cpp | |||
| @@ -0,0 +1,842 @@ | |||
| 1 | /* armcopro.c -- co-processor interface: ARM6 Instruction Emulator. | ||
| 2 | Copyright (C) 1994, 2000 Advanced RISC Machines Ltd. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program; if not, write to the Free Software | ||
| 16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
| 17 | |||
| 18 | |||
| 19 | #include "core/arm/interpreter/armdefs.h" | ||
| 20 | #include "core/arm/interpreter/armos.h" | ||
| 21 | #include "core/arm/interpreter/armemu.h" | ||
| 22 | #include "core/arm/interpreter/vfp/vfp.h" | ||
| 23 | |||
| 24 | //chy 2005-07-08 | ||
| 25 | //#include "ansidecl.h" | ||
| 26 | //chy ------- | ||
| 27 | //#include "iwmmxt.h" | ||
| 28 | |||
| 29 | |||
| 30 | //chy 2005-09-19 add CP6 MRC support (for get irq number and base) | ||
| 31 | extern unsigned xscale_cp6_mrc (ARMul_State * state, unsigned type, | ||
| 32 | ARMword instr, ARMword * data); | ||
| 33 | //chy 2005-09-19--------------- | ||
| 34 | |||
| 35 | extern unsigned xscale_cp13_init (ARMul_State * state); | ||
| 36 | extern unsigned xscale_cp13_exit (ARMul_State * state); | ||
| 37 | extern unsigned xscale_cp13_ldc (ARMul_State * state, unsigned type, | ||
| 38 | ARMword instr, ARMword data); | ||
| 39 | extern unsigned xscale_cp13_stc (ARMul_State * state, unsigned type, | ||
| 40 | ARMword instr, ARMword * data); | ||
| 41 | extern unsigned xscale_cp13_mrc (ARMul_State * state, unsigned type, | ||
| 42 | ARMword instr, ARMword * data); | ||
| 43 | extern unsigned xscale_cp13_mcr (ARMul_State * state, unsigned type, | ||
| 44 | ARMword instr, ARMword data); | ||
| 45 | extern unsigned xscale_cp13_cdp (ARMul_State * state, unsigned type, | ||
| 46 | ARMword instr); | ||
| 47 | extern unsigned xscale_cp13_read_reg (ARMul_State * state, unsigned reg, | ||
| 48 | ARMword * data); | ||
| 49 | extern unsigned xscale_cp13_write_reg (ARMul_State * state, unsigned reg, | ||
| 50 | ARMword data); | ||
| 51 | extern unsigned xscale_cp14_init (ARMul_State * state); | ||
| 52 | extern unsigned xscale_cp14_exit (ARMul_State * state); | ||
| 53 | extern unsigned xscale_cp14_ldc (ARMul_State * state, unsigned type, | ||
| 54 | ARMword instr, ARMword data); | ||
| 55 | extern unsigned xscale_cp14_stc (ARMul_State * state, unsigned type, | ||
| 56 | ARMword instr, ARMword * data); | ||
| 57 | extern unsigned xscale_cp14_mrc (ARMul_State * state, unsigned type, | ||
| 58 | ARMword instr, ARMword * data); | ||
| 59 | extern unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type, | ||
| 60 | ARMword instr, ARMword data); | ||
| 61 | extern unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type, | ||
| 62 | ARMword instr); | ||
| 63 | extern unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg, | ||
| 64 | ARMword * data); | ||
| 65 | extern unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg, | ||
| 66 | ARMword data); | ||
| 67 | extern unsigned xscale_cp15_init (ARMul_State * state); | ||
| 68 | extern unsigned xscale_cp15_exit (ARMul_State * state); | ||
| 69 | extern unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type, | ||
| 70 | ARMword instr, ARMword data); | ||
| 71 | extern unsigned xscale_cp15_stc (ARMul_State * state, unsigned type, | ||
| 72 | ARMword instr, ARMword * data); | ||
| 73 | extern unsigned xscale_cp15_mrc (ARMul_State * state, unsigned type, | ||
| 74 | ARMword instr, ARMword * data); | ||
| 75 | extern unsigned xscale_cp15_mcr (ARMul_State * state, unsigned type, | ||
| 76 | ARMword instr, ARMword data); | ||
| 77 | extern unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type, | ||
| 78 | ARMword instr); | ||
| 79 | extern unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg, | ||
| 80 | ARMword * data); | ||
| 81 | extern unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg, | ||
| 82 | ARMword data); | ||
| 83 | extern unsigned xscale_cp15_cp_access_allowed (ARMul_State * state, unsigned reg, | ||
| 84 | unsigned cpnum); | ||
| 85 | |||
| 86 | /* Dummy Co-processors. */ | ||
| 87 | |||
| 88 | static unsigned | ||
| 89 | NoCoPro3R (ARMul_State * state, | ||
| 90 | unsigned a, ARMword b) | ||
| 91 | { | ||
| 92 | return ARMul_CANT; | ||
| 93 | } | ||
| 94 | |||
| 95 | static unsigned | ||
| 96 | NoCoPro4R (ARMul_State * state, | ||
| 97 | unsigned a, | ||
| 98 | ARMword b, ARMword c) | ||
| 99 | { | ||
| 100 | return ARMul_CANT; | ||
| 101 | } | ||
| 102 | |||
| 103 | static unsigned | ||
| 104 | NoCoPro4W (ARMul_State * state, | ||
| 105 | unsigned a, | ||
| 106 | ARMword b, ARMword * c) | ||
| 107 | { | ||
| 108 | return ARMul_CANT; | ||
| 109 | } | ||
| 110 | |||
| 111 | static unsigned | ||
| 112 | NoCoPro5R (ARMul_State * state, | ||
| 113 | unsigned a, | ||
| 114 | ARMword b, | ||
| 115 | ARMword c, ARMword d) | ||
| 116 | { | ||
| 117 | return ARMul_CANT; | ||
| 118 | } | ||
| 119 | |||
| 120 | static unsigned | ||
| 121 | NoCoPro5W (ARMul_State * state, | ||
| 122 | unsigned a, | ||
| 123 | ARMword b, | ||
| 124 | ARMword * c, ARMword * d ) | ||
| 125 | { | ||
| 126 | return ARMul_CANT; | ||
| 127 | } | ||
| 128 | |||
| 129 | /* The XScale Co-processors. */ | ||
| 130 | |||
| 131 | /* Coprocessor 15: System Control. */ | ||
| 132 | static void write_cp14_reg (unsigned, ARMword); | ||
| 133 | static ARMword read_cp14_reg (unsigned); | ||
| 134 | |||
| 135 | /* There are two sets of registers for copro 15. | ||
| 136 | One set is available when opcode_2 is 0 and | ||
| 137 | the other set when opcode_2 >= 1. */ | ||
| 138 | static ARMword XScale_cp15_opcode_2_is_0_Regs[16]; | ||
| 139 | static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16]; | ||
| 140 | /* There are also a set of breakpoint registers | ||
| 141 | which are accessed via CRm instead of opcode_2. */ | ||
| 142 | static ARMword XScale_cp15_DBR1; | ||
| 143 | static ARMword XScale_cp15_DBCON; | ||
| 144 | static ARMword XScale_cp15_IBCR0; | ||
| 145 | static ARMword XScale_cp15_IBCR1; | ||
| 146 | |||
| 147 | static unsigned | ||
| 148 | XScale_cp15_init (ARMul_State * state) | ||
| 149 | { | ||
| 150 | int i; | ||
| 151 | |||
| 152 | for (i = 16; i--;) { | ||
| 153 | XScale_cp15_opcode_2_is_0_Regs[i] = 0; | ||
| 154 | XScale_cp15_opcode_2_is_not_0_Regs[i] = 0; | ||
| 155 | } | ||
| 156 | |||
| 157 | /* Initialise the processor ID. */ | ||
| 158 | //chy 2003-03-24, is same as cpu id in skyeye_options.c | ||
| 159 | //XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000; | ||
| 160 | XScale_cp15_opcode_2_is_0_Regs[0] = 0x69050000; | ||
| 161 | |||
| 162 | /* Initialise the cache type. */ | ||
| 163 | XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA; | ||
| 164 | |||
| 165 | /* Initialise the ARM Control Register. */ | ||
| 166 | XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078; | ||
| 167 | |||
| 168 | return No_exp; | ||
| 169 | } | ||
| 170 | |||
| 171 | /* Check an access to a register. */ | ||
| 172 | |||
| 173 | static unsigned | ||
| 174 | check_cp15_access (ARMul_State * state, | ||
| 175 | unsigned reg, | ||
| 176 | unsigned CRm, unsigned opcode_1, unsigned opcode_2) | ||
| 177 | { | ||
| 178 | /* Do not allow access to these register in USER mode. */ | ||
| 179 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode | ||
| 180 | if (state->Mode == USER26MODE || state->Mode == USER32MODE ) | ||
| 181 | return ARMul_CANT; | ||
| 182 | |||
| 183 | /* Opcode_1should be zero. */ | ||
| 184 | if (opcode_1 != 0) | ||
| 185 | return ARMul_CANT; | ||
| 186 | |||
| 187 | /* Different register have different access requirements. */ | ||
| 188 | switch (reg) { | ||
| 189 | case 0: | ||
| 190 | case 1: | ||
| 191 | /* CRm must be 0. Opcode_2 can be anything. */ | ||
| 192 | if (CRm != 0) | ||
| 193 | return ARMul_CANT; | ||
| 194 | break; | ||
| 195 | case 2: | ||
| 196 | case 3: | ||
| 197 | /* CRm must be 0. Opcode_2 must be zero. */ | ||
| 198 | if ((CRm != 0) || (opcode_2 != 0)) | ||
| 199 | return ARMul_CANT; | ||
| 200 | break; | ||
| 201 | case 4: | ||
| 202 | /* Access not allowed. */ | ||
| 203 | return ARMul_CANT; | ||
| 204 | case 5: | ||
| 205 | case 6: | ||
| 206 | /* Opcode_2 must be zero. CRm must be 0. */ | ||
| 207 | if ((CRm != 0) || (opcode_2 != 0)) | ||
| 208 | return ARMul_CANT; | ||
| 209 | break; | ||
| 210 | case 7: | ||
| 211 | /* Permissable combinations: | ||
| 212 | Opcode_2 CRm | ||
| 213 | 0 5 | ||
| 214 | 0 6 | ||
| 215 | 0 7 | ||
| 216 | 1 5 | ||
| 217 | 1 6 | ||
| 218 | 1 10 | ||
| 219 | 4 10 | ||
| 220 | 5 2 | ||
| 221 | 6 5 */ | ||
| 222 | switch (opcode_2) { | ||
| 223 | default: | ||
| 224 | return ARMul_CANT; | ||
| 225 | case 6: | ||
| 226 | if (CRm != 5) | ||
| 227 | return ARMul_CANT; | ||
| 228 | break; | ||
| 229 | case 5: | ||
| 230 | if (CRm != 2) | ||
| 231 | return ARMul_CANT; | ||
| 232 | break; | ||
| 233 | case 4: | ||
| 234 | if (CRm != 10) | ||
| 235 | return ARMul_CANT; | ||
| 236 | break; | ||
| 237 | case 1: | ||
| 238 | if ((CRm != 5) && (CRm != 6) && (CRm != 10)) | ||
| 239 | return ARMul_CANT; | ||
| 240 | break; | ||
| 241 | case 0: | ||
| 242 | if ((CRm < 5) || (CRm > 7)) | ||
| 243 | return ARMul_CANT; | ||
| 244 | break; | ||
| 245 | } | ||
| 246 | break; | ||
| 247 | |||
| 248 | case 8: | ||
| 249 | /* Permissable combinations: | ||
| 250 | Opcode_2 CRm | ||
| 251 | 0 5 | ||
| 252 | 0 6 | ||
| 253 | 0 7 | ||
| 254 | 1 5 | ||
| 255 | 1 6 */ | ||
| 256 | if (opcode_2 > 1) | ||
| 257 | return ARMul_CANT; | ||
| 258 | if ((CRm < 5) || (CRm > 7)) | ||
| 259 | return ARMul_CANT; | ||
| 260 | if (opcode_2 == 1 && CRm == 7) | ||
| 261 | return ARMul_CANT; | ||
| 262 | break; | ||
| 263 | case 9: | ||
| 264 | /* Opcode_2 must be zero or one. CRm must be 1 or 2. */ | ||
| 265 | if (((CRm != 0) && (CRm != 1)) | ||
| 266 | || ((opcode_2 != 1) && (opcode_2 != 2))) | ||
| 267 | return ARMul_CANT; | ||
| 268 | break; | ||
| 269 | case 10: | ||
| 270 | /* Opcode_2 must be zero or one. CRm must be 4 or 8. */ | ||
| 271 | if (((CRm != 0) && (CRm != 1)) | ||
| 272 | || ((opcode_2 != 4) && (opcode_2 != 8))) | ||
| 273 | return ARMul_CANT; | ||
| 274 | break; | ||
| 275 | case 11: | ||
| 276 | /* Access not allowed. */ | ||
| 277 | return ARMul_CANT; | ||
| 278 | case 12: | ||
| 279 | /* Access not allowed. */ | ||
| 280 | return ARMul_CANT; | ||
| 281 | case 13: | ||
| 282 | /* Opcode_2 must be zero. CRm must be 0. */ | ||
| 283 | if ((CRm != 0) || (opcode_2 != 0)) | ||
| 284 | return ARMul_CANT; | ||
| 285 | break; | ||
| 286 | case 14: | ||
| 287 | /* Opcode_2 must be 0. CRm must be 0, 3, 4, 8 or 9. */ | ||
| 288 | if (opcode_2 != 0) | ||
| 289 | return ARMul_CANT; | ||
| 290 | |||
| 291 | if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8) | ||
| 292 | && (CRm != 9)) | ||
| 293 | return ARMul_CANT; | ||
| 294 | break; | ||
| 295 | case 15: | ||
| 296 | /* Opcode_2 must be zero. CRm must be 1. */ | ||
| 297 | if ((CRm != 1) || (opcode_2 != 0)) | ||
| 298 | return ARMul_CANT; | ||
| 299 | break; | ||
| 300 | default: | ||
| 301 | /* Should never happen. */ | ||
| 302 | return ARMul_CANT; | ||
| 303 | } | ||
| 304 | |||
| 305 | return ARMul_DONE; | ||
| 306 | } | ||
| 307 | |||
| 308 | /* Coprocessor 13: Interrupt Controller and Bus Controller. */ | ||
| 309 | |||
| 310 | /* There are two sets of registers for copro 13. | ||
| 311 | One set (of three registers) is available when CRm is 0 | ||
| 312 | and the other set (of six registers) when CRm is 1. */ | ||
| 313 | |||
| 314 | static ARMword XScale_cp13_CR0_Regs[16]; | ||
| 315 | static ARMword XScale_cp13_CR1_Regs[16]; | ||
| 316 | |||
| 317 | static unsigned | ||
| 318 | XScale_cp13_init (ARMul_State * state) | ||
| 319 | { | ||
| 320 | int i; | ||
| 321 | |||
| 322 | for (i = 16; i--;) { | ||
| 323 | XScale_cp13_CR0_Regs[i] = 0; | ||
| 324 | XScale_cp13_CR1_Regs[i] = 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | return No_exp; | ||
| 328 | } | ||
| 329 | |||
| 330 | /* Check an access to a register. */ | ||
| 331 | |||
| 332 | static unsigned | ||
| 333 | check_cp13_access (ARMul_State * state, | ||
| 334 | unsigned reg, | ||
| 335 | unsigned CRm, unsigned opcode_1, unsigned opcode_2) | ||
| 336 | { | ||
| 337 | /* Do not allow access to these registers in USER mode. */ | ||
| 338 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode | ||
| 339 | if (state->Mode == USER26MODE || state->Mode == USER32MODE ) | ||
| 340 | return ARMul_CANT; | ||
| 341 | |||
| 342 | /* The opcodes should be zero. */ | ||
| 343 | if ((opcode_1 != 0) || (opcode_2 != 0)) | ||
| 344 | return ARMul_CANT; | ||
| 345 | |||
| 346 | /* Do not allow access to these register if bit | ||
| 347 | 13 of coprocessor 15's register 15 is zero. */ | ||
| 348 | if (!CP_ACCESS_ALLOWED (state, 13)) | ||
| 349 | return ARMul_CANT; | ||
| 350 | |||
| 351 | /* Registers 0, 4 and 8 are defined when CRm == 0. | ||
| 352 | Registers 0, 1, 4, 5, 6, 7, 8 are defined when CRm == 1. | ||
| 353 | For all other CRm values undefined behaviour results. */ | ||
| 354 | if (CRm == 0) { | ||
| 355 | if (reg == 0 || reg == 4 || reg == 8) | ||
| 356 | return ARMul_DONE; | ||
| 357 | } | ||
| 358 | else if (CRm == 1) { | ||
| 359 | if (reg == 0 || reg == 1 || (reg >= 4 && reg <= 8)) | ||
| 360 | return ARMul_DONE; | ||
| 361 | } | ||
| 362 | |||
| 363 | return ARMul_CANT; | ||
| 364 | } | ||
| 365 | |||
| 366 | /* Coprocessor 14: Performance Monitoring, Clock and Power management, | ||
| 367 | Software Debug. */ | ||
| 368 | |||
| 369 | static ARMword XScale_cp14_Regs[16]; | ||
| 370 | |||
| 371 | static unsigned | ||
| 372 | XScale_cp14_init (ARMul_State * state) | ||
| 373 | { | ||
| 374 | int i; | ||
| 375 | |||
| 376 | for (i = 16; i--;) | ||
| 377 | XScale_cp14_Regs[i] = 0; | ||
| 378 | |||
| 379 | return No_exp; | ||
| 380 | } | ||
| 381 | |||
| 382 | /* Check an access to a register. */ | ||
| 383 | |||
| 384 | static unsigned | ||
| 385 | check_cp14_access (ARMul_State * state, | ||
| 386 | unsigned reg, | ||
| 387 | unsigned CRm, unsigned opcode1, unsigned opcode2) | ||
| 388 | { | ||
| 389 | /* Not allowed to access these register in USER mode. */ | ||
| 390 | //chy 2006-02-16 , should not consider system mode, don't conside 26bit mode | ||
| 391 | if (state->Mode == USER26MODE || state->Mode == USER32MODE ) | ||
| 392 | return ARMul_CANT; | ||
| 393 | |||
| 394 | /* CRm should be zero. */ | ||
| 395 | if (CRm != 0) | ||
| 396 | return ARMul_CANT; | ||
| 397 | |||
| 398 | /* OPcodes should be zero. */ | ||
| 399 | if (opcode1 != 0 || opcode2 != 0) | ||
| 400 | return ARMul_CANT; | ||
| 401 | |||
| 402 | /* Accessing registers 4 or 5 has unpredicatable results. */ | ||
| 403 | if (reg >= 4 && reg <= 5) | ||
| 404 | return ARMul_CANT; | ||
| 405 | |||
| 406 | return ARMul_DONE; | ||
| 407 | } | ||
| 408 | |||
| 409 | /* Here's ARMulator's MMU definition. A few things to note: | ||
| 410 | 1) It has eight registers, but only two are defined. | ||
| 411 | 2) You can only access its registers with MCR and MRC. | ||
| 412 | 3) MMU Register 0 (ID) returns 0x41440110 | ||
| 413 | 4) Register 1 only has 4 bits defined. Bits 0 to 3 are unused, bit 4 | ||
| 414 | controls 32/26 bit program space, bit 5 controls 32/26 bit data space, | ||
| 415 | bit 6 controls late abort timimg and bit 7 controls big/little endian. */ | ||
| 416 | |||
| 417 | static ARMword MMUReg[8]; | ||
| 418 | |||
| 419 | static unsigned | ||
| 420 | MMUInit (ARMul_State * state) | ||
| 421 | { | ||
| 422 | /* 2004-05-09 chy | ||
| 423 | ------------------------------------------------------------- | ||
| 424 | read ARM Architecture Reference Manual | ||
| 425 | 2.6.5 Data Abort | ||
| 426 | There are three Abort Model in ARM arch. | ||
| 427 | |||
| 428 | Early Abort Model: used in some ARMv3 and earlier implementations. In this | ||
| 429 | model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and | ||
| 430 | the base register was unchanged for all other instructions. (oldest) | ||
| 431 | |||
| 432 | Base Restored Abort Model: If a Data Abort occurs in an instruction which | ||
| 433 | specifies base register writeback, the value in the base register is | ||
| 434 | unchanged. (strongarm, xscale) | ||
| 435 | |||
| 436 | Base Updated Abort Model: If a Data Abort occurs in an instruction which | ||
| 437 | specifies base register writeback, the base register writeback still occurs. | ||
| 438 | (arm720T) | ||
| 439 | |||
| 440 | read PART B | ||
| 441 | chap2 The System Control Coprocessor CP15 | ||
| 442 | 2.4 Register1:control register | ||
| 443 | L(bit 6): in some ARMv3 and earlier implementations, the abort model of the | ||
| 444 | processor could be configured: | ||
| 445 | 0=early Abort Model Selected(now obsolete) | ||
| 446 | 1=Late Abort Model selceted(same as Base Updated Abort Model) | ||
| 447 | |||
| 448 | on later processors, this bit reads as 1 and ignores writes. | ||
| 449 | ------------------------------------------------------------- | ||
| 450 | So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model) | ||
| 451 | if lateabtSig=0, then it means Base Restored Abort Model | ||
| 452 | because the ARMs which skyeye simulates are all belonged to ARMv4, | ||
| 453 | so I think MMUReg[1]'s bit 6 should always be 1 | ||
| 454 | |||
| 455 | */ | ||
| 456 | |||
| 457 | MMUReg[1] = state->prog32Sig << 4 | | ||
| 458 | state->data32Sig << 5 | 1 << 6 | state->bigendSig << 7; | ||
| 459 | //state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7; | ||
| 460 | |||
| 461 | |||
| 462 | NOTICE_LOG(ARM11, "ARMul_ConsolePrint: MMU present"); | ||
| 463 | |||
| 464 | return TRUE; | ||
| 465 | } | ||
| 466 | |||
| 467 | static unsigned | ||
| 468 | MMUMRC (ARMul_State * state, unsigned type, | ||
| 469 | ARMword instr, ARMword * value) | ||
| 470 | { | ||
| 471 | mmu_mrc (state, instr, value); | ||
| 472 | return (ARMul_DONE); | ||
| 473 | } | ||
| 474 | |||
| 475 | static unsigned | ||
| 476 | MMUMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value) | ||
| 477 | { | ||
| 478 | mmu_mcr (state, instr, value); | ||
| 479 | return (ARMul_DONE); | ||
| 480 | } | ||
| 481 | |||
| 482 | /* What follows is the Validation Suite Coprocessor. It uses two | ||
| 483 | co-processor numbers (4 and 5) and has the follwing functionality. | ||
| 484 | Sixteen registers. Both co-processor nuimbers can be used in an MCR | ||
| 485 | and MRC to access these registers. CP 4 can LDC and STC to and from | ||
| 486 | the registers. CP 4 and CP 5 CDP 0 will busy wait for the number of | ||
| 487 | cycles specified by a CP register. CP 5 CDP 1 issues a FIQ after a | ||
| 488 | number of cycles (specified in a CP register), CDP 2 issues an IRQW | ||
| 489 | in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5 | ||
| 490 | stores a 32 bit time value in a CP register (actually it's the total | ||
| 491 | number of N, S, I, C and F cyles). */ | ||
| 492 | |||
| 493 | static ARMword ValReg[16]; | ||
| 494 | |||
| 495 | static unsigned | ||
| 496 | ValLDC (ARMul_State * state, | ||
| 497 | unsigned type, ARMword instr, ARMword data) | ||
| 498 | { | ||
| 499 | static unsigned words; | ||
| 500 | |||
| 501 | if (type != ARMul_DATA) | ||
| 502 | words = 0; | ||
| 503 | else { | ||
| 504 | ValReg[BITS (12, 15)] = data; | ||
| 505 | |||
| 506 | if (BIT (22)) | ||
| 507 | /* It's a long access, get two words. */ | ||
| 508 | if (words++ != 4) | ||
| 509 | return ARMul_INC; | ||
| 510 | } | ||
| 511 | |||
| 512 | return ARMul_DONE; | ||
| 513 | } | ||
| 514 | |||
| 515 | static unsigned | ||
| 516 | ValSTC (ARMul_State * state, | ||
| 517 | unsigned type, ARMword instr, ARMword * data) | ||
| 518 | { | ||
| 519 | static unsigned words; | ||
| 520 | |||
| 521 | if (type != ARMul_DATA) | ||
| 522 | words = 0; | ||
| 523 | else { | ||
| 524 | *data = ValReg[BITS (12, 15)]; | ||
| 525 | |||
| 526 | if (BIT (22)) | ||
| 527 | /* It's a long access, get two words. */ | ||
| 528 | if (words++ != 4) | ||
| 529 | return ARMul_INC; | ||
| 530 | } | ||
| 531 | |||
| 532 | return ARMul_DONE; | ||
| 533 | } | ||
| 534 | |||
| 535 | static unsigned | ||
| 536 | ValMRC (ARMul_State * state, | ||
| 537 | unsigned type, ARMword instr, ARMword * value) | ||
| 538 | { | ||
| 539 | *value = ValReg[BITS (16, 19)]; | ||
| 540 | |||
| 541 | return ARMul_DONE; | ||
| 542 | } | ||
| 543 | |||
| 544 | static unsigned | ||
| 545 | ValMCR (ARMul_State * state, | ||
| 546 | unsigned type, ARMword instr, ARMword value) | ||
| 547 | { | ||
| 548 | ValReg[BITS (16, 19)] = value; | ||
| 549 | |||
| 550 | return ARMul_DONE; | ||
| 551 | } | ||
| 552 | |||
| 553 | static unsigned | ||
| 554 | ValCDP (ARMul_State * state, unsigned type, ARMword instr) | ||
| 555 | { | ||
| 556 | static unsigned int finish = 0; | ||
| 557 | |||
| 558 | if (BITS (20, 23) != 0) | ||
| 559 | return ARMul_CANT; | ||
| 560 | |||
| 561 | if (type == ARMul_FIRST) { | ||
| 562 | ARMword howlong; | ||
| 563 | |||
| 564 | howlong = ValReg[BITS (0, 3)]; | ||
| 565 | |||
| 566 | /* First cycle of a busy wait. */ | ||
| 567 | finish = ARMul_Time (state) + howlong; | ||
| 568 | |||
| 569 | return howlong == 0 ? ARMul_DONE : ARMul_BUSY; | ||
| 570 | } | ||
| 571 | else if (type == ARMul_BUSY) { | ||
| 572 | if (ARMul_Time (state) >= finish) | ||
| 573 | return ARMul_DONE; | ||
| 574 | else | ||
| 575 | return ARMul_BUSY; | ||
| 576 | } | ||
| 577 | |||
| 578 | return ARMul_CANT; | ||
| 579 | } | ||
| 580 | |||
| 581 | static unsigned | ||
| 582 | DoAFIQ (ARMul_State * state) | ||
| 583 | { | ||
| 584 | state->NfiqSig = LOW; | ||
| 585 | return 0; | ||
| 586 | } | ||
| 587 | |||
| 588 | static unsigned | ||
| 589 | DoAIRQ (ARMul_State * state) | ||
| 590 | { | ||
| 591 | state->NirqSig = LOW; | ||
| 592 | return 0; | ||
| 593 | } | ||
| 594 | |||
| 595 | static unsigned | ||
| 596 | IntCDP (ARMul_State * state, unsigned type, ARMword instr) | ||
| 597 | { | ||
| 598 | static unsigned int finish; | ||
| 599 | ARMword howlong; | ||
| 600 | |||
| 601 | howlong = ValReg[BITS (0, 3)]; | ||
| 602 | |||
| 603 | switch ((int) BITS (20, 23)) { | ||
| 604 | case 0: | ||
| 605 | if (type == ARMul_FIRST) { | ||
| 606 | /* First cycle of a busy wait. */ | ||
| 607 | finish = ARMul_Time (state) + howlong; | ||
| 608 | |||
| 609 | return howlong == 0 ? ARMul_DONE : ARMul_BUSY; | ||
| 610 | } | ||
| 611 | else if (type == ARMul_BUSY) { | ||
| 612 | if (ARMul_Time (state) >= finish) | ||
| 613 | return ARMul_DONE; | ||
| 614 | else | ||
| 615 | return ARMul_BUSY; | ||
| 616 | } | ||
| 617 | return ARMul_DONE; | ||
| 618 | |||
| 619 | case 1: | ||
| 620 | if (howlong == 0) | ||
| 621 | ARMul_Abort (state, ARMul_FIQV); | ||
| 622 | else | ||
| 623 | ARMul_ScheduleEvent (state, howlong, DoAFIQ); | ||
| 624 | return ARMul_DONE; | ||
| 625 | |||
| 626 | case 2: | ||
| 627 | if (howlong == 0) | ||
| 628 | ARMul_Abort (state, ARMul_IRQV); | ||
| 629 | else | ||
| 630 | ARMul_ScheduleEvent (state, howlong, DoAIRQ); | ||
| 631 | return ARMul_DONE; | ||
| 632 | |||
| 633 | case 3: | ||
| 634 | state->NfiqSig = HIGH; | ||
| 635 | return ARMul_DONE; | ||
| 636 | |||
| 637 | case 4: | ||
| 638 | state->NirqSig = HIGH; | ||
| 639 | return ARMul_DONE; | ||
| 640 | |||
| 641 | case 5: | ||
| 642 | ValReg[BITS (0, 3)] = ARMul_Time (state); | ||
| 643 | return ARMul_DONE; | ||
| 644 | } | ||
| 645 | |||
| 646 | return ARMul_CANT; | ||
| 647 | } | ||
| 648 | |||
| 649 | /* Install co-processor instruction handlers in this routine. */ | ||
| 650 | |||
| 651 | unsigned | ||
| 652 | ARMul_CoProInit (ARMul_State * state) | ||
| 653 | { | ||
| 654 | unsigned int i; | ||
| 655 | |||
| 656 | /* Initialise tham all first. */ | ||
| 657 | for (i = 0; i < 16; i++) | ||
| 658 | ARMul_CoProDetach (state, i); | ||
| 659 | |||
| 660 | /* Install CoPro Instruction handlers here. | ||
| 661 | The format is: | ||
| 662 | ARMul_CoProAttach (state, CP Number, Init routine, Exit routine | ||
| 663 | LDC routine, STC routine, MRC routine, MCR routine, | ||
| 664 | CDP routine, Read Reg routine, Write Reg routine). */ | ||
| 665 | if (state->is_ep9312) { | ||
| 666 | ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4, | ||
| 667 | DSPMRC4, DSPMCR4, NULL, NULL, DSPCDP4, NULL, NULL); | ||
| 668 | ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5, | ||
| 669 | DSPMRC5, DSPMCR5, NULL, NULL, DSPCDP5, NULL, NULL); | ||
| 670 | ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL, | ||
| 671 | DSPMRC6, DSPMCR6, NULL, NULL, DSPCDP6, NULL, NULL); | ||
| 672 | } | ||
| 673 | else { | ||
| 674 | ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC, | ||
| 675 | ValMRC, ValMCR, NULL, NULL, ValCDP, NULL, NULL); | ||
| 676 | |||
| 677 | ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL, | ||
| 678 | ValMRC, ValMCR, NULL, NULL, IntCDP, NULL, NULL); | ||
| 679 | } | ||
| 680 | |||
| 681 | if (state->is_XScale) { | ||
| 682 | //chy 2005-09-19, for PXA27x's CP6 | ||
| 683 | if (state->is_pxa27x) { | ||
| 684 | ARMul_CoProAttach (state, 6, NULL, NULL, | ||
| 685 | NULL, NULL, xscale_cp6_mrc, | ||
| 686 | NULL, NULL, NULL, NULL, NULL, NULL); | ||
| 687 | } | ||
| 688 | //chy 2005-09-19 end------------- | ||
| 689 | ARMul_CoProAttach (state, 13, xscale_cp13_init, | ||
| 690 | xscale_cp13_exit, xscale_cp13_ldc, | ||
| 691 | xscale_cp13_stc, xscale_cp13_mrc, | ||
| 692 | xscale_cp13_mcr, NULL, NULL, xscale_cp13_cdp, | ||
| 693 | xscale_cp13_read_reg, | ||
| 694 | xscale_cp13_write_reg); | ||
| 695 | |||
| 696 | ARMul_CoProAttach (state, 14, xscale_cp14_init, | ||
| 697 | xscale_cp14_exit, xscale_cp14_ldc, | ||
| 698 | xscale_cp14_stc, xscale_cp14_mrc, | ||
| 699 | xscale_cp14_mcr, NULL, NULL, xscale_cp14_cdp, | ||
| 700 | xscale_cp14_read_reg, | ||
| 701 | xscale_cp14_write_reg); | ||
| 702 | //chy: 2003-08-24. | ||
| 703 | ARMul_CoProAttach (state, 15, xscale_cp15_init, | ||
| 704 | xscale_cp15_exit, xscale_cp15_ldc, | ||
| 705 | xscale_cp15_stc, xscale_cp15_mrc, | ||
| 706 | xscale_cp15_mcr, NULL, NULL, xscale_cp15_cdp, | ||
| 707 | xscale_cp15_read_reg, | ||
| 708 | xscale_cp15_write_reg); | ||
| 709 | } | ||
| 710 | else if (state->is_v6) { | ||
| 711 | ARMul_CoProAttach (state, 10, VFPInit, NULL, VFPLDC, VFPSTC, | ||
| 712 | VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL); | ||
| 713 | ARMul_CoProAttach (state, 11, VFPInit, NULL, VFPLDC, VFPSTC, | ||
| 714 | VFPMRC, VFPMCR, VFPMRRC, VFPMCRR, VFPCDP, NULL, NULL); | ||
| 715 | |||
| 716 | ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL, | ||
| 717 | MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL); | ||
| 718 | } | ||
| 719 | else { //all except xscale | ||
| 720 | ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL, | ||
| 721 | // MMUMRC, MMUMCR, NULL, MMURead, MMUWrite); | ||
| 722 | MMUMRC, MMUMCR, NULL, NULL, NULL, NULL, NULL); | ||
| 723 | } | ||
| 724 | //chy 2003-09-03 do it in future!!!!???? | ||
| 725 | #if 0 | ||
| 726 | if (state->is_iWMMXt) { | ||
| 727 | ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC, | ||
| 728 | NULL, NULL, IwmmxtCDP, NULL, NULL); | ||
| 729 | |||
| 730 | ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL, | ||
| 731 | IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL, | ||
| 732 | NULL); | ||
| 733 | } | ||
| 734 | #endif | ||
| 735 | //----------------------------------------------------------------------------- | ||
| 736 | //chy 2004-05-25, found the user/system code visit CP 1,2, so I add below code. | ||
| 737 | ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL, | ||
| 738 | ValMRC, ValMCR, NULL, NULL, NULL, NULL, NULL); | ||
| 739 | ARMul_CoProAttach (state, 2, NULL, NULL, ValLDC, ValSTC, | ||
| 740 | NULL, NULL, NULL, NULL, NULL, NULL, NULL); | ||
| 741 | //------------------------------------------------------------------------------ | ||
| 742 | /* No handlers below here. */ | ||
| 743 | |||
| 744 | /* Call all the initialisation routines. */ | ||
| 745 | for (i = 0; i < 16; i++) | ||
| 746 | if (state->CPInit[i]) | ||
| 747 | (state->CPInit[i]) (state); | ||
| 748 | |||
| 749 | return TRUE; | ||
| 750 | } | ||
| 751 | |||
| 752 | /* Install co-processor finalisation routines in this routine. */ | ||
| 753 | |||
| 754 | void | ||
| 755 | ARMul_CoProExit (ARMul_State * state) | ||
| 756 | { | ||
| 757 | register unsigned i; | ||
| 758 | |||
| 759 | for (i = 0; i < 16; i++) | ||
| 760 | if (state->CPExit[i]) | ||
| 761 | (state->CPExit[i]) (state); | ||
| 762 | |||
| 763 | for (i = 0; i < 16; i++) /* Detach all handlers. */ | ||
| 764 | ARMul_CoProDetach (state, i); | ||
| 765 | } | ||
| 766 | |||
| 767 | /* Routines to hook Co-processors into ARMulator. */ | ||
| 768 | |||
| 769 | void | ||
| 770 | ARMul_CoProAttach (ARMul_State * state, | ||
| 771 | unsigned number, | ||
| 772 | ARMul_CPInits * init, | ||
| 773 | ARMul_CPExits * exit, | ||
| 774 | ARMul_LDCs * ldc, | ||
| 775 | ARMul_STCs * stc, | ||
| 776 | ARMul_MRCs * mrc, | ||
| 777 | ARMul_MCRs * mcr, | ||
| 778 | ARMul_MRRCs * mrrc, | ||
| 779 | ARMul_MCRRs * mcrr, | ||
| 780 | ARMul_CDPs * cdp, | ||
| 781 | ARMul_CPReads * read, ARMul_CPWrites * write) | ||
| 782 | { | ||
| 783 | if (init != NULL) | ||
| 784 | state->CPInit[number] = init; | ||
| 785 | if (exit != NULL) | ||
| 786 | state->CPExit[number] = exit; | ||
| 787 | if (ldc != NULL) | ||
| 788 | state->LDC[number] = ldc; | ||
| 789 | if (stc != NULL) | ||
| 790 | state->STC[number] = stc; | ||
| 791 | if (mrc != NULL) | ||
| 792 | state->MRC[number] = mrc; | ||
| 793 | if (mcr != NULL) | ||
| 794 | state->MCR[number] = mcr; | ||
| 795 | if (mrrc != NULL) | ||
| 796 | state->MRRC[number] = mrrc; | ||
| 797 | if (mcrr != NULL) | ||
| 798 | state->MCRR[number] = mcrr; | ||
| 799 | if (cdp != NULL) | ||
| 800 | state->CDP[number] = cdp; | ||
| 801 | if (read != NULL) | ||
| 802 | state->CPRead[number] = read; | ||
| 803 | if (write != NULL) | ||
| 804 | state->CPWrite[number] = write; | ||
| 805 | } | ||
| 806 | |||
| 807 | void | ||
| 808 | ARMul_CoProDetach (ARMul_State * state, unsigned number) | ||
| 809 | { | ||
| 810 | ARMul_CoProAttach (state, number, NULL, NULL, | ||
| 811 | NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R, | ||
| 812 | NoCoPro5W, NoCoPro5R, NoCoPro3R, NULL, NULL); | ||
| 813 | |||
| 814 | state->CPInit[number] = NULL; | ||
| 815 | state->CPExit[number] = NULL; | ||
| 816 | state->CPRead[number] = NULL; | ||
| 817 | state->CPWrite[number] = NULL; | ||
| 818 | } | ||
| 819 | |||
| 820 | //chy 2003-09-03:below funs just replace the old ones | ||
| 821 | |||
| 822 | /* Set the XScale FSR and FAR registers. */ | ||
| 823 | |||
| 824 | void | ||
| 825 | XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far) | ||
| 826 | { | ||
| 827 | //if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0) | ||
| 828 | if (!state->is_XScale) | ||
| 829 | return; | ||
| 830 | //assume opcode2=0 crm =0 | ||
| 831 | xscale_cp15_write_reg (state, 5, fsr); | ||
| 832 | xscale_cp15_write_reg (state, 6, _far); | ||
| 833 | } | ||
| 834 | |||
| 835 | //chy 2003-09-03 seems 0 is CANT, 1 is DONE ???? | ||
| 836 | int | ||
| 837 | XScale_debug_moe (ARMul_State * state, int moe) | ||
| 838 | { | ||
| 839 | //chy 2003-09-03 , W/R CP14 reg, now it's no use ???? | ||
| 840 | printf ("SKYEYE: XScale_debug_moe called !!!!\n"); | ||
| 841 | return 1; | ||
| 842 | } | ||