1/* V810 Emulator 2 * 3 * Copyright (C) 2006 David Tucker 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20 21 // Macro test taken from http://gcc.gnu.org/viewcvs/trunk/gcc/testsuite/gcc.dg/20020919-1.c?view=markup&pathrev=142696 22 //#if defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) || defined (__POWERPC__) || defined (PPC) || defined (_IBMR2) 23 // v810_timestamp_t timestamp_rl asm("15") = v810_timestamp; 24 //#elif defined(__x86_64__) 25 // v810_timestamp_t timestamp_rl asm("r11") = v810_timestamp; 26 //#else 27 v810_timestamp_t timestamp_rl = v810_timestamp; 28 //#endif 29 30 uint32 opcode; 31 uint32 tmp2; 32 int val = 0; 33 34 35 #define ADDCLOCK(__n) { timestamp += __n; } 36 37 #define CHECK_HALTED(); { if(Halted && timestamp < next_event_ts) { timestamp = next_event_ts; } } 38 39 while(Running) 40 { 41 #ifdef RB_DEBUGMODE 42 uint32 old_PC = RB_GETPC(); 43 #endif 44 uint32 tmpop; 45 46 assert(timestamp_rl <= next_event_ts); 47 48 if(!IPendingCache) 49 { 50 if(Halted) 51 { 52 timestamp_rl = next_event_ts; 53 } 54 else if(in_bstr) 55 { 56 tmpop = in_bstr_to; 57 opcode = tmpop >> 9; 58 goto op_BSTR; 59 } 60 } 61 62 while(timestamp_rl < next_event_ts) 63 { 64 #ifdef RB_DEBUGMODE 65 old_PC = RB_GETPC(); 66 #endif 67 68 P_REG[0] = 0; //Zero the Zero Reg!!! 69 70 RB_CPUHOOK(RB_GETPC()); 71 72 { 73 //printf("%08x\n", RB_GETPC()); 74 { 75 v810_timestamp_t timestamp = timestamp_rl; 76 77 tmpop = RB_RDOP(0, 0); 78 79 timestamp_rl = timestamp; 80 } 81 82 opcode = (tmpop >> 9) | IPendingCache; 83 84 //printf("%02x\n", opcode >> 1); 85#if HAVE_COMPUTED_GOTO 86 #define CGBEGIN static const void *const op_goto_table[256] = { 87 #define CGE(l) &&l, 88 #define CGEND }; goto *op_goto_table[opcode]; 89#else 90 /* (uint8) cast for cheaper alternative to generated branch+compare bounds check instructions, but still more 91 expensive than computed goto which needs no masking nor bounds checking. 92 */ 93 #define CGBEGIN { enum { CGESB = 1 + __COUNTER__ }; switch((uint8)opcode) { 94 #define CGE(l) case __COUNTER__ - CGESB: goto l; 95 #define CGEND } } 96#endif 97 98 CGBEGIN 99 CGE(op_MOV) CGE(op_MOV) CGE(op_ADD) CGE(op_ADD) CGE(op_SUB) CGE(op_SUB) CGE(op_CMP) CGE(op_CMP) 100 CGE(op_SHL) CGE(op_SHL) CGE(op_SHR) CGE(op_SHR) CGE(op_JMP) CGE(op_JMP) CGE(op_SAR) CGE(op_SAR) 101 CGE(op_MUL) CGE(op_MUL) CGE(op_DIV) CGE(op_DIV) CGE(op_MULU) CGE(op_MULU) CGE(op_DIVU) CGE(op_DIVU) 102 CGE(op_OR) CGE(op_OR) CGE(op_AND) CGE(op_AND) CGE(op_XOR) CGE(op_XOR) CGE(op_NOT) CGE(op_NOT) 103 CGE(op_MOV_I) CGE(op_MOV_I) CGE(op_ADD_I) CGE(op_ADD_I) CGE(op_SETF) CGE(op_SETF) CGE(op_CMP_I) CGE(op_CMP_I) 104 CGE(op_SHL_I) CGE(op_SHL_I) CGE(op_SHR_I) CGE(op_SHR_I) CGE(op_EI) CGE(op_EI) CGE(op_SAR_I) CGE(op_SAR_I) 105 CGE(op_TRAP) CGE(op_TRAP) CGE(op_RETI) CGE(op_RETI) CGE(op_HALT) CGE(op_HALT) CGE(op_INVALID) CGE(op_INVALID) 106 CGE(op_LDSR) CGE(op_LDSR) CGE(op_STSR) CGE(op_STSR) CGE(op_DI) CGE(op_DI) CGE(op_BSTR) CGE(op_BSTR) 107 CGE(op_BV) CGE(op_BL) CGE(op_BE) CGE(op_BNH) CGE(op_BN) CGE(op_BR) CGE(op_BLT) CGE(op_BLE) 108 CGE(op_BNV) CGE(op_BNL) CGE(op_BNE) CGE(op_BH) CGE(op_BP) CGE(op_NOP) CGE(op_BGE) CGE(op_BGT) 109 CGE(op_MOVEA) CGE(op_MOVEA) CGE(op_ADDI) CGE(op_ADDI) CGE(op_JR) CGE(op_JR) CGE(op_JAL) CGE(op_JAL) 110 CGE(op_ORI) CGE(op_ORI) CGE(op_ANDI) CGE(op_ANDI) CGE(op_XORI) CGE(op_XORI) CGE(op_MOVHI) CGE(op_MOVHI) 111 CGE(op_LD_B) CGE(op_LD_B) CGE(op_LD_H) CGE(op_LD_H) CGE(op_INVALID) CGE(op_INVALID) CGE(op_LD_W) CGE(op_LD_W) 112 CGE(op_ST_B) CGE(op_ST_B) CGE(op_ST_H) CGE(op_ST_H) CGE(op_INVALID) CGE(op_INVALID) CGE(op_ST_W) CGE(op_ST_W) 113 CGE(op_IN_B) CGE(op_IN_B) CGE(op_IN_H) CGE(op_IN_H) CGE(op_CAXI) CGE(op_CAXI) CGE(op_IN_W) CGE(op_IN_W) 114 CGE(op_OUT_B) CGE(op_OUT_B) CGE(op_OUT_H) CGE(op_OUT_H) CGE(op_FPP) CGE(op_FPP) CGE(op_OUT_W) CGE(op_OUT_W) 115 116 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 117 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 118 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 119 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 120 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 121 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 122 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 123 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 124 125 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 126 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 127 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 128 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 129 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 130 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 131 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) 132 CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INVALID) CGE(op_INT_HANDLER) 133 CGEND 134 135 // Bit string subopcodes 136 #define DO_AM_BSTR() \ 137 const uint32 arg1 = (tmpop >> 5) & 0x1F; \ 138 const uint32 arg2 = (tmpop & 0x1F); \ 139 RB_INCPCBY2(); 140 141 142 #define DO_AM_FPP() \ 143 const uint32 arg1 = (tmpop >> 5) & 0x1F; \ 144 const uint32 arg2 = (tmpop & 0x1F); \ 145 const uint32 arg3 = ((RB_RDOP(2) >> 10)&0x3F); \ 146 RB_INCPCBY4(); 147 148 149 #define DO_AM_UDEF() \ 150 RB_INCPCBY2(); 151 152 #define DO_AM_I() \ 153 const uint32 arg1 = tmpop & 0x1F; \ 154 const uint32 arg2 = (tmpop >> 5) & 0x1F; \ 155 RB_INCPCBY2(); 156 157 #define DO_AM_II() DO_AM_I(); 158 159 160 #define DO_AM_IV() \ 161 const uint32 arg1 = ((tmpop & 0x000003FF) << 16) | RB_RDOP(2); \ 162 163 164 #define DO_AM_V() \ 165 const uint32 arg3 = (tmpop >> 5) & 0x1F; \ 166 const uint32 arg2 = tmpop & 0x1F; \ 167 const uint32 arg1 = RB_RDOP(2); \ 168 RB_INCPCBY4(); 169 170 171 #define DO_AM_VIa() \ 172 const uint32 arg1 = RB_RDOP(2); \ 173 const uint32 arg2 = tmpop & 0x1F; \ 174 const uint32 arg3 = (tmpop >> 5) & 0x1F; \ 175 RB_INCPCBY4(); \ 176 177 178 #define DO_AM_VIb() \ 179 const uint32 arg1 = (tmpop >> 5) & 0x1F; \ 180 const uint32 arg2 = RB_RDOP(2); \ 181 const uint32 arg3 = (tmpop & 0x1F); \ 182 RB_INCPCBY4(); \ 183 184 #define DO_AM_IX() \ 185 const uint32 arg1 = (tmpop & 0x1); \ 186 RB_INCPCBY2(); \ 187 188 #define DO_AM_III() \ 189 const uint32 arg1 = tmpop & 0x1FE; 190 191 #include "v810_do_am.h" 192 193 #define BEGIN_OP(meowtmpop) { op_##meowtmpop: v810_timestamp_t timestamp = timestamp_rl; DO_##meowtmpop ##_AM(); 194 #define END_OP() timestamp_rl = timestamp; goto OpFinished; } 195 #define END_OP_SKIPLO() timestamp_rl = timestamp; goto OpFinishedSkipLO; } 196 197 BEGIN_OP(MOV); 198 ADDCLOCK(1); 199 SetPREG(arg2, P_REG[arg1]); 200 END_OP(); 201 202 203 BEGIN_OP(ADD); 204 ADDCLOCK(1); 205 uint32 temp = P_REG[arg2] + P_REG[arg1]; 206 207 SetFlag(PSW_OV, ((P_REG[arg2]^(~P_REG[arg1]))&(P_REG[arg2]^temp))&0x80000000); 208 SetFlag(PSW_CY, temp < P_REG[arg2]); 209 210 SetPREG(arg2, temp); 211 SetSZ(P_REG[arg2]); 212 END_OP(); 213 214 215 BEGIN_OP(SUB); 216 ADDCLOCK(1); 217 uint32 temp = P_REG[arg2] - P_REG[arg1]; 218 219 SetFlag(PSW_OV, ((P_REG[arg2]^P_REG[arg1])&(P_REG[arg2]^temp))&0x80000000); 220 SetFlag(PSW_CY, temp > P_REG[arg2]); 221 222 SetPREG(arg2, temp); 223 SetSZ(P_REG[arg2]); 224 END_OP(); 225 226 227 BEGIN_OP(CMP); 228 ADDCLOCK(1); 229 uint32 temp = P_REG[arg2] - P_REG[arg1]; 230 231 SetSZ(temp); 232 SetFlag(PSW_OV, ((P_REG[arg2]^P_REG[arg1])&(P_REG[arg2]^temp))&0x80000000); 233 SetFlag(PSW_CY, temp > P_REG[arg2]); 234 END_OP(); 235 236 237 BEGIN_OP(SHL); 238 ADDCLOCK(1); 239 val = P_REG[arg1] & 0x1F; 240 241 // set CY before we destroy the regisrer info.... 242 SetFlag(PSW_CY, (val != 0) && ((P_REG[arg2] >> (32 - val))&0x01) ); 243 SetFlag(PSW_OV, FALSE); 244 SetPREG(arg2, P_REG[arg2] << val); 245 SetSZ(P_REG[arg2]); 246 END_OP(); 247 248 BEGIN_OP(SHR); 249 ADDCLOCK(1); 250 val = P_REG[arg1] & 0x1F; 251 // set CY before we destroy the regisrer info.... 252 SetFlag(PSW_CY, (val) && ((P_REG[arg2] >> (val-1))&0x01)); 253 SetFlag(PSW_OV, FALSE); 254 SetPREG(arg2, P_REG[arg2] >> val); 255 SetSZ(P_REG[arg2]); 256 END_OP(); 257 258 BEGIN_OP(JMP); 259 260 (void)arg2; // arg2 is unused. 261 262 ADDCLOCK(3); 263 RB_SETPC((P_REG[arg1] & 0xFFFFFFFE)); 264 if(RB_AccurateMode) 265 { 266 BRANCH_ALIGN_CHECK(PC); 267 } 268 RB_ADDBT(old_PC, RB_GETPC(), 0); 269 END_OP(); 270 271 BEGIN_OP(SAR); 272 ADDCLOCK(1); 273 val = P_REG[arg1] & 0x1F; 274 275 SetFlag(PSW_CY, (val) && ((P_REG[arg2]>>(val-1))&0x01) ); 276 SetFlag(PSW_OV, FALSE); 277 278 SetPREG(arg2, (uint32) ((int32)P_REG[arg2] >> val)); 279 280 SetSZ(P_REG[arg2]); 281 END_OP(); 282 283 BEGIN_OP(OR); 284 ADDCLOCK(1); 285 SetPREG(arg2, P_REG[arg1] | P_REG[arg2]); 286 SetFlag(PSW_OV, FALSE); 287 SetSZ(P_REG[arg2]); 288 END_OP(); 289 290 BEGIN_OP(AND); 291 ADDCLOCK(1); 292 SetPREG(arg2, P_REG[arg1] & P_REG[arg2]); 293 SetFlag(PSW_OV, FALSE); 294 SetSZ(P_REG[arg2]); 295 END_OP(); 296 297 BEGIN_OP(XOR); 298 ADDCLOCK(1); 299 SetPREG(arg2, P_REG[arg1] ^ P_REG[arg2]); 300 SetFlag(PSW_OV, FALSE); 301 SetSZ(P_REG[arg2]); 302 END_OP(); 303 304 BEGIN_OP(NOT); 305 ADDCLOCK(1); 306 SetPREG(arg2, ~P_REG[arg1]); 307 SetFlag(PSW_OV, FALSE); 308 SetSZ(P_REG[arg2]); 309 END_OP(); 310 311 BEGIN_OP(MOV_I); 312 ADDCLOCK(1); 313 SetPREG(arg2,sign_5(arg1)); 314 END_OP(); 315 316 BEGIN_OP(ADD_I); 317 ADDCLOCK(1); 318 uint32 temp = P_REG[arg2] + sign_5(arg1); 319 320 SetFlag(PSW_OV, ((P_REG[arg2]^(~sign_5(arg1)))&(P_REG[arg2]^temp))&0x80000000); 321 SetFlag(PSW_CY, (uint32)temp < P_REG[arg2]); 322 323 SetPREG(arg2, (uint32)temp); 324 SetSZ(P_REG[arg2]); 325 END_OP(); 326 327 328 BEGIN_OP(SETF); 329 ADDCLOCK(1); 330 331 P_REG[arg2] = 0; 332 333 switch (arg1 & 0x0F) 334 { 335 case COND_V: 336 if (TESTCOND_V) P_REG[arg2] = 1; 337 break; 338 case COND_C: 339 if (TESTCOND_C) P_REG[arg2] = 1; 340 break; 341 case COND_Z: 342 if (TESTCOND_Z) P_REG[arg2] = 1; 343 break; 344 case COND_NH: 345 if (TESTCOND_NH) P_REG[arg2] = 1; 346 break; 347 case COND_S: 348 if (TESTCOND_S) P_REG[arg2] = 1; 349 break; 350 case COND_T: 351 P_REG[arg2] = 1; 352 break; 353 case COND_LT: 354 if (TESTCOND_LT) P_REG[arg2] = 1; 355 break; 356 case COND_LE: 357 if (TESTCOND_LE) P_REG[arg2] = 1; 358 break; 359 case COND_NV: 360 if (TESTCOND_NV) P_REG[arg2] = 1; 361 break; 362 case COND_NC: 363 if (TESTCOND_NC) P_REG[arg2] = 1; 364 break; 365 case COND_NZ: 366 if (TESTCOND_NZ) P_REG[arg2] = 1; 367 break; 368 case COND_H: 369 if (TESTCOND_H) P_REG[arg2] = 1; 370 break; 371 case COND_NS: 372 if (TESTCOND_NS) P_REG[arg2] = 1; 373 break; 374 case COND_F: 375 //always false! do nothing more 376 break; 377 case COND_GE: 378 if (TESTCOND_GE) P_REG[arg2] = 1; 379 break; 380 case COND_GT: 381 if (TESTCOND_GT) P_REG[arg2] = 1; 382 break; 383 } 384 END_OP(); 385 386 BEGIN_OP(CMP_I); 387 ADDCLOCK(1); 388 uint32 temp = P_REG[arg2] - sign_5(arg1); 389 390 SetSZ(temp); 391 SetFlag(PSW_OV, ((P_REG[arg2]^(sign_5(arg1)))&(P_REG[arg2]^temp))&0x80000000); 392 SetFlag(PSW_CY, temp > P_REG[arg2]); 393 END_OP(); 394 395 BEGIN_OP(SHR_I); 396 ADDCLOCK(1); 397 SetFlag(PSW_CY, arg1 && ((P_REG[arg2] >> (arg1-1))&0x01) ); 398 // set CY before we destroy the regisrer info.... 399 SetPREG(arg2, P_REG[arg2] >> arg1); 400 SetFlag(PSW_OV, FALSE); 401 SetSZ(P_REG[arg2]); 402 END_OP(); 403 404 BEGIN_OP(SHL_I); 405 ADDCLOCK(1); 406 SetFlag(PSW_CY, arg1 && ((P_REG[arg2] >> (32 - arg1))&0x01) ); 407 // set CY before we destroy the regisrer info.... 408 409 SetPREG(arg2, P_REG[arg2] << arg1); 410 SetFlag(PSW_OV, FALSE); 411 SetSZ(P_REG[arg2]); 412 END_OP(); 413 414 BEGIN_OP(SAR_I); 415 ADDCLOCK(1); 416 SetFlag(PSW_CY, arg1 && ((P_REG[arg2]>>(arg1-1))&0x01) ); 417 418 SetPREG(arg2, (uint32) ((int32)P_REG[arg2] >> arg1)); 419 420 SetFlag(PSW_OV, FALSE); 421 SetSZ(P_REG[arg2]); 422 END_OP(); 423 424 BEGIN_OP(LDSR); // Loads a Sys Reg with the value in specified PR 425 ADDCLOCK(1); // ? 426 427 SetSREG(timestamp, arg1 & 0x1F, P_REG[arg2 & 0x1F]); 428 END_OP(); 429 430 BEGIN_OP(STSR); // Loads a PR with the value in specified Sys Reg 431 ADDCLOCK(1); // ? 432 P_REG[arg2 & 0x1F] = GetSREG(arg1 & 0x1F); 433 END_OP(); 434 435 BEGIN_OP(EI); 436 (void)arg1; // arg1 is unused. 437 (void)arg2; // arg2 is unused. 438 439 if(VBMode) 440 { 441 ADDCLOCK(1); 442 S_REG[PSW] = S_REG[PSW] &~ PSW_ID; 443 RecalcIPendingCache(); 444 } 445 else 446 { 447 ADDCLOCK(1); 448 RB_DECPCBY2(); 449 Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); 450 CHECK_HALTED(); 451 } 452 END_OP(); 453 454 BEGIN_OP(DI); 455 (void)arg1; // arg1 is unused. 456 (void)arg2; // arg2 is unused. 457 458 if(VBMode) 459 { 460 ADDCLOCK(1); 461 S_REG[PSW] |= PSW_ID; 462 IPendingCache = 0; 463 } 464 else 465 { 466 ADDCLOCK(1); 467 RB_DECPCBY2(); 468 Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); 469 CHECK_HALTED(); 470 } 471 END_OP(); 472 473 474 #define COND_BRANCH(cond) \ 475 if(cond) \ 476 { \ 477 ADDCLOCK(3); \ 478 RB_PCRELCHANGE(sign_9(arg1) & 0xFFFFFFFE); \ 479 if(RB_AccurateMode) \ 480 { \ 481 BRANCH_ALIGN_CHECK(PC); \ 482 } \ 483 RB_ADDBT(old_PC, RB_GETPC(), 0); \ 484 } \ 485 else \ 486 { \ 487 ADDCLOCK(1); \ 488 RB_INCPCBY2(); \ 489 } 490 491 BEGIN_OP(BV); 492 COND_BRANCH(TESTCOND_V); 493 END_OP(); 494 495 496 BEGIN_OP(BL); 497 COND_BRANCH(TESTCOND_L); 498 END_OP(); 499 500 BEGIN_OP(BE); 501 COND_BRANCH(TESTCOND_E); 502 END_OP(); 503 504 BEGIN_OP(BNH); 505 COND_BRANCH(TESTCOND_NH); 506 END_OP(); 507 508 BEGIN_OP(BN); 509 COND_BRANCH(TESTCOND_N); 510 END_OP(); 511 512 BEGIN_OP(BR); 513 COND_BRANCH(TRUE); 514 END_OP(); 515 516 BEGIN_OP(BLT); 517 COND_BRANCH(TESTCOND_LT); 518 END_OP(); 519 520 BEGIN_OP(BLE); 521 COND_BRANCH(TESTCOND_LE); 522 END_OP(); 523 524 BEGIN_OP(BNV); 525 COND_BRANCH(TESTCOND_NV); 526 END_OP(); 527 528 BEGIN_OP(BNL); 529 COND_BRANCH(TESTCOND_NL); 530 END_OP(); 531 532 BEGIN_OP(BNE); 533 COND_BRANCH(TESTCOND_NE); 534 END_OP(); 535 536 BEGIN_OP(BH); 537 COND_BRANCH(TESTCOND_H); 538 END_OP(); 539 540 BEGIN_OP(BP); 541 COND_BRANCH(TESTCOND_P); 542 END_OP(); 543 544 BEGIN_OP(BGE); 545 COND_BRANCH(TESTCOND_GE); 546 END_OP(); 547 548 BEGIN_OP(BGT); 549 COND_BRANCH(TESTCOND_GT); 550 END_OP(); 551 552 BEGIN_OP(JR); 553 ADDCLOCK(3); 554 RB_PCRELCHANGE(sign_26(arg1) & 0xFFFFFFFE); 555 if(RB_AccurateMode) 556 { 557 BRANCH_ALIGN_CHECK(PC); 558 } 559 RB_ADDBT(old_PC, RB_GETPC(), 0); 560 END_OP(); 561 562 BEGIN_OP(JAL); 563 ADDCLOCK(3); 564 P_REG[31] = RB_GETPC() + 4; 565 RB_PCRELCHANGE(sign_26(arg1) & 0xFFFFFFFE); 566 if(RB_AccurateMode) 567 { 568 BRANCH_ALIGN_CHECK(PC); 569 } 570 RB_ADDBT(old_PC, RB_GETPC(), 0); 571 END_OP(); 572 573 BEGIN_OP(MOVEA); 574 ADDCLOCK(1); 575 SetPREG(arg3, P_REG[arg2] + sign_16(arg1)); 576 END_OP(); 577 578 BEGIN_OP(ADDI); 579 ADDCLOCK(1); 580 uint32 temp = P_REG[arg2] + sign_16(arg1); 581 582 SetFlag(PSW_OV, ((P_REG[arg2]^(~sign_16(arg1)))&(P_REG[arg2]^temp))&0x80000000); 583 SetFlag(PSW_CY, (uint32)temp < P_REG[arg2]); 584 585 SetPREG(arg3, (uint32)temp); 586 SetSZ(P_REG[arg3]); 587 END_OP(); 588 589 BEGIN_OP(ORI); 590 ADDCLOCK(1); 591 SetPREG(arg3, arg1 | P_REG[arg2]); 592 SetFlag(PSW_OV, FALSE); 593 SetSZ(P_REG[arg3]); 594 END_OP(); 595 596 BEGIN_OP(ANDI); 597 ADDCLOCK(1); 598 SetPREG(arg3, (arg1 & P_REG[arg2])); 599 SetFlag(PSW_OV, FALSE); 600 SetSZ(P_REG[arg3]); 601 END_OP(); 602 603 BEGIN_OP(XORI); 604 ADDCLOCK(1); 605 SetPREG(arg3, arg1 ^ P_REG[arg2]); 606 SetFlag(PSW_OV, FALSE); 607 SetSZ(P_REG[arg3]); 608 END_OP(); 609 610 BEGIN_OP(MOVHI); 611 ADDCLOCK(1); 612 SetPREG(arg3, (arg1 << 16) + P_REG[arg2]); 613 END_OP(); 614 615 // LD.B 616 BEGIN_OP(LD_B); 617 ADDCLOCK(1); 618 tmp2 = (sign_16(arg1)+P_REG[arg2])&0xFFFFFFFF; 619 620 SetPREG(arg3, sign_8(MemRead8(timestamp, tmp2))); 621 622 //should be 3 clocks when executed alone, 2 when precedes another LD, or 1 623 //when precedes an instruction with many clocks (I'm guessing FP, MUL, DIV, etc) 624 if(lastop >= 0) 625 { 626 if(lastop == LASTOP_LD) 627 { 628 ADDCLOCK(1); 629 } 630 else 631 { 632 ADDCLOCK(2); 633 } 634 } 635 lastop = LASTOP_LD; 636 END_OP_SKIPLO(); 637 638 // LD.H 639 BEGIN_OP(LD_H); 640 ADDCLOCK(1); 641 tmp2 = (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFE; 642 SetPREG(arg3, sign_16(MemRead16(timestamp, tmp2))); 643 644 if(lastop >= 0) 645 { 646 if(lastop == LASTOP_LD) 647 { 648 ADDCLOCK(1); 649 } 650 else 651 { 652 ADDCLOCK(2); 653 } 654 } 655 lastop = LASTOP_LD; 656 END_OP_SKIPLO(); 657 658 659 // LD.W 660 BEGIN_OP(LD_W); 661 ADDCLOCK(1); 662 663 tmp2 = (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFC; 664 665 if(MemReadBus32[tmp2 >> 24]) 666 { 667 SetPREG(arg3, MemRead32(timestamp, tmp2)); 668 669 if(lastop >= 0) 670 { 671 if(lastop == LASTOP_LD) 672 { 673 ADDCLOCK(1); 674 } 675 else 676 { 677 ADDCLOCK(2); 678 } 679 } 680 } 681 else 682 { 683 uint32 rv; 684 685 rv = MemRead16(timestamp, tmp2); 686 rv |= MemRead16(timestamp, tmp2 | 2) << 16; 687 688 SetPREG(arg3, rv); 689 690 if(lastop >= 0) 691 { 692 if(lastop == LASTOP_LD) 693 { 694 ADDCLOCK(3); 695 } 696 else 697 { 698 ADDCLOCK(4); 699 } 700 } 701 } 702 lastop = LASTOP_LD; 703 END_OP_SKIPLO(); 704 705 // ST.B 706 BEGIN_OP(ST_B); 707 ADDCLOCK(1); 708 MemWrite8(timestamp, sign_16(arg2)+P_REG[arg3], P_REG[arg1] & 0xFF); 709 710 if(lastop == LASTOP_ST) 711 { 712 ADDCLOCK(1); 713 } 714 lastop = LASTOP_ST; 715 END_OP_SKIPLO(); 716 717 // ST.H 718 BEGIN_OP(ST_H); 719 ADDCLOCK(1); 720 721 MemWrite16(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFE, P_REG[arg1] & 0xFFFF); 722 723 if(lastop == LASTOP_ST) 724 { 725 ADDCLOCK(1); 726 } 727 lastop = LASTOP_ST; 728 END_OP_SKIPLO(); 729 730 // ST.W 731 BEGIN_OP(ST_W); 732 ADDCLOCK(1); 733 tmp2 = (sign_16(arg2)+P_REG[arg3]) & 0xFFFFFFFC; 734 735 if(MemWriteBus32[tmp2 >> 24]) 736 { 737 MemWrite32(timestamp, tmp2, P_REG[arg1]); 738 739 if(lastop == LASTOP_ST) 740 { 741 ADDCLOCK(1); 742 } 743 } 744 else 745 { 746 MemWrite16(timestamp, tmp2, P_REG[arg1] & 0xFFFF); 747 MemWrite16(timestamp, tmp2 | 2, P_REG[arg1] >> 16); 748 749 if(lastop == LASTOP_ST) 750 { 751 ADDCLOCK(3); 752 } 753 } 754 lastop = LASTOP_ST; 755 END_OP_SKIPLO(); 756 757 // IN.B 758 BEGIN_OP(IN_B); 759 { 760 ADDCLOCK(3); 761 SetPREG(arg3, IORead8(timestamp, sign_16(arg1)+P_REG[arg2])); 762 } 763 lastop = LASTOP_IN; 764 END_OP_SKIPLO(); 765 766 767 // IN.H 768 BEGIN_OP(IN_H); 769 { 770 ADDCLOCK(3); 771 SetPREG(arg3, IORead16(timestamp, (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFE)); 772 } 773 lastop = LASTOP_IN; 774 END_OP_SKIPLO(); 775 776 777 // IN.W 778 BEGIN_OP(IN_W); 779 if(IORead32) 780 { 781 ADDCLOCK(3); 782 SetPREG(arg3, IORead32(timestamp, (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFC)); 783 } 784 else 785 { 786 uint32 eff_addr = (sign_16(arg1) + P_REG[arg2]) & 0xFFFFFFFC; 787 uint32 rv; 788 789 ADDCLOCK(5); 790 791 rv = IORead16(timestamp, eff_addr); 792 rv |= IORead16(timestamp, eff_addr | 2) << 16; 793 794 SetPREG(arg3, rv); 795 } 796 lastop = LASTOP_IN; 797 END_OP_SKIPLO(); 798 799 800 // OUT.B 801 BEGIN_OP(OUT_B); 802 ADDCLOCK(1); 803 IOWrite8(timestamp, sign_16(arg2)+P_REG[arg3],P_REG[arg1]&0xFF); 804 805 if(lastop == LASTOP_OUT) 806 { 807 ADDCLOCK(1); 808 } 809 lastop = LASTOP_OUT; 810 END_OP_SKIPLO(); 811 812 813 // OUT.H 814 BEGIN_OP(OUT_H); 815 ADDCLOCK(1); 816 IOWrite16(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFE,P_REG[arg1]&0xFFFF); 817 818 if(lastop == LASTOP_OUT) 819 { 820 ADDCLOCK(1); 821 } 822 lastop = LASTOP_OUT; 823 END_OP_SKIPLO(); 824 825 826 // OUT.W 827 BEGIN_OP(OUT_W); 828 ADDCLOCK(1); 829 830 if(IOWrite32) 831 IOWrite32(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFC,P_REG[arg1]); 832 else 833 { 834 uint32 eff_addr = (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFC; 835 IOWrite16(timestamp, eff_addr, P_REG[arg1] & 0xFFFF); 836 IOWrite16(timestamp, eff_addr | 2, P_REG[arg1] >> 16); 837 } 838 839 if(lastop == LASTOP_OUT) 840 { 841 if(IOWrite32) 842 { 843 ADDCLOCK(1); 844 } 845 else 846 { 847 ADDCLOCK(3); 848 } 849 } 850 lastop = LASTOP_OUT; 851 END_OP_SKIPLO(); 852 853 BEGIN_OP(NOP); 854 (void)arg1; // arg1 is unused. 855 856 ADDCLOCK(1); 857 RB_INCPCBY2(); 858 END_OP(); 859 860 BEGIN_OP(RETI); 861 (void)arg1; // arg1 is unused. 862 863 ADDCLOCK(10); 864 865 //Return from Trap/Interupt 866 if(S_REG[PSW] & PSW_NP) { // Read the FE Reg 867 RB_SETPC(S_REG[FEPC] & 0xFFFFFFFE); 868 S_REG[PSW] = S_REG[FEPSW]; 869 } else { //Read the EI Reg Interupt 870 RB_SETPC(S_REG[EIPC] & 0xFFFFFFFE); 871 S_REG[PSW] = S_REG[EIPSW]; 872 } 873 RecalcIPendingCache(); 874 875 RB_ADDBT(old_PC, RB_GETPC(), 0); 876 END_OP(); 877 878 BEGIN_OP(MUL); 879 ADDCLOCK(13); 880 881 uint64 temp = (int64)(int32)P_REG[arg1] * (int32)P_REG[arg2]; 882 883 SetPREG(30, (uint32)(temp >> 32)); 884 SetPREG(arg2, temp); 885 SetSZ(P_REG[arg2]); 886 SetFlag(PSW_OV, temp != (uint64)(int64)(int32)(uint32)temp); 887 lastop = -1; 888 END_OP_SKIPLO(); 889 890 BEGIN_OP(MULU); 891 ADDCLOCK(13); 892 uint64 temp = (uint64)P_REG[arg1] * (uint64)P_REG[arg2]; 893 894 SetPREG(30, (uint32)(temp >> 32)); 895 SetPREG(arg2, (uint32)temp); 896 897 SetSZ(P_REG[arg2]); 898 SetFlag(PSW_OV, temp != (uint32)temp); 899 lastop = -1; 900 END_OP_SKIPLO(); 901 902 BEGIN_OP(DIVU); 903 ADDCLOCK(36); 904 if(P_REG[arg1] == 0) // Divide by zero! 905 { 906 RB_DECPCBY2(); 907 Exception(ZERO_DIV_HANDLER_ADDR, ECODE_ZERO_DIV); 908 CHECK_HALTED(); 909 } 910 else 911 { 912 // Careful here, since arg2 can be == 30 913 uint32 quotient = (uint32)P_REG[arg2] / (uint32)P_REG[arg1]; 914 uint32 remainder = (uint32)P_REG[arg2] % (uint32)P_REG[arg1]; 915 916 SetPREG(30, remainder); 917 SetPREG(arg2, quotient); 918 919 SetFlag(PSW_OV, FALSE); 920 SetSZ(quotient); 921 } 922 lastop = -1; 923 END_OP_SKIPLO(); 924 925 BEGIN_OP(DIV); 926 //if(P_REG[arg1] & P_REG[arg2] & 0x80000000) 927 //{ 928 // printf("Div: %08x %08x\n", P_REG[arg1], P_REG[arg2]); 929 //} 930 931 ADDCLOCK(38); 932 if((uint32)P_REG[arg1] == 0) // Divide by zero! 933 { 934 RB_DECPCBY2(); 935 Exception(ZERO_DIV_HANDLER_ADDR, ECODE_ZERO_DIV); 936 CHECK_HALTED(); 937 } 938 else 939 { 940 if((P_REG[arg2]==0x80000000)&&(P_REG[arg1]==0xFFFFFFFF)) 941 { 942 SetFlag(PSW_OV, TRUE); 943 P_REG[30]=0; 944 SetPREG(arg2, 0x80000000); 945 SetSZ(P_REG[arg2]); 946 } 947 else 948 { 949 // Careful here, since arg2 can be == 30 950 uint32 quotient = (int32)P_REG[arg2] / (int32)P_REG[arg1]; 951 uint32 remainder = (int32)P_REG[arg2] % (int32)P_REG[arg1]; 952 953 SetPREG(30, remainder); 954 SetPREG(arg2, quotient); 955 956 SetFlag(PSW_OV, FALSE); 957 SetSZ(quotient); 958 } 959 } 960 lastop = -1; 961 END_OP_SKIPLO(); 962 963 BEGIN_OP(FPP); 964 ADDCLOCK(1); 965 fpu_subop(timestamp, arg3, arg1, arg2); 966 lastop = -1; 967 CHECK_HALTED(); 968 END_OP_SKIPLO(); 969 970 BEGIN_OP(BSTR); 971 if(!in_bstr) 972 { 973 ADDCLOCK(1); 974 } 975 976 if(bstr_subop(timestamp, arg2, arg1)) 977 { 978 RB_DECPCBY2(); 979 in_bstr = TRUE; 980 in_bstr_to = tmpop; 981 } 982 else 983 { 984 in_bstr = FALSE; 985 have_src_cache = have_dst_cache = FALSE; 986 } 987 END_OP(); 988 989 BEGIN_OP(HALT); 990 (void)arg1; // arg1 is unused. 991 992 ADDCLOCK(1); 993 Halted = HALT_HALT; 994 //printf("Untested opcode: HALT\n"); 995 END_OP(); 996 997 BEGIN_OP(TRAP); 998 (void)arg2; // arg2 is unused. 999 1000 ADDCLOCK(15); 1001 1002 Exception(TRAP_HANDLER_BASE + (arg1 & 0x10), ECODE_TRAP_BASE + (arg1 & 0x1F)); 1003 CHECK_HALTED(); 1004 END_OP(); 1005 1006 BEGIN_OP(CAXI); 1007 //printf("Untested opcode: caxi\n"); 1008 1009 // Lock bus(N/A) 1010 1011 ADDCLOCK(26); 1012 1013 { 1014 uint32 addr, tmp, compare_temp; 1015 uint32 to_write; 1016 1017 addr = sign_16(arg1) + P_REG[arg2]; 1018 addr &= ~3; 1019 1020 if(MemReadBus32[addr >> 24]) 1021 tmp = MemRead32(timestamp, addr); 1022 else 1023 { 1024 tmp = MemRead16(timestamp, addr); 1025 tmp |= MemRead16(timestamp, addr | 2) << 16; 1026 } 1027 1028 compare_temp = P_REG[arg3] - tmp; 1029 1030 SetSZ(compare_temp); 1031 SetFlag(PSW_OV, ((P_REG[arg3]^tmp)&(P_REG[arg3]^compare_temp))&0x80000000); 1032 SetFlag(PSW_CY, compare_temp > P_REG[arg3]); 1033 1034 if(!compare_temp) // If they're equal... 1035 to_write = P_REG[30]; 1036 else 1037 to_write = tmp; 1038 1039 if(MemWriteBus32[addr >> 24]) 1040 MemWrite32(timestamp, addr, to_write); 1041 else 1042 { 1043 MemWrite16(timestamp, addr, to_write & 0xFFFF); 1044 MemWrite16(timestamp, addr | 2, to_write >> 16); 1045 } 1046 P_REG[arg3] = tmp; 1047 } 1048 1049 // Unlock bus(N/A) 1050 1051 END_OP(); 1052 1053 1054 1055 op_INT_HANDLER: 1056 { 1057 int iNum = ilevel; 1058 1059 S_REG[EIPC] = GetPC(); 1060 S_REG[EIPSW] = S_REG[PSW]; 1061 1062 SetPC(0xFFFFFE00 | (iNum << 4)); 1063 1064 RB_ADDBT(old_PC, RB_GETPC(), 0xFE00 | (iNum << 4)); 1065 1066 S_REG[ECR] = 0xFE00 | (iNum << 4); 1067 1068 S_REG[PSW] |= PSW_EP; 1069 S_REG[PSW] |= PSW_ID; 1070 S_REG[PSW] &= ~PSW_AE; 1071 1072 // Now, set need to set the interrupt enable level to he level that is being processed + 1, 1073 // saturating at 15. 1074 iNum++; 1075 1076 if(iNum > 0x0F) 1077 iNum = 0x0F; 1078 1079 S_REG[PSW] &= ~PSW_IA; 1080 S_REG[PSW] |= iNum << 16; 1081 1082 // Accepting an interrupt takes us out of normal HALT status, of course! 1083 Halted = HALT_NONE; 1084 1085 // Invalidate our bitstring state(forces the instruction to be re-read, and the r/w buffers reloaded). 1086 in_bstr = FALSE; 1087 have_src_cache = FALSE; 1088 have_dst_cache = FALSE; 1089 1090 IPendingCache = 0; 1091 1092 goto OpFinished; 1093 } 1094 1095 1096 BEGIN_OP(INVALID); 1097 RB_DECPCBY2(); 1098 if(!RB_AccurateMode) 1099 { 1100 RB_SETPC(RB_GETPC()); 1101 if((uint32)(RB_RDOP(0, 0) >> 9) != opcode) 1102 { 1103 //printf("Trampoline: %08x %02x\n", RB_GETPC(), opcode >> 1); 1104 } 1105 else 1106 { 1107 ADDCLOCK(1); 1108 Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); 1109 CHECK_HALTED(); 1110 } 1111 } 1112 else 1113 { 1114 ADDCLOCK(1); 1115 Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); 1116 CHECK_HALTED(); 1117 } 1118 END_OP(); 1119 1120 } 1121 1122 OpFinished: ; 1123 lastop = opcode; 1124 OpFinishedSkipLO: ; 1125 } // end while(timestamp_rl < next_event_ts) 1126 next_event_ts = event_handler(timestamp_rl); 1127 //printf("Next: %d, Cur: %d\n", next_event_ts, timestamp); 1128 } 1129 1130v810_timestamp = timestamp_rl; 1131