Move the opcode map: nothing in 0x0X, and room for a return variant

Three blocks move and nothing else changes. Branches take 0x60, subroutines
take 0x70, and the ALU moves up into the 0x10 block the two of them used to
share. Order within each block is preserved exactly - this relocates them,
it does not rethink them.

WHAT IT BUYS IS AN EMPTY 0x00 TO 0x0F. Program Memory that was never
written, or a load that stopped part way and left zeroes in its tail, used
to read as a long run of ADDs: the machine carried on through them, arrived
somewhere unpredictable, and whatever broke there was a long way from the
byte that caused it. Now it faults where it is met:

  Fault: 0x00 at Program Address 0x0004 is not an instruction.

That is the address of the byte after the last real instruction, which is
the difference between a diagnosis and a search. Reserving the whole nibble
rather than just 0x00 means a run into blank memory faults wherever it
starts rather than only when it lands on the right byte. runOffTest records
it, and the block is left empty for whatever turns out to want it.

The other half is room: branches and subroutines had filled 0x10 to 0x1F
between them, so a service return that keeps Q and DP3 had nowhere to sit
next to its family. It has 0x76 waiting now.

Five places wrote an opcode down that the scripted remap did not reach, and
four of them were found by tests rather than by looking:

- secondPass.c lists which opcodes take an address, and firstPass.c knows
  SWI by number. Missing those made XOR read as a branch.
- Asm.asm knows SWI by number too, being the other assembler. Missing it
  made the native and host assemblers disagree byte for byte, which is
  exactly the check that exists to catch a thing known in two places.
- loaderTest.asm carries a hand written payload, and its RETI was 0x19. To
  the assembler those are numbers and to the program they are data, so
  nothing but running it could notice. It says so in a comment now.
- The Assembler Manual prints the bytes hello.asm assembles to, and two of
  them were branches.

The monitor's recorded disassembly moved by exactly the bytes it should:
18 became 72 wherever SWI appears, with SETD and INIB untouched and every
disassembled line still reading the same.
This commit is contained in:
Anachronaut
2026-08-27 18:05:54 -04:00
parent ce2a2cd7e6
commit cd5f548736
15 changed files with 213 additions and 186 deletions
+36 -26
View File
@@ -67,35 +67,45 @@ The Bytes column is the total length of the instruction, counting its opcode, an
### Arithmetic and Logic Operations: 9 Instructions
| Hex Code | Mnemonic | Bytes | Description |
| -- | ---- | -- | -- |
| 00 | ADD | 1 | Adds A, B, and the Carry Flag, the result is stored in Q. |
| 01 | SUB | 1 | Subtracts B and the Carry Flag from A, the result is stored in Q. |
| 02 | AND | 1 | Bitwise and of A and B, the result is stored in Q. |
| 03 | OR | 1 | Bitwise or of A and B, the result is stored in Q. |
| 04 | XOR | 1 | Bitwise xor of A and B, the result is stored in Q. |
| 05 | NOTA | 1 | Bitwise inversion of A, the result is stored in Q. |
| 06 | NOTB | 1 | Bitwise inversion of B, the result is stored in Q. |
| 07 | SHL | 1 | A and B form a circular shift register. Rotate this register left. |
| 08 | SHR | 1 | A and B form a circular shift register. Rotate this register right. |
| 10 | ADD | 1 | Adds A, B, and the Carry Flag, the result is stored in Q. |
| 11 | SUB | 1 | Subtracts B and the Carry Flag from A, the result is stored in Q. |
| 12 | AND | 1 | Bitwise and of A and B, the result is stored in Q. |
| 13 | OR | 1 | Bitwise or of A and B, the result is stored in Q. |
| 14 | XOR | 1 | Bitwise xor of A and B, the result is stored in Q. |
| 15 | NOTA | 1 | Bitwise inversion of A, the result is stored in Q. |
| 16 | NOTB | 1 | Bitwise inversion of B, the result is stored in Q. |
| 17 | SHL | 1 | A and B form a circular shift register. Rotate this register left. |
| 18 | SHR | 1 | A and B form a circular shift register. Rotate this register right. |
### Branch and Subroutine Operations: 16 Instructions
### Branch Operations: 10 Instructions
| Hex Code | Mnemonic | Bytes | Description |
| -- | ---- | -- | -- |
| 10 | BRI | 3 | Branch Immediately. Loads the immediate next two bytes of Program Memory into the Program Counter, first the most significant byte, then the least. |
| 11 | BRQ | 3 | Branch on Q. If Q is zero, loads the immediate next two bytes of Program Memory into the Program Counter. |
| 12 | BRA | 3 | Branch on A. If A is zero, loads the immediate next two bytes of Program Memory into the Program Counter. |
| 13 | BRB | 3 | Branch on B. If B is zero, loads the immediate next two bytes of Program Memory into the Program Counter. |
| 14 | BRC | 3 | Branch if Carry is set. |
| 15 | BRD | 2 | Branch to the address held in the named Data Pointer. |
| 1A | BNQ | 3 | Branch if Q is not zero. |
| 1B | BNA | 3 | Branch if A is not zero. |
| 1C | BNB | 3 | Branch if B is not zero. |
| 1D | BNC | 3 | Branch if the Carry Flag is clear. |
| 16 | RCAL | 3 | Raw call. Pushes only the Program Counter, then performs an immediate branch. Two bytes of Stack, and nothing is put back. Must be returned from with RRET. |
| 17 | CALL | 3 | Call subroutine. Pushes the Program Counter, Data Pointers 0 through 2, B and A to the Stack, then performs an immediate branch. This costs ten bytes of Stack. |
| 18 | SWI | 2 | Software Interrupt. The next byte names a software vector. Pushes an interrupt frame and dispatches through it. Never masked. |
| 19 | RETI | 1 | Return from an interrupt. Restores everything the frame holds and carries on from where the interrupt arrived. |
| 1E | RRET | 1 | Return from a raw call. Takes back the Program Counter and nothing else. |
| 1F | RET | 1 | Return from subroutine. Restores A, B, and Data Pointers 0 through 2 from the Stack, then sets the Program Counter to the instruction after the CALL. Data Pointer 3 and Q are left as the subroutine leaves them. |
| 60 | BRI | 3 | Branch Immediately. Loads the immediate next two bytes of Program Memory into the Program Counter, first the most significant byte, then the least. |
| 61 | BRQ | 3 | Branch on Q. If Q is zero, loads the immediate next two bytes of Program Memory into the Program Counter. |
| 62 | BRA | 3 | Branch on A. If A is zero, loads the immediate next two bytes of Program Memory into the Program Counter. |
| 63 | BRB | 3 | Branch on B. If B is zero, loads the immediate next two bytes of Program Memory into the Program Counter. |
| 64 | BRC | 3 | Branch if Carry is set. |
| 65 | BRD | 2 | Branch to the address held in the named Data Pointer. |
| 66 | BNQ | 3 | Branch if Q is not zero. |
| 67 | BNA | 3 | Branch if A is not zero. |
| 68 | BNB | 3 | Branch if B is not zero. |
| 69 | BNC | 3 | Branch if the Carry Flag is clear. |
### Subroutine Operations: 6 Instructions
A block of their own, because the branches and these outgrew one nibble between them. Each
raw form sits immediately below the ordinary one it cannot be mixed with - RCAL under CALL,
RRET under RET - since the frames differ and returning through the wrong one takes the
machine somewhere nobody named.
| Hex Code | Mnemonic | Bytes | Description |
| -- | ---- | -- | -- |
| 70 | RCAL | 3 | Raw call. Pushes only the Program Counter, then performs an immediate branch. Two bytes of Stack, and nothing is put back. Must be returned from with RRET. |
| 71 | CALL | 3 | Call subroutine. Pushes the Program Counter, Data Pointers 0 through 2, B and A to the Stack, then performs an immediate branch. This costs ten bytes of Stack. |
| 72 | SWI | 2 | Software Interrupt. The next byte names a software vector. Pushes an interrupt frame and dispatches through it. Never masked. |
| 73 | RETI | 1 | Return from an interrupt. Restores everything the frame holds and carries on from where the interrupt arrived. |
| 74 | RRET | 1 | Return from a raw call. Takes back the Program Counter and nothing else. |
| 75 | RET | 1 | Return from subroutine. Restores A, B, and Data Pointers 0 through 2 from the Stack, then sets the Program Counter to the instruction after the CALL. Data Pointer 3 and Q are left as the subroutine leaves them. |
### Register Operations: 13 Instructions
| Hex Code | Mnemonic | Bytes | Description |