From ca6ff6db6ab56809ecc82caddd52ade906aae54e Mon Sep 17 00:00:00 2001 From: NeilFraser Date: Mon, 23 Mar 2026 22:05:08 +0100 Subject: [PATCH 1/5] Add six equality operators. --- Apps/Blockly.agc | 77 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 6 deletions(-) diff --git a/Apps/Blockly.agc b/Apps/Blockly.agc index ff5a4ec..c40a05e 100644 --- a/Apps/Blockly.agc +++ b/Apps/Blockly.agc @@ -37,7 +37,7 @@ XCH ARUPT CA NUM0 # Clear SLEEPING flag. TS SLEEPING - TCF WAKEUP + TCF T4WAKEUP # DSKY1 (interrupt #5) RESUME @@ -127,7 +127,7 @@ T5RAND TS RAND # Save new num to RAND RESUME -WAKEUP XCH ARUPT +T4WAKEUP XCH ARUPT RESUME @@ -143,9 +143,9 @@ SLEEP EXTEND # Workaround: load 2^14-1, then increment. CA 10MS INCR A - EXTEND + EXTEND # Subtract the desired delay. SU L - TS T4 + TS T4 # Set the interrupt timer EXTEND QXCH QPOP @@ -184,19 +184,84 @@ DISPLAY EXTEND QXCH QPOP RETURN + +# The six equality operators start by pushing two values on the stack. +# Then several chained calls are made depending on which operator is needed. +# In all cases, if 0 is returned on the A register, then the operator is true. +# Calls for '==': +# TCR OP-EQ +# Calls for '!=': +# TCR OP-EQ +# TCR OP-NEG +# Calls for '<=': +# TCR OP-EQ +# TCR OP-LTE +# Calls for '>=': +# TCR OP-EQ +# TCR OP-GTE +# Calls for '<': +# TCR OP-EQ +# TCR OP-GTE +# TCR OP-NEG +# Calls for '>': +# TCR OP-EQ +# TCR OP-LTE +# TCR OP-NEG + + +# Base equality operator. +# Arguments: +# First value. +# Second value. +# Returns (on A): +# Zero if equal. +# Positive if first < second. +# Negative if first > second. +OP-EQ EXTEND + QXCH QPOP + TCR POP # Pop the second value. + # Subtract the first value on the stack from the second value. + EXTEND + INDEX STACKPTR + SU STACK + TCR DROP # Throw away the first value. + EXTEND + QXCH QPOP + RETURN + +# Suffix functions to OP-EQ. +# OP-LTE returns 0 if first '<=' second. +# OP-GTE returns 0 if first '>=' second. +OP-LTE COM +OP-GTE EXTEND + BZMF OP-0 # Return with 0. + TCF OP-1 # Return with 1. + +# Suffix function to OP-EQ, OP-LTE and OP-GTE. Reverses zero and non-zero. +OP-NEG EXTEND + BZF OP-1 +OP-0 CA NUM0 + RETURN +OP-1 CA NUM1 + RETURN + + # Push the contents of the 'A' register onto the stack. PUSH INCR STACKPTR INDEX STACKPTR TS STACK RETURN -# Pop the last value on the stack into the 'A' register. + +# POP: Pop the last value on the stack into the 'A' register. +# DROP: Drop the last value without returning it. POP INDEX STACKPTR CAE STACK - EXTEND +DROP EXTEND DIM STACKPTR RETURN + # Variables in memory. SLEEPING = 061 # Flag indicating if we are busy-sleeping. RAND = 062 # Random number (0 to RANDMAX inc) From 628f9a891f7dfbfee45f1e6fe0f6d703f61c9fdc Mon Sep 17 00:00:00 2001 From: NeilFraser Date: Fri, 27 Mar 2026 19:55:21 +0100 Subject: [PATCH 2/5] Move to own directory and split up. --- Apps/Blockly.agc | 311 ---------------------------------- Apps/Blockly/Boolean-test.agc | 237 ++++++++++++++++++++++++++ Apps/Blockly/Boolean.agc | 107 ++++++++++++ Apps/Blockly/Main.agc | 199 ++++++++++++++++++++++ Apps/Blockly/Math-test.agc | 83 +++++++++ Apps/Blockly/Math.agc | 56 ++++++ Operators/SU.agc | 3 +- 7 files changed, 684 insertions(+), 312 deletions(-) delete mode 100644 Apps/Blockly.agc create mode 100644 Apps/Blockly/Boolean-test.agc create mode 100644 Apps/Blockly/Boolean.agc create mode 100644 Apps/Blockly/Main.agc create mode 100644 Apps/Blockly/Math-test.agc create mode 100644 Apps/Blockly/Math.agc diff --git a/Apps/Blockly.agc b/Apps/Blockly.agc deleted file mode 100644 index c40a05e..0000000 --- a/Apps/Blockly.agc +++ /dev/null @@ -1,311 +0,0 @@ -# Copyright: Public domain. -# Filename: Blockly.agc -# Purpose: Framework to enable Blockly-based programming using higher-level -# blocks. -# Assembler: yaYUL -# Contact: Neil Fraser -# Contact: - -# Interrupts, must have 4 lines per interrupt - SETLOC 4000 - - # Power up - CA 100MS # Schedule T5 soon. - TS T5 - TCF START - NOOP - - # T6 (interrupt #1) - RESUME - NOOP - NOOP - NOOP - - # T5 (interrupt #2) - XCH ARUPT - CAF 100MS # Reschedule T5 soon. - TS T5 - TCF T5RUPT - - # T3 (interrupt #3) - RESUME - NOOP - NOOP - NOOP - - # T4 (interrupt #4) - XCH ARUPT - CA NUM0 # Clear SLEEPING flag. - TS SLEEPING - TCF T4WAKEUP - - # DSKY1 (interrupt #5) - RESUME - NOOP - NOOP - NOOP - - # DSKY2 (interrupt #6) - RESUME - NOOP - NOOP - NOOP - - # Uplink (interrupt #7) - RESUME - NOOP - NOOP - NOOP - - # Downlink (interrupt #8) - RESUME - NOOP - NOOP - NOOP - - # Radar (interrupt #9) - RESUME - NOOP - NOOP - NOOP - - # Hand controller (interrupt #10) - RESUME - NOOP - NOOP - NOOP - -START CA NUM0 # Initializations. - TS STACKPTR # Stack pointer to zero. - TS RAND # Current random number to zero. - CA NUM1 # Random number range = 0-1. - TS RANDMAX - - # Set RANDMAX to 9 - CA NUM7 - TS RANDMAX - - # Display a 00. - CA D14-15 - TCR PUSH - CA NUM0 - TCR PUSH - CA NUM0 - TCR PUSH - TCR DISPLAY - - # Wait a second. - CA NUM100 - TCR PUSH - TCR SLEEP - - # Display a 11. - CA D14-15 - TCR PUSH - # Fetch random number. - CA RAND - TCR PUSH - # Fetch random number. - CA RAND - TCR PUSH - TCR DISPLAY - - # Wait a second. - CA NUM100 - TCR PUSH - TCR SLEEP - TCF START - - -T5RUPT CA NEWJOB # Tickle the night watchman. - # Step the random number (down to zero, wrapping up). - CCS RAND - TCF T5RAND # RAND > 0 (A = RAND-1) - CAE RANDMAX # RAND = 0, make it RANDMAX again -T5RAND TS RAND # Save new num to RAND - XCH ARUPT - RESUME - - -T4WAKEUP XCH ARUPT - RESUME - - -# Function that sleeps for the duration of SLEEPCS. -# Arguments: -# Delay in 100ths of a second, thus 100 is 1 second. -SLEEP EXTEND - QXCH QPOP - TCR POP # Pop the delay from the stack. - TS L - # We want to load 2^14 (40,000 oct). But doing so gets treated - # as a negative number since it uses the 15th bit. - # Workaround: load 2^14-1, then increment. - CA 10MS - INCR A - EXTEND # Subtract the desired delay. - SU L - TS T4 # Set the interrupt timer - EXTEND - QXCH QPOP - - # Set SLEEPING to any non-zero value as a flag. - # 'A' happens to be a non-zero number, so use that. - TS SLEEPING - -SLEEPBZF CA SLEEPING - EXTEND - BZF SLEEPEND # Loop until SLEEPING flag is zero. - TCF SLEEPBZF -SLEEPEND RETURN - - -# Function that displays a pair of digits on the DSKY. -# Arguments: -# Position of pair on DSKY. -# Second digit. -# First digit. -DISPLAY EXTEND - QXCH QPOP - TCR POP # Pop first digit from stack. - INDEX A - CA DSKYDIG - EXTEND - MP DSKYC2D # Stored in L - TCR POP # Pop second digit from stack. - INDEX A - CA DSKYDIG - ADS L - TCR POP # Pop DSKY pair position from stack. - AD L - EXTEND - WRITE 010 - EXTEND - QXCH QPOP - RETURN - - -# The six equality operators start by pushing two values on the stack. -# Then several chained calls are made depending on which operator is needed. -# In all cases, if 0 is returned on the A register, then the operator is true. -# Calls for '==': -# TCR OP-EQ -# Calls for '!=': -# TCR OP-EQ -# TCR OP-NEG -# Calls for '<=': -# TCR OP-EQ -# TCR OP-LTE -# Calls for '>=': -# TCR OP-EQ -# TCR OP-GTE -# Calls for '<': -# TCR OP-EQ -# TCR OP-GTE -# TCR OP-NEG -# Calls for '>': -# TCR OP-EQ -# TCR OP-LTE -# TCR OP-NEG - - -# Base equality operator. -# Arguments: -# First value. -# Second value. -# Returns (on A): -# Zero if equal. -# Positive if first < second. -# Negative if first > second. -OP-EQ EXTEND - QXCH QPOP - TCR POP # Pop the second value. - # Subtract the first value on the stack from the second value. - EXTEND - INDEX STACKPTR - SU STACK - TCR DROP # Throw away the first value. - EXTEND - QXCH QPOP - RETURN - -# Suffix functions to OP-EQ. -# OP-LTE returns 0 if first '<=' second. -# OP-GTE returns 0 if first '>=' second. -OP-LTE COM -OP-GTE EXTEND - BZMF OP-0 # Return with 0. - TCF OP-1 # Return with 1. - -# Suffix function to OP-EQ, OP-LTE and OP-GTE. Reverses zero and non-zero. -OP-NEG EXTEND - BZF OP-1 -OP-0 CA NUM0 - RETURN -OP-1 CA NUM1 - RETURN - - -# Push the contents of the 'A' register onto the stack. -PUSH INCR STACKPTR - INDEX STACKPTR - TS STACK - RETURN - - -# POP: Pop the last value on the stack into the 'A' register. -# DROP: Drop the last value without returning it. -POP INDEX STACKPTR - CAE STACK -DROP EXTEND - DIM STACKPTR - RETURN - - -# Variables in memory. -SLEEPING = 061 # Flag indicating if we are busy-sleeping. -RAND = 062 # Random number (0 to RANDMAX inc) -RANDMAX = 063 # Maximum possible random number. -QPOP = 100 # Temporary spot for Q. -STACKPTR = 101 # Stack pointer. -STACK = 102 # Start of the stack. - -# Constants. -10MS OCT 37777 # 2^14-1 is 10 ms to T4/T5 overflow. -100MS OCT 37766 # 2^14-10 is 100 ms to T4/T5 overflow. - -NUM1 DEC 1 -NUM2 DEC 2 -NUM3 DEC 3 -NUM4 DEC 4 -NUM5 DEC 5 -NUM6 DEC 6 -NUM7 DEC 7 -NUM8 DEC 8 -NUM9 DEC 9 -NUM100 DEC 100 - -D14-15 DEC 12288 -# TODO ADD OTHER PAIRS - -DSKYDIG DEC 21 - DEC 3 - DEC 25 - DEC 27 - DEC 15 - DEC 30 - DEC 28 - DEC 19 - DEC 29 - DEC 31 -DSKYC2D DEC 32 - -# System Address Locations -A = 00 -L = 01 -Q = 02 -NUM0 = 07 -ARUPT = 10 -T4 = 27 -T5 = 30 -NEWJOB = 67 diff --git a/Apps/Blockly/Boolean-test.agc b/Apps/Blockly/Boolean-test.agc new file mode 100644 index 0000000..9b57630 --- /dev/null +++ b/Apps/Blockly/Boolean-test.agc @@ -0,0 +1,237 @@ + +# TEST: NOT + + CA NUM0 # NOT 0 is 1 + TCR BL-NOT + EXTEND + BZF TSBL-F + + CA NUM1 # NOT NOT 1 is 1 + TCR BL-NOT + TCR BL-NOT + EXTEND + BZF TSBL-F + + +# TEST: ==, !=, <, >, <=, >= + + TCR TSBL_33 # 3 == 3 + TCR MA-SU + TCR BL-NOT + EXTEND + BZF TSBL-F + + TCR TSBL_33 # 3 <= 3 + TCR MA-SU + TCR BL-GT + EXTEND + BZF TSBL-F + + TCR TSBL_33 # 3 >= 3 + TCR MA-SU + TCR BL-LT + EXTEND + BZF TSBL-F + + + TCR TSBL_00 # +0 == -0 + TCR MA-SU + TCR BL-NOT + EXTEND + BZF TSBL-F + + TCR TSBL_00 # +0 <= -0 + TCR MA-SU + TCR BL-GT + EXTEND + BZF TSBL-F + + TCR TSBL_00 # +0 >= -0 + TCR MA-SU + TCR BL-LT + EXTEND + BZF TSBL-F + + + TCR TSBL_36 # 3 != 6 + TCR MA-SU + EXTEND + BZF TSBL-F + + TCR TSBL_36 # 3 < 6 + TCR MA-SU + TCR BL-LT + TCR BL-NOT + EXTEND + BZF TSBL-F + + TCR TSBL_36 # 3 <= 6 + TCR MA-SU + TCR BL-GT + EXTEND + BZF TSBL-F + + + TCR TSBL_71 # 7 != 1 + TCR MA-SU + EXTEND + BZF TSBL-F + + TCR TSBL_71 # 7 > 1 + TCR MA-SU + TCR BL-GT + TCR BL-NOT + EXTEND + BZF TSBL-F + + TCR TSBL_71 # 7 >= 1 + TCR MA-SU + TCR BL-LT + EXTEND + BZF TSBL-F + + +# TEST: OR + + CA NUM0 # 0 OR 0 = 0 + TCR PUSH + CA NUM0 + TCR PUSH + TCR BL-OR + TCR BL-NOT + EXTEND + BZF TSBL-F + + CA NUM0 # 0 OR 1 = 1 + TCR PUSH + CA NUM1 + TCR PUSH + TCR BL-OR + EXTEND + BZF TSBL-F + + CA NUM1 # 1 OR 0 = 1 + TCR PUSH + CA NUM0 + TCR PUSH + TCR BL-OR + EXTEND + BZF TSBL-F + + CA NUM1 # 1 OR 1 = 1 + TCR PUSH + CA NUM1 + TCR PUSH + TCR BL-OR + EXTEND + BZF TSBL-F + + +# TEST: AND + + CA NUM0 # 0 AND 0 = 0 + TCR PUSH + CA NUM0 + TCR PUSH + TCR BL-AND + TCR BL-NOT + EXTEND + BZF TSBL-F + + CA NUM0 # 0 AND 1 = 0 + TCR PUSH + CA NUM1 + TCR PUSH + TCR BL-AND + TCR BL-NOT + EXTEND + BZF TSBL-F + + CA NUM1 # 1 AND 0 = 0 + TCR PUSH + CA NUM0 + TCR PUSH + TCR BL-AND + TCR BL-NOT + EXTEND + BZF TSBL-F + + CA NUM1 # 1 AND 1 = 1 + TCR PUSH + CA NUM1 + TCR PUSH + TCR BL-AND + EXTEND + BZF TSBL-F + + +# TEST: Conditional operator (a ? b : c) + + CA NUM4 # 0 ? 0 : 4 = 4 + TCR PUSH + CA NUM0 + TCR PUSH + CA NUM0 + TCR PUSH + TCR BL-COND + EXTEND + BZF TSBL-F + + CA NUM0 # 2 ? 4 : 0 = 4 + TCR PUSH + CA NUM4 + TCR PUSH + CA NUM2 + TCR PUSH + TCR BL-COND + EXTEND + BZF TSBL-F + + TCF TSBL-END # Skip execution past the private functions. + + +TSBL_33 EXTEND + QXCH L + CA NUM3 # Load 3 and 3 onto the stack. + TCR PUSH + CA NUM3 + TCR PUSH + EXTEND + QXCH L + RETURN + +TSBL_00 EXTEND + QXCH L + CA NUM0 # Load +0 and -0 onto the stack. + TCR PUSH + CA NUM0 + COM + TCR PUSH + EXTEND + QXCH L + RETURN + +TSBL_36 EXTEND + QXCH L + CA NUM3 # Load 3 and 6 onto the stack. + TCR PUSH + CA NUM6 + TCR PUSH + EXTEND + QXCH L + RETURN + +TSBL_71 EXTEND + QXCH L + CA NUM7 # Load 7 and 1 onto the stack. + TCR PUSH + CA NUM1 + TCR PUSH + EXTEND + QXCH L + RETURN + +TSBL-F TCF TSBL-F # Test failed. Trigger TC Trap. + + +TSBL-END NOOP diff --git a/Apps/Blockly/Boolean.agc b/Apps/Blockly/Boolean.agc new file mode 100644 index 0000000..3cb0ed3 --- /dev/null +++ b/Apps/Blockly/Boolean.agc @@ -0,0 +1,107 @@ +# The six equality operators start by pushing two values on the stack then +# calling MA-SU followed by various chained calls are made depending on which +# operator is needed. +# In all cases, if 0 is returned on the A register, then the operator is false. +# The true value may be any non-zero number. +# Calls for '==': +# TCR MA-SU +# TCR BL-NOT +# Calls for '!=': +# TCR MA-SU +# Calls for '<': +# TCR MA-SU +# TCR BL-LT +# Calls for '>': +# TCR MA-SU +# TCR BL-GT +# Calls for '<=': +# TCR MA-SU +# TCR BL-GT +# TCR BL-NOT +# Calls for '>=': +# TCR MA-SU +# TCR BL-LT +# TCR BL-NOT + + +# Suffix functions to MA-SU. +# BL-GT returns 1 if first '>' second. +# BL-LT returns 1 if first '<' second. +BL-GT COM +BL-LT EXTEND + BZMF BL-1 # Return with 1. + TCF BL-0 # Return with 0. + +# Reverses zero and non-zero. +BL-NOT EXTEND + BZF BL-1 +BL-0 CA NUM0 + RETURN +BL-1 CA NUM1 + RETURN + + +# OR operator. +# Stack arguments: +# First value. +# Second value. +# Returns (on A): +# Second value if it is non-zero, otherwise first value. +BL-OR EXTEND + QXCH QPOP + TCR POP # Pop the second value. + EXTEND + BZF BL-OR2 + # Second value was non-zero. Return it. + TCR DROP # Throw away the first value. + TCF BL-ORX + # Second value was a zero. Return the first value. +BL-OR2 TCR POP +BL-ORX EXTEND + QXCH QPOP + RETURN + + +# AND operator. +# Stack arguments: +# First value. +# Second value. +# Returns (on A): +# Second value if it is non-zero, otherwise first value. +BL-AND EXTEND + QXCH QPOP + TCR POP # Pop the second value. + EXTEND + BZF BL-AND0 + # Second value was non-zero. Return first value. + TCR POP + TCF BL-ANDX + # Second value was a zero. Return it. +BL-AND0 TCR DROP # Throw away the first value. +BL-ANDX EXTEND + QXCH QPOP + RETURN + + +# Inline conditional operator (a ? b : c). +# Stack arguments: +# If-false value (c). +# If-true value (b). +# Conditional value (a). +# Returns (on A): +# If-false value if conditional value is zero, otherwise if-true value. +BL-COND EXTEND + QXCH QPOP + TCR POP # Pop the conditional value. + EXTEND + BZF BL-COND0 + # Conditional value was non-zero. Return if-true value. + TCR POP # Pop the if-true value. + TCR DROP # Throw away the if-false value. + TCF BL-CONDX + # Conditional value was a zero. Return if-false value. +BL-COND0 TCR DROP # Throw away the if-true value. + TCR POP # Pop the if-false value. +BL-CONDX EXTEND + QXCH QPOP + RETURN diff --git a/Apps/Blockly/Main.agc b/Apps/Blockly/Main.agc new file mode 100644 index 0000000..6bcfd01 --- /dev/null +++ b/Apps/Blockly/Main.agc @@ -0,0 +1,199 @@ +# Copyright: Public domain. +# Filename: Blockly.agc +# Purpose: Framework to enable Blockly-based programming using higher-level +# blocks. +# Assembler: yaYUL +# Contact: Neil Fraser +# Contact: Luca Rosenberg + +# Interrupts, must have 4 lines per interrupt + SETLOC 4000 + + # Power up + CA 100MS # Schedule T5 soon. + TS T5 + TCF START + NOOP + + # T6 (interrupt #1) + RESUME + NOOP + NOOP + NOOP + + # T5 (interrupt #2) + XCH ARUPT + CA 100MS # Reschedule T5 soon. + TS T5 + TCF T5RUPT + + # T3 (interrupt #3) + RESUME + NOOP + NOOP + NOOP + + # T4 (interrupt #4) + XCH ARUPT + CA NUM0 # Clear SLEEPING flag. + TS SLEEPING + TCF T4RUPT + + # DSKY1 (interrupt #5) + XCH ARUPT + EXTEND + READ KEY15 + TCF KEYRUPT + + # DSKY2 (interrupt #6) + XCH ARUPT + EXTEND + READ KEY15 + TCF KEYRUPT + + # Uplink (interrupt #7) + RESUME + NOOP + NOOP + NOOP + + # Downlink (interrupt #8) + RESUME + NOOP + NOOP + NOOP + + # Radar (interrupt #9) + RESUME + NOOP + NOOP + NOOP + + # Hand controller (interrupt #10) + RESUME + NOOP + NOOP + NOOP + +# Initialize the stack pointer to be 0. +# This is the offset from the starting stack position. +START CA NUM0 + TS STACKPTR + +# Unit tests. +$Boolean-test.agc +$Math-test.agc + + # Wait a second. + CA NUM100 + TCR PUSH + TCR SLEEP + + TCR INPUT + + TCF START + + +# Code modules. +$Boolean.agc +$Math.agc + + +# Interrupt handlers that are slightly too long to fit in the jump table. +KEYRUPT TS INPUTING +T5RUPT CA NEWJOB # Tickle the night watchman. +T4RUPT XCH ARUPT + RESUME + + +# Function that waits for a DSKY keypress. +# Returns (on A): +# Keycode of keypress. +INPUT CA NUM1 # Set INPUTTING to -1 + COM + TS INPUTING + # Wait until INPUTTING isn't -1. +INPUT-WT CA INPUTING + INCR A + EXTEND + BZF INPUT-WT + RETURN + + +# Function that sleeps for the specified duration. +# Stack argument: +# Delay in 100ths of a second, thus 100 is 1 second. +SLEEP EXTEND + QXCH QPOP + TCR POP # Pop the delay from the stack. + TS L + # We want to load 2^14 (40,000 oct). But doing so gets treated + # as a negative number since it uses the 15th bit. + # Workaround: load 2^14-1, then increment. + CA 10MS + INCR A + EXTEND # Subtract the desired delay. + SU L + TS T4 # Set the interrupt timer + EXTEND + QXCH QPOP + + # Set SLEEPING to any non-zero value as a flag. + # 'A' happens to be a non-zero number, so use that. + TS SLEEPING + +SLEEPBZF CA SLEEPING + EXTEND + BZF SLEEPEND # Loop until SLEEPING flag is zero. + TCF SLEEPBZF +SLEEPEND RETURN + + +# Push the contents of the 'A' register onto the stack. +PUSH INCR STACKPTR + INDEX STACKPTR + TS STACK + RETURN + + +# POP: Pop the last value on the stack into the 'A' register. +# DROP: Drop the last value without returning it. +POP INDEX STACKPTR + CAE STACK +DROP EXTEND + DIM STACKPTR + RETURN + + +# Variables in memory. +SLEEPING = 061 # Flag indicating if we are busy-sleeping. +INPUTING = 062 # Waiting for a DSKY key press. +QPOP = 063 # Temporary spot for Q. +STACKPTR = 064 # Stack pointer, starts at 0. +STACK = 064 # Start address of stack (minus one). + +# Constants. +10MS OCT 37777 # 2^14-1 is 10 ms to T4/T5 overflow. +100MS OCT 37766 # 2^14-10 is 100 ms to T4/T5 overflow. + +NUM1 DEC 1 +NUM2 DEC 2 +NUM3 DEC 3 +NUM4 DEC 4 +NUM5 DEC 5 +NUM6 DEC 6 +NUM7 DEC 7 +NUM8 DEC 8 +NUM9 DEC 9 +NUM100 DEC 100 + +# System Address Locations +A = 00 +L = 01 +Q = 02 +NUM0 = 07 +ARUPT = 10 +KEY15 = 15 # I/O Channel 15 (DSKY keypad) +T4 = 27 +T5 = 30 +NEWJOB = 67 diff --git a/Apps/Blockly/Math-test.agc b/Apps/Blockly/Math-test.agc new file mode 100644 index 0000000..435f4b7 --- /dev/null +++ b/Apps/Blockly/Math-test.agc @@ -0,0 +1,83 @@ + +# TEST: ADD + + CA NUM1 # 1 + 2 = 3 + TCR PUSH + CA NUM2 + TCR PUSH + TCR MA-AD + # Diminish three times, checking each time it's not zero. + EXTEND + BZF TSMA-F + EXTEND + DIM A + EXTEND + BZF TSMA-F + EXTEND + DIM A + EXTEND + BZF TSMA-F + EXTEND + DIM A + EXTEND # Make sure it's now zero. + BZF TSMA-AD1 + TCF TSMA-F +TSMA-AD1 NOOP + + CA NUM3 # -3 + 3 = 0 + COM + TCR PUSH + CA NUM3 + TCR PUSH + TCR MA-AD + EXTEND # Make sure it's now zero. + BZF TSMA-AD2 + TCF TSMA-F +TSMA-AD2 NOOP + + +# TEST: SUBTRACT + + CA NUM5 # 5 - 3 = 2 + TCR PUSH + CA NUM3 + TCR PUSH + TCR MA-SU + # Diminish twice, checking each time it's not zero. + EXTEND + BZF TSMA-F + EXTEND + DIM A + EXTEND + BZF TSMA-F + EXTEND + DIM A + EXTEND # Make sure it's now zero. + BZF TSMA-SU1 + TCF TSMA-F +TSMA-SU1 NOOP + + +# TEST: MULTIPLY + + CA NUM2 # 2 * 3 = 6 + TCR PUSH + CA NUM3 + TCR PUSH + TCR MA-MP + TCR PUSH + CA NUM6 + TCR PUSH + TCR MA-SU + EXTEND # Make sure it's now zero. + BZF TSMA-MP1 + TCF TSMA-F +TSMA-MP1 NOOP + + + TCF TSMA-END # Skip execution past the private functions. + +TSMA-F TCF TSMA-F # Test failed. Trigger TC Trap. + + +TSMA-END NOOP diff --git a/Apps/Blockly/Math.agc b/Apps/Blockly/Math.agc new file mode 100644 index 0000000..4456cd3 --- /dev/null +++ b/Apps/Blockly/Math.agc @@ -0,0 +1,56 @@ + +# Addition. +# Stack arguments: +# First value. +# Second value. +# Returns (on A): +# Both values added. +MA-AD EXTEND + QXCH QPOP + TCR POP # Pop the second value. + # Add the first value on the stack to the second value. + INDEX STACKPTR + AD STACK + TCR DROP # Throw away the first value. + EXTEND + QXCH QPOP + RETURN + +# Subtraction. +# Stack arguments: +# First value. +# Second value. +# Returns (on A): +# First value minus second value. +MA-SU EXTEND + QXCH QPOP + TCR POP # Pop the second value. + # Subtract the first value on the stack from the second value. + EXTEND + INDEX STACKPTR + SU STACK + TCR DROP # Throw away the first value. + EXTEND + QXCH QPOP + RETURN + + +# Multiplication +# Stack arguments: +# First value. +# Second value. +# Returns (on A): +# Both values multiplied together. +# Uses L register. +MA-MP EXTEND + QXCH QPOP + TCR POP # Pop the second value. + # Multiply the first value on the stack with the second value. + EXTEND + INDEX STACKPTR + MP STACK + CA L + TCR DROP # Throw away the first value. + EXTEND + QXCH QPOP + RETURN diff --git a/Operators/SU.agc b/Operators/SU.agc index 088aba2..a588769 100644 --- a/Operators/SU.agc +++ b/Operators/SU.agc @@ -3,7 +3,8 @@ SETLOC 4000 INHINT - # SU subtracts a number from the 'A' register, must be in EraseableMem(0ct 0-1777) + # SU subtracts a number from the 'A' register, + # must be in Eraseable Memory (OCT 0-1777) CAF TWO # Load 2 into 'A' register. TS 1234 # Store 2 into memory location 1234. From 103528c9f74e41532353b02547cf7ecbaf7d03c4 Mon Sep 17 00:00:00 2001 From: NeilFraser Date: Sat, 28 Mar 2026 10:55:13 +0100 Subject: [PATCH 3/5] Improve testing. --- Apps/Blockly/Boolean-test.agc | 224 +++++++++++++++++++++------------- Apps/Blockly/Boolean.agc | 2 + Apps/Blockly/Main.agc | 42 +++---- Apps/Blockly/Math-test.agc | 71 +++-------- Apps/Blockly/Math.agc | 2 +- Apps/Blockly/Test.agc | 35 ++++++ 6 files changed, 217 insertions(+), 159 deletions(-) create mode 100644 Apps/Blockly/Test.agc diff --git a/Apps/Blockly/Boolean-test.agc b/Apps/Blockly/Boolean-test.agc index 9b57630..90cfe52 100644 --- a/Apps/Blockly/Boolean-test.agc +++ b/Apps/Blockly/Boolean-test.agc @@ -1,191 +1,248 @@ +# Unit tests for the Boolean functions. # TEST: NOT - CA NUM0 # NOT 0 is 1 + CA NUM0 # NOT 0 -> 1 TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM1 + TCR PUSH + TCR TS-EQUAL - CA NUM1 # NOT NOT 1 is 1 + CA NUM1 # NOT 1 -> 0 TCR BL-NOT + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL + + CA NUM6 # NOT 6 -> 0 TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL # TEST: ==, !=, <, >, <=, >= +# Although these tests only check for conditions that output 0, +# that's still comprehensive since half of them use BL-NOT. - TCR TSBL_33 # 3 == 3 + TCR TSBL_33 # 3 != 3 -> 0 TCR MA-SU - TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_33 # 3 <= 3 + TCR TSBL_33 # 3 > 3 -> 0 TCR MA-SU TCR BL-GT - EXTEND - BZF TSBL-F + TCR BL-NOT + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_33 # 3 >= 3 + TCR TSBL_33 # 3 < 3 -> 0 TCR MA-SU TCR BL-LT - EXTEND - BZF TSBL-F + TCR BL-NOT + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_00 # +0 == -0 + TCR TSBL_00 # +0 != -0 -> 0 TCR MA-SU - TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_00 # +0 <= -0 + TCR TSBL_00 # +0 > -0 -> 0 TCR MA-SU TCR BL-GT - EXTEND - BZF TSBL-F + TCR BL-NOT + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_00 # +0 >= -0 + TCR TSBL_00 # +0 < -0 -> 0 TCR MA-SU TCR BL-LT - EXTEND - BZF TSBL-F + TCR BL-NOT + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_36 # 3 != 6 + TCR TSBL_36 # 3 == 6 -> 0 TCR MA-SU - EXTEND - BZF TSBL-F + TCR BL-NOT + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_36 # 3 < 6 + TCR TSBL_36 # 3 >= 6 -> 0 TCR MA-SU TCR BL-LT - TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_36 # 3 <= 6 + TCR TSBL_36 # 3 > 6 -> 0 TCR MA-SU TCR BL-GT - EXTEND - BZF TSBL-F + TCR BL-NOT + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_71 # 7 != 1 + TCR TSBL_71 # 7 == 1 -> 0 TCR MA-SU - EXTEND - BZF TSBL-F + TCR BL-NOT + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_71 # 7 > 1 + TCR TSBL_71 # 7 <= 1 -> 0 TCR MA-SU TCR BL-GT - TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - TCR TSBL_71 # 7 >= 1 + TCR TSBL_71 # 7 < 1 -> 0 TCR MA-SU TCR BL-LT - EXTEND - BZF TSBL-F + TCR BL-NOT + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL # TEST: OR - CA NUM0 # 0 OR 0 = 0 + CA NUM0 # 0 OR 0 -> 0 TCR PUSH CA NUM0 TCR PUSH TCR BL-OR - TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - CA NUM0 # 0 OR 1 = 1 + CA NUM0 # 0 OR 1 -> 1 TCR PUSH CA NUM1 TCR PUSH TCR BL-OR - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM1 + TCR PUSH + TCR TS-EQUAL - CA NUM1 # 1 OR 0 = 1 + CA NUM1 # 1 OR 0 -> 1 TCR PUSH CA NUM0 TCR PUSH TCR BL-OR - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM1 + TCR PUSH + TCR TS-EQUAL - CA NUM1 # 1 OR 1 = 1 + CA NUM1 # 1 OR 1 -> 1 TCR PUSH CA NUM1 TCR PUSH TCR BL-OR - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM1 + TCR PUSH + TCR TS-EQUAL # TEST: AND - CA NUM0 # 0 AND 0 = 0 + CA NUM0 # 0 AND 0 -> 0 TCR PUSH CA NUM0 TCR PUSH TCR BL-AND - TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - CA NUM0 # 0 AND 1 = 0 + CA NUM0 # 0 AND 1 -> 0 TCR PUSH CA NUM1 TCR PUSH TCR BL-AND - TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - CA NUM1 # 1 AND 0 = 0 + CA NUM1 # 1 AND 0 -> 0 TCR PUSH CA NUM0 TCR PUSH TCR BL-AND - TCR BL-NOT - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL - CA NUM1 # 1 AND 1 = 1 + CA NUM1 # 1 AND 1 -> 1 TCR PUSH CA NUM1 TCR PUSH TCR BL-AND - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM1 + TCR PUSH + TCR TS-EQUAL # TEST: Conditional operator (a ? b : c) - CA NUM4 # 0 ? 0 : 4 = 4 + CA NUM7 # 0 ? 3 : 7 = 7 TCR PUSH - CA NUM0 + CA NUM3 TCR PUSH CA NUM0 TCR PUSH TCR BL-COND - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM7 + TCR PUSH + TCR TS-EQUAL - CA NUM0 # 2 ? 4 : 0 = 4 + CA NUM7 # 2 ? 3 : 7 = 3 TCR PUSH - CA NUM4 + CA NUM3 TCR PUSH CA NUM2 TCR PUSH TCR BL-COND - EXTEND - BZF TSBL-F + TCR PUSH + CA NUM3 + TCR PUSH + TCR TS-EQUAL TCF TSBL-END # Skip execution past the private functions. @@ -231,7 +288,4 @@ TSBL_71 EXTEND QXCH L RETURN -TSBL-F TCF TSBL-F # Test failed. Trigger TC Trap. - - TSBL-END NOOP diff --git a/Apps/Blockly/Boolean.agc b/Apps/Blockly/Boolean.agc index 3cb0ed3..0f4e470 100644 --- a/Apps/Blockly/Boolean.agc +++ b/Apps/Blockly/Boolean.agc @@ -25,6 +25,7 @@ # Suffix functions to MA-SU. +# Operates on the 'A' register, no need for the stack. # BL-GT returns 1 if first '>' second. # BL-LT returns 1 if first '<' second. BL-GT COM @@ -33,6 +34,7 @@ BL-LT EXTEND TCF BL-0 # Return with 0. # Reverses zero and non-zero. +# Operates on the 'A' register, no need for the stack. BL-NOT EXTEND BZF BL-1 BL-0 CA NUM0 diff --git a/Apps/Blockly/Main.agc b/Apps/Blockly/Main.agc index 6bcfd01..ccda5ed 100644 --- a/Apps/Blockly/Main.agc +++ b/Apps/Blockly/Main.agc @@ -81,8 +81,7 @@ START CA NUM0 TS STACKPTR # Unit tests. -$Boolean-test.agc -$Math-test.agc +$Test.agc # Wait a second. CA NUM100 @@ -150,6 +149,7 @@ SLEEPEND RETURN # Push the contents of the 'A' register onto the stack. +# No registers are affected. PUSH INCR STACKPTR INDEX STACKPTR TS STACK @@ -176,24 +176,24 @@ STACK = 064 # Start address of stack (minus one). 10MS OCT 37777 # 2^14-1 is 10 ms to T4/T5 overflow. 100MS OCT 37766 # 2^14-10 is 100 ms to T4/T5 overflow. -NUM1 DEC 1 -NUM2 DEC 2 -NUM3 DEC 3 -NUM4 DEC 4 -NUM5 DEC 5 -NUM6 DEC 6 -NUM7 DEC 7 -NUM8 DEC 8 -NUM9 DEC 9 -NUM100 DEC 100 +NUM1 DEC 1 +NUM2 DEC 2 +NUM3 DEC 3 +NUM4 DEC 4 +NUM5 DEC 5 +NUM6 DEC 6 +NUM7 DEC 7 +NUM8 DEC 8 +NUM9 DEC 9 +NUM100 DEC 100 # System Address Locations -A = 00 -L = 01 -Q = 02 -NUM0 = 07 -ARUPT = 10 -KEY15 = 15 # I/O Channel 15 (DSKY keypad) -T4 = 27 -T5 = 30 -NEWJOB = 67 +A = 00 +L = 01 +Q = 02 +NUM0 = 07 +ARUPT = 10 +KEY15 = 15 # I/O Channel 15 (DSKY keypad) +T4 = 27 +T5 = 30 +NEWJOB = 67 diff --git a/Apps/Blockly/Math-test.agc b/Apps/Blockly/Math-test.agc index 435f4b7..249c633 100644 --- a/Apps/Blockly/Math-test.agc +++ b/Apps/Blockly/Math-test.agc @@ -1,66 +1,45 @@ +# Unit tests for the Math functions. # TEST: ADD - CA NUM1 # 1 + 2 = 3 + CA NUM1 # 1 + 2 -> 3 TCR PUSH CA NUM2 TCR PUSH TCR MA-AD - # Diminish three times, checking each time it's not zero. - EXTEND - BZF TSMA-F - EXTEND - DIM A - EXTEND - BZF TSMA-F - EXTEND - DIM A - EXTEND - BZF TSMA-F - EXTEND - DIM A - EXTEND # Make sure it's now zero. - BZF TSMA-AD1 - TCF TSMA-F -TSMA-AD1 NOOP + TCR PUSH + CA NUM3 + TCR PUSH + TCR TS-EQUAL - CA NUM3 # -3 + 3 = 0 + CA NUM3 # -3 + 3 -> 0 COM TCR PUSH CA NUM3 TCR PUSH TCR MA-AD - EXTEND # Make sure it's now zero. - BZF TSMA-AD2 - TCF TSMA-F -TSMA-AD2 NOOP + TCR PUSH + CA NUM0 + TCR PUSH + TCR TS-EQUAL # TEST: SUBTRACT - CA NUM5 # 5 - 3 = 2 + CA NUM3 # 5 - 3 -> 2 TCR PUSH - CA NUM3 + CA NUM5 TCR PUSH TCR MA-SU - # Diminish twice, checking each time it's not zero. - EXTEND - BZF TSMA-F - EXTEND - DIM A - EXTEND - BZF TSMA-F - EXTEND - DIM A - EXTEND # Make sure it's now zero. - BZF TSMA-SU1 - TCF TSMA-F -TSMA-SU1 NOOP + TCR PUSH + CA NUM2 + TCR PUSH + TCR TS-EQUAL # TEST: MULTIPLY - CA NUM2 # 2 * 3 = 6 + CA NUM2 # 2 * 3 -> 6 TCR PUSH CA NUM3 TCR PUSH @@ -68,16 +47,4 @@ TSMA-SU1 NOOP TCR PUSH CA NUM6 TCR PUSH - TCR MA-SU - EXTEND # Make sure it's now zero. - BZF TSMA-MP1 - TCF TSMA-F -TSMA-MP1 NOOP - - - TCF TSMA-END # Skip execution past the private functions. - -TSMA-F TCF TSMA-F # Test failed. Trigger TC Trap. - - -TSMA-END NOOP + TCR TS-EQUAL diff --git a/Apps/Blockly/Math.agc b/Apps/Blockly/Math.agc index 4456cd3..088fa1b 100644 --- a/Apps/Blockly/Math.agc +++ b/Apps/Blockly/Math.agc @@ -21,7 +21,7 @@ MA-AD EXTEND # First value. # Second value. # Returns (on A): -# First value minus second value. +# Second value minus first value. MA-SU EXTEND QXCH QPOP TCR POP # Pop the second value. diff --git a/Apps/Blockly/Test.agc b/Apps/Blockly/Test.agc new file mode 100644 index 0000000..b338f42 --- /dev/null +++ b/Apps/Blockly/Test.agc @@ -0,0 +1,35 @@ +# Unit test framework. + +# Execute the tests. +$Boolean-test.agc +$Math-test.agc + +# To execute the tests, compile with yaYUL, then 'run' with yaAGC. +# If the screen fills up with alarms, then a test failed. +# Break the execution with ^C. +# If the current line is not TS-FAIL, then 'run' again and break again. +# Use 'info stack' to find the line of the failed test. It will be the first +# entry in the list that's in a *-test.agc file. + + TCF TS-END # Skip execution past the private functions. + +# This assertion function verifies that two values are equal. +# If they aren't, trigger a TC Trap. +# Stack arguments: +# First value. +# Second value. +TS-EQUAL EXTEND + QXCH L # Temporarily save the Q value into L + # The arguments for TS-EQUAL are the same as for MA-SU. + # So there's no need to touch the stack. + TCR MA-SU + TCR BL-NOT + EXTEND + BZF TS-FAIL + EXTEND + QXCH L + RETURN + +TS-FAIL TCR TS-FAIL # Test failed. Trigger TC Trap. + +TS-END NOOP From 086d46b41a7a54b658c3c1c5e2be9134e87aaf41 Mon Sep 17 00:00:00 2001 From: NeilFraser Date: Sun, 29 Mar 2026 23:01:39 +0200 Subject: [PATCH 4/5] Fix bug in INPUT that failed to return the key Also tighten up the code by using dead space in the jump table. --- Apps/Blockly/Main.agc | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/Apps/Blockly/Main.agc b/Apps/Blockly/Main.agc index ccda5ed..94b0bec 100644 --- a/Apps/Blockly/Main.agc +++ b/Apps/Blockly/Main.agc @@ -4,7 +4,7 @@ # blocks. # Assembler: yaYUL # Contact: Neil Fraser -# Contact: Luca Rosenberg +# Contact: Luca Rosenberg # Interrupts, must have 4 lines per interrupt SETLOC 4000 @@ -40,10 +40,10 @@ TCF T4RUPT # DSKY1 (interrupt #5) - XCH ARUPT - EXTEND - READ KEY15 - TCF KEYRUPT + NOOP # Fall through to DSKY2. + NOOP + NOOP + NOOP # DSKY2 (interrupt #6) XCH ARUPT @@ -53,15 +53,15 @@ # Uplink (interrupt #7) RESUME - NOOP - NOOP - NOOP +KEYRUPT TS INPUTING # Squeeze the remaining key handler in here. + XCH ARUPT + RESUME # Downlink (interrupt #8) RESUME - NOOP - NOOP - NOOP +T5RUPT CA NEWJOB # Tickle the night watchman. +T4RUPT XCH ARUPT + RESUME # Radar (interrupt #9) RESUME @@ -71,9 +71,9 @@ # Hand controller (interrupt #10) RESUME - NOOP - NOOP - NOOP + #NOOP # Save three words by allowing START to move up. + #NOOP + #NOOP # Initialize the stack pointer to be 0. # This is the offset from the starting stack position. @@ -98,24 +98,18 @@ $Boolean.agc $Math.agc -# Interrupt handlers that are slightly too long to fit in the jump table. -KEYRUPT TS INPUTING -T5RUPT CA NEWJOB # Tickle the night watchman. -T4RUPT XCH ARUPT - RESUME - - # Function that waits for a DSKY keypress. # Returns (on A): # Keycode of keypress. INPUT CA NUM1 # Set INPUTTING to -1 COM TS INPUTING - # Wait until INPUTTING isn't -1. + # Wait until INPUTING isn't -1. INPUT-WT CA INPUTING INCR A EXTEND BZF INPUT-WT + CA INPUTING RETURN From 22505f75bc2e9f6feec9bcf8c6a59d90cd3c55f3 Mon Sep 17 00:00:00 2001 From: NeilFraser Date: Sun, 29 Mar 2026 23:14:03 +0200 Subject: [PATCH 5/5] Update comments --- Apps/Blockly/Boolean.agc | 4 +++- Apps/Blockly/Main.agc | 2 +- Apps/Blockly/Math.agc | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Apps/Blockly/Boolean.agc b/Apps/Blockly/Boolean.agc index 0f4e470..5016087 100644 --- a/Apps/Blockly/Boolean.agc +++ b/Apps/Blockly/Boolean.agc @@ -1,3 +1,5 @@ +# Boolean functions. + # The six equality operators start by pushing two values on the stack then # calling MA-SU followed by various chained calls are made depending on which # operator is needed. @@ -69,7 +71,7 @@ BL-ORX EXTEND # First value. # Second value. # Returns (on A): -# Second value if it is non-zero, otherwise first value. +# Second value if it is zero, otherwise first value. BL-AND EXTEND QXCH QPOP TCR POP # Pop the second value. diff --git a/Apps/Blockly/Main.agc b/Apps/Blockly/Main.agc index 94b0bec..99b65bd 100644 --- a/Apps/Blockly/Main.agc +++ b/Apps/Blockly/Main.agc @@ -1,5 +1,5 @@ # Copyright: Public domain. -# Filename: Blockly.agc +# Filename: Main.agc # Purpose: Framework to enable Blockly-based programming using higher-level # blocks. # Assembler: yaYUL diff --git a/Apps/Blockly/Math.agc b/Apps/Blockly/Math.agc index 088fa1b..a3c4560 100644 --- a/Apps/Blockly/Math.agc +++ b/Apps/Blockly/Math.agc @@ -1,3 +1,4 @@ +# Math functions. # Addition. # Stack arguments: