00305 :
00306
00307 This function
is called to emulate a floating operation and convert
the
00308 exception status to
the proper value. If
the exception
is an unimplemented
00309 operation, then
the operation
is emulated. Otherwise,
the status code
is
00310 just converted to its proper value.
00311
00312 Arguments:
00313
00314 ExceptionRecord - Supplies a pointer to an exception record.
00315
00316 ExceptionFrame - Supplies a pointer to an exception frame.
00317
00318 TrapFrame - Supplies a pointer to a trap frame.
00319
00320 SoftwareFpcr - Supplies a pointer to a variable that contains a copy of
00321
the software FPCR.
00322
00323 Return Value:
00324
00325
A value of
TRUE is returned
if the floating exception
is successfully
00326 emulated. Otherwise, a value of
FALSE is returned.
00327
00328 --*/
00329
00330 {
00331
00332 ULARGE_INTEGER AhighBhigh;
00333 ULARGE_INTEGER AhighBlow;
00334 ULARGE_INTEGER AlowBhigh;
00335 ULARGE_INTEGER AlowBlow;
00336 ULONG Carry1;
00337 ULONG Carry2;
00338 BOOLEAN CompareEqual;
00339 BOOLEAN CompareLess;
00340 BOOLEAN CompareResult;
00341
FP_CONTEXT_BLOCK ContextBlock;
00342 LARGE_INTEGER DoubleDividend;
00343 LARGE_INTEGER DoubleDivisor;
00344 ULONG DoubleMantissaLow;
00345 LONG DoubleMantissaHigh;
00346
FP_DOUBLE_OPERAND DoubleOperand1;
00347
FP_DOUBLE_OPERAND DoubleOperand2;
00348
FP_DOUBLE_OPERAND DoubleOperand3;
00349 LARGE_INTEGER DoubleQuotient;
00350 PVOID ExceptionAddress;
00351 ULONG ExponentDifference;
00352 ULONG Fa;
00353 ULONG Fb;
00354 ULONG Function;
00355 ULONG
Index;
00356 ALPHA_INSTRUCTION Instruction;
00357 ULARGE_INTEGER LargeResult;
00358 LONG Negation;
00359 LONGLONG Quadword;
00360 LONG SingleMantissa;
00361
FP_SINGLE_OPERAND SingleOperand1;
00362
FP_SINGLE_OPERAND SingleOperand2;
00363
FP_SINGLE_OPERAND SingleOperand3;
00364 ULONG StickyBits;
00365 BOOLEAN ValidOperation;
00366
00367
00368
00369
00370
00371
00372 ExceptionAddress = ExceptionRecord->ExceptionAddress;
00373
00374
00375
00376
00377
00378
00379
00380
00381
try {
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 Instruction = *((PALPHA_INSTRUCTION)ExceptionRecord->ExceptionAddress);
00395
DBGPRINT(
"KiEmulateFloating: Instruction = %.8lx, Fpcr = %.16Lx\n",
00396 Instruction.Long, TrapFrame->Fpcr);
00397 Function = Instruction.FpOp.Function;
00398
00399 ValidOperation =
FALSE;
00400
if (Instruction.FpOp.Opcode == IEEEFP_OP) {
00401
00402
00403
00404
00405
00406
if (Function == CVTST_FUNC) {
00407 Function =
CVTST_FUNC_PROPER;
00408
00409 }
else if (Function == CVTST_S_FUNC) {
00410 Function =
CVTST_FUNC_PROPER | FP_TRAP_ENABLE_S;
00411 }
00412
00413
switch (Function & FP_FUNCTION_MASK) {
00414
case ADDS_FUNC :
00415
case SUBS_FUNC :
00416
case MULS_FUNC :
00417
case DIVS_FUNC :
00418
case ADDT_FUNC :
00419
case SUBT_FUNC :
00420
case MULT_FUNC :
00421
case DIVT_FUNC :
00422
case CVTTQ_FUNC :
00423
case CVTTS_FUNC :
00424
00425
switch (Function & FP_TRAP_ENABLE_MASK) {
00426
case FP_TRAP_ENABLE_NONE :
00427
case FP_TRAP_ENABLE_U :
00428
case FP_TRAP_ENABLE_SU :
00429
case FP_TRAP_ENABLE_SUI :
00430
00431 ValidOperation =
TRUE;
00432
break;
00433 }
00434
break;
00435
00436
case CVTQS_FUNC :
00437
case CVTQT_FUNC :
00438
00439
switch (Function & FP_TRAP_ENABLE_MASK) {
00440
case FP_TRAP_ENABLE_NONE :
00441
case FP_TRAP_ENABLE_SUI :
00442
00443 ValidOperation =
TRUE;
00444
break;
00445 }
00446
break;
00447
00448
case CVTST_FUNC_PROPER :
00449
00450
switch (Function & FP_TRAP_ENABLE_MASK) {
00451
case FP_TRAP_ENABLE_NONE :
00452
case FP_TRAP_ENABLE_S :
00453
00454 ValidOperation =
TRUE;
00455
break;
00456 }
00457
break;
00458
00459
case CMPTEQ_FUNC :
00460
case CMPTLE_FUNC :
00461
case CMPTLT_FUNC :
00462
case CMPTUN_FUNC :
00463
00464 ValidOperation =
TRUE;
00465
break;
00466 }
00467
00468 }
else if (Instruction.FpOp.Opcode == FPOP_OP) {
00469
switch (Function) {
00470
case CVTLQ_FUNC :
00471
case CVTQL_FUNC :
00472
case CVTQLV_FUNC :
00473
case CVTQLSV_FUNC :
00474
00475 ValidOperation =
TRUE;
00476
break;
00477 }
00478 }
00479
00480
if (ValidOperation ==
FALSE) {
00481
00482
00483
00484
00485
00486
00487
00488 ExceptionRecord->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
00489
DBGPRINT(
"KiEmulateFloating: Invalid Function or Format\n");
00490
return FALSE;
00491 }
00492
00493
00494
00495
00496
00497
KeGetCurrentPrcb()->KeFloatingEmulationCount += 1;
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508 ContextBlock.
ExceptionRecord = ExceptionRecord;
00509 ContextBlock.
ExceptionFrame = ExceptionFrame;
00510 ContextBlock.
TrapFrame = TrapFrame;
00511 ContextBlock.
SoftwareFpcr = SoftwareFpcr;
00512
00513
00514
00515
00516
00517
00518
00519
00520
if ((Function & FP_TRAP_ENABLE_S) != 0) {
00521 ContextBlock.
IeeeMode =
TRUE;
00522
00523 }
else {
00524 ContextBlock.
IeeeMode =
FALSE;
00525 }
00526
00527
if ((Function & FP_TRAP_ENABLE_U) != 0) {
00528 ContextBlock.
UnderflowEnable =
TRUE;
00529
00530 }
else {
00531 ContextBlock.
UnderflowEnable =
FALSE;
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 ContextBlock.
Fc = Instruction.FpOp.Fc;
00543 Fa = Instruction.FpOp.Fa;
00544 Fb = Instruction.FpOp.Fb;
00545
00546
if ((Function & FP_ROUND_MASK) == FP_ROUND_D) {
00547 ContextBlock.
Round = ((PFPCR)&TrapFrame->Fpcr)->DynamicRoundingMode;
00548
00549 }
else {
00550 ContextBlock.
Round = (Function & FP_ROUND_MASK) >> FP_ROUND_SHIFT;
00551 }
00552
00553 SoftwareFpcr->EmulationOccurred = 1;
00554
00555
00556
00557
00558
00559
switch (Function & FP_FUNCTION_MASK) {
00560
case ADDS_FUNC :
00561
case SUBS_FUNC :
00562
case MULS_FUNC :
00563
case DIVS_FUNC :
00564
00565
00566
00567
00568
00569
KiUnpackSingle(Fa, &ContextBlock, &SingleOperand1);
00570
KiUnpackSingle(Fb, &ContextBlock, &SingleOperand2);
00571
00572
00573
00574
00575
00576
00577
if ((ContextBlock.
IeeeMode ==
FALSE) &&
00578 ((SingleOperand1.
Normal ==
FALSE) ||
00579 (SingleOperand2.
Normal ==
FALSE))) {
00580 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
00581
return FALSE;
00582 }
00583
00584
if ((SingleOperand1.
Nan !=
FALSE) || (SingleOperand2.
Nan !=
FALSE)) {
00585
00586
00587
00588
00589
00590
00591
00592
00593
return KiInvalidOperationSingle(&ContextBlock,
00594 TRUE,
00595 &SingleOperand1,
00596 &SingleOperand2);
00597 }
00598
break;
00599
00600
case ADDT_FUNC :
00601
case SUBT_FUNC :
00602
case MULT_FUNC :
00603
case DIVT_FUNC :
00604
00605
00606
00607
00608
00609
KiUnpackDouble(Fa, &ContextBlock, &DoubleOperand1);
00610
KiUnpackDouble(Fb, &ContextBlock, &DoubleOperand2);
00611
00612
00613
00614
00615
00616
00617
if ((ContextBlock.
IeeeMode ==
FALSE) &&
00618 ((DoubleOperand1.
Normal ==
FALSE) ||
00619 (DoubleOperand2.
Normal ==
FALSE))) {
00620 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
00621
return FALSE;
00622 }
00623
if ((DoubleOperand1.
Nan !=
FALSE) || (DoubleOperand2.
Nan !=
FALSE)) {
00624
00625
00626
00627
00628
00629
00630
00631
00632
return KiInvalidOperationDouble(&ContextBlock,
00633 TRUE,
00634 &DoubleOperand1,
00635 &DoubleOperand2);
00636 }
00637
break;
00638
00639
case CMPTEQ_FUNC :
00640
case CMPTLE_FUNC :
00641
case CMPTLT_FUNC :
00642
case CMPTUN_FUNC :
00643
00644
00645
00646
00647
00648
KiUnpackDouble(Fa, &ContextBlock, &DoubleOperand1);
00649
KiUnpackDouble(Fb, &ContextBlock, &DoubleOperand2);
00650
00651
00652
00653
00654
00655
00656
if ((ContextBlock.
IeeeMode ==
FALSE) &&
00657 (((DoubleOperand1.
Normal ==
FALSE) &&
00658 (DoubleOperand1.
Infinity ==
FALSE)) ||
00659 ((DoubleOperand2.
Normal ==
FALSE) &&
00660 (DoubleOperand2.
Infinity ==
FALSE)))) {
00661 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
00662
return FALSE;
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
if ((DoubleOperand1.
Nan !=
FALSE) || (DoubleOperand2.
Nan !=
FALSE)) {
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
if ((Function & FP_FUNCTION_MASK) == CMPTUN_FUNC) {
00691
KiSetRegisterValue(ContextBlock.
Fc + 32,
00692 FP_COMPARE_TRUE,
00693 ExceptionFrame,
00694 TrapFrame);
00695
00696
return KiInvalidCompareDouble(&ContextBlock,
00697 TRUE,
00698 &DoubleOperand1,
00699 &DoubleOperand2);
00700
00701 }
else if ((Function & FP_FUNCTION_MASK) == CMPTEQ_FUNC) {
00702
KiSetRegisterValue(ContextBlock.
Fc + 32,
00703 FP_COMPARE_FALSE,
00704 ExceptionFrame,
00705 TrapFrame);
00706
00707
return KiInvalidCompareDouble(&ContextBlock,
00708 TRUE,
00709 &DoubleOperand1,
00710 &DoubleOperand2);
00711
00712 }
else {
00713
KiSetRegisterValue(ContextBlock.
Fc + 32,
00714 FP_COMPARE_FALSE,
00715 ExceptionFrame,
00716 TrapFrame);
00717
00718
return KiInvalidCompareDouble(&ContextBlock,
00719 FALSE,
00720 &DoubleOperand1,
00721 &DoubleOperand2);
00722 }
00723
00724 }
else {
00725
if ((Function & FP_FUNCTION_MASK) == CMPTUN_FUNC) {
00726
KiSetRegisterValue(ContextBlock.
Fc + 32,
00727 FP_COMPARE_FALSE,
00728 ExceptionFrame,
00729 TrapFrame);
00730
00731
return TRUE;
00732 }
00733 }
00734
break;
00735
00736
case CVTST_FUNC_PROPER :
00737
00738
00739
00740
00741
00742
00743
KiUnpackSingle(Fb, &ContextBlock, &SingleOperand1);
00744
00745
00746
00747
00748
00749
00750
if ((ContextBlock.
IeeeMode ==
FALSE) &&
00751 (SingleOperand1.
Normal ==
FALSE)) {
00752 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
00753
return FALSE;
00754 }
00755
break;
00756
00757
case CVTTQ_FUNC :
00758
case CVTTS_FUNC :
00759
00760
00761
00762
00763
00764
00765
KiUnpackDouble(Fb, &ContextBlock, &DoubleOperand1);
00766
00767
00768
00769
00770
00771
00772
if ((ContextBlock.
IeeeMode ==
FALSE) &&
00773 (DoubleOperand1.
Normal ==
FALSE)) {
00774 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
00775
return FALSE;
00776 }
00777
break;
00778
00779
case CVTLQ_FUNC :
00780
case CVTQL_FUNC :
00781
case CVTQS_FUNC :
00782
case CVTQT_FUNC :
00783
00784
00785
00786
00787
00788
00789 Quadword =
KiGetRegisterValue(Fb + 32,
00790 ContextBlock.
ExceptionFrame,
00791 ContextBlock.
TrapFrame);
00792
break;
00793 }
00794
00795
00796
00797
00798
00799 Negation = 0;
00800
switch (Function & FP_FUNCTION_MASK) {
00801
00802
00803
00804
00805
00806
00807
00808
00809
case SUBS_FUNC :
00810
DBGPRINT2(
"subs\n");
00811 Negation = 0x1;
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
case ADDS_FUNC :
00839
DBGPRINT2(
"adds\n");
00840
00841
00842
00843
00844
00845
00846 SingleOperand2.
Sign ^= Negation;
00847
00848
00849
00850
00851
00852
00853
if (SingleOperand2.
Exponent > SingleOperand1.
Exponent) {
00854 SingleOperand3 = SingleOperand2;
00855 SingleOperand2 = SingleOperand1;
00856 SingleOperand1 = SingleOperand3;
00857 }
00858
00859
00860
00861
00862
00863
00864
00865
00866 ExponentDifference =
00867 SingleOperand1.
Exponent - SingleOperand2.
Exponent;
00868
00869
if (ExponentDifference > 26) {
00870 ExponentDifference = 26;
00871 }
00872
00873 StickyBits =
00874 SingleOperand2.
Mantissa & ((1 << ExponentDifference) - 1);
00875 SingleMantissa = SingleOperand2.
Mantissa >> ExponentDifference;
00876
00877
00878
00879
00880
00881
00882
00883
00884
if ((SingleOperand1.
Sign ^ SingleOperand2.
Sign) == 0) {
00885 SingleOperand1.
Mantissa += SingleMantissa;
00886
00887 }
else {
00888
if ((SingleOperand1.
Infinity !=
FALSE) &&
00889 (SingleOperand2.
Infinity !=
FALSE)) {
00890
return KiInvalidOperationSingle(&ContextBlock,
00891 FALSE,
00892 &SingleOperand1,
00893 &SingleOperand2);
00894
00895 }
else if (SingleOperand1.
Infinity ==
FALSE) {
00896
if (StickyBits != 0) {
00897 SingleOperand1.
Mantissa -= 1;
00898 }
00899
00900 SingleOperand1.
Mantissa -= SingleMantissa;
00901
if (SingleOperand1.
Mantissa < 0) {
00902 SingleOperand1.
Mantissa = -SingleOperand1.
Mantissa;
00903 SingleOperand1.
Sign ^= 0x1;
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
if ((SingleOperand1.
Mantissa == 0) && (StickyBits == 0)) {
00913
if (ContextBlock.
Round == ROUND_TO_MINUS_INFINITY) {
00914 SingleOperand1.
Sign = 0x1;
00915
00916 }
else {
00917 SingleOperand1.
Sign = 0x0;
00918 }
00919 }
00920 }
00921 }
00922
00923
00924
00925
00926
00927
return KiNormalizeSingle(&ContextBlock,
00928 &SingleOperand1,
00929 StickyBits);
00930
00931
case SUBT_FUNC :
00932
DBGPRINT2(
"subt\n");
00933 Negation = 0x1;
00934
00935
case ADDT_FUNC :
00936
DBGPRINT2(
"addt\n");
00937
00938
00939
00940
00941
00942
00943 DoubleOperand2.
Sign ^= Negation;
00944
00945
00946
00947
00948
00949
00950
if (DoubleOperand2.
Exponent > DoubleOperand1.
Exponent) {
00951 DoubleOperand3 = DoubleOperand2;
00952 DoubleOperand2 = DoubleOperand1;
00953 DoubleOperand1 = DoubleOperand3;
00954 }
00955
00956
00957
00958
00959
00960
00961
00962
00963 ExponentDifference =
00964 DoubleOperand1.
Exponent - DoubleOperand2.
Exponent;
00965
00966
if (ExponentDifference > 55) {
00967 ExponentDifference = 55;
00968 }
00969
00970
if (ExponentDifference >= 32) {
00971 ExponentDifference -= 32;
00972 StickyBits = (DoubleOperand2.
MantissaLow) |
00973 (DoubleOperand2.
MantissaHigh & ((1 << ExponentDifference) - 1));
00974
00975 DoubleMantissaLow =
00976 DoubleOperand2.
MantissaHigh >> ExponentDifference;
00977
00978 DoubleMantissaHigh = 0;
00979
00980 }
else if (ExponentDifference > 0) {
00981 StickyBits =
00982 DoubleOperand2.
MantissaLow & ((1 << ExponentDifference) - 1);
00983
00984 DoubleMantissaLow =
00985 (DoubleOperand2.
MantissaLow >> ExponentDifference) |
00986 (DoubleOperand2.
MantissaHigh << (32 - ExponentDifference));
00987
00988 DoubleMantissaHigh =
00989 DoubleOperand2.
MantissaHigh >> ExponentDifference;
00990
00991 }
else {
00992 StickyBits = 0;
00993 DoubleMantissaLow = DoubleOperand2.
MantissaLow;
00994 DoubleMantissaHigh = DoubleOperand2.
MantissaHigh;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
if ((DoubleOperand1.
Sign ^ DoubleOperand2.
Sign) == 0) {
01005 DoubleOperand1.
MantissaLow += DoubleMantissaLow;
01006 DoubleOperand1.
MantissaHigh += DoubleMantissaHigh;
01007
if (DoubleOperand1.
MantissaLow < DoubleMantissaLow) {
01008 DoubleOperand1.
MantissaHigh += 1;
01009 }
01010
01011 }
else {
01012
if ((DoubleOperand1.
Infinity !=
FALSE) &&
01013 (DoubleOperand2.
Infinity !=
FALSE)) {
01014
return KiInvalidOperationDouble(&ContextBlock,
01015 FALSE,
01016 &DoubleOperand1,
01017 &DoubleOperand2);
01018
01019 }
else if (DoubleOperand1.
Infinity ==
FALSE) {
01020
if (StickyBits != 0) {
01021
if (DoubleOperand1.
MantissaLow < 1) {
01022 DoubleOperand1.
MantissaHigh -= 1;
01023 }
01024
01025 DoubleOperand1.
MantissaLow -= 1;
01026 }
01027
01028
if (DoubleOperand1.
MantissaLow < DoubleMantissaLow) {
01029 DoubleOperand1.
MantissaHigh -= 1;
01030 }
01031
01032 DoubleOperand1.
MantissaLow -= DoubleMantissaLow;
01033 DoubleOperand1.
MantissaHigh -= DoubleMantissaHigh;
01034
if (DoubleOperand1.
MantissaHigh < 0) {
01035 DoubleOperand1.
MantissaLow = -(LONG)DoubleOperand1.
MantissaLow;
01036 DoubleOperand1.
MantissaHigh = -DoubleOperand1.
MantissaHigh;
01037
if (DoubleOperand1.
MantissaLow != 0) {
01038 DoubleOperand1.
MantissaHigh -= 1;
01039 }
01040 DoubleOperand1.
Sign ^= 0x1;
01041 }
01042
01043
01044
01045
01046
01047
01048
01049
if ((DoubleOperand1.
MantissaHigh == 0) &&
01050 (DoubleOperand1.
MantissaLow == 0) &&
01051 (StickyBits == 0)) {
01052
if (ContextBlock.
Round == ROUND_TO_MINUS_INFINITY) {
01053 DoubleOperand1.
Sign = 0x1;
01054
01055 }
else {
01056 DoubleOperand1.
Sign = 0x0;
01057 }
01058 }
01059 }
01060 }
01061
01062
01063
01064
01065
01066
return KiNormalizeDouble(&ContextBlock,
01067 &DoubleOperand1,
01068 StickyBits);
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
case MULS_FUNC :
01082
DBGPRINT2(
"muls\n");
01083
01084
01085
01086
01087
01088
01089
if (SingleOperand2.
Exponent > SingleOperand1.
Exponent) {
01090 SingleOperand3 = SingleOperand2;
01091 SingleOperand2 = SingleOperand1;
01092 SingleOperand1 = SingleOperand3;
01093 }
01094
01095
01096
01097
01098
01099
01100
if ((SingleOperand1.
Infinity !=
FALSE) &&
01101 (SingleOperand2.
Infinity ==
FALSE) &&
01102 (SingleOperand2.
Mantissa == 0)) {
01103
return KiInvalidOperationSingle(&ContextBlock,
01104 FALSE,
01105 &SingleOperand1,
01106 &SingleOperand2);
01107 }
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129 LargeResult.QuadPart = ((ULONGLONG)((ULONG)(SingleOperand1.
Mantissa << (32 - 26)))) *
01130 ((ULONGLONG)((ULONG)(SingleOperand2.
Mantissa << 1)));
01131
01132 SingleOperand1.
Mantissa = LargeResult.HighPart;
01133 StickyBits = LargeResult.LowPart;
01134
01135
01136
01137
01138
01139 SingleOperand1.
Sign ^= SingleOperand2.
Sign;
01140 SingleOperand1.
Exponent +=
01141 SingleOperand2.
Exponent - SINGLE_EXPONENT_BIAS;
01142
01143
01144
01145
01146
01147
return KiNormalizeSingle(&ContextBlock,
01148 &SingleOperand1,
01149 StickyBits);
01150
01151
case MULT_FUNC :
01152
DBGPRINT2(
"mult\n");
01153
01154
01155
01156
01157
01158
01159
if (DoubleOperand2.
Exponent > DoubleOperand1.
Exponent) {
01160 DoubleOperand3 = DoubleOperand2;
01161 DoubleOperand2 = DoubleOperand1;
01162 DoubleOperand1 = DoubleOperand3;
01163 }
01164
01165
01166
01167
01168
01169
01170
if ((DoubleOperand1.
Infinity !=
FALSE) &&
01171 (DoubleOperand2.
Infinity ==
FALSE) &&
01172 (DoubleOperand2.
MantissaHigh == 0)) {
01173
return KiInvalidOperationDouble(&ContextBlock,
01174 FALSE,
01175 &DoubleOperand1,
01176 &DoubleOperand2);
01177 }
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199 DoubleOperand1.
MantissaHigh =
01200 (DoubleOperand1.
MantissaHigh << 1) |
01201 (DoubleOperand1.
MantissaLow >> 31);
01202
01203 DoubleOperand1.
MantissaLow <<= 1;
01204 DoubleOperand2.
MantissaHigh =
01205 (DoubleOperand2.
MantissaHigh << (64 - 55)) |
01206 (DoubleOperand2.
MantissaLow >> (32 - (64 - 55)));
01207
01208 DoubleOperand2.
MantissaLow <<= (64 - 55);
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224 AhighBhigh.QuadPart = (ULONGLONG)(ULONG)DoubleOperand1.
MantissaHigh *
01225 (ULONGLONG)(ULONG)DoubleOperand2.
MantissaHigh;
01226
01227 AhighBlow.QuadPart = (ULONGLONG)(ULONG)DoubleOperand1.
MantissaHigh *
01228 (ULONGLONG)DoubleOperand2.
MantissaLow;
01229
01230 AlowBhigh.QuadPart = (ULONGLONG)DoubleOperand1.
MantissaLow *
01231 (ULONGLONG)(ULONG)DoubleOperand2.
MantissaHigh;
01232
01233 AlowBlow.QuadPart = (ULONGLONG)DoubleOperand1.
MantissaLow *
01234 (ULONGLONG)DoubleOperand2.
MantissaLow;
01235
01236 AlowBlow.HighPart += AhighBlow.LowPart;
01237
if (AlowBlow.HighPart < AhighBlow.LowPart) {
01238 Carry1 = 1;
01239
01240 }
else {
01241 Carry1 = 0;
01242 }
01243
01244 AlowBlow.HighPart += AlowBhigh.LowPart;
01245
if (AlowBlow.HighPart < AlowBhigh.LowPart) {
01246 Carry1 += 1;
01247 }
01248
01249 DoubleOperand1.
MantissaLow = AhighBlow.HighPart + Carry1;
01250
if (DoubleOperand1.
MantissaLow < Carry1) {
01251 Carry2 = 1;
01252
01253 }
else {
01254 Carry2 = 0;
01255 }
01256
01257 DoubleOperand1.
MantissaLow += AlowBhigh.HighPart;
01258
if (DoubleOperand1.
MantissaLow < AlowBhigh.HighPart) {
01259 Carry2 += 1;
01260 }
01261
01262 DoubleOperand1.
MantissaLow += AhighBhigh.LowPart;
01263
if (DoubleOperand1.
MantissaLow < AhighBhigh.LowPart) {
01264 Carry2 += 1;
01265 }
01266
01267 DoubleOperand1.
MantissaHigh = AhighBhigh.HighPart + Carry2;
01268 StickyBits = AlowBlow.HighPart | AlowBlow.LowPart;
01269
01270
01271
01272
01273
01274 DoubleOperand1.
Sign ^= DoubleOperand2.
Sign;
01275 DoubleOperand1.
Exponent +=
01276 DoubleOperand2.
Exponent - DOUBLE_EXPONENT_BIAS;
01277
01278
01279
01280
01281
01282
return KiNormalizeDouble(&ContextBlock,
01283 &DoubleOperand1,
01284 StickyBits);
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
case DIVS_FUNC :
01299
DBGPRINT2(
"divs\n");
01300
01301
01302
01303
01304
01305
01306
01307
if (((SingleOperand1.
Infinity !=
FALSE) &&
01308 (SingleOperand2.
Infinity !=
FALSE)) ||
01309 ((SingleOperand1.
Infinity ==
FALSE) &&
01310 (SingleOperand1.
Mantissa == 0) &&
01311 (SingleOperand2.
Infinity ==
FALSE) &&
01312 (SingleOperand2.
Mantissa == 0))) {
01313
return KiInvalidOperationSingle(&ContextBlock,
01314 FALSE,
01315 &SingleOperand1,
01316 &SingleOperand2);
01317 }
01318
01319
01320
01321
01322
01323
01324
if ((SingleOperand2.
Infinity ==
FALSE) &&
01325 (SingleOperand2.
Mantissa == 0)) {
01326
return KiDivideByZeroSingle(&ContextBlock,
01327 &SingleOperand1,
01328 &SingleOperand2);
01329 }
01330
01331
01332
01333
01334
01335
01336
01337
01338
if (SingleOperand1.
Infinity !=
FALSE) {
01339 SingleOperand1.
Sign ^= SingleOperand2.
Sign;
01340
return KiNormalizeSingle(&ContextBlock,
01341 &SingleOperand1,
01342 0);
01343
01344 }
else if (SingleOperand2.
Infinity !=
FALSE) {
01345 SingleOperand1.
Sign ^= SingleOperand2.
Sign;
01346 SingleOperand1.
Exponent = 0;
01347 SingleOperand1.
Mantissa = 0;
01348
return KiNormalizeSingle(&ContextBlock,
01349 &SingleOperand1,
01350 0);
01351 }
01352
01353
01354
01355
01356
01357
01358 SingleOperand3.
Mantissa = 0;
01359
for (
Index = 0;
Index < 26;
Index += 1) {
01360 SingleOperand3.
Mantissa <<= 1;
01361
if (SingleOperand1.
Mantissa >= SingleOperand2.
Mantissa) {
01362 SingleOperand1.
Mantissa -= SingleOperand2.
Mantissa;
01363 SingleOperand3.
Mantissa |= 1;
01364 }
01365
01366 SingleOperand1.
Mantissa <<= 1;
01367 }
01368
01369
01370
01371
01372
01373 SingleOperand3.
Sign = SingleOperand1.
Sign ^ SingleOperand2.
Sign;
01374 SingleOperand3.
Exponent = SingleOperand1.
Exponent -
01375 SingleOperand2.
Exponent + SINGLE_EXPONENT_BIAS;
01376
01377
01378
01379
01380
01381 SingleOperand3.
Infinity =
FALSE;
01382 SingleOperand3.
Nan =
FALSE;
01383
return KiNormalizeSingle(&ContextBlock,
01384 &SingleOperand3,
01385 SingleOperand1.
Mantissa);
01386
01387
case DIVT_FUNC :
01388
DBGPRINT2(
"divt\n");
01389
01390
01391
01392
01393
01394
01395
01396
if (((DoubleOperand1.
Infinity !=
FALSE) &&
01397 (DoubleOperand2.
Infinity !=
FALSE)) ||
01398 ((DoubleOperand1.
Infinity ==
FALSE) &&
01399 (DoubleOperand1.
MantissaHigh == 0) &&
01400 (DoubleOperand2.
Infinity ==
FALSE) &&
01401 (DoubleOperand2.
MantissaHigh == 0))) {
01402
return KiInvalidOperationDouble(&ContextBlock,
01403 FALSE,
01404 &DoubleOperand1,
01405 &DoubleOperand2);
01406 }
01407
01408
01409
01410
01411
01412
01413
if ((DoubleOperand2.
Infinity ==
FALSE) &&
01414 (DoubleOperand2.
MantissaHigh == 0)) {
01415
return KiDivideByZeroDouble(&ContextBlock,
01416 &DoubleOperand1,
01417 &DoubleOperand2);
01418 }
01419
01420
01421
01422
01423
01424
01425
01426
01427
if (DoubleOperand1.
Infinity !=
FALSE) {
01428 DoubleOperand1.
Sign ^= DoubleOperand2.
Sign;
01429
return KiNormalizeDouble(&ContextBlock,
01430 &DoubleOperand1,
01431 0);
01432
01433 }
else if (DoubleOperand2.
Infinity !=
FALSE) {
01434 DoubleOperand1.
Sign ^= DoubleOperand2.
Sign;
01435 DoubleOperand1.
Exponent = 0;
01436 DoubleOperand1.
MantissaHigh = 0;
01437 DoubleOperand1.
MantissaLow = 0;
01438
return KiNormalizeDouble(&ContextBlock,
01439 &DoubleOperand1,
01440 0);
01441 }
01442
01443
01444
01445
01446
01447
01448 DoubleDividend.LowPart = DoubleOperand1.
MantissaLow;
01449 DoubleDividend.HighPart = DoubleOperand1.
MantissaHigh;
01450 DoubleDivisor.LowPart = DoubleOperand2.
MantissaLow;
01451 DoubleDivisor.HighPart = DoubleOperand2.
MantissaHigh;
01452 DoubleQuotient.LowPart = 0;
01453 DoubleQuotient.HighPart = 0;
01454
for (
Index = 0;
Index < 55;
Index += 1) {
01455 DoubleQuotient.HighPart =
01456 (DoubleQuotient.HighPart << 1) |
01457 DoubleQuotient.LowPart >> 31;
01458
01459 DoubleQuotient.LowPart <<= 1;
01460
if (DoubleDividend.QuadPart >= DoubleDivisor.QuadPart) {
01461 DoubleDividend.QuadPart = DoubleDividend.QuadPart - DoubleDivisor.QuadPart;
01462 DoubleQuotient.LowPart |= 1;
01463 }
01464
01465 DoubleDividend.HighPart =
01466 (DoubleDividend.HighPart << 1) |
01467 DoubleDividend.LowPart >> 31;
01468
01469 DoubleDividend.LowPart <<= 1;
01470 }
01471
01472 DoubleOperand3.
MantissaLow = DoubleQuotient.LowPart;
01473 DoubleOperand3.
MantissaHigh = DoubleQuotient.HighPart;
01474
01475
01476
01477
01478
01479 DoubleOperand3.
Sign = DoubleOperand1.
Sign ^ DoubleOperand2.
Sign;
01480 DoubleOperand3.
Exponent = DoubleOperand1.
Exponent -
01481 DoubleOperand2.
Exponent + DOUBLE_EXPONENT_BIAS;
01482
01483
01484
01485
01486
01487 DoubleOperand3.
Infinity =
FALSE;
01488 DoubleOperand3.
Nan =
FALSE;
01489
return KiNormalizeDouble(&ContextBlock,
01490 &DoubleOperand3,
01491 DoubleDividend.LowPart | DoubleDividend.HighPart);
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
case CMPTEQ_FUNC :
01507
case CMPTLE_FUNC :
01508
case CMPTLT_FUNC :
01509
01510
01511
01512
01513
01514
01515
01516
if ((DoubleOperand1.
Infinity ==
FALSE) &&
01517 (DoubleOperand1.
MantissaHigh == 0)) {
01518 DoubleOperand1.
Sign = 0;
01519 DoubleOperand1.
Exponent = -52;
01520 }
01521
01522
if ((DoubleOperand2.
Infinity ==
FALSE) &&
01523 (DoubleOperand2.
MantissaHigh == 0)) {
01524 DoubleOperand2.
Sign = 0;
01525 DoubleOperand2.
Exponent = -52;
01526 }
01527
01528
01529
01530
01531
01532
if (DoubleOperand1.
Sign < DoubleOperand2.
Sign) {
01533
01534
01535
01536
01537
01538 CompareEqual =
FALSE;
01539 CompareLess =
FALSE;
01540
01541 }
else if (DoubleOperand1.
Sign > DoubleOperand2.
Sign) {
01542
01543
01544
01545
01546
01547 CompareEqual =
FALSE;
01548 CompareLess =
TRUE;
01549
01550 }
else {
01551
01552
01553
01554
01555
01556
01557
01558
01559
if (DoubleOperand1.
Sign == 0) {
01560
01561
01562
01563
01564
01565
if (DoubleOperand1.
Exponent > DoubleOperand2.
Exponent) {
01566 CompareEqual =
FALSE;
01567 CompareLess =
FALSE;
01568
01569 }
else if (DoubleOperand1.
Exponent < DoubleOperand2.
Exponent) {
01570 CompareEqual =
FALSE;
01571 CompareLess =
TRUE;
01572
01573 }
else {
01574
if (DoubleOperand1.
MantissaHigh >
01575 DoubleOperand2.
MantissaHigh) {
01576 CompareEqual =
FALSE;
01577 CompareLess =
FALSE;
01578
01579 }
else if (DoubleOperand1.
MantissaHigh <
01580 DoubleOperand2.
MantissaHigh) {
01581 CompareEqual =
FALSE;
01582 CompareLess =
TRUE;
01583
01584 }
else {
01585
if (DoubleOperand1.
MantissaLow >
01586 DoubleOperand2.
MantissaLow) {
01587 CompareEqual =
FALSE;
01588 CompareLess =
FALSE;
01589
01590 }
else if (DoubleOperand1.
MantissaLow <
01591 DoubleOperand2.
MantissaLow) {
01592 CompareEqual =
FALSE;
01593 CompareLess =
TRUE;
01594
01595 }
else {
01596 CompareEqual =
TRUE;
01597 CompareLess =
FALSE;
01598 }
01599 }
01600 }
01601
01602 }
else {
01603
01604
01605
01606
01607
01608
if (DoubleOperand2.
Exponent > DoubleOperand1.
Exponent) {
01609 CompareEqual =
FALSE;
01610 CompareLess =
FALSE;
01611
01612 }
else if (DoubleOperand2.
Exponent < DoubleOperand1.
Exponent) {
01613 CompareEqual =
FALSE;
01614 CompareLess =
TRUE;
01615
01616 }
else {
01617
if (DoubleOperand2.
MantissaHigh >
01618 DoubleOperand1.
MantissaHigh) {
01619 CompareEqual =
FALSE;
01620 CompareLess =
FALSE;
01621
01622 }
else if (DoubleOperand2.
MantissaHigh <
01623 DoubleOperand1.
MantissaHigh) {
01624 CompareEqual =
FALSE;
01625 CompareLess =
TRUE;
01626
01627 }
else {
01628
if (DoubleOperand2.
MantissaLow >
01629 DoubleOperand1.
MantissaLow) {
01630 CompareEqual =
FALSE;
01631 CompareLess =
FALSE;
01632
01633 }
else if (DoubleOperand2.
MantissaLow <
01634 DoubleOperand1.
MantissaLow) {
01635 CompareEqual =
FALSE;
01636 CompareLess =
TRUE;
01637
01638 }
else {
01639 CompareEqual =
TRUE;
01640 CompareLess =
FALSE;
01641 }
01642 }
01643 }
01644 }
01645 }
01646
01647
01648
01649
01650
01651
01652
switch (Function & FP_FUNCTION_MASK) {
01653
case CMPTEQ_FUNC :
01654 CompareResult = CompareEqual;
01655
DBGPRINT2(
"cmpteq\n");
01656
break;
01657
01658
case CMPTLE_FUNC :
01659 CompareResult = (CompareLess | CompareEqual);
01660
DBGPRINT2(
"cmptle\n");
01661
break;
01662
01663
case CMPTLT_FUNC :
01664 CompareResult = CompareLess;
01665
DBGPRINT2(
"cmptlt\n");
01666
break;
01667 }
01668
01669
01670
01671
01672
01673
01674
if (CompareResult !=
FALSE) {
01675
KiSetRegisterValue(ContextBlock.
Fc + 32,
01676 FP_COMPARE_TRUE,
01677 ExceptionFrame,
01678 TrapFrame);
01679
01680 }
else {
01681
KiSetRegisterValue(ContextBlock.
Fc + 32,
01682 FP_COMPARE_FALSE,
01683 ExceptionFrame,
01684 TrapFrame);
01685 }
01686
return TRUE;
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
case CVTST_FUNC_PROPER :
01697
DBGPRINT2(
"cvtst\n");
01698
01699
01700
01701
01702
01703
01704
01705
01706
if (SingleOperand1.
Nan !=
FALSE) {
01707 DoubleOperand1.
MantissaHigh =
01708 SingleOperand1.
Mantissa >> (26 - (55 - 32));
01709 DoubleOperand1.
MantissaLow =
01710 SingleOperand1.
Mantissa << (32 - (26 - (55 - 32)));
01711 DoubleOperand1.
Exponent = DOUBLE_MAXIMUM_EXPONENT;
01712 DoubleOperand1.
Sign = SingleOperand1.
Sign;
01713 DoubleOperand1.
Infinity =
FALSE;
01714 DoubleOperand1.
Nan =
TRUE;
01715
return KiInvalidOperationDouble(&ContextBlock,
01716 TRUE,
01717 &DoubleOperand1,
01718 &DoubleOperand1);
01719 }
01720
01721
01722
01723
01724
01725 DoubleOperand1.
MantissaHigh =
01726 SingleOperand1.
Mantissa >> (26 - (55 - 32));
01727 DoubleOperand1.
MantissaLow =
01728 SingleOperand1.
Mantissa << (32 - (26 - (55 - 32)));
01729 DoubleOperand1.
Exponent = SingleOperand1.
Exponent +
01730 DOUBLE_EXPONENT_BIAS - SINGLE_EXPONENT_BIAS;
01731 DoubleOperand1.
Sign = SingleOperand1.
Sign;
01732 DoubleOperand1.
Infinity = SingleOperand1.
Infinity;
01733 DoubleOperand1.
Nan =
FALSE;
01734
01735
01736
01737
01738
01739
return KiNormalizeDouble(&ContextBlock,
01740 &DoubleOperand1,
01741 0);
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
case CVTTS_FUNC :
01752
DBGPRINT2(
"cvtts\n");
01753
01754
01755
01756
01757
01758
01759
01760
01761
if (DoubleOperand1.
Nan !=
FALSE) {
01762 SingleOperand1.
Mantissa =
01763 (DoubleOperand1.
MantissaHigh << (26 - (55 - 32))) |
01764 (DoubleOperand1.
MantissaLow >> (32 - (26 - (55 - 32))));
01765 SingleOperand1.
Exponent = SINGLE_MAXIMUM_EXPONENT;
01766 SingleOperand1.
Sign = DoubleOperand1.
Sign;
01767 SingleOperand1.
Infinity =
FALSE;
01768 SingleOperand1.
Nan =
TRUE;
01769
return KiInvalidOperationSingle(&ContextBlock,
01770 TRUE,
01771 &SingleOperand1,
01772 &SingleOperand1);
01773 }
01774
01775
01776
01777
01778
01779 SingleOperand1.
Mantissa =
01780 (DoubleOperand1.
MantissaHigh << (26 - (55 - 32))) |
01781 (DoubleOperand1.
MantissaLow >> (32 - (26 - (55 - 32))));
01782 StickyBits = DoubleOperand1.
MantissaLow << (26 - (55 - 32));
01783 SingleOperand1.
Exponent = DoubleOperand1.
Exponent +
01784 SINGLE_EXPONENT_BIAS - DOUBLE_EXPONENT_BIAS;
01785 SingleOperand1.
Sign = DoubleOperand1.
Sign;
01786 SingleOperand1.
Infinity = DoubleOperand1.
Infinity;
01787 SingleOperand1.
Nan =
FALSE;
01788
01789
01790
01791
01792
01793
return KiNormalizeSingle(&ContextBlock,
01794 &SingleOperand1,
01795 StickyBits);
01796
01797
01798
01799
01800
01801
01802
01803
01804
case CVTLQ_FUNC :
01805
DBGPRINT2(
"cvtlq\n");
01806
01807
01808
01809
01810
01811
01812
01813
01814 Quadword = ((Quadword >> 62) << 62) | ((ULONGLONG)(Quadword << 5) >> 2);
01815
KiSetRegisterValue(ContextBlock.
Fc + 32,
01816 Quadword >> 32,
01817 ExceptionFrame,
01818 TrapFrame);
01819
01820
return TRUE;
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
case CVTQL_FUNC :
01831
DBGPRINT2(
"cvtql\n");
01832
01833
return KiConvertQuadwordToLongword(&ContextBlock, Quadword);
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
case CVTQS_FUNC :
01844
DBGPRINT2(
"cvtqs\n");
01845
01846
01847
01848
01849
01850
if (Quadword < 0) {
01851 SingleOperand1.
Sign = 0x1;
01852 Quadword = -Quadword;
01853
01854 }
else {
01855 SingleOperand1.
Sign = 0;
01856 }
01857
01858
01859
01860
01861
01862 SingleOperand1.
Infinity =
FALSE;
01863 SingleOperand1.
Nan =
FALSE;
01864
01865
01866
01867
01868
01869
01870
if (Quadword != 0) {
01871 SingleOperand1.
Exponent = SINGLE_EXPONENT_BIAS + 63;
01872
while (Quadword > 0) {
01873 Quadword <<= 1;
01874 SingleOperand1.
Exponent -= 1;
01875 }
01876
01877 SingleOperand1.
Mantissa = (LONG)((ULONGLONG)Quadword >> (64 - 26));
01878
if (Quadword & (((ULONGLONG)1 << (64 - 26)) - 1)) {
01879 StickyBits = 1;
01880
01881 }
else {
01882 StickyBits = 0;
01883 }
01884
01885 }
else {
01886 SingleOperand1.
Exponent = 0;
01887 SingleOperand1.
Mantissa = 0;
01888 StickyBits = 0;
01889 }
01890
01891
01892
01893
01894
01895
return KiNormalizeSingle(&ContextBlock,
01896 &SingleOperand1,
01897 StickyBits);
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
case CVTQT_FUNC :
01908
DBGPRINT2(
"cvtqt\n");
01909
01910
01911
01912
01913
01914
if (Quadword < 0) {
01915 DoubleOperand1.
Sign = 0x1;
01916 Quadword = -Quadword;
01917
01918 }
else {
01919 DoubleOperand1.
Sign = 0;
01920 }
01921
01922
01923
01924
01925
01926 DoubleOperand1.
Infinity =
FALSE;
01927 DoubleOperand1.
Nan =
FALSE;
01928
01929
01930
01931
01932
01933
01934
if (Quadword != 0) {
01935 DoubleOperand1.
Exponent = DOUBLE_EXPONENT_BIAS + 63;
01936
while (Quadword > 0) {
01937 Quadword <<= 1;
01938 DoubleOperand1.
Exponent -= 1;
01939 }
01940
01941 DoubleOperand1.
MantissaHigh = (LONG)((ULONGLONG)Quadword >> ((64 - 55) + 32));
01942 DoubleOperand1.
MantissaLow = (LONG)((ULONGLONG)Quadword >> (64 - 55));
01943
if (Quadword & (((ULONGLONG)1 << (64 - 55)) - 1)) {
01944 StickyBits = 1;
01945
01946 }
else {
01947 StickyBits = 0;
01948 }
01949
01950 }
else {
01951 DoubleOperand1.
MantissaHigh = 0;
01952 DoubleOperand1.
MantissaLow = 0;
01953 DoubleOperand1.
Exponent = 0;
01954 StickyBits = 0;
01955 }
01956
01957
01958
01959
01960
01961
return KiNormalizeDouble(&ContextBlock,
01962 &DoubleOperand1,
01963 StickyBits);
01964
01965
01966
01967
01968
01969
01970
01971
01972
case CVTTQ_FUNC :
01973
DBGPRINT2(
"cvttq\n");
01974
01975
01976
01977
01978
01979
01980
01981
01982
if ((DoubleOperand1.
Infinity !=
FALSE) ||
01983 (DoubleOperand1.
Nan !=
FALSE)) {
01984
return KiInvalidOperationQuadword(&ContextBlock, 0);
01985 }
01986
01987
01988
01989
01990
01991
return KiNormalizeQuadword(&ContextBlock, &DoubleOperand1);
01992 }
01993
01994
01995
01996
01997
01998
01999 } except (
KiCopyInformation(ExceptionRecord,
02000 (GetExceptionInformation())->ExceptionRecord)) {
02001
02002
02003
02004
02005
02006 ExceptionRecord->ExceptionAddress = ExceptionAddress;
02007
DBGPRINT(
"KiEmulateFloating: Exception\n");
02008
return FALSE;
02009 }
02010
02011
DBGPRINT(
"KiEmulateFloating: Invalid Instruction\n");
02012
return FALSE;
02013 }