REXX Language implementation
Floating-point instructions operate on the binary64 payload of a VM register. RXAS registers are not statically typed: a register operand means that the instruction reads or writes the float, integer, or string payload named below. Writing one payload does not copy the source register’s other payloads or status flags.
Float literals must use a decimal point or exponent, such as 2.0 or 2e0.
The arithmetic instructions use the host C binary64 operations and libm.
Consequently, infinity, NaN, signed zero, and rounding follow the platform’s
binary64 behavior. These instructions do not translate floating-point status or
errno into RXAS signals: division by zero, invalid fmod/pow domains, and
overflowing finite results produce the corresponding binary64 result.
faddAdd two binary64 values. This is the normal float addition primitive.
| Opcode | Form | Effect |
|---|---|---|
0x012c |
fadd rDst,rLeft,rRight |
Set the float payload of rDst to rLeft + rRight. |
0x012d |
fadd rDst,rLeft,float |
Add a float literal or float constant to rLeft. |
Register sources are read through their float payloads. Only the destination’s float payload is replaced; sources are unchanged. Destination aliasing with either source is allowed because the operands are read before the result is stored.
No signal is raised for binary64 overflow, underflow, NaN, or infinity.
.globals=0
main() .locals=3
load r1,1.25
fadd r0,r1,2.5
ret
fsub, fmult, fdiv.
fcopyCopy one register’s binary64 payload without copying its other value payloads or status flags.
| Opcode | Form | Effect |
|---|---|---|
0x000a |
fcopy rDst,rSrc |
Copy the float payload of rSrc to rDst. |
Both operands are registers. The source is unchanged. The destination’s string, integer, decimal, attributes, status flags, and are not copied.
This instruction does not raise a signal.
.globals=0
main() .locals=2
load r1,3.5
fcopy r0,r1
ret
copy, icopy, dcopy, scopy.
fdivDivide one binary64 value by another.
| Opcode | Form | Effect |
|---|---|---|
0x0133 |
fdiv rDst,rDividend,rDivisor |
Divide two register float payloads. |
0x0134 |
fdiv rDst,rDividend,float |
Divide a register float payload by a float literal. |
0x0135 |
fdiv rDst,float,rDivisor |
Divide a float literal by a register float payload. |
rDst receives a float payload. Sources are unchanged, and source
registers may alias the destination.
There is no RXAS divide-by-zero signal for fdiv. Binary64 division determines
the infinity or NaN result; overflow and underflow likewise do not raise a VM
signal.
.globals=0
main() .locals=2
load r1,7.5
fdiv r0,r1,2.5
ret
fidiv, fmod, ddiv, idiv.
feqCompare two binary64 values for exact IEEE equality and write an integer Boolean result.
| Opcode | Form | Effect |
|---|---|---|
0x013c |
feq rResult,rLeft,rRight |
Set rResult to 1 when the register float payloads compare equal. |
0x013d |
feq rResult,rLeft,float |
Compare a register float payload with a float literal. |
rResult receives integer 0 or 1; its float payload is not the destination.
The sources are unchanged. Positive and negative zero compare equal. A NaN is
not equal to any value, including itself.
This comparison does not raise a signal for NaN or infinity.
.globals=0
main() .locals=2
load r1,4.0
feq r0,r1,4.0
ret
fne, fgt, fgte, flt, flte.
fextrDecompose a binary64 value into a normalized decimal coefficient string and a base-10 integer exponent. It is the preferred primitive for caller-controlled float formatting.
| Opcode | Form | Effect |
|---|---|---|
0x0152 |
fextr rCoefficient,rExponent,rFloat |
Extract rFloat = coefficient * 10**exponent. |
rCoefficient receives a string such as "1.25"; rExponent receives an
integer. The coefficient uses the current numeric case setting for nan and
inf. Precision is the current numeric digits value clamped to the VM minimum
and DBL_DIG; trailing fractional zeroes are removed. Finite nonzero output is
normalized to one digit before the decimal point. Zero produces coefficient
"0" and exponent 0; infinities and NaNs produce inf, -inf, or nan
and exponent 0. The source float payload is unchanged.
This instruction does not signal for non-finite values.
.globals=0
main() .locals=3
load r2,125.0
fextr r0,r1,r2
ret
ftos, fformat, getnumdgts, getnumcas.
fformatFormat a binary64 value with a restricted printf-style format. This instruction
is deprecated; use fextr for new code.
| Opcode | Form | Effect |
|---|---|---|
0x0106 |
fformat rString,rFloat,rFormat |
Format rFloat according to the string payload of rFormat. |
The checked parser accepts one conversion from a, A, e, E, f, F,
g, or G, with optional decimal width and precision, plus literal text and
%%. Unsupported or additional conversion text is copied literally. The
destination string is replaced. The format register may be NUL-terminated
internally as part of the
operation; callers should therefore treat its private string buffer state as
mutable even though its logical text is unchanged.
Malformed or unsupported format text does not raise a signal; it is retained as literal text from the first unaccepted conversion onward.
.globals=0
main() .locals=3
load r1,12.5
load r2,"%.1f"
fformat r0,r1,r2
ret
fextr, ftos.
fgtCompare two binary64 values and return whether the left value is greater.
| Opcode | Form | Effect |
|---|---|---|
0x0140 |
fgt rResult,rLeft,rRight |
Compare two register float payloads. |
0x0141 |
fgt rResult,rLeft,float |
Compare a register float payload with a literal. |
0x0142 |
fgt rResult,float,rRight |
Compare a literal with a register float payload. |
rResult receives integer 0 or 1. Sources are unchanged. Any
ordered comparison involving NaN is false.
No signal is raised for NaN or infinity.
.globals=0
main() .locals=2
load r1,3.0
fgt r0,r1,2.0
ret
fgtbr, fgte, flt.
fgtbrBranch when one register’s binary64 value is greater than another’s.
| Opcode | Form | Effect |
|---|---|---|
0x014c |
fgtbr label,rLeft,rRight |
Branch to label when rLeft > rRight; otherwise continue. |
label is a procedure-local RXAS label. Both value operands are registers read
through their float payloads. No register is changed. A NaN makes the
condition false.
The comparison does not raise a signal.
.globals=0
main() .locals=2
load r0,2.0
load r1,1.0
fgtbr greater,r0,r1
ret
greater:
ret
fgt, fltbr, brt.
fgteCompare two binary64 values and return whether the left value is greater than or equal to the right value.
| Opcode | Form | Effect |
|---|---|---|
0x0143 |
fgte rResult,rLeft,rRight |
Compare two register float payloads. |
0x0144 |
fgte rResult,rLeft,float |
Compare a register float payload with a literal. |
0x0145 |
fgte rResult,float,rRight |
Compare a literal with a register float payload. |
rResult receives integer 0 or 1. Sources are unchanged.
Positive and negative zero compare equal; any ordered comparison involving NaN
is false.
The comparison does not raise a signal.
.globals=0
main() .locals=2
load r1,2.0
fgte r0,r1,2.0
ret
fgt, flte, feq.
fidivDivide two binary64 values and truncate the quotient toward zero, retaining the result as a float payload.
| Opcode | Form | Effect |
|---|---|---|
0x0136 |
fidiv rDst,rDividend,rDivisor |
Truncate a register/register quotient. |
0x0137 |
fidiv rDst,rDividend,float |
Truncate a register/literal quotient. |
0x0138 |
fidiv rDst,float,rDivisor |
Truncate a literal/register quotient. |
The VM computes binary64 division, applies C trunc, and writes that binary64
value to rDst. Despite the mnemonic, it does not write an integer payload.
Sources are unchanged.
Division by zero and non-finite results do not raise a VM signal.
.globals=0
main() .locals=2
load r1,7.5
fidiv r0,r1,2.0
ret
fdiv, fmod, ftoi.
fltCompare two binary64 values and return whether the left value is less.
| Opcode | Form | Effect |
|---|---|---|
0x0146 |
flt rResult,rLeft,rRight |
Compare two register float payloads. |
0x0147 |
flt rResult,rLeft,float |
Compare a register float payload with a literal. |
0x0148 |
flt rResult,float,rRight |
Compare a literal with a register float payload. |
rResult receives integer 0 or 1. Sources are unchanged. Any
ordered comparison involving NaN is false.
The comparison does not raise a signal.
.globals=0
main() .locals=2
load r1,1.0
flt r0,r1,2.0
ret
fltbr, flte, fgt.
fltbrBranch when one register’s binary64 value is less than another’s.
| Opcode | Form | Effect |
|---|---|---|
0x014d |
fltbr label,rLeft,rRight |
Branch to label when rLeft < rRight; otherwise continue. |
label is a procedure-local RXAS label. Both value operands are registers read
through their float payloads. No register is changed. A NaN makes the
condition false.
The comparison does not raise a signal.
.globals=0
main() .locals=2
load r0,1.0
load r1,2.0
fltbr smaller,r0,r1
ret
smaller:
ret
flt, fgtbr, brt.
flteCompare two binary64 values and return whether the left value is less than or equal to the right value.
| Opcode | Form | Effect |
|---|---|---|
0x0149 |
flte rResult,rLeft,rRight |
Compare two register float payloads. |
0x014a |
flte rResult,rLeft,float |
Compare a register float payload with a literal. |
0x014b |
flte rResult,float,rRight |
Compare a literal with a register float payload. |
rResult receives integer 0 or 1. Sources are unchanged.
Positive and negative zero compare equal; any ordered comparison involving NaN
is false.
The comparison does not raise a signal.
.globals=0
main() .locals=2
load r1,2.0
flte r0,r1,2.0
ret
flt, fgte, feq.
fmodCompute the C fmod remainder of two binary64 values. The result has the sign
of the dividend and is not the same as a floor-modulus operation for negative
operands.
| Opcode | Form | Effect |
|---|---|---|
0x0139 |
fmod rDst,rDividend,rDivisor |
Remainder of two register float payloads. |
0x013a |
fmod rDst,rDividend,float |
Remainder with a literal divisor. |
0x013b |
fmod rDst,float,rDivisor |
Remainder with a literal dividend. |
rDst receives a float payload. Sources are unchanged. Destination
aliasing is allowed.
A zero divisor or other invalid binary64 input produces the platform fmod
NaN result; it does not raise a VM signal.
.globals=0
main() .locals=2
load r1,7.5
fmod r0,r1,2.0
ret
fdiv, fidiv, imod, dmod.
fmultMultiply two binary64 values.
| Opcode | Form | Effect |
|---|---|---|
0x0131 |
fmult rDst,rLeft,rRight |
Multiply two register float payloads. |
0x0132 |
fmult rDst,rLeft,float |
Multiply a register float payload by a literal. |
Only rDst’s float payload is replaced. Sources are unchanged, and
the destination may alias a source.
No signal is raised for binary64 overflow, underflow, NaN, or infinity.
.globals=0
main() .locals=2
load r1,2.5
fmult r0,r1,4.0
ret
fadd, fdiv, fpow.
fndblnkFind a Unicode whitespace character in a string. The historical fnd prefix
means “find”; this instruction operates on string and integer payloads, not
float payloads.
| Opcode | Form | Effect |
|---|---|---|
0x00a5 |
fndblnk rIndex,rString,rStart |
Find the next blank at or after the requested position. |
rString supplies a string and rStart an integer character index. A
nonnegative start searches forward. A negative start requests a reverse search
from the absolute index, clamped to the last character. rIndex receives the
zero-based character index. A failed forward search returns -length; a failed
reverse search returns a negative value. In UTF builds, a non-ASCII scan may
update the source register’s VM-private UTF lookup cache while examining
characters. This is not observable RXAS state; the logical string and start
register are unchanged.
Invalid UTF-8 in rString raises UNICODE_ERROR. Out-of-range start positions
are handled by the search rules rather than raising OUT_OF_RANGE.
.globals=0
main() .locals=3
load r1,"one two"
load r2,0
fndblnk r0,r1,r2
ret
fndnblnk, strchar, substring.
fndnblnkFind a non-whitespace Unicode character in a string. Despite its placement in the historical floating-point opcode range, it operates on string and integer payloads.
| Opcode | Form | Effect |
|---|---|---|
0x00a6 |
fndnblnk rIndex,rString,rStart |
Find the next nonblank at or after the requested position. |
rString supplies a string and rStart an integer character index. A
nonnegative start searches forward. A negative start searches backward from the
absolute index, clamped to the last character. rIndex receives the zero-based
character index. A failed forward search returns -length; a failed reverse
search returns -1. In UTF builds, a non-ASCII scan may update the source
register’s VM-private UTF lookup cache while examining characters; this is not
observable RXAS state. The logical string and start register are unchanged.
Invalid UTF-8 in rString raises UNICODE_ERROR. Out-of-range start positions
are handled by the search rules rather than raising OUT_OF_RANGE.
.globals=0
main() .locals=3
load r1," word"
load r2,0
fndnblnk r0,r1,r2
ret
fndblnk, strchar, substring.
fneCompare two binary64 values for IEEE inequality and write an integer Boolean result.
| Opcode | Form | Effect |
|---|---|---|
0x013e |
fne rResult,rLeft,rRight |
Compare two register float payloads. |
0x013f |
fne rResult,rLeft,float |
Compare a register float payload with a literal. |
rResult receives integer 0 or 1; sources are unchanged. A NaN
compares unequal to every value, including itself.
The comparison does not raise a signal.
.globals=0
main() .locals=2
load r1,3.0
fne r0,r1,4.0
ret
feq, fgt, flt.
fpowRaise a binary64 base to a binary64 exponent using the platform C pow
function.
| Opcode | Form | Effect |
|---|---|---|
0x014e |
fpow rDst,rBase,rExponent |
Power with two register float payloads. |
0x014f |
fpow rDst,rBase,float |
Power with a literal exponent. |
0x0150 |
fpow rDst,float,rExponent |
Power with a literal base. |
rDst receives the pow binary64 result. Sources are unchanged,
and destination aliasing is allowed.
Domain, pole, overflow, and underflow results are not translated into VM signals; inspect the resulting NaN, infinity, zero, or finite value.
.globals=0
main() .locals=2
load r1,2.0
fpow r0,r1,3.0
ret
fmult, ipow, dpow.
fsexChange the sign of a register’s binary64 payload in place.
| Opcode | Form | Effect |
|---|---|---|
0x0151 |
fsex rValue |
Set the float payload to 0 - rValue. |
The register is both source and destination. Other payloads, status flags, and value state is unchanged. Because the implementation subtracts from positive zero, applying it to positive zero produces positive zero rather than a bit-level sign toggle; NaN sign bits are likewise not a portable contract.
This instruction does not raise a signal.
.globals=0
main() .locals=1
load r0,2.5
fsex r0
ret
fsub, isex, dsex.
fsubSubtract one binary64 value from another.
| Opcode | Form | Effect |
|---|---|---|
0x012e |
fsub rDst,rLeft,rRight |
Subtract two register float payloads. |
0x012f |
fsub rDst,rLeft,float |
Subtract a literal from a register float payload. |
0x0130 |
fsub rDst,float,rRight |
Subtract a register float payload from a literal. |
Only rDst’s float payload is replaced. Sources are unchanged, and
the destination may alias a source.
No signal is raised for binary64 overflow, underflow, NaN, or infinity.
.globals=0
main() .locals=2
load r1,5.0
fsub r0,r1,1.5
ret
fadd, fmult, fdiv.
ftobConvert a register’s binary64 payload to an integer Boolean payload in place.
| Opcode | Form | Effect |
|---|---|---|
0x00e9 |
ftob rValue |
Store integer 0 for float zero, otherwise integer 1. |
The float payload is read and the integer payload of the same register is
written. Both positive and negative zero become 0; finite nonzero values
become 1. Other payloads, status flags, and are unchanged.
No signal is raised. The implementation does not explicitly guard NaN or
infinite inputs before its internal float-to-integer step, so portable RXAS
should apply ftob only to finite values.
.globals=0
main() .locals=1
load r0,-0.25
ftob r0
ret
ftoi, btof, itob, stob.
ftoiConvert a register’s binary64 payload to an integer payload using the VM’s nearest-integer conversion and require an exact round trip.
| Opcode | Form | Effect |
|---|---|---|
0x00e8 |
ftoi rValue |
Write the converted integer payload in the same register. |
The conversion starts with floor(value) and increments when the remaining
fraction is greater than 0.5; exact half values therefore stay at the lower
integer. The integer payload is written before exactness is checked. The float
payload, other payloads, status flags, and are unchanged.
Raises CONVERSION_ERROR unless converting the result back to binary64 exactly
equals the original float. Fractional inputs therefore signal even though the
rounded integer payload has been written. The implementation has no explicit
pre-conversion bounds or non-finite check; portable code must restrict input to
finite values representable by the VM integer type.
.globals=0
main() .locals=1
load r0,42.0
ftoi r0
ret
ftob, itof, stoi, fidiv.
ftosFormat a register’s binary64 payload as a Rexx numeric string using the current numeric context.
| Opcode | Form | Effect |
|---|---|---|
0x00e6 |
ftos rValue |
Replace the register’s string payload with the formatted float value. |
The float payload remains available and the string payload of the same register is replaced. Formatting honors numeric digits, form, and case after the extractor clamps binary64 precision to its supported range. NaN and infinity are rendered using the current numeric case.
This conversion does not signal for NaN or infinity.
.globals=0
main() .locals=1
load r0,12.5
ftos r0
ret
fextr, fformat, stof, dtos.