This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revision | |||
| en:multiasm:papc:chapter_6_10 [2026/02/18 11:29] – [Basic arithmetic instructions] ktokarz | en:multiasm:papc:chapter_6_10 [2026/06/22 16:53] (current) – pczekalski | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== FPU ====== | ====== FPU ====== | ||
| - | The Floating Point Unit is developed | + | The Floating Point Unit is designed |
| < | < | ||
| - | Although modern extensions | + | Although modern extensions |
| </ | </ | ||
| - | Registers in the FPU are organised as a stack with 8 levels of depth. Physical registers are named R0 - R8, while registers visible | + | Registers in the FPU are organised as a stack with 8 levels of depth. Physical registers are named R0-R8, while registers visible |
| <figure fpuinit> | <figure fpuinit> | ||
| Line 18: | Line 18: | ||
| </ | </ | ||
| - | The stack organisation of registers makes it easier to implement | + | The stack organisation of registers makes it easier to implement |
| Further in this section, we'll present the FPU coprocessor' | Further in this section, we'll present the FPU coprocessor' | ||
| * data transfer instructions, | * data transfer instructions, | ||
| Line 29: | Line 29: | ||
| ===== Data transfer instructions ===== | ===== Data transfer instructions ===== | ||
| - | Data in the memory used by FPU can be stored as a single precision, double precision or double extended-precision floating point value or as an integer of the type word, double word, quadword, or 18-digit BCD number. The FPU always converts it into double-extended precision floating point while loading it into an internal register and converts the data to the required format while storing it back into memory. | + | Data in the memory used by the FPU can be stored as a single-precision, double-precision, or double-extended-precision floating-point value, or as an integer of the type word, double word, quadword, or 18-digit BCD number. The FPU always converts it to double-extended-precision floating-point while loading it into an internal register, and converts the data to the required format while storing it back into memory. |
| - | Loading instructions, always first decrement the stack top field in the status word register | + | |
| - | The **fld** instruction loads a single precision, double precision or double extended-precision onto the FPU register stack. It can also copy data from other FPU register | + | Loading instructions: always first decrement the stack top field in the status word register, |
| - | Store instructions take data off the FPU register stack and place it in the memory. | + | The **fld** instruction loads a single precision, double precision or double extended-precision onto the FPU register stack. It can also copy data from other FPU registers |
| - | The **fst** instruction stores a single precision or a double precision value to the memory. It can also copy a value to another FPU register. The **fstp** instruction also works with 80-bit double extended precision values and additionally pops data off the stack by incrementing the stack top field in the status word register. It can also copy a value to another FPU register, popping it off the FPU register stack. | + | The **fild** instruction loads integer values of word, doubleword or quadword.\\ |
| - | The **fist** converts the value from the top of the FPU register stack into a word or doubleword integer and stores it in memory. The **fistp** | + | The **fbld** instruction loads an 18-digit binary decimal encoded value.\\ |
| - | The **fbstp** pops value off the FPU register stack and writes it as an 80-bit BCD encoded integer | + | |
| + | Store instructions take data off the FPU register stack and place it in the memory.\\ | ||
| + | The **fst** instruction stores a single-precision or a double-precision value to the memory. It can also copy a value to another FPU register.\\ | ||
| + | The **fstp** instruction also works with 80-bit double extended precision values and additionally pops data off the stack by incrementing the stack top field in the status word register. It can also copy a value to another FPU register, popping it off the FPU register stack.\\ | ||
| + | The **fist** converts the value from the top of the FPU register stack into a word or doubleword integer and stores it in memory.\\ | ||
| + | The **fistp** can also store a 64-bit quadword integer and pop the value from the stack top.\\ | ||
| + | The **fbstp** pops a value from the FPU register stack and writes it as an 80-bit BCD-encoded integer | ||
| < | < | ||
| - | Please note that it is not possible to exchange values between the FPU stack and CPU registers | + | Please note that it is not possible to exchange values |
| </ | </ | ||
| - | The **fxch** instruction exchanges values in two FPU registers, where one of them is the top of the stack. This instruction, | + | The **fxch** instruction exchanges values in two FPU registers, where one of them is the top of the stack. This instruction, |
| - | The **fcmov// | + | The **fcmov// |
| + | The **fcmov// | ||
| There are eight such instructions summarised in the table {{ref> | There are eight such instructions summarised in the table {{ref> | ||
| <table fpufcmovcc> | <table fpufcmovcc> | ||
| Line 57: | Line 64: | ||
| </ | </ | ||
| < | < | ||
| - | Unordered means that at least one of the arguments of the comparison instruction does not represent a proper numerical value (is NaN). | + | Unordered means that at least one of the arguments of the comparison instruction does not represent a proper numerical value (is '' |
| </ | </ | ||
| ===== Load constants instructions ===== | ===== Load constants instructions ===== | ||
| - | Some constant values can be pushed onto the FPU register stack without the need to define them in memory. Such loading is faster than in instructions | + | Some constant values can be pushed onto the FPU register stack without the need to define them in memory. Such loading is faster than loading from memory |
| <table fload_constants> | <table fload_constants> | ||
| < | < | ||
| Line 75: | Line 82: | ||
| ===== Basic arithmetic instructions ===== | ===== Basic arithmetic instructions ===== | ||
| - | This group of instructions | + | This group of instructions |
| - | If the instruction has a single argument, it must be a memory argument, which specifies a single | + | If the instruction has a single argument, it must be a memory argument |
| + | |||
| + | For example, **fsub ST(0), ST(i)** subtracts ST(i) from ST(0) and stores the result in ST(0).\\ | ||
| + | The **fsub ST(i), ST(0)** subtracts ST(0) from ST(i) and stores the result in ST(i). The popped version with two arguments additionally pops the stack.\\ | ||
| + | For example, **fsubp ST(i), ST(0)** subtracts ST(0) from ST(i), stores the result in ST(i) and pops the stack. No argument version implies ST(1) as the destination and ST(0) as the source argument.\\ | ||
| + | For example, **fsubp** subtracts ST(0) from ST(1), stores the result in ST(1) and pops the stack. The result is then at the top of the stack. Basic arithmetic instructions are summarised in table {{ref> | ||
| <table ffparithmetic> | <table ffparithmetic> | ||
| < | < | ||
| Line 154: | Line 166: | ||
| </ | </ | ||
| - | The basic arithmetic instructions also contain instructions for other calculations. The **fprem** and **fprem1** calculate the partial remainder obtained from dividing the value in the ST(0) register by the value in the ST(1) register. The **fabs** calculate the absolute value of ST(0). The **fchs** changes the sign of ST(0). The **frndint** rounds the ST(0) to an integer. The **fscale** scales ST(0) by a power of two taken from ST(1), while **fxtract** separates the value in ST(0) into the exponent placed in ST(0) and the significand, | + | The basic arithmetic instructions also contain instructions for other calculations.\\ |
| + | The **fprem** and **fprem1** calculate the partial remainder obtained from dividing the value in the ST(0) register by the value in the ST(1) register.\\ | ||
| + | The **fabs** calculate the absolute value of ST(0).\\ | ||
| + | The **fchs** changes the sign of ST(0).\\ | ||
| + | The **frndint** rounds the ST(0) to an integer. | ||
| + | The **fscale** scales ST(0) by a power of two taken from ST(1),\\ | ||
| + | while **fxtract** separates the value in ST(0) into the exponent placed in ST(0) and the significand, | ||
| + | It is also possible to calculate the square root of ST(0) with the **sqrt** instruction. | ||
| ===== Comparison instructions ===== | ===== Comparison instructions ===== | ||
| - | The comparison instructions compare two floating point values and set flags appropriate to the result. The operand of the **fcom** instruction can be a memory operand or another FPU register. It is always compared with the top of the stack. If no operand is specified, it compares ST(0) and ST(1). Popped version **fcomp** pops ST(0) off the stack. The instruction **fcompp** with double " | + | The comparison instructions compare two floating-point values and set flags appropriate to the result.\\ |
| - | If one of the arguments is NaN, they generate the invalid arithmetic operand exception. To avoid unwanted exceptions, there are unordered versions of comparison instructions. These are **fucom**, **fucomp**, and **fucompp**. Unordered comparison instructions do not operate with memory arguments. Two instructions are implemented to compare integers. The **ficom** and **ficomp** have a single memory argument that can be a word or doubleword, which is compared with the top of the stack. | + | The operand of the **fcom** instruction can be a memory operand or another FPU register. It is always compared with the top of the stack. If no operand is specified, it compares ST(0) and ST(1).\\ |
| - | Original | + | Popped version **fcomp** pops ST(0) off the stack. |
| - | To the group of the comparison instructions also belong **fxam** and **ftst** instructions. The **fxam** instruction classifies the value of ST(0), while the **ftst** instruction compares ST(0) with the value of 0.0. They return the information in C0, C2 and C3 flags. | + | The instruction **fcompp** with double " |
| + | If one of the arguments is NaN, they generate the invalid arithmetic operand exception. To avoid unwanted exceptions, there are unordered versions of comparison instructions. These are **fucom**, **fucomp**, and **fucompp**. Unordered comparison instructions do not operate with memory arguments. Two instructions are implemented to compare integers.\\ | ||
| + | The **ficom** and **ficomp** have a single memory argument that can be a word or doubleword, which is compared with the top of the stack.\\ | ||
| + | |||
| + | The original | ||
| + | To the group of comparison instructions also belong **fxam** and **ftst** instructions. | ||
| + | The **fxam** instruction classifies the value of ST(0), while the **ftst** instruction compares ST(0) with the value of 0.0. They return the information in C0, C2 and C3 flags. | ||
| ===== Transcendental instructions ===== | ===== Transcendental instructions ===== | ||
| - | The transcendental instructions perform calculations of advanced mathematical functions. | + | The transcendental instructions perform calculations of advanced mathematical functions.\\ |
| - | The **fsin** instruction calculates the sine, while the **fcos** calculates the cosine of the argument stored in ST(0). The **fsincos** calculates both sine and cosine with the same instruction. The sine is returned in ST(1), the cosine in ST(0). The **fptan** instruction calculates the partial tangent and **fpatan** the partial arctangent. After calculating the tangent, the value of 1.0 is pushed onto the stack to make it easier to calculate cotangent | + | The **fsin** instruction calculates the sine, while the **fcos** calculates the cosine of the argument stored in ST(0).\\ |
| + | The **fsincos** calculates both sine and cosine with the same instruction. The sine is returned in ST(1), the cosine in ST(0).\\ | ||
| + | The **fptan** instruction calculates the partial tangent and **fpatan** the partial arctangent. After calculating the tangent, the value 1.0 is pushed onto the stack to make it easier to calculate | ||
| The instructions for exponential and logarithmic functions are summarised in table {{ref> | The instructions for exponential and logarithmic functions are summarised in table {{ref> | ||
| <table ftrans> | <table ftrans> | ||
| Line 175: | Line 202: | ||
| ===== FPU control instructions ===== | ===== FPU control instructions ===== | ||
| - | The FPU control instructions help the programmer to save and restore the contents of chosen registers if there is a need to use them in an interrupt handler or inside a function. It is also possible to initialise | + | The FPU control instructions help the programmer to save and restore the contents of chosen registers if there is a need to use them in an interrupt handler or inside a function. It is also possible to initialise the FPU unit's state or clear errors.\\ |
| - | The **fincstp** increments and **fdecstp** decrements the FPU register stack pointer. | + | The **fincstp** increments and **fdecstp** decrements the FPU register stack pointer.\\ |
| - | The following set of instructions can perform error checking while execution (instructions without " | + | The following set of instructions can perform error checking while execution (instructions without " |
| - | The **finit** and **fninit** initialise the FPU (after checking error conditions or without checking | + | The **finit** and **fninit** |
| - | The **fclex** and **fnclex** clear floating-point exception flags. | + | The **fclex** and **fnclex** clear floating-point exception flags.\\ |
| - | The **fstcw** and **fnstcw** store the FPU control word. | + | The **fstcw** and **fnstcw** store the FPU control word.\\ |
| - | The **fldcw** loads the FPU control word. | + | The **fldcw** loads the FPU control word.\\ |
| - | The **fstenv** and **fnstenr** store the FPU environment. The environment consists of the FPU control word, status | + | The **fstenv** and **fnstenr** store the FPU environment. The environment consists of the FPU control word, status word, tag word, instruction pointer, data pointer, and last opcode register.\\ |
| - | word, tag word, instruction pointer, data pointer, and last opcode register. | + | The **fldenv** loads the FPU environment.\\ |
| - | The **fldenv** loads the FPU environment. | + | The **fsave** and **fnsave** save the FPU state. The state is the operating environment and full register stack.\\ |
| - | The **fsave** and **fnsave** save the FPU state. The state is the operating environment and full register stack. | + | The **frstor** restores the FPU state.\\ |
| - | The **frstor** restores the FPU state. | + | The **fstsw** and **fnstsw** store the FPU status word. There is no instruction for restoring the status word.\\ |
| - | The **fstsw** and **fnstsw** store the FPU status word. There is no instruction for restoring the status word. | + | The **wait** or **fwait** waits for the FPU to finish the operation.\\ |
| - | The **wait** or **fwait** waits for the FPU to finish the operation. | + | The **fnop** instruction is the no-operation instruction for the FPU.\\ |
| - | The **fnop** instruction is the no operation instruction for the FPU. | + | |