Code: Alles auswählen
;- FPU-Helferlein
;- "Helle" Klaus Helbing, 12.08.2007, PB4.02
;===================================================================================================
;- FPU-STATUS-REGISTER:
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; Bit | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; | B | C3 | Top | C2 | C1 | C0 | E | S | P | U | O | Z | D | I |
; +----+----+--------------+----+----+----+----+----+----+----+----+----+----+----+
;- Bedeutung:
;- I: Invalid Operation; es wurde eine ungültige Operation durchgeführt
;- D: Denormalized Operand; eine denormalisierte Zahl wurde verwendet
;- Z: Zero Divide; es wurde versucht, durch Null zu dividieren
;- O: Overflow; mit der vorhergehenden Operation wurde der maximal darstellbare Wert überschritten
;- U: Underflow; mit der vorhergehenden Operation wurde der minimal darstellbare Wert unterschritten
;- P: Precision; die Genauigkeit der Berechnung ist unzureichend, z.B. eingestellte Genauigkeit ist
; Double Extended Precision, aber es werden Double- oder Single-Precision-Werte geladen
;- S: Stack Fault; es wurde versucht, einen Wert zu laden, obwohl alle Register belegt sind
; oder ein leeres Register soll gepoppt werden
;- E: Error Summary Status
;- C0: Condition Code 0; Flag für z.B. Vergleiche
;- C1: Condition Code 1; Flag für z.B. angewandte Rundung
;- C2: Condition Code 2; Flag für z.B. Vergleiche
;- Top: Top of Stack; Wert zwischen 0 und 7, gibt an, welches Register aktuell das oberste ist
;- C3: Condition Code 3; Flag für z.B. Vergleiche
;- B: Busy; signalisiert, das die FPU beschäftigt ist
;- Mittels
;!fnstsw ax ;Status-Word der FPU in Register AX kopieren
;!sahf ;Register AH in CPU-Flag-Register kopieren
;- lassen sich C0, C2, C3 und Busy direkt auswerten. Es gelten dann folgende Zuordnungen:
;- C0 = Carry-Flag
;- C2 = Parity-Flag
;- C3 = Zero-Flag
;- B = Sign-Flag
;===================================================================================================
;- FPU-CONTROL-REGISTER:
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; Bit | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
; +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
; | | IC | RC | PC | | | P | U | O | Z | D | I |
; +--------------+----+---------+---------+----+----+----+----+----+----+----+----+
;- Bedeutung:
;- I: Invalid Operation; es wurde eine ungültige Operation durchgeführt
;- D: Denormalized Operand; eine denormalisierte Zahl wurde verwendet
;- Z: Zero Divide; es wurde versucht, durch Null zu dividieren
;- O: Overflow; mit der vorhergehenden Operation wurde der maximal darstellbare Wert überschritten
;- U: Underflow; mit der vorhergehenden Operation wurde der minimal darstellbare Wert unterschritten
;- P: Precision; die Genauigkeit der Berechnung ist unzureichend; es wurden Double-oder Single-
; Precision-Werte geladen
;- PC: Precision Control; aktuell eingestellte Genauigkeit der Mantisse:
; 00b = 0 = Single Precision 24 Bits
; 01b = 1 = Reserviert
; 10b = 2 = Double Precision 53 Bits
; 11b = 3 = Double Extended Precision 64 Bits; Initialisierungs-Wert
;- RC: Rounding Control; aktuell eingestellter Rundungs-Modus:
; 00b = 0 = Rundung zum nächsten Wert oder bei Gleichheit zum geraden Wert;
; Initialisierungs-Wert
; 01b = 1 = Rundung in Richtung minus Unendlich
; 10b = 2 = Rundung in Richtung plus Unendlich
; 11b = 3 = Rundung in Richtung Null, d.h. der Nachkomma-Anteil wird
; abgeschnitten
;- IC: Infinity Control; aktuell eingestelltes Verfahren zur Unendlichkeits-Handhabung:
; 0b = 0 = projektives Verfahren, ist ein Zahlenkreis, minus und plus
; Unendlich treffen sich in einem Punkt; Initialisierungs-Wert
; 1b = 1 = affines Verfahren, ist eine Zahlen-Gerade mit den beiden Achs-
; Endpunkten minus Unendlich und plus Unendlich
;===================================================================================================
;OPCODES alphabetisch bzw. thematisch:
;D9 F0 F2XM1 Replace ST(0) with (2^ST(0))-1.
;D9 E1 FABS Replace ST with its absolute value.
;D8 /0 FADD m32fp Add m32fp To ST(0) and store result in ST(0).
;DC /0 FADD m64fp Add m64fp To ST(0) and store result in ST(0).
;D8 C0+i FADD ST(0), ST(i) Add ST(0) To ST(i) and store result in ST(0).
;DC C0+i FADD ST(i), ST(0) Add ST(i) To ST(0) and store result in ST(i).
;DE C0+i FADDP ST(i), ST(0) Add ST(0) To ST(i), store result in ST(i), and pop the register stack.
;DE C1 FADDP Add ST(0) To ST(1), store result in ST(1), and pop the register stack.
;DA /0 FIADD m32int Add m32int To ST(0) and store result in ST(0).
;DE /0 FIADD m16int Add m16int To ST(0) and store result in ST(0).
;DF /4 FBLD m80 dec Convert BCD value to floating-point and push onto the FPU stack.
;DF /6 FBSTP m80bcd Store ST(0) in m80bcd and pop ST(0).
;D9 E0 FCHS Complements sign of ST(0).
;9B DB E2 FCLEX Clear floating-point exception flags after checking for pending
; unmasked floating-point exceptions.
;DB E2 FNCLEX Clear floating-point exception flags without checking for
; pending unmasked floating-point exceptions.
;DA C0+i FCMOVB ST(0), ST(i) Move if below (CF=1).
;DA C8+i FCMOVE ST(0), ST(i) Move if equal (ZF=1).
;DA D0+i FCMOVBE ST(0), ST(i) Move if below or equal (CF=1 or ZF=1).
;DA D8+i FCMOVU ST(0), ST(i) Move if unordered (PF=1).
;DB C0+i FCMOVNB ST(0), ST(i) Move if not below (CF=0).
;DB C8+i FCMOVNE ST(0), ST(i) Move if not equal (ZF=0).
;DB D0+i FCMOVNBE ST(0), ST(i) Move if not below or equal (CF=0 and ZF=0).
;DB D8+i FCMOVNU ST(0), ST(i) Move if not unordered (PF=0).
;D8 /2 FCOM m32fp Compare ST(0) with m32fp.
;DC /2 FCOM m64fp Compare ST(0) with m64fp.
;D8 D0+i FCOM ST(i) Compare ST(0) with ST(i).
;D8 D1 FCOM Compare ST(0) With ST(1).
;D8 /3 FCOMP m32fp Compare ST(0) with m32fp and pop register stack.
;DC /3 FCOMP m64fp Compare ST(0) with m64fp and pop register stack.
;D8 D8+i FCOMP ST(i) Compare ST(0) with ST(i) and pop register stack.
;D8 D9 FCOMP Compare ST(0) with ST(1) and pop register stack.
;DE D9 FCOMPP Compare ST(0) with ST(1) and pop register stack twice.
;DB F0+i FCOMI ST, ST(i) Compare ST(0) with ST(i) and set status flags accordingly.
;DF F0+i FCOMIP ST, ST(i) Compare ST(0) with ST(i), set status flags accordingly, and
; pop register stack.
;DB E8+i FUCOMI ST, ST(i) Compare ST(0) with ST(i), check for ordered values, and set
; status flags accordingly.
;DF E8+i FUCOMIP ST, ST(i) Compare ST(0) with ST(i), check for ordered values, set status
; flags accordingly, and pop register stack.
;D9 FF FCOS Replace ST(0) with its cosine.
;D9 F6 FDECSTP Decrement TOP field in FPU status word.
;D8 /6 FDIV m32fp Divide ST(0) by m32fp and store result in ST(0).
;DC /6 FDIV m64fp Divide ST(0) by m64fp and store result in ST(0).
;D8 F0+i FDIV ST(0), ST(i) Divide ST(0) by ST(i) and store result in ST(0).
;DC F8+i FDIV ST(i), ST(0) Divide ST(i) by ST(0) and store result in ST(i).
;DE F8+i FDIVP ST(i), ST(0) Divide ST(i) by ST(0), store result in ST(i), and pop the
; register stack.
;DE F9 FDIVP Divide ST(1) by ST(0), store result in ST(1), and pop the
; register stack.
;DA /6 FIDIV m32int Divide ST(0) by m32int and store result in ST(0).
;DE /6 FIDIV m16int Divide ST(0) by m64int and store result in ST(0).
;D8 /7 FDIVR m32fp Divide m32fp by ST(0) and store result in ST(0).
;DC /7 FDIVR m64fp Divide m64fp by ST(0) and store result in ST(0).
;D8 F8+i FDIVR ST(0), ST(i) Divide ST(i) by ST(0) and store result in ST(0).
;DC F0+i FDIVR ST(i), ST(0) Divide ST(0) by ST(i) and store result in ST(i).
;DE F0+i FDIVRP ST(i), ST(0) Divide ST(0) by ST(i), store result in ST(i), and pop the
; register stack.
;DE F1 FDIVRP Divide ST(0) by ST(1), store result in ST(1), and pop the
; register stack.
;DA /7 FIDIVR m32int Divide m32int by ST(0) and store result in ST(0).
;DE /7 FIDIVR m16int Divide m16int by ST(0) and store result in ST(0).
;DD C0+i FFREE ST(i) Sets tag for ST(i) to empty.
;DE /2 FICOM m16int Compare ST(0) with m16int.
;DA /2 FICOM m32int Compare ST(0) with m32int.
;DE /3 FICOMP m16int Compare ST(0) with m16int and pop stack register.
;DA /3 FICOMP m32int Compare ST(0) with m32int and pop stack register.
;DF /0 FILD m16int Push m16int onto the FPU register stack.
;DB /0 FILD m32int Push m32int onto the FPU register stack.
;DF /5 FILD m64int Push m64int onto the FPU register stack.
;D9 F7 FINCSTP Increment the TOP field in the FPU status register.
;9B DB E3 FINIT Initialize FPU after checking for pending unmasked
; floating-point exceptions.
;DB E3 FNINIT Initialize FPU without checking for pending unmasked
; floating-point exceptions.
;DF /2 FIST m16int Store ST(0) in m16int.
;DB /2 FIST m32int Store ST(0) in m32int.
;DF /3 FISTP m16int Store ST(0) in m16int and pop register stack.
;DB /3 FISTP m32int Store ST(0) in m32int and pop register stack.
;DF /7 FISTP m64int Store ST(0) in m64int and pop register stack.
;DF /1 FISTTP m16int Store ST(0) in m16int with truncation.
;DB /1 FISTTP m32int Store ST(0) in m32int with truncation.
;DD /1 FISTTP m64int Store ST(0) in m64int with truncation.
;D9 /0 FLD m32fp Push m32fp onto the FPU register stack.
;DD /0 FLD m64fp Push m64fp onto the FPU register stack.
;DB /5 FLD m80fp Push m80fp onto the FPU register stack.
;D9 C0+i FLD ST(i) Push ST(i) onto the FPU register stack.
;D9 E8 FLD1 Push +1.0 onto the FPU register stack.
;D9 E9 FLDL2T Push log210 onto the FPU register stack.
;D9 EA FLDL2E Push log2e onto the FPU register stack.
;D9 EB FLDPI Push p onto the FPU register stack.
;D9 EC FLDLG2 Push log102 onto the FPU register stack.
;D9 ED FLDLN2 Push loge2 onto the FPU register stack.
;D9 EE FLDZ Push +0.0 onto the FPU register stack.
;D9 /5 FLDCW m2byte Load FPU control word from m2byte.
;D9 /4 FLDENV m14/28byte Load FPU environment from m14byte or m28byte.
;D8 /1 FMUL m32fp Multiply ST(0) by m32fp and store result in ST(0).
;DC /1 FMUL m64fp Multiply ST(0) by m64fp and store result in ST(0).
;D8 C8+i FMUL ST(0), ST(i) Multiply ST(0) by ST(i) and store result in ST(0).
;DC C8+i FMUL ST(i), ST(0) Multiply ST(i) by ST(0) and store result in ST(i).
;DE C8+i FMULP ST(i), ST(0) Multiply ST(i) by ST(0), store result in ST(i), and pop
; the register stack.
;DE C9 FMULP Multiply ST(1) by ST(0), store result in ST(1), and pop
; the register stack.
;DA /1 FIMUL m32int Multiply ST(0) by m32int and store result in ST(0).
;DE /1 FIMUL m16int Multiply ST(0) by m16int and store result in ST(0).
;D9 D0 FNOP No operation is performed.
;D9 F3 FPATAN Replace ST(1) with arctan(ST(1)/ST(0)) and pop the register
; stack.
;D9 F8 FPREM Replace ST(0) with the remainder obtained from dividing ST(0)
; by ST(1).
;D9 F5 FPREM1 Replace ST(0) with the IEEE remainder obtained from dividing
; ST(0) by ST(1).
;D9 F2 FPTAN Replace ST(0) with its tangent and push 1 onto the FPU stack.
;D9 FC FRNDINT Round ST(0) to an integer.
;DD /4 FRSTOR m94/108byte Load FPU state from m94byte or m108byte.
;9B DD /6 FSAVE m94/108byte Store FPU state to m94byte or m108byte after checking for
; pending unmasked floatingpoint exceptions. Then reinitialize
; the FPU.
;DD /6 FNSAVE m94/108byte Store FPU environment to m94byte or m108byte without checking
; for pending unmasked floating-point exceptions. Then
; re-initialize the FPU.
;D9 FD FSCALE Scale ST(0) by ST(1).
;D9 FE FSIN Replace ST(0) with its sine.
;D9 FB FSINCOS Compute the sine and cosine of ST(0); replace ST(0) with the
; sine, and push the cosine onto the register stack.
;D9 FA FSQRT Computes square root of ST(0) and stores the result in ST(0).
;D9 /2 FST m32fp Copy ST(0) to m32fp.
;DD /2 FST m64fp Copy ST(0) to m64fp.
;DD D0+i FST ST(i) Copy ST(0) to ST(i).
;D9 /3 FSTP m32fp Copy ST(0) to m32fp and pop register stack.
;DD /3 FSTP m64fp Copy ST(0) to m64fp and pop register stack.
;DB /7 FSTP m80fp Copy ST(0) to m80fp and pop register stack.
;DD D8+i FSTP ST(i) Copy ST(0) to ST(i) and pop register stack.
;9B D9 /7 FSTCW m2byte Store FPU control word to m2byte after checking for pending
; unmasked floating-point exceptions.
;D9 /7 FNSTCW m2byte Store FPU control word to m2byte without checking for pending
; unmasked floating-point exceptions.
;9B D9 /6 FSTENV m14/28byte Store FPU environment to m14byte or m28byte after checking for
; pending unmasked floating-point exceptions. Then mask all
; floating-point exceptions.
;D9 /6 FNSTENV m14/28byte Store FPU environment to m14byte or m28byte without checking
; for pending unmasked floating-point exceptions. Then mask all
; floating-point exceptions.
;9B DD /7 FSTSW m2byte Store FPU status word at m2byte after checking for pending
; unmasked floatingpoint exceptions.
;9B DF E0 FSTSW AX Store FPU status word in AX register after checking for pending
; unmasked floatingpoint exceptions.
;DD /7 FNSTSW m2byte Store FPU status word at m2byte without checking for pending
; unmasked floatingpoint exceptions.
;DF E0 FNSTSW AX Store FPU status word in AX register without checking for
; pending unmasked floatingpoint exceptions.
;D8 /4 FSUB m32fp Subtract m32fp from ST(0) and store result in ST(0).
;DC /4 FSUB m64fp Subtract m64fp from ST(0) and store result in ST(0).
;D8 E0+i FSUB ST(0), ST(i) Subtract ST(i) from ST(0) and store result in ST(0).
;DC E8+i FSUB ST(i), ST(0) Subtract ST(0) from ST(i) and store result in ST(i).
;DE E8+i FSUBP ST(i), ST(0) Subtract ST(0) from ST(i), store result in ST(i), and pop
; register stack.
;DE E9 FSUBP Subtract ST(0) from ST(1), store result in ST(1), and pop
; register stack.
;DA /4 FISUB m32int Subtract m32int from ST(0) and store result in ST(0).
;DE /4 FISUB m16int Subtract m16int from ST(0) and store result in ST(0).
;D8 /5 FSUBR m32fp Subtract ST(0) from m32fp and store result in ST(0).
;DC /5 FSUBR m64fp Subtract ST(0) from m64fp and store result in ST(0).
;D8 E8+i FSUBR ST(0), ST(i) Subtract ST(0) from ST(i) and store result in ST(0).
;DC E0+i FSUBR ST(i), ST(0) Subtract ST(i) from ST(0) and store result in ST(i).
;DE E0+i FSUBRP ST(i), ST(0) Subtract ST(i) from ST(0), store result in ST(i), and pop
; register stack.
;DE E1 FSUBRP Subtract ST(1) from ST(0), store result in ST(1), and pop
; register stack.
;DA /5 FISUBR m32int Subtract ST(0) from m32int and store result in ST(0).
;DE /5 FISUBR m16int Subtract ST(0) from m16int and store result in ST(0).
;D9 E4 FTST Compare ST(0) with 0.0.
;DD E0+i FUCOM ST(i) Compare ST(0) with ST(i).
;DD E1 FUCOM Compare ST(0) with ST(1).
;DD E8+i FUCOMP ST(i) Compare ST(0) with ST(i) and pop register stack.
;DD E9 FUCOMP Compare ST(0) with ST(1) and pop register stack.
;DA E9 FUCOMPP Compare ST(0) with ST(1) and pop register stack twice.
;D9 E5 FXAM Classify value or number in ST(0).
;D9 C8+i FXCH ST(i) Exchange the contents of ST(0) and ST(i).
;D9 C9 FXCH Exchange the contents of ST(0) and ST(1).
;0F AE /1 FXRSTOR m512byte Restore the x87 FPU, MMX, XMM and MXCSR register state from
; m512byte.
;0F AE /0 FXSAVE m512byte Save the x87 FPU, MMX, XMM and MXCSR register state to m512byte.
;D9 F4 FXTRACT Separate value in ST(0) into exponent and significand, store
; exponent in ST(0) and push the significand onto the register
; stack.
;D9 F1 FYL2X Replace ST(1) with (ST(1) * log2ST(0)) and pop the register
; stack.
;D9 F9 FYL2XP1 Replace ST(1) with ST(1) * log2(ST(0) + 1.0) and pop the
; register stack.
;---------------------------------------------------------------------------------------------------
;OPCODES High-Byte aufsteigend:
;0F AE /1 FXRSTOR m512byte Restore the x87 FPU, MMX, XMM and MXCSR register state from
; m512byte.
;0F AE /0 FXSAVE m512byte Save the x87 FPU, MMX, XMM and MXCSR register state to m512byte.
;-------------
;9B D9 /6 FSTENV m14/28byte Store FPU environment to m14byte or m28byte after checking for
; pending unmasked floating-point exceptions. Then mask all
; floating-point exceptions.
;9B D9 /7 FSTCW m2byte Store FPU control word to m2byte after checking for pending
; unmasked floating-point exceptions.
;9B DB E2 FCLEX Clear floating-point exception flags after checking for pending
; unmasked floating-point exceptions.
;9B DB E3 FINIT Initialize FPU after checking for pending unmasked
; floating-point exceptions.
;9B DD /6 FSAVE m94/108byte Store FPU state to m94byte or m108byte after checking for
; pending unmasked floatingpoint exceptions. Then reinitialize
; the FPU.
;9B DD /7 FSTSW m2byte Store FPU status word at m2byte after checking for pending
; unmasked floatingpoint exceptions.
;9B DF E0 FSTSW AX Store FPU status word in AX register after checking for pending
; unmasked floatingpoint exceptions.
;-------------
;D8 /0 FADD m32fp Add m32fp To ST(0) and store result in ST(0).
;D8 /1 FMUL m32fp Multiply ST(0) by m32fp and store result in ST(0).
;D8 /2 FCOM m32fp Compare ST(0) with m32fp.
;D8 /3 FCOMP m32fp Compare ST(0) with m32fp and pop register stack.
;D8 /4 FSUB m32fp Subtract m32fp from ST(0) and store result in ST(0).
;D8 /5 FSUBR m32fp Subtract ST(0) from m32fp and store result in ST(0).
;D8 /6 FDIV m32fp Divide ST(0) by m32fp and store result in ST(0).
;D8 /7 FDIVR m32fp Divide m32fp by ST(0) and store result in ST(0).
;D8 C0+i FADD ST(0), ST(i) Add ST(0) To ST(i) and store result in ST(0).
;D8 C8+i FMUL ST(0), ST(i) Multiply ST(0) by ST(i) and store result in ST(0).
;D8 D0+i FCOM ST(i) Compare ST(0) with ST(i).
;D8 D1 FCOM Compare ST(0) With ST(1).
;D8 D8+i FCOMP ST(i) Compare ST(0) with ST(i) and pop register stack.
;D8 D9 FCOMP Compare ST(0) with ST(1) and pop register stack.
;D8 E0+i FSUB ST(0), ST(i) Subtract ST(i) from ST(0) and store result in ST(0).
;D8 E8+i FSUBR ST(0), ST(i) Subtract ST(0) from ST(i) and store result in ST(0).
;D8 F0+i FDIV ST(0), ST(i) Divide ST(0) by ST(i) and store result in ST(0).
;D8 F8+i FDIVR ST(0), ST(i) Divide ST(i) by ST(0) and store result in ST(0).
;-------------
;D9 /0 FLD m32fp Push m32fp onto the FPU register stack.
;D9 /2 FST m32fp Copy ST(0) to m32fp.
;D9 /3 FSTP m32fp Copy ST(0) to m32fp and pop register stack.
;D9 /4 FLDENV m14/28byte Load FPU environment from m14byte or m28byte.
;D9 /5 FLDCW m2byte Load FPU control word from m2byte.
;D9 /6 FNSTENV m14/28byte Store FPU environment to m14byte or m28byte without checking
; for pending unmasked floating-point exceptions. Then mask all
; floating-point exceptions.
;D9 /7 FNSTCW m2byte Store FPU control word to m2byte without checking for pending
; unmasked floating-point exceptions.
;D9 C0+i FLD ST(i) Push ST(i) onto the FPU register stack.
;D9 C8+i FXCH ST(i) Exchange the contents of ST(0) and ST(i).
;D9 C9 FXCH Exchange the contents of ST(0) and ST(1).
;D9 D0 FNOP No operation is performed.
;D9 E0 FCHS Complements sign of ST(0).
;D9 E1 FABS Replace ST with its absolute value.
;D9 E4 FTST Compare ST(0) with 0.0.
;D9 E5 FXAM Classify value or number in ST(0).
;D9 E8 FLD1 Push +1.0 onto the FPU register stack.
;D9 E9 FLDL2T Push log210 onto the FPU register stack.
;D9 EA FLDL2E Push log2e onto the FPU register stack.
;D9 EB FLDPI Push p onto the FPU register stack.
;D9 EC FLDLG2 Push log102 onto the FPU register stack.
;D9 ED FLDLN2 Push loge2 onto the FPU register stack.
;D9 EE FLDZ Push +0.0 onto the FPU register stack.
;D9 F0 F2XM1 Replace ST(0) with (2^ST(0))-1.
;D9 F1 FYL2X Replace ST(1) with (ST(1) * log2ST(0)) and pop the register
; stack.
;D9 F2 FPTAN Replace ST(0) with its tangent and push 1 onto the FPU stack.
;D9 F3 FPATAN Replace ST(1) with arctan(ST(1)/ST(0)) and pop the register
; stack.
;D9 F4 FXTRACT Separate value in ST(0) into exponent and significand, store
; exponent in ST(0) and push the significand onto the register
; stack.
;D9 F5 FPREM1 Replace ST(0) with the IEEE remainder obtained from dividing
; ST(0) by ST(1).
;D9 F6 FDECSTP Decrement TOP field in FPU status word.
;D9 F7 FINCSTP Increment the TOP field in the FPU status register.
;D9 F8 FPREM Replace ST(0) with the remainder obtained from dividing ST(0)
; by ST(1).
;D9 F9 FYL2XP1 Replace ST(1) with ST(1) * log2(ST(0) + 1.0) and pop the
; register stack.
;D9 FA FSQRT Computes square root of ST(0) and stores the result in ST(0).
;D9 FB FSINCOS Compute the sine and cosine of ST(0); replace ST(0) with the
; sine, and push the cosine onto the register stack.
;D9 FC FRNDINT Round ST(0) to an integer.
;D9 FD FSCALE Scale ST(0) by ST(1).
;D9 FE FSIN Replace ST(0) with its sine.
;D9 FF FCOS Replace ST(0) with its cosine.
;-------------
;DA /0 FIADD m32int Add m32int To ST(0) and store result in ST(0).
;DA /1 FIMUL m32int Multiply ST(0) by m32int and store result in ST(0).
;DA /2 FICOM m32int Compare ST(0) with m32int.
;DA /3 FICOMP m32int Compare ST(0) with m32int and pop stack register.
;DA /4 FISUB m32int Subtract m32int from ST(0) and store result in ST(0).
;DA /5 FISUBR m32int Subtract ST(0) from m32int and store result in ST(0).
;DA /6 FIDIV m32int Divide ST(0) by m32int and store result in ST(0).
;DA /7 FIDIVR m32int Divide m32int by ST(0) and store result in ST(0).
;DA C0+i FCMOVB ST(0), ST(i) Move if below (CF=1).
;DA C8+i FCMOVE ST(0), ST(i) Move if equal (ZF=1).
;DA D0+i FCMOVBE ST(0), ST(i) Move if below or equal (CF=1 or ZF=1).
;DA D8+i FCMOVU ST(0), ST(i) Move if unordered (PF=1).
;DA E9 FUCOMPP Compare ST(0) with ST(1) and pop register stack twice.
;-------------
;DB /0 FILD m32int Push m32int onto the FPU register stack.
;DB /1 FISTTP m32int Store ST(0) in m32int with truncation.
;DB /2 FIST m32int Store ST(0) in m32int.
;DB /3 FISTP m32int Store ST(0) in m32int and pop register stack.
;DB /5 FLD m80fp Push m80fp onto the FPU register stack.
;DB /7 FSTP m80fp Copy ST(0) to m80fp and pop register stack.
;DB C0+i FCMOVNB ST(0), ST(i) Move if not below (CF=0).
;DB C8+i FCMOVNE ST(0), ST(i) Move if not equal (ZF=0).
;DB D0+i FCMOVNBE ST(0), ST(i) Move if not below or equal (CF=0 and ZF=0).
;DB D8+i FCMOVNU ST(0), ST(i) Move if not unordered (PF=0).
;DB E2 FNCLEX Clear floating-point exception flags without checking for
; pending unmasked floating-point exceptions.
;DB E3 FNINIT Initialize FPU without checking for pending unmasked
; floating-point exceptions.
;DB E8+i FUCOMI ST, ST(i) Compare ST(0) with ST(i), check for ordered values, and set
; status flags accordingly.
;DB F0+i FCOMI ST, ST(i) Compare ST(0) with ST(i) and set status flags accordingly.
;-------------
;DC /0 FADD m64fp Add m64fp To ST(0) and store result in ST(0).
;DC /1 FMUL m64fp Multiply ST(0) by m64fp and store result in ST(0).
;DC /2 FCOM m64fp Compare ST(0) with m64fp.
;DC /3 FCOMP m64fp Compare ST(0) with m64fp and pop register stack.
;DC /4 FSUB m64fp Subtract m64fp from ST(0) and store result in ST(0).
;DC /5 FSUBR m64fp Subtract ST(0) from m64fp and store result in ST(0).
;DC /6 FDIV m64fp Divide ST(0) by m64fp and store result in ST(0).
;DC /7 FDIVR m64fp Divide m64fp by ST(0) and store result in ST(0).
;DC C0+i FADD ST(i), ST(0) Add ST(i) To ST(0) and store result in ST(i).
;DC C8+i FMUL ST(i), ST(0) Multiply ST(i) by ST(0) and store result in ST(i).
;DC E0+i FSUBR ST(i), ST(0) Subtract ST(i) from ST(0) and store result in ST(i).
;DC E8+i FSUB ST(i), ST(0) Subtract ST(0) from ST(i) and store result in ST(i).
;DC F0+i FDIVR ST(i), ST(0) Divide ST(0) by ST(i) and store result in ST(i).
;DC F8+i FDIV ST(i), ST(0) Divide ST(i) by ST(0) and store result in ST(i).
;-------------
;DD /0 FLD m64fp Push m64fp onto the FPU register stack.
;DD /1 FISTTP m64int Store ST(0) in m64int with truncation.
;DD /2 FST m64fp Copy ST(0) to m64fp.
;DD /3 FSTP m64fp Copy ST(0) to m64fp and pop register stack.
;DD /4 FRSTOR m94/108byte Load FPU state from m94byte or m108byte.
;DD /6 FNSAVE m94/108byte Store FPU environment to m94byte or m108byte without checking
; for pending unmasked floating-point exceptions. Then
; re-initialize the FPU.
;DD /7 FNSTSW m2byte Store FPU status word at m2byte without checking for pending
; unmasked floatingpoint exceptions.
;DD C0+i FFREE ST(i) Sets tag for ST(i) to empty.
;DD D0+i FST ST(i) Copy ST(0) to ST(i).
;DD D8+i FSTP ST(i) Copy ST(0) to ST(i) and pop register stack.
;DD E0+i FUCOM ST(i) Compare ST(0) with ST(i).
;DD E1 FUCOM Compare ST(0) with ST(1).
;DD E8+i FUCOMP ST(i) Compare ST(0) with ST(i) and pop register stack.
;DD E9 FUCOMP Compare ST(0) with ST(1) and pop register stack.
;-------------
;DE /0 FIADD m16int Add m16int To ST(0) and store result in ST(0).
;DE /1 FIMUL m16int Multiply ST(0) by m16int and store result in ST(0).
;DE /2 FICOM m16int Compare ST(0) with m16int.
;DE /3 FICOMP m16int Compare ST(0) with m16int and pop stack register.
;DE /4 FISUB m16int Subtract m16int from ST(0) and store result in ST(0).
;DE /5 FISUBR m16int Subtract ST(0) from m16int and store result in ST(0).
;DE /6 FIDIV m16int Divide ST(0) by m64int and store result in ST(0).
;DE /7 FIDIVR m16int Divide m16int by ST(0) and store result in ST(0).
;DE C0+i FADDP ST(i), ST(0) Add ST(0) To ST(i), store result in ST(i), and pop the register stack.
;DE C1 FADDP Add ST(0) To ST(1), store result in ST(1), and pop the register stack.
;DE C8+i FMULP ST(i), ST(0) Multiply ST(i) by ST(0), store result in ST(i), and pop
; the register stack.
;DE C9 FMULP Multiply ST(1) by ST(0), store result in ST(1), and pop
; the register stack.
;DE D9 FCOMPP Compare ST(0) with ST(1) and pop register stack twice.
;DE E0+i FSUBRP ST(i), ST(0) Subtract ST(i) from ST(0), store result in ST(i), and pop
; register stack.
;DE E1 FSUBRP Subtract ST(1) from ST(0), store result in ST(1), and pop
; register stack.
;DE E8+i FSUBP ST(i), ST(0) Subtract ST(0) from ST(i), store result in ST(i), and pop
; register stack.
;DE E9 FSUBP Subtract ST(0) from ST(1), store result in ST(1), and pop
; register stack.
;DE F0+i FDIVRP ST(i), ST(0) Divide ST(0) by ST(i), store result in ST(i), and pop the
; register stack.
;DE F1 FDIVRP Divide ST(0) by ST(1), store result in ST(1), and pop the
; register stack.
;DE F8+i FDIVP ST(i), ST(0) Divide ST(i) by ST(0), store result in ST(i), and pop the
; register stack.
;DE F9 FDIVP Divide ST(1) by ST(0), store result in ST(1), and pop the
; register stack.
;-------------
;DF /0 FILD m16int Push m16int onto the FPU register stack.
;DF /1 FISTTP m16int Store ST(0) in m16int with truncation.
;DF /2 FIST m16int Store ST(0) in m16int.
;DF /3 FISTP m16int Store ST(0) in m16int and pop register stack.
;DF /4 FBLD m80 dec Convert BCD value to floating-point and push onto the FPU stack.
;DF /5 FILD m64int Push m64int onto the FPU register stack.
;DF /6 FBSTP m80bcd Store ST(0) in m80bcd and pop ST(0).
;DF /7 FISTP m64int Store ST(0) in m64int and pop register stack.
;DF E0 FNSTSW AX Store FPU status word in AX register without checking for
; pending unmasked floatingpoint exceptions.
;DF E8+i FUCOMIP ST, ST(i) Compare ST(0) with ST(i), check for ordered values, set status
; flags accordingly, and pop register stack.
;DF F0+i FCOMIP ST, ST(i) Compare ST(0) with ST(i), set status flags accordingly, and
; pop register stack.
;-------------
Procedure FPU()
Global FST0.d
Global FST1.d
Global FST2.d
Global FST3.d
Global FST4.d
Global FST5.d
Global FST6.d
Global FST7.d
Global SaveRam.l
Global FPUSW.w
Global FPUCW.w
Global OpcodeH.c
Global OpcodeL.c
Global C1.b
Global PhysReg.b
Global Tag.b
Global Zeiger.b
Global Alarm$="Schwerwiegender Fehler ! Weitermachen ist Muster ohne Wert !"
Global Reg$
Global B1$
Global B$
Global C01$
Global C0$
Global C11$
Global C1$
Global C21$
Global C2$
Global C31$
Global C3$
Global CX$="Das Condition-Code-Flag "
Global Tag0$
Global Tag1$
Global Tag2$
Global Tag3$
Global Tag4$
Global Tag5$
Global Tag6$
Global Tag7$
Global I$
Global D$
Global Z$
Global O$
Global U$
Global P$
Global P1$
Global S$
Global S1$
Global Prec$
Global Round$
Global Inf$
Global TOS$
Global OP$
Global OF$="Overflow !"
Global UF$="Underflow !"
Global OP1$="Letzter FPU-Befehl : " ;nicht möglich für FSTENV, FNSTENV, FLDENV, FINIT, FNINIT,
Global OPH$ ; FSAVE, FNSAVE, FXSAVE, FRSTOR, FXRSTOR, FCLEX, FNCLEX,
Global OPL$ ; FLDCW, FSTCW, FNSTCW, FSTSW, FNSTSW
Global D8$= "FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR "
Global D9$= "FLD FXCH FST FSTP "
Global D91$="FCHS FABS FTST FXAM FLD1 FLDL2T FLDL2E FLDPI FLDLG2 FLDLN2 FLDZ "
Global D92$="F2XM1 FYL2X FPTAN FPATAN FXTRACT FPREM1 FDECSTP FINCSTP FPREM FYL2XP1 FSQRT FSINCOS FRNDINT FSCALE FSIN FCOS "
Global DA$= "FIADD FIMUL FICOM FICOMP FISUB FISUBR FIDIV FIDIVR "
Global DA1$="FCMOVB FCMOVE FCMOVBE FCMOVU FUCOMPP "
Global DB$= "FILD FISTTP FIST FISTP FLD FSTP "
Global DB1$="FCMOVNB FCMOVNE FCMOVNBEFCMOVNU FUCOMI FCOMI "
Global DC$= "FADD FMUL FSUBR FSUB FDIVR FDIV "
Global DD$= "FLD FISTTP FST FSTP "
Global DD1$="FFREE FST FSTP FUCOM FUCOMP "
Global DE$= "FIADD FIMUL FICOM FICOMP FISUB FISUBR FIDIV FIDIVR "
Global DE1$="FADDP FMULP FCOMPP FSUBRP FSUBP FDIVRP FDIVP "
Global DF$= "FILD FISTTP FIST FISTP FBLD FILD FBSTP FISTP "
Global DF1$=" FUCOMIP FCOMIP "
Global DX$
Global DX1$
!pushad ;Prozessor-Register sichern
!pushfd ;EFlag-Register sichern; FCOMI(P)!
!fnstcw [v_FPUCW] ;Control-Word laden
!fnstsw [v_FPUSW] ;Status-Word laden
SaveRam = AllocateMemory(540) ;512 Byte für FXSAVE und 28 Byte für FNSTENV
!mov esi,[v_SaveRam]
!fnstenv [esi+512] ;nur wegen Opcode (AMD!)
!fxsave [esi]
!fwait
Tag0$=" Frei"
Tag1$=" Frei"
Tag2$=" Frei"
Tag3$=" Frei"
Tag4$=" Frei"
Tag5$=" Frei"
Tag6$=" Frei"
Tag7$=" Frei"
!mov al,[esi+4] ;Tag
!mov [v_Tag],al
!test [v_Tag],1
!jz @f
Tag7$=" Belegt"
!@@:
!test [v_Tag],2
!jz @f
Tag6$=" Belegt"
!@@:
!test [v_Tag],4
!jz @f
Tag5$=" Belegt"
!@@:
!test [v_Tag],8
!jz @f
Tag4$=" Belegt"
!@@:
!test [v_Tag],10h
!jz @f
Tag3$=" Belegt"
!@@:
!test [v_Tag],20h
!jz @f
Tag2$=" Belegt"
!@@:
!test [v_Tag],40h
!jz @f
Tag1$=" Belegt"
!@@:
!test [v_Tag],80h
!jz @f
Tag0$=" Belegt"
!@@:
!mov ax,[esi+530]
!or ah,0d8h
!mov [v_OpcodeH],ah
!mov [v_OpcodeL],al
!fld tword[esi+32]
!fstp qword[v_FST0]
!fld tword[esi+48]
!fstp qword[v_FST1]
!fld tword[esi+64]
!fstp qword[v_FST2]
!fld tword[esi+80]
!fstp qword[v_FST3]
!fld tword[esi+96]
!fstp qword[v_FST4]
!fld tword[esi+112]
!fstp qword[v_FST5]
!fld tword[esi+128]
!fstp qword[v_FST6]
!fld tword[esi+144]
!fstp qword[v_FST7]
!cmp ah,0d8h
!je l_d8
!cmp ah,0d9h
!je l_d9
!cmp ah,0dah
!je l_da
!cmp ah,0dbh
!je l_db
!cmp ah,0dch
!je l_dc
!cmp ah,0ddh
!je l_dd
!cmp ah,0deh
!je l_de
;----------------------------
!push eax
DX$=DF$
DX1$=DF1$
!pop eax
!jmp l_dx
;----------------------------
D8:
!and al,00111000b
!mov [v_Zeiger],al
OP$=Mid(D8$,Zeiger,8)+#LFCR$
!jmp l_ope
;----------------------------
D9:
!cmp al,0d0h
!jae @f
!and al,00111000b
!mov [v_Zeiger],al
OP$=Mid(D9$,Zeiger,8)+#LFCR$
!jmp l_ope
!@@:
!ja @f
OP$="FNOP"+#LFCR$
!jmp l_ope
!@@:
!cmp al,0f0h
!jae @f
!and al,00001111b
!shl al,3
!mov [v_Zeiger],al
OP$=Mid(D91$,Zeiger,8)+#LFCR$
!jmp l_ope
!@@:
!and al,00001111b
!shl al,3
!mov [v_Zeiger],al
OP$=Mid(D92$,Zeiger,8)+#LFCR$
!jmp l_ope
;----------------------------
DA:
!push eax
DX$=DA$
DX1$=DA1$
!pop eax
!jmp l_dx
;----------------------------
DB:
!cmp al,0c0h
!jae @f
!and al,00111000b
!mov [v_Zeiger],al
OP$=Mid(DB$,Zeiger,8)+#LFCR$
!jmp l_ope
!@@:
!and al,00111000b
!mov [v_Zeiger],al
OP$=Mid(DB1$,Zeiger,8)+#LFCR$
!jmp l_ope
;----------------------------
DC:
!cmp al,0c0h
!jb l_d8
!and al,00111000b
!mov [v_Zeiger],al
OP$=Mid(DC$,Zeiger,8)+#LFCR$
!jmp l_ope
;----------------------------
DD:
!push eax
DX$=DD$
DX1$=DD1$
!pop eax
!jmp l_dx
;----------------------------
DE:
!push eax
DX$=DE$
DX1$=DE1$
!pop eax
;----------------------------
DX:
!cmp al,0c0h
!jae @f
!and al,00111000b
!mov [v_Zeiger],al
OP$=Mid(DX$,Zeiger,8)+#LFCR$
!jmp l_ope
!@@:
!and al,00111000b
!mov [v_Zeiger],al
OP$=Mid(DX1$,Zeiger,8)+#LFCR$
;----------------------------
OPE:
OPH$="Letzter FPU-Befehl High-Byte : "+RSet(Bin(OpcodeH),8,"0")+" = "+RSet(Hex(OpcodeH),2,"0")+"h"+#LFCR$
OPL$="Letzter FPU-Befehl Low-Byte : "+RSet(Bin(OpcodeL),8,"0")+" = "+RSet(Hex(OpcodeL),2,"0")+"h"+#LFCR$+#LFCR$
Reg$="ST0 = "+StrD(FST0)+Tag0$+#LFCR$
Reg$+"ST1 = "+StrD(FST1)+Tag1$+#LFCR$
Reg$+"ST2 = "+StrD(FST2)+Tag2$+#LFCR$
Reg$+"ST3 = "+StrD(FST3)+Tag3$+#LFCR$
Reg$+"ST4 = "+StrD(FST4)+Tag4$+#LFCR$
Reg$+"ST5 = "+StrD(FST5)+Tag5$+#LFCR$
Reg$+"ST6 = "+StrD(FST6)+Tag6$+#LFCR$
Reg$+"ST7 = "+StrD(FST7)+Tag7$
!mov [v_C1],0
!test [v_FPUSW],200h
!jz @f
!mov [v_C1],1 ;z.B. für Stack-Fault
!@@:
I$=""
!test [v_FPUSW],1
!jz @f
I$="Invalid Operation !"+#LFCR$+Alarm$+#LFCR$
!@@:
D$=""
!test [v_FPUSW],2
!jz @f
D$="Denormalized Operand !"+#LFCR$+Alarm$+#LFCR$
!@@:
Z$=""
!test [v_FPUSW],4
!jz @f
Z$="Division by Zero !"+#LFCR$+Alarm$+#LFCR$
!@@:
O$=""
!test [v_FPUSW],8
!jz @f
O$=OF$+#LFCR$
!@@:
U$=""
!test [v_FPUSW],10h
!jz @f
U$=UF$+#LFCR$
!@@:
P$=""
P1$=""
!test [v_FPUSW],20h
!jz @f
P1$="kleineren Wert !"+#LFCR$
P$="Low Precision ! Rundung erfolgte zum "
!cmp [v_C1],0
!jz @f
P1$="grösseren Wert !"+#LFCR$
!@@:
P$+P1$
S$=""
S1$=""
!test [v_FPUSW],40h
!jz @f
S1$=UF$+#LFCR$+Alarm$+#LFCR$
S$="Stack Fault : "
!cmp [v_C1],0
!je @f
S1$=OF$+#LFCR$+Alarm$+#LFCR$
!@@:
S$+S1$
B1$="nicht"
!mov ax,[v_FPUSW]
!sahf
!jns @f
B1$=""
!@@:
B$="Das Busy-Flag ist "+B1$+" gesetzt !"+#LFCR$
C11$="nicht"
!cmp byte[v_C1],0
!je @f
C11$=""
!@@:
C1$=CX$+"C1 ist "+C11$+" gesetzt !"+#LFCR$
C01$="nicht"
C21$="nicht"
C31$="nicht"
!mov ax,[v_FPUSW]
!sahf
!jnc @f
!pushfd
C01$=""
!popfd
!@@:
!jnp @f
!pushfd
C21$=""
!popfd
!@@:
!jnz @f
!pushfd
C31$=""
!popfd
!@@:
C0$=CX$+"C0 ist "+C01$+" gesetzt !"+#LFCR$
C2$=CX$+"C2 ist "+C21$+" gesetzt !"+#LFCR$
C3$=CX$+"C3 ist "+C31$+" gesetzt !"+#LFCR$+#LFCR$
!mov ax,[v_FPUSW]
!and ah,38h
!shr ah,3 ;in Bit 0-2 schieben
!mov [v_PhysReg],ah
TOS$="Das physische Register " + Str(PhysReg) + " ist Top of Stack !"+#LFCR$
Prec$=#LFCR$+"Die eingestellte Genauigkeit ist "
!mov ax,[v_FPUCW]
!and ah,3
!jz l_single
!cmp ah,2
!je l_double
Prec$+"Double Extended Precision 64 Bits"
!jmp l_precend
Single:
Prec$+"Single Precision 24 Bits"
!jmp l_precend
Double:
Prec$+"Double Precision 53 Bits"
PrecEnd:
Prec$+#LFCR$
Round$="Rundung erfolgt "
!mov ax,[v_FPUCW]
!and ah,0ch
!cmp ah,4
!je l_round1
!cmp ah,8
!je l_round2
!cmp ah,0ch
!je l_round3
Round$+"zum nächsten oder geraden Wert"
!jmp l_roundend
Round1:
Round$+"in Richtung minus Unendlich"
!jmp l_roundend
Round2:
Round$+"in Richtung plus Unendlich"
!jmp l_roundend
Round3:
Round$+"keine, Nachkommastellen werden abgeschnitten"
RoundEnd:
Round$+#LFCR$
Inf$="Infinity ist "
!mov ax,[v_FPUCW]
!test ah,10h
!jnz @f
Inf$+"projektiv"
!jmp l_infend
!@@:
Inf$+"affinitiv"
InfEnd:
Inf$+#LFCR$+#LFCR$
MessageRequester("FPU-Innenleben",I$+D$+Z$+O$+U$+P$+S$+Prec$+Round$+Inf$+OP1$+OP$+OPH$+OPL$+B$+C0$+C1$+C2$+C3$+TOS$+#LFCR$+Reg$)
!mov esi,[v_SaveRam]
!fxrstor [esi]
FreeMemory(SaveRam)
!popfd
!popad
EndProcedure
;- Beispiel: Berechnung Kugelvolumen: V=4/3*Pi*Radius^3
Global R.d=123.456
Global Z.d=4
Global N.d=3
Global V.d
;!fninit
FPU()
!fldpi ;ST0 Pi
FPU()
!fmul qword[v_Z] ;ST0 Pi*4
FPU()
!fdiv qword[v_N] ;ST0 Pi*4/3
FPU()
!fld qword[v_R] ;ST0 ST1=Pi*4/3
FPU()
!fmul st0,st0 ;ST0=R*R
FPU()
!fmul qword[v_R] ;ST0=R*R*R
FPU()
!fmulp ;ST0=ST0*ST1
FPU()
!fstp qword[v_V] ;ST0 in V kopieren
FPU()
MessageRequester("Kugelvolumen-Berechnung mit FPU()",StrD(V))
;Aus Jux mal sehen, wie PB die FPU verlässt:
V=4/3*#PI*R*R*R
FPU()
V=4/3*#PI*Pow(R,3)
FPU()
End
Helle
Edit: Korrektur+Erweiterung 11.08.2007
Edit: Kosmetik+Erweiterung 12.08.2007