REXX Language implementation
These instructions combine recurring compiler or assembler sequences into one
VM dispatch. They are ordinary public RXAS instructions, although most source
programs should let rxc or the RXAS keyhole optimiser select them.
Each fused form preserves the ordered state changes, signals, and externally observable result of its documented component sequence. Opcode numbers for withdrawn experimental forms remain reserved so an old or provisional RXBIN cannot be decoded as a different instruction.
fdivsubDivide into the divisor register, then subtract a literal into a result.
| Opcode | Form | Effect |
|---|---|---|
0x0129 |
fdivsub rResult,rNumerator,rDivisor,float |
Set rDivisor = rNumerator / rDivisor, then rResult = rDivisor - float. |
Both writes are observable and occur in that order. The quotient is retained
in rDivisor; this is not the proposed result-only replacement that would keep
the intermediate in a VM-local C value.
Like fdiv and fsub, this instruction does not signal for binary64 zero
division, overflow, underflow, infinity, or NaN.
.globals=0
main() .locals=3
load r1,8.0
load r2,2.0
fdivsub r0,r1,r2,1.5
ret
fdiv, fsub.
fmulticopyMultiply one float payload in place, then copy an independent integer payload.
| Opcode | Form | Effect |
|---|---|---|
0x012a |
fmulticopy rFloat,float,rIntResult,rIntSource |
Multiply rFloat by the literal, then integer-copy rIntSource to rIntResult. |
The float write happens before the integer copy. Only rFloat.float and
rIntResult.int change; the source integer and other payloads are unchanged.
This instruction does not signal for binary64 overflow, underflow, infinity, or NaN. The integer copy does not signal.
.globals=0
main() .locals=4
load r0,4.0
load r3,82
fmulticopy r0,2.5,r2,r3
ret
fmult, icopy.
igetunlinkRead an integer through an alias and then restore that alias register.
| Opcode | Form | Effect |
|---|---|---|
0x011d |
igetunlink rResult,rAlias |
Save rAlias.int, unlink rAlias, then write the saved integer to rResult. |
The value is saved before the binding is restored, so rResult receives the
aliased storage value. Only its integer payload changes.
This instruction does not signal.
.globals=0
main() .locals=3
setattrs r1,1
linkattr1 r2,r1,1
load r2,7
igetunlink r0,r2
ret
icopy, linkattr1, unlink.
iloadsetunlinkStore an integer literal through an alias, then restore the alias register.
| Opcode | Form | Effect |
|---|---|---|
0x011e |
iloadsetunlink rAlias,integer |
Load the integer through rAlias, then unlink it. |
The literal is written to the currently aliased storage before the local register binding is restored to its frame-owned base value.
This instruction does not signal.
.globals=0
main() .locals=2
setattrs r1,1
linkattr1 r0,r1,1
iloadsetunlink r0,21
ret
load, linkattr1, unlink.
iloadsetunlinknStore a literal through an alias and restore two local bindings.
| Opcode | Form | Effect |
|---|---|---|
0x0121 |
iloadsetunlinkn rAlias,integer,rOther |
Load through rAlias, then unlink rAlias and rOther. |
0x01a6 |
iloadsetunlinkn rLoaded,rAlias,integer,rOther |
Load rLoaded, copy its integer through rAlias, then unlink both aliases. |
The compact form has no intermediate register. The wider form deliberately
retains rLoaded because compiler TRACE metadata can observe that generated
write. Prefer the compact form only when that observation is not required.
Neither form signals.
.globals=0
main() .locals=5
setattrs r1,2
linkattr1 r2,r1,1
linkattr1 r3,r1,2
iloadsetunlinkn r2,7,r3
linkattr1 r2,r1,1
linkattr1 r3,r1,2
iloadsetunlinkn r4,r2,8,r3
ret
load, icopy, unlink, unlinkn.
isetattr1Copy an integer directly into a constant one-based attribute.
| Opcode | Form | Effect |
|---|---|---|
0x0196 |
isetattr1 rObject,index,rSource |
Set the selected attribute integer payload from rSource. |
The object must already have the selected attribute. Only that attribute’s integer payload changes; no temporary alias register is created.
Raises OUT_OF_RANGE when index is less than one or greater than the
object’s logical attribute count.
.globals=0
main() .locals=3
setattrs r1,1
load r2,35
isetattr1 r1,1,r2
ret
icopy, linkattr1, setattrs.
isetunlinkCopy an integer through an alias, then restore that alias register.
| Opcode | Form | Effect |
|---|---|---|
0x011c |
isetunlink rAlias,rSource |
Integer-copy rSource through rAlias, then unlink rAlias. |
Only the aliased target’s integer payload is copied. The alias binding is
restored after the write; rSource is unchanged.
This instruction does not signal.
.globals=0
main() .locals=4
setattrs r1,1
linkattr1 r2,r1,1
load r3,20
isetunlink r2,r3
ret
icopy, linkattr1, unlink.
isetunlinknCopy an integer through one alias, then restore two alias registers.
| Opcode | Form | Effect |
|---|---|---|
0x011f |
isetunlinkn rAlias,rSource,rOther |
Store through rAlias, then unlink rAlias and rOther. |
The integer write precedes both binding restorations. The second alias is restored without copying a value.
This instruction does not signal.
.globals=0
main() .locals=5
setattrs r1,2
linkattr1 r2,r1,1
linkattr1 r3,r1,2
load r4,22
isetunlinkn r2,r4,r3
ret
icopy, unlink, unlinkn.
linksetattrslinkaddLink an outer attribute, size it, and link a calculated nested attribute.
| Opcode | Form | Effect |
|---|---|---|
0x019c |
linksetattrslinkadd rOuter,rObject,index,count,rNested,rBase,offset |
Link the outer attribute, set its count, then link nested index rBase+offset. |
The outer one-based index is checked before rOuter is linked. That linked
value is resized to count; the checked integer sum then selects the one-based
nested attribute for rNested. Both result registers remain aliases.
Raises OUT_OF_RANGE for either invalid one-based index and
OVERFLOW_UNDERFLOW when rBase+offset is not representable. Attribute
allocation failure is fatal rather than catchable.
.globals=0
main() .locals=5
setattrs r1,1
load r2,2
linksetattrslinkadd r3,r1,1,3,r4,r2,1
unlink r4
unlink r3
ret
linkattr1, setattrs, iadd.
loadsettp2Load an integer into one register and update another register’s public flags.
| Opcode | Form | Effect |
|---|---|---|
0x010c |
loadsettp2 rLoaded,integer,rStatus,flags |
Load rLoaded, then apply settp semantics to rStatus. |
The integer load is complete before the status update. The status operand uses
the same band-aware public write as settp; VM-private flags are preserved.
This instruction does not signal.
.globals=0
main() .locals=3
loadsettp2 r1,11,r2,512
ret
load, settp.
loadsettpswapLoad an integer, set status flags, then exchange two complete bindings.
| Opcode | Form | Effect |
|---|---|---|
0x010d |
loadsettpswap rLoaded,integer,rStatus,flags,rOther |
Load, update rStatus, then swap rStatus/rOther. |
The three component effects occur in operand order. The final swap exchanges complete register bindings, not just scalar payloads.
This instruction does not signal.
.globals=0
main() .locals=4
load r2,2
load r3,3
loadsettpswap r1,12,r2,256,r3
ret
load, settp, swap.
minlinkattr1Ensure sufficient attribute capacity and link a one-based attribute.
| Opcode | Form | Effect |
|---|---|---|
0x0125 |
minlinkattr1 rAlias,rObject,index |
Grow as needed and link the literal index. |
0x0126 |
minlinkattr1 rAlias,rObject,rIndex,offset |
Grow as needed and link rIndex+offset. |
The object grows only when the selected index exceeds its logical count.
Existing attributes are preserved. rAlias remains bound to the selected
attribute until it is unlinked.
Raises OUT_OF_RANGE for an index below one and
OVERFLOW_UNDERFLOW when the register-plus-offset sum is not representable.
Allocation failure is fatal rather than catchable.
.globals=0
main() .locals=5
minlinkattr1 r2,r1,3
unlink r2
load r4,3
minlinkattr1 r2,r1,r4,1
unlink r2
ret
minattrs, linkattr1, unlink.
nullnReset two, three, or four registers to empty values.
| Opcode | Form | Effect |
|---|---|---|
0x0112 |
nulln r1,r2 |
Clear two complete values in order. |
0x0113 |
nulln r1,r2,r3 |
Clear three complete values in order. |
0x0114 |
nulln r1,r2,r3,r4 |
Clear four complete values in order. |
Each operand receives normal null/value_zero semantics: payloads, owned
storage, attributes, type metadata, flags, and references are reset.
These forms do not signal.
.globals=0
main() .locals=4
load r0,"a"
load r1,"b"
load r2,"c"
load r3,"d"
nulln r0,r1,r2,r3
ret
null, erase.
parseplanExecute a compiler-prepared PARSE descriptor without decoding a textual plan at runtime.
| Opcode | Form | Effect |
|---|---|---|
0x019a |
parseplan rResults,rSource,"descriptor" |
Populate the reusable result vector from rSource. |
rResults receives one attribute per stored target; dropped fields do not
consume an attribute. The string constant is the versioned compact descriptor
emitted by rxc, not PARSE source text. Version 1 stores frozen item kinds and
flags, literal byte and character lengths, numeric movements, item count, and
result count in a portable little-endian payload.
Version 2 also supports dynamic delimiter and position items. Each such item
contains a compact index that selects either an earlier completed result or a
temporary external-value slot after the public result slots. Compiler-generated
code populates external slots before parseplan; the instruction reads them,
executes the plan, and shrinks rResults to its declared public result count.
Dynamic numeric values must convert to a nonnegative native integer.
The VM validates the header and each item boundary before using it. It reuses the result vector’s attribute storage across executions where possible. Normal compiler lowering evaluates and copies the source first and then assigns vector elements to source targets in order.
Raises INVALID_ARGUMENTS for a malformed, truncated, unsupported-version, or
internally inconsistent descriptor. A dynamic numeric value that is not a
nonnegative native integer raises CONVERSION_ERROR. Allocation failure is
fatal.
parseplan is intended for compiler output. The final operand below is an
illustrative hex-string placeholder, not a complete hand-authored descriptor:
parseplan r0,r1,"<versioned-descriptor-bytes>"x
parsepos2, parsewords3, parsewords3d.
parsepos2Split a source at a fixed PARSE character position and capture the next blank-delimited word.
| Opcode | Form | Effect |
|---|---|---|
0x0198 |
parsepos2 rPrefix,rWord,rSource,split |
Write the fixed prefix and the next word. |
split is the number of source characters placed in rPrefix. The VM then
skips ASCII blanks and writes the following blank-delimited word to rWord;
the remainder is discarded. Character counting is by Unicode code point in
UTF builds and by byte in non-UTF builds. Source/output aliasing is supported.
If an aliased source must be snapshotted and allocation fails, the VM raises
FAILURE. Ordinary empty or short input produces empty/truncated fields rather
than a signal.
.globals=0
main() .locals=3
load r2,"abcde next remainder"
parsepos2 r0,r1,r2,5
ret
parseplan, parsewords3, parsewords3d.
parsewords3Capture two blank-delimited words and the unparsed remaining tail directly into three registers.
| Opcode | Form | Effect |
|---|---|---|
0x0195 |
parsewords3 rFirst,rSecond,rTail,rSource |
Write two words and the remaining tail. |
The VM skips leading ASCII blanks before each of the first two fields. It then
writes the rest of the source, unchanged, to rTail. The instruction is also
the chaining primitive for longer eligible implicit-word templates. Any output
may alias the source; the VM snapshots source bytes before ordered writes when
needed.
If an aliased source snapshot cannot be allocated, the VM raises FAILURE.
Empty or short input yields empty fields without a signal.
.globals=0
main() .locals=4
load r3,"one two three four"
parsewords3 r0,r1,r2,r3
ret
parseplan, parsepos2, parsewords3d.
parsewords3dCapture three blank-delimited words and discard the remaining tail.
| Opcode | Form | Effect |
|---|---|---|
0x0199 |
parsewords3d rFirst,rSecond,rThird,rSource |
Write three words and discard the tail. |
Leading ASCII blanks are skipped before every captured word. Text after the third word is ignored. Any output may alias the source; the VM snapshots source bytes before ordered writes when needed.
If an aliased source snapshot cannot be allocated, the VM raises FAILURE.
Empty or short input yields empty fields without a signal.
.globals=0
main() .locals=4
load r3,"one two three ignored"
parsewords3d r0,r1,r2,r3
ret
parseplan, parsepos2, parsewords3.
setlinkattr1Set exact attribute capacity and link a one-based attribute.
| Opcode | Form | Effect |
|---|---|---|
0x0123 |
setlinkattr1 rAlias,rObject,count,rIndex |
Resize to count, then link rIndex. |
0x0124 |
setlinkattr1 rAlias,rObject,count,rIndex,offset |
Resize, then link rIndex+offset. |
Capacity is set before the selected index is checked. Growth and shrink have
normal setattrs semantics; rAlias remains a live binding to the selected
attribute until unlink.
Raises OUT_OF_RANGE for an invalid one-based index and
OVERFLOW_UNDERFLOW when the register-plus-offset sum is not representable.
Attribute allocation failure is fatal rather than catchable.
.globals=0
main() .locals=5
load r4,1
setlinkattr1 r2,r1,4,r4
unlink r2
load r4,2
setlinkattr1 r2,r1,4,r4,1
unlink r2
ret
setattrs, linkattr1, unlink.
setlinkiloadSet attribute capacity, link an attribute, and load an independent integer.
| Opcode | Form | Effect |
|---|---|---|
0x019f |
setlinkiload rAlias,rObject,count,rIndex,rLoaded,integer |
Resize/link, then load the independent register. |
The object is resized first and the one-based register index is checked before
rAlias is linked. The integer load occurs only after a successful link.
Raises OUT_OF_RANGE for an invalid selected index. Attribute allocation
failure is fatal rather than catchable.
.globals=0
main() .locals=5
load r2,2
setlinkiload r3,r1,4,r2,r4,42
unlink r3
ret
setattrs, linkattr1, load.
settpcallSet the final call-window value’s flags, then call a named procedure.
| Opcode | Form | Effect |
|---|---|---|
0x011a |
settpcall rResult,function(),rCount,rValue,flags |
Apply settp to rValue, then execute the mapped call. |
rCount.int is the argument count and the call window begins at the next
numbered register. Hand-written RXAS must place rValue in that window as
required by the component sequence. The VM records the same window metadata as
ordinary call.
The status update does not signal. The call propagates
FUNCTION_NOT_FOUND, frame-allocation failure, and callee/native signals as
documented for call.
.globals=0
main() .locals=12
load r10,1
load r11,43
settpcall r0,return_arg(),r10,r11,512
ret
return_arg() .locals=0
ret a1
settp, call, settpswapcall.
settpswapUpdate one register’s public flags, then exchange two complete bindings.
| Opcode | Form | Effect |
|---|---|---|
0x010b |
settpswap rStatus,flags,rOther |
Apply settp to rStatus, then swap rStatus/rOther. |
The status update happens before the pointer swap, so the updated complete
value is the one moved into rOther.
This instruction does not signal.
.globals=0
main() .locals=3
load r1,1
load r2,2
settpswap r1,256,r2
ret
settp, swap.
settpswapcallSet and swap the final call-window value, then call a named procedure.
| Opcode | Form | Effect |
|---|---|---|
0x0119 |
settpswapcall rResult,function(),rCount,rValue,flags,rWindow |
Set rValue, swap it with rWindow, then call. |
rCount.int is the argument count and the call window begins at the next
numbered register. The status write and pointer swap happen before call
mapping. The call records the same window base/count metadata as ordinary
call, including for native signal unwind.
The setup does not signal. Call resolution, allocation, native, and callee
signals are the same as call.
.globals=0
main() .locals=13
load r10,1
load r11,0
load r12,42
settpswapcall r0,return_arg(),r10,r12,256,r11
ret
return_arg() .locals=0
ret a1
settp, swap, call, settpcall.
settpswapsettpswapPrepare two values with the same status mask and swap each into place.
| Opcode | Form | Effect |
|---|---|---|
0x0111 |
settpswapsettpswap rFirst,flags,rFirstWindow,rSecond,rSecondWindow |
Set/swap the first pair, then set/swap the second pair. |
The ordered sequence is settp rFirst,flags, swap the first pair,
settp rSecond,flags, then swap the second pair. Both swaps exchange complete
bindings.
This instruction does not signal.
.globals=0
main() .locals=5
load r1,1
load r2,2
load r3,3
load r4,4
settpswapsettpswap r1,512,r2,r3,r4
ret
settp, swap, settpswap.
swapcallSwap the final call-window value into place, then call a named procedure.
| Opcode | Form | Effect |
|---|---|---|
0x0118 |
swapcall rResult,function(),rCount,rWindow,rValue |
Swap rWindow/rValue, then execute the mapped call. |
rCount.int is the argument count and its next numbered register is the first
argument. The pointer swap happens before the call window is mapped. Normal
return and cold signal unwind use the same window contract as ordinary call.
The swap does not signal. The call has the same resolution, allocation,
native, and callee signals as call.
.globals=0
main() .locals=13
load r10,1
load r11,0
load r12,41
swapcall r0,return_arg(),r10,r11,r12
ret
return_arg() .locals=0
ret a1
swap, call, settpswapcall.
swapnExchange two, three, or four register-binding pairs in operand order.
| Opcode | Form | Effect |
|---|---|---|
0x0108 |
swapn r1,r2,r3,r4 |
Swap two pairs. |
0x0109 |
swapn r1,r2,r3,r4,r5,r6 |
Swap three pairs. |
0x010a |
swapn r1,r2,r3,r4,r5,r6,r7,r8 |
Swap four pairs. |
Each pair uses ordinary swap pointer semantics, so complete values and their
storage move together. Pairs are processed from left to right; repeated
register operands therefore observe earlier swaps.
These forms do not signal.
.globals=0
main() .locals=4
load r0,20
load r1,22
load r2,1
load r3,2
swapn r0,r1,r2,r3
ret
swap.
swapsettpExchange one pair, then update another register’s public flags.
| Opcode | Form | Effect |
|---|---|---|
0x010e |
swapsettp rLeft,rRight,rStatus,flags |
Swap rLeft/rRight, then apply settp to rStatus. |
The pointer swap is complete before the band-aware public status update. Operand aliasing therefore observes the post-swap binding.
This instruction does not signal.
.globals=0
main() .locals=4
load r1,1
load r2,2
load r3,3
swapsettp r1,r2,r3,512
ret
swap, settp.
swapsettpswapSwap one pair, update status, then swap the updated value with another.
| Opcode | Form | Effect |
|---|---|---|
0x010f |
swapsettpswap rLeft,rRight,rStatus,flags,rOther |
Swap, set rStatus, then swap rStatus/rOther. |
All three effects occur left to right using complete binding swaps and
band-aware settp semantics.
This instruction does not signal.
.globals=0
main() .locals=5
load r1,1
load r2,2
load r3,3
load r4,4
swapsettpswap r1,r2,r3,256,r4
ret
swap, settp, settpswap.
unlinkbrRestore a local register binding and then branch unconditionally.
| Opcode | Form | Effect |
|---|---|---|
0x0120 |
unlinkbr rAlias,label |
Unlink rAlias, then transfer control to label. |
The binding restoration happens before control transfers. There is no fall-through path.
This instruction does not signal.
.globals=0
main() .locals=2
setattrs r1,1
linkattr1 r0,r1,1
unlinkbr r0,done
ret 1
done:
ret
unlink, br.
unlinknRestore two local register numbers to their frame-owned base storage.
| Opcode | Form | Effect |
|---|---|---|
0x011b |
unlinkn rFirst,rSecond |
Unlink both registers in operand order. |
Like two unlink instructions, this changes bindings rather than copying
values. Calling it on an already restored register simply assigns the same
base pointer.
This instruction does not signal.
.globals=0
main() .locals=4
setattrs r1,2
linkattr1 r2,r1,1
linkattr1 r3,r1,2
unlinkn r2,r3
ret
unlink, linkattr1.