HOVALAAG Processor Documentation

The processor in HOVALAAG is the █████ designed by ████████ █████ Technologies in 19██.
It is a Harvard architecture VLIW processor with no data storage, only instruction
storage. The original CPU could only address 64 instruction words; HOVALAAG uses the
later ██ variant which allows 256 program words (although only the first 64 can be
branched to with "short" labels).

Each instruction is encoded in 32 bits as follows:

31302928 27262524 23222120 19181716 15141312 1110 9 8 7 6 5 4 3 2 1 0
ALU A B C D W F PC O IO X K L
See "sample.vasm" for documentation on assembly language syntax. In all cases, the values used are the values in the registers at the start of the instruction. In other words, all operations proceed in parallel (except as noted).
ALU The Arithmetic & Logic Unit can perform one of sixteen possible computations.
0000   0 constant zero (not the value of K)
0001-Anegated value of A register
0010Bvalue of B register
0011Cvalue of C register
0100A>>1signed right bitshift of A; see notes below
0101A+Bsum of A and B registers
0110B-Adifference of B and A registers
0111A+B+Fsum of A and B, and carry from 1-bit F register
1000B-A-Fdifference of B and A, and borrow from 1-bit F register
1001A|Bbitwise OR of A and B
1010A&Bbitwise AND of A and B
1011A^Bbitwise XOR of A and B
1100~Abitwise inverse of A
1101BCD A+Bbinary-coded duodecimal add
1110BCD B-Abinary-coded duodecimal subtract
1111BCD A+B+F binary-coded duodecimal add with carry
Note 1: A>>1 (0100b) causes the F operation to use the bottom bit of A instead of the hidden top bit of the ALU operation when computing the new value of F. This means you can load the bottom bit of A into F using F=NEG(A>>1). Note 2: the BCD instructions, which compute base-12 arithmetic, are not supported by the HOVALAAG assembler or the HOVALAAG emulator. Note 3: registers that load from the ALU (later in this document) load the value computed by the ALU in this cycle, not the previous cycle (the ALU is not a register).
A A is a 12-bit generic register used as an input to the ALU and used for loading data from input.
00     A is unchanged
01 A=ALU A is loaded from the ALU computation
10 A=D A is loaded from register D
11 A=IN#   A is loaded from input stream 1 or 2, depending on the value of IO

B B is a 12-bit generic register used as an input to the ALU. It also allows feeding a constant embedded in the instruction to the ALU.
00   B is unchanged
01 B=ALU   B is loaded from the ALU computation
10 B=A B is loaded from register A
11   B=K B is loaded from the constant K in the instruction word
If the X bit is set, the 6-bit constant K is replaced by the 12-bit constant K:L.
C C is a 12-bit counting register used to allow efficient looping.
00   C is unchanged
01 C=ALU   C is loaded from the ALU computation
10 DEC compute C=C-1
11   DECNZ compute C=C-1; if the result is non-zero, branch to address L
If the X bit is set, the 6-bit constant L is conceptually replaced by the 12-bit constant K:L. In practice, only the bottom 8 bits of the combined constant are loaded into the 8-bit program counter.
D D is a 12-bit data storage register which can be easily swapped with register A.
0     D is unchanged
1 D=A   D is loaded from A

W W is a 12-bit buffer register used to store values meant to be written to an output stream. It is not possible to get values stored in W back into the rest of the CPU.
00     W is unchanged
01 W=ALU   W is loaded from the ALU computation
10 W=A W is loaded from register A
11 W=K W is loaded from constant K in the instruction word
If the X bit is set, the 6-bit constant K is replaced by the 12-bit constant K:L.
F F is a 1-bit register which is used for conditional branches and as a carry flag.
00     F is unchanged
01 F=ZERO(ALU)   F is 1 iff the ALU computation is zero
10 F=NEG(ALU) F is 1 iff the ALU computation is negative
11 F=POS(ALU) F is 1 iff the ALU computation is positive
Note that the ALU computation is computed with a hidden sign bit, so F=NEG(B-A) will be 1 if A > B, even if the computation overflows. Note that if the ALU computation is A>>1, the original bottom bit of A is used as the hidden sign bit, so F=NEG(A>>1) loads the bottom bit of A into F.
PC The 8-bit PC register stores the program counter, which is the index of the instruction word currently being executed by the processor. The unit is used to implement conditional and unconditional branches. The value of the program counter cannot be loaded to or from other registers in the processor.
00     execution proceeds to the next instruction
01 JMP   unconditional branch to instruction L
10 JMPT branch to instruction L if F is 1
11 JMPF branch to instruction L if F is 0
Note that DECNZ in the C unit can also trigger a branch to L. If the X bit is set, the 6-bit constant L is conceptually replaced by the 12-bit constant K:L. In practice, only the bottom 8 bits of the combined constant are loaded into the 8-bit program counter.
O O is the name of the "output" unit, which allows writing to an output stream.
0     no output
1 OUT#=W   output the value in W to output stream #IO

IO A 1-bit selector that determines which input and output stream should be accessed this cycle. It has no effect if no input or output is performed. Because there is only a single bit, it is not possible to read from IN0 and write to OUT1 in the same cycle; similarly IN1 and OUT0.
0   IN1,OUT1 use input and/or output stream 1
1 IN2,OUT2   use input and/or output stream 2

X A flag which indicates that the two 6-bit constants below should be combined into a single 12-bit constant.
K A 6-bit constant in the instruction word used for arithmetic. Sign-extended to 12 bits. Can be full 12-bit constant by setting the X flag.
L A 6-bit constant in the instruction word used for branch targets. Zero-extended to 8 bits. Can be full 8-bit constant by setting the X flag.