00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00080 #include "StdAfx.h"
00081 #include "AlphaCPU.h"
00082
00083 #include "Serial.h"
00084 #include "AliM1543C_ide.h"
00085 #include "Disk.h"
00086
00087
00088
00089
00090
00091
00092 #define p4 state.r[32 + 4]
00093 #define p5 state.r[32 + 5]
00094 #define p6 state.r[32 + 6]
00095 #define p7 state.r[32 + 7]
00096
00097 #define p20 state.r[32 + 20]
00098 #define p21 state.r[32 + 21]
00099 #define p22 state.r[32 + 22]
00100 #define p23 state.r[32 + 23]
00101
00102 #define r0 state.r[0]
00103 #define r1 state.r[1]
00104 #define r2 state.r[2]
00105 #define r3 state.r[3]
00106
00107
00108
00109
00110
00111 #define r8 state.r[8]
00112 #define r9 state.r[9]
00113 #define r10 state.r[10]
00114 #define r11 state.r[11]
00115 #define r12 state.r[12]
00116 #define r13 state.r[13]
00117 #define r14 state.r[14]
00118 #define r15 state.r[15]
00119 #define r16 state.r[16]
00120 #define r17 state.r[17]
00121 #define r18 state.r[18]
00122 #define r19 state.r[19]
00123
00124
00125
00126
00127
00128 #define r24 state.r[24]
00129
00130
00131
00132 #define r27 state.r[27]
00133 #define r28 state.r[28]
00134 #define r29 state.r[29]
00135 #define r30 state.r[30]
00136 #define r31 state.r[31]
00137
00138 #define hw_stq(a, b) cSystem->WriteMem(a &~U64(0x7), 64, b, this)
00139 #define hw_stl(a, b) cSystem->WriteMem(a &~U64(0x3), 32, b, this)
00140 #define stq(a, b) \
00141 if(virt2phys(a, &phys_address, ACCESS_WRITE, NULL, 0)) \
00142 return -1; \
00143 cSystem->WriteMem(phys_address, 64, b, this);
00144 #define ldq(a, b) \
00145 if(virt2phys(a, &phys_address, ACCESS_READ, NULL, 0)) \
00146 return -1; \
00147 b = cSystem->ReadMem(phys_address, 64, this);
00148 #define stl(a, b) \
00149 if(virt2phys(a, &phys_address, ACCESS_WRITE, NULL, 0)) \
00150 return -1; \
00151 cSystem->WriteMem(phys_address, 32, b, this);
00152 #define ldl(a, b) \
00153 if(virt2phys(a, &phys_address, ACCESS_READ, NULL, 0)) \
00154 return -1; \
00155 b = sext_u64_32(cSystem->ReadMem(phys_address, 32, this));
00156 #define ldb(a, b) \
00157 if(virt2phys(a, &phys_address, ACCESS_READ, NULL, 0)) \
00158 return -1; \
00159 b = (char) (cSystem->ReadMem(phys_address, 8, this));
00160 #define hw_ldq(a, b) b = cSystem->ReadMem(a &~U64(0x7), 64, this)
00161 #define hw_ldl(a, b) b = sext_u64_32(cSystem->ReadMem(a &~U64(0x3), 32, this));
00162 #define hw_ldbu(a, b) b = cSystem->ReadMem(a, 8, this)
00163
00172 static int ipl_ier_mask[32][6] =
00173 {
00174
00175
00176 { 0x3f, 0, 1, 3, 0xfffe, 1 },
00177 { 0x3f, 0, 1, 3, 0xfffc, 1 },
00178 { 0x3f, 0, 1, 3, 0xfff8, 0 },
00179 { 0x3f, 0, 1, 3, 0xfff0, 0 },
00180 { 0x3f, 0, 1, 3, 0xffe0, 0 },
00181 { 0x3f, 0, 1, 3, 0xffc0, 0 },
00182 { 0x3f, 0, 1, 3, 0xff80, 0 },
00183 { 0x3f, 0, 1, 3, 0xff00, 0 },
00184 { 0x3f, 0, 1, 3, 0xfe00, 0 },
00185 { 0x3f, 0, 1, 3, 0xfc00, 0 },
00186 { 0x3f, 0, 1, 3, 0xf800, 0 },
00187 { 0x3f, 0, 1, 3, 0xf000, 0 },
00188 { 0x3f, 0, 1, 3, 0xe000, 0 },
00189 { 0x3f, 0, 1, 3, 0xc000, 0 },
00190 { 0x3f, 0, 1, 3, 0x8000, 0 },
00191 { 0x3f, 0, 1, 3, 0, 0 },
00192 { 0x3f, 0, 1, 3, 0, 0 },
00193 { 0x3f, 0, 1, 3, 0, 0 },
00194 { 0x3f, 0, 1, 3, 0, 0 },
00195 { 0x3f, 0, 1, 3, 0, 0 },
00196 { 0x3f, 0, 1, 3, 0, 0 },
00197 { 0x3d, 0, 1, 3, 0, 0 },
00198 { 0x31, 0, 1, 3, 0, 0 },
00199 { 0x31, 0, 1, 3, 0, 0 },
00200 { 0x31, 0, 1, 3, 0, 0 },
00201 { 0x31, 0, 1, 3, 0, 0 },
00202 { 0x31, 0, 1, 3, 0, 0 },
00203 { 0x31, 0, 1, 3, 0, 0 },
00204 { 0x31, 0, 1, 3, 0, 0 },
00205 { 0x31, 0, 1, 0, 0, 0 },
00206 { 0x31, 0, 1, 3, 0, 0 },
00207 { 0x10, 0, 1, 3, 0, 0 }
00208 };
00209
00210
00211
00217
00218
00222 void CAlphaCPU::vmspal_call_cflush()
00223 {
00224
00225
00226 }
00227
00231 void CAlphaCPU::vmspal_call_draina()
00232 {
00233
00234
00235 }
00236
00240 void CAlphaCPU::vmspal_call_ldqp()
00241 {
00242 hw_ldq(r16, r0);
00243 }
00244
00248 void CAlphaCPU::vmspal_call_stqp()
00249 {
00250 hw_stq(r16, r17);
00251 }
00252
00256 void CAlphaCPU::vmspal_call_swpctx()
00257 {
00258 p23 = state.pc;
00259
00260 if(r16 & 0x7f)
00261 {
00262
00263
00264 p4 = 0x430;
00265 hw_stq(p21 + 0x150, p23);
00266 hw_stq(p21 + 0x158, p4);
00267 vmspal_int_initiate_exception();
00268 return;
00269 }
00270
00271 hw_ldq(r16 + 0x30, p4);
00272 hw_ldq(r16 + 0x38, p5);
00273 hw_ldq(r16 + 0x28, p6);
00274
00275 p20 = state.aster | (state.astrr << 4);
00276
00277 p6 &= 0xff;
00278 state.asn0 = (int) p6;
00279 state.asn1 = (int) p6;
00280 state.asn = (int) p6;
00281 state.aster = (int) p4 & 0xf;
00282 state.astrr = (int) (p4 >> 4) & 0xf;
00283 state.fpen = (int) p5 & 1;
00284 state.ppcen = (int) (p5 >> 0x3e) & 1;
00285 state.check_int = true;
00286
00287 hw_ldq(r16 + 0x40, p7);
00288 hw_ldq(r16 + 0x20, p6);
00289
00290 p4 = (state.cc & U64(0xffffffff)) + state.cc_offset;
00291 state.cc_offset = ((u32) p7 & 0xffffffff) - (state.cc & U64(0xffffffff));
00292
00293 p6 <<= 0x0d;
00294 hw_stq(p21 + 8, p6);
00295 hw_ldq(p21 + 0x10, p5);
00296 hw_ldq(r16, p6);
00297 hw_stl(p5 + 0x40, p4);
00298 hw_stq(p5 + 0x30, p20);
00299 hw_stq(p5, r30);
00300
00301 r30 = p6;
00302 hw_stq(p21 + 0x10, r16);
00303 }
00304
00308 void CAlphaCPU::vmspal_call_mfpr_asn()
00309 {
00310 r0 = state.asn;
00311 }
00312
00316 void CAlphaCPU::vmspal_call_mtpr_asten()
00317 {
00318 r0 = state.aster;
00319 state.aster &= r16;
00320 state.aster |= (r16 >> 4) & 0xf;
00321 state.check_int = true;
00322 }
00323
00327 void CAlphaCPU::vmspal_call_mtpr_astsr()
00328 {
00329 r0 = state.astrr;
00330 state.astrr &= r16;
00331 state.astrr |= (r16 >> 4) & 0xf;
00332 state.check_int = true;
00333 }
00334
00338 void CAlphaCPU::vmspal_call_cserve()
00339 {
00340 p23 = state.pc;
00341
00342 switch(r16)
00343 {
00344 case 0x10: hw_ldl(r17, r0); break;
00345 case 0x11: hw_stl(r17, r18); break;
00346 case 0x12: set_pc(0x12e21); break;
00347 case 0x13: set_pc(0x12f95); break;
00348 case 0x14: set_pc(0x13115); break;
00349 case 0x15: set_pc(0x131c1); break;
00350 case 0x40: set_pc(0x13249); break;
00351 case 0x41: hw_ldq(p21 + 0x98, r0); break;
00352 case 0x42: set_pc(0x13781); break;
00353 case 0x43: set_pc(0x13261); break;
00354 case 0x44: set_pc(r17); break;
00355 case 0x45: set_pc(0x13289); break;
00356 case 0x65: set_pc(0x132bd); break;
00357 case 0x3e: set_pc(0x1344d); break;
00358 case 0x66: set_pc(0x133e9); break;
00359 }
00360 }
00361
00365 void CAlphaCPU::vmspal_call_mfpr_fen()
00366 {
00367 r0 = state.fpen ? 1 : 0;
00368 }
00369
00373 void CAlphaCPU::vmspal_call_mtpr_fen()
00374 {
00375 hw_ldq(p21 + 0x10, p4);
00376 state.fpen = (r16 & 1);
00377 hw_stl(p4 + 0x38, r16);
00378 }
00379
00383 void CAlphaCPU::vmspal_call_mfpr_ipl()
00384 {
00385 r0 = (p22 >> 8) & 0x1f;
00386 }
00387
00391 void CAlphaCPU::vmspal_call_mtpr_ipl()
00392 {
00393 r0 = (p22 >> 8) & 0xff;
00394 p22 &= ~U64(0xff00);
00395 p22 |= (r16 << 8);
00396 state.eien = ipl_ier_mask[r16][0];
00397 state.slen = ipl_ier_mask[r16][1];
00398 state.cren = ipl_ier_mask[r16][2];
00399 state.pcen = ipl_ier_mask[r16][3];
00400 state.sien = ipl_ier_mask[r16][4];
00401 state.asten = ipl_ier_mask[r16][5];
00402 state.check_int = true;
00403 }
00404
00408 void CAlphaCPU::vmspal_call_mfpr_mces()
00409 {
00410 r0 = (p22 >> 16) & 0xff;
00411 }
00412
00416 void CAlphaCPU::vmspal_call_mtpr_mces()
00417 {
00418 p22 = (p22 & U64(0xffffffffff00ffff)) |
00419 (p22 & U64(0x0000000000070000) &~(r16 << 16)) |
00420 ((r16 << 16) & U64(0x0000000000180000));
00421 }
00422
00426 void CAlphaCPU::vmspal_call_mfpr_pcbb()
00427 {
00428 hw_ldq(p21 + 0x10, r0);
00429 }
00430
00434 void CAlphaCPU::vmspal_call_mfpr_prbr()
00435 {
00436 hw_ldq(p21 + 0xa8, r0);
00437 }
00438
00442 void CAlphaCPU::vmspal_call_mtpr_prbr()
00443 {
00444 hw_stq(p21 + 0xa8, r16);
00445 }
00446
00450 void CAlphaCPU::vmspal_call_mfpr_ptbr()
00451 {
00452 hw_ldq(p21 + 8, r0);
00453 r0 >>= 0x0d;
00454 }
00455
00459 void CAlphaCPU::vmspal_call_mfpr_scbb()
00460 {
00461 hw_ldq(p21 + 0x170, r0);
00462 r0 >>= 0x0d;
00463 }
00464
00468 void CAlphaCPU::vmspal_call_mtpr_scbb()
00469 {
00470 hw_stq(p21 + 0x170, (r16 & U64(0xffffffff)) << 0xd);
00471 }
00472
00476 void CAlphaCPU::vmspal_call_mtpr_sirr()
00477 {
00478 if(r16 > 0 && r16 < 16)
00479 {
00480 state.sir |= 1 << r16;
00481 state.check_int = true;
00482 }
00483 }
00484
00488 void CAlphaCPU::vmspal_call_mfpr_sisr()
00489 {
00490 r0 = state.sir;
00491 }
00492
00496 void CAlphaCPU::vmspal_call_mfpr_tbchk()
00497 {
00498 r0 = U64(0x8000000000000000);
00499 }
00500
00504 void CAlphaCPU::vmspal_call_mtpr_tbia()
00505 {
00506 tbia(ACCESS_READ);
00507 tbia(ACCESS_EXEC);
00508 flush_icache();
00509 }
00510
00514 void CAlphaCPU::vmspal_call_mtpr_tbiap()
00515 {
00516 tbiap(ACCESS_READ);
00517 tbiap(ACCESS_EXEC);
00518 flush_icache_asm();
00519 }
00520
00524 void CAlphaCPU::vmspal_call_mtpr_tbis()
00525 {
00526 tbis(r16, ACCESS_READ);
00527 tbis(r16, ACCESS_EXEC);
00528 }
00529
00533 void CAlphaCPU::vmspal_call_mfpr_esp()
00534 {
00535 u64 t;
00536 hw_ldq(p21 + 0x10, t);
00537 hw_ldq(t + 8, r0);
00538 }
00539
00543 void CAlphaCPU::vmspal_call_mtpr_esp()
00544 {
00545 u64 t;
00546 hw_ldq(p21 + 0x10, t);
00547 hw_stq(t + 8, r16);
00548 }
00549
00553 void CAlphaCPU::vmspal_call_mfpr_ssp()
00554 {
00555 u64 t;
00556 hw_ldq(p21 + 0x10, t);
00557 hw_ldq(t + 0x10, r0);
00558 }
00559
00563 void CAlphaCPU::vmspal_call_mtpr_ssp()
00564 {
00565 u64 t;
00566 hw_ldq(p21 + 0x10, t);
00567 hw_stq(t + 0x10, r16);
00568 }
00569
00573 void CAlphaCPU::vmspal_call_mfpr_usp()
00574 {
00575 u64 t;
00576 hw_ldq(p21 + 0x10, t);
00577 hw_ldq(t + 0x18, r0);
00578 }
00579
00583 void CAlphaCPU::vmspal_call_mtpr_usp()
00584 {
00585 u64 t;
00586 hw_ldq(p21 + 0x10, t);
00587 hw_stq(t + 0x18, r16);
00588 }
00589
00593 void CAlphaCPU::vmspal_call_mtpr_tbisd()
00594 {
00595 tbis(r16, ACCESS_READ);
00596 }
00597
00601 void CAlphaCPU::vmspal_call_mtpr_tbisi()
00602 {
00603 tbis(r16, ACCESS_EXEC);
00604 }
00605
00609 void CAlphaCPU::vmspal_call_mfpr_asten()
00610 {
00611 r0 = state.aster;
00612 }
00613
00617 void CAlphaCPU::vmspal_call_mfpr_astsr()
00618 {
00619 r0 = state.astrr;
00620 }
00621
00625 void CAlphaCPU::vmspal_call_mfpr_vptb()
00626 {
00627 hw_ldq(p21, r0);
00628 }
00629
00633 void CAlphaCPU::vmspal_call_mtpr_datfx()
00634 {
00635 u64 t;
00636
00637 u64 u;
00638 hw_ldq(p21 + 0x10, t);
00639 hw_ldq(t, u);
00640 u |= U64(0x1) << 0x3f;
00641 u &= ~(r16 << 0x3f);
00642 hw_stq(t, u);
00643 }
00644
00648 void CAlphaCPU::vmspal_call_mfpr_whami()
00649 {
00650 hw_ldq(p21 + 0x98, r0);
00651 }
00652
00656 void CAlphaCPU::vmspal_call_imb()
00657 {
00658 if(p22 & 0x18)
00659 {
00660 hw_ldq(p21 + 0x10, p20);
00661 hw_ldl(p20 + 0x3c, p5);
00662 p5 |= 1;
00663 hw_stl(p20 + 0x3c, p5);
00664 }
00665
00666 flush_icache();
00667 }
00668
00672 void CAlphaCPU::vmspal_call_prober()
00673 {
00674 u64 pa;
00675
00676 p23 = state.pc;
00677 p4 = r18 & 3;
00678 p5 = p22 & 0x18;
00679 p5 >>= 3;
00680 p6 = p5 - p4;
00681 if(p5 > p4)
00682 p4 = p5;
00683 state.alt_cm = (int) p4;
00684 hw_stq(p21 + 0x140, state.pc);
00685 hw_stq(p21 + 0x148, p4);
00686
00687 if(virt2phys(r16, &pa, ACCESS_READ | ALT | PROBE, NULL, 0) < 0)
00688 return;
00689
00690 if(virt2phys(r16 + r17, &pa, ACCESS_READ | ALT | PROBE, NULL, 0) < 0)
00691 return;
00692
00693 r0 = 1;
00694 return;
00695 }
00696
00700 void CAlphaCPU::vmspal_call_probew()
00701 {
00702 u64 pa;
00703
00704 p23 = state.pc;
00705 p4 = r18 & 3;
00706 p5 = p22 & 0x18;
00707 p5 >>= 3;
00708 p6 = p5 - p4;
00709 if(p5 > p4)
00710 p4 = p5;
00711 state.alt_cm = (int) p4;
00712 hw_stq(p21 + 0x140, state.pc);
00713 hw_stq(p21 + 0x148, p4);
00714 if(virt2phys(r16, &pa, ACCESS_WRITE | ALT | PROBE | PROBEW, NULL, 0) < 0)
00715 return;
00716
00717 if(virt2phys(r16 + r17, &pa, ACCESS_WRITE | ALT | PROBE | PROBEW, NULL, 0) < 0)
00718 return;
00719
00720 r0 = 1;
00721 return;
00722 }
00723
00727 void CAlphaCPU::vmspal_call_rd_ps()
00728 {
00729 r0 = p22 & U64(0xffff);
00730 }
00731
00735 int CAlphaCPU::vmspal_call_rei()
00736 {
00737 u64 phys_address;
00738
00739 p23 = state.pc;
00740
00741 p7 = p22 & 0x18;
00742 hw_stq(p21 + 0x150, p23);
00743 if(r30 & 0x3f)
00744 {
00745
00746
00747 p4 = 0x430;
00748 hw_stq(p21 + 0x158, p4);
00749 return vmspal_int_initiate_exception();
00750 }
00751
00752 if(p7)
00753 {
00754
00755
00756 ldq(r30 + 0x38, p20);
00757 state.bIntrFlag = false;
00758 ldq(r30 + 0x30, p23);
00759 p4 = p20 & 0x18;
00760 if((p4 < p7) || (p20 &~U64(0x3f0000000000001b)))
00761 {
00762 p4 = 0x430;
00763 hw_stq(p21 + 0x158, p4);
00764 vmspal_int_initiate_exception();
00765 return 0;
00766 }
00767
00768 ldq(r30 + 0x10, state.r[4]);
00769 ldq(r30 + 0x18, state.r[5]);
00770 ldq(r30 + 0x20, state.r[6]);
00771 ldq(r30 + 0x28, state.r[7]);
00772 ldq(r30, r2);
00773 ldq(r30 + 8, r3);
00774 hw_ldq(p21 + 0x10, p6);
00775 p5 = (p20 >> 56) & 0xff;
00776 p7 += p6;
00777 p6 += p4;
00778 p20 &= 0xffff;
00779 p22 &= ~U64(0xffff);
00780 state.cm = (int) (p4 >> 3) & 3;
00781 p22 |= p20;
00782 p23 &= ~U64(0x3);
00783 p20 = r30 + 0x40;
00784 p20 |= p5;
00785 hw_stq(p7, p20);
00786 hw_ldq(p6, r30);
00787 set_pc(p23);
00788 return 0;
00789 }
00790
00791 ldq(r30 + 0x38, p20);
00792 state.bIntrFlag = false;
00793 p7 = (p20 >> 8) & 0xff;
00794 ldq(r30 + 0x10, state.r[4]);
00795 ldq(r30 + 0x18, state.r[5]);
00796 ldq(r30 + 0x20, state.r[6]);
00797 ldq(r30 + 0x28, state.r[7]);
00798 ldq(r30, r2);
00799 ldq(r30 + 8, r3);
00800 p4 = p20 & 0x18;
00801 ldq(r30 + 0x30, p23);
00802
00803 if(p4)
00804 {
00805 hw_ldq(p21 + 0x10, p7);
00806 p7 += p4;
00807 state.cm = (int) (p4 >> 3) & 3;
00808 p5 = (p20 >> 56) & 0xff;
00809 p20 &= 0xff;
00810 p22 &= ~U64(0xffff);
00811 p22 |= p20;
00812 p23 &= ~U64(0x3);
00813 p20 = r30 + 0x40;
00814 p20 |= p5;
00815 hw_ldq(p7, r30);
00816 hw_stq(p21 + 0x18, p20);
00817 state.eien = ipl_ier_mask[0][0];
00818 state.slen = ipl_ier_mask[0][1];
00819 state.cren = ipl_ier_mask[0][2];
00820 state.pcen = ipl_ier_mask[0][3];
00821 state.sien = ipl_ier_mask[0][4];
00822 state.asten = ipl_ier_mask[0][5];
00823 state.check_int = true;
00824 set_pc(p23);
00825 return 0;
00826 }
00827
00828 p5 = (p20 >> 56) & 0xff;
00829 p20 &= 0xffff;
00830 p22 &= ~U64(0xffff);
00831 p7 = (p20 >> 8) & 0xff;
00832 p22 |= p20;
00833 p23 &= ~U64(0x3);
00834 p20 = r30 + 0x40;
00835 r30 = p20 | p5;
00836 state.eien = ipl_ier_mask[p7][0];
00837 state.slen = ipl_ier_mask[p7][1];
00838 state.cren = ipl_ier_mask[p7][2];
00839 state.pcen = ipl_ier_mask[p7][3];
00840 state.sien = ipl_ier_mask[p7][4];
00841 state.asten = ipl_ier_mask[p7][5];
00842 state.check_int = true;
00843 set_pc(p23);
00844 return 0;
00845 }
00846
00850 void CAlphaCPU::vmspal_call_swasten()
00851 {
00852 r0 = (state.aster & (1 << ((p22 >> 3) & 3))) ? 1 : 0;
00853 if(r16 & 1)
00854 {
00855 state.aster |= (1 << ((p22 >> 3) & 3));
00856 state.check_int = true;
00857 }
00858 else
00859 state.aster &= ~(1 << ((p22 >> 3) & 3));
00860 }
00861
00865 void CAlphaCPU::vmspal_call_wr_ps_sw()
00866 {
00867 p22 &= ~U64(0x3);
00868 p22 |= r16 & U64(0x3);
00869 }
00870
00874 void CAlphaCPU::vmspal_call_rscc()
00875 {
00876 hw_ldq(p21 + 0xa0, r0);
00877 if((state.cc & U64(0xffffffff)) < (r0 & U64(0x00000000ffffffff)))
00878 r0 += U64(0x1) << 0x20;
00879 r0 &= U64(0xffffffff00000000);
00880 r0 |= (state.cc & U64(0xffffffff));
00881 hw_stq(p21 + 0xa0, r0);
00882 }
00883
00887 void CAlphaCPU::vmspal_call_read_unq()
00888 {
00889 u64 t;
00890 hw_ldq(p21 + 0x10, t);
00891 hw_ldq(t + 0x48, r0);
00892 }
00893
00897 void CAlphaCPU::vmspal_call_write_unq()
00898 {
00899 u64 t;
00900 hw_ldq(p21 + 0x10, t);
00901 hw_stq(t + 0x48, r16);
00902 }
00903
00904
00905
00906
00907
00913
00914
00918 int CAlphaCPU::vmspal_int_initiate_exception()
00919 {
00920 u64 phys_address;
00921
00922 p4 = p22 & U64(0x18);
00923 hw_ldq(p21 + U64(0x10), p20);
00924 if(p4)
00925 {
00926
00927
00928 state.cm = 0;
00929
00930
00931 p20 += p4;
00932 hw_stq(p20, r30);
00933 hw_ldq(p21 + U64(0x18), r30);
00934 }
00935
00936 p20 = r30 & U64(0x3f);
00937 r30 &= ~U64(0x3f);
00938 stq(r30 - U64(0x40), r2);
00939 stq(r30 - U64(0x38), r3);
00940 hw_stq(p21 + U64(0xf0), r1);
00941 r3 = p21;
00942 stq(r30 - U64(0x30), state.r[4]);
00943 stq(r30 - U64(0x28), state.r[5]);
00944 stq(r30 - U64(0x20), state.r[6]);
00945 stq(r30 - U64(0x18), state.r[7]);
00946 hw_ldq(state.r[3] + U64(0x160), state.r[4]);
00947 hw_ldq(state.r[3] + U64(0x168), state.r[5]);
00948 hw_ldq(p21 + U64(0xf0), r1);
00949 hw_ldq(p21 + U64(0x170), p4);
00950 hw_ldq(p21 + U64(0x158), p5);
00951 p7 = p22 & U64(0xffff);
00952 p20 <<= 0x38;
00953 p20 |= p7;
00954 p4 += p5;
00955 hw_ldq(p4 + U64(0x00), r2);
00956 hw_ldq(p4 + U64(0x08), r3);
00957 p22 &= ~U64(0x1b);
00958 r30 -= U64(0x40);
00959 hw_ldq(p21 + U64(0x150), p6);
00960 r2 &= ~U64(0x3);
00961 stq(r30 + U64(0x38), p20);
00962 stq(r30 + U64(0x30), p6);
00963
00964 set_pc(r2);
00965 return -1;
00966 }
00967
00971 int CAlphaCPU::vmspal_int_initiate_interrupt()
00972 {
00973 u64 phys_address;
00974
00975 p4 = p22 & U64(0x18);
00976 hw_ldq(p21 + U64(0x10), p20);
00977 if(p4)
00978 {
00979
00980
00981 state.cm = 0;
00982
00983
00984 p20 += p4;
00985 hw_stq(p20, r30);
00986 hw_ldq(p21 + U64(0x18), r30);
00987 }
00988
00989 p20 = r30 & U64(0x3f);
00990 r30 &= ~U64(0x3f);
00991 stq(r30 - U64(0x40), r2);
00992 stq(r30 - U64(0x38), r3);
00993 hw_stq(p21 + U64(0xf0), r1);
00994 r3 = p21;
00995 stq(r30 - U64(0x30), state.r[4]);
00996 stq(r30 - U64(0x28), state.r[5]);
00997 stq(r30 - U64(0x20), state.r[6]);
00998 stq(r30 - U64(0x18), state.r[7]);
00999 hw_ldq(state.r[3] + U64(0x160), state.r[4]);
01000 hw_ldq(state.r[3] + U64(0x168), state.r[5]);
01001 hw_ldq(p21 + U64(0xf0), r1);
01002 hw_ldq(p21 + U64(0x170), p4);
01003 hw_ldq(p21 + U64(0x158), p5);
01004 p7 = p22 & U64(0xffff);
01005 p20 <<= 0x38;
01006 p20 |= p7;
01007 p4 += p5;
01008 hw_ldq(p4, r2);
01009 hw_ldq(p4 + U64(0x08), r3);
01010 hw_ldq(p21 + U64(0x128), p4);
01011 p22 &= ~U64(0xffff);
01012 p22 |= p4;
01013 r30 -= U64(0x40);
01014 hw_ldq(p21 + U64(0x150), p6);
01015 r2 &= ~U64(0x3);
01016 stq(r30 + U64(0x38), p20);
01017 stq(r30 + U64(0x30), p6);
01018
01019 set_pc(r2);
01020 return -1;
01021 }
01022
01023
01024
01025
01026
01032
01033
01037 int CAlphaCPU::vmspal_ent_sw_int(int si)
01038 {
01039 int x;
01040
01041 state.exc_addr = state.current_pc;
01042 p23 = state.current_pc;
01043 for(x = 15; x >= 0; x--)
01044 {
01045 if(si & (1 << x))
01046 break;
01047 }
01048
01049 if(x <= 0)
01050 return 0;
01051
01052 p7 = x;
01053 p4 = (u64) x << 4;
01054 p5 = p4 + 0x500;
01055 hw_stq(p21 + 0x158, p5);
01056 hw_stq(p21 + 0x150, state.current_pc);
01057 state.sir &= ~(1 << x);
01058 state.eien = ipl_ier_mask[x][0];
01059 state.slen = ipl_ier_mask[x][1];
01060 state.cren = ipl_ier_mask[x][2];
01061 state.pcen = ipl_ier_mask[x][3];
01062 state.sien = ipl_ier_mask[x][4];
01063 state.asten = ipl_ier_mask[x][5];
01064 state.check_int = true;
01065 p20 = (u64) x << 8;
01066 p20 |= 4;
01067 hw_stq(p21 + 0x128, p20);
01068 return vmspal_int_initiate_interrupt();
01069 }
01070
01074 int CAlphaCPU::vmspal_ent_ext_int(int ei)
01075 {
01076 bool do_11670 = false;
01077
01078 state.exc_addr = state.current_pc;
01079 p23 = state.current_pc;
01080 p7 = ei;
01081 if(ei & 0x04)
01082 {
01083
01084
01085 cSystem->clear_clock_int(state.iProcNum);
01086 p6 = cSystem->get_c_misc();
01087
01088 p22 += U64(0x0000010000000000);
01089 p22 &= U64(0xffff0fffffffffff);
01090
01091 hw_ldq(p21 + 0xa0, p20);
01092 p6 = U64(0x1) << 0x20;
01093 p4 = (state.cc & U64(0xffffffff));
01094 p5 = p20 & U64(0xffffffff);
01095 p20 &= U64(0xffffffff00000000);
01096 p7 = p4 - p5;
01097 if(((s64) p7) < 0)
01098 p20 += p6;
01099 p20 |= (state.cc & U64(0xffffffff));
01100 hw_stq(p21 + 0xa0, p20);
01101 hw_stq(p21 + 0x1c8, 0);
01102 p20 = 0x600;
01103 p7 = 0x16;
01104
01105 do_11670 = true;
01106 }
01107 else if(ei & 0x02)
01108 {
01109 p5 = cSystem->get_c_dir(state.iProcNum);
01110 if(test_bit_64(p5, 0x32))
01111 FAILURE(NotImplemented, "Can't handle IRQ 50");
01112
01113 p4 = 0x100;
01114 p20 = 8;
01115 while(p20 < 0x30)
01116 {
01117 if(p4 & p5)
01118 break;
01119 p4 *= 2;
01120 p20++;
01121 }
01122
01123 if(p4 & p5)
01124 {
01125 p20 <<= 4;
01126 p20 += 0x900;
01127 p7 = 0x15;
01128
01129 do_11670 = true;
01130 }
01131 else if(test_bit_64(p5, 0x37))
01132 {
01133
01134
01135 p5 = U64(0x00000801f8000000);
01136
01137
01138 hw_ldl(p5, p5);
01139 p4 = p5 & 0xff;
01140 if(p4 == 0x07)
01141 FAILURE(NotImplemented, "Can't handle PIC interrupt 7");
01142
01143 if(p4 >= 0x10)
01144 return 0;
01145
01146 p4 <<= 4;
01147 p20 = p4 + 0x800;
01148 hw_ldq(0x148, p5);
01149 if(!p5 || p20 != U64(0x830))
01150 {
01151 p7 = 0x15;
01152 do_11670 = true;
01153 }
01154 else
01155 {
01156 hw_stq(0x150, p20);
01157 p4 = U64(0x00000801a0000000);
01158 p5 = U64(0x2000);
01159 hw_stq(p4 + 0x80, p5);
01160 hw_ldq(p4 + 0x80, p5);
01161 return 0;
01162 }
01163 }
01164 else
01165 {
01166 p6 = p5 & U64(0x0060000000000000);
01167 if(p6)
01168 cSystem->set_c_dim(state.iProcNum,
01169 cSystem->get_c_dim(state.iProcNum) &~p6);
01170 return 0;
01171 }
01172 }
01173
01174 if(do_11670)
01175 {
01176 hw_stq(p21 + 0x150, state.current_pc);
01177 hw_stq(p21 + 0x158, p20);
01178 hw_stq(p21 + 0x1d8, p20);
01179 state.eien = ipl_ier_mask[p7][0];
01180 state.slen = ipl_ier_mask[p7][1];
01181 state.cren = ipl_ier_mask[p7][2];
01182 state.pcen = ipl_ier_mask[p7][3];
01183 state.sien = ipl_ier_mask[p7][4];
01184 state.asten = ipl_ier_mask[p7][5];
01185 state.check_int = true;
01186 p20 = p7 << 8;
01187 p20 |= 4;
01188 hw_stq(p21 + 0x128, p20);
01189
01190 return vmspal_int_initiate_interrupt();
01191 }
01192
01193 return 0;
01194 }
01195
01199 int CAlphaCPU::vmspal_ent_ast_int(int ast)
01200 {
01201 int x;
01202
01203 state.exc_addr = state.current_pc;
01204 p23 = state.current_pc;
01205
01206 for(x = 0; x < 4; x++)
01207 {
01208 if(ast & (1 << x))
01209 break;
01210 }
01211
01212 state.asten = 0;
01213 state.sien &= ~7;
01214 p4 = (u64) x << 4;
01215 p5 = 0x240 + p4;
01216 hw_stq(p21 + 0x158, p5);
01217 hw_stq(p21 + 0x150, p23);
01218 state.astrr &= ~(1 << x);
01219 p20 = (p22 & 4) + 0x200;
01220 hw_stq(p21 + 0x128, p20);
01221 return vmspal_int_initiate_interrupt();
01222 }
01223
01227 int CAlphaCPU::vmspal_ent_dtbm_single(int flags)
01228 {
01229 u64 pte_phys;
01230 u64 t25;
01231 u64 t26;
01232
01233 p23 = state.exc_addr;
01234 p4 = va_form(state.fault_va, false);
01235 p5 = state.mm_stat;
01236 p7 = state.exc_sum;
01237 p6 = state.fault_va;
01238 p7 &= ~U64(0x1);
01239 if(test_bit_64(p22, 63))
01240 {
01241
01242
01243 p5 = 0xff01;
01244 p4 = p6 >> 0x0d;
01245 if(!test_bit_64(p6, 43))
01246 {
01247 p4 &= ~U64(0xffffffffbfc00000);
01248 if((p4 >= 0x400a0000 && p4 <= 0x400bffff)
01249 || (p4 >= 0x400c8000 && p4 <= 0x400cffff)
01250 || (p4 >= 0x400e0000 && p4 <= 0x400fbfff)
01251 || (p4 >= 0x400ff800 && p4 <= 0x400fffff)
01252 || (p4 >= 0x40180000 && p4 <= 0x401bffff)
01253 || (p4 >= 0x401c8000 && p4 <= 0x401fbfff)
01254 || (p4 >= 0x401fb000 && p4 <= 0x401fffff)
01255 || (p4 >= 0x40200000 && p4 <= 0x403fffff)) p5 = U64(0x1);
01256 }
01257
01258 p4 <<= 0x20;
01259 p4 |= p5;
01260 add_tb_d(p6, p4);
01261 return 0;
01262 }
01263
01264 p4 &= ~U64(0x7);
01265 if(virt2phys(p4, &pte_phys, ACCESS_READ | NO_CHECK | VPTE | (flags & (PROBE | PROBEW)),
01266 NULL, 0))
01267 return -1;
01268 p4 = cSystem->ReadMem(pte_phys, 64, this);
01269
01270 if(!test_bit_64(p4, 0))
01271 {
01272 if(flags & PROBE)
01273 {
01274 t25 = U64(0x30000);
01275 p4 |= t25;
01276 t26 = p5 & 1;
01277 t26 *= 4;
01278 t25 = ((p22 >> 3) & 3) | 8;
01279 t26 += t25;
01280 t25 = p4 >> 0x10;
01281 if(!(t25 & 1))
01282 t26 = 8;
01283 t26 = (t25 << t26) & p4;
01284 p7 = t26 ? 0x90 : 0x80;
01285 hw_stq(p21 + 0x158, p7);
01286 t26 = p23 &~U64(0x3);
01287 hw_ldq(p21 + 0x148, p7);
01288 if(test_bit_64(p4, (int) (8 + p7 + ((flags & PROBEW) ? 4 : 0))))
01289 return 1;
01290 r0 = 0;
01291 return -1;
01292 }
01293
01294 if(state.current_pc & 1)
01295 {
01296 t25 = U64(0x30000);
01297 p4 |= t25;
01298 t26 = p5 & 1;
01299 t26 *= 4;
01300 t25 = ((p22 >> 3) & 3) | 8;
01301 t26 += t25;
01302 t25 = p4 >> 0x10;
01303 if(!(t25 & 1))
01304 t26 = 8;
01305 t26 = (t25 << t26) & p4;
01306 p7 = t26 ? 0x90 : 0x80;
01307 hw_stq(p21 + 0x158, p7);
01308 t26 = p23 &~U64(0x3);
01309
01310 hw_stq(p21 + 0x118, state.r[25]);
01311 hw_stq(p21 + 0x120, state.r[26]);
01312 state.r[25] = t25;
01313 state.r[26] = t26;
01314 set_pc(0xd981);
01315 return -1;
01316
01317
01318 }
01319
01320 hw_stq(p21 + U64(0x150), p23);
01321 hw_stq(p21 + U64(0x160), p6);
01322 p20 = ((p22 >> 3) & 3) + 8;
01323 if((test_bit_64(p5, 0) && ((p5 >> 4) & 0x3f) == 0x18)
01324 || (!test_bit_64(p5, 0) && ((p7 >> 8) & 0x1f) == 0x1f))
01325 {
01326
01327
01328 set_pc(state.current_pc + 4);
01329 return -1;
01330 }
01331
01332 p5 &= U64(0x1);
01333 p7 = p5 << 0x3f;
01334 p6 = 4 * p5;
01335 hw_stq(p21 + U64(0x168), p7);
01336 p6 += p20;
01337 p6 = U64(0x1) << p6;
01338 p6 &= p4;
01339 p20 = (p6) ? 0x90 : 0x80;
01340 hw_stq(p21 + U64(0x158), p20);
01341 return vmspal_int_initiate_exception();
01342 }
01343
01344 add_tb_d(p6, p4);
01345 return 0;
01346 }
01347
01351 int CAlphaCPU::vmspal_ent_itbm(int flags)
01352 {
01353 u64 pte_phys;
01354
01355 p4 = va_form(state.exc_addr, true);
01356 p23 = state.exc_addr;
01357 p6 = p23;
01358 if(test_bit_64(p22, 63))
01359 {
01360
01361
01362 p6 = p23 >> 0x0d;
01363 p5 = 0xf01;
01364 p6 <<= 0x0d;
01365 p6 |= p5;
01366 add_tb_i(p23, p6);
01367 return 0;
01368 }
01369
01370 p4 &= ~U64(0x7);
01371 if(virt2phys(p4, &pte_phys, ACCESS_READ | NO_CHECK | VPTE, NULL, 0))
01372 return -1;
01373 p4 = cSystem->ReadMem(pte_phys, 64, this);
01374
01375 p6 = 0xfff;
01376 p5 = p4 & p6;
01377 p6 = p4 >> 0x20;
01378 p6 <<= 0x0d;
01379 if(!(p4 & 1) || (p4 & 8))
01380 {
01381 p20 = (p4 & 1) ? 0xc0 : 0x90;
01382
01383 p6 = p22 >> 3;
01384 hw_stq(p21 + 0x160, p23);
01385 hw_stq(p21 + 0x150, p23);
01386 p6 &= U64(0x3);
01387 p5 = 1;
01388 p6 += 8;
01389 hw_stq(p21 + 0x168, p5);
01390 p6 = p5 << p6;
01391 p6 &= p4;
01392
01393
01394 if(!p6)
01395 p20 = 0x80;
01396 hw_stq(p21 + 0x158, p20);
01397 return vmspal_int_initiate_exception();
01398 }
01399
01400 p6 |= p5;
01401 add_tb_i(p23, p6);
01402 return 0;
01403 }
01404
01408 int CAlphaCPU::vmspal_ent_dtbm_double_3(int flags)
01409 {
01410 u64 t25;
01411 u64 t26;
01412
01413 p7 &= 0xffff;
01414 p5 <<= 16;
01415 p7 |= p5;
01416 p5 = state.exc_addr;
01417 p7 |= 1;
01418 hw_ldq(p21 + 8, t25);
01419 t26 = (p4 << 0x1f) >> 0x33;
01420 t25 += t26;
01421 hw_ldq(t25, t25);
01422 t26 = (p4 << 0x29) >> 0x33;
01423 if(t25 & 1)
01424 {
01425 t25 >>= 0x20;
01426 t25 <<= 0x0d;
01427 t25 += t26;
01428 hw_ldq(t25, t25);
01429 if(t25 & 1)
01430 {
01431 add_tb_d(p4, t25);
01432 return 0;
01433 }
01434 }
01435
01436
01437 p4 = p5;
01438 p5 = p7 >> 0x10;
01439 t26 = state.pal_base;
01440
01441 if(flags & PROBE)
01442 {
01443 p4 = t25 &~U64(0x30000);
01444 t26 = p5 & 1;
01445 t26 *= 4;
01446 t25 = ((p22 >> 3) & 3) | 8;
01447 t26 += t25;
01448 t25 = p4 >> 16;
01449 if(!(t25 & 1))
01450 t26 = 8;
01451 t26 = (U64(0x1) << t26) & p4;
01452 p7 = t26 ? 0x90 : 0x80;
01453 hw_stq(p21 + 0x158, p7);
01454
01455 if(p7 != 0x80)
01456 {
01457 p5 = (flags & PROBEW) ? U64(0x8000000000000000) : 0;
01458 hw_stq(p21 + 0x160, p6);
01459 hw_stq(p21 + 0x168, p5);
01460 hw_stq(p21 + 0x150, state.current_pc);
01461 return vmspal_int_initiate_exception();
01462 }
01463
01464 r0 = 0;
01465 return -1;
01466 }
01467
01468 if(p23 & 1)
01469 {
01470 p4 = t25 &~U64(0x30000);
01471 t26 = p5 & 1;
01472 t26 *= 4;
01473 t25 = ((p22 >> 3) & 3) | 8;
01474 t26 += t25;
01475 t25 = p4 >> 16;
01476 if(!(t25 & 1))
01477 t26 = 8;
01478 t26 = (U64(0x1) << t26) & p4;
01479 p7 = t26 ? 0x90 : 0x80;
01480 hw_stq(p21 + 0x158, p7);
01481 t26 = p23 &~U64(0x3);
01482
01483 hw_stq(p21 + 0x118, state.r[25]);
01484 hw_stq(p21 + 0x120, state.r[26]);
01485 state.r[25] = t25;
01486 state.r[26] = t26;
01487 set_pc(0xd981);
01488 return -1;
01489 }
01490
01491 p20 = p4 &~U64(0x3);
01492 p4 = t25 & 0x100;
01493 hw_stq(p21 + 0x150, p23);
01494 p20 = t26 - p20;
01495 t26 = p20 + 0x590;
01496 if(!t26)
01497 {
01498 p5 = 1;
01499 hw_stq(p21 + 0x160, p23);
01500 p20 = p4 ? 0x90 : 0x80;
01501 hw_stq(p21 + 0x168, p5);
01502 hw_stq(p21 + 0x158, p20);
01503 return vmspal_int_initiate_exception();
01504 }
01505
01506 if((test_bit_64(p5, 0) && ((p5 >> 4) & 0x3f) == 0x18)
01507 || (!test_bit_64(p5, 0) && ((p7 >> 8) & 0x1f) == 0x1f))
01508 {
01509 set_pc(p23 + 4);
01510 return -1;
01511 }
01512
01513 p5 <<= 0x3f;
01514 p20 = p4 ? 0x90 : 0x80;
01515 hw_stq(p21 + 0x168, p5);
01516 hw_stq(p21 + 0x160, p6);
01517 hw_stq(p21 + 0x158, p20);
01518 return vmspal_int_initiate_exception();
01519 }
01520
01524 int CAlphaCPU::vmspal_ent_iacv(int flags)
01525 {
01526 p6 = state.current_pc;
01527 p4 = 1;
01528 p5 = 0x80;
01529 hw_stq(p21 + 0x168, p4);
01530 hw_stq(p21 + 0x158, p5);
01531 if(state.current_pc & 1)
01532 {
01533 p7 = state.current_pc;
01534 p20 = 5;
01535 hw_stq(p21 + 0xc8, p20);
01536 p23 = state.current_pc;
01537 set_pc(0xde01);
01538 return -1;
01539 }
01540
01541 hw_stq(p21 + 0x160, state.current_pc);
01542 hw_stq(p21 + 0x150, state.current_pc);
01543 return vmspal_int_initiate_exception();
01544 }
01545
01549 int CAlphaCPU::vmspal_ent_dfault(int flags)
01550 {
01551 u64 t25;
01552
01553 u64 t26;
01554 p6 = state.current_pc;
01555 p7 = state.exc_sum;
01556 p5 = state.mm_stat;
01557 if(flags & PROBE)
01558 {
01559 hw_stq(p21 + 0xd0, p23);
01560 p23 = p6;
01561 t26 = p6 &~U64(0x3);
01562 p6 = state.fault_va;
01563 t25 = p5 & 2;
01564 p7 = 0x80;
01565 if(!t25)
01566 {
01567 t25 = p5 & 8;
01568 p7 = t25 ? 0xb0 : 0xa0;
01569 tbis(p6, ACCESS_READ);
01570 }
01571
01572 hw_stq(p21 + 0x158, p7);
01573 p4 = 1;
01574 hw_ldq(p21 + 0x158, p7);
01575 if(p7 == 0xa0 || p7 == 0xb0)
01576 {
01577 return 1;
01578 }
01579
01580 r0 = 0;
01581 return -1;
01582 }
01583
01584 if(state.current_pc & 1)
01585 {
01586 hw_stq(p21 + 0xd0, p23);
01587 p23 = p6;
01588 t26 = p6 &~U64(0x3);
01589 p6 = state.fault_va;
01590 t25 = p5 & 2;
01591 p7 = 0x80;
01592 if(!t25)
01593 {
01594 t25 = p5 & 8;
01595 p7 = t25 ? 0xb0 : 0xa0;
01596 tbis(p6, ACCESS_READ);
01597 }
01598
01599 hw_stq(p21 + 0x158, p7);
01600 p4 = 1;
01601 hw_stq(p21 + 0x118, state.r[25]);
01602 hw_stq(p21 + 0x120, state.r[26]);
01603 state.r[25] = t25;
01604 state.r[26] = t26;
01605 set_pc(0xd981);
01606 return -1;
01607 }
01608
01609 p20 = state.fault_va;
01610 if(((state.mm_stat & 1) && (((state.mm_stat >> 4) & 0x3f) == 0x18))
01611 || (!(state.mm_stat & 1) && (((state.exc_sum >> 8) & 0x1f) == 0x1f)))
01612 {
01613 set_pc(state.current_pc + 4);
01614 return -1;
01615 }
01616
01617 p7 = 0x80;
01618 if(!(state.mm_stat & 2))
01619 {
01620 p7 = (state.mm_stat & 4) ? 0xa0 : 0xb0;
01621 tbis(p20, ACCESS_READ);
01622 }
01623
01624 hw_stq(p21 + 0x158, p7);
01625 hw_stq(p21 + 0x160, p20);
01626 p5 <<= 0x3f;
01627 hw_stq(p21 + 0x168, p5);
01628 hw_stq(p21 + 0x150, p6);
01629 return vmspal_int_initiate_exception();
01630 }
01631
01632