Architecture: Processor

The processor reads and evaluates instructions serially from program memory.

Instruction cycle

An instruction value will be read from the memory address currently referenced by the program counter, the program counter will be incremented by 1, and then the processor will evaluate the instruction. This cycle will repeat until an instruction value of zero is encountered, at which point the processor will halt.

Instruction encoding

Instructions for the Bedrock processor are encoded as 8-bit values. The lower five bits of the value determine which operation will be performed, and the higher three bits of the value are mode flags which determine how the operation will be performed.

BitMaskDescription
0x70x80Return-mode flag
0x60x40Literal-mode flag
0x50x20Double-mode flag
...0x1fOperation code

Return-mode flag

If the return-mode flag is set, the instruction will use the return stack in place of the working stack, and the working stack in place of the return stack.

Literal-mode flag

If the literal-mode flag is set, the first time the instruction would pop a value from a stack, it will instead read a value from the next byte or double of program memory, incrementing the program counter by 1 for each byte read in the process.

Double-mode flag

If the double-mode flag is set, the instruction will operate on double-size values, otherwise the instruction will operate on byte-size values. Some operations use fixed-size values, which will not be affected by this flag. Fixed-size byte values are denoted by a trailing ! in a signature, and fixed-size double values are denoted by a trailing * in a signature.

Operation code

The processor can perform 32 different operations, as per the following table:

BaseNameDescriptionSignature
0x00HLTHalt the processor.( -- )
0x01JMPJump to an address.( a* -- )
0x02JCNConditionally jump to an address.( t! a* -- )
0x03JCKConditionally jump to an address, keeping the value.( t a* -- t )
0x04LDARead a value from program memory.( a* -- v )
0x05STAWrite a value to program memory.( v a* -- )
0x06LDDRead a value from the device bus.( p! -- v )
0x07STDWrite a value to the device bus.( v p! -- )
0x08PSHMove the top value from one stack to the other.( -- x : x -- )
0x09POPRemove the top value of a stack.( x -- )
0x0ACPYCopy the top value from one stack to the other.( -- x : x -- x )
0x0BSPLSplit packed values into multiple bytes.( x -- y z )
0x0CDUPDuplicate the top value of a stack.( x -- x x )
0x0DOVRDuplicate the second value of a stack.( x y -- x y x )
0x0ESWPSwap the top two values on a stack.( x y -- y x )
0x0FROTRotate the top three values on a stack.( x y z -- y z x )
0x10ADDFind the sum of two values.( x y -- r )
0x11SUBFind the difference of two values.( x y -- r )
0x12INCIncrement a value by 1.( x -- r )
0x13DECDecrement a value by 1.( x -- r )
0x14LTHTest if one value is less than another.( x y -- t! )
0x15GTHTest if one value is greater than another.( x y -- t! )
0x16EQUTest if two values are equal.( x y -- t! )
0x17NQKTest if two values are inequal, keeping the values.( x y -- x y t! )
0x18IORFind the bitwise disjunction of two values.( x y -- r )
0x19XORFind the bitwise non-equivalence of two values.( x y -- r )
0x1AANDFind the bitwise conjugation of two values.( x y -- r )
0x1BNOTFind the bitwise compliment of a value.( x -- r )
0x1CSHFShift the bits of a value.( x y! -- r )
0x1DSHCRotate the bits of a value.( x y! -- r )
0x1ETALCount the number of set bits in a value.( x -- r! )
0x1FREVReverse the order of bits in a value.( x -- r )

Operations

HLT

Halt the processor. If any mode flag is set, do nothing.

The instruction variants DB1, DB2, DB3, DB4, DB5, and DB6 can be used as hooks for implementation defined debug functionality.

Signature
( -- )
Instr.Mnm.*:rWorking stackReturn stackNotes
0x00HLT( -- )( -- )Halt the processor.
0x20NOP*( -- )( -- )No effect.
0x40DB1:( -- )( -- )No effect.
0x60DB2*:( -- )( -- )No effect.
0x80DB3r( -- )( -- )No effect.
0xA0DB4*r( -- )( -- )No effect.
0xC0DB5:r( -- )( -- )No effect.
0xE0DB6*:r( -- )( -- )No effect.

JMP

Jump to an address.

The double a is popped from the primary stack. If the double-mode flag is set, the double b is then read from the program counter and pushed to the secondary stack. The double a is then written to the program counter.

Signature
( a* -- : -- [b*] )
Instr.Mnm.*:rWorking stackReturn stack
0x01JMP( a* -- )( -- )
0x21JMS*( a* -- )( -- b* )
0x41JMP::( -- )( -- )
0x61JMS:*:( -- )( -- b* )
0x81JMPrr( -- )( a* -- )
0xA1JMSr*r( -- b* )( a* -- )
0xC1JMPr::r( -- )( -- )
0xE1JMSr:*:r( -- b* )( -- )

JCN

Conditionally jump to an address.

The double a is popped from the primary stack, then the byte t is popped from the primary stack. If the double-mode flag is set and t is not zero, the double b is then read from the program counter and pushed to the secondary stack. If t is not zero, the double a is then written to the program counter.

Signature
( t! a* -- : -- [b*] )
Instr.Mnm.*:rWorking stackReturn stack
0x02JCN( t a* -- )( -- )
0x22JCS*( t a* -- )( -- b* )
0x42JCN::( t -- )( -- )
0x62JCS:*:( t -- )( -- b* )
0x82JCNrr( -- )( t a* -- )
0xA2JCSr*r( -- b* )( t a* -- )
0xC2JCNr::r( -- )( t -- )
0xE2JCSr:*:r( -- b* )( t -- )

JCK

Conditionally jump to an address, keeping the test value.

The double a is popped from the primary stack, then the value t is popped from the primary stack, then the value t is written to the primary stack. The double a is then written to the program counter if t is not zero.

Signature
( t a* -- t )
Instr.Mnm.*:rWorking stackReturn stack
0x03JCK( t a* -- t )( -- )
0x23JCK**( t* a* -- t* )( -- )
0x43JCK::( t -- t )( -- )
0x63JCK*:*:( t* -- t* )( -- )
0x83JCKrr( -- )( t a* -- t )
0xA3JCKr**r( -- )( t* a* -- t* )
0xC3JCKr::r( -- )( t -- t )
0xE3JCKr*:*:r( -- )( t* -- t* )

LDA

Read a value from program memory.

The double a is popped from the primary stack, and then the value v is read from program memory starting at the memory address referenced by a and is pushed to the primary stack.

Signature
( a* -- v )
Instr.Mnm.*:rWorking stackReturn stack
0x04LDA( a* -- v )( -- )
0x24LDA**( a* -- v* )( -- )
0x44LDA::( -- v )( -- )
0x64LDA*:*:( -- v* )( -- )
0x84LDArr( -- )( a* -- v )
0xA4LDAr**r( -- )( a* -- v* )
0xC4LDAr::r( -- )( -- v )
0xE4LDAr*:*:r( -- )( -- v* )

STA

Write a value to program memory.

The double a is popped from the primary stack, then the value v is popped from the primary stack, and then the value v is written to program memory starting at the memory address referenced by a.

Signature
( v a* -- )
Instr.Mnm.*:rWorking stackReturn stack
0x05STA( a* -- v )( -- )
0x25STA**( a* -- v* )( -- )
0x45STA::( -- v )( -- )
0x65STA*:*:( -- v* )( -- )
0x85STArr( -- )( a* -- v )
0xA5STAr**r( -- )( a* -- v* )
0xC5STAr::r( -- )( -- v )
0xE5STAr*:*:r( -- )( -- v* )

LDD

Read a value from the device bus.

The byte p is popped from the primary stack, and then the value v is read from the device bus starting at the device port referenced by p and is pushed to the primary stack.

Signature
( p! -- v )
Instr.Mnm.*:rWorking stackReturn stack
0x06LDD( p -- v )( -- )
0x26LDD**( p -- v* )( -- )
0x46LDD::( -- v )( -- )
0x66LDD*:*:( -- v* )( -- )
0x86LDDrr( -- )( p -- v )
0xA6LDDr**r( -- )( p -- v* )
0xC6LDDr::r( -- )( -- v )
0xE6LDDr*:*:r( -- )( -- v* )

STD

Write a value to the device bus.

The byte p is popped from the primary stack, then the value v is popped from the primary stack, and then the value v is written to the device bus starting at the device port referenced by p.

Signature
( v p! -- )
Instr.Mnm.*:rWorking stackReturn stack
0x07STD( v p -- )( -- )
0x27STD**( v* p -- )( -- )
0x47STD::( v -- )( -- )
0x67STD*:*:( v* -- )( -- )
0x87STDrr( -- )( v p -- )
0xA7STDr**r( -- )( v* p -- )
0xC7STDr::r( -- )( v -- )
0xE7STDr*:*:r( -- )( v* -- )

PSH

Move the top value from one stack to the other.

The value x is popped from the secondary stack, and then the value x is pushed to the primary stack.

Signature
( -- x : x -- )
Instr.Mnm.*:rWorking stackReturn stack
0x08PSH( -- x )( x -- )
0x28PSH**( -- x* )( x* -- )
0x48PSH::( -- l )( -- )
0x68PSH*:*:( -- l* )( -- )
0x88PSHrr( x -- )( -- x )
0xA8PSHr**r( x* -- )( -- x* )
0xC8PSHr::r( -- )( -- l )
0xE8PSHr*:*:r( -- )( -- l* )

POP

Remove the top value of a stack.

The value x is popped from the primary stack.

Signature
( x -- )
Instr.Mnm.*:rWorking stackReturn stack
0x09POP( x -- )( -- )
0x29POP**( x* -- )( -- )
0x49POP::( -- )( -- )
0x69POP*:*:( -- )( -- )
0x89POPrr( -- )( x -- )
0xA9POPr**r( -- )( x* -- )
0xC9POPr::r( -- )( -- )
0xE9POPr*:*:r( -- )( -- )

CPY

Copy the top value from one stack to the other.

The value x is popped from the secondary stack, then the value x is pushed to the secondary stack, and then the value x is pushed to the primary stack.

Signature
( -- x : x -- x )
Instr.Mnm.*:rWorking stackReturn stack
0x0ACPY( -- x )( x -- x )
0x2ACPY**( -- x* )( x* -- x* )
0x4ACPY::( -- l )( -- l )
0x6ACPY*:*:( -- l* )( -- l* )
0x8ACPYrr( x -- x )( -- x )
0xAACPYr**r( x* -- x* )( -- x* )
0xCACPYr::r( -- l )( -- l )
0xEACPYr*:*:r( -- l* )( -- l* )

SPL

Split packed values into multiple bytes.

The value x is popped from the primary stack. For each byte b of x, starting with the high byte, create a byte y where the high four bits of b are the low four bits of y, and push y to the primary stack, then create a byte z where the low four bits of b are the low four bits of z, and push z to the primary stack.

Signature
( x -- y z )
Instr.Mnm.*:rWorking stackReturn stack
0x0BSPL( x -- y z )( -- )
0x2BSPL**( x* -- y* z* )( -- )
0x4BSPL::( -- y z )( -- )
0x6BSPL*:*:( -- y* z* )( -- )
0x8BSPLrr( -- )( x -- y z )
0xABSPLr**r( -- )( x* -- y* z* )
0xCBSPLr::r( -- )( -- y z )
0xEBSPLr*:*:r( -- )( -- y* z* )

DUP

Duplicate the top value of a stack.

The value x is popped from the primary stack, then the value x is pushed to the primary stack, and then the value x is pushed to the primary stack.

Signature
( x -- x x )
Instr.Mnm.*:rWorking stackReturn stack
0x0CDUP( x -- x x )( -- )
0x2CDUP**( x* -- x* x* )( -- )
0x4CDUP::( -- l l )( -- )
0x6CDUP*:*:( -- l* l* )( -- )
0x8CDUPrr( -- )( x -- x x )
0xACDUPr**r( -- )( x* -- x* x* )
0xCCDUPr::r( -- )( -- l l )
0xECDUPr*:*:r( -- )( -- l* l* )

OVR

Duplicate the second value of a stack.

The value y is popped from the primary stack, then the value x is popped from the primary stack, then the value x is pushed to the primary stack, then the value y is pushed to the primary stack, and then the value x is pushed to the primary stack.

Signature
( x y -- x y x )
Instr.Mnm.*:rWorking stackReturn stack
0x0DOVR( x y -- x y x )( -- )
0x2DOVR**( x* y* -- x* y* x* )( -- )
0x4DOVR::( x -- x l x )( -- )
0x6DOVR*:*:( x* -- x* l* x* )( -- )
0x8DOVRrr( -- )( x y -- x y x )
0xADOVRr**r( -- )( x* y* -- x* y* x* )
0xCDOVRr::r( -- )( x -- x l x )
0xEDOVRr*:*:r( -- )( x* -- x* l* x* )

SWP

Swap the top two values on a stack.

The value y is popped from the primary stack, then the value x is popped from the primary stack, then the value y is pushed to the primary stack, and then the value x is pushed to the primary stack.

Signature
( x y -- y x )
Instr.Mnm.*:rWorking stackReturn stack
0x0ESWP( x y -- y x )( -- )
0x2ESWP**( x* y* -- y* x* )( -- )
0x4ESWP::( x -- l x )( -- )
0x6ESWP*:*:( x* -- l* x* )( -- )
0x8ESWPrr( -- )( x y -- y x )
0xAESWPr**r( -- )( x* y* -- y* x* )
0xCESWPr::r( -- )( x -- l x )
0xEESWPr*:*:r( -- )( x* -- l* x* )

ROT

Rotate the top three values on a stack.

The value z is popped from the primary stack, then the value y is popped from the primary stack, then the value x is popped from the primary stack, then the value y is pushed to the primary stack, then the value z is pushed to the primary stack, and then the value x is pushed to the primary stack.

Signature
( x y z -- y z x )
Instr.Mnm.*:rWorking stackReturn stack
0x0FROT( x y z -- y z x )( -- )
0x2FROT**( x* y* z* -- y* z* x* )( -- )
0x4FROT::( x y -- y l x )( -- )
0x6FROT*:*:( x* y* -- y* l* x* )( -- )
0x8FROTrr( -- )( x y z -- y z x )
0xAFROTr**r( -- )( x* y* z* -- y* z* x* )
0xCFROTr::r( -- )( x y -- y l x )
0xEFROTr*:*:r( -- )( x* y* -- y* l* x* )

ADD

Find the sum of two values.

The value y is popped from the primary stack, then the value x is popped from the primary stack, and then the value r is calculated as the wrapped addition of y to x and is pushed to the primary stack.

Signature
( x y -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x10ADD( x y -- r )( -- )
0x30ADD**( x* y* -- r* )( -- )
0x50ADD::( x -- r )( -- )
0x70ADD*:*:( x* -- r* )( -- )
0x90ADDrr( -- )( x y -- r )
0xB0ADDr**r( -- )( x* y* -- r* )
0xD0ADDr::r( -- )( x -- r )
0xF0ADDr*:*:r( -- )( x* -- r* )

SUB

Find the difference of two values.

The value y is popped from the primary stack, then the value x is popped from the primary stack, and then the value r is calculated as the wrapped subtraction of y from x and is pushed to the primary stack.

Signature
( x y -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x11SUB( x y -- r )( -- )
0x31SUB**( x* y* -- r* )( -- )
0x51SUB::( x -- r )( -- )
0x71SUB*:*:( x* -- r* )( -- )
0x91SUBrr( -- )( x y -- r )
0xB1SUBr**r( -- )( x* y* -- r* )
0xD1SUBr::r( -- )( x -- r )
0xF1SUBr*:*:r( -- )( x* -- r* )

INC

Increment a value by 1.

The value x is popped from the primary stack, and then the value r is calculated as the wrapped addition of 1 to x and is pushed to the primary stack.

Signature
( x -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x12INC( x -- r )( -- )
0x32INC**( x* -- r* )( -- )
0x52INC::( -- r )( -- )
0x72INC*:*:( -- r* )( -- )
0x92INCrr( -- )( x -- r )
0xB2INCr**r( -- )( x* -- r* )
0xD2INCr::r( -- )( -- r )
0xF2INCr*:*:r( -- )( -- r* )

DEC

Decrement a value by 1.

The value x is popped from the primary stack, and then the value r is calculated as the wrapped subtraction of 1 from x and is pushed to the primary stack.

Signature
( x -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x13DEC( x -- r )( -- )
0x33DEC**( x* -- r* )( -- )
0x53DEC::( -- r )( -- )
0x73DEC*:*:( -- r* )( -- )
0x93DECrr( -- )( x -- r )
0xB3DECr**r( -- )( x* -- r* )
0xD3DECr::r( -- )( -- r )
0xF3DECr*:*:r( -- )( -- r* )

LTH

Test if one value is less than another.

The value y is popped from the primary stack, and then the value x is popped from the primary stack. If x is less than y, the byte 0xff is pushed to the primary stack, otherwise the byte 0x00 is pushed to the primary stack.

Signature
( x y -- t! )
Instr.Mnm.*:rWorking stackReturn stack
0x14LTH( x y -- t )( -- )
0x34LTH**( x* y* -- t )( -- )
0x54LTH::( x -- t )( -- )
0x74LTH*:*:( x* -- t )( -- )
0x94LTHrr( -- )( x y -- t )
0xB4LTHr**r( -- )( x* y* -- t )
0xD4LTHr::r( -- )( x -- t )
0xF4LTHr*:*:r( -- )( x* -- t )

GTH

Test if one value is greater than another.

The value y is popped from the primary stack, and then the value x is popped from the primary stack. If x is greater than y, the byte 0xff is pushed to the primary stack, otherwise the byte 0x00 is pushed to the primary stack.

Signature
( x y -- t! )
Instr.Mnm.*:rWorking stackReturn stack
0x15GTH( x y -- t )( -- )
0x35GTH**( x* y* -- t )( -- )
0x55GTH::( x -- t )( -- )
0x75GTH*:*:( x* -- t )( -- )
0x95GTHrr( -- )( x y -- t )
0xB5GTHr**r( -- )( x* y* -- t )
0xD5GTHr::r( -- )( x -- t )
0xF5GTHr*:*:r( -- )( x* -- t )

EQU

Test if two values are equal.

The value y is popped from the primary stack, and then the value x is popped from the primary stack. If x is equal to y, the byte 0xff is pushed to the primary stack, otherwise the byte 0x00 is pushed to the primary stack.

Signature
( x y -- t! )
Instr.Mnm.*:rWorking stackReturn stack
0x16EQU( x y -- t )( -- )
0x36EQU**( x* y* -- t )( -- )
0x56EQU::( x -- t )( -- )
0x76EQU*:*:( x* -- t )( -- )
0x96EQUrr( -- )( x y -- t )
0xB6EQUr**r( -- )( x* y* -- t )
0xD6EQUr::r( -- )( x -- t )
0xF6EQUr*:*:r( -- )( x* -- t )

NQK

Test if two values are inequal, keeping the values.

The value y is popped from the primary stack, then the value x is popped from the primary stack, then the value x is pushed to the primary stack, and then the value y is pushed to the primary stack. If x is not equal to y, the byte 0xff is pushed to the primary stack, otherwise the byte 0x00 is pushed to the primary stack.

Signature
( x y -- x y t! )
Instr.Mnm.*:rWorking stackReturn stack
0x17NQK( x y -- x y t )( -- )
0x37NQK**( x* y* -- x* y* t )( -- )
0x57NQK::( x -- x l t )( -- )
0x77NQK*:*:( x* -- x* l* t )( -- )
0x97NQKrr( -- )( x y -- x y t )
0xB7NQKr**r( -- )( x* y* -- x* y* t )
0xD7NQKr::r( -- )( x -- x l t )
0xF7NQKr*:*:r( -- )( x* -- x* l* t )

IOR

Find the bitwise disjunction of two values. This operation is also known as ‘inclusive-or’.

The value y is popped from the primary stack, and then the value x is popped from the primary stack. The value r is then calculated bitwise, where each bit of r is set only if at least one of the corresponding bits of x and y is set. The value r is then pushed to the primary stack.

Signature
( x y -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x18IOR( x y -- r )( -- )
0x38IOR**( x* y* -- r* )( -- )
0x58IOR::( x -- r )( -- )
0x78IOR*:*:( x* -- r* )( -- )
0x98IORrr( -- )( x y -- r )
0xB8IORr**r( -- )( x* y* -- r* )
0xD8IORr::r( -- )( x -- r )
0xF8IORr*:*:r( -- )( x* -- r* )

XOR

Find the bitwise non-equivalence of two values. This operation is also known as ‘exclusive-or’.

The value y is popped from the primary stack, and then the value x is popped from the primary stack. The value r is then calculated bitwise, where each bit of r is set only if exactly one of the corresponding bits of x and y is set. The value r is then pushed to the primary stack.

Signature
( x y -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x19XOR( x y -- r )( -- )
0x39XOR**( x* y* -- r* )( -- )
0x59XOR::( x -- r )( -- )
0x79XOR*:*:( x* -- r* )( -- )
0x99XORrr( -- )( x y -- r )
0xB9XORr**r( -- )( x* y* -- r* )
0xD9XORr::r( -- )( x -- r )
0xF9XORr*:*:r( -- )( x* -- r* )

AND

Find the bitwise conjunction of two values. This operation is also known as ‘and’.

The value y is popped from the primary stack, and then the value x is popped from the primary stack. The value r is then calculated bitwise, where each bit of r is set only if both of the corresponding bits of x and y are set. The value r is then pushed to the primary stack.

Signature
( x y -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x1AAND( x y -- r )( -- )
0x3AAND**( x* y* -- r* )( -- )
0x5AAND::( x -- r )( -- )
0x7AAND*:*:( x* -- r* )( -- )
0x9AANDrr( -- )( x y -- r )
0xBAANDr**r( -- )( x* y* -- r* )
0xDAANDr::r( -- )( x -- r )
0xFAANDr*:*:r( -- )( x* -- r* )

NOT

Find the bitwise compliment of a value. This operation is also known as ‘not’.

The value x is popped from the primary stack. The value r is then calculated bitwise, where each bit of r is set only if the corresponding bit of x is not set. The value r is then pushed to the primary stack.

Signature
( x -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x1BNOT( x -- r )( -- )
0x3BNOT**( x* -- r* )( -- )
0x5BNOT::( -- r )( -- )
0x7BNOT*:*:( -- r* )( -- )
0x9BNOTrr( -- )( x -- r )
0xBBNOTr**r( -- )( x* -- r* )
0xDBNOTr::r( -- )( -- r )
0xFBNOTr*:*:r( -- )( -- r* )

SHF

Shift the bits of a value.

The byte y is popped from the primary stack, then the value x is popped from the primary stack. The value r is calculated from x by shifting the bits of x rightwards by a distance represented by the lower four bits of y, and then by shifting the resultant bits leftwards by a distance represented by the higher four bits of y. The value r is then pushed to the primary stack.

When a value is shifted n bits in one direction, each bit of the value is set to the state of the bit lying n bits in the opposite direction. If this would reach past the end of the value, the bit is unset.

Signature
( x y! -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x1CSHF( x y -- r )( -- )
0x3CSHF**( x* y -- r )( -- )
0x5CSHF::( x -- r )( -- )
0x7CSHF*:*:( x* -- r )( -- )
0x9CSHFrr( -- )( x y -- r )
0xBCSHFr**r( -- )( x* y -- r )
0xDCSHFr::r( -- )( x -- r )
0xFCSHFr*:*:r( -- )( x* -- r )

SHC

Rotate the bits of a value. This operation is also known as a ‘circular shift’.

The byte y is popped from the primary stack, then the value x is popped from the primary stack. The value r is calculated from x by rotating the bits of x rightwards by a distance represented by the lower four bits of y, and then by rotating the resultant bits leftwards by a distance represented by the higher four bits of y. The value r is then pushed to the primary stack.

When a value is rotated n bits in one direction, each bit of the value is set to the state of the bit lying n bits in the opposite direction. If this would reach past the end of the value, wrap around to the other end of the value and continue.

Signature
( x y! -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x1DSHC( x y -- r )( -- )
0x3DSHC**( x* y -- r )( -- )
0x5DSHC::( x -- r )( -- )
0x7DSHC*:*:( x* -- r )( -- )
0x9DSHCrr( -- )( x y -- r )
0xBDSHCr**r( -- )( x* y -- r )
0xDDSHCr::r( -- )( x -- r )
0xFDSHCr*:*:r( -- )( x* -- r )

TAL

Count the number of set bits in a value. This operation is also known as ‘population count’.

The value x is popped from the primary stack, and then the value r is calculated as the number of bits set in x and is pushed to the primary stack.

Signature
( x -- r! )
Instr.Mnm.*:rWorking stackReturn stack
0x1ETAL( x -- r )( -- )
0x3ETAL**( x* -- r )( -- )
0x5ETAL::( -- r )( -- )
0x7ETAL*:*:( -- r )( -- )
0x9ETALrr( -- )( x -- r )
0xBETALr**r( -- )( x* -- r )
0xDETALr::r( -- )( -- r )
0xFETALr*:*:r( -- )( -- r )

REV

Reverse the order of bits in a value.

The value x is popped from the primary stack. The value r is then calculated bitwise, where each bit of r starting from one end of the value is set only if the corresponding bit of x starting from the opposite end of the value is set. The value r is then pushed to the primary stack.

Signature
( x -- r )
Instr.Mnm.*:rWorking stackReturn stack
0x1FREV( x -- r )( -- )
0x3FREV**( x* -- r* )( -- )
0x5FREV::( -- r )( -- )
0x7FREV*:*:( -- r* )( -- )
0x9FREVrr( -- )( x -- r )
0xBFREVr**r( -- )( x* -- r* )
0xDFREVr::r( -- )( -- r )
0xFFREVr*:*:r( -- )( -- r* )