If a branch is taken, the branch-and-push instruction leaves in the stack a return address (absolute, not relative), which is the address of the first instruction in physical genspace that follows the branch instruction. The return address can also be calculated by adding 17 to the address of the branch instruction. Otherwise, the branch-and-push instruction works the same as its non-push counterpart.

At the end of a subroutine (which was presumably invoked with a branch-and-push instruction) the instruction to return is simply BA_A.

In the descriptions below:

u3 is an unsigned 3-bit integer (0…7)

u8 is an unsigned 8-bit integer (0…255)

s9 is a signed 9-bit integer (−255…+255)

u3 or u8 is the address of a bit within #0 to test. If it represents an unused bit, an exception will be thrown.

s9 is the offset, and it indicates the address, relative to that of the physically-next instruction, to which to branch. The offset is multiplied by 17 (because every instruction is 17 bits long) and added to the address of what would have been the next instruction had no branch been taken. If it is null, an exception will be thrown. If a branch relative instruction has an offset of zero, execution proceeds to the same instruction as if no branch instruction had been encountered.

Branch string. These instructions branch according to the value of a bit, indicated by the bit number, within a string.

BS_0AE

branch string on zero, absolute, bit number embedded

u8_0001_0_0010

BS_0AR

branch string on zero, absolute, bit number in register

18_0001_0_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: address to which to go

Pushed: none

If u8 is 255, BS_0AR is performed instead.

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: address to which to go
• #2 signed integer 0…254: bit number

Pushed: none

BS_1AE

branch string on one, absolute, bit number embedded

u8_0101_0_0010

BS_1AR

branch string on one, absolute, bit number in register

18_0101_0_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: address to which to go

Pushed: none

If u8 is 255, BS_1AR is performed instead.

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: address to which to go
• #2 signed integer 0…254: bit number

Pushed: none

BS_0RB

branch string on zero, relative, bit number embedded

u8_1001_0_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: offset

If u8 is 255, BS_0RR is performed instead.

BS_0RO

branch string on zero, relative, offset embedded

s9_011_0_0010

BS_0RR

branch string on zero, relative, all operands in registers

081_011_0_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer 0…254: bit number

If s9 is a null integer, BS_0RR is performed instead.

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: offset
• #2 signed integer 0…254: bit number

Pushed: none

BS_1RB

branch string on one, relative, bit number embedded

u8_1101_0_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: offset

If u8 is 255, BS_1RR is performed instead.

BS_1RO

branch string on one, relative, offset embedded

s9_111_0_0010

BS_1RR

branch string on one, relative, all operands in registers

081_111_0_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer 0…254: bit number

If s9 is a null integer, BS_1RR is performed instead.

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: offset
• #2 signed integer 0…254: bit number

Pushed: none

BPS_0AE

branch-and-push string on zero, absolute, bit number embedded

u8_0001_1_0010

BPS_0AR

branch-and-push string on zero, absolute, bit number in register

18_0001_1_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: address to which to go

Pushed, if branch is taken:• #0 signed integer: return address

If u8 is 255, BPS_0AR is performed instead.

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: address to which to go
• #2 signed integer 0…254: bit number

Pushed, if branch is taken:• #0 signed integer: return address

BPS_1AE

branch-and-push string on one, absolute, bit number embedded

u8_0101_1_0010

BPS_1AR

branch-and-push string on one, absolute, bit number in register

18_0101_1_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: address to which to go

Pushed, if branch is taken:• #0 signed integer: return address

If u8 is 255, BPS_1AR is performed instead.

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: address to which to go
• #2 signed integer 0…254: bit number

Pushed, if branch is taken:• #0 signed integer: return address

BPS_0RB

branch-and-push string on zero, relative, bit number embedded

u8_1001_1_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: offset

Pushed, if branch is taken:• #0 signed integer: return address

If u8 is 255, BPS_0RR is performed instead.

BPS_0RO

branch-and-push string on zero, relative, offset embedded

s9_011_1_0010

BPS_0RR

branch-and-push string on zero, relative, all operands in registers

081_011_1_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer 0…254: bit number

Pushed, if branch is taken:• #0 signed integer: return address

If s9 is a null integer, BPS_0RR is performed instead.

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: offset
• #2 signed integer 0…254: bit number

Pushed, if branch is taken:• #0 signed integer: return address

BPS_1RB

branch-and-push string on one, relative, bit number embedded

u8_1101_1_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: offset

Pushed, if branch is taken:• #0 signed integer: return address

If u8 is 255, BPS_1RR is performed instead.

BPS_1RO

branch-and-push string on one, relative, offset embedded

s9_111_1_0010

BPS_1RR

branch-and-push string on one, relative, all operands in registers

081_111_1_0010

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer 0…254: bit number

Pushed, if branch is taken:• #0 signed integer: return address

If s9 is a null integer, BPS_1RR is performed instead.

Pulled:
• #0 string: container of the bit to be tested
• #1 signed integer: offset
• #2 signed integer 0…254: bit number

Pushed, if branch is taken:• #0 signed integer: return address

Branch integer or float. (see also integer and float) These quick-test instructions branch according to whether an integer or float has a value, or how it compares to zero. Each instruction performs one of eight tests:

Value of u3

Branch when …

Comments

0

#0 has a value, and #0 > 0

never both true

1

#0 has a value, and #0 ≤ 0

2

#0 has a value, and #0 ≠ 0

never both true

3

#0 has a value, and #0 = 0

4

#0 has a value, and #0 < 0

never both true

5

#0 has a value, and #0 ≥ 0

6

#0 is null

never the same

7

#0 has a value

The tests do not attempt to handle the case where a float is to be tested with a tolerance.

BI_0A

branch integer on zero, absolute

u3_x4_000_10_0_0010

BPI0A

branch-and-push integer on zero, absolute

u3_x4_000_10_1_0010

Pulled:
• #0 signed integer: to be tested
• #1 signed integer: address to which to go

Pushed: none

Pulled:
• #0 signed integer: to be tested
• #1 signed integer: address to which to go

Pushed, if branch is taken:• #0 signed integer: return address

BI_1A

branch integer on one, absolute

u3_x4_100_10_0_0010

BPI1A

branch-and-push integer on one, absolute

u3_x4_100_10_1_0010

Pulled:
• #0 signed integer: to be tested
• #1 signed integer: address to which to go

Pushed: none

Pulled:
• #0 signed integer: to be tested
• #1 signed integer: address to which to go

Pushed, if branch is taken:• #0 signed integer: return address

BI_0R

branch integer on zero, relative

u3_x4_010_10_0_0010

BPI0R

branch-and-push integer on zero, relative

u3_x4_010_10_1_0010

Pulled:
• #0 signed integer: to be tested
• #1 signed integer: offset

Pushed: none

Pulled:
• #0 signed integer: to be tested
• #1 signed integer: offset

Pushed, if branch is taken:• #0 signed integer: return address

BI_1R

branch integer on one, relative

u3_x4_110_10_0_0010

BPI1R

branch-and-push integer on one, relative

u3_x4_110_10_1_0010

Pulled:
• #0 signed integer: to be tested
• #1 signed integer: offset

Pushed: none

Pulled:
• #0 signed integer: to be tested
• #1 signed integer: offset

Pushed, if branch is taken:• #0 signed integer: return address

BF_0A

branch float on zero, absolute

u3_x4_001_10_0_0010

BPF_0A

branch-and-push float on zero, absolute

u3_x4_001_10_1_0010

Pulled:
• #0 float: to be tested
• #1 signed integer: address to which to go

Pushed: none

Pulled:
• #0 float: to be tested
• #1 signed integer: address to which to go

Pushed, if branch is taken:• #0 signed integer: return address

BF_1A

branch float on one, absolute

u3_x4_101_10_0_0010

BPF_1A

branch-and-push float on one, absolute

u3_x4_101_10_1_0010

Pulled:
• #0 float: to be tested
• #1 signed integer: address to which to go

Pushed: none

Pulled:
• #0 float: to be tested
• #1 signed integer: address to which to go

Pushed, if branch is taken:• #0 signed integer: return address

BF_0R

branch float on zero, relative

u3_x4_011_10_0_0010

BPF_0R

branch-and-push float on zero, relative

u3_x4_011_10_1_0010

Pulled:
• #0 float: to be tested
• #1 signed integer: offset

Pushed: none

Pulled:
• #0 float: to be tested
• #1 signed integer: offset

Pushed, if branch is taken:• #0 signed integer: return address

BF_1R

branch float on one, relative

u3_x4_111_10_0_0010

BPF_1R

branch-and-push float on one, relative

u3_x4_111_10_1_0010

Pulled:
• #0 float: to be tested
• #1 signed integer: offset

Pushed: none

Pulled:
• #0 float: to be tested
• #1 signed integer: offset

Pushed, if branch is taken:• #0 signed integer: return address

Branch uninterruptable. These tests inquire of the the CPU whether it is willing to perform the the next several instructions atomically, that is to say suppressing any interrupts, context switches, et cetera.

If the CPU is willing, the branch is taken on a grant, and skipped on a deny.

If the CPU is unwilling, the branch is taken on a deny and skipped on a grant.

The branch uninterruptable instruction itself does not count toward the instruction count.

The purpose of the branch uninterruptable tests is to allow short instruction sequences to be processed atomically, while still preventing any one thread from taking over the machine. Some CPUs might be wired with a fixed maximum count, while others might fluctuate according to the circumstances.

A request of zero instructions, being trivially satisfiable, is always granted.

A request of one instruction is always granted, because any single instruction is uninterruptable whether requested or not.

A request that is negative throws an exception.

A request that is a null integer is denied.

Programmers frequently need (for instance, for semaphores) an uninterruptable sequence similar to this: (1) read an integer from genspace into a register, (2) increment the integer, and (3) write the integer from the register into genspace. Thus for programs to make good progress, three-instruction requests should rarely be denied. To go further: if the designers of a particular implementation of the CPU see that it will always be sensible to grant uninterruptibility for short sequences, they can include a simpler instruction (see XU_DE and XU_DR below) that omits branching information.

A program, having been granted one uninterruptability request, might ask for a second before the first expires:

If the second request would expire no later than the first, it will be granted.

If the second request would expire later than the first, and it is denied, the first request continues normally.

If the second request would expire later than the first, and it is granted, then the second will start to run immediately, and the remainder of the first request will be forgotten. In this case, there will be no break in uninterruptability as the first request ends and the second begins.

The use of branching means that a clever program, when faced with a denied request, can try an alternate means to accomplish the task at hand, or can initiate a non-busy wait.

Ideally, there will be no constraint on what kinds of instructions may be executed during the uninterruptable period. Whether this can be accomplished in practice is an open issue, raising the question of what to do if uninterruptibility is granted, and then an ineligible instruction is encountered.

Throwing an exception in the midst of an unterruptable section is no panacea, because it may leave inconsistent data in shared genspace, confusing other CPUs in a multiprocessor system.

A complication is that an uninterruptable segment might contain ordinary conditional branching statements, and it would be difficult for the CPU to pre-scan all possible paths within the program in order to verify that all instructions qualify. Even a total prohibition of branching statements, which might make a pre-scan feasible in a pipelining environment, still leaves a problem if some instruction throws an exception that the programmer did not anticipate, such as a get from a bad address.