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
+1 -1
View File
@@ -203,7 +203,7 @@ passNotVectorName:
BNQ passNotSwi
SETD.0 ClsOpcode
LDA.0
INIB 0x18
INIB 0x72 ; SWI. Moved with the rest of the subroutine block.
XOR
BNQ passNotSwi
INIA 0d1
+25 -25
View File
@@ -40,31 +40,31 @@ AsmInstructionCount:
0d71
AsmInstructions:
0x00 0d0 "ADD "
0x01 0d0 "SUB "
0x02 0d0 "AND "
0x03 0d0 "OR "
0x04 0d0 "XOR "
0x05 0d0 "NOTA"
0x06 0d0 "NOTB"
0x07 0d0 "SHL "
0x08 0d0 "SHR "
0x10 0d1 "BRI "
0x11 0d1 "BRQ "
0x12 0d1 "BRA "
0x13 0d1 "BRB "
0x14 0d1 "BRC "
0x15 0d3 "BRD "
0x1A 0d1 "BNQ "
0x1B 0d1 "BNA "
0x1C 0d1 "BNB "
0x1D 0d1 "BNC "
0x16 0d1 "RCAL"
0x17 0d1 "CALL"
0x18 0d2 "SWI "
0x19 0d0 "RETI"
0x1E 0d0 "RRET"
0x1F 0d0 "RET "
0x10 0d0 "ADD "
0x11 0d0 "SUB "
0x12 0d0 "AND "
0x13 0d0 "OR "
0x14 0d0 "XOR "
0x15 0d0 "NOTA"
0x16 0d0 "NOTB"
0x17 0d0 "SHL "
0x18 0d0 "SHR "
0x60 0d1 "BRI "
0x61 0d1 "BRQ "
0x62 0d1 "BRA "
0x63 0d1 "BRB "
0x64 0d1 "BRC "
0x65 0d3 "BRD "
0x66 0d1 "BNQ "
0x67 0d1 "BNA "
0x68 0d1 "BNB "
0x69 0d1 "BNC "
0x70 0d1 "RCAL"
0x71 0d1 "CALL"
0x72 0d2 "SWI "
0x73 0d0 "RETI"
0x74 0d0 "RRET"
0x75 0d0 "RET "
0x20 0d0 "RSTA"
0x21 0d0 "RSTB"
0x22 0d0 "INCA"
+25 -25
View File
@@ -3837,31 +3837,31 @@ InstructionCount:
; it by Tests/docs.sh. Seven bytes each: the opcode, the shape, and four characters of name
; with the zero the assembler puts after a string.
Instructions:
0x00 0d0 "ADD "
0x01 0d0 "SUB "
0x02 0d0 "AND "
0x03 0d0 "OR "
0x04 0d0 "XOR "
0x05 0d0 "NOTA"
0x06 0d0 "NOTB"
0x07 0d0 "SHL "
0x08 0d0 "SHR "
0x10 0d1 "BRI "
0x11 0d1 "BRQ "
0x12 0d1 "BRA "
0x13 0d1 "BRB "
0x14 0d1 "BRC "
0x15 0d3 "BRD "
0x1A 0d1 "BNQ "
0x1B 0d1 "BNA "
0x1C 0d1 "BNB "
0x1D 0d1 "BNC "
0x16 0d1 "RCAL"
0x17 0d1 "CALL"
0x18 0d2 "SWI "
0x19 0d0 "RETI"
0x1E 0d0 "RRET"
0x1F 0d0 "RET "
0x10 0d0 "ADD "
0x11 0d0 "SUB "
0x12 0d0 "AND "
0x13 0d0 "OR "
0x14 0d0 "XOR "
0x15 0d0 "NOTA"
0x16 0d0 "NOTB"
0x17 0d0 "SHL "
0x18 0d0 "SHR "
0x60 0d1 "BRI "
0x61 0d1 "BRQ "
0x62 0d1 "BRA "
0x63 0d1 "BRB "
0x64 0d1 "BRC "
0x65 0d3 "BRD "
0x66 0d1 "BNQ "
0x67 0d1 "BNA "
0x68 0d1 "BNB "
0x69 0d1 "BNC "
0x70 0d1 "RCAL"
0x71 0d1 "CALL"
0x72 0d2 "SWI "
0x73 0d0 "RETI"
0x74 0d0 "RRET"
0x75 0d0 "RET "
0x20 0d0 "RSTA"
0x21 0d0 "RSTB"
0x22 0d0 "INCA"
+7 -1
View File
@@ -114,6 +114,12 @@ Back:
; by hand because SplitBit has no linker: to this program it is just so much data.
;
; INIA 'l' OUTA 0 INIA 'o' OUTA 0 ... and so on, then RETI
;
; THESE ARE OPCODES AND THEY MOVE WHEN THE MAP MOVES. Nothing checks them - to the
; assembler they are numbers, and to this program they are data - so an opcode
; reorganisation has to come here by hand. It has happened once: RETI was 0x19 before the
; branch and subroutine blocks were split apart, and this was the only place in the corpus
; that noticed, by faulting on a byte that had stopped being an instruction.
Payload:
0x26 0x6C 0xD1 0x00
0x26 0x6F 0xD1 0x00
@@ -122,4 +128,4 @@ Payload:
0x26 0x65 0xD1 0x00
0x26 0x64 0xD1 0x00
0x26 0x0A 0xD1 0x00
0x19
0x73 ; RETI
+21
View File
@@ -0,0 +1,21 @@
; runOffTest.asm
; A program that runs off the end of itself.
;
; THIS IS WHY 0x00 IS NOT AN INSTRUCTION. Program Memory that has never been written, or a
; load that stopped part way and left zeroes in its tail, used to read as a long run of
; additions - the machine would carry on through them, arrive somewhere unpredictable, and
; whatever went wrong there would be a long way from the byte that caused it.
;
; Nothing in 0x00 to 0x0F is an instruction now, so a run into blank memory faults where it
; is met and says the address. That is the difference between a diagnosis and a search, and
; it costs an opcode block nobody was using.
;
; The program does not halt. It is not supposed to: falling off the end IS the test.
;
; Written by Anachronaut
#Program
start:
INIA 0x2E ; "."
OUTA 0x00