From 333b605b2afd472b823aeda0adf0e8b1ea9843c0 Mon Sep 17 00:00:00 2001 From: fishsoupisgood Date: Mon, 27 May 2019 02:41:51 +0100 Subject: initial commit from asl-1.41r8.tar.gz --- tests/t_bas52/asflags | 0 tests/t_bas52/bas52.clk | 18 + tests/t_bas52/bas52.fp | 1616 ++++++++++++++++ tests/t_bas52/bas52.out | 75 + tests/t_bas52/bas52.pgm | 125 ++ tests/t_bas52/bas52.pwm | 25 + tests/t_bas52/bas52.rst | 111 ++ tests/t_bas52/bas52.tl | 16 + tests/t_bas52/look52.inc | 779 ++++++++ tests/t_bas52/t_bas52.asm | 4644 +++++++++++++++++++++++++++++++++++++++++++++ tests/t_bas52/t_bas52.doc | 11 + tests/t_bas52/t_bas52.inc | 2 + tests/t_bas52/t_bas52.ori | Bin 0 -> 8192 bytes 13 files changed, 7422 insertions(+) create mode 100644 tests/t_bas52/asflags create mode 100644 tests/t_bas52/bas52.clk create mode 100644 tests/t_bas52/bas52.fp create mode 100644 tests/t_bas52/bas52.out create mode 100644 tests/t_bas52/bas52.pgm create mode 100644 tests/t_bas52/bas52.pwm create mode 100644 tests/t_bas52/bas52.rst create mode 100644 tests/t_bas52/bas52.tl create mode 100644 tests/t_bas52/look52.inc create mode 100644 tests/t_bas52/t_bas52.asm create mode 100644 tests/t_bas52/t_bas52.doc create mode 100644 tests/t_bas52/t_bas52.inc create mode 100644 tests/t_bas52/t_bas52.ori (limited to 'tests/t_bas52') diff --git a/tests/t_bas52/asflags b/tests/t_bas52/asflags new file mode 100644 index 0000000..e69de29 diff --git a/tests/t_bas52/bas52.clk b/tests/t_bas52/bas52.clk new file mode 100644 index 0000000..d019e11 --- /dev/null +++ b/tests/t_bas52/bas52.clk @@ -0,0 +1,18 @@ + ;************************************************************** + ; + ; The statement action routine - CLOCK + ; + ;************************************************************** + ; +SCLOCK: ACALL OTST ;GET CHARACTER AFTER CLOCK TOKEN + CLR ET0 + CLR C_BIT + JNC SC_R ;EXIT IF A ZERO + ANL TMOD,#0F0H ;SET UP THE MODE + SETB C_BIT ;USER INTERRUPTS + ORL IE,#82H ;ENABLE ET0 AND EA + SETB TR0 ;TURN ON THE TIMER + ; +SC_R: RET + ; + diff --git a/tests/t_bas52/bas52.fp b/tests/t_bas52/bas52.fp new file mode 100644 index 0000000..c8a137c --- /dev/null +++ b/tests/t_bas52/bas52.fp @@ -0,0 +1,1616 @@ +;************************************************************ +; +; This is a complete BCD floating point package for the 8051 micro- +; controller. It provides 8 digits of accuracy with exponents that +; range from +127 to -127. The mantissa is in packed BCD, while the +; exponent is expressed in pseudo-twos complement. A ZERO exponent +; is used to express the number ZERO. An exponent value of 80H or +; greater than means the exponent is positive, i.e. 80H = E 0, +; 81H = E+1, 82H = E+2 and so on. If the exponent is 7FH or less, +; the exponent is negative, 7FH = E-1, 7EH = E-2, and so on. +; ALL NUMBERS ARE ASSUMED TO BE NORMALIZED and all results are +; normalized after calculation. A normalized mantissa is >=.10 and +; <=.99999999. +; +; The numbers in memory assumed to be stored as follows: +; +; EXPONENT OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE +; SIGN OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-1 +; DIGIT 78 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-2 +; DIGIT 56 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-3 +; DIGIT 34 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-4 +; DIGIT 12 OF ARGUMENT 2 = VALUE OF ARG_STACK+FP_NUMBER_SIZE-5 +; +; EXPONENT OF ARGUMENT 1 = VALUE OF ARG_STACK +; SIGN OF ARGUMENT 1 = VALUE OF ARG_STACK-1 +; DIGIT 78 OF ARGUMENT 1 = VALUE OF ARG_STACK-2 +; DIGIT 56 OF ARGUMENT 1 = VALUE OF ARG_STACK-3 +; DIGIT 34 OF ARGUMENT 1 = VALUE OF ARG_STACK-4 +; DIGIT 12 OF ARGUMENT 1 = VALUE OF ARG_STACK-5 +; +; The operations are performed thusly: +; +; ARG_STACK+FP_NUMBER_SIZE = ARG_STACK+FP_NUMBER_SIZE # ARG_STACK +; +; Which is ARGUMENT 2 = ARGUMENT 2 # ARGUMENT 1 +; +; Where # can be ADD, SUBTRACT, MULTIPLY OR DIVIDE. +; +; Note that the stack gets popped after an operation. +; +; The FP_COMP instruction POPS the ARG_STACK TWICE and returns status. +; +;********************************************************************** +; + + segment code + newpage + section float ; protect symbols +;********************************************************************** +; +; STATUS ON RETURN - After performing an operation (+, -, *, /) +; the accumulator contains the following status +; +; ACCUMULATOR - BIT 0 - FLOATING POINT UNDERFLOW OCCURED +; +; - BIT 1 - FLOATING POINT OVERFLOW OCCURED +; +; - BIT 2 - RESULT WAS ZER0 +; +; - BIT 3 - DIVIDE BY ZERO ATTEMPTED +; +; - BIT 4 - NOT USED, 0 RETURNED +; +; - BIT 5 - NOT USED, 0 RETURNED +; +; - BIT 6 - NOT USED, 0 RETURNED +; +; - BIT 7 - NOT USED, 0 RETURNED +; +; NOTE: When underflow occures, a ZERO result is returned. +; When overflow or divide by zero occures, a result of +; .99999999 E+127 is returned and it is up to the user +; to handle these conditions as needed in the program. +; +; NOTE: The Compare instruction returns F0 = 0 if ARG 1 = ARG 2 +; and returns a CARRY FLAG = 1 if ARG 1 is > ARG 2 +; +;*********************************************************************** +; + newpage +;*********************************************************************** +; +; The following values MUST be provided by the user +; +;*********************************************************************** +; +ARG_STACK EQU 9 ;ARGUMENT STACK POINTER +ARG_STACK_PAGE EQU 1 +FORMAT EQU 23 ;LOCATION OF OUTPUT FORMAT BYTE +OUTPUT EQU 1990H ;CALL LOCATION TO OUTPUT A CHARACTER +CONVT EQU 58H ;LOCATION TO CONVERT NUMBERS +INTGRC BIT 25 ;BIT SET IF INTGER ERROR +ZSURP BIT 54 ;ZERO SUPRESSION FOR HEX PRINT +; +;*********************************************************************** +; +; The following equates are used internally +; +;*********************************************************************** +; +FP_NUMBER_SIZE EQU 6 +DIGIT EQU FP_NUMBER_SIZE-2 +R0B0 EQU 0 +R1B0 EQU 1 +UNDERFLOW EQU 0 +ACC_UNDERFLOW BIT ACC.0 ; ******AA added +OVERFLOW EQU 1 +ACC_OVERFLOW BIT ACC.1 ; ******AA added +ZERO EQU 2 +ACC_ZERO BIT ACC.2 ; ******AA added +ZERO_DIVIDE EQU 3 +ACC_ZERO_DIVIDE BIT ACC.3 ; ******AA added +; +;*********************************************************************** + newpage + ;************************************************************** + ; + ; The following internal locations are used by the math pack + ; ordering is important and the FP_DIGITS must be bit + ; addressable + ; + ;*************************************************************** + ; +FP_STATUS EQU 28H ;NOT USED +FP_TEMP EQU FP_STATUS+1 ;NOT USED +FP_CARRY SFRB FP_STATUS+2 ;USED FOR BITS ******AA EQU-->SFRB +ADD_IN BIT 35 ;DCMPXZ IN BASIC BACKAGE +XSIGN BIT FP_CARRY.0 +FOUND_RADIX BIT FP_CARRY.1 +FIRST_RADIX BIT FP_CARRY.2 +DONE_LOAD BIT FP_CARRY.3 +FP_DIG12 EQU FP_CARRY+1 +FP_DIG34 EQU FP_CARRY+2 +FP_DIG56 EQU FP_CARRY+3 +FP_DIG78 EQU FP_CARRY+4 +FP_SIGN SFRB FP_CARRY+5 ; ******AA EQU-->SFRB +MSIGN BIT FP_SIGN.0 +FP_EXP EQU FP_CARRY+6 +FP_NIB1 EQU FP_DIG12 +FP_NIB2 EQU FP_NIB1+1 +FP_NIB3 EQU FP_NIB1+2 +FP_NIB4 EQU FP_NIB1+3 +FP_NIB5 EQU FP_NIB1+4 +FP_NIB6 EQU FP_NIB1+5 +FP_NIB7 EQU FP_NIB1+6 +FP_NIB8 EQU FP_NIB1+7 +FP_ACCX EQU FP_NIB1+8 +FP_ACCC EQU FP_NIB1+9 +FP_ACC1 EQU FP_NIB1+10 +FP_ACC2 EQU FP_NIB1+11 +FP_ACC3 EQU FP_NIB1+12 +FP_ACC4 EQU FP_NIB1+13 +FP_ACC5 EQU FP_NIB1+14 +FP_ACC6 EQU FP_NIB1+15 +FP_ACC7 EQU FP_NIB1+16 +FP_ACC8 EQU FP_NIB1+17 +FP_ACCS EQU FP_NIB1+18 + ; + newpage + ORG 1993H + ; + ;************************************************************** + ; + ; The floating point entry points and jump table + ; + ;************************************************************** + ; + AJMP FLOATING_ADD + AJMP FLOATING_SUB + AJMP FLOATING_COMP + AJMP FLOATING_MUL + AJMP FLOATING_DIV + AJMP HEXSCAN + AJMP FLOATING_POINT_INPUT + AJMP FLOATING_POINT_OUTPUT + AJMP CONVERT_BINARY_TO_ASCII_STRING + AJMP CONVERT_ASCII_STRING_TO_BINARY + AJMP MULNUM10 + AJMP HEXOUT + AJMP PUSHR2R0 + ; + newpage + ; +FLOATING_SUB: + ; + MOV P2,#ARG_STACK_PAGE + MOV R0,ARG_STACK + DEC R0 ;POINT TO SIGN + MOVX A,@R0 ;READ SIGN + CPL ACC.0 + MOVX @R0,A + ; + ;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + ; +FLOATING_ADD: + ; + ;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + ; + ; + ACALL MDES1 ;R7=TOS EXP, R6=TOS-1 EXP, R4=TOS SIGN + ;R3=TOS-1 SIGN, OPERATION IS R1 # R0 + ; + MOV A,R7 ;GET TOS EXPONENT + JZ POP_AND_EXIT ;IF TOS=0 THEN POP AND EXIT + CJNE R6,#0,LOAD1 ;CLEAR CARRY EXIT IF ZERO + ; + ;************************************************************** + ; +SWAP_AND_EXIT: ; Swap external args and return + ; + ;************************************************************** + ; + ACALL LOAD_POINTERS + MOV R7,#FP_NUMBER_SIZE + ; +SE1: MOVX A,@R0 ;SWAP THE ARGUMENTS + MOVX @R1,A + DEC R0 + DEC R1 + DJNZ R7,SE1 + ; +POP_AND_EXIT: + ; + MOV A,ARG_STACK ;POP THE STACK + ADD A,#FP_NUMBER_SIZE + MOV ARG_STACK,A + CLR A + RET + ; + ; +LOAD1: SUBB A,R6 ;A = ARG 1 EXP - ARG 2 EXP + MOV FP_EXP,R7 ;SAVE EXPONENT AND SIGN + MOV FP_SIGN,R4 + JNC LOAD2 ;ARG1 EXPONENT IS LARGER OR SAME + MOV FP_EXP,R6 + MOV FP_SIGN,R3 + CPL A + INC A ;COMPENSATE FOR EXP DELTA + XCH A,R0 ;FORCE R0 TO POINT AT THE LARGEST + XCH A,R1 ;EXPONENT + XCH A,R0 + ; +LOAD2: MOV R7,A ;SAVE THE EXPONENT DELTA IN R7 + CLR ADD_IN + CJNE R5,#0,$+5 + SETB ADD_IN + ; + newpage + ; Load the R1 mantissa + ; + ACALL LOADR1_MANTISSA ;LOAD THE SMALLEST NUMBER + ; + ; Now align the number to the delta exponent + ; R4 points to the string of the last digits lost + ; + CJNE R7,#DIGIT+DIGIT+3,$+3 + JC $+4 + MOV R7,#DIGIT+DIGIT+2 + ; + MOV FP_CARRY,#00 ;CLEAR THE CARRY + ACALL RIGHT ;SHIFT THE NUMBER + ; + ; Set up for addition and subtraction + ; + MOV R7,#DIGIT ;LOOP COUNT + MOV R1,#FP_DIG78 + MOV A,#9EH + CLR C + SUBB A,R4 + DA A + XCH A,R4 + JNZ $+3 + MOV R4,A + CJNE A,#50H,$+3 ;TEST FOR SUBTRACTION + JNB ADD_IN,SUBLP ;DO SUBTRACTION IF NO ADD_IN + CPL C ;FLIP CARRY FOR ADDITION + ACALL ADDLP ;DO ADDITION + ; + JNC ADD_R + INC FP_CARRY + MOV R7,#1 + ACALL RIGHT + ACALL INC_FP_EXP ;SHIFT AND BUMP EXPONENT + ; +ADD_R: AJMP STORE_ALIGN_TEST_AND_EXIT + ; +ADDLP: MOVX A,@R0 + ADDC A,@R1 + DA A + MOV @R1,A + DEC R0 + DEC R1 + DJNZ R7,ADDLP ;LOOP UNTIL DONE + RET + ; + newpage + ; +SUBLP: MOVX A,@R0 ;NOW DO SUBTRACTION + MOV R6,A + CLR A + ADDC A,#99H + SUBB A,@R1 + ADD A,R6 + DA A + MOV @R1,A + DEC R0 + DEC R1 + DJNZ R7,SUBLP + JC FSUB6 + ; + newpage + ; + ; Need to complement the result and sign because the floating + ; point accumulator mantissa was larger than the external + ; memory and their signs were equal. + ; + CPL FP_SIGN.0 + MOV R1,#FP_DIG78 + MOV R7,#DIGIT ;LOOP COUNT + ; +FSUB5: MOV A,#9AH + SUBB A,@R1 + ADD A,#0 + DA A + MOV @R1,A + DEC R1 + CPL C + DJNZ R7,FSUB5 ;LOOP + ; + ; Now see how many zeros their are + ; +FSUB6: MOV R0,#FP_DIG12 + MOV R7,#0 + ; +FSUB7: MOV A,@R0 + JNZ FSUB8 + INC R7 + INC R7 + INC R0 + CJNE R0,#FP_SIGN,FSUB7 + AJMP ZERO_AND_EXIT + ; +FSUB8: CJNE A,#10H,$+3 + JNC FSUB9 + INC R7 + ; + ; Now R7 has the number of leading zeros in the FP ACC + ; +FSUB9: MOV A,FP_EXP ;GET THE OLD EXPONENT + CLR C + SUBB A,R7 ;SUBTRACT FROM THE NUMBER OF ZEROS + JZ FSUB10 + JC FSUB10 + ; + MOV FP_EXP,A ;SAVE THE NEW EXPONENT + ; + ACALL LEFT1 ;SHIFT THE FP ACC + MOV FP_CARRY,#0 + AJMP STORE_ALIGN_TEST_AND_EXIT + ; +FSUB10: AJMP UNDERFLOW_AND_EXIT + ; + newpage + ;*************************************************************** + ; +FLOATING_COMP: ; Compare two floating point numbers + ; used for relational operations and is faster + ; than subtraction. ON RETURN, The carry is set + ; if ARG1 is > ARG2, else carry is not set + ; if ARG1 = ARG2, F0 gets set + ; + ;*************************************************************** + ; + ACALL MDES1 ;SET UP THE REGISTERS + MOV A,ARG_STACK + ADD A,#FP_NUMBER_SIZE+FP_NUMBER_SIZE + MOV ARG_STACK,A ;POP THE STACK TWICE, CLEAR THE CARRY + MOV A,R6 ;CHECK OUT EXPONENTS + CLR F0 + SUBB A,R7 + JZ EXPONENTS_EQUAL + JC ARG1_EXP_IS_LARGER + ; + ; Now the ARG2 EXPONENT is > ARG1 EXPONENT + ; +SIGNS_DIFFERENT: + ; + MOV A,R3 ;SEE IF SIGN OF ARG2 IS POSITIVE + SJMP $+3 + ; +ARG1_EXP_IS_LARGER: + ; + MOV A,R4 ;GET THE SIGN OF ARG1 EXPONENT + JZ $+3 + CPL C + RET + ; +EXPONENTS_EQUAL: + ; + ; First, test the sign, then the mantissa + ; + CJNE R5,#0,SIGNS_DIFFERENT + ; +BOTH_PLUS: + ; + MOV R7,#DIGIT ;POINT AT MS DIGIT + DEC R0 + DEC R0 + DEC R0 + DEC R1 + DEC R1 + DEC R1 + ; + ; Now do the compare + ; +CLOOP: MOVX A,@R0 + MOV R6,A + MOVX A,@R1 + SUBB A,R6 + JNZ ARG1_EXP_IS_LARGER + INC R0 + INC R1 + DJNZ R7,CLOOP + ; + ; If here, the numbers are the same, the carry is cleared + ; + SETB F0 + RET ;EXIT WITH EQUAL + ; + newpage +;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +; +FLOATING_MUL: ; Floating point multiply +; +;MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +; + ACALL MUL_DIV_EXP_AND_SIGN + ; + ; check for zero exponents + ; + CJNE R6,#00,$+5 ;ARG 2 EXP ZERO? + AJMP ZERO_AND_EXIT + ; + ; calculate the exponent + ; +FMUL1: MOV FP_SIGN,R5 ;SAVE THE SIGN, IN CASE OF FAILURE + ; + MOV A,R7 + JZ FMUL1-2 + ADD A,R6 ;ADD THE EXPONENTS + JB ACC.7,FMUL_OVER + JBC CY,FMUL2 ;SEE IF CARRY IS SET + ; + AJMP UNDERFLOW_AND_EXIT + ; +FMUL_OVER: + ; + JNC FMUL2 ;OK IF SET + ; +FOV: AJMP OVERFLOW_AND_EXIT + ; +FMUL2: SUBB A,#129 ;SUBTRACT THE EXPONENT BIAS + MOV R6,A ;SAVE IT FOR LATER + ; + ; Unpack and load R0 + ; + ACALL UNPACK_R0 + ; + ; Now set up for loop multiply + ; + MOV R3,#DIGIT + MOV R4,R1B0 + ; + newpage + ; + ; Now, do the multiply and accumulate the product + ; +FMUL3: MOV R1B0,R4 + MOVX A,@R1 + MOV R2,A + ACALL MUL_NIBBLE + ; + MOV A,R2 + SWAP A + ACALL MUL_NIBBLE + DEC R4 + DJNZ R3,FMUL3 + ; + ; Now, pack and restore the sign + ; + MOV FP_EXP,R6 + MOV FP_SIGN,R5 + AJMP PACK ;FINISH IT OFF + ; + newpage + ;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + ; +FLOATING_DIV: + ; + ;DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + ; + ACALL MDES1 + ; + ; Check the exponents + ; + MOV FP_SIGN,R5 ;SAVE THE SIGN + CJNE R7,#0,DIV0 ;CLEARS THE CARRY + ACALL OVERFLOW_AND_EXIT + CLR A + SETB ACC_ZERO_DIVIDE + RET + ; +DIV0: MOV A,R6 ;GET EXPONENT + JZ FMUL1-2 ;EXIT IF ZERO + SUBB A,R7 ;DELTA EXPONENT + JB ACC.7,D_UNDER + JNC DIV3 + AJMP UNDERFLOW_AND_EXIT + ; +D_UNDER:JNC FOV + ; +DIV3: ADD A,#129 ;CORRECTLY BIAS THE EXPONENT + MOV FP_EXP,A ;SAVE THE EXPONENT + ACALL LOADR1_MANTISSA ;LOAD THE DIVIDED + ; + MOV R2,#FP_ACCC ;SAVE LOCATION + MOV R3,R0B0 ;SAVE POINTER IN R3 + MOV FP_CARRY,#0 ;ZERO CARRY BYTE + ; +DIV4: MOV R5,#0FFH ;LOOP COUNT + SETB C + ; +DIV5: MOV R0B0,R3 ;RESTORE THE EXTERNAL POINTER + MOV R1,#FP_DIG78 ;SET UP INTERNAL POINTER + MOV R7,#DIGIT ;LOOP COUNT + JNC DIV7 ;EXIT IF NO CARRY + ; +DIV6: MOVX A,@R0 ;DO ACCUMLATION + MOV R6,A + CLR A + ADDC A,#99H + SUBB A,R6 + ADD A,@R1 + DA A + MOV @R1,A + DEC R0 + DEC R1 + DJNZ R7,DIV6 ;LOOP + ; + INC R5 ;SUBTRACT COUNTER + JC DIV5 ;KEEP LOOPING IF CARRY + MOV A,@R1 ;GET CARRY + SUBB A,#1 ;CARRY IS CLEARED + MOV @R1,A ;SAVE CARRY DIGIT + CPL C + SJMP DIV5 ;LOOP + ; + ; Restore the result if carry was found + ; +DIV7: ACALL ADDLP ;ADD NUMBER BACK + MOV @R1,#0 ;CLEAR CARRY + MOV R0B0,R2 ;GET SAVE COUNTER + MOV @R0,5 ;SAVE COUNT BYTE + ; + INC R2 ;ADJUST SAVE COUNTER + MOV R7,#1 ;BUMP DIVIDEND + ACALL LEFT + CJNE R2,#FP_ACC8+2,DIV4 + ; + DJNZ FP_EXP,DIV8 + AJMP UNDERFLOW_AND_EXIT + ; +DIV8: MOV FP_CARRY,#0 + ; + newpage + ;*************************************************************** + ; +PACK: ; Pack the mantissa + ; + ;*************************************************************** + ; + ; First, set up the pointers + ; + MOV R0,#FP_ACCC + MOV A,@R0 ;GET FP_ACCC + MOV R6,A ;SAVE FOR ZERO COUNT + JZ PACK0 ;JUMP OVER IF ZERO + ACALL INC_FP_EXP ;BUMP THE EXPONENT + DEC R0 + ; +PACK0: INC R0 ;POINT AT FP_ACC1 + ; +PACK1: MOV A,#8 ;ADJUST NIBBLE POINTER + MOV R1,A + ADD A,R0 + MOV R0,A + CJNE @R0,#5,$+3 ;SEE IF ADJUSTING NEEDED + JC PACK3+1 + ; +PACK2: SETB C + CLR A + DEC R0 + ADDC A,@R0 + DA A + XCHD A,@R0 ;SAVE THE VALUE + JNB ACC.4,PACK3 + DJNZ R1,PACK2 + ; + DEC R0 + MOV @R0,#1 + ACALL INC_FP_EXP + SJMP PACK4 + ; +PACK3: DEC R1 + MOV A,R1 + CLR C + XCH A,R0 + SUBB A,R0 + MOV R0,A + ; +PACK4: MOV R1,#FP_DIG12 + ; + ; Now, pack + ; +PLOOP: MOV A,@R0 + SWAP A ;FLIP THE DIGITS + INC R0 + XCHD A,@R0 + ORL 6,A ;ACCUMULATE THE OR'ED DIGITS + MOV @R1,A + INC R0 + INC R1 + CJNE R1,#FP_SIGN,PLOOP + MOV A,R6 + JNZ STORE_ALIGN_TEST_AND_EXIT + MOV FP_EXP,#0 ;ZERO EXPONENT + ; + ;************************************************************** + ; +STORE_ALIGN_TEST_AND_EXIT: ;Save the number align carry and exit + ; + ;************************************************************** + ; + ACALL LOAD_POINTERS + MOV ARG_STACK,R1 ;SET UP THE NEW STACK + MOV R0,#FP_EXP + ; + ; Now load the numbers + ; +STORE2: MOV A,@R0 + MOVX @R1,A ;SAVE THE NUMBER + DEC R0 + DEC R1 + CJNE R0,#FP_CARRY,STORE2 + ; + CLR A ;NO ERRORS + ; +PRET: RET ;EXIT + ; + newpage +INC_FP_EXP: + ; + INC FP_EXP + MOV A,FP_EXP + JNZ PRET ;EXIT IF NOT ZERO + POP ACC ;WASTE THE CALLING STACK + POP ACC + AJMP OVERFLOW_AND_EXIT + ; +;*********************************************************************** +; +UNPACK_R0: ; Unpack BCD digits and load into nibble locations +; +;*********************************************************************** + ; + PUSH R1B0 + MOV R1,#FP_NIB8 + ; +ULOOP: MOVX A,@R0 + ANL A,#0FH + MOV @R1,A ;SAVE THE NIBBLE + MOVX A,@R0 + SWAP A + ANL A,#0FH + DEC R1 + MOV @R1,A ;SAVE THE NIBBLE AGAIN + DEC R0 + DEC R1 + CJNE R1,#FP_NIB1-1,ULOOP + ; + POP R1B0 + ; +LOAD7: RET + ; + newpage + ;************************************************************** + ; +OVERFLOW_AND_EXIT: ;LOAD 99999999 E+127, SET OV BIT, AND EXIT + ; + ;************************************************************** + ; + MOV R0,#FP_DIG78 + MOV A,#99H + ; +OVE1: MOV @R0,A + DEC R0 + CJNE R0,#FP_CARRY,OVE1 + ; + MOV FP_EXP,#0FFH + ACALL STORE_ALIGN_TEST_AND_EXIT + ; + SETB ACC_OVERFLOW ; ******AA + RET + ; + newpage + ;************************************************************** + ; +UNDERFLOW_AND_EXIT: ;LOAD 0, SET UF BIT, AND EXIT + ; + ;************************************************************** + ; + ACALL ZERO_AND_EXIT + CLR A + SETB ACC_UNDERFLOW ; ******AA + RET + ; + ;************************************************************** + ; +ZERO_AND_EXIT: ;LOAD 0, SET ZERO BIT, AND EXIT + ; + ;************************************************************** + ; + ACALL FP_CLEAR + ACALL STORE_ALIGN_TEST_AND_EXIT + SETB ACC_ZERO ; ******AA + RET ;EXIT + ; + ;************************************************************** + ; +FP_CLEAR: + ; + ; Clear internal storage + ; + ;************************************************************** + ; + CLR A + MOV R0,#FP_ACC8+1 + ; +FPC1: MOV @R0,A + DEC R0 + CJNE R0,#FP_TEMP,FPC1 + RET + ; + newpage + ;************************************************************** + ; +RIGHT: ; Shift ACCUMULATOR RIGHT the number of nibbles in R7 + ; Save the shifted values in R4 if SAVE_ROUND is set + ; + ;************************************************************** + ; + MOV R4,#0 ;IN CASE OF NO SHIFT + ; +RIGHT1: CLR C + MOV A,R7 ;GET THE DIGITS TO SHIFT + JZ RIGHT5-1 ;EXIT IF ZERO + SUBB A,#2 ;TWO TO DO? + JNC RIGHT5 ;SHIFT TWO NIBBLES + ; + ; Swap one nibble then exit + ; +RIGHT3: PUSH R0B0 ;SAVE POINTER REGISTER + PUSH R1B0 + ; + MOV R1,#FP_DIG78 ;LOAD THE POINTERS + MOV R0,#FP_DIG56 + MOV A,R4 ;GET THE OVERFLOW REGISTER + XCHD A,@R1 ;GET DIGIT 8 + SWAP A ;FLIP FOR LOAD + MOV R4,A + ; +RIGHTL: MOV A,@R1 ;GET THE LOW ORDER BYTE + XCHD A,@R0 ;SWAP NIBBLES + SWAP A ;FLIP FOR STORE + MOV @R1,A ;SAVE THE DIGITS + DEC R0 ;BUMP THE POINTERS + DEC R1 + CJNE R1,#FP_DIG12-1,RIGHTL ;LOOP + ; + MOV A,@R1 ;ACC = CH8 + SWAP A ;ACC = 8CH + ANL A,#0FH ;ACC = 0CH + MOV @R1,A ;CARRY DONE + POP R1B0 ;EXIT + POP R0B0 ;RESTORE REGISTER + RET + ; +RIGHT5: MOV R7,A ;SAVE THE NEW SHIFT NUMBER + CLR A + XCH A,FP_CARRY ;SWAP THE NIBBLES + XCH A,FP_DIG12 + XCH A,FP_DIG34 + XCH A,FP_DIG56 + XCH A,FP_DIG78 + MOV R4,A ;SAVE THE LAST DIGIT SHIFTED + SJMP RIGHT1+1 + ; + newpage + ;*************************************************************** + ; +LEFT: ; Shift ACCUMULATOR LEFT the number of nibbles in R7 + ; + ;*************************************************************** + ; + MOV R4,#00H ;CLEAR FOR SOME ENTRYS + ; +LEFT1: CLR C + MOV A,R7 ;GET SHIFT VALUE + JZ LEFT5-1 ;EXIT IF ZERO + SUBB A,#2 ;SEE HOW MANY BYTES TO SHIFT + JNC LEFT5 + ; +LEFT3: PUSH R0B0 ;SAVE POINTER + PUSH R1B0 + MOV R0,#FP_CARRY + MOV R1,#FP_DIG12 + ; + MOV A,@R0 ;ACC=CHCL + SWAP A ;ACC = CLCH + MOV @R0,A ;ACC = CLCH, @R0 = CLCH + ; +LEFTL: MOV A,@R1 ;DIG 12 + SWAP A ;DIG 21 + XCHD A,@R0 + MOV @R1,A ;SAVE IT + INC R0 ;BUMP POINTERS + INC R1 + CJNE R0,#FP_DIG78,LEFTL + ; + MOV A,R4 + SWAP A + XCHD A,@R0 + ANL A,#0F0H + MOV R4,A + ; + POP R1B0 + POP R0B0 ;RESTORE + RET ;DONE + ; +LEFT5: MOV R7,A ;RESTORE COUNT + CLR A + XCH A,R4 ;GET THE RESTORATION BYTE + XCH A,FP_DIG78 ;DO THE SWAP + XCH A,FP_DIG56 + XCH A,FP_DIG34 + XCH A,FP_DIG12 + XCH A,FP_CARRY + SJMP LEFT1+1 + ; + newpage +MUL_NIBBLE: + ; + ; Multiply the nibble in R7 by the FP_NIB locations + ; accumulate the product in FP_ACC + ; + ; Set up the pointers for multiplication + ; + ANL A,#0FH ;STRIP OFF MS NIBBLE + MOV R7,A + MOV R0,#FP_ACC8 + MOV R1,#FP_NIB8 + CLR A + MOV FP_ACCX,A + ; +MNLOOP: DEC R0 ;BUMP POINTER TO PROPAGATE CARRY + ADD A,@R0 ;ATTEMPT TO FORCE CARRY + DA A ;BCD ADJUST + JNB ACC.4,MNL0 ;DON'T ADJUST IF NO NEED + DEC R0 ;PROPAGATE CARRY TO THE NEXT DIGIT + INC @R0 ;DO THE ADJUSTING + INC R0 ;RESTORE R0 + ; +MNL0: XCHD A,@R0 ;RESTORE INITIAL NUMBER + MOV B,R7 ;GET THE NUBBLE TO MULTIPLY + MOV A,@R1 ;GET THE OTHER NIBBLE + MUL AB ;DO THE MULTIPLY + MOV B,#10 ;NOW BCD ADJUST + DIV AB + XCH A,B ;GET THE REMAINDER + ADD A,@R0 ;PROPAGATE THE PARTIAL PRODUCTS + DA A ;BCD ADJUST + JNB ACC.4,MNL1 ;PROPAGATE PARTIAL PRODUCT CARRY + INC B + ; +MNL1: INC R0 + XCHD A,@R0 ;SAVE THE NEW PRODUCT + DEC R0 + MOV A,B ;GET BACK THE QUOTIENT + DEC R1 + CJNE R1,#FP_NIB1-1,MNLOOP + ; + ADD A,FP_ACCX ;GET THE OVERFLOW + DA A ;ADJUST + MOV @R0,A ;SAVE IT + RET ;EXIT + ; + newpage + ;*************************************************************** + ; +LOAD_POINTERS: ; Load the ARG_STACK into R0 and bump R1 + ; + ;*************************************************************** + ; + MOV P2,#ARG_STACK_PAGE + MOV R0,ARG_STACK + MOV A,#FP_NUMBER_SIZE + ADD A,R0 + MOV R1,A + RET + ; + ;*************************************************************** + ; +MUL_DIV_EXP_AND_SIGN: + ; + ; Load the sign into R7, R6. R5 gets the sign for + ; multiply and divide. + ; + ;*************************************************************** + ; + ACALL FP_CLEAR ;CLEAR INTERNAL MEMORY + ; +MDES1: ACALL LOAD_POINTERS ;LOAD REGISTERS + MOVX A,@R0 ;ARG 1 EXP + MOV R7,A ;SAVED IN R7 + MOVX A,@R1 ;ARG 2 EXP + MOV R6,A ;SAVED IN R6 + DEC R0 ;BUMP POINTERS TO SIGN + DEC R1 + MOVX A,@R0 ;GET THE SIGN + MOV R4,A ;SIGN OF ARG1 + MOVX A,@R1 ;GET SIGN OF NEXT ARG + MOV R3,A ;SIGN OF ARG2 + XRL A,R4 ;ACC GETS THE NEW SIGN + MOV R5,A ;R5 GETS THE NEW SIGN + ; + ; Bump the pointers to point at the LS digit + ; + DEC R0 + DEC R1 + ; + RET + ; + newpage + ;*************************************************************** + ; +LOADR1_MANTISSA: + ; + ; Load the mantissa of R0 into FP_Digits + ; + ;*************************************************************** + ; + PUSH R0B0 ;SAVE REGISTER 1 + MOV R0,#FP_DIG78 ;SET UP THE POINTER + ; +LOADR1: MOVX A,@R1 + MOV @R0,A + DEC R1 + DEC R0 + CJNE R0,#FP_CARRY,LOADR1 + ; + POP R0B0 + RET + ; + newpage + ;*************************************************************** + ; +HEXSCAN: ; Scan a string to determine if it is a hex number + ; set carry if hex, else carry = 0 + ; + ;*************************************************************** + ; + ACALL GET_DPTR_CHARACTER + PUSH DPH + PUSH DPL ;SAVE THE POINTER + ; +HEXSC1: MOVX A,@DPTR ;GET THE CHARACTER + ACALL DIGIT_CHECK ;SEE IF A DIGIT + JC HS1 ;CONTINUE IF A DIGIT + ACALL HEX_CHECK ;SEE IF HEX + JC HS1 + ; + CLR ACC.5 ;NO LOWER CASE + CJNE A,#'H',HEXDON + SETB C + SJMP HEXDO1 ;NUMBER IS VALID HEX, MAYBE + ; +HEXDON: CLR C + ; +HEXDO1: POP DPL ;RESTORE POINTER + POP DPH + RET + ; +HS1: INC DPTR ;BUMP TO NEXT CHARACTER + SJMP HEXSC1 ;LOOP + ; +HEX_CHECK: ;CHECK FOR A VALID ASCII HEX, SET CARRY IF FOUND + ; + CLR ACC.5 ;WASTE LOWER CASE + CJNE A,#'F'+1,$+3 ;SEE IF F OR LESS + JC HC1 + RET + ; +HC1: CJNE A,#'A',$+3 ;SEE IF A OR GREATER + CPL C + RET + ; + newpage + ; +PUSHR2R0: + ; + MOV R3,#HI(CONVT) ;CONVERSION LOCATION + MOV R1,#LO(CONVT) + ACALL CONVERT_BINARY_TO_ASCII_STRING + MOV A,#0DH ;A CR TO TERMINATE + MOVX @R1,A ;SAVE THE CR + MOV DPTR,#CONVT + ; + ; Falls thru to FLOATING INPUT + ; + newpage + ;*************************************************************** + ; +FLOATING_POINT_INPUT: ; Input a floating point number pointed to by + ; the DPTR + ; + ;*************************************************************** + ; + ACALL FP_CLEAR ;CLEAR EVERYTHING + ACALL GET_DPTR_CHARACTER + ACALL PLUS_MINUS_TEST + MOV MSIGN,C ;SAVE THE MANTISSA SIGN + ; + ; Now, set up for input loop + ; + MOV R0,#FP_ACCC + MOV R6,#7FH ;BASE EXPONENT + SETB F0 ;SET INITIAL FLAG + ; +INLOOP: ACALL GET_DIGIT_CHECK + JNC GTEST ;IF NOT A CHARACTER, WHAT IS IT? + ANL A,#0FH ;STRIP ASCII + ACALL STDIG ;STORE THE DIGITS + ; +INLPIK: INC DPTR ;BUMP POINTER FOR LOOP + SJMP INLOOP ;LOOP FOR INPUT + ; +GTEST: CJNE A,#'.',GT1 ;SEE IF A RADIX + JB FOUND_RADIX,INERR + SETB FOUND_RADIX + CJNE R0,#FP_ACCC,INLPIK + SETB FIRST_RADIX ;SET IF FIRST RADIX + SJMP INLPIK ;GET ADDITIONAL DIGITS + ; +GT1: JB F0,INERR ;ERROR IF NOT CLEARED + CJNE A,#'e',$+5 ;CHECK FOR LOWER CASE + SJMP $+5 + CJNE A,#'E',FINISH_UP + ACALL INC_AND_GET_DPTR_CHARACTER + ACALL PLUS_MINUS_TEST + MOV XSIGN,C ;SAVE SIGN STATUS + ACALL GET_DIGIT_CHECK + JNC INERR + ; + ANL A,#0FH ;STRIP ASCII BIAS OFF THE CHARACTER + MOV R5,A ;SAVE THE CHARACTER IN R5 + ; +GT2: INC DPTR + ACALL GET_DIGIT_CHECK + JNC FINISH1 + ANL A,#0FH ;STRIP OFF BIAS + XCH A,R5 ;GET THE LAST DIGIT + MOV B,#10 ;MULTIPLY BY TEN + MUL AB + ADD A,R5 ;ADD TO ORIGINAL VALUE + MOV R5,A ;SAVE IN R5 + JNC GT2 ;LOOP IF NO CARRY + MOV R5,#0FFH ;FORCE AN ERROR + ; +FINISH1:MOV A,R5 ;GET THE SIGN + JNB XSIGN,POSNUM ;SEE IF EXPONENT IS POS OR NEG + CLR C + SUBB A,R6 + CPL A + INC A + JC FINISH2 + MOV A,#01H + RET + ; +POSNUM: ADD A,R6 ;ADD TO EXPONENT + JNC FINISH2 + ; +POSNM1: MOV A,#02H + RET + ; +FINISH2:XCH A,R6 ;SAVE THE EXPONENT + ; +FINISH_UP: + ; + MOV FP_EXP,R6 ;SAVE EXPONENT + CJNE R0,#FP_ACCC,$+5 + ACALL FP_CLEAR ;CLEAR THE MEMORY IF 0 + MOV A,ARG_STACK ;GET THE ARG STACK + CLR C + SUBB A,#FP_NUMBER_SIZE+FP_NUMBER_SIZE + MOV ARG_STACK,A ;ADJUST FOR STORE + AJMP PACK + ; +STDIG: CLR F0 ;CLEAR INITIAL DESIGNATOR + JNZ STDIG1 ;CONTINUE IF NOT ZERO + CJNE R0,#FP_ACCC,STDIG1 + JNB FIRST_RADIX,RET_X + ; +DECX: DJNZ R6,RET_X + ; +INERR: MOV A,#0FFH + ; +RET_X: RET + ; +STDIG1: JB DONE_LOAD,FRTEST + CLR FIRST_RADIX + ; +FRTEST: JB FIRST_RADIX,DECX + ; +FDTEST: JB FOUND_RADIX,FDT1 + INC R6 + ; +FDT1: JB DONE_LOAD,RET_X + CJNE R0,#FP_ACC8+1,FDT2 + SETB DONE_LOAD + ; +FDT2: MOV @R0,A ;SAVE THE STRIPPED ACCUMULATOR + INC R0 ;BUMP THE POINTER + RET ;EXIT + ; + newpage + ;*************************************************************** + ; + ; I/O utilities + ; + ;*************************************************************** + ; +INC_AND_GET_DPTR_CHARACTER: + ; + INC DPTR + ; +GET_DPTR_CHARACTER: + ; + MOVX A,@DPTR ;GET THE CHARACTER + CJNE A,#' ',PMT1 ;SEE IF A SPACE + ; + ; Kill spaces + ; + SJMP INC_AND_GET_DPTR_CHARACTER + ; +PLUS_MINUS_TEST: + ; + CJNE A,#0E3H,$+5 ;SEE IF A PLUS, PLUS TOKEN FROM BASIC + SJMP PMT3 + CJNE A,#'+',$+5 + SJMP PMT3 + CJNE A,#0E5H,$+5 ;SEE IF MINUS, MINUS TOKEN FROM BASIC + SJMP PMT2 + CJNE A,#'-',PMT1 + ; +PMT2: SETB C + ; +PMT3: INC DPTR + ; +PMT1: RET + ; + newpage + ;*************************************************************** + ; +FLOATING_POINT_OUTPUT: ; Output the number, format is in location 23 + ; + ; IF FORMAT = 00 - FREE FLOATING + ; = FX - EXPONENTIAL (X IS THE NUMBER OF SIG DIGITS) + ; = NX - N = NUM BEFORE RADIX, X = NUM AFTER RADIX + ; N + X = 8 MAX + ; + ;*************************************************************** + ; + ACALL MDES1 ;GET THE NUMBER TO OUTPUT, R0 IS POINTER + ACALL POP_AND_EXIT ;OUTPUT POPS THE STACK + MOV A,R7 + MOV R6,A ;PUT THE EXPONENT IN R6 + ACALL UNPACK_R0 ;UNPACK THE NUMBER + MOV R0,#FP_NIB1 ;POINT AT THE NUMBER + MOV A,FORMAT ;GET THE FORMAT + MOV R3,A ;SAVE IN CASE OF EXP FORMAT + JZ FREE ;FREE FLOATING? + CJNE A,#0F0H,$+3 ;SEE IF EXPONENTIAL + JNC EXPOUT + ; + ; If here, must be integer USING format + ; + MOV A,R6 ;GET THE EXPONENT + JNZ $+4 + MOV R6,#80H + MOV A,R3 ;GET THE FORMAT + SWAP A ;SPLIT INTEGER AND FRACTION + ANL A,#0FH + MOV R2,A ;SAVE INTEGER + ACALL NUM_LT ;GET THE NUMBER OF INTEGERS + XCH A,R2 ;FLIP FOR SUBB + CLR C + SUBB A,R2 + MOV R7,A + JNC $+8 + MOV R5,#'?' ;OUTPUT A QUESTION MARK + ACALL SOUT1 ;NUMBER IS TOO LARGE FOR FORMAT + AJMP FREE + CJNE R2,#00,USING0 ;SEE IF ZERO + DEC R7 + ACALL SS7 + ACALL ZOUT ;OUTPUT A ZERO + SJMP USING1 + ; +USING0: ACALL SS7 ;OUTPUT SPACES, IF NEED TO + MOV A,R2 ;OUTPUT DIGITS + MOV R7,A + ACALL OUTR0 + ; +USING1: MOV A,R3 + ANL A,#0FH ;GET THE NUMBER RIGHT OF DP + MOV R2,A ;SAVE IT + JZ PMT1 ;EXIT IF ZERO + ACALL ROUT ;OUTPUT DP + ACALL NUM_RT + CJNE A,2,USINGX ;COMPARE A TO R2 + ; +USINGY: MOV A,R2 + AJMP Z7R7 + ; +USINGX: JNC USINGY + ; +USING2: XCH A,R2 + CLR C + SUBB A,R2 + XCH A,R2 + ACALL Z7R7 ;OUTPUT ZEROS IF NEED TO + MOV A,R2 + MOV R7,A + AJMP OUTR0 + ; + ; First, force exponential output, if need to + ; +FREE: MOV A,R6 ;GET THE EXPONENT + JNZ FREE1 ;IF ZERO, PRINT IT + ACALL SOUT + AJMP ZOUT + ; +FREE1: MOV R3,#0F0H ;IN CASE EXP NEEDED + MOV A,#80H-DIGIT-DIGIT-1 + ADD A,R6 + JC EXPOUT + SUBB A,#0F7H + JC EXPOUT + ; + ; Now, just print the number + ; + ACALL SINOUT ;PRINT THE SIGN OF THE NUMBER + ACALL NUM_LT ;GET THE NUMBER LEFT OF DP + CJNE A,#8,FREE4 + AJMP OUTR0 + ; +FREE4: ACALL OUTR0 + ACALL ZTEST ;TEST FOR TRAILING ZEROS + JZ U_RET ;DONE IF ALL TRAILING ZEROS + ACALL ROUT ;OUTPUT RADIX + ; +FREE2: MOV R7,#1 ;OUTPUT ONE DIGIT + ACALL OUTR0 + JNZ U_RET + ACALL ZTEST + JZ U_RET + SJMP FREE2 ;LOOP + ; +EXPOUT: ACALL SINOUT ;PRINT THE SIGN + MOV R7,#1 ;OUTPUT ONE CHARACTER + ACALL OUTR0 + ACALL ROUT ;OUTPUT RADIX + MOV A,R3 ;GET FORMAT + ANL A,#0FH ;STRIP INDICATOR + JZ EXPOTX + ; + MOV R7,A ;OUTPUT THE NUMBER OF DIGITS + DEC R7 ;ADJUST BECAUSE ONE CHAR ALREADY OUT + ACALL OUTR0 + SJMP EXPOT4 + ; +EXPOTX: ACALL FREE2 ;OUTPUT UNTIL TRAILING ZEROS + ; +EXPOT4: ACALL SOUT ;OUTPUT A SPACE + MOV R5,#'E' + ACALL SOUT1 ;OUTPUT AN E + MOV A,R6 ;GET THE EXPONENT + JZ XOUT0 ;EXIT IF ZERO + DEC A ;ADJUST FOR THE DIGIT ALREADY OUTPUT + CJNE A,#80H,XOUT2 ;SEE WHAT IT IS + ; +XOUT0: ACALL SOUT + CLR A + SJMP XOUT4 + ; +XOUT2: JC XOUT3 ;NEGATIVE EXPONENT + MOV R5,#'+' ;OUTPUT A PLUS SIGN + ACALL SOUT1 + SJMP XOUT4 + ; +XOUT3: ACALL MOUT + CPL A ;FLIP BITS + INC A ;BUMP + ; +XOUT4: CLR ACC.7 + MOV R0,A + MOV R2,#0 + MOV R1,#LO(CONVT) ;CONVERSION LOCATION + MOV R3,#HI(CONVT) + ACALL CONVERT_BINARY_TO_ASCII_STRING + MOV R0,#LO(CONVT) ;NOW, OUTPUT EXPONENT + ; +EXPOT5: MOVX A,@R0 ;GET THE CHARACTER + MOV R5,A ;OUTPUT IT + ACALL SOUT1 + INC R0 ;BUMP THE POINTER + MOV A,R0 ;GET THE POINTER + CJNE A,R1B0,EXPOT5 ;LOOP + ; +U_RET: RET ;EXIT + ; +OUTR0: ; Output the characters pointed to by R0, also bias ascii + ; + MOV A,R7 ;GET THE COUNTER + JZ OUTR ;EXIT IF DONE + MOV A,@R0 ;GET THE NUMBER + ORL A,#30H ;ASCII BIAS + INC R0 ;BUMP POINTER AND COUNTER + DEC R7 + MOV R5,A ;PUT CHARACTER IN OUTPUT REGISTER + ACALL SOUT1 ;OUTPUT THE CHARACTER + CLR A ;JUST FOR TEST + CJNE R0,#FP_NIB8+1,OUTR0 + MOV A,#55H ;KNOW WHERE EXIT OCCURED + ; +OUTR: RET + ; +ZTEST: MOV R1,R0B0 ;GET POINTER REGISTER + ; +ZT0: MOV A,@R1 ;GET THE VALUE + JNZ ZT1 + INC R1 ;BUMP POINTER + CJNE R1,#FP_NIB8+1,ZT0 + ; +ZT1: RET + ; +NUM_LT: MOV A,R6 ;GET EXPONENT + CLR C ;GET READY FOR SUBB + SUBB A,#80H ;SUB EXPONENT BIAS + JNC NL1 ;OK IF NO CARRY + CLR A ;NO DIGITS LEFT + ; +NL1: MOV R7,A ;SAVE THE COUNT + RET + ; +NUM_RT: CLR C ;SUBB AGAIN + MOV A,#80H ;EXPONENT BIAS + SUBB A,R6 ;GET THE BIASED EXPONENT + JNC NR1 + CLR A + ; +NR1: RET ;EXIT + ; +SPACE7: MOV A,R7 ;GET THE NUMBER OF SPACES + JZ NR1 ;EXIT IF ZERO + ACALL SOUT ;OUTPUT A SPACE + DEC R7 ;BUMP COUNTER + SJMP SPACE7 ;LOOP + ; +Z7R7: MOV R7,A + ; +ZERO7: MOV A,R7 ;GET COUNTER + JZ NR1 ;EXIT IF ZERO + ACALL ZOUT ;OUTPUT A ZERO + DEC R7 ;BUMP COUNTER + SJMP ZERO7 ;LOOP + ; +SS7: ACALL SPACE7 + ; +SINOUT: MOV A,R4 ;GET THE SIGN + JZ SOUT ;OUTPUT A SPACE IF ZERO + ; +MOUT: MOV R5,#'-' + SJMP SOUT1 ;OUTPUT A MINUS IF NOT + ; +ROUT: MOV R5,#'.' ;OUTPUT A RADIX + SJMP SOUT1 + ; +ZOUT: MOV R5,#'0' ;OUTPUT A ZERO + SJMP SOUT1 + ; +SOUT: MOV R5,#' ' ;OUTPUT A SPACE + ; +SOUT1: AJMP OUTPUT + ; + newpage + ;*************************************************************** + ; +CONVERT_ASCII_STRING_TO_BINARY: + ; + ;DPTR POINTS TO ASCII STRING + ;PUT THE BINARY NUMBER IN R2:R0, ERROR IF >64K + ; + ;*************************************************************** + ; +CASB: ACALL HEXSCAN ;SEE IF HEX NUMBER + MOV ADD_IN,C ;IF ADD_IN IS SET, THE NUMBER IS HEX + ACALL GET_DIGIT_CHECK + CPL C ;FLIP FOR EXIT + JC RCASB + MOV R3,#00H ;ZERO R3:R1 FOR LOOP + MOV R1,#00H + SJMP CASB5 + ; +CASB2: INC DPTR + MOV R0B0,R1 ;SAVE THE PRESENT CONVERTED VALUE + MOV R0B0+2,R3 ;IN R2:R0 + ACALL GET_DIGIT_CHECK + JC CASB5 + JNB ADD_IN,RCASB ;CONVERSION COMPLETE + ACALL HEX_CHECK ;SEE IF HEX NUMBER + JC CASB4 ;PROCEED IF GOOD + INC DPTR ;BUMP PAST H + SJMP RCASB + ; +CASB4: ADD A,#9 ;ADJUST HEX ASCII BIAS + ; +CASB5: MOV B,#10 + JNB ADD_IN,CASB6 + MOV B,#16 ;HEX MODE + ; +CASB6: ACALL MULNUM ;ACCUMULATE THE DIGITS + JNC CASB2 ;LOOP IF NO CARRY + ; +RCASB: CLR A ;RESET ACC + MOV ACC_OVERFLOW,C ;IF OVERFLOW, SAY SO ******AA + RET ;EXIT + ; + newpage + ; +MULNUM10:MOV B,#10 + ; + ;*************************************************************** + ; +MULNUM: ; Take the next digit in the acc (masked to 0FH) + ; accumulate in R3:R1 + ; + ;*************************************************************** + ; + PUSH ACC ;SAVE ACC + PUSH B ;SAVE MULTIPLIER + MOV A,R1 ;PUT LOW ORDER BITS IN ACC + MUL AB ;DO THE MULTIPLY + MOV R1,A ;PUT THE RESULT BACK + MOV A,R3 ;GET THE HIGH ORDER BYTE + MOV R3,B ;SAVE THE OVERFLOW + POP B ;GET THE MULTIPLIER + MUL AB ;DO IT + MOV C,OV ;SAVE OVERFLOW IN F0 + MOV F0,C + ADD A,R3 ;ADD OVERFLOW TO HIGH RESULT + MOV R3,A ;PUT IT BACK + POP ACC ;GET THE ORIGINAL ACC BACK + ORL C,F0 ;OR CARRY AND OVERFLOW + JC MULX ;NO GOOD IF THE CARRY IS SET + ; +MUL11: ANL A,#0FH ;MASK OFF HIGH ORDER BITS + ADD A,R1 ;NOW ADD THE ACC + MOV R1,A ;PUT IT BACK + CLR A ;PROPAGATE THE CARRY + ADDC A,R3 + MOV R3,A ;PUT IT BACK + ; +MULX: RET ;EXIT WITH OR WITHOUT CARRY + ; + ;*************************************************************** + ; +CONVERT_BINARY_TO_ASCII_STRING: + ; + ;R3:R1 contains the address of the string + ;R2:R0 contains the value to convert + ;DPTR, R7, R6, and ACC gets clobbered + ; + ;*************************************************************** + ; + CLR A ;NO LEADING ZEROS + MOV DPTR,#10000 ;SUBTRACT 10000 + ACALL RSUB ;DO THE SUBTRACTION + MOV DPTR,#1000 ;NOW 1000 + ACALL RSUB + MOV DPTR,#100 ;NOW 100 + ACALL RSUB + MOV DPTR,#10 ;NOW 10 + ACALL RSUB + MOV DPTR,#1 ;NOW 1 + ACALL RSUB + JZ RSUB2 ;JUMP OVER RET + ; +RSUB_R: RET + ; +RSUB: MOV R6,#-1 ;SET UP THE COUNTER + ; +RSUB1: INC R6 ;BUMP THE COUNTER + XCH A,R2 ;DO A FAST COMPARE + CJNE A,DPH,$+3 + XCH A,R2 + JC FAST_DONE + XCH A,R0 ;GET LOW BYTE + SUBB A,DPL ;SUBTRACT, CARRY IS CLEARED + XCH A,R0 ;PUT IT BACK + XCH A,R2 ;GET THE HIGH BYTE + SUBB A,DPH ;ADD THE HIGH BYTE + XCH A,R2 ;PUT IT BACK + JNC RSUB1 ;LOOP UNTIL CARRY + ; + XCH A,R0 + ADD A,DPL ;RESTORE R2:R0 + XCH A,R0 + XCH A,R2 + ADDC A,DPH + XCH A,R2 + ; +FAST_DONE: + ; + ORL A,R6 ;OR THE COUNT VALUE + JZ RSUB_R ;RETURN IF ZERO + ; +RSUB2: MOV A,#'0' ;GET THE ASCII BIAS + ADD A,R6 ;ADD THE COUNT + ; +RSUB4: MOV P2,R3 ;SET UP P2 + MOVX @R1,A ;PLACE THE VALUE IN MEMORY + INC R1 + CJNE R1,#00H,RSUB3 ;SEE IF RAPPED AROUND + INC R3 ;BUMP HIGH BYTE + ; +RSUB3: RET ;EXIT + ; + newpage + ;*************************************************************** + ; +HEXOUT: ; Output the hex number in R3:R1, supress leading zeros, if set + ; + ;*************************************************************** + ; + ACALL SOUT ;OUTPUT A SPACE + MOV C,ZSURP ;GET ZERO SUPPRESSION BIT + MOV ADD_IN,C + MOV A,R3 ;GET HIGH NIBBLE AND PRINT IT + ACALL HOUTHI + MOV A,R3 + ACALL HOUTLO + ; +HEX2X: CLR ADD_IN ;DON'T SUPPRESS ZEROS + MOV A,R1 ;GET LOW NIBBLE AND PRINT IT + ACALL HOUTHI + MOV A,R1 + ACALL HOUTLO + MOV R5,#'H' ;OUTPUT H TO INDICATE HEX MODE + ; +SOUT_1: AJMP SOUT1 + ; +HOUT1: CLR ADD_IN ;PRINTED SOMETHING, SO CLEAR ADD_IN + ADD A,#90H ;CONVERT TO ASCII + DA A + ADDC A,#40H + DA A ;GOT IT HERE + MOV R5,A ;OUTPUT THE BYTE + SJMP SOUT_1 + ; +HOUTHI: SWAP A ;SWAP TO OUTPUT HIGH NIBBLE + ; +HOUTLO: ANL A,#0FH ;STRIP + JNZ HOUT1 ;PRINT IF NOT ZERO + JNB ADD_IN,HOUT1 ;OUTPUT A ZERO IF NOT SUPRESSED + RET + ; + newpage + ORG 1FEBH ;FOR LINK COMPATABILITY + ; + ; +GET_DIGIT_CHECK: ; Get a character, then check for digit + ; + ACALL GET_DPTR_CHARACTER + ; +DIGIT_CHECK: ;CHECK FOR A VALID ASCII DIGIT, SET CARRY IF FOUND + ; + CJNE A,#'9'+1,$+3 ;SEE IF ASCII 9 OR LESS + JC DC1 + RET + ; +DC1: CJNE A,#'0',$+3 ;SEE IF ASCII 0 OR GREATER + CPL C + RET + + endsection diff --git a/tests/t_bas52/bas52.out b/tests/t_bas52/bas52.out new file mode 100644 index 0000000..b6a0f80 --- /dev/null +++ b/tests/t_bas52/bas52.out @@ -0,0 +1,75 @@ + ;*************************************************************** + ; + ; TEROT - Output a character to the system console + ; update PHEAD position. + ; + ;*************************************************************** + ; +STEROT: MOV R5,#' ' ;OUTPUT A SPACE + ; +TEROT: PUSH ACC ;SAVE THE ACCUMULATOR + PUSH DPH ;SAVE THE DPTR + PUSH DPL + JNB CNT_S,$+7 ;WAIT FOR A CONTROL Q + ACALL BCK ;GET SERIAL STATUS + SJMP $-5 + MOV A,R5 ;PUT OUTPUT BYTE IN A + JNB BO,$+8 ;CHECK FOR MONITOR + LCALL 2040H ;DO THE MONITOR + AJMP TEROT1 ;CLEAN UP + JNB COUB,$+8 ;SEE IF USER WANTS OUTPUT + LCALL 4030H + AJMP TEROT1 + JNB UPB,T_1 ;NO AT IF NO XBIT + JNB LPB,T_1 ;AT PRINT + LCALL 403CH ;CALL AT LOCATION + AJMP TEROT1 ;FINISH OFF OUTPUT + ; +T_1: JNB COB,TXX ;SEE IF LIST SET + MOV DPTR,#SPV ;LOAD BAUD RATE + ACALL LD_T + CLR LP ;OUTPUT START BIT + ACALL TIMER_LOAD ;LOAD AND START THE TIMER + MOV A,R5 ;GET THE OUTPUT BYTE + SETB C ;SET CARRY FOR LAST OUTPUT + MOV R5,#9 ;LOAD TIMER COUNTDOWN + ; +LTOUT1: RRC A ;ROTATE A + JNB TF1,$ ;WAIT TILL TIMER READY + MOV LP,C ;OUTPUT THE BIT + ACALL TIMER_LOAD ;DO THE NEXT BIT + DJNZ R5,LTOUT1 ;LOOP UNTIL DONE + JNB TF1,$ ;FIRST STOP BIT + ACALL TIMER_LOAD + JNB TF1,$ ;SECOND STOP BIT + MOV R5,A ;RESTORE R5 + SJMP TEROT1 ;BACK TO TEROT + ; + newpage +TXX: JNB TI,$ ;WAIT FOR TRANSMIT READY + CLR TI + MOV SBUF,R5 ;SEND OUT THE CHARACTER + ; +TEROT1: CJNE R5,#CR,$+6 ;SEE IF A CR + MOV PHEAD,#00H ;IF A CR, RESET PHEAD AND + ; + CJNE R5,#LF,NLC ;SEE IF A LF + MOV A,NULLCT ;GET THE NULL COUNT + JZ NLC ;NO NULLS IF ZERO + ; +TEROT2: MOV R5,#NULL ;PUT THE NULL IN THE OUTPUT REGISTER + ACALL TEROT ;OUTPUT THE NULL + DEC A ;DECREMENT NULL COUNT + JNZ TEROT2 ;LOOP UNTIL DONE + ; +NLC: CJNE R5,#BS,$+5 ;DEC PHEAD IF A BACKSPACE + DEC PHEAD + CJNE R5,#20H,$+3 ;IS IT A PRINTABLE CHARACTER? + JC $+4 ;DON'T INCREMENT PHEAD IF NOT PRINTABLE + INC PHEAD ;BUMP PRINT HEAD + POP DPL ;RESTORE DPTR + POP DPH + POP ACC ;RESTORE ACC + RET ;EXIT + ; + diff --git a/tests/t_bas52/bas52.pgm b/tests/t_bas52/bas52.pgm new file mode 100644 index 0000000..080d43f --- /dev/null +++ b/tests/t_bas52/bas52.pgm @@ -0,0 +1,125 @@ + +PG8: MOV R7,#00H ;PROGRAM ONE BYTE AT A TIME + MOV R6,#01H + MOV R2,#HI(ROMADR-1) + MOV R0,#LO(ROMADR-1);LOAD PROM ADDRESS + ACALL PG1+3 + INC R6 + DB 0E5H ;MOV A DIRECT OP CODE + DB 0CBH ;ADDRESS OF R2CAP HIGH + ACALL PG1+3 + DB 0E5H ;MOV A, DIRECT OP CODE + DB 0CAH ;R2CAP LOW + MOV R6,#3 + MOV R1,#LO(MEMTOP-1) + MOV R3,#HI(MEMTOP) + ACALL PG1+3 ;SAVE MEMTOP + SJMP PGR + ; +CIPROG: MOV DPTR,#IPROGS ;LOAD IPROG LOCATION + SETB INTELB + SJMP $+7 ;GO DO PROG + ; +CPROG: MOV DPTR,#PROGS ;LOAD PROG LOCATION + CLR INTELB + ; + ACALL LD_T ;LOAD THE TIMER + CLR PROMV ;TURN ON THE PROM VOLTAGE + LCALL DELTST ;SEE IF A CR ******AA CALL-->LCALL + JNZ PG8 ;SAVE TIMER IF SO + MOV R4,#0FEH + SETB INBIT + ACALL ROMFD ;GET THE ROM ADDRESS OF THE LAST LOCATION + LCALL TEMPD ;SAVE THE ADDRESS ******AA CALL-->LCALL + MOV A,R4 ;GET COUNT + CPL A + LCALL TWO_R2 ;PUT IT ON THE STACK ******AA CALL-->LCALL + CALL FP_BASE+14 ;OUTPUT IT + ACALL CCAL ;GET THE PROGRAM + ACALL CRLF ;DO CRLF + MOV R0,TEMP4 ;GET ADDRESS + MOV R2,TEMP5 + MOV A,#55H ;LOAD SIGNIFIER + INC R6 ;LOAD LEN + 1 + CJNE R6,#00,$+4 + INC R7 + ACALL PG2-2 + ; + newpage +PGR: SETB PROMV + AJMP C_K + ; +PG1: MOV P2,R3 ;GET THE BYTE TO PROGRAM + MOVX A,@R1 + LCALL INC3210 ;BUMP POINTERS + MOV R5,#1 ;SET UP INTELLIGENT COUMTER + ; +PG2: MOV R4,A ;SAVE THE BYTE IN R4 + ACALL PG7 ;PROGRAM THE BYTE + ACALL PG9 + JB INTELB,PG4 ;SEE IF INTELLIGENT PROGRAMMING + ; +PG3: XRL A,R4 + JNZ PG6 ;ERROR IF NOT THE SAME + LCALL DEC76 ;BUMP THE COUNTERS ******AA CALL-->LCALL + JNZ PG1 ;LOOP IF NOT DONE + ANL PSW,#11100111B ;INSURE RB0 + RET + ; +PG4: XRL A,R4 ;SEE IF PROGRAMMED + JNZ PG5 ;JUMP IF NOT + MOV A,R4 ;GET THE DATA BACK + ACALL PG7 ;PROGRAM THE LOCATION + ACALL ZRO ;AGAIN + ACALL ZRO ;AND AGAIN + ACALL ZRO ;AND AGAIN + DJNZ R5,$-6 ;KEEP DOING IT + ACALL PG9 ;RESET PROG + SJMP PG3 ;FINISH THE LOOP + ; +PG5: INC R5 ;BUMP THE COUNTER + MOV A,R4 ;GET THE BYTE + CJNE R5,#25,PG2 ;SEE IF TRIED 25 TIMES + ; +PG6: SETB PROMV ;TURN OFF PROM VOLTAGE + MOV PSW,#0 ;INSURE RB0 + JNB DIRF,PG4-1 ;EXIT IF IN RUN MODE + MOV DPTR,#E16X ;PROGRAMMING ERROR + ; +ERRLK: LJMP ERROR ;PROCESS THE ERROR + ; + newpage +PG7: MOV P0,R0 ;SET UP THE PORTS + MOV P2,R2 ;LATCH LOW ORDER ADDRESS + ACALL PG11 ;DELAY FOR 8748/9 + CLR ALED + MOV P0,A ;PUT DATA ON THE PORT + ; +ZRO: NOP ;SETTLEING TIME + FP ZERO + NOP + NOP + NOP + NOP + NOP + ACALL PG11 ;DELAY A WHILE + CLR PROMP ;START PROGRAMMING + ACALL TIMER_LOAD ;START THE TIMER + JNB TF1,$ ;WAIT FOR PART TO PROGRAM + RET ;EXIT + ; +PG9: SETB PROMP + ACALL PG11 ;DELAY FOR A WHILE + JNB P3.2,$ ;LOOP FOR EEPROMS + MOV P0,#0FFH + CLR P3.7 ;LOWER READ + ACALL PG11 + MOV A,P0 ;READ THE PORT + SETB P3.7 + SETB ALED + RET + ; +PG11: MOV TEMP5,#12 ;DELAY 30uS AT 12 MHZ + DJNZ TEMP5,$ + RET + ; + diff --git a/tests/t_bas52/bas52.pwm b/tests/t_bas52/bas52.pwm new file mode 100644 index 0000000..44ac409 --- /dev/null +++ b/tests/t_bas52/bas52.pwm @@ -0,0 +1,25 @@ + ;************************************************************** + ; +STONE: ; Toggle the I/O port + ; + ;************************************************************** + ; + CALL THREE ;GET THE NUMBERS + ACALL CBIAS ;BIAS R3:R1 FOR COUNT LOOP + ; +STONE1: CLR T_BIT ;TOGGLE THE BIT + CLR TR1 ;STOP THE TIMER + MOV TH1,R3 ;LOAD THE TIMER + MOV TL1,R1 + CLR TF1 ;CLEAR THE OVERFLOW FLAG + SETB TR1 ;TURN IT ON + ACALL DEC76 + JNB TF1,$ ;WAIT + ACALL ALPAR + SETB T_BIT ;BACK TO A ONE + CALL TIMER_LOAD+2 ;LOAD THE HIGH VALUE + JNB TF1,$ ;WAIT + JNZ STONE1 ;LOOP + RET + ; + diff --git a/tests/t_bas52/bas52.rst b/tests/t_bas52/bas52.rst new file mode 100644 index 0000000..2d2f13a --- /dev/null +++ b/tests/t_bas52/bas52.rst @@ -0,0 +1,111 @@ + + ;************************************************************** + ; +CRST: ; This performs system initialzation, it was moved here so the + ; new power on reset functions could be tested in an 8751. + ; + ;************************************************************** + ; + ; First, initialize SFR's + ; + MOV SCON,#5AH ;INITIALIZE SFR'S + MOV TMOD,#10H + MOV TCON,#54H + DB 75H ;MOV DIRECT, # OP CODE + DB 0C8H ;T2CON LOCATION + DB 34H ;CONFIGURATION BYTE + ; + MOV DPTR,#2001H ;READ CODE AT 2001H + CLR A + MOVC A,@A+DPTR + CJNE A,#0AAH,$+6 ;IF IT IS AN AAH, DO USER RESET + LCALL 2090H + ; + MOV R0,#IRAMTOP ;PUT THE TOP OF RAM IN R0 + CLR A ;ZERO THE ACC + ; + MOV @R0,A ;CLEAR INTERNAL MEMORY + DJNZ R0,$-1 ;LOOP TIL DONE + ; + ; Now, test the external memory + ; + MOV SPSAV,#CMNDSP ;SET UP THE STACK + MOV SP,SPSAV + ; + MOV BOFAH,#HI(ROMADR) + MOV BOFAL,#LO(ROMADR+17) + MOV DPTR,#ROMADR ;GET THE BYTE AT 8000H + MOVX A,@DPTR + CLR C + SUBB A,#31H ;FOR BIAS + MOV MT1,A ;SAVE IN DIRECT MATH LOC + CLR ACC.2 ;SAVE FOR RESET + MOV R7,A ;SAVE IT IN R7 + INC DPTR + ACALL L31DPI ;SAVE BAUD RATE + LCALL RCL + INC DPTR ;GET MEMTOP + ACALL L31DPI + MOV DPTR,#5FH ;READ THE EXTERNAL BYTE + MOVX A,@DPTR + MOV DPTR,#0 ;ESTABLISH BASE FOR CLEAR + CJNE A,#0A5H,CRS + MOV A,MT1 + CLR ACC.0 ;CLEAR BIT ONE + XRL A,#4H + JZ CR2 + ; +CRS: CJNE R7,#2,$+5 + SJMP $+5 + CJNE R7,#3,$+7 + ACALL CL_1 + SJMP CR1 + ; +CR0: MOV R3,DPH ;SAVE THE DPTR + MOV R1,DPL + INC DPTR + MOV A,#5AH + MOVX @DPTR,A + MOVX A,@DPTR + CJNE A,#5AH,CR1 + CLR A + MOVX @DPTR,A + CJNE R3,#0E0H,CR0 + ; +CR1: CJNE R3,#03H,$+3 ;NEED THIS MUCH RAM + JC CRST + MOV DPTR,#MEMTOP ;SAVE MEMTOP + ACALL S31DP2 ;SAVE MEMTOP AND SEED RCELL + ACALL CNEW ;CLEAR THE MEMORY AND SET UP POINTERS + ; +CR2: ACALL RC1 ;SET UP STACKS IF NOT DONE + ; + LCALL AXTAL0 ;DO THE CRYSTAL + MOV A,MT1 ;GET THE RESET BYTE + CJNE A,#5,$+6 + LCALL 4039H + JNC BG1 ;CHECK FOR 0,1,2,3, OR 4 + JNB ACC.0,BG3 ;NO RUN IF WRONG TYPE + MOV DPTR,#ROMADR+16 + MOVX A,@DPTR ;READ THE BYTE + CJNE A,#55H,BG3 + LJMP CRUN + ; +BG1: CLR A ;DO BAUD RATE + MOV R3,A + MOV R1,A + MOV R0,#4 + JB RXD,$ ;LOOP UNTIL A CHARACTER IS RECEIVED + ; +BG2: DJNZ R0,$ ;FOUR CLOCKS, IN LOOP + LCALL DEC3210+4 ;NINE CLOCKS ******AA CALL-->LCALL + MOV R0,#2 ;ONE CLOCK + JNB RXD,BG2 ;TWO CLOCKS, LOOP UNTIL DONE + JB RXD,$ ;WAIT FOR STOP CHARACTER TO END + JNB RXD,$ + LCALL RCL ;LOAD THE TIMER ******AA CALL-->LCALL + ; +BG3: MOV DPTR,#S_N ;GET THE MESSAGE + ACALL CRP ;PRINT IT + LJMP CRAM + diff --git a/tests/t_bas52/bas52.tl b/tests/t_bas52/bas52.tl new file mode 100644 index 0000000..fdf95da --- /dev/null +++ b/tests/t_bas52/bas52.tl @@ -0,0 +1,16 @@ + + ;************************************************************** + ; +TIMER_LOAD:; Load the timer + ; + ;************************************************************* + ; + ACALL $-1 ;DELAY FOUR CLOCKS + CLR TR1 ;STOP IT WHILE IT'S LOADED + MOV TH1,T_HH + MOV TL1,T_LL + CLR TF1 ;CLEAR THE OVERFLOW FLAG + SETB TR1 ;START IT NOW + RET + ; + diff --git a/tests/t_bas52/look52.inc b/tests/t_bas52/look52.inc new file mode 100644 index 0000000..b4d13f4 --- /dev/null +++ b/tests/t_bas52/look52.inc @@ -0,0 +1,779 @@ + ;************************************************************** + ; + ; This is the equate table for 8052 basic. + ; + ;************************************************************** + ; + ; The register to direct equates for CJNE instructions. + ; +R0B0 EQU 0 +R1B0 EQU 1 +R2B0 EQU 2 +R3B0 EQU 3 +R4B0 EQU 4 +R5B0 EQU 5 +R6B0 EQU 6 +R7B0 EQU 7 + ; + ; Register bank 1 contains the text pointer + ; and the arg stack pointer. + ; +TXAL EQU 8 ;R0 BANK 1 = TEXT POINTER LOW +ASTKA EQU 9 ;R1 BANK 1 = ARG STACK +TXAH EQU 10 ;R2 BANK 1 = TEXT POINTER HIGH + ; + ; Now five temporary locations that are used by basic. + ; +TEMP1 EQU 11 +TEMP2 EQU 12 +TEMP3 EQU 13 +TEMP4 EQU 14 +TEMP5 EQU 15 + ; + newpage + ; Register bank 2 contains the read text pointer + ; and the control stack pointer. + ; +RTXAL EQU 16 ;R0 BANK 2 = READ TEXT POINTER LOW +CSTKA EQU 17 ;R1 BANK 2 = CONTROL STACK POINTER +RTXAH EQU 18 ;R2 BANK 2 = READ TEXT POINTER HIGH + ; + ; Now some internal system equates. + ; +BOFAH EQU 19 ;START OF THE BASIC PROGRAM, HIGH BYTE +BOFAL EQU 20 ;START OF THE BASIC PROGRAM, LOW BYTE +NULLCT EQU 21 ;NULL COUNT +PHEAD EQU 22 ;PRINT HEAD POSITION +FORMAT EQU 23 + ; + ; Register bank 3 is for the user and can be loaded + ; by basic + ; + ; + ; + ; Now everything else is used by basic. + ; First the bit locations, these use bytes 34, 35, 36, 37 and 38 + ; + newpage +OTS BIT 16 ;34.0-ON TIME INSTRUCTION EXECUTED +INPROG BIT 17 ;34.1-INTERRUPT IN PROCESS +INTBIT BIT 18 ;34.2-INTERRUPT SET BIT +ON_ERR BIT 19 ;34.3-ON ERROR EXECUTED +OTI BIT 20 ;34.4-ON TIME INTERRUPT IN PROGRESS +LINEB BIT 21 ;34.5-LINE CHANGE OCCURED +INTPEN BIT 22 ;34.6-INTERRUPT PENDING BIT +CONB BIT 23 ;34.7-CAN CONTINUE IF SET +GTRD BIT 24 ;35.0-READ GET LOCATION +LPB BIT 25 ;35.1-PRINT TO LINE PRINTER PORT +CKS_B BIT 26 ;35.2-FOR PWM INTERRUPT +COB BIT 27 ;35.3-CONSOLE OUT BIT + ; 0 = SERIAL PORT + ; 1 = LINE PRINTER +COUB BIT 28 ;35.4-USER CONSOLE OUT BIT + ; 0 = SERIAL PORT + ; 1 = USER DRIVER +INBIT BIT 29 ;35.5-INITIALIZATION BIT +CIUB BIT 30 ;35.6-USER CONSOLE IN BIT + ; 0 = SERIAL PORT + ; 1 = USER ROUTINE +SPINT BIT 31 ;35.7-SERIAL PORT INTERRUPT +STOPBIT BIT 32 ;36.0-PROGRAM STOP ENCOUNTERED +U_IDL BIT 33 ;36.1-USER IDLE BREAK +INP_B BIT 34 ;36.2-SET DURING INPUT INSTRUCTION +;DCMPXZ BIT 35 ;36.3-DCMPX ZERO FLAG +ARGF BIT 36 ;36.4-ARG STACK HAS A VALUE +RETBIT BIT 37 ;36.5-RET FROM INTERRUPT EXECUTED +I_T0 BIT 38 ;36.6-TRAP INTERRUPT ZERO TO MON +UPB BIT 39 ;36.7-SET WHEN @ IS VALID +JKBIT BIT 40 ;37.0-WB TRIGGER +ENDBIT BIT 41 ;37.1-GET END OF PROGRAM +UBIT BIT 42 ;37.2-FOR DIM STATEMENT +ISAV BIT 43 ;37.3-SAVE INTERRUPT STATUS +BO BIT 44 ;37.4-BUBBLE OUTPUT +XBIT BIT 45 ;37.5-EXTERNAL PROGRAM PRESENT +C_BIT BIT 46 ;37.6-SET WHEN CLOCK RUNNING +DIRF BIT 47 ;37.7-DIRECT INPUT MODE +NO_C BIT 48 ;38.0-NO CONTROL C +DRQ BIT 49 ;38.1-DMA ENABLED +BI BIT 50 ;38.2-BUBBLE INPUT +INTELB BIT 51 ;38.3-INTELLIGENT PROM PROGRAMMING +C0ORX1 BIT 52 ;38.4-PRINT FROM ROM OR RAM +CNT_S BIT 53 ;38.5-CONTROL S ENCOUNTERED +ZSURP BIT 54 ;38.6-ZERO SUPRESS +HMODE BIT 55 ;38.7-HEX MODE PRINT +LP BIT P1.7 ;SOFTWARE LINE PRINTER +DACK BIT P1.6 ;DMA ACK +PROMV BIT P1.5 ;TURN ON PROM VOLTAGE +PROMP BIT P1.4 ;PROM PULSE +ALED BIT P1.3 ;ALE DISABLE +T_BIT BIT P1.2 ;I/O TOGGLE BIT + ; + newpage + ; + ; The next location is a bit addressable byte counter + ; +BABC EQU 39 + ; + ; Now floating point and the other temps + ; + ; FP Uses to locations 03CH + ; + ; Now the stack designators. + ; +SPSAV EQU 3EH +S_LEN EQU 3FH +T_HH EQU 40H +T_LL EQU 41H +INTXAH EQU 42H +INTXAL EQU 43H +MT1 EQU 45H +MT2 EQU 46H +MILLIV EQU 47H ;TIMER LOCATIONS +TVH EQU 48H +TVL EQU 49H +SAVE_T EQU 4AH +SP_H EQU 4BH ;SERIAL PORT TIME OUT +SP_L EQU 4CH +CMNDSP EQU 4DH ;SYSTEM STACK POINTER +IRAMTOP EQU 0FFH ;TOP OF RAM +STACKTP EQU 0FEH ;ARG AND CONTROL STACK TOPS + ; + ; The character equates + ; +CR EQU 0DH ;CARRIAGE RETURN +LF EQU 0AH ;LINE FEED +BELL EQU 07H ;BELL CHARACTER +BS EQU 08H ;BACK SPACE +CNTRLC EQU 03H ;CONTROL C +CNTRLD EQU 04H ;CONTROL D +NULL EQU 00H ;NULL + ; + newpage + ; + ; The internal system equates + ; +LINLEN EQU 73 ;THE LENGTH OF AN INPUT LINE +EOF EQU 01 ;END OF FILE CHARACTER +ASTKAH EQU 01 ;ASTKA IS IN PAGE 1 OF RAM +CSTKAH EQU 00 ;CSTKA IS IN PAGE 0 OF RAM +FTYPE EQU 01 ;CONTROL STACK "FOR" +GTYPE EQU 02 ;CONTROL STACK "GOSUB" +DTYPE EQU 03 ;DO-WHILE/UNTIL TYPE +ROMADR EQU 8000H ;LOCATION OF ROM + ; + ; The floating point equates + ; +FPSIZ EQU 6 ;NO. OF BYTES IN A FLOATING NUM +DIGIT EQU FPSIZ-2 ;THE MANTISSA OF A FLOATING NUM +STESIZ EQU FPSIZ+3 ;SIZE OF SYMBOL ADJUSTED TABLE ELEMENT +FP_BASE EQU 1993H ;BASE OF FLOATING POINT ROUTINES +PSTART EQU 512 ;START OF A PROGRAM IN RAM +FSIZE EQU FPSIZ+FPSIZ+2+2+1 + ; + newpage + ;************************************************************** + ; +USENT: ; User entry jump table + ; + ;************************************************************** + ; + DW CMND1 ;(00, 00H)COMMAND MODE JUMP + DW IFIX ;(01, 01H)CONVERT FP TO INT + DW PUSHAS ;(02, 02H)PUSH VALUE ONTO ARG STACK + DW POPAS ;(03, 03H)POP VALUE OFF ARG STACK + DW PG1 ;(04, 04H)PROGRAM A PROM + DW INLINE ;(05, 05H)INPUT A LINE + DW UPRNT ;(06, 06H)PRINT A LINR + DW CRLF ;(07, 07H)OUTPUT A CRLF + ; + ;************************************************************** + ; + ; This is the operation jump table for arithmetics + ; + ;************************************************************** + ; +OPTAB: DW ALPAR ;(08, 08H)LEFT PAREN + DW AEXP ;(09, 09H)EXPONENTAION + DW AMUL ;(10, 0AH)FP MUL + DW AADD ;(11, 0BH)FLOATING POINT ADD + DW ADIV ;(12, 0CH)FLOATING POINT DIVIDE + DW ASUB ;(13, 0DH)FLOATING POINT SUBTRACTION + DW AXRL ;(14, 0EH)XOR + DW AANL ;(15, 0FH)AND + DW AORL ;(16, 10H)OR + DW ANEG ;(17, 11H)NEGATE + DW AEQ ;(18, 12H)EQUAL + DW AGE ;(19, 13H)GREATER THAN OR EQUAL + DW ALE ;(20, 14H)LESS THAN OR EQUAL + DW ANE ;(21, 15H)NOT EQUAL + DW ALT ;(22, 16H)LESS THAN + DW AGT ;(23, 17H)GREATER THAN + ; + newpage + ;*************************************************************** + ; + ; This is the jump table for unary operators + ; + ;*************************************************************** + ; + DW AABS ;(24, 18H)ABSOLUTE VALUE + DW AINT ;(25, 19H)INTEGER OPERATOR + DW ASGN ;(26, 1AH)SIGN OPERATOR + DW ANOT ;(27, 1BH)ONE'S COMPLEMENT + DW ACOS ;(28, 1CH)COSINE + DW ATAN ;(29, 1DH)TANGENT + DW ASIN ;(30, 1EH)SINE + DW ASQR ;(31, 1FH)SQUARE ROOT + DW ACBYTE ;(32, 20H)READ CODE + DW AETOX ;(33, 21H)E TO THE X + DW AATAN ;(34, 22H)ARC TANGENT + DW ALN ;(35, 23H)NATURAL LOG + DW ADBYTE ;(36, 24H)READ DATA MEMORY + DW AXBYTE ;(37, 25H)READ EXTERNAL MEMORY + DW PIPI ;(38, 26H)PI + DW ARND ;(39, 27H)RANDOM NUMBER + DW AGET ;(40, 28H)GET INPUT CHARACTER + DW AFREE ;(41, 29H)COMPUTE #BYTES FREE + DW ALEN ;(42, 2AH) COMPUTE LEN OF PORGRAM + DW AXTAL ;(43, 2BH) CRYSTAL + DW PMTOP ;(44, 2CH)TOP OF MEMORY + DW ATIME ;(45, 2DH) TIME + DW A_IE ;(46, 2EH) IE + DW A_IP ;(47, 2FH) IP + DW ATIM0 ;(48, 30H) TIMER 0 + DW ATIM1 ;(49, 31H) TIMER 1 + DW ATIM2 ;(50, 32H) TIMER 2 + DW AT2CON ;(51, 33H) T2CON + DW ATCON ;(52, 34H) TCON + DW ATMOD ;(53, 35H) ATMOD + DW ARCAP2 ;(54, 36H) RCAP2 + DW AP1 ;(55, 37H) P1 + DW APCON ;(56, 38H) PCON + DW EXPRB ;(57, 39H) EVALUATE AN EXPRESSION + DW AXTAL1 ;(58, 3AH) CALCULATE CRYSTAL + DW LINE ;(59, 3BH) EDIT A LINE + DW PP ;(60, 3CH) PROCESS A LINE + DW UPPL-3 ;(61, 3DH) UNPROCESS A LINE + DW VAR ;(62, 3EH) FIND A VARIABLE + DW GC ;(63, 3FH) GET A CHARACTER + DW GCI ;(64, 40H) GET CHARACTER AND INCREMENT + DW INCHAR ;(65, 41H) INPUT A CHARACTER + DW CRUN ;(66, 42H) RUN A PROGRAM + newpage +OPBOL: DB 1 ; + ; + DB 15 ;LEFT PAREN + DB 14 ;EXPONENTIAN ** + DB 10 ;MUL + DB 8 ;ADD + DB 10 ;DIVIDE + DB 8 ;SUB + DB 3 ;XOR + DB 5 ;AND + DB 4 ;OR + DB 12 ;NEGATE + DB 6 ;EQ + DB 6 ;GT + DB 6 ;LT + DB 6 ;NE + DB 6 ;LE + DB 6 ;GE + ; +UOPBOL: DB 15 ;AABS + DB 15 ;AAINT + DB 15 ;ASGN + DB 15 ;ANOT + DB 15 ;ACOS + DB 15 ;ATAN + DB 15 ;ASIN + DB 15 ;ASQR + DB 15 ;ACBYTE + DB 15 ;E TO THE X + DB 15 ;AATAN + DB 15 ;NATURAL LOG + DB 15 ;DBYTE + DB 15 ;XBYTE + ; + newpage + ;*************************************************************** + ; + ; The ASCII printed messages. + ; + ;*************************************************************** + ; +STP: DB "STOP",'"' + ; +IAN: DB "TRY AGAIN",'"' + ; +RDYS: DB "READY",'"' + ; +INS: DB " - IN LINE ",'"' + ; + ;************************************************************** + ; + ; This is the command jump table + ; + ;************************************************************** + ; +CMNDD: DW CRUN ;RUN + DW CLIST ;LIST + DW CNULL ;NULL + DW CNEW ;NEW + DW CCONT ;CONTINUE + DW CPROG ;PROGRAM A PROM + DW CXFER ;TRANSFER FROM ROM TO RAM + DW CRAM ;RAM MODE + DW CROM ;ROM MODE + DW CIPROG ;INTELLIGENT PROM PROGRAMMING + ; + newpage + ;*************************************************************** + ; + ; This is the statement jump table. + ; + ;************************************************************** + ; +STATD: ; + DW SLET ;LET 80H + DW SCLR ;CLEAR 81H + DW SPUSH ;PUSH VAR 82H + DW SGOTO ;GO TO 83H + DW STONE ;TONE 84H + DW SPH0 ;PRINT MODE 0 85H + DW SUI ;USER INPUT 86H + DW SUO ;USER OUTPUT 87H + DW SPOP ;POP VAR 88H + DW SPRINT ;PRINT 89H + DW SCALL ;CALL 8AH + DW SDIMX ;DIMENSION 8BH + DW STRING ;STRING ALLO 8CH + DW SBAUD ;SET BAUD 8DH + DW SCLOCK ;CLOCK 8EH + DW SPH1 ;PRINT MODE 1 8FH + ; + ; No direct mode from here on + ; + DW SSTOP ;STOP 90H + DW SOT ;ON TIME 91H + DW SONEXT ;ON EXT INT 92H + DW SRETI ;RET FROM INT 93H + DW S_DO ;DO 94H + DW SRESTR ;RESTOR 95H + DW WCR ;REM 96H + DW SNEXT ;NEXT 97H + DW SONERR ;ON ERROR 98H + DW S_ON ;ON 99H + DW SINPUT ;INPUT 9AH + DW SREAD ;READ 9BH + DW FINDCR ;DATA 9CH + DW SRETRN ;RETURN 9DH + DW SIF ;IF 9EH + DW SGOSUB ;GOSUB 9FH + DW SFOR ;FOR A0H + DW SWHILE ;WHILE A1H + DW SUNTIL ;UNTIL A2H + DW CMND1 ;END A3H + DW I_DL ;IDLE A4H + DW ST_A ;STORE AT A5H + DW LD_A ;LOAD AT A6H + DW PGU ;PGM A7H + DW RROM ;RUN A ROM A9H + ; + newpage + ;************************************************************** + ; +TOKTAB: ; This is the basic token table + ; + ;************************************************************** + ; + ; First the tokens for statements + ; + DB 80H ;LET TOKEN + DB "LET" + ; + DB 81H ;CLEAR TOKEN + DB "CLEAR" + ; + DB 82H ;PUSH TOKEN + DB "PUSH" + ; +T_GOTO EQU 83H + ; + DB 83H ;GO TO TOKEN + DB "GOTO" + ; + DB 84H ;TOGGLE TOKEN + DB "PWM" + ; + DB 85H ;PRINT HEX MODE 0 + DB "PH0." + ; + DB 86H ;USER IN TOKEN + DB "UI" + ; + DB 87H ;USER OUT TOKEN + DB "UO" + ; + DB 88H ;POP TOKEN + DB "POP" + ; + newpage + DB 89H ;PRINT TOKEN + DB "PRINT" + DB 89H + DB "P." ;P. ALSO MEANS PRINT + DB 89H ;? ALSO + DB '?' + ; + DB 8AH ;CALL TOKEN + DB "CALL" + ; + DB 8BH ;DIMENSION TOKEN + DB "DIM" + ; + DB 8CH ;STRING TOKEN + DB "STRING" + ; + DB 8DH ;SET BAUD RATE + DB "BAUD" + ; + DB 8EH ;CLOCK + DB "CLOCK" + ; + DB 8FH ;PRINT HEX MODE 1 + DB "PH1." + ; +T_STOP EQU 90H ;STOP TOKEN + DB T_STOP + DB "STOP" + ; +T_DIR EQU T_STOP ;NO DIRECT FROM HERE ON + ; + DB T_STOP+1 ;ON TIMER INTERRUPT + DB "ONTIME" + ; + DB T_STOP+2 ;ON EXTERNAL INTERRUPT + DB "ONEX1" + ; + DB T_STOP+3 ;RETURN FROM INTERRUPT + DB "RETI" + ; + DB T_STOP+4 ;DO TOKEN + DB "DO" + ; + DB T_STOP+5 ;RESTORE TOKEN + DB "RESTORE" + ; + newpage +T_REM EQU T_STOP+6 ;REMARK TOKEN + DB T_REM + DB "REM" + ; + DB T_REM+1 ;NEXT TOKEN + DB "NEXT" + ; + DB T_REM+2 ;ON ERROR TOKEN + DB "ONERR" + ; + DB T_REM+3 ;ON TOKEN + DB "ON" + ; + DB T_REM+4 ;INPUT + DB "INPUT" + ; + DB T_REM+5 ;READ + DB "READ" + ; +T_DATA EQU T_REM+6 ;DATA + DB T_DATA + DB "DATA" + ; + DB T_DATA+1 ;RETURN + DB "RETURN" + ; + DB T_DATA+2 ;IF + DB "IF" + ; +T_GOSB EQU T_DATA+3 ;GOSUB + DB T_GOSB + DB "GOSUB" + ; + DB T_GOSB+1 ;FOR + DB "FOR" + ; + DB T_GOSB+2 ;WHILE + DB "WHILE" + ; + DB T_GOSB+3 ;UNTIL + DB "UNTIL" + ; + DB T_GOSB+4 ;END + DB "END" + ; + newpage +T_LAST EQU T_GOSB+5 ;LAST INITIAL TOKEN + ; +T_TAB EQU T_LAST ;TAB TOKEN + DB T_TAB + DB "TAB" + ; +T_THEN EQU T_LAST+1 ;THEN TOKEN + DB T_THEN + DB "THEN" + ; +T_TO EQU T_LAST+2 ;TO TOKEN + DB T_TO + DB "TO" + ; +T_STEP EQU T_LAST+3 ;STEP TOKEN + DB T_STEP + DB "STEP" + ; +T_ELSE EQU T_LAST+4 ;ELSE TOKEN + DB T_ELSE + DB "ELSE" + ; +T_SPC EQU T_LAST+5 ;SPACE TOKEN + DB T_SPC + DB "SPC" + ; +T_CR EQU T_LAST+6 + DB T_CR + DB "CR" + ; + DB T_CR+1 + DB "IDLE" + ; + DB T_CR+2 + DB "ST@" + ; + DB T_CR+3 + DB "LD@" + ; + DB T_CR+4 + DB "PGM" + ; + DB T_CR+5 + DB "RROM" + ; + newpage + ; Operator tokens + ; +T_LPAR EQU 0E0H ;LEFT PAREN + DB T_LPAR + DB '(' + ; + DB T_LPAR+1 ;EXPONENTIAN + DB "**" + ; + DB T_LPAR+2 ;FP MULTIPLY + DB '*' + ; +T_ADD EQU T_LPAR+3 + DB T_LPAR+3 ;ADD TOKEN + DB '+' + ; + DB T_LPAR+4 ;DIVIDE TOKEN + DB '/' + ; +T_SUB EQU T_LPAR+5 ;SUBTRACT TOKEN + DB T_SUB + DB '-' + ; + DB T_LPAR+6 ;LOGICAL EXCLUSIVE OR + DB ".XOR." + ; + DB T_LPAR+7 ;LOGICAL AND + DB ".AND." + ; + DB T_LPAR+8 ;LOGICAL OR + DB ".OR." + ; +T_NEG EQU T_LPAR+9 + ; +T_EQU EQU T_LPAR+10 ;EQUAL + DB T_EQU + DB '=' + ; + DB T_LPAR+11 ;GREATER THAN OR EQUAL + DB ">=" + ; + DB T_LPAR+12 ;LESS THAN OR EQUAL + DB "<=" + ; + DB T_LPAR+13 ;NOT EQUAL + DB "<>" + ; + DB T_LPAR+14 ;LESS THAN + DB '<' + ; + DB T_LPAR+15 ;GREATER THAN + DB '>' + ; + ; +T_UOP EQU 0B0H ;UNARY OP BASE TOKEN + ; + DB T_UOP ;ABS TOKEN + DB "ABS" + ; + DB T_UOP+1 ;INTEGER TOKEN + DB "INT" + ; + DB T_UOP+2 ;SIGN TOKEN + DB "SGN" + ; + DB T_UOP+3 ;GET TOKEN + DB "NOT" + ; + DB T_UOP+4 ;COSINE TOKEN + DB "COS" + ; + DB T_UOP+5 ;TANGENT TOKEN + DB "TAN" + ; + DB T_UOP+6 ;SINE TOKEN + DB "SIN" + ; + DB T_UOP+7 ;SQUARE ROOT TOKEN + DB "SQR" + ; + DB T_UOP+8 ;CBYTE TOKEN + DB "CBY" + ; + DB T_UOP+9 ;EXP (E TO THE X) TOKEN + DB "EXP" + ; + DB T_UOP+10 + DB "ATN" + ; + DB T_UOP+11 + DB "LOG" + ; + DB T_UOP+12 ;DBYTE TOKEN + DB "DBY" + ; + DB T_UOP+13 ;XBYTE TOKEN + DB "XBY" + ; +T_ULAST EQU T_UOP+14 ;LAST OPERATOR NEEDING PARENS + ; + DB T_ULAST + DB "PI" + ; + DB T_ULAST+1 ;RND TOKEN + DB "RND" + ; + DB T_ULAST+2 ;GET TOKEN + DB "GET" + ; + DB T_ULAST+3 ;FREE TOKEN + DB "FREE" + ; + DB T_ULAST+4 ;LEN TOKEN + DB "LEN" + ; +T_XTAL EQU T_ULAST+5 ;CRYSTAL TOKEN + DB T_XTAL + DB "XTAL" + ; +T_MTOP EQU T_ULAST+6 ;MTOP + DB T_MTOP + DB "MTOP" + ; +T_IE EQU T_ULAST+8 ;IE REGISTER + DB T_IE + DB "IE" + ; +T_IP EQU T_ULAST+9 ;IP REGISTER + DB T_IP + DB "IP" + ; +TMR0 EQU T_ULAST+10 ;TIMER 0 + DB TMR0 + DB "TIMER0" + ; +TMR1 EQU T_ULAST+11 ;TIMER 1 + DB TMR1 + DB "TIMER1" + ; +TMR2 EQU T_ULAST+12 ;TIMER 2 + DB TMR2 + DB "TIMER2" + ; +T_TIME EQU T_ULAST+7 ;TIME + DB T_TIME + DB "TIME" + ; +TT2C EQU T_ULAST+13 ;T2CON + DB TT2C + DB "T2CON" + ; +TTC EQU T_ULAST+14 ;TCON + DB TTC + DB "TCON" + ; +TTM EQU T_ULAST+15 ;TMOD + DB TTM + DB "TMOD" + ; +TRC2 EQU T_ULAST+16 ;RCAP2 + DB TRC2 + DB "RCAP2" + ; +T_P1 EQU T_ULAST+17 ;P1 + DB T_P1 + DB "PORT1" + ; +T_PC EQU T_ULAST+18 ;PCON + DB T_PC + DB "PCON" + ; +T_ASC EQU T_ULAST+19 ;ASC TOKEN + DB T_ASC + DB "ASC(" + ; +T_USE EQU T_ULAST+20 ;USING TOKEN + DB T_USE + DB "USING(" + DB T_USE + DB "U.(" + ; +T_CHR EQU T_ULAST+21 ;CHR TOKEN + DB T_CHR + DB "CHR(" + ; + newpage +T_CMND EQU 0F0H ;COMMAND BASE + ; + DB 0F0H ;RUN TOKEN + DB "RUN" + ; + DB 0F1H ;LIST TOKEN + DB "LIST" + ; + DB 0F2H ;NULL TOKEN + DB "NULL" + ; + DB 0F3H ;NEW TOKEN + DB "NEW" + ; + DB 0F4H ;CONTINUE TOKEN + DB "CONT" + ; + DB 0F5H ;PROGRAM TOKEN + DB "PROG" + ; + DB 0F6H ;TRANSFER TOKEN + DB "XFER" + ; + DB 0F7H ;RAM MODE + DB "RAM" + ; + DB 0F8H ;ROM MODE + DB "ROM" + ; + DB 0F9H ;INTELLIGENT PROM PROGRAMMING + DB "FPROG" + ; + DB 0FFH ;END OF TABLE + ; diff --git a/tests/t_bas52/t_bas52.asm b/tests/t_bas52/t_bas52.asm new file mode 100644 index 0000000..3fff5d8 --- /dev/null +++ b/tests/t_bas52/t_bas52.asm @@ -0,0 +1,4644 @@ +; December 18, 1986 +; MS-DOS compatible Source code for MCS BASIC-52 (tm) +; Assembles with ASM51 Macro Assembler Version 2.2 +; +; The following source code does not include the floating point math +; routines. These are seperately compiled using FP52.SRC. +; +; Both the BASIC.SRC and FP52.SRC programs assemble into ABSOLUTE +; object files, and do not need to be relocated or linked. The FP52 +; object code and the BASIC object code, when compiled without modification +; of the source listings, create the same object code that is found on +; the MCS BASIC-52 Version 1.1 microcontrollers. +; +; The original source code had 7 "include" files that have been incorporated +; into this file for ease of assembly. +; These 7 files are: LOOK52.SRC, BAS52.RST, BAS52.PGM, BAS52.TL, BAS52.OUT, +; BAS52.PWM, and BAS52.CLK. +; +; +; Intel Corporation, Embedded Controller Operations + + cpu 8052 + + page 0 + newpage + + include stddef51.inc + include bitfuncs.inc + bigendian on + + segment code + + ;************************************************************** + ; + ; TRAP VECTORS TO MONITOR + ; + ; RESET TAG (0AAH) ---------2001H + ; + ; TAG LOCATION (5AH) ------ 2002H + ; + ; EXTERNAL INTERRUPT 0 ---- 2040H + ; + ; COMMAND MODE ENTRY ------ 2048H + ; + ; SERIAL PORT ------------- 2050H + ; + ; MONITOR (BUBBLE) OUTPUT - 2058H + ; + ; MONITOR (BUBBLE) INPUT -- 2060H + ; + ; MONITOR (BUBBLE) CSTS --- 2068H + ; + ; GET USER JUMP VECTOR ---- 2070H + ; + ; GET USER LOOKUP VECTOR -- 2078H + ; + ; PRINT AT VECTOR --------- 2080H + ; + ; INTERRUPT PWM ----------- 2088H + ; + ; EXTERNAL RESET ---------- 2090H + ; + ; USER OUTPUT-------------- 4030H + ; + ; USER INPUT -------------- 4033H + ; + ; USER CSTS --------------- 4036H + ; + ; USER RESET -------------- 4039H + ; + ; USER DEFINED PRINT @ --- 403CH + ; + ;*************************************************************** + ; + newpage + ;*************************************************************** + ; + ; MCS - 51 - 8K BASIC VERSION 1.1 + ; + ;*************************************************************** + ; + AJMP CRST ;START THE PROGRAM + db 037h ; ******AA inserted + ; + ORG 3H + ; + ;*************************************************************** + ; + ;EXTERNAL INTERRUPT 0 + ; + ;*************************************************************** + ; + JB DRQ,STQ ;SEE IF DMA IS SET + PUSH PSW ;SAVE THE STATUS + LJMP 4003H ;JUMP TO USER IF NOT SET + ; + ORG 0BH + ; + ;*************************************************************** + ; + ;TIMER 0 OVERFLOW INTERRUPT + ; + ;*************************************************************** + ; + PUSH PSW ;SAVE THE STATUS + JB C_BIT,STJ ;SEE IF USER WANTS INTERRUPT + LJMP 400BH ;EXIT IF USER WANTS INTERRUPTS + ; + ORG 13H + ; + ;*************************************************************** + ; + ;EXTERNAL INTERRUPT 1 + ; + ;*************************************************************** + ; + JB INTBIT,STK + PUSH PSW + LJMP 4013H + ; + newpage + ; + ORG 1BH + ; + ;*************************************************************** + ; + ;TIMER 1 OVERFLOW INTERRUPT + ; + ;*************************************************************** + ; + PUSH PSW + LJMP CKS_I + ; +STJ: LJMP I_DR ;DO THE INTERRUPT + ; + ;*************************************************************** + ; + ;SERIAL PORT INTERRUPT + ; + ;*************************************************************** + ; + ORG 23H + ; + PUSH PSW + JB SPINT,STU ;SEE IF MONITOR EANTS INTERRUPT + LJMP 4023H + ; + ORG 2BH + ; + ;************************************************************** + ; + ;TIMER 2 OVERFLOW INTERRUPT + ; + ;************************************************************** + ; + PUSH PSW + LJMP 402BH + ; + newpage + ;************************************************************** + ; + ;USER ENTRY + ; + ;************************************************************** + ; + ORG 30H + ; + LJMP IBLK ;LINK TO USER BLOCK + ; +STQ: JB I_T0,STS ;SEE IF MONITOR WANTS IT + CLR DACK + JNB P3.2,$ ;WAIT FOR DMA TO END + SETB DACK + RETI + ; +STS: LJMP 2040H ;GO TO THE MONITOR + ; +STK: SETB INTPEN ;TELL BASIC AN INTERRUPT WAS RECEIVED + RETI + ; +STU: LJMP 2050H ;SERIAL PORT INTERRUPT + ; + newpage + + include look52.inc ; ******AA + +EIG: DB "EXTRA IGNORED",'"' + ; +EXA: DB "A-STACK",'"' + ; +EXC: DB "C-STACK",'"' + ; + newpage + + include bas52.rst ; ******AA + + newpage + ;*************************************************************** + ; + ; CIPROG AND CPROG - Program a prom + ; + ;*************************************************************** + ; + include bas52.pgm ; ******AA + newpage + ;************************************************************** + ; +PGU: ;PROGRAM A PROM FOR THE USER + ; + ;************************************************************** + ; + CLR PROMV ;TURN ON THE VOLTAGE + MOV PSW,#00011000B ;SELECT RB3 + ACALL PG1 ;DO IT + SETB PROMV ;TURN IT OFF + RET + ; + ; + ;************************************************************* + ; +CCAL: ; Set up for prom moves + ; R3:R1 gets source + ; R7:R6 gets # of bytes + ; + ;************************************************************* + ; + ACALL GETEND ;GET THE LAST LOCATION + INC DPTR ;BUMP TO LOAD EOF + MOV R3,BOFAH + MOV R1,BOFAL ;RESTORE START + CLR C ;PREPARE FOR SUBB + MOV A,DPL ;SUB DPTR - BOFA > R7:R6 + SUBB A,R1 + MOV R6,A + MOV A,DPH + SUBB A,R3 + MOV R7,A + RET + ; + ; + include bas52.tl ; ******AA + newpage + ;*************************************************************** + ; +CROM: ; The command action routine - ROM - Run out of rom + ; + ;*************************************************************** + ; + CLR CONB ;CAN'T CONTINUE IF MODE CHANGE + ACALL RO1 ;DO IT + ; +C_K: LJMP CL3 ;EXIT + ; +RO1: LCALL DELTST ;SEE IF INTGER PRESENT ******AA CALL-->LCALL, INTGER-->DELTST + MOV R4,#R1B0 ;SAVE THE NUMBER ******AA ABS-->IMM, R0B0-->R0B1 ?!? + JNC $+6 ; ******AA $+4-->$+6 ??? + ;MOV R4,#01H ;ONE IF NO INTEGER PRESENT ******AA repl. by next two + LCALL ONE ; ******AA + MOV R4,A ; ******AA + ACALL ROMFD ;FIND THE PROGRAM + CJNE R4,#0,RFX ;EXIT IF R4 <> 0 + INC DPTR ;BUMP PAST TAG + MOV BOFAH,DPH ;SAVE THE ADDRESS + MOV BOFAL,DPL + RET + ; +ROMFD: MOV DPTR,#ROMADR+16 ;START OF USER PROGRAM + ; +RF1: MOVX A,@DPTR ;GET THE BYTE + CJNE A,#55H,RF3 ;SEE IF PROPER TAG + DJNZ R4,RF2 ;BUMP COUNTER + ; +RFX: RET ;DPTR HAS THE START ADDRESS + ; +RF2: INC DPTR ;BUMP PAST TAG + ACALL G5 + INC DPTR ;BUMP TO NEXT PROGRAM + SJMP RF1 ;DO IT AGAIN + ; +RF3: JBC INBIT,RFX ;EXIT IF SET + ; +NOGO: MOV DPTR,#NOROM + AJMP ERRLK + ; + newpage + ;*************************************************************** + ; +L20DPI: ; load R2:R0 with the location the DPTR is pointing to + ; + ;*************************************************************** + ; + MOVX A,@DPTR + MOV R2,A + INC DPTR + MOVX A,@DPTR + MOV R0,A + RET ;DON'T BUMP DPTR + ; + ;*************************************************************** + ; +X31DP: ; swap R3:R1 with DPTR + ; + ;*************************************************************** + ; + XCH A,R3 + XCH A,DPH + XCH A,R3 + XCH A,R1 + XCH A,DPL + XCH A,R1 + RET + ; + ;*************************************************************** + ; +LD_T: ; Load the timer save location with the value the DPTR is + ; pointing to. + ; + ;**************************************************************** + ; + MOVX A,@DPTR + MOV T_HH,A + INC DPTR + MOVX A,@DPTR + MOV T_LL,A + RET + ; + newpage + ; + ;*************************************************************** + ; + ;GETLIN - FIND THE LOCATION OF THE LINE NUMBER IN R3:R1 + ; IF ACC = 0 THE LINE WAS NOT FOUND I.E. R3:R1 + ; WAS TOO BIG, ELSE ACC <> 0 AND THE DPTR POINTS + ; AT THE LINE THAT IS GREATER THAN OR EQUAL TO THE + ; VALUE IN R3:R1. + ; + ;*************************************************************** + ; +GETEND: SETB ENDBIT ;GET THE END OF THE PROGRAM + ; +GETLIN: LCALL DP_B ;GET BEGINNING ADDRESS ******AA CALL-->LCALL + ; +G1: LCALL B_C ; ******AA CALL-->LCALL + JZ G3 ;EXIT WITH A ZERO IN A IF AT END + INC DPTR ;POINT AT THE LINE NUMBER + JB ENDBIT,G2 ;SEE IF WE WANT TO FIND THE END + ACALL DCMPX ;SEE IF (DPTR) = R3:R1 + ACALL DECDP ;POINT AT LINE COUNT + MOVX A,@DPTR ;PUT LINE LENGTH INTO ACC + JB UBIT,G3 ;EXIT IF EQUAL + JC G3 ;SEE IF LESS THAN OR ZERO + ; +G2: ACALL ADDPTR ;ADD IT TO DPTR + SJMP G1 ;LOOP + ; +G3: CLR ENDBIT ;RESET ENDBIT + RET ;EXIT + ; +G4: MOV DPTR,#PSTART ;DO RAM + ; +G5: SETB ENDBIT + SJMP G1 ;NOW DO TEST + ; + newpage + ;*************************************************************** + ; + ; LDPTRI - Load the DATA POINTER with the value it is pointing + ; to - DPH = (DPTR) , DPL = (DPTR+1) + ; + ; acc gets wasted + ; + ;*************************************************************** + ; +LDPTRI: MOVX A,@DPTR ;GET THE HIGH BYTE + PUSH ACC ;SAVE IT + INC DPTR ;BUMP THE POINTER + MOVX A,@DPTR ;GET THE LOW BYTE + MOV DPL,A ;PUT IT IN DPL + POP DPH ;GET THE HIGH BYTE + RET ;GO BACK + ; + ;*************************************************************** + ; + ;L31DPI - LOAD R3 WITH (DPTR) AND R1 WITH (DPTR+1) + ; + ;ACC GETS CLOBBERED + ; + ;*************************************************************** + ; +L31DPI: MOVX A,@DPTR ;GET THE HIGH BYTE + MOV R3,A ;PUT IT IN THE REG + INC DPTR ;BUMP THE POINTER + MOVX A,@DPTR ;GET THE NEXT BYTE + MOV R1,A ;SAVE IT + RET + ; + ;*************************************************************** + ; + ;DECDP - DECREMENT THE DATA POINTER - USED TO SAVE SPACE + ; + ;*************************************************************** + ; +DECDP2: ACALL DECDP + ; +DECDP: XCH A,DPL ;GET DPL + JNZ $+4 ;BUMP IF ZERO + DEC DPH + DEC A ;DECREMENT IT + XCH A,DPL ;GET A BACK + RET ;EXIT + ; + newpage + ;*************************************************************** + ; + ;DCMPX - DOUBLE COMPARE - COMPARE (DPTR) TO R3:R1 + ;R3:R1 - (DPTR) = SET CARRY FLAG + ; + ;IF R3:R1 > (DPTR) THEN C = 0 + ;IF R3:R1 < (DPTR) THEN C = 1 + ;IF R3:R1 = (DPTR) THEN C = 0 + ; + ;*************************************************************** + ; +DCMPX: CLR UBIT ;ASSUME NOT EQUAL + MOVX A,@DPTR ;GET THE BYTE + CJNE A,R3B0,D1 ;IF A IS GREATER THAN R3 THEN NO CARRY + ;WHICH IS R3<@DPTR = NO CARRY AND + ;R3>@DPTR CARRY IS SET + INC DPTR ;BUMP THE DATA POINTER + MOVX A,@DPTR ;GET THE BYTE + ACALL DECDP ;PUT DPTR BACK + CJNE A,R1B0,D1 ;DO THE COMPARE + CPL C ;FLIP CARRY + ; + CPL UBIT ;SET IT +D1: CPL C ;GET THE CARRY RIGHT + RET ;EXIT + ; + ;*************************************************************** + ; + ; ADDPTR - Add acc to the dptr + ; + ; acc gets wasted + ; + ;*************************************************************** + ; +ADDPTR: ADD A,DPL ;ADD THE ACC TO DPL + MOV DPL,A ;PUT IT IN DPL + JNC $+4 ;JUMP IF NO CARRY + INC DPH ;BUMP DPH + RET ;EXIT + ; + newpage + ;************************************************************* + ; +LCLR: ; Set up the storage allocation + ; + ;************************************************************* + ; + ACALL ICLR ;CLEAR THE INTERRUPTS + ACALL G4 ;PUT END ADDRESS INTO DPTR + MOV A,#6 ;ADJUST MATRIX SPACE + ACALL ADDPTR ;ADD FOR PROPER BOUNDS + ACALL X31DP ;PUT MATRIX BOUNDS IN R3:R1 + MOV DPTR,#MT_ALL ;SAVE R3:R1 IN MATRIX FREE SPACE + ACALL S31DP ;DPTR POINTS TO MEMTOP + ACALL L31DPI ;LOAD MEMTOP INTO R3:R1 + MOV DPTR,#STR_AL ;GET MEMORY ALLOCATED FOR STRINGS + ACALL LDPTRI + LCALL DUBSUB ;R3:R1 = MEMTOP - STRING ALLOCATION ******AA CALL-->LCALL + MOV DPTR,#VARTOP ;SAVE R3:R1 IN VARTOP + ; + ; FALL THRU TO S31DP2 + ; + ;*************************************************************** + ; + ;S31DP - STORE R3 INTO (DPTR) AND R1 INTO (DPTR+1) + ; + ;ACC GETS CLOBBERED + ; + ;*************************************************************** + ; +S31DP2: ACALL S31DP ;DO IT TWICE + ; +S31DP: MOV A,R3 ;GET R3 INTO ACC + MOVX @DPTR,A ;STORE IT + INC DPTR ;BUMP DPTR + MOV A,R1 ;GET R1 + MOVX @DPTR,A ;STORE IT + INC DPTR ;BUMP IT AGAIN TO SAVE PROGRAM SPACE + RET ;GO BACK + ; + ; + ;*************************************************************** + ; +STRING: ; Allocate memory for strings + ; + ;*************************************************************** + ; + LCALL TWO ;R3:R1 = NUMBER, R2:R0 = LEN + MOV DPTR,#STR_AL ;SAVE STRING ALLOCATION + ACALL S31DP + INC R6 ;BUMP + MOV S_LEN,R6 ;SAVE STRING LENGTH + AJMP RCLEAR ;CLEAR AND SET IT UP + ; + newpage + ;*************************************************************** + ; + ; F_VAR - Find the variable in symbol table + ; R7:R6 contain the variable name + ; If not found create a zero entry and set the carry + ; R2:R0 has the address of variable on return + ; + ;*************************************************************** + ; +F_VAR: MOV DPTR,#VARTOP ;PUT VARTOP IN DPTR + ACALL LDPTRI + ACALL DECDP2 ;ADJUST DPTR FOR LOOKUP + ; +F_VAR0: MOVX A,@DPTR ;LOAD THE VARIABLE + JZ F_VAR2 ;TEST IF AT THE END OF THE TABLE + INC DPTR ;BUMP FOR NEXT BYTE + CJNE A,R7B0,F_VAR1 ;SEE IF MATCH + MOVX A,@DPTR ;LOAD THE NAME + CJNE A,R6B0,F_VAR1 + ; + ; Found the variable now adjust and put in R2:R0 + ; +DLD: MOV A,DPL ;R2:R0 = DPTR-2 + SUBB A,#2 + MOV R0,A + MOV A,DPH + SUBB A,#0 ;CARRY IS CLEARED + MOV R2,A + RET + ; +F_VAR1: MOV A,DPL ;SUBTRACT THE STACK SIZE+ADJUST + CLR C + SUBB A,#STESIZ + MOV DPL,A ;RESTORE DPL + JNC F_VAR0 + DEC DPH + SJMP F_VAR0 ;CONTINUE COMPARE + ; + newpage + ; + ; Add the entry to the symbol table + ; +F_VAR2: LCALL R76S ;SAVE R7 AND R6 + CLR C + ACALL DLD ;BUMP THE POINTER TO GET ENTRY ADDRESS + ; + ; Adjust pointer and save storage allocation + ; and make sure we aren't wiping anything out + ; First calculate new storage allocation + ; + MOV A,R0 + SUBB A,#STESIZ-3 ;NEED THIS MUCH RAM + MOV R1,A + MOV A,R2 + SUBB A,#0 + MOV R3,A + ; + ; Now save the new storage allocation + ; + MOV DPTR,#ST_ALL + CALL S31DP ;SAVE STORAGE ALLOCATION + ; + ; Now make sure we didn't blow it, by wiping out MT_ALL + ; + ACALL DCMPX ;COMPARE STORAGE ALLOCATION + JC CCLR3 ;ERROR IF CARRY + SETB C ;DID NOT FIND ENTRY + RET ;EXIT IF TEST IS OK + ; + newpage + ;*************************************************************** + ; + ; Command action routine - NEW + ; + ;*************************************************************** + ; +CNEW: MOV DPTR,#PSTART ;SAVE THE START OF PROGRAM + MOV A,#EOF ;END OF FILE + MOVX @DPTR,A ;PUT IT IN MEMORY + ; + ; falls thru + ; + ;***************************************************************** + ; + ; The statement action routine - CLEAR + ; + ;***************************************************************** + ; + CLR LINEB ;SET UP FOR RUN AND GOTO + ; +RCLEAR: ACALL LCLR ;CLEAR THE INTERRUPTS, SET UP MATRICES + MOV DPTR,#MEMTOP ;PUT MEMTOP IN R3:R1 + ACALL L31DPI + ACALL G4 ;DPTR GETS END ADDRESS + ACALL CL_1 ;CLEAR THE MEMORY + ; +RC1: MOV DPTR,#STACKTP ;POINT AT CONTROL STACK TOP + CLR A ;CONTROL UNDERFLOW + ; +RC2: MOVX @DPTR,A ;SAVE IN MEMORY + MOV CSTKA,#STACKTP + MOV ASTKA,#STACKTP + CLR CONB ;CAN'T CONTINUE + RET + ; + newpage + ;*************************************************************** + ; + ; Loop until the memory is cleared + ; + ;*************************************************************** + ; +CL_1: INC DPTR ;BUMP MEMORY POINTER + CLR A ;CLEAR THE MEMORY + MOVX @DPTR,A ;CLEAR THE RAM + MOVX A,@DPTR ;READ IT + JNZ CCLR3 ;MAKE SURE IT IS CLEARED + MOV A,R3 ;GET POINTER FOR COMPARE + CJNE A,DPH,CL_1 ;SEE TO LOOP + MOV A,R1 ;NOW TEST LOW BYTE + CJNE A,DPL,CL_1 + ; +CL_2: RET + ; +CCLR3: LJMP TB ;ALLOCATED MEMORY DOESN'T EXSIST ******AA JMP-->LJMP + ; + ;************************************************************** + ; +SCLR: ;Entry point for clear return + ; + ;************************************************************** + ; + LCALL DELTST ;TEST FOR A CR ******AA CALL-->LCALL + JNC RCLEAR + LCALL GCI1 ;BUMP THE TEST POINTER ******AA CALL-->LCALL + CJNE A,#'I',RC1 ;SEE IF I, ELSE RESET THE STACK + ; + ;************************************************************** + ; +ICLR: ; Clear interrupts and system garbage + ; + ;************************************************************** + ; + JNB INTBIT,$+5 ;SEE IF BASIC HAS INTERRUPTS + CLR EX1 ;IF SO, CLEAR INTERRUPTS + ANL 34,#00100000B ;SET INTERRUPTS + CONTINUE + RETI + ; + newpage + ;*************************************************************** + ; + ;OUTPUT ROUTINES + ; + ;*************************************************************** + ; +CRLF2: ACALL CRLF ;DO TWO CRLF'S + ; +CRLF: MOV R5,#CR ;LOAD THE CR + ACALL TEROT ;CALL TERMINAL OUT + MOV R5,#LF ;LOAD THE LF + AJMP TEROT ;OUTPUT IT AND RETURN + ; + ;PRINT THE MESSAGE ADDRESSED IN ROM OR RAM BY THE DPTR + ;ENDS WITH THE CHARACTER IN R4 + ;DPTR HAS THE ADDRESS OF THE TERMINATOR + ; +CRP: ACALL CRLF ;DO A CR THEN PRINT ROM + ; +ROM_P: CLR A ;CLEAR A FOR LOOKUP + MOVC A,@A+DPTR ;GET THE CHARACTER + CLR ACC.7 ;CLEAR MS BIT + CJNE A,#'"',$+4 ;EXIT IF TERMINATOR + RET + SETB C0ORX1 + ; +PN1: MOV R5,A ;OUTPUT THE CHARACTER + ACALL TEROT + INC DPTR ;BUMP THE POINTER + SJMP PN0 + ; +UPRNT: ACALL X31DP + ; +PRNTCR: MOV R4,#CR ;OUTPUT UNTIL A CR + ; +PN0: JBC C0ORX1,ROM_P + MOVX A,@DPTR ;GET THE RAM BYTE + JZ $+5 + CJNE A,R4B0,$+4 ;SEE IF THE SAME AS TERMINATOR + RET ;EXIT IF THE SAME + CJNE A,#CR,PN1 ;NEVER PRINT A CR IN THIS ROUTINE + LJMP E1XX ;BAD SYNTAX + ; + newpage + ;*************************************************************** + ; + ; INLINE - Input a line to IBUF, exit when a CR is received + ; + ;*************************************************************** + ; +INL2: CJNE A,#CNTRLD,INL2B ;SEE IF A CONTROL D + ; +INL0: ACALL CRLF ;DO A CR + ; +INLINE: MOV P2,#HI(IBUF) ;IBUF IS IN THE ZERO PAGE + MOV R0,#LO(IBUF) ;POINT AT THE INPUT BUFFER + ; +INL1: ACALL INCHAR ;GET A CHARACTER + MOV R5,A ;SAVE IN R5 FOR OUTPUT + CJNE A,#7FH,INL2 ;SEE IF A DELETE CHARACTER + CJNE R0,#LO(IBUF),INL6 + MOV R5,#BELL ;OUTPUT A BELL + ; +INLX: ACALL TEROT ;OUTPUT CHARACTER + SJMP INL1 ;DO IT AGAIN + ; +INL2B: MOVX @R0,A ;SAVE THE CHARACTER + CJNE A,#CR,$+5 ;IS IT A CR + AJMP CRLF ;OUTPUT A CRLF AND EXIT + CJNE A,#20H,$+3 + JC INLX ;ONLY ECHO CONTROL CHARACTERS + INC R0 ;BUMP THE POINTER + CJNE R0,#IBUF+79,INLX + DEC R0 ;FORCE 79 + SJMP INLX-2 ;OUTPUT A BELL + ; +INL6: DEC R0 ;DEC THE RAM POINTER + MOV R5,#BS ;OUTPUT A BACK SPACE + ACALL TEROT + ACALL STEROT ;OUTPUT A SPACE + MOV R5,#BS ;ANOTHER BACK SPACE + SJMP INLX ;OUTPUT IT + ; +PTIME: DB 128-2 ; PROM PROGRAMMER TIMER + DB 00H + DB 00H + DB 50H + DB 67H + DB 41H + ; + newpage + include bas52.out ; ******AA + ; +BCK: ACALL CSTS ;CHECK STATUS + JNC CI_RET+1 ;EXIT IF NO CHARACTER + ; + newpage + ;*************************************************************** + ; + ;INPUTS A CHARACTER FROM THE SYSTEM CONSOLE. + ; + ;*************************************************************** + ; +INCHAR: JNB BI,$+8 ;CHECK FOR MONITOR (BUBBLE) + LCALL 2060H + SJMP INCH1 + JNB CIUB,$+8 ;CHECK FOR USER + LCALL 4033H + SJMP INCH1 + JNB RI,$ ;WAIT FOR RECEIVER READY. + MOV A,SBUF + CLR RI ;RESET READY + CLR ACC.7 ;NO BIT 7 + ; +INCH1: CJNE A,#13H,$+5 + SETB CNT_S + CJNE A,#11H,$+5 + CLR CNT_S + CJNE A,#CNTRLC,$+7 + JNB NO_C,C_EX ;TRAP NO CONTROL C + RET + ; + CLR JKBIT + CJNE A,#17H,CI_RET ;CONTROL W + SETB JKBIT + ; +CI_RET: SETB C ;CARRY SET IF A CHARACTER + RET ;EXIT + ; + ;************************************************************* + ; + ;RROM - The Statement Action Routine RROM + ; + ;************************************************************* + ; +RROM: SETB INBIT ;SO NO ERRORS + ACALL RO1 ;FIND THE LINE NUMBER + JBC INBIT,CRUN + RET ;EXIT + ; + newpage + ;*************************************************************** + ; +CSTS: ; RETURNS CARRY = 1 IF THERE IS A CHARACTER WAITING FROM + ; THE SYSTEM CONSOLE. IF NO CHARACTER THE READY CHARACTER + ; WILL BE CLEARED + ; + ;*************************************************************** + ; + JNB BI,$+6 ;BUBBLE STATUS + LJMP 2068H + JNB CIUB,$+6 ;SEE IF EXTERNAL CONSOLE + LJMP 4036H + MOV C,RI + RET + ; + MOV DPTR,#WB ;EGO MESSAGE + ACALL ROM_P + ; +C_EX: CLR CNT_S ;NO OUTPUT STOP + LCALL SPRINT+4 ;ASSURE CONSOLE + ACALL CRLF + JBC JKBIT,C_EX-5 + ; + JNB DIRF,SSTOP0 + AJMP C_K ;CLEAR COB AND EXIT + ; +T_CMP: MOV A,TVH ;COMPARE TIMER TO SP_H AND SP_L + MOV R1,TVL + CJNE A,TVH,T_CMP + XCH A,R1 + SUBB A,SP_L + MOV A,R1 + SUBB A,SP_H + RET + ; + ;************************************************************* + ; +BR0: ; Trap the timer interrupt + ; + ;************************************************************* + ; + CALL T_CMP ;COMPARE TIMER + JC BCHR+6 ;EXIT IF TEST FAILS + SETB OTI ;DOING THE TIMER INTERRUPT + CLR OTS ;CLEAR TIMER BIT + MOV C,INPROG ;SAVE IN PROGRESS + MOV ISAV,C + MOV DPTR,#TIV + SJMP BR2 + ; + newpage + ;*************************************************************** + ; + ; The command action routine - RUN + ; + ;*************************************************************** + ; +CRUN: LCALL RCLEAR-2 ;CLEAR THE STORAGE ARRAYS + ACALL SRESTR+2 ;GET THE STARTING ADDRESS + ACALL B_C + JZ CMNDLK ;IF NULL GO TO COMMAND MODE + ; + ACALL T_DP + ACALL B_TXA ;BUMP TO STARTING LINE + ; +CILOOP: ACALL SP0 ;DO A CR AND A LF + CLR DIRF ;NOT IN DIRECT MODE + ; + ;INTERPERTER DRIVER + ; +ILOOP: MOV SP,SPSAV ;RESTORE THE STACK EACH TIME + JB DIRF,$+9 ;NO INTERRUPTS IF IN DIRECT MODE + MOV INTXAH,TXAH ;SAVE THE TEXT POINTER + MOV INTXAL,TXAL + LCALL BCK ;GET CONSOLE STATUS + JB DIRF,I_L ;DIRECT MODE + ANL C,/GTRD ;SEE IF CHARACTER READY + JNC BCHR ;NO CHARACTER = NO CARRY + ; + ; DO TRAP OPERATION + ; + MOV DPTR,#GTB ;SAVE TRAP CHARACTER + MOVX @DPTR,A + SETB GTRD ;SAYS READ A BYTE + ; +BCHR: JB OTI,I_L ;EXIT IF TIMER INTERRUPT IN PROGRESS + JB OTS,BR0 ;TEST TIMER VALUE IF SET + JNB INTPEN,I_L ;SEE IF INTERRUPT PENDING + JB INPROG,I_L ;DON'T DO IT AGAIN IF IN PROGRESS + MOV DPTR,#INTLOC ;POINT AT INTERRUPT LOCATION + ; +BR2: MOV R4,#GTYPE ;SETUP FOR A FORCED GOSUB + ACALL SGS1 ;PUT TXA ON STACK + SETB INPROG ;INTERRUPT IN PROGRESS + ; +ERL4: CALL L20DPI + AJMP D_L1 ;GET THE LINE NUMBER + ; +I_L: ACALL ISTAT ;LOOP + ACALL CLN_UP ;FINISH IT OFF + JNC ILOOP ;LOOP ON THE DRIVER + JNB DIRF,CMNDLK ;CMND1 IF IN RUN MODE + LJMP CMNDR ;DON'T PRINT READY + ; +CMNDLK: LJMP CMND1 ;DONE ******AA JMP-->LJMP + newpage + ;************************************************************** + ; + ; The Statement Action Routine - STOP + ; + ;************************************************************** + ; +SSTOP: ACALL CLN_UP ;FINISH OFF THIS LINE + MOV INTXAH,TXAH ;SAVE TEXT POINTER FOR CONT + MOV INTXAL,TXAL + ; +SSTOP0: SETB CONB ;CONTINUE WILL WORK + MOV DPTR,#STP ;PRINT THE STOP MESSAGE + SETB STOPBIT ;SET FOR ERROR ROUTINE + LJMP ERRS ;JUMP TO ERROR ROUTINE ******AA JMP-->LJMP + ; + newpage + ;************************************************************** + ; + ; ITRAP - Trap special function register operators + ; + ;************************************************************** + ; +ITRAP: CJNE A,#TMR0,$+8 ;TIMER 0 + MOV TH0,R3 + MOV TL0,R1 + RET + ; + CJNE A,#TMR1,$+8 ;TIMER 1 + MOV TH1,R3 + MOV TL1,R1 + RET + ; + CJNE A,#TMR2,$+8 ;TIMER 2 + DB 8BH ;MOV R3 DIRECT OP CODE + DB 0CDH ;T2H LOCATION + DB 89H ;MOV R1 DIRECT OP CODE + DB 0CCH ;T2L LOCATION + RET + ; + CJNE A,#TRC2,$+8 ;RCAP2 TOKEN +RCL: DB 8BH ;MOV R3 DIRECT OP CODE + DB 0CBH ;RCAP2H LOCATION + DB 89H ;MOV R1 DIRECT OP CODE + DB 0CAH ;RCAP2L LOCATION + RET + ; + ACALL R3CK ;MAKE SURE THAT R3 IS ZERO + CJNE A,#TT2C,$+6 + DB 89H ;MOV R1 DIRECT OP CODE + DB 0C8H ;T2CON LOCATION + RET + ; + CJNE A,#T_IE,$+6 ;IE TOKEN + MOV IE,R1 + RET + ; + CJNE A,#T_IP,$+6 ;IP TOKEN + MOV IP,R1 + RET + ; + CJNE A,#TTC,$+6 ;TCON TOKEN + MOV TCON,R1 + RET + ; + CJNE A,#TTM,$+6 ;TMOD TOKEN + MOV TMOD,R1 + RET + ; + CJNE A,#T_P1,T_T2 ;P1 TOKEN + MOV P1,R1 + RET + ; + ;*************************************************************** + ; + ; T_TRAP - Trap special operators + ; + ;*************************************************************** + ; +T_T: MOV TEMP5,A ;SAVE THE TOKEN + ACALL GCI1 ;BUMP POINTER + ACALL SLET2 ;EVALUATE AFTER = + MOV A,TEMP5 ;GET THE TOKEN BACK + CJNE A,#T_XTAL,$+6 + LJMP AXTAL1 ;SET UP CRYSTAL + ; + ACALL IFIXL ;R3:R1 HAS THE TOS + MOV A,TEMP5 ;GET THE TOKEN AGAIN + CJNE A,#T_MTOP,T_T1 ;SEE IF MTOP TOKEN + MOV DPTR,#MEMTOP + CALL S31DP + JMP RCLEAR ;CLEAR THE MEMORY + ; +T_T1: CJNE A,#T_TIME,ITRAP ;SEE IF A TIME TOKEN + MOV C,EA ;SAVE INTERRUPTS + CLR EA ;NO TIMER 0 INTERRUPTS DURING LOAD + MOV TVH,R3 ;SAVE THE TIME + MOV TVL,R1 + MOV EA,C ;RESTORE INTERRUPTS + RET ;EXIT + ; +T_T2: CJNE A,#T_PC,INTERX ;PCON TOKEN + DB 89H ;MOV DIRECT, R1 OP CODE + DB 87H ;ADDRESS OF PCON + RET ;EXIT + ; +T_TRAP: CJNE A,#T_ASC,T_T ;SEE IF ASC TOKEN + ACALL IGC ;EAT IT AND GET THE NEXT CHARACTER + CJNE A,#'$',INTERX ;ERROR IF NOT A STRING + ACALL CSY ;CALCULATE ADDRESS + ACALL X3120 + LCALL TWO_EY ; ******AA CALL-->LCALL + ACALL SPEOP+4 ;EVALUATE AFTER EQUALS + AJMP ISTAX1 ;SAVE THE CHARACTER + ; + newpage + ;************************************************************** + ; + ;INTERPERT THE STATEMENT POINTED TO BY TXAL AND TXAH + ; + ;************************************************************** + ; +ISTAT: ACALL GC ;GET THR FIRST CHARACTER + JNB XBIT,IAT ;TRAP TO EXTERNAL RUN PACKAGE + CJNE A,#20H,$+3 + JNC IAT + LCALL 2070H ;LET THE USER SET UP THE DPTR + ACALL GCI1 + ANL A,#0FH ;STRIP OFF BIAS + SJMP ISTA1 + ; +IAT: CJNE A,#T_XTAL,$+3 + JNC T_TRAP + JNB ACC.7,SLET ;IMPLIED LET IF BIT 7 NOT SET + CJNE A,#T_UOP+12,ISTAX ;DBYTE TOKEN + ACALL SPEOP ;EVALUATE SPECIAL OPERATOR + ACALL R3CK ;CHECK LOCATION + MOV @R1,A ;SAVE IT + RET + ; +ISTAX: CJNE A,#T_UOP+13,ISTAY ;XBYTE TOKEN + ACALL SPEOP + ; +ISTAX1: MOV P2,R3 + MOVX @R1,A + RET + ; +ISTAY: CJNE A,#T_CR+1,$+3 ;TRAP NEW OPERATORS + JC I_S + CJNE A,#0B0H,$+3 ;SEE IF TOO BIG + JNC INTERX + ADD A,#0F9H ;BIAS FOR LOOKUP TABLE + SJMP ISTA0 ;DO THE OPERATION + ; +I_S: CJNE A,#T_LAST,$+3 ;MAKE SURE AN INITIAL RESERVED WORD + JC $+5 ;ERROR IF NOT + ; +INTERX: LJMP E1XX ;SYNTAX ERROR + ; + JNB DIRF,ISTA0 ;EXECUTE ALL STATEMENTS IF IN RUN MODE + CJNE A,#T_DIR,$+3 ;SEE IF ON TOKEN + JC ISTA0 ;OK IF DIRECT + CJNE A,#T_GOSB+1,$+5 ;SEE IF FOR + SJMP ISTA0 ;FOR IS OK + CJNE A,#T_REM+1,$+5 ;NEXT IS OK + SJMP ISTA0 + CJNE A,#T_STOP+6,INTERX ;SO IS REM + ; + newpage +ISTA0: ACALL GCI1 ;ADVANCE THE TEXT POINTER + MOV DPTR,#STATD ;POINT DPTR TO LOOKUP TABLE + CJNE A,#T_GOTO-3,$+5 ;SEE IF LET TOKEN + SJMP ISTAT ;WASTE LET TOKEN + ANL A,#3FH ;STRIP OFF THE GARBAGE + ; +ISTA1: RL A ;ROTATE FOR OFFSET + ADD A,DPL ;BUMP + MOV DPL,A ;SAVE IT + CLR A + MOVC A,@A+DPTR ;GET HIGH BYTE + PUSH ACC ;SAVE IT + INC DPTR + CLR A + MOVC A,@A+DPTR ;GET LOW BYTE + POP DPH + MOV DPL,A + ; +AC1: CLR A + JMP @A+DPTR ;GO DO IT + ; + newpage + ;*************************************************************** + ; + ; The statement action routine - LET + ; + ;*************************************************************** + ; +SLET: ACALL S_C ;CHECK FOR POSSIBLE STRING + JC SLET0 ;NO STRING + CLR LINEB ;USED STRINGS + ; + CALL X31DP ;PUT ADDRESS IN DPTR + MOV R7,#T_EQU ;WASTE = + ACALL EATC + ACALL GC ;GET THE NEXT CHARACTER + CJNE A,#'"',S_3 ;CHECK FOR A " + MOV R7,S_LEN ;GET THE STRING LENGTH + ; +S_0: ACALL GCI1 ;BUMP PAST " + ACALL DELTST ;CHECK FOR DELIMITER + JZ INTERX ;EXIT IF CARRIAGE RETURN + MOVX @DPTR,A ;SAVE THE CHARACTER + CJNE A,#'"',S_1 ;SEE IF DONE + ; +S_E: MOV A,#CR ;PUT A CR IN A + MOVX @DPTR,A ;SAVE CR + AJMP GCI1 + ; +S_3: PUSH DPH + PUSH DPL ;SAVE DESTINATION + ACALL S_C ;CALCULATE SOURCE + JC INTERX ;ERROR IF CARRY + POP R0B0 ;GET DESTINATION BACK + POP R2B0 + ; +SSOOP: MOV R7,S_LEN ;SET UP COUNTER + ; +S_4: LCALL TBYTE ;TRANSFER THE BYTE ******AA CALL-->LCALL + CJNE A,#CR,$+4 ;EXIT IF A CR + RET + DJNZ R7,S_5 ;BUMP COUNTER + MOV A,#CR ;SAVE A CR + MOVX @R0,A + AJMP EIGP ;PRINT EXTRA IGNORED + ; + newpage + ; +S_5: CALL INC3210 ;BUMP POINTERS + SJMP S_4 ;LOOP + ; +S_1: DJNZ R7,$+8 ;SEE IF DONE + ACALL S_E + ACALL EIGP ;PRINT EXTRA IGNORED + AJMP FINDCR ;GO FIND THE END + INC DPTR ;BUMP THE STORE POINTER + SJMP S_0 ;CONTINUE TO LOOP + ; +E3XX: MOV DPTR,#E3X ;BAD ARG ERROR + AJMP EK + ; +SLET0: ACALL SLET1 + AJMP POPAS ;COPY EXPRESSION TO VARIABLE + ; +SLET1: ACALL VAR_ER ;CHECK FOR A"VARIABLE" + ; +SLET2: PUSH R2B0 ;SAVE THE VARIABLE ADDRESS + PUSH R0B0 + MOV R7,#T_EQU ;GET EQUAL TOKEN + ACALL WE + POP R1B0 ;POP VARIABLE TO R3:R1 + POP R3B0 + RET ;EXIT + ; +R3CK: CJNE R3,#00H,E3XX ;CHECK TO SEE IF R3 IS ZERO + RET + ; +SPEOP: ACALL GCI1 ;BUMP TXA + ACALL P_E ;EVALUATE PAREN + ACALL SLET2 ;EVALUATE AFTER = + CALL TWOL ;R7:R6 GETS VALUE, R3:R1 GETS LOCATION + MOV A,R6 ;SAVE THE VALUE + ; + CJNE R7,#00H,E3XX ;R2 MUST BE = 0 + RET + ; + newpage + ;************************************************************** + ; + ; ST_CAL - Calculate string Address + ; + ;************************************************************** + ; +IST_CAL:; + ; + ACALL I_PI ;BUMP TEXT, THEN EVALUATE + ACALL R3CK ;ERROR IF R3 <> 0 + INC R1 ;BUMP FOR OFFSET + MOV A,R1 ;ERROR IF R1 = 255 + JZ E3XX + MOV DPTR,#VARTOP ;GET TOP OF VARIABLE STORAGE + MOV B,S_LEN ;MULTIPLY FOR LOCATION + ACALL VARD ;CALCULATE THE LOCATION + MOV DPTR,#MEMTOP ;SEE IF BLEW IT + CALL FUL1 + MOV DPL,S_LEN ;GET STRING LENGTH, DPH = 00H + DEC DPH ;DPH = 0 + ; +DUBSUB: CLR C + MOV A,R1 + SUBB A,DPL + MOV R1,A + MOV A,R3 + SUBB A,DPH + MOV R3,A + ORL A,R1 + RET + ; + ;*************************************************************** + ; + ;VARD - Calculate the offset base + ; + ;*************************************************************** + ; +VARB: MOV B,#FPSIZ ;SET UP FOR OPERATION + ; +VARD: CALL LDPTRI ;LOAD DPTR + MOV A,R1 ;MULTIPLY BASE + MUL AB + ADD A,DPL + MOV R1,A + MOV A,B + ADDC A,DPH + MOV R3,A + RET + ; + newpage + ;************************************************************* + ; +CSY: ; Calculate a biased string address and put in R3:R1 + ; + ;************************************************************* + ; + ACALL IST_CAL ;CALCULATE IT + PUSH R3B0 ;SAVE IT + PUSH R1B0 + MOV R7,#',' ;WASTE THE COMMA + ACALL EATC + ACALL ONE ;GET THE NEXT EXPRESSION + MOV A,R1 ;CHECK FOR BOUNDS + CJNE A,S_LEN,$+3 + JNC E3XX ;MUST HAVE A CARRY + DEC R1 ;BIAS THE POINTER + POP ACC ;GET VALUE LOW + ADD A,R1 ;ADD IT TO BASE + MOV R1,A ;SAVE IT + POP R3B0 ;GET HIGH ADDRESS + JNC $+3 ;PROPAGATE THE CARRY + INC R3 + AJMP ERPAR ;WASTE THE RIGHT PAREN + ; + newpage + ;*************************************************************** + ; + ; The statement action routine FOR + ; + ;*************************************************************** + ; +SFOR: ACALL SLET1 ;SET UP CONTROL VARIABLE + PUSH R3B0 ;SAVE THE CONTROL VARIABLE LOCATION + PUSH R1B0 + ACALL POPAS ;POP ARG STACK AND COPY CONTROL VAR + MOV R7,#T_TO ;GET TO TOKEN + ACALL WE + ACALL GC ;GET NEXT CHARACTER + CJNE A,#T_STEP,SF2 + ACALL GCI1 ;EAT THE TOKEN + ACALL EXPRB ;EVALUATE EXPRESSION + SJMP $+5 ;JUMP OVER + ; +SF2: LCALL PUSH_ONE ;PUT ONE ON THE STACK + ; + MOV A,#-FSIZE ;ALLOCATE FSIZE BYTES ON THE CONTROL STACK + ACALL PUSHCS ;GET CS IN R0 + ACALL CSC ;CHECK CONTROL STACK + MOV R3,#CSTKAH ;IN CONTROL STACK + MOV R1,R0B0 ;STACK ADDRESS + ACALL POPAS ;PUT STEP ON STACK + ACALL POPAS ;PUT LIMIT ON STACK + ACALL DP_T ;DPTR GETS TEXT + MOV R0,R1B0 ;GET THE POINTER + ACALL T_X_S ;SAVE THE TEXT + POP TXAL ;GET CONTROL VARIABLE + POP TXAH + MOV R4,#FTYPE ;AND THE TYPE + ACALL T_X_S ;SAVE IT + ; +SF3: ACALL T_DP ;GET THE TEXT POINTER + AJMP ILOOP ;CONTINUE TO PROCESS + ; + newpage + ;************************************************************** + ; + ; The statement action routines - PUSH and POP + ; + ;************************************************************** + ; +SPUSH: ACALL EXPRB ;PUT EXPRESSION ON STACK + ACALL C_TST ;SEE IF MORE TO DO + JNC SPUSH ;IF A COMMA PUSH ANOTHER + RET + ; + ; +SPOP: ACALL VAR_ER ;GET VARIABLE + ACALL XPOP ;FLIP THE REGISTERS FOR POPAS + ACALL C_TST ;SEE IF MORE TO DO + JNC SPOP + ; + RET + ; + ;*************************************************************** + ; + ; The statement action routine - IF + ; + ;*************************************************************** + ; +SIF: ACALL RTST ;EVALUATE THE EXPRESSION + MOV R1,A ;SAVE THE RESULT + ACALL GC ;GET THE CHARACTER AFTER EXPR + CJNE A,#T_THEN,$+5 ;SEE IF THEN TOKEN + ACALL GCI1 ;WASTE THEN TOKEN + CJNE R1,#0,T_F1 ;CHECK R_OP RESULT + ; +E_FIND: MOV R7,#T_ELSE ;FIND ELSE TOKEN + ACALL FINDC + JZ SIF-1 ;EXIT IF A CR + ACALL GCI1 ;BUMP PAST TOKEN + CJNE A,#T_ELSE,E_FIND;WASTE IF NO ELSE + ; +T_F1: ACALL INTGER ;SEE IF NUMBER + JNC D_L1 ;EXECUTE LINE NUMBER + AJMP ISTAT ;EXECUTE STATEMENT IN NOT + ; +B_C: MOVX A,@DPTR + DEC A + JB ACC.7,FL3-5 + RET + ; + newpage + ;*************************************************************** + ; + ; The statement action routine - GOTO + ; + ;*************************************************************** + ; +SGOTO: ACALL RLINE ;R2:R0 AND DPTR GET INTGER + ; +SGT1: ACALL T_DP ;TEXT POINTER GETS DPTR + ; + JBC RETBIT,SGT2 ;SEE IF RETI EXECUTED + ; + JNB LINEB,$+6 ;SEE IF A LINE WAS EDITED + LCALL RCLEAR-2 ;CLEAR THE MEMORY IF SET + AJMP ILOOP-2 ;CLEAR DIRF AND LOOP + ; +SGT2: JBC OTI,$+8 ;SEE IF TIMER INTERRUPT + ANL 34,#10111101B ;CLEAR INTERRUPTS + AJMP ILOOP ;EXECUTE + MOV C,ISAV + MOV INPROG,C + AJMP ILOOP ;RESTORE INTERRUPTS AND RET + ; + ; + ;************************************************************* + ; +RTST: ; Test for ZERO + ; + ;************************************************************* + ; + ACALL EXPRB ;EVALUATE EXPRESSION + CALL INC_ASTKA ;BUMP ARG STACK + JZ $+4 ;EXIT WITH ZERO OR 0FFH + MOV A,#0FFH + RET + ; + newpage + ; + ;************************************************************** + ; + ; GLN - get the line number in R2:R0, return in DPTR + ; + ;************************************************************** + ; +GLN: ACALL DP_B ;GET THE BEGINNING ADDRESS + ; +FL1: MOVX A,@DPTR ;GET THE LENGTH + MOV R7,A ;SAVE THE LENGTH + DJNZ R7,FL3 ;SEE IF END OF FILE + ; + MOV DPTR,#E10X ;NO LINE NUMBER + AJMP EK ;HANDLE THE ERROR + ; +FL3: JB ACC.7,$-5 ;CHECK FOR BIT 7 + INC DPTR ;POINT AT HIGH BYTE + MOVX A,@DPTR ;GET HIGH BYTE + CJNE A,R2B0,FL2 ;SEE IF MATCH + INC DPTR ;BUMP TO LOW BYTE + DEC R7 ;ADJUST AGAIN + MOVX A,@DPTR ;GET THE LOW BYTE + CJNE A,R0B0,FL2 ;SEE IF LOW BYTE MATCH + INC DPTR ;POINT AT FIRST CHARACTER + RET ;FOUND IT + ; +FL2: MOV A,R7 ;GET THE LENGTH COUNTER + CALL ADDPTR ;ADD A TO DATA POINTER + SJMP FL1 ;LOOP + ; + ; + ;************************************************************* + ; + ;RLINE - Read in ASCII string, get line, and clean it up + ; + ;************************************************************* + ; +RLINE: ACALL INTERR ;GET THE INTEGER + ; +RL1: ACALL GLN + AJMP CLN_UP + ; + ; +D_L1: ACALL GLN ;GET THE LINE + AJMP SGT1 ;EXECUTE THE LINE + ; + newpage + ;*************************************************************** + ; + ; The statement action routines WHILE and UNTIL + ; + ;*************************************************************** + ; +SWHILE: ACALL RTST ;EVALUATE RELATIONAL EXPRESSION + CPL A + SJMP S_WU + ; +SUNTIL: ACALL RTST ;EVALUATE RELATIONAL EXPRESSION + ; +S_WU: MOV R4,#DTYPE ;DO EXPECTED + MOV R5,A ;SAVE R_OP RESULT + SJMP SR0 ;GO PROCESS + ; + ; + ;*************************************************************** + ; +CNULL: ; The Command Action Routine - NULL + ; + ;*************************************************************** + ; + ACALL INTERR ;GET AN INTEGER FOLLOWING NULL + MOV NULLCT,R0 ;SAVE THE NULLCOUNT + AJMP CMNDLK ;JUMP TO COMMAND MODE + ; + newpage + ;*************************************************************** + ; + ; The statement action routine - RETI + ; + ;*************************************************************** + ; +SRETI: SETB RETBIT ;SAYS THAT RETI HAS BEEN EXECUTED + ; + ;*************************************************************** + ; + ; The statement action routine - RETURN + ; + ;*************************************************************** + ; +SRETRN: MOV R4,#GTYPE ;MAKE SURE OF GOSUB + MOV R5,#55H ;TYPE RETURN TYPE + ; +SR0: ACALL CSETUP ;SET UP CONTROL STACK + MOVX A,@R0 ;GET RETURN TEXT ADDRESS + MOV DPH,A + INC R0 + MOVX A,@R0 + MOV DPL,A + INC R0 ;POP CONTROL STACK + MOVX A,@DPTR ;SEE IF GOSUB WAS THE LAST STATEMENT + CJNE A,#EOF,$+5 + AJMP CMNDLK + MOV A,R5 ;GET TYPE + JZ SGT1 ;EXIT IF ZERO + MOV CSTKA,R0 ;POP THE STACK + CPL A ;OPTION TEST, 00H, 55H, 0FFH, NOW 55H + JNZ SGT1 ;MUST BE GOSUB + RET ;NORMAL FALL THRU EXIT FOR NO MATCH + ; + newpage + ;*************************************************************** + ; + ; The statement action routine - GOSUB + ; + ;*************************************************************** + ; +SGOSUB: ACALL RLINE ;NEW TXA IN DPTR + ; +SGS0: MOV R4,#GTYPE + ACALL SGS1 ;SET EVERYTHING UP + AJMP SF3 ;EXIT + ; +SGS1: MOV A,#-3 ;ALLOCATE 3 BYTES ON CONTROL STACK + ACALL PUSHCS + ; +T_X_S: MOV P2,#CSTKAH ;SET UP PORT FOR CONTROL STACK + MOV A,TXAL ;GET RETURN ADDRESS AND SAVE IT + MOVX @R0,A + DEC R0 + MOV A,TXAH + MOVX @R0,A + DEC R0 + MOV A,R4 ;GET TYPE + MOVX @R0,A ;SAVE TYPE + RET ;EXIT + ; + ; +CS1: MOV A,#3 ;POP 3 BYTES + ACALL PUSHCS + ; +CSETUP: MOV R0,CSTKA ;GET CONTROL STACK + MOV P2,#CSTKAH + MOVX A,@R0 ;GET BYTE + CJNE A,R4B0,$+5 ;SEE IF TYPE MATCH + INC R0 + RET + JZ E4XX ;EXIT IF STACK UNDERFLOW + CJNE A,#FTYPE,CS1 ;SEE IF FOR TYPE + ACALL PUSHCS-2 ;WASTE THE FOR TYPE + SJMP CSETUP ;LOOP + ; + newpage + ;*************************************************************** + ; + ; The statement action routine - NEXT + ; + ;*************************************************************** + ; +SNEXT: MOV R4,#FTYPE ;FOR TYPE + ACALL CSETUP ;SETUP CONTROL STACK + MOV TEMP5,R0 ;SAVE CONTROL VARIABLE ADDRESS + MOV R1,#TEMP1 ;SAVE VAR + RETURN IN TEMP1-4 + ; +XXI: MOVX A,@R0 ;LOOP UNTIL DONE + MOV @R1,A + INC R1 + INC R0 + CJNE R1,#TEMP5,XXI + ; + ACALL VAR ;SEE IF THE USER HAS A VARIABLE + JNC $+6 + MOV R2,TEMP1 + MOV R0,TEMP2 + MOV A,R2 ;SEE IF VAR'S AGREE + CJNE A,TEMP1,E4XX + MOV A,R0 + CJNE A,TEMP2,E4XX + ACALL PUSHAS ;PUT CONTROL VARIABLE ON STACK + MOV A,#FPSIZ+FPSIZ+2;COMPUTE ADDRESS TO STEP VALUE SIGN + ADD A,TEMP5 ;ADD IT TO BASE OF STACK + MOV R0,A ;SAVE IN R0 + MOV R2,#CSTKAH ;SET UP TO PUSH STEP VALUE + MOV P2,R2 ;SET UP PORT + MOVX A,@R0 ;GET SIGN + INC R0 ;BACK TO EXPONENT + PUSH ACC ;SAVE SIGN OF STEP + ACALL PUSHAS ;PUT STEP VALUE ON STACK + PUSH R0B0 ;SAVE LIMIT VALUE LOCATION + CALL AADD ;ADD STEP VALUE TO VARIABLE + CALL CSTAKA ;COPY STACK + MOV R3,TEMP1 ;GET CONTROL VARIABLE + MOV R1,TEMP2 + ACALL POPAS ;SAVE THE RESULT + MOV R2,#CSTKAH ;RESTORE LIMIT LOCATION + POP R0B0 + ACALL PUSHAS ;PUT LIMIT ON STACK + CALL FP_BASE+4 ;DO THE COMPARE + POP ACC ;GET LIMIT SIGN BACK + JZ $+3 ;IF SIGN NEGATIVE, TEST "BACKWARDS" + CPL C + ORL C,F0 ;SEE IF EQUAL + JC N4 ;STILL SMALLER THAN LIMIT? + MOV A,#FSIZE ;REMOVE CONTROL STACK ENTRY + ; + ; Fall thru to PUSHCS + ; + newpage + ;*************************************************************** + ; + ; PUSHCS - push frame onto control stack + ; acc has - number of bytes, also test for overflow + ; + ;*************************************************************** + ; +PUSHCS: ADD A,CSTKA ;BUMP CONTROL STACK + CJNE A,#CONVT+17,$+3 ;SEE IF OVERFLOWED + JC E4XX ;EXIT IF STACK OVERFLOW + XCH A,CSTKA ;STORE NEW CONTROL STACK VALUE, GET OLD + DEC A ;BUMP OLD VALUE + MOV R0,A ;PUT OLD-1 IN R0 + ; + RET ;EXIT + ; +CSC: ACALL CLN_UP ;FINISH OFF THE LINE + JNC CSC-1 ;EXIT IF NO TERMINATOR + ; +E4XX: MOV DPTR,#EXC ;CONTROL STACK ERROR + AJMP EK ;STACK ERROR + ; +N4: MOV TXAH,TEMP3 ;GET TEXT POINTER + MOV TXAL,TEMP4 + AJMP ILOOP ;EXIT + ; + ;*************************************************************** + ; + ; The statement action routine - RESTORE + ; + ;*************************************************************** + ; +SRESTR: ACALL X_TR ;SWAP POINTERS + ACALL DP_B ;GET THE STARTING ADDRESS + ACALL T_DP ;PUT STARTING ADDRESS IN TEXT POINTER + ACALL B_TXA ;BUMP TXA + ; + ; Fall thru + ; +X_TR: ;swap txa and rtxa + ; + XCH A,TXAH + XCH A,RTXAH + XCH A,TXAH + XCH A,TXAL + XCH A,RTXAL + XCH A,TXAL + RET ;EXIT + ; + newpage + ;*************************************************************** + ; + ; The statement action routine - READ + ; + ;*************************************************************** + ; +SREAD: ACALL X_TR ;SWAP POINTERS + ; +SRD0: ACALL C_TST ;CHECK FOR COMMA + JC SRD4 ;SEE WHAT IT IS + ; +SRD: ACALL EXPRB ;EVALUATE THE EXPRESSION + ACALL GC ;GET THE CHARACTER AFTER EXPRESSION + CJNE A,#',',SRD1 ;SEE IF MORE DATA + SJMP SRD2 ;BYBASS CLEAN UP IF A COMMA + ; +SRD1: ACALL CLN_UP ;FINISH OFF THE LINE, IF AT END + ; +SRD2: ACALL X_TR ;RESTORE POINTERS + ACALL VAR_ER ;GET VARIABLE ADDRESS + ACALL XPOP ;FLIP THE REGISTERS FOR POPAS + ACALL C_TST ;SEE IF A COMMA + JNC SREAD ;READ AGAIN IF A COMMA + RET ;EXIT IF NOT + ; +SRD4: CJNE A,#T_DATA,SRD5 ;SEE IF DATA + ACALL GCI1 ;BUMP POINTER + SJMP SRD + ; +SRD5: CJNE A,#EOF,SRD6 ;SEE IF YOU BLEW IT + ACALL X_TR ;GET THE TEXT POINTER BACK + MOV DPTR,#E14X ;READ ERROR + ; +EK: LJMP ERROR + ; +SRD6: ACALL FINDCR ;WASTE THIS LINE + ACALL CLN_UP ;CLEAN IT UP + JC SRD5+3 ;ERROR IF AT END + SJMP SRD0 + ; +NUMC: ACALL GC ;GET A CHARACTER + CJNE A,#'#',NUMC1 ;SEE IF A # + SETB COB ;VALID LINE PRINT + AJMP IGC ;BUMP THE TEXT POINTER + ; +NUMC1: CJNE A,#'@',SRD4-1 ;EXIT IF NO GOOD + SETB LPB + AJMP IGC + ; + newpage + ;*************************************************************** + ; + ; The statement action routine - PRINT + ; + ;*************************************************************** + ; +SPH0: SETB ZSURP ;NO ZEROS + ; +SPH1: SETB HMODE ;HEX MODE + ; +SPRINT: ACALL NUMC ;TEST FOR A LINE PRINT + ACALL $+9 ;PROCEED + ANL 35,#11110101B ;CLEAR COB AND LPB + ANL 38,#00111111B ;NO HEX MODE + ; + RET + ; + ACALL DELTST ;CHECK FOR A DELIMITER + JC SP1 + ; +SP0: JMP CRLF ;EXIT WITH A CR IF SO + ; +SP2: ACALL C_TST ;CHECK FOR A COMMA + JC SP0 ;EXIT IF NO COMMA + ; +SP1: ACALL CPS ;SEE IF A STRING TO PRINT + JNC SP2 ;IF A STRING, CHECK FOR A COMMA + ; +SP4: CJNE A,#T_TAB,SP6 + ACALL I_PI ;ALWAYS CLEARS CARRY + SUBB A,PHEAD ;TAKE DELTA BETWEEN TAB AND PHEAD + JC SP2 ;EXIT IF PHEAD > TAB + SJMP SP7 ;OUTPUT SPACES + ; +SP6: CJNE A,#T_SPC,SM + ACALL I_PI ;SET UP PAREN VALUE + ; +SP7: JZ SP2 + LCALL STEROT ;OUTPUT A SPACE + DEC A ;DECREMENT COUNTER + SJMP SP7 ;LOOP + ; + newpage +SM: CJNE A,#T_CHR,SP8 + ACALL IGC + CJNE A,#'$',$+9 + ACALL CNX ;PUT THE CHARACTER ON THE STACK + ACALL IFIXL ;PUT THE CHARACTER IN R1 + SJMP $+6 + ACALL ONE ;EVALUATE THE EXPRESSION, PUT IN R3:R1 + ACALL ERPAR + MOV R5,R1B0 ;BYTE TO OUTPUT + SJMP SQ + ; +SP8: CJNE A,#T_CR,SX + ACALL GCI1 ;EAT THE TOKEN + MOV R5,#CR + ; +SQ: CALL TEROT + SJMP SP2 ;OUTPUT A CR AND DO IT AGAIN + ; +SX: CJNE A,#T_USE,SP9 ;USING TOKEN + ACALL IGC ;GE THE CHARACTER AFTER THE USING TOKEN + CJNE A,#'F',U4 ;SEE IF FLOATING + MOV FORMAT,#0F0H ;SET FLOATING + ACALL IGC ;BUMP THE POINTER AND GET THE CHARACTER + ACALL GCI1 ;BUMP IT AGAIN + ANL A,#0FH ;STRIP OFF ASCII BIAS + JZ U3 ;EXIT IF ZERO + CJNE A,#3,$+3 ;SEE IF AT LEAST A THREE + JNC U3 ;FORCE A THREE IF NOT A THREE + MOV A,#3 + ; +U3: ORL FORMAT,A ;PUT DIGIT IN FORMAT + SJMP U8 ;CLEAN UP END + ; +U4: CJNE A,#'0',U5 + MOV FORMAT,#0 ;FREE FORMAT + ACALL GCI1 ;BUMP THE POINTER + SJMP U8 + ; +U5: CJNE A,#'#',U8 ;SEE IF INTGER FORMAT + ACALL U6 + MOV FORMAT,R7 ;SAVE THE FORMAT + CJNE A,#'.',U8A ;SEE IF TERMINATOR WAS RADIX + ACALL IGC ;BUMP PAST . + ACALL U6 ;LOOP AGAIN + MOV A,R7 ;GET COUNT + ADD A,FORMAT ;SEE IF TOO BIG + ADD A,#0F7H + JNC U5A + ; + newpage +SE0: AJMP INTERX ;ERROR, BAD SYNTAX + ; +U5A: MOV A,R7 ;GET THE COUNT BACK + SWAP A ;ADJUST + ORL FORMAT,A ;GET THE COUNT + ; +U8A: MOV A,FORMAT + ; +U8B: SWAP A ;GET THE FORMAT RIGHT + MOV FORMAT,A + ; +U8: ACALL ERPAR + AJMP SP2 ;DONE + ; +U6: MOV R7,#0 ;SET COUNTER + ; +U7: CJNE A,#'#',SP9A ;EXIT IF NOT A # + INC R7 ;BUMP COUNTER + ACALL IGC ;GET THE NEXT CHARACTER + SJMP U7 ;LOOP + ; +SP9: ACALL DELTST+2 ;CHECK FOR DELIMITER + JNC SP9A ;EXIT IF A DELIMITER + ; + CJNE A,#T_ELSE,SS + ; +SP9A: RET ;EXIT IF ELSE TOKEN + ; + ;************************************************************** + ; + ; P_E - Evaluate an expression in parens ( ) + ; + ;************************************************************** + ; +P_E: MOV R7,#T_LPAR + ACALL WE + ; +ERPAR: MOV R7,#')' ;EAT A RIGHT PAREN + ; +EATC: ACALL GCI ;GET THE CHARACTER + CJNE A,R7B0,SE0 ;ERROR IF NOT THE SAME + RET + ; + newpage + ;*************************************************************** + ; +S_ON: ; ON Statement + ; + ;*************************************************************** + ; + ACALL ONE ;GET THE EXPRESSION + ACALL GCI ;GET THE NEXT CHARACTER + CJNE A,#T_GOTO,C0 + ACALL C1 ;EAT THE COMMAS + AJMP SF3 ;DO GOTO + ; +C0: CJNE A,#T_GOSB,SE0 + ACALL C1 + AJMP SGS0 ;DO GOSUB + ; +C1: CJNE R1,#0,C2 + ACALL INTERR ;GET THE LINE NUMBER + ACALL FINDCR + AJMP RL1 ;FINISH UP THIS LINE + ; +C2: MOV R7,#',' + ACALL FINDC + CJNE A,#',',SE0 ;ERROR IF NOT A COMMA + DEC R1 + ACALL GCI1 ;BUMP PAST COMMA + SJMP C1 + ; + newpage + ; +SS: ACALL S_C ;SEE IF A STRING + JC SA ;NO STRING IF CARRY IS SET + LCALL UPRNT ;PUT POINTER IN DPTR + AJMP SP2 ;SEE IF MORE + ; +SA: ACALL EXPRB ;MUST BE AN EXPRESSION + MOV A,#72 + CJNE A,PHEAD,$+3 ;CHECK PHEAD POSITION + JNC $+4 + ACALL SP0 ;FORCE A CRLF + JNB HMODE,S13 ;HEX MODE? + CALL FCMP ;SEE IF TOS IS < 0FFFH + JC S13 ;EXIT IF GREATER + CALL AABS ;GET THE SIGN + JNZ OOPS ;WASTE IF NEGATIVE + ACALL IFIXL + CALL FP_BASE+22 ;PRINT HEXMODE + AJMP SP2 +OOPS: CALL ANEG ;MAKE IT NEGATIVE + ; +S13: CALL FP_BASE+14 ;DO FP OUTPUT + MOV A,#1 ;OUTPUT A SPACE + AJMP SP7 + ; + newpage + ;*************************************************************** + ; + ; ANU - Get variable name from text - set carry if not found + ; if succeeds returns variable in R7:R6 + ; R6 = 0 if no digit in name + ; + ;*************************************************************** + ; +ANU: ACALL IGC ;INCREMENT AND GET CHARACTER + LCALL 1FEDH ;CHECK FOR DIGIT + JC $+14 ;EXIT IF VALID DIGIT + CJNE A,#'_',$+4 ;SEE IF A _ + RET + ; +AL: CJNE A,#'A',$+3 ;IS IT AN ASCII A? + JC $+6 ;EXIT IF CARRY IS SET + CJNE A,#'Z'+1,$+3 ;IS IT LESS THAN AN ASCII Z + CPL C ;FLIP CARRY + RET + ; + JNB F0,VAR2 + ; +SD0: MOV DPTR,#E6X + AJMP EK + ; +SDIMX: SETB F0 ;SAYS DOING A DIMENSION + SJMP VAR1 + ; +VAR: CLR F0 ;SAYS DOING A VARIABLE + ; +VAR1: ACALL GC ;GET THE CHARACTER + ACALL AL ;CHECK FOR ALPHA + JNC $+6 ;ERROR IF IN DIM + JB F0,SD0 + RET + MOV R7,A ;SAVE ALPHA CHARACTER + CLR A ;ZERO IN CASE OF FAILURE + MOV R5,A ;SAVE IT + ; +VY: MOV R6,A + ACALL ANU ;CHECK FOR ALPHA OR NUMBER + JC VX ;EXIT IF NO ALPHA OR NUM + ; + XCH A,R7 + ADD A,R5 ;NUMBER OF CHARACTERS IN ALPHABET + XCH A,R7 ;PUT IT BACK + MOV R5,#26 ;FOR THE SECOND TIME AROUND + SJMP VY + ; +VX: CLR LINEB ;TELL EDITOR A VARIABLE IS DECLARED + CJNE A,#T_LPAR,V4 ;SEE IF A LEFT PAREN + ; + ORL R6B0,#80H ;SET BIT 7 TO SIGINIFY MATRIX + CALL F_VAR ;FIND THE VARIABLE + PUSH R2B0 ;SAVE THE LOCATION + PUSH R0B0 + JNC SD0-3 ;DEFAULT IF NOT IN TABLE + JB F0,SDI ;NO DEFAULT FOR DIMENSION + MOV R1,#10 + MOV R3,#0 + ACALL D_CHK + ; +VAR2: ACALL PAREN_INT ;EVALUATE INTEGER IN PARENS + CJNE R3,#0,SD0 ;ERROR IF R3<>0 + POP DPL ;GET VAR FOR LOOKUP + POP DPH + MOVX A,@DPTR ;GET DIMENSION + DEC A ;BUMP OFFSET + SUBB A,R1 ;A MUST BE > R1 + JC SD0 + LCALL DECDP2 ;BUMP POINTER TWICE + ACALL VARB ;CALCULATE THE BASE + ; +X3120: XCH A,R1 ;SWAP R2:R0, R3:R1 + XCH A,R0 + XCH A,R1 + XCH A,R3 + XCH A,R2 + XCH A,R3 + RET + ; +V4: JB F0,SD0 ;ERROR IF NO LPAR FOR DIM + LCALL F_VAR ;GET SCALAR VARIABLE + CLR C + RET + ; + newpage + ; +SDI: ACALL PAREN_INT ;EVALUATE PAREN EXPRESSION + CJNE R3,#0,SD0 ;ERROR IF NOT ZERO + POP R0B0 ;SET UP R2:R0 + POP R2B0 + ACALL D_CHK ;DO DIM + ACALL C_TST ;CHECK FOR COMMA + JNC SDIMX ;LOOP IF COMMA + RET ;RETURN IF NO COMMA + ; +D_CHK: INC R1 ;BUMP FOR TABLE LOOKUP + MOV A,R1 + JZ SD0 ;ERROR IF 0FFFFH + MOV R4,A ;SAVE FOR LATER + MOV DPTR,#MT_ALL ;GET MATRIX ALLOCATION + ACALL VARB ;DO THE CALCULATION + MOV R7,DPH ;SAVE MATRIX ALLOCATION + MOV R6,DPL + MOV DPTR,#ST_ALL ;SEE IF TOO MUCH MEMORY TAKEN + CALL FUL1 ;ST_ALL SHOULD BE > R3:R1 + MOV DPTR,#MT_ALL ;SAVE THE NEW MATRIX POINTER + CALL S31DP + MOV DPL,R0 ;GET VARIABLE ADDRESS + MOV DPH,R2 + MOV A,R4 ;DIMENSION SIZE + MOVX @DPTR,A ;SAVE IT + CALL DECDP2 ;SAVE TARGET ADDRESS + ; +R76S: MOV A,R7 + MOVX @DPTR,A + INC DPTR + MOV A,R6 ;ELEMENT SIZE + MOVX @DPTR,A + RET ;R2:R0 STILL HAS SYMBOL TABLE ADDRESS + ; + newpage + ;*************************************************************** + ; + ; The statement action routine - INPUT + ; + ;*************************************************************** + ; +SINPUT: ACALL CPS ;PRINT STRING IF THERE + ; + ACALL C_TST ;CHECK FOR A COMMA + JNC IN2A ;NO CRLF + ACALL SP0 ;DO A CRLF + ; +IN2: MOV R5,#'?' ;OUTPUT A ? + CALL TEROT + ; +IN2A: SETB INP_B ;DOING INPUT + CALL INLINE ;INPUT THE LINE + CLR INP_B + MOV TEMP5,#HI(IBUF) + MOV TEMP4,#LO(IBUF) + ; +IN3: ACALL S_C ;SEE IF A STRING + JC IN3A ;IF CARRY IS SET, NO STRING + ACALL X3120 ;FLIP THE ADDRESSES + MOV R3,TEMP5 + MOV R1,TEMP4 + ACALL SSOOP + ACALL C_TST ;SEE IF MORE TO DO + JNC IN2 + RET + ; +IN3A: CALL DTEMP ;GET THE USER LOCATION + CALL GET_NUM ;GET THE USER SUPPLIED NUMBER + JNZ IN5 ;ERROR IF NOT ZERO + CALL TEMPD ;SAVE THE DATA POINTER + ACALL VAR_ER ;GET THE VARIABLE + ACALL XPOP ;SAVE THE VARIABLE + CALL DTEMP ;GET DPTR BACK FROM VAR_ER + ACALL C_TST ;SEE IF MORE TO DO + JC IN6 ;EXIT IF NO COMMA + MOVX A,@DPTR ;GET INPUT TERMINATOR + CJNE A,#',',IN5 ;IF NOT A COMMA DO A CR AND TRY AGAIN + INC DPTR ;BUMP PAST COMMA AND READ NEXT VALUE + CALL TEMPD + SJMP IN3 + ; + newpage + ; +IN5: MOV DPTR,#IAN ;PRINT INPUT A NUMBER + CALL CRP ;DO A CR, THEN, PRINT FROM ROM + LJMP CC1 ;TRY IT AGAIN + ; +IN6: MOVX A,@DPTR + CJNE A,#CR,EIGP + RET + ; +EIGP: MOV DPTR,#EIG + CALL CRP ;PRINT THE MESSAGE AND EXIT + AJMP SP0 ;EXIT WITH A CRLF + ; + ;*************************************************************** + ; +SOT: ; On timer interrupt + ; + ;*************************************************************** + ; + ACALL TWO ;GET THE NUMBERS + MOV SP_H,R3 + MOV SP_L,R1 + MOV DPTR,#TIV ;SAVE THE NUMBER + SETB OTS + AJMP R76S ;EXIT + ; + ; + ;*************************************************************** + ; +SCALL: ; Call a user rountine + ; + ;*************************************************************** + ; + ACALL INTERR ;CONVERT INTEGER + CJNE R2,#0,S_C_1 ;SEE IF TRAP + MOV A,R0 + JB ACC.7,S_C_1 + ADD A,R0 + MOV DPTR,#4100H + MOV DPL,A + ; +S_C_1: ACALL AC1 ;JUMP TO USER PROGRAM + ANL PSW,#11100111B ;BACK TO BANK 0 + RET ;EXIT + ; + newpage + ;************************************************************** + ; +THREE: ; Save value for timer function + ; + ;************************************************************** + ; + ACALL ONE ;GET THE FIRST INTEGER + CALL CBIAS ;BIAS FOR TIMER LOAD + MOV T_HH,R3 + MOV T_LL,R1 + MOV R7,#',' ;WASTE A COMMA + ACALL EATC ;FALL THRU TO TWO + ; + ;************************************************************** + ; +TWO: ; Get two values seperated by a comma off the stack + ; + ;************************************************************** + ; + ACALL EXPRB + MOV R7,#',' ;WASTE THE COMMA + ACALL WE + JMP TWOL ;EXIT + ; + ;************************************************************* + ; +ONE: ; Evaluate an expression and get an integer + ; + ;************************************************************* + ; + ACALL EXPRB ;EVALUATE EXPERSSION + ; +IFIXL: CALL IFIX ;INTEGERS IN R3:R1 + MOV A,R1 + RET + ; + ; + ;************************************************************* + ; +I_PI: ; Increment text pointer then get an integer + ; + ;************************************************************* + ; + ACALL GCI1 ;BUMP TEXT, THEN GET INTEGER + ; +PAREN_INT:; Get an integer in parens ( ) + ; + ACALL P_E + SJMP IFIXL + ; + newpage + ; +DP_B: MOV DPH,BOFAH + MOV DPL,BOFAL + RET + ; +DP_T: MOV DPH,TXAH + MOV DPL,TXAL + RET + ; +CPS: ACALL GC ;GET THE CHARACTER + CJNE A,#'"',NOPASS ;EXIT IF NO STRING + ACALL DP_T ;GET TEXT POINTER + INC DPTR ;BUMP PAST " + MOV R4,#'"' + CALL PN0 ;DO THE PRINT + INC DPTR ;GO PAST QUOTE + CLR C ;PASSED TEST + ; +T_DP: MOV TXAH,DPH ;TEXT POINTER GETS DPTR + MOV TXAL,DPL + RET + ; + ;************************************************************* + ; +S_C: ; Check for a string + ; + ;************************************************************* + ; + ACALL GC ;GET THE CHARACTER + CJNE A,#'$',NOPASS ;SET CARRY IF NOT A STRING + AJMP IST_CAL ;CLEAR CARRY, CALCULATE OFFSET + ; + ; + ; + ;************************************************************** + ; +C_TST: ACALL GC ;GET A CHARACTER + CJNE A,#',',NOPASS ;SEE IF A COMMA + ; + newpage + ;*************************************************************** + ; + ;GC AND GCI - GET A CHARACTER FROM TEXT (NO BLANKS) + ; PUT CHARACTER IN THE ACC + ; + ;*************************************************************** + ; +IGC: ACALL GCI1 ;BUMP POINTER, THEN GET CHARACTER + ; +GC: SETB RS0 ;USE BANK 1 + MOV P2,R2 ;SET UP PORT 2 + MOVX A,@R0 ;GET EXTERNAL BYTE + CLR RS0 ;BACK TO BANK 0 + RET ;EXIT + ; +GCI: ACALL GC + ; + ; This routine bumps txa by one and always clears the carry + ; +GCI1: SETB RS0 ;BANK 1 + INC R0 ;BUMP TXA + CJNE R0,#0,$+4 + INC R2 + CLR RS0 + RET ;EXIT + ; + newpage + ;************************************************************** + ; + ; Check delimiters + ; + ;************************************************************** + ; +DELTST: ACALL GC ;GET A CHARACTER + CJNE A,#CR,DT1 ;SEE IF A CR + CLR A + RET + ; +DT1: CJNE A,#':',NOPASS ;SET CARRY IF NO MATCH + ; +L_RET: RET + ; + ; + ;*************************************************************** + ; + ; FINDC - Find the character in R7, update TXA + ; + ;*************************************************************** + ; +FINDCR: MOV R7,#CR ;KILL A STATEMENT LINE + ; +FINDC: ACALL DELTST + JNC L_RET + ; + CJNE A,R7B0,FNDCL2 ;MATCH? + RET + ; +FNDCL2: ACALL GCI1 + SJMP FINDC ;LOOP + ; + ACALL GCI1 + ; +WCR: ACALL DELTST ;WASTE UNTIL A "REAL" CR + JNZ WCR-2 + RET + ; + newpage + ;*************************************************************** + ; + ; VAR_ER - Check for a variable, exit if error + ; + ;*************************************************************** + ; +VAR_ER: ACALL VAR + SJMP INTERR+2 + ; + ; + ;*************************************************************** + ; + ; S_D0 - The Statement Action Routine DO + ; + ;*************************************************************** + ; +S_DO: ACALL CSC ;FINISH UP THE LINE + MOV R4,#DTYPE ;TYPE FOR STACK + ACALL SGS1 ;SAVE ON STACK + AJMP ILOOP ;EXIT + ; + newpage + ;*************************************************************** + ; + ; CLN_UP - Clean up the end of a statement, see if at end of + ; file, eat character and line count after CR + ; + ;*************************************************************** + ; +C_2: CJNE A,#':',C_1 ;SEE IF A TERMINATOR + AJMP GCI1 ;BUMP POINTER AND EXIT, IF SO + ; +C_1: CJNE A,#T_ELSE,EP5 + ACALL WCR ;WASTE UNTIL A CR + ; +CLN_UP: ACALL GC ;GET THE CHARACTER + CJNE A,#CR,C_2 ;SEE IF A CR + ACALL IGC ;GET THE NEXT CHARACTER + CJNE A,#EOF,B_TXA ;SEE IF TERMINATOR + ; +NOPASS: SETB C + RET + ; +B_TXA: XCH A,TXAL ;BUMP TXA BY THREE + ADD A,#3 + XCH A,TXAL + JBC CY,$+4 + RET + INC TXAH + RET + ; + newpage + ;*************************************************************** + ; + ; Get an INTEGER from the text + ; sets CARRY if not found + ; returns the INTGER value in DPTR and R2:R0 + ; returns the terminator in ACC + ; + ;*************************************************************** + ; +INTERR: ACALL INTGER ;GET THE INTEGER + JC EP5 ;ERROR IF NOT FOUND + RET ;EXIT IF FOUND + ; +INTGER: ACALL DP_T + CALL FP_BASE+18 ;CONVERT THE INTEGER + ACALL T_DP + MOV DPH,R2 ;PUT THE RETURNED VALUE IN THE DPTR + MOV DPL,R0 + ; +ITRET: RET ;EXIT + ; + ; +WE: ACALL EATC ;WASTE THE CHARACTER + ; + ; Fall thru to evaluate the expression + ; + newpage + ;*************************************************************** + ; + ; EXPRB - Evaluate an expression + ; + ;*************************************************************** + ; +EXPRB: MOV R2,#LO(OPBOL) ;BASE PRECEDENCE + ; +EP1: PUSH R2B0 ;SAVE OPERATOR PRECEDENCE + CLR ARGF ;RESET STACK DESIGNATOR + ; +EP2: MOV A,SP ;GET THE STACK POINTER + ADD A,#12 ;NEED AT LEAST 12 BYTES + JNC $+5 + LJMP ERROR-3 + MOV A,ASTKA ;GET THE ARG STACK + SUBB A,#LO(TM_TOP+12);NEED 12 BYTES ALSO + JNC $+5 + LJMP E4YY + JB ARGF,EP4 ;MUST BE AN OPERATOR, IF SET + ACALL VAR ;IS THE VALUE A VARIABLE? + JNC EP3 ;PUT VARIABLE ON STACK + ; + ACALL CONST ;IS THE VALUE A NUMERIC CONSTANT? + JNC EP4 ;IF SO, CONTINUE, IF NOT, SEE WHAT + CALL GC ;GET THE CHARACTER + CJNE A,#T_LPAR,EP4 ;SEE IF A LEFT PAREN + MOV A,#(LO(OPBOL+1)) + SJMP XLPAR ;PROCESS THE LEFT PAREN + ; +EP3: ACALL PUSHAS ;SAVE VAR ON STACK + ; +EP4: ACALL GC ;GET THE OPERATOR + ; + CJNE A,#T_LPAR,$+3 ;IS IT AN OPERATOR + JNC XOP ;PROCESS OPERATOR + CJNE A,#T_UOP,$+3 ;IS IT A UNARY OPERATOR + JNC XBILT ;PROCESS UNARY (BUILT IN) OPERATOR + POP R2B0 ;GET BACK PREVIOUS OPERATOR PRECEDENCE + JB ARGF,ITRET ;OK IF ARG FLAG IS SET + ; +EP5: CLR C ;NO RECOVERY + LJMP E1XX+2 + ; + ; Process the operator + ; +XOP: ANL A,#1FH ;STRIP OFF THE TOKE BITS + JB ARGF,XOP1 ;IF ARG FLAG IS SET, PROCESS + CJNE A,#T_SUB-T_LPAR,XOP3 + MOV A,#T_NEG-T_LPAR + ; + newpage +XOP1: ADD A,#LO(OPBOL+1) ;BIAS THE TABLE + MOV R2,A + MOV DPTR,#00H + MOVC A,@A+DPTR ;GET THE CURRENT PRECEDENCE + MOV R4,A + POP ACC ;GET THE PREVIOUS PRECEDENCE + MOV R5,A ;SAVE THE PREVIOUS PRECEDENCE + MOVC A,@A+DPTR ;GET IT + CJNE A,R4B0,$+7 ;SEE WHICH HAS HIGHER PRECEDENCE + CJNE A,#12,ITRET ;SEE IF ANEG + SETB C + JNC ITRET ;PROCESS NON-INCREASING PRECEDENCE + ; + ; Save increasing precedence + ; + PUSH R5B0 ;SAVE OLD PRECEDENCE ADDRESS + PUSH R2B0 ;SAVE NEW PRECEDENCE ADDRESS + ACALL GCI1 ;EAT THE OPERATOR + ACALL EP1 ;EVALUATE REMAINING EXPRESSION + POP ACC + ; + ; R2 has the action address, now setup and perform operation + ; +XOP2: MOV DPTR,#OPTAB + ADD A,#LO(~OPBOL) + CALL ISTA1 ;SET UP TO RETURN TO EP2 + AJMP EP2 ;JUMP TO EVALUATE EXPRESSION + ; + ; Built-in operator processing + ; +XBILT: ACALL GCI1 ;EAT THE TOKEN + ADD A,#LO(50H+LO(UOPBOL)) + JB ARGF,EP5 ;XBILT MUST COME AFTER AN OPERATOR + CJNE A,#STP,$+3 + JNC XOP2 + ; +XLPAR: PUSH ACC ;PUT ADDRESS ON THE STACK + ACALL P_E + SJMP XOP2-2 ;PERFORM OPERATION + ; +XOP3: CJNE A,#T_ADD-T_LPAR,EP5 + ACALL GCI1 + AJMP EP2 ;WASTE + SIGN + ; + newpage +XPOP: ACALL X3120 ;FLIP ARGS THEN POP + ; + ;*************************************************************** + ; + ; POPAS - Pop arg stack and copy variable to R3:R1 + ; + ;*************************************************************** + ; +POPAS: LCALL INC_ASTKA + JMP VARCOP ;COPY THE VARIABLE + ; +AXTAL: MOV R2,#HI(CXTAL) + MOV R0,#LO(CXTAL) + ; + ; fall thru + ; + ;*************************************************************** + ; +PUSHAS: ; Push the Value addressed by R2:R0 onto the arg stack + ; + ;*************************************************************** + ; + CALL DEC_ASTKA + SETB ARGF ;SAYS THAT SOMTHING IS ON THE STACK + LJMP VARCOP + ; + ; + ;*************************************************************** + ; +ST_A: ; Store at expression + ; + ;*************************************************************** + ; + ACALL ONE ;GET THE EXPRESSION + SJMP POPAS ;SAVE IT + ; + ; + ;*************************************************************** + ; +LD_A: ; Load at expression + ; + ;*************************************************************** + ; + ACALL ONE ;GET THE EXPRESSION + ACALL X3120 ;FLIP ARGS + SJMP PUSHAS + ; + newpage + ;*************************************************************** + ; +CONST: ; Get a constant fron the text + ; + ;*************************************************************** + ; + CALL GC ;FIRST SEE IF LITERAL + CJNE A,#T_ASC,C0C ;SEE IF ASCII TOKEN + CALL IGC ;GET THE CHARACTER AFTER TOKEN + CJNE A,#'$',CN0 ;SEE IF A STRING + ; +CNX: CALL CSY ;CALCULATE IT + LJMP AXBYTE+2 ;SAVE IT ON THE STACK ******AA JMP-->LJMP + ; +CN0: LCALL TWO_R2 ;PUT IT ON THE STACK ******AA CALL-->LCALL + CALL GCI1 ;BUMP THE POINTER + LJMP ERPAR ;WASTE THE RIGHT PAREN ******AA JMP-->LJMP + ; + ; +C0C: CALL DP_T ;GET THE TEXT POINTER + CALL GET_NUM ;GET THE NUMBER + CJNE A,#0FFH,C1C ;SEE IF NO NUMBER + SETB C +C2C: RET + ; +C1C: JNZ FPTST + CLR C + SETB ARGF + ; +C3C: JMP T_DP + ; +FPTST: ANL A,#00001011B ;CHECK FOR ERROR + JZ C2C ;EXIT IF ZERO + ; + ; Handle the error condition + ; + MOV DPTR,#E2X ;DIVIDE BY ZERO + JNB ACC.0,$+6 ;UNDERFLOW + MOV DPTR,#E7X + JNB ACC.1,$+6 ;OVERFLOW + MOV DPTR,#E11X + ; +FPTS: JMP ERROR + ; + newpage + ;*************************************************************** + ; + ; The Command action routine - LIST + ; + ;*************************************************************** + ; +CLIST: CALL NUMC ;SEE IF TO LINE PORT + ACALL FSTK ;PUT 0FFFFH ON THE STACK + CALL INTGER ;SEE IF USER SUPPLIES LN + CLR A ;LN = 0 TO START + MOV R3,A + MOV R1,A + JC CL1 ;START FROM ZERO + ; + CALL TEMPD ;SAVE THE START ADDTESS + CALL GCI ;GET THE CHARACTER AFTER LIST + CJNE A,#T_SUB,$+10 ;CHECK FOR TERMINATION ADDRESS '-' + ACALL INC_ASTKA ;WASTE 0FFFFH + LCALL INTERR ;GET TERMINATION ADDRESS + ACALL TWO_EY ;PUT TERMINATION ON THE ARG STACK + MOV R3,TEMP5 ;GET THE START ADDTESS + MOV R1,TEMP4 + ; +CL1: CALL GETLIN ;GET THE LINE NO IN R3:R1 + JZ CL3 ;RET IF AT END + ; +CL2: ACALL C3C ;SAVE THE ADDRESS + INC DPTR ;POINT TO LINE NUMBER + ACALL PMTOP+3 ;PUT LINE NUMBER ON THE STACK + ACALL CMPLK ;COMPARE LN TO END ADDRESS + JC CL3 ;EXIT IF GREATER + CALL BCK ;CHECK FOR A CONTROL C + ACALL DEC_ASTKA ;SAVE THE COMPARE ADDRESS + CALL DP_T ;RESTORE ADDRESS + ACALL UPPL ;UN-PROCESS THE LINE + ACALL C3C ;SAVE THE CR ADDRESS + ACALL CL6 ;PRINT IT + INC DPTR ;BUMP POINTER TO NEXT LINE + MOVX A,@DPTR ;GET LIN LENGTH + DJNZ ACC,CL2 ;LOOP + ACALL INC_ASTKA ;WASTE THE COMPARE BYTE + ; +CL3: AJMP CMND1 ;BACK TO COMMAND PROCESSOR + ; +CL6: MOV DPTR,#IBUF ;PRINT IBUF + CALL PRNTCR ;PRINT IT + CALL DP_T + ; +CL7: JMP CRLF + ; + LCALL X31DP + newpage + ;*************************************************************** + ; + ;UPPL - UN PREPROCESS A LINE ADDRESSED BY DPTR INTO IBUF + ; RETURN SOURCE ADDRESS OF CR IN DPTR ON RETURN + ; + ;*************************************************************** + ; +UPPL: MOV R3,#HI(IBUF) ;POINT R3 AT HIGH IBUF + MOV R1,#LO(IBUF) ;POINT R1 AT IBUF + INC DPTR ;SKIP OVER LINE LENGTH + ACALL C3C ;SAVE THE DPTR (DP_T) + CALL L20DPI ;PUT LINE NUMBER IN R2:R0 + CALL FP_BASE+16 ;CONVERT R2:R0 TO INTEGER + CALL DP_T + INC DPTR ;BUMP DPTR PAST THE LINE NUMBER + ; +UPP0: CJNE R1,#LO(IBUF+6),$+3 + JC UPP1A-4 ;PUT SPACES IN TEXT + INC DPTR ;BUMP PAST LN HIGH + MOVX A,@DPTR ;GET USER TEXT + MOV R6,A ;SAVE A IN R6 FOR TOKE COMPARE + JB ACC.7,UPP1 ;IF TOKEN, PROCESS + CJNE A,#20H,$+3 ;TRAP THE USER TOKENS + JNC $+5 + CJNE A,#CR,UPP1 ;DO IT IF NOT A CR + CJNE A,#'"',UPP9 ;SEE IF STRING + ACALL UPP7 ;SAVE IT + ACALL UPP8 ;GET THE NEXT CHARACTER AND SAVE IT + CJNE A,#'"',$-2 ;LOOP ON QUOTES + SJMP UPP0 + ; +UPP9: CJNE A,#':',UPP1A ;PUT A SPACE IN DELIMITER + ACALL UPP7A + MOV A,R6 + ACALL UPP7 + ACALL UPP7A + SJMP UPP0 + ; +UPP1A: ACALL UPP8+2 ;SAVE THE CHARACTER, UPDATE POINTER + SJMP UPP0 ;EXIT IF A CR, ELSE LOOP + ; +UPP1: ACALL C3C ;SAVE THE TEXT POINTER + MOV C,XBIT + MOV F0,C ;SAVE XBIT IN F0 + MOV DPTR,#TOKTAB ;POINT AT TOKEN TABLE + JNB F0,UPP2 + LCALL 2078H ;SET UP DPTR FOR LOOKUP + ; +UPP2: CLR A ;ZERO A FOR LOOKUP + MOVC A,@A+DPTR ;GET TOKEN + INC DPTR ;ADVANCE THE TOKEN POINTER + CJNE A,#0FFH,UP_2 ;SEE IF DONE + JBC F0,UPP2-9 ;NOW DO NORMAL TABLE + AJMP CMND1 ;EXIT IF NOT FOUND + ; +UP_2: CJNE A,R6B0,UPP2 ;LOOP UNTIL THE SAME + ; +UP_3: CJNE A,#T_UOP,$+3 + JNC UPP3 + ACALL UPP7A ;PRINT THE SPACE IF OK + ; +UPP3: CLR A ;DO LOOKUP + MOVC A,@A+DPTR + JB ACC.7,UPP4 ;EXIT IF DONE, ELSE SAVE + JZ UPP4 ;DONE IF ZERO + ACALL UPP7 ;SAVE THE CHARACTER + INC DPTR + SJMP UPP3 ;LOOP + ; +UPP4: CALL DP_T ;GET IT BACK + MOV A,R6 ;SEE IF A REM TOKEN + XRL A,#T_REM + JNZ $+6 + ACALL UPP8 + SJMP $-2 + JNC UPP0 ;START OVER AGAIN IF NO TOKEN + ACALL UPP7A ;PRINT THE SPACE IF OK + SJMP UPP0 ;DONE + ; +UPP7A: MOV A,#' ' ;OUTPUT A SPACE + ; +UPP7: AJMP PPL9+1 ;SAVE A + ; +UPP8: INC DPTR + MOVX A,@DPTR + CJNE A,#CR,UPP7 + AJMP PPL7+1 + ; + newpage + ;************************************************************** + ; + ; This table contains all of the floating point constants + ; + ; The constants in ROM are stored "backwards" from the way + ; basic normally treats floating point numbers. Instead of + ; loading from the exponent and decrementing the pointer, + ; ROM constants pointers load from the most significant + ; digits and increment the pointers. This is done to 1) make + ; arg stack loading faster and 2) compensate for the fact that + ; no decrement data pointer instruction exsist. + ; + ; The numbers are stored as follows: + ; + ; BYTE X+5 = MOST SIGNIFICANT DIGITS IN BCD + ; BYTE X+4 = NEXT MOST SIGNIFICANT DIGITS IN BCD + ; BYTE X+3 = NEXT LEAST SIGNIFICANT DIGITS IN BCD + ; BYTE X+2 = LEAST SIGNIFICANT DIGITS IN BCD + ; BYTE X+1 = SIGN OF THE ABOVE MANTISSA 0 = +, 1 = - + ; BYTE X = EXPONENT IN TWO'S COMPLEMENT BINARY + ; ZERO EXPONENT = THE NUMBER ZERO + ; + ;************************************************************** + ; +ATTAB: DB 128-2 ; ARCTAN LOOKUP + DB 00H + DB 57H + DB 22H + DB 66H + DB 28H + ; + DB 128-1 + DB 01H + DB 37H + DB 57H + DB 16H + DB 16H + ; + DB 128-1 + DB 00H + DB 14H + DB 96H + DB 90H + DB 42H + ; + DB 128-1 + DB 01H + DB 40H + DB 96H + DB 28H + DB 75H + ; + DB 128 + DB 00H + DB 64H + DB 62H + DB 65H + DB 10H + ; + DB 128 + DB 01H + DB 99H + DB 88H + DB 20H + DB 14H + ; + DB 128 + DB 00H + DB 51H + DB 35H + DB 99H + DB 19H + ; + DB 128 + DB 01H + DB 45H + DB 31H + DB 33H + DB 33H + ; + DB 129 + DB 00H + DB 00H + DB 00H + DB 00H + DB 10H + ; + DB 0FFH ;END OF TABLE + ; +NTWO: DB 129 + DB 0 + DB 0 + DB 0 + DB 0 + DB 20H + ; +TTIME: DB 128-4 ; CLOCK CALCULATION + DB 00H + DB 00H + DB 00H + DB 04H + DB 13H + ; + newpage + ;*************************************************************** + ; + ; COSINE - Add pi/2 to stack, then fall thru to SIN + ; + ;*************************************************************** + ; +ACOS: ACALL POTWO ;PUT PI/2 ON THE STACK + ACALL AADD ;TOS = TOS+PI/2 + ; + ;*************************************************************** + ; + ; SINE - use taylor series to calculate sin function + ; + ;*************************************************************** + ; +ASIN: ACALL PIPI ;PUT PI ON THE STACK + ACALL RV ;REDUCE THE VALUE + MOV A,MT2 ;CALCULATE THE SIGN + ANL A,#01H ;SAVE LSB + XRL MT1,A ;SAVE SIGN IN MT1 + ACALL CSTAKA ;NOW CONVERT TO ONE QUADRANT + ACALL POTWO + ACALL CMPLK ;DO COMPARE + JC $+6 + ACALL PIPI + ACALL ASUB + ACALL AABS + MOV DPTR,#SINTAB ;SET UP LOOKUP TABLE + ACALL POLYC ;CALCULATE THE POLY + ACALL STRIP + AJMP SIN0 + ; + ; Put PI/2 on the stack + ; +POTWO: ACALL PIPI ;PUT PI ON THE STACK, NOW DIVIDE + ; +DBTWO: MOV DPTR,#NTWO + ACALL PUSHC + ;MOV A,#2 ;BY TWO + ;ACALL TWO_R2 + AJMP ADIV + ; + newpage + ;************************************************************* + ; +POLYC: ; Expand a power series to calculate a polynomial + ; + ;************************************************************* + ; + ACALL CSTAKA2 ;COPY THE STACK + ACALL AMUL ;SQUARE THE STACK + ACALL POP_T1 ;SAVE X*X + ACALL PUSHC ;PUT CONSTANT ON STACK + ; +POLY1: ACALL PUSH_T1 ;PUT COMPUTED VALUE ON STACK + ACALL AMUL ;MULTIPLY CONSTANT AND COMPUTED VALUE + ACALL PUSHC ;PUT NEXT CONSTANT ON STACK + ACALL AADD ;ADD IT TO THE OLD VALUE + CLR A ;CHECK TO SEE IF DONE + MOVC A,@A+DPTR + CJNE A,#0FFH,POLY1 ;LOOP UNTIL DONE + ; +AMUL: LCALL FP_BASE+6 + AJMP FPTST + ; + ;************************************************************* + ; +RV: ; Reduce a value for Trig and A**X functions + ; + ; value = (value/x - INT(value/x)) * x + ; + ;************************************************************* + ; + ACALL C_T2 ;COPY TOS TO T2 + ACALL ADIV ;TOS = TOS/TEMP2 + ACALL AABS ;MAKE THE TOS A POSITIVE NUMBER + MOV MT1,A ;SAVE THE SIGN + ACALL CSTAKA2 ;COPY THE STACK TWICE + ACALL IFIX ;PUT THE NUMBER IN R3:R1 + PUSH R3B0 ;SAVE R3 + MOV MT2,R1 ;SAVE THE LS BYTE IN MT2 + ACALL AINT ;MAKE THE TOS AN INTEGER + ACALL ASUB ;TOS = TOS/T2 - INT(TOS/T2) + ACALL P_T2 ;TOS = T2 + ACALL AMUL ;TOS = T2*(TOS/T2 - INT(TOS/T2) + POP R3B0 ;RESTORE R3 + RET ;EXIT + ; + newpage + ;************************************************************** + ; + ; TAN + ; + ;************************************************************** + ; +ATAN: ACALL CSTAKA ;DUPLACATE STACK + ACALL ASIN ;TOS = SIN(X) + ACALL SWAP_ASTKA ;TOS = X + ACALL ACOS ;TOS = COS(X) + AJMP ADIV ;TOS = SIN(X)/COS(X) + ; +STRIP: ACALL SETREG ;SETUP R0 + MOV R3,#1 ;LOOP COUNT + AJMP AI2-1 ;WASTE THE LSB + ; + ;************************************************************ + ; + ; ARC TAN + ; + ;************************************************************ + ; +AATAN: ACALL AABS + MOV MT1,A ;SAVE THE SIGN + ACALL SETREG ;GET THE EXPONENT + ADD A,#7FH ;BIAS THE EXPONENT + MOV UBIT,C ;SAVE CARRY STATUS + JNC $+4 ;SEE IF > 1 + ACALL RECIP ;IF > 1, TAKE RECIP + MOV DPTR,#ATTAB ;SET UP TO CALCULATE THE POLY + ACALL POLYC ;CALCULATE THE POLY + JNB UBIT,SIN0 ;JUMP IF NOT SET + ACALL ANEG ;MAKE X POLY NEGATIVE + ACALL POTWO ;SUBTRACT PI/2 + ACALL AADD + ; +SIN0: MOV A,MT1 ;GET THE SIGN + JZ SRT + AJMP ANEG + ; + newpage + ;************************************************************* + ; + ; FCOMP - COMPARE 0FFFFH TO TOS + ; + ;************************************************************* + ; +FCMP: ACALL CSTAKA ;COPY THE STACK + ACALL FSTK ;MAKE THE TOS = 0FFFFH + ACALL SWAP_ASTKA ;NOW COMPARE IS 0FFFFH - X + ; +CMPLK: JMP FP_BASE+4 ;DO THE COMPARE + ; + ;************************************************************* + ; +DEC_ASTKA: ;Push ARG STACK and check for underflow + ; + ;************************************************************* + ; + MOV A,#-FPSIZ + ADD A,ASTKA + CJNE A,#LO(TM_TOP+6),$+3 + JC E4YY + MOV ASTKA,A + MOV R1,A + MOV R3,#ASTKAH + ; +SRT: RET + ; +E4YY: MOV DPTR,#EXA + AJMP FPTS ;ARG STACK ERROR + ; + ; +AXTAL3: ACALL PUSHC ;PUSH CONSTANT, THEN MULTIPLY + ACALL AMUL + ; + ; Fall thru to IFIX + ; + newpage + ;*************************************************************** + ; +IFIX: ; Convert a floating point number to an integer, put in R3:R1 + ; + ;*************************************************************** + ; + CLR A ;RESET THE START + MOV R3,A + MOV R1,A + MOV R0,ASTKA ;GET THE ARG STACK + MOV P2,#ASTKAH + MOVX A,@R0 ;READ EXPONENT + CLR C + SUBB A,#81H ;BASE EXPONENT + MOV R4,A ;SAVE IT + DEC R0 ;POINT AT SIGN + MOVX A,@R0 ;GET THE SIGN + JNZ SQ_ERR ;ERROR IF NEGATIVE + JC INC_ASTKA ;EXIT IF EXPONENT IS < 81H + INC R4 ;ADJUST LOOP COUNTER + MOV A,R0 ;BUMP THE POINTER REGISTER + SUBB A,#FPSIZ-1 + MOV R0,A + ; +I2: INC R0 ;POINT AT DIGIT + MOVX A,@R0 ;GET DIGIT + SWAP A ;FLIP + CALL FP_BASE+20 ;ACCUMULATE + JC SQ_ERR + DJNZ R4,$+4 + SJMP INC_ASTKA + MOVX A,@R0 ;GET DIGIT + CALL FP_BASE+20 + JC SQ_ERR + DJNZ R4,I2 + ; + newpage + ;************************************************************ + ; +INC_ASTKA: ; Pop the ARG STACK and check for overflow + ; + ;************************************************************ + ; + MOV A,#FPSIZ ;NUMBER TO POP + SJMP SETREG+1 + ; +SETREG: CLR A ;DON'T POP ANYTHING + MOV R0,ASTKA + MOV R2,#ASTKAH + MOV P2,R2 + ADD A,R0 + JC E4YY + MOV ASTKA,A + MOVX A,@R0 +A_D: RET + ; + ;************************************************************ + ; + ; EBIAS - Bias a number for E to the X calculations + ; + ;************************************************************ + ; +EBIAS: ACALL PUSH_ONE + ACALL RV + CJNE R3,#00H,SQ_ERR ;ERROR IF R3 <> 0 + ACALL C_T2 ;TEMP 2 GETS FRACTIONS + ACALL INC_ASTKA + ACALL POP_T1 + ACALL PUSH_ONE + ; +AELP: MOV A,MT2 + JNZ AEL1 + ; + MOV A,MT1 + JZ A_D + MOV DPTR,#FPT2-1 + MOVX @DPTR,A ;MAKE THE FRACTIONS NEGATIVE + ; +RECIP: ACALL PUSH_ONE + ACALL SWAP_ASTKA + AJMP ADIV + ; +AEL1: DEC MT2 + ACALL PUSH_T1 + ACALL AMUL + SJMP AELP + ; +SQ_ERR: LJMP E3XX ;LINK TO BAD ARG + ; + newpage + ;************************************************************ + ; + ; SQUARE ROOT + ; + ;************************************************************ + ; +ASQR: ACALL AABS ;GET THE SIGN + JNZ SQ_ERR ;ERROR IF NEGATIVE + ACALL C_T2 ;COPY VARIABLE TO T2 + ACALL POP_T1 ;SAVE IT IN T1 + MOV R0,#LO(FPT1) + MOVX A,@R0 ;GET EXPONENT + JZ ALN-2 ;EXIT IF ZERO + ADD A,#128 ;BIAS THE EXPONENT + JNC SQR1 ;SEE IF < 80H + RR A + ANL A,#127 + SJMP SQR2 + ; +SQR1: CPL A ;FLIP BITS + INC A + RR A + ANL A,#127 ;STRIP MSB + CPL A + INC A + ; +SQR2: ADD A,#128 ;BIAS EXPONENT + MOVX @R0,A ;SAVE IT + ; + ; NEWGUESS = ( X/OLDGUESS + OLDGUESS) / 2 + ; +SQR4: ACALL P_T2 ;TOS = X + ACALL PUSH_T1 ;PUT NUMBER ON STACK + ACALL ADIV ;TOS = X/GUESS + ACALL PUSH_T1 ;PUT ON AGAIN + ACALL AADD ;TOS = X/GUESS + GUESS + ACALL DBTWO ;TOS = ( X/GUESS + GUESS ) / 2 + ACALL TEMP_COMP ;SEE IF DONE + JNB F0,SQR4 + ; + AJMP PUSH_T1 ;PUT THE ANSWER ON THE STACK + ; + newpage + ;************************************************************* + ; + ; NATURAL LOG + ; + ;************************************************************* + ; +ALN: ACALL AABS ;MAKE SURE THAT NUM IS POSITIVE + JNZ SQ_ERR ;ERROR IF NOT + MOV MT2,A ;CLEAR FOR LOOP + INC R0 ;POINT AT EXPONENT + MOVX A,@R0 ;READ THE EXPONENT + JZ SQ_ERR ;ERROR IF EXPONENT IS ZERO + CJNE A,#81H,$+3 ;SEE IF NUM >= 1 + MOV UBIT,C ;SAVE CARRY STATUS + JC $+4 ;TAKE RECIP IF >= 1 + ACALL RECIP + ; + ; Loop to reduce + ; +ALNL: ACALL CSTAKA ;COPY THE STACK FOR COMPARE + ACALL PUSH_ONE ;COMPARE NUM TO ONE + ACALL CMPLK + JNC ALNO ;EXIT IF DONE + ACALL SETREG ;GET THE EXPONENT + ADD A,#85H ;SEE HOW BIG IT IS + JNC ALN11 ;BUMP BY EXP(11) IF TOO SMALL + ACALL PLNEXP ;PUT EXP(1) ON STACK + MOV A,#1 ;BUMP COUNT + ; +ALNE: ADD A,MT2 + JC SQ_ERR + MOV MT2,A + ACALL AMUL ;BIAS THE NUMBER + SJMP ALNL + ; +ALN11: MOV DPTR,#EXP11 ;PUT EXP(11) ON STACK + ACALL PUSHC + MOV A,#11 + SJMP ALNE + ; + newpage +ALNO: ACALL C_T2 ;PUT NUM IN TEMP 2 + ACALL PUSH_ONE ;TOS = 1 + ACALL ASUB ;TOS = X - 1 + ACALL P_T2 ;TOS = X + ACALL PUSH_ONE ;TOS = 1 + ACALL AADD ;TOS = X + 1 + ACALL ADIV ;TOS = (X-1)/(X+1) + MOV DPTR,#LNTAB ;LOG TABLE + ACALL POLYC + INC DPTR ;POINT AT LN(10) + ACALL PUSHC + ACALL AMUL + MOV A,MT2 ;GET THE COUNT + ACALL TWO_R2 ;PUT IT ON THE STACK + ACALL ASUB ;INT - POLY + ACALL STRIP + JNB UBIT,AABS + ; +LN_D: RET + ; + ;************************************************************* + ; +TEMP_COMP: ; Compare FPTEMP1 to TOS, FPTEMP1 gets TOS + ; + ;************************************************************* + ; + ACALL PUSH_T1 ;SAVE THE TEMP + ACALL SWAP_ASTKA ;TRADE WITH THE NEXT NUMBER + ACALL CSTAKA ;COPY THE STACK + ACALL POP_T1 ;SAVE THE NEW NUMBER + JMP FP_BASE+4 ;DO THE COMPARE + ; + newpage +AETOX: ACALL PLNEXP ;EXP(1) ON TOS + ACALL SWAP_ASTKA ;X ON TOS + ; +AEXP: ;EXPONENTIATION + ; + ACALL EBIAS ;T1=BASE,T2=FRACTIONS,TOS=INT MULTIPLIED + MOV DPTR,#FPT2 ;POINT AT FRACTIONS + MOVX A,@DPTR ;READ THE EXP OF THE FRACTIONS + JZ LN_D ;EXIT IF ZERO + ACALL P_T2 ;TOS = FRACTIONS + ACALL PUSH_T1 ;TOS = BASE + ACALL SETREG ;SEE IF BASE IS ZERO + JZ $+4 + ACALL ALN ;TOS = LN(BASE) + ACALL AMUL ;TOS = FRACTIONS * LN(BASE) + ACALL PLNEXP ;TOS = EXP(1) + ACALL SWAP_ASTKA ;TOS = FRACTIONS * LN(BASE) + ACALL EBIAS ;T2 = FRACTIONS, TOS = INT MULTIPLIED + MOV MT2,#00H ;NOW CALCULATE E**X + ACALL PUSH_ONE + ACALL CSTAKA + ACALL POP_T1 ;T1 = 1 + ; +AEXL: ACALL P_T2 ;TOS = FRACTIONS + ACALL AMUL ;TOS = FRACTIONS * ACCUMLATION + INC MT2 ;DO THE DEMONIATOR + MOV A,MT2 + ACALL TWO_R2 + ACALL ADIV + ACALL CSTAKA ;SAVE THE ITERATION + ACALL PUSH_T1 ;NOW ACCUMLATE + ACALL AADD ;ADD ACCUMLATION + ACALL TEMP_COMP + JNB F0,AEXL ;LOOP UNTIL DONE + ; + ACALL INC_ASTKA + ACALL PUSH_T1 + ACALL AMUL ;LAST INT MULTIPLIED + ; +MU1: AJMP AMUL ;FIRST INT MULTIPLIED + ; + newpage + ;*************************************************************** + ; + ; integer operator - INT + ; + ;*************************************************************** + ; +AINT: ACALL SETREG ;SET UP THE REGISTERS, CLEAR CARRY + SUBB A,#129 ;SUBTRACT EXPONENT BIAS + JNC AI1 ;JUMP IF ACC > 81H + ; + ; Force the number to be a zero + ; + ACALL INC_ASTKA ;BUMP THE STACK + ; +P_Z: MOV DPTR,#ZRO ;PUT ZERO ON THE STACK + AJMP PUSHC + ; +AI1: SUBB A,#7 + JNC AI3 + CPL A + INC A + MOV R3,A + DEC R0 ;POINT AT SIGN + ; +AI2: DEC R0 ;NOW AT LSB'S + MOVX A,@R0 ;READ BYTE + ANL A,#0F0H ;STRIP NIBBLE + MOVX @R0,A ;WRITE BYTE + DJNZ R3,$+3 + RET + CLR A + MOVX @R0,A ;CLEAR THE LOCATION + DJNZ R3,AI2 + ; +AI3: RET ;EXIT + ; + newpage + ;*************************************************************** + ; +AABS: ; Absolute value - Make sign of number positive + ; return sign in ACC + ; + ;*************************************************************** + ; + ACALL ANEG ;CHECK TO SEE IF + OR - + JNZ ALPAR ;EXIT IF NON ZERO, BECAUSE THE NUM IS + MOVX @R0,A ;MAKE A POSITIVE SIGN + RET + ; + ;*************************************************************** + ; +ASGN: ; Returns the sign of the number 1 = +, -1 = - + ; + ;*************************************************************** + ; + ACALL INC_ASTKA ;POP STACK, GET EXPONENT + JZ P_Z ;EXIT IF ZERO + DEC R0 ;BUMP TO SIGN + MOVX A,@R0 ;GET THE SIGN + MOV R7,A ;SAVE THE SIGN + ACALL PUSH_ONE ;PUT A ONE ON THE STACK + MOV A,R7 ;GET THE SIGN + JZ ALPAR ;EXIT IF ZERO + ; + ; Fall thru to ANEG + ; + ;*************************************************************** + ; +ANEG: ; Flip the sign of the number on the tos + ; + ;*************************************************************** + ; + ACALL SETREG + DEC R0 ;POINT AT THE SIGN OF THE NUMBER + JZ ALPAR ;EXIT IF ZERO + MOVX A,@R0 + XRL A,#01H ;FLIP THE SIGN + MOVX @R0,A + XRL A,#01H ;RESTORE THE SIGN + ; +ALPAR: RET + ; + newpage + ;*************************************************************** + ; +ACBYTE: ; Read the ROM + ; + ;*************************************************************** + ; + ACALL IFIX ;GET EXPRESSION + CALL X31DP ;PUT R3:R1 INTO THE DP + CLR A + MOVC A,@A+DPTR + AJMP TWO_R2 + ; + ;*************************************************************** + ; +ADBYTE: ; Read internal memory + ; + ;*************************************************************** + ; + ACALL IFIX ;GET THE EXPRESSION + CALL R3CK ;MAKE SURE R3 = 0 + MOV A,@R1 + AJMP TWO_R2 + ; + ;*************************************************************** + ; +AXBYTE: ; Read external memory + ; + ;*************************************************************** + ; + ACALL IFIX ;GET THE EXPRESSION + MOV P2,R3 + MOVX A,@R1 + AJMP TWO_R2 + ; + newpage + ;*************************************************************** + ; + ; The relational operators - EQUAL (=) + ; GREATER THAN (>) + ; LESS THAN (<) + ; GREATER THAN OR EQUAL (>=) + ; LESS THAN OR EQUAL (<=) + ; NOT EQUAL (<>) + ; + ;*************************************************************** + ; +AGT: ACALL CMPLK + ORL C,F0 ;SEE IF EITHER IS A ONE + JC P_Z + ; +FSTK: MOV DPTR,#FS + AJMP PUSHC + ; +FS: DB 85H + DB 00H + DB 00H + DB 50H + DB 53H + DB 65H + ; +ALT: ACALL CMPLK + CPL C + SJMP AGT+4 + ; +AEQ: ACALL CMPLK + MOV C,F0 + SJMP ALT+2 + ; +ANE: ACALL CMPLK + CPL F0 + SJMP AEQ+2 + ; +AGE: ACALL CMPLK + SJMP AGT+4 + ; +ALE: ACALL CMPLK + ORL C,F0 + SJMP ALT+2 + ; + newpage + ;*************************************************************** + ; +ARND: ; Generate a random number + ; + ;*************************************************************** + ; + MOV DPTR,#RCELL ;GET THE BINARY SEED + CALL L31DPI + MOV A,R1 + CLR C + RRC A + MOV R0,A + MOV A,#6 + RRC A + ADD A,R1 + XCH A,R0 + ADDC A,R3 + MOV R2,A + DEC DPL ;SAVE THE NEW SEED + ACALL S20DP + ACALL TWO_EY + ACALL FSTK + ; +ADIV: LCALL FP_BASE+8 + AJMP FPTST + ; + newpage + ;*************************************************************** + ; +SONERR: ; ON ERROR Statement + ; + ;*************************************************************** + ; + LCALL INTERR ;GET THE LINE NUMBER + SETB ON_ERR + MOV DPTR,#ERRNUM ;POINT AT THR ERROR LOCATION + SJMP S20DP + ; + ; + ;************************************************************** + ; +SONEXT: ; ON EXT1 Statement + ; + ;************************************************************** + ; + LCALL INTERR + SETB INTBIT + ORL IE,#10000100B ;ENABLE INTERRUPTS + MOV DPTR,#INTLOC + ; +S20DP: MOV A,R2 ;SAVE R2:R0 @DPTR + MOVX @DPTR,A + INC DPTR + MOV A,R0 + MOVX @DPTR,A + RET + ; + newpage + ;*************************************************************** + ; + ; CASTAK - Copy and push another top of arg stack + ; + ;*************************************************************** + ; +CSTAKA2:ACALL CSTAKA ;COPY STACK TWICE + ; +CSTAKA: ACALL SETREG ;SET UP R2:R0 + SJMP PUSH_T1+4 + ; +PLNEXP: MOV DPTR,#EXP1 + ; + ;*************************************************************** + ; + ; PUSHC - Push constant on to the arg stack + ; + ;*************************************************************** + ; +PUSHC: ACALL DEC_ASTKA + MOV P2,R3 + MOV R3,#FPSIZ ;LOOP COUNTER + ; +PCL: CLR A ;SET UP A + MOVC A,@A+DPTR ;LOAD IT + MOVX @R1,A ;SAVE IT + INC DPTR ;BUMP POINTERS + DEC R1 + DJNZ R3,PCL ;LOOP + ; + SETB ARGF + RET ;EXIT + ; +PUSH_ONE:; + ; + MOV DPTR,#FPONE + AJMP PUSHC + ; + newpage + ; +POP_T1: + ; + MOV R3,#HI(FPT1) + MOV R1,#LO(FPT1) + JMP POPAS + ; +PUSH_T1: + ; + MOV R0,#LO(FPT1) + MOV R2,#HI(FPT1) + LJMP PUSHAS + ; +P_T2: MOV R0,#LO(FPT2) + SJMP $-7 ;JUMP TO PUSHAS + ; + ;**************************************************************** + ; +SWAP_ASTKA: ; SWAP TOS<>TOS-1 + ; + ;**************************************************************** + ; + ACALL SETREG ;SET UP R2:R0 AND P2 + MOV A,#FPSIZ ;PUT TOS+1 IN R1 + MOV R2,A + ADD A,R0 + MOV R1,A + ; +S_L: MOVX A,@R0 + MOV R3,A + MOVX A,@R1 + MOVX @R0,A + MOV A,R3 + MOVX @R1,A + DEC R1 + DEC R0 + DJNZ R2,S_L + RET + ; + newpage + ; +C_T2: ACALL SETREG ;SET UP R2:R0 + MOV R3,#HI(FPT2) + MOV R1,#LO(FPT2) ;TEMP VALUE + ; + ; Fall thru + ; + ;*************************************************************** + ; + ; VARCOP - Copy a variable from R2:R0 to R3:R1 + ; + ;*************************************************************** + ; +VARCOP: MOV R4,#FPSIZ ;LOAD THE LOOP COUNTER + ; +V_C: MOV P2,R2 ;SET UP THE PORTS + MOVX A,@R0 ;READ THE VALUE + MOV P2,R3 ;PORT TIME AGAIN + MOVX @R1,A ;SAVE IT + ACALL DEC3210 ;BUMP POINTERS + DJNZ R4,V_C ;LOOP + RET ;EXIT + ; +PIPI: MOV DPTR,#PIE + AJMP PUSHC + ; + newpage + ;*************************************************************** + ; + ; The logical operators ANL, ORL, XRL, NOT + ; + ;*************************************************************** + ; +AANL: ACALL TWOL ;GET THE EXPRESSIONS + MOV A,R3 ;DO THE AND + ANL A,R7 + MOV R2,A + MOV A,R1 + ANL A,R6 + SJMP TWO_EX + ; +AORL: ACALL TWOL ;SAME THING FOR OR + MOV A,R3 + ORL A,R7 + MOV R2,A + MOV A,R1 + ORL A,R6 + SJMP TWO_EX + ; +ANOT: ACALL FSTK ;PUT 0FFFFH ON THE STACK + ; +AXRL: ACALL TWOL + MOV A,R3 + XRL A,R7 + MOV R2,A + MOV A,R1 + XRL A,R6 + SJMP TWO_EX + ; +TWOL: ACALL IFIX + MOV R7,R3B0 + MOV R6,R1B0 + AJMP IFIX + ; + newpage + ;************************************************************* + ; +AGET: ; READ THE BREAK BYTE AND PUT IT ON THE ARG STACK + ; + ;************************************************************* + ; + MOV DPTR,#GTB ;GET THE BREAK BYTE + MOVX A,@DPTR + JBC GTRD,TWO_R2 + CLR A + ; +TWO_R2: MOV R2,#00H ;ACC GOES TO STACK + ; + ; +TWO_EX: MOV R0,A ;R2:ACC GOES TO STACK + ; + ; +TWO_EY: SETB ARGF ;R2:R0 GETS PUT ON THE STACK + JMP FP_BASE+24 ;DO IT + ; + newpage + ;************************************************************* + ; + ; Put directs onto the stack + ; + ;************************************************************** + ; +A_IE: MOV A,IE ;IE + SJMP TWO_R2 + ; +A_IP: MOV A,IP ;IP + SJMP TWO_R2 + ; +ATIM0: MOV R2,TH0 ;TIMER 0 + MOV R0,TL0 + SJMP TWO_EY + ; +ATIM1: MOV R2,TH1 ;TIMER 1 + MOV R0,TL1 + SJMP TWO_EY + ; +ATIM2: DB 0AAH ;MOV R2 DIRECT OP CODE + DB 0CDH ;T2 HIGH + DB 0A8H ;MOV R0 DIRECT OP CODE + DB 0CCH ;T2 LOW + SJMP TWO_EY ;TIMER 2 + ; +AT2CON: DB 0E5H ;MOV A,DIRECT OPCODE + DB 0C8H ;T2CON LOCATION + SJMP TWO_R2 + ; +ATCON: MOV A,TCON ;TCON + SJMP TWO_R2 + ; +ATMOD: MOV A,TMOD ;TMOD + SJMP TWO_R2 + ; +ARCAP2: DB 0AAH ;MOV R2, DIRECT OP CODE + DB 0CBH ;RCAP2H LOCATION + DB 0A8H ;MOV R0, DIRECT OP CODE + DB 0CAH ;R2CAPL LOCATION + SJMP TWO_EY + ; +AP1: MOV A,P1 ;GET P1 + SJMP TWO_R2 ;PUT IT ON THE STACK + ; +APCON: DB 0E5H ;MOV A, DIRECT OP CODE + DB 87H ;ADDRESS OF PCON + SJMP TWO_R2 ;PUT PCON ON THE STACK + ; + newpage + ;*************************************************************** + ; + ;THIS IS THE LINE EDITOR + ; + ;TAKE THE PROCESSED LINE IN IBUF AND INSERT IT INTO THE + ;BASIC TEXT FILE. + ; + ;*************************************************************** + ; + LJMP NOGO ;CAN'T EDIT A ROM + ; +LINE: MOV A,BOFAH + CJNE A,#HI(PSTART),LINE-3 + CALL G4 ;GET END ADDRESS FOR EDITING + MOV R4,DPL + MOV R5,DPH + MOV R3,TEMP5 ;GET HIGH ORDER IBLN + MOV R1,TEMP4 ;LOW ORDER IBLN + ; + CALL GETLIN ;FIND THE LINE + JNZ INSR ;INSERT IF NOT ZERO, ELSE APPEND + ; + ;APPEND THE LINE AT THE END + ; + MOV A,TEMP3 ;PUT IBCNT IN THE ACC + CJNE A,#4H,$+4 ;SEE IF NO ENTRY + RET ;RET IF NO ENTRY + ; + ACALL FULL ;SEE IF ENOUGH SPACE LEFT + MOV R2,R5B0 ;PUT END ADDRESS A INTO TRANSFER + MOV R0,R4B0 ;REGISTERS + ACALL IMOV ;DO THE BLOCK MOVE + ; +UE: MOV A,#EOF ;SAVE EOF CHARACTER + AJMP TBR + ; + ;INSERT A LINE INTO THE FILE + ; +INSR: MOV R7,A ;SAVE IT IN R7 + CALL TEMPD ;SAVE INSERATION ADDRESS + MOV A,TEMP3 ;PUT THE COUNT LENGTH IN THE ACC + JC LTX ;JUMP IF NEW LINE # NOT = OLD LINE # + CJNE A,#04H,$+4 ;SEE IF NULL + CLR A + ; + SUBB A,R7 ;SUBTRACT LINE COUNT FROM ACC + JZ LIN1 ;LINE LENGTHS EQUAL + JC GTX ;SMALLER LINE + ; + newpage + ; + ;EXPAND FOR A NEW LINE OR A LARGER LINE + ; +LTX: MOV R7,A ;SAVE A IN R7 + MOV A,TEMP3 ;GET THE COUNT IN THE ACC + CJNE A,#04H,$+4 ;DO NO INSERTATION IF NULL LINE + RET ;EXIT IF IT IS + ; + MOV A,R7 ;GET THE COUNT BACK - DELTA IN A + ACALL FULL ;SEE IF ENOUGH MEMORY NEW EOFA IN R3:R1 + CALL DTEMP ;GET INSERATION ADDRESS + ACALL NMOV ;R7:R6 GETS (EOFA)-DPTR + CALL X3120 + MOV R1,R4B0 ;EOFA LOW + MOV R3,R5B0 ;EOFA HIGH + INC R6 ;INCREMENT BYTE COUNT + CJNE R6,#00,$+4 ;NEED TO BUMP HIGH BYTE? + INC R7 + ; + ACALL RMOV ;GO DO THE INSERTION + SJMP LIN1 ;INSERT THE CURRENT LINE + ; +GTX: CPL A ;FLIP ACC + INC A ;TWOS COMPLEMENT + CALL ADDPTR ;DO THE ADDITION + ACALL NMOV ;R7:R6 GETS (EOFA)-DPTR + MOV R1,DPL ;SET UP THE REGISTERS + MOV R3,DPH + MOV R2,TEMP5 ;PUT INSERTATION ADDRESS IN THE RIGHT REG + MOV R0,TEMP4 + JZ $+4 ;IF ACC WAS ZERO FROM NMOV, JUMP + ACALL LMOV ;IF NO ZERO DO A LMOV + ; + ACALL UE ;SAVE NEW END ADDRESS + ; +LIN1: MOV R2,TEMP5 ;GET THE INSERTATION ADDRESS + MOV R0,TEMP4 + MOV A,TEMP3 ;PUT THE COUNT LENGTH IN ACC + CJNE A,#04H,IMOV ;SEE IF NULL + RET ;EXIT IF NULL + newpage + ;*************************************************************** + ; + ;INSERT A LINE AT ADDRESS R2:R0 + ; + ;*************************************************************** + ; +IMOV: CLR A ;TO SET UP + MOV R1,#LO(IBCNT) ;INITIALIZE THE REGISTERS + MOV R3,A + MOV R6,TEMP3 ;PUT THE BYTE COUNT IN R6 FOR LMOV + MOV R7,A ;PUT A 0 IN R7 FOR LMOV + ; + ;*************************************************************** + ; + ;COPY A BLOCK FROM THE BEGINNING + ; + ;R2:R0 IS THE DESTINATION ADDRESS + ;R3:R1 IS THE SOURCE ADDRESS + ;R7:R6 IS THE COUNT REGISTER + ; + ;*************************************************************** + ; +LMOV: ACALL TBYTE ;TRANSFER THE BYTE + ACALL INC3210 ;BUMP THE POINTER + ACALL DEC76 ;BUMP R7:R6 + JNZ LMOV ;LOOP + RET ;GO BACK TO CALLING ROUTINE + ; +INC3210:INC R0 + CJNE R0,#00H,$+4 + INC R2 + ; + INC R1 + CJNE R1,#00H,$+4 + INC R3 + RET + ; + newpage + ;*************************************************************** + ; + ;COPY A BLOCK STARTING AT THE END + ; + ;R2:R0 IS THE DESTINATION ADDRESS + ;R3:R1 IS THE SOURCE ADDRESS + ;R6:R7 IS THE COUNT REGISTER + ; + ;*************************************************************** + ; +RMOV: ACALL TBYTE ;TRANSFER THE BYTE + ACALL DEC3210 ;DEC THE LOCATIONS + ACALL DEC76 ;BUMP THE COUNTER + JNZ RMOV ;LOOP + ; +DEC_R: NOP ;CREATE EQUAL TIMING + RET ;EXIT + ; +DEC3210:DEC R0 ;BUMP THE POINTER + CJNE R0,#0FFH,$+4 ;SEE IF OVERFLOWED + DEC R2 ;BUMP THE HIGH BYTE + DEC R1 ;BUMP THE POINTER + CJNE R1,#0FFH,DEC_R ;SEE IF OVERFLOWED + DEC R3 ;CHANGE THE HIGH BYTE + RET ;EXIT + ; + ;*************************************************************** + ; + ;TBYTE - TRANSFER A BYTE + ; + ;*************************************************************** + ; +TBYTE: MOV P2,R3 ;OUTPUT SOURCE REGISTER TO PORT + MOVX A,@R1 ;PUT BYTE IN ACC + ; +TBR: MOV P2,R2 ;OUTPUT DESTINATION TO PORT + MOVX @R0,A ;SAVE THE BYTE + RET ;EXIT + ; + newpage + ;*************************************************************** + ; + ;NMOV - R7:R6 = END ADDRESS - DPTR + ; + ;ACC GETS CLOBBERED + ; + ;*************************************************************** + ; +NMOV: MOV A,R4 ;THE LOW BYTE OF EOFA + CLR C ;CLEAR THE CARRY FOR SUBB + SUBB A,DPL ;SUBTRACT DATA POINTER LOW + MOV R6,A ;PUT RESULT IN R6 + MOV A,R5 ;HIGH BYTE OF EOFA + SUBB A,DPH ;SUBTRACT DATA POINTER HIGH + MOV R7,A ;PUT RESULT IN R7 + ORL A,R6 ;SEE IF ZERO + RET ;EXIT + ; + ;*************************************************************** + ; + ;CHECK FOR A FILE OVERFLOW + ;LEAVES THE NEW END ADDRESS IN R3:R1 + ;A HAS THE INCREASE IN SIZE + ; + ;*************************************************************** + ; +FULL: ADD A,R4 ;ADD A TO END ADDRESS + MOV R1,A ;SAVE IT + CLR A + ADDC A,R5 ;ADD THE CARRY + MOV R3,A + MOV DPTR,#VARTOP ;POINT AT VARTOP + ; +FUL1: CALL DCMPX ;COMPARE THE TWO + JC FULL-1 ;OUT OF ROOM + ; +TB: MOV DPTR,#E5X ;OUT OF MEMORY + AJMP FPTS + ; + newpage + ;*************************************************************** + ; + ; PP - Preprocesses the line in IBUF back into IBUF + ; sets F0 if no line number + ; leaves the correct length of processed line in IBCNT + ; puts the line number in IBLN + ; wastes the text address TXAL and TXAH + ; + ;*************************************************************** + ; +PP: ACALL T_BUF ;TXA GETS IBUF + CALL INTGER ;SEE IF A NUMBER PRESENT + CALL TEMPD ;SAVE THE INTEGER IN TEMP5:TEMP4 + MOV F0,C ;SAVE INTEGER IF PRESENT + MOV DPTR,#IBLN ;SAVE THE LINE NUMBER, EVEN IF NONE + ACALL S20DP + MOV R0,TXAL ;TEXT POINTER + MOV R1,#LO(IBUF) ;STORE POINTER + ; + ; Now process the line back into IBUF + ; +PPL: CLR ARGF ;FIRST PASS DESIGNATOR + MOV DPTR,#TOKTAB ;POINT DPTR AT LOOK UP TABLE + ; +PPL1: MOV R5B0,R0 ;SAVE THE READ POINTER + CLR A ;ZERO A FOR LOOKUP + MOVC A,@A+DPTR ;GET THE TOKEN + MOV R7,A ;SAVE TOKEN IN CASE OF MATCH + ; +PPL2: MOVX A,@R0 ;GET THE USER CHARACTER + MOV R3,A ;SAVE FOR REM + CJNE A,#'a',$+3 + JC PPX ;CONVERT LOWER TO UPPER CASE + CJNE A,#('z'+1),$+3 + JNC PPX + CLR ACC.5 + ; +PPX: MOV R2,A + MOVX @R0,A ;SAVE UPPER CASE + INC DPTR ;BUMP THE LOOKUP POINTER + CLR A + MOVC A,@A+DPTR + CJNE A,R2B0,PPL3 ;LEAVE IF NOT THE SAME + INC R0 ;BUMP THE USER POINTER + SJMP PPL2 ;CONTINUE TO LOOP + ; +PPL3: JB ACC.7,PPL6 ;JUMP IF FOUND MATCH + JZ PPL6 ;USER MATCH + ; + ; + ; Scan to the next TOKTAB entry + ; +PPL4: INC DPTR ;ADVANCE THE POINTER + CLR A ;ZERO A FOR LOOKUP + MOVC A,@A+DPTR ;LOAD A WITH TABLE + JB ACC.7,$+6 ;KEEP SCANNING IF NOT A RESERVED WORD + JNZ PPL4 + INC DPTR + ; + ; See if at the end of TOKTAB + ; + MOV R0,R5B0 ;RESTORE THE POINTER + CJNE A,#0FFH,PPL1 ;SEE IF END OF TABLE + ; + ; Character not in TOKTAB, so see what it is + ; + CJNE R2,#' ',PPLX ;SEE IF A SPACE + INC R0 ;BUMP USER POINTER + SJMP PPL ;TRY AGAIN + ; +PPLX: JNB XBIT,PPLY ;EXTERNAL TRAP + JB ARGF,PPLY + SETB ARGF ;SAYS THAT THE USER HAS TABLE + LCALL 2078H ;SET UP POINTER + AJMP PPL1 + ; +PPLY: ACALL PPL7 ;SAVE CHARACTER, EXIT IF A CR + CJNE A,#'"',PPL ;SEE IF QUOTED STRING, START AGAIN IF NOT + ; + ; Just copy a quoted string + ; + ACALL PPL7 ;SAVE THE CHARACTER, TEST FOR CR + CJNE A,#'"',$-2 ;IS THERE AN ENDQUOTE, IF NOT LOOP + SJMP PPL ;DO IT AGAIN IF ENDQUOTE + ; +PPL6: MOV A,R7 ;GET THE TOKEN + ACALL PPL9+1 ;SAVE THE TOKEN + CJNE A,#T_REM,PPL ;SEE IF A REM TOKEN + MOV A,R3 + ACALL PPL7+1 ;WASTE THE REM STATEMENT + ACALL PPL7 ;LOOP UNTIL A CR + SJMP $-2 + ; +PPL7: MOVX A,@R0 ;GET THE CHARACTER + CJNE A,#CR,PPL9 ;FINISH IF A CR + POP R0B0 ;WASTE THE CALLING STACK + POP R0B0 + MOVX @R1,A ;SAVE CR IN MEMORY + INC R1 ;SAVE A TERMINATOR + MOV A,#EOF + MOVX @R1,A + MOV A,R1 ;SUBTRACT FOR LENGTH + SUBB A,#4 + MOV TEMP3,A ;SAVE LENGTH + MOV R1,#LO(IBCNT) ;POINT AT BUFFER COUNT + ; +PPL9: INC R0 + MOVX @R1,A ;SAVE THE CHARACTER + INC R1 ;BUMP THE POINTERS + RET ;EXIT TO CALLING ROUTINE + ; + ; + ;*************************************************************** + ; + ;DEC76 - DECREMENT THE REGISTER PAIR R7:R6 + ; + ;ACC = ZERO IF R7:R6 = ZERO ; ELSE ACC DOES NOT + ; + ;*************************************************************** + ; +DEC76: DEC R6 ;BUMP R6 + CJNE R6,#0FFH,$+4 ;SEE IF RAPPED AROUND + DEC R7 + MOV A,R7 ;SEE IF ZERO + ORL A,R6 + RET ;EXIT + ; + ;*************************************************************** + ; + ; MTOP - Get or Put the top of assigned memory + ; + ;*************************************************************** + ; +PMTOP: MOV DPTR,#MEMTOP + CALL L20DPI + AJMP TWO_EY ;PUT R2:R0 ON THE STACK + ; + newpage + ;************************************************************* + ; + ; AXTAL - Crystal value calculations + ; + ;************************************************************* + ; +AXTAL0: MOV DPTR,#XTALV ;CRYSTAL VALUE + ACALL PUSHC + ; +AXTAL1: ACALL CSTAKA2 ;COPY CRYSTAL VALUE TWICE + ACALL CSTAKA + MOV DPTR,#PTIME ;PROM TIMER + ACALL AXTAL2 + MOV DPTR,#PROGS + ACALL S31L + MOV DPTR,#IPTIME ;IPROM TIMER + ACALL AXTAL2 + MOV DPTR,#IPROGS + ACALL S31L + MOV DPTR,#TTIME ;CLOCK CALCULATION + ACALL AXTAL3 + MOV A,R1 + CPL A + INC A + MOV SAVE_T,A + MOV R3,#HI(CXTAL) + MOV R1,#LO(CXTAL) + JMP POPAS + ; +AXTAL2: ACALL AXTAL3 + ; +CBIAS: ;Bias the crystal calculations + ; + MOV A,R1 ;GET THE LOW COUNT + CPL A ;FLIP IT FOR TIMER LOAD + ADD A,#15 ;BIAS FOR CALL AND LOAD TIMES + MOV R1,A ;RESTORE IT + MOV A,R3 ;GET THE HIGH COUNT + CPL A ;FLIP IT + ADDC A,#00H ;ADD THE CARRY + MOV R3,A ;RESTORE IT + RET + ; + newpage + include bas52.pwm ; ******AA + newpage + ;LNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLN + ; +LNTAB: ; Natural log lookup table + ; + ;LNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLNLN + ; + DB 80H + DB 00H + DB 71H + DB 37H + DB 13H + DB 19H + ; + DB 7FH + DB 00H + DB 76H + DB 64H + DB 37H + DB 94H + ; + DB 80H + DB 00H + DB 07H + DB 22H + DB 75H + DB 17H + ; + DB 80H + DB 00H + DB 52H + DB 35H + DB 93H + DB 28H + ; + DB 80H + DB 00H + DB 71H + DB 91H + DB 85H + DB 86H + ; + DB 0FFH + ; + DB 81H + DB 00H + DB 51H + DB 58H + DB 02H + DB 23H + ; + newpage + ;SINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSIN + ; +SINTAB: ; Sin lookup table + ; + ;SINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSINSIN + ; + DB 128-9 + DB 00H + DB 44H + DB 90H + DB 05H + DB 16H + ; + DB 128-7 + DB 01H + DB 08H + DB 21H + DB 05H + DB 25H + ; + DB 128-5 + DB 00H + DB 19H + DB 73H + DB 55H + DB 27H + ; + newpage + ; + DB 128-3 + DB 01H + DB 70H + DB 12H + DB 84H + DB 19H + ; + DB 128-2 + DB 00H + DB 33H + DB 33H + DB 33H + DB 83H + ; + DB 128 + DB 01H + DB 67H + DB 66H + DB 66H + DB 16H + ; +FPONE: DB 128+1 + DB 00H + DB 00H + DB 00H + DB 00H + DB 10H + ; + DB 0FFH ;END OF TABLE + ; + newpage + ; +SBAUD: CALL AXTAL ;PUT CRYSTAL ON THE STACK + CALL EXPRB ;PUT THE NUMBER AFTER BAUD ON STACK + MOV A,#12 + ACALL TWO_R2 ;TOS = 12 + ACALL AMUL ;TOS = 12*BAUD + ACALL ADIV ;TOS = XTAL/(12*BAUD) + ACALL IFIX + ACALL CBIAS + MOV DPTR,#SPV + ; +S31L: JMP S31DP + ; +AFREE: CALL PMTOP ;PUT MTOP ON STACK + CALL G4 ;GET END ADDRESS + MOV R0,DPL + MOV R2,DPH + ACALL TWO_EY + ; +ASUB: LCALL FP_BASE+2 ;DO FP SUB + AJMP FPTST + ; +ALEN: CALL CCAL ;CALCULATE THE LEN OF THE SELECTED PROGRAM + MOV R2,R7B0 ;SAVE THE HIGH BYTE + MOV A,R6 ;SAVE THE LOW BYTE + AJMP TWO_EX ;PUT IT ON THE STACK + ; +ATIME: MOV C,EA ;SAVE INTERRUTS + CLR EA + PUSH MILLIV ;SAVE MILLI VALUE + MOV R2,TVH ;GET THE TIMER + MOV A,TVL + MOV EA,C ;SAVE INTERRUPTS + ACALL TWO_EX ;PUT TIMER ON THE STACK + POP ACC ;GET MILLI + ACALL TWO_R2 ;PUT MILLI ON STACK + MOV A,#200 + ACALL TWO_R2 ;DIVIDE MILLI BY 200 + ACALL ADIV + ; +AADD: LCALL FP_BASE ;DO FP ADDITION + AJMP FPTST ;CHECK FOR ERRORS + ; + newpage + ;************************************************************** + ; + ; Here are some error messages that were moved + ; + ;************************************************************** + ; + ; +E1X: DB "BAD SYNTAX",'"' +E2X: DB 128+10 + DB "DIVIDE BY ZERO",'"' + ; +E6X: DB "ARRAY SIZE",'"' + ; + newpage + ;************************************************************** + ; +T_BUF: ; TXA gets IBUF + ; + ;************************************************************** + ; + MOV TXAH,#HI(IBUF) + MOV TXAL,#LO(IBUF) + RET + ; + ; + ;*************************************************************** + ; +CXFER: ; Transfer a program from rom to ram + ; + ;*************************************************************** + ; + CALL CCAL ;GET EVERYTHING SET UP + MOV R2,#HI(PSTART) + MOV R0,#LO(PSTART) + ACALL LMOV ;DO THE TRANSFER + CALL RCLEAR ;CLEAR THE MEMORY + ; + ; Fall thru to CRAM + ; + ;*************************************************************** + ; +CRAM: ; The command action routine - RAM - Run out of ram + ; + ;*************************************************************** + ; + CLR CONB ;CAN'T CONTINUE IF MODE CHANGE + MOV BOFAH,#HI(PSTART) + MOV BOFAL,#LO(PSTART) + ; + ; Fall thru to Command Processor + ; + newpage + ;*************************************************************** + ; +CMND1: ; The entry point for the command processor + ; + ;*************************************************************** + ; + LCALL SPRINT+4 ;WASTE AT AND HEX + CLR XBIT ;TO RESET IF NEEDED + CLR A + MOV DPTR,#2002H ;CHECK FOR EXTERNAL TRAP PACKAGE + MOVC A,@A+DPTR + CJNE A,#5AH,$+6 + LCALL 2048H ;IF PRESENT JUMP TO LOCATION 200BH + MOV DPTR,#RDYS ;PRINT THE READY MESSAGE + CALL CRP ;DO A CR, THEN, PRINT FROM THE ROM + ; +CMNDR: SETB DIRF ;SET THE DIRECT INPUT BIT + MOV SP,SPSAV ;LOAD THE STACK + ACALL CL7 ;DO A CRLF + ; +CMNX: CLR GTRD ;CLEAR BREAK + MOV DPTR,#5EH ;DO RUN TRAP + MOVX A,@DPTR + XRL A,#52 + JNZ $+5 + LJMP CRUN + MOV R5,#'>' ;OUTPUT A PROMPT + LCALL TEROT + CALL INLINE ;INPUT A LINE INTO IBUF + CALL PP ;PRE-PROCESS THE LINE + JB F0,CMND3 ;NO LINE NUMBER + CALL LINE ;PROCESS THE LINE + LCALL LCLR + JB LINEB,CMNX ;DON'T CLEAR MEMORY IF NO NEED + SETB LINEB + LCALL RCLEAR ;CLEAR THE MEMORY + SJMP CMNX ;LOOP BACK + ; +CMND3: CALL T_BUF ;SET UP THE TEXT POINTER + CALL DELTST ;GET THE CHARACTER + JZ CMNDR ;IF CR, EXIT + MOV DPTR,#CMNDD ;POINT AT THE COMMAND LOOKUP + CJNE A,#T_CMND,$+3 ;PROCESS STATEMENT IF NOT A COMMAND + JC CMND5 + CALL GCI1 ;BUMP TXA + ANL A,#0FH ;STRIP MSB'S FOR LOOKUP + LCALL ISTA1 ;PROCESS COMMAND + SJMP CMNDR + ; +CMND5: LJMP ILOOP ;CHECK FOR A POSSIBLE BREAK + ; + ; + ; + ;CONSTANTS + ; +XTALV: DB 128+8 ; DEFAULT CRYSTAL VALUE + DB 00H + DB 00H + DB 92H + DB 05H + DB 11H + ; +EXP11: DB 85H + DB 00H + DB 42H + DB 41H + DB 87H + DB 59H + ; +EXP1: DB 128+1 ; EXP(1) + DB 00H + DB 18H + DB 28H + DB 18H + DB 27H + ; +IPTIME: DB 128-4 ;FPROG TIMING + DB 00H + DB 00H + DB 00H + DB 75H + DB 83H + ; +PIE: DB 128+1 ;PI + DB 00H + DB 26H + DB 59H + DB 41H + DB 31H ; 3.1415926 + ; + newpage + ;*************************************************************** + ; + ; The error messages, some have been moved + ; + ;*************************************************************** + ; +E7X: DB 128+30 + DB "ARITH. UNDERFLOW",'"' + ; +E5X: DB "MEMORY ALLOCATION",'"' + ; +E3X: DB 128+40 + DB "BAD ARGUMENT",'"' + ; +EXI: DB "I-STACK",'"' + ; + newpage + ;*************************************************************** + ; + ; The command action routine - CONTINUE + ; + ;*************************************************************** + ; +CCONT: MOV DPTR,#E15X + JNB CONB,ERROR ;ERROR IF CONTINUE IS NOT SET + ; +CC1: ;used for input statement entry + ; + MOV TXAH,INTXAH ;RESTORE TXA + MOV TXAL,INTXAL + JMP CILOOP ;EXECUTE + ; +DTEMP: MOV DPH,TEMP5 ;RESTORE DPTR + MOV DPL,TEMP4 + RET + ; +TEMPD: MOV TEMP5,DPH + MOV TEMP4,DPL + RET + ; + newpage + ;************************************************************** + ; +I_DL: ; IDLE + ; + ;************************************************************** + ; + JB DIRF,E1XX ;SYNTAX ERROR IN DIRECT INPUT + CLR DACK ;ACK IDLE + ; +U_ID1: DB 01000011B ;ORL DIRECT OP CODE + DB 87H ;PCON ADDRESS + DB 01H ;SET IDLE BIT + JB INTPEN,I_RET ;EXIT IF EXTERNAL INTERRUPT + JBC U_IDL,I_RET ;EXIT IF USER WANTS TO + JNB OTS,U_ID1 ;LOOP IF TIMER NOT ENABLED + LCALL T_CMP ;CHECK THE TIMER + JC U_ID1 ;LOOP IF TIME NOT BIG ENOUGH + ; +I_RET: SETB DACK ;RESTORE EXECUTION + RET ;EXIT IF IT IS + ; + ; + ; +ER0: INC DPTR ;BUMP TO TEXT + JB DIRF,ERROR0 ;CAN'T GET OUT OF DIRECT MODE + JNB ON_ERR,ERROR0 ;IF ON ERROR ISN'T SET, GO BACK + MOV DPTR,#ERRLOC ;SAVE THE ERROR CODE + CALL RC2 ;SAVE ERROR AND SET UP THE STACKS + INC DPTR ;POINT AT ERRNUM + JMP ERL4 ;LOAD ERR NUM AND EXIT + ; + newpage + ; + ; Syntax error + ; +E1XX: MOV C,DIRF ;SEE IF IN DIRECT MODE + MOV DPTR,#E1X ;ERROR MESSAGE + SJMP ERROR+1 ;TRAP ON SET DIRF + ; + MOV DPTR,#EXI ;STACK ERROR + ; + ; Falls through + ; + ;*************************************************************** + ; + ;ERROR PROCESSOR - PRINT OUT THE ERROR TYPE, CHECK TO SEE IF IN + ; RUN OR COMMAND MODE, FIND AND PRINT OUT THE + ; LINE NUMBER IF IN RUN MODE + ; + ;*************************************************************** + ; +ERROR: CLR C ;RESET STACK + MOV SP,SPSAV ;RESET THE STACK + LCALL SPRINT+4 ;CLEAR LINE AND AT MODE + CLR A ;SET UP TO GET ERROR CODE + MOVC A,@A+DPTR + JBC ACC.7,ER0 ;PROCESS ERROR + ; +ERROR0: ACALL TEMPD ;SAVE THE DATA POINTER + JC $+5 ;NO RESET IF CARRY IS SET + LCALL RC1 ;RESET THE STACKS + CALL CRLF2 ;DO TWO CARRIAGE RET - LINE FEED + MOV DPTR,#ERS ;OUTPUT ERROR MESSAGE + CALL ROM_P + CALL DTEMP ;GET THE ERROR MESSAGE BACK + ; +ERRS: CALL ROM_P ;PRINT ERROR TYPE + JNB DIRF,ER1 ;DO NOT PRINT IN LINE IF DIRF=1 + ; +SERR1: CLR STOPBIT ;PRINT STOP THEN EXIT, FOR LIST + JMP CMND1 + ; +ER1: MOV DPTR,#INS ;OUTPUT IN LINE + CALL ROM_P + ; + ;NOW, FIND THE LINE NUMBER + ; + ; + newpage + ; + ; + CALL DP_B ;GET THE FIRST ADDRESS OF THE PROGRAM + CLR A ;FOR INITIALIZATION + ; +ER2: ACALL TEMPD ;SAVE THE DPTR + CALL ADDPTR ;ADD ACC TO DPTR + ACALL ER4 ;R3:R1 = TXA-DPTR + JC ER3 ;EXIT IF DPTR>TXA + JZ ER3 ;EXIT IF DPTR=TXA + MOVX A,@DPTR ;GET LENGTH + CJNE A,#EOF,ER2 ;SEE IF AT THE END + ; +ER3: ACALL DTEMP ;PUT THE LINE IN THE DPTR + ACALL ER4 ;R3:R1 = TXA - BEGINNING OF LINE + MOV A,R1 ;GET LENGTH + ADD A,#10 ;ADD 10 TO LENGTH, DPTR STILL HAS ADR + MOV MT1,A ;SAVE THE COUNT + INC DPTR ;POINT AT LINE NUMBER HIGH BYTE + CALL PMTOP+3 ;LOAD R2:R0, PUT IT ON THE STACK + ACALL FP_BASE+14 ;OUTPUT IT + JB STOPBIT,SERR1 ;EXIT IF STOP BIT SET + CALL CRLF2 ;DO SOME CRLF'S + CALL DTEMP + CALL UPPL ;UNPROCESS THE LINE + CALL CL6 ;PRINT IT + MOV R5,#'-' ;OUTPUT DASHES, THEN AN X + ACALL T_L ;PRINT AN X IF ERROR CHARACTER FOUND + DJNZ MT1,$-4 ;LOOP UNTIL DONE + MOV R5,#'X' + ACALL T_L + AJMP SERR1 + ; +ER4: MOV R3,TXAH ;GET TEXT POINTER AND PERFORM SUBTRACTION + MOV R1,TXAL + JMP DUBSUB + ; + newpage + ;************************************************************** + ; + ; Interrupt driven timer + ; + ;************************************************************** + ; +I_DR: MOV TH0,SAVE_T ;LOAD THE TIMER + XCH A,MILLIV ;SAVE A, GET MILLI COUNTER + INC A ;BUMP COUNTER + CJNE A,#200,TR ;CHECK OUT TIMER VALUE + CLR A ;FORCE ACC TO BE ZERO + INC TVL ;INCREMENT LOW TIMER + CJNE A,TVL,TR ;CHECK LOW VALUE + INC TVH ;BUMP TIMER HIGH + ; +TR: XCH A,MILLIV + POP PSW + RETI + ; + newpage + include bas52.clk + ;*************************************************************** + ; +SUI: ; Statement USER IN action routine + ; + ;*************************************************************** + ; + ACALL OTST + MOV CIUB,C ;SET OR CLEAR CIUB + RET + ; + ;*************************************************************** + ; +SUO: ; Statement USER OUT action routine + ; + ;*************************************************************** + ; + ACALL OTST + MOV COUB,C + RET + ; +OTST: ; Check for a one + ; + LCALL GCI ;GET THE CHARACTER, CLEARS CARRY + SUBB A,#'1' ;SEE IF A ONE + CPL C ;SETS CARRY IF ONE, CLEARS IT IF ZERO + RET + ; + newpage + ;************************************************************** + ; + ; IBLK - EXECUTE USER SUPPLIED TOKEN + ; + ;************************************************************** + ; +IBLK: JB PSW.4,IBLK-1 ;EXIT IF REGISTER BANK <> 0 + JB PSW.3,IBLK-1 + JBC ACC.7,$+9 ;SEE IF BIT SEVEN IS SET + MOV DPTR,#USENT ;USER ENTRY LOCATION + LJMP ISTA1 + ; + JB ACC.0,199FH ;FLOATING POINT INPUT + JZ T_L ;DO OUTPUT ON 80H + MOV DPTR,#FP_BASE-2 + JMP @A+DPTR + ; + ; + ;************************************************************** + ; + ; GET_NUM - GET A NUMBER, EITHER HEX OR FLOAT + ; + ;************************************************************** + ; +GET_NUM:ACALL FP_BASE+10 ;SCAN FOR HEX + JNC FP_BASE+12 ;DO FP INPUT + ; + ACALL FP_BASE+18 ;ASCII STRING TO R2:R0 + JNZ H_RET + PUSH DPH ;SAVE THE DATA_POINTER + PUSH DPL + ACALL FP_BASE+24 ;PUT R2:R0 ON THE STACK + POP DPL ;RESTORE THE DATA_POINTER + POP DPH + CLR A ;NO ERRORS + RET ;EXIT + ; + newpage + ;************************************************************** + ; + ; WB - THE EGO MESSAGE + ; + ;************************************************************** + ; +WB: DB 'W'+80H,'R'+80H + DB 'I'+80H,'T'+80H,'T','E'+80H,'N'+80H + DB ' ','B'+80H,'Y'+80H,' ' + DB 'J'+80H,'O'+80H,'H'+80H,'N'+80H,' '+80H + DB 'K','A'+80H,'T'+80H,'A'+80H,'U'+80H + DB 'S','K'+80H,'Y'+80H + DB ", I",'N'+80H,'T'+80H,'E'+80H,'L'+80H + DB ' '+80H,'C'+80H,'O'+80H,'R'+80H,'P'+80H + DB ". 1",'9'+80H,"85" +H_RET: RET + ; + newpage + ORG 1990H + ; +T_L: LJMP TEROT + ; + ORG 1F78H + ; +CKS_I: JB CKS_B,CS_I + LJMP 401BH + ; +CS_I: LJMP 2088H + ; +E14X: DB "NO DATA",'"' + ; +E11X: DB 128+20 + DB "ARITH. OVERFLOW",'"' + ; +E16X: DB "PROGRAMMING",'"' + ; +E15X: DB "CAN" + DB 27H + DB "T CONTINUE",'"' + ; +E10X: DB "INVALID LINE NUMBER",'"' + ; +NOROM: DB "PROM MODE",'"' + ; +S_N: DB "*MCS-51(tm) BASIC V1.1*",'"' + ; + ORG 1FF8H + ; +ERS: DB "ERROR: ",'"' + ; + newpage + ;*************************************************************** + ; + segment xdata ;External Ram + ; + ;*************************************************************** + ; + DS 4 +IBCNT: DS 1 ;LENGTH OF A LINE +IBLN: DS 2 ;THE LINE NUMBER +IBUF: DS LINLEN ;THE INPUT BUFFER +CONVT: DS 15 ;CONVERSION LOCATION FOR FPIN + ; + ORG 100H + ; +GTB: DS 1 ;GET LOCATION +ERRLOC: DS 1 ;ERROR TYPE +ERRNUM: DS 2 ;WHERE TO GO ON AN ERROR +VARTOP: DS 2 ;TOP OF VARIABLE STORAGE +ST_ALL: DS 2 ;STORAGE ALLOCATION +MT_ALL: DS 2 ;MATRIX ALLOCATION +MEMTOP: DS 2 ;TOP OF MEMORY +RCELL: DS 2 ;RANDOM NUMBER CELL + DS FPSIZ-1 +CXTAL: DS 1 ;CRYSTAL + DS FPSIZ-1 +FPT1: DS 1 ;FLOATINP POINT TEMP 1 + DS FPSIZ-1 +FPT2: DS 1 ;FLOATING POINT TEMP 2 +INTLOC: DS 2 ;LOCATION TO GO TO ON INTERRUPT +STR_AL: DS 2 ;STRING ALLOCATION +SPV: DS 2 ;SERIAL PORT BAUD RATE +TIV: DS 2 ;TIMER INTERRUPT NUM AND LOC +PROGS: DS 2 ;PROGRAM A PROM TIME OUT +IPROGS: DS 2 ;INTELLIGENT PROM PROGRAMMER TIMEOUT +TM_TOP: DS 1 + + include bas52.fp + + END diff --git a/tests/t_bas52/t_bas52.doc b/tests/t_bas52/t_bas52.doc new file mode 100644 index 0000000..05efe9d --- /dev/null +++ b/tests/t_bas52/t_bas52.doc @@ -0,0 +1,11 @@ ++---------------------- Test Application BAS52 ----------------------------+ +| | +| This is the source of the BASIC interpreter for Intel's 8052AH-Basic | +| (version 1.1). In contrast to other test programs, the reference binary | +| was extracted from a real 8052AH and not generated with the BP version | +| of AS. Since the source of this interpreter is now freeware, it should | +| be okay to include this program. Of course, I had to modify the code a | +| bit to adapt it to AS... The source and ROM dump was provided by | +| squest@cris.com. | +| | ++----------------------------------------------------------------------------+ diff --git a/tests/t_bas52/t_bas52.inc b/tests/t_bas52/t_bas52.inc new file mode 100644 index 0000000..6bf1b5c --- /dev/null +++ b/tests/t_bas52/t_bas52.inc @@ -0,0 +1,2 @@ +; tests/t_bas52/t_bas52.asm-Includefile für Assembler-Programm +; Ende Includefile für Assembler-Programm diff --git a/tests/t_bas52/t_bas52.ori b/tests/t_bas52/t_bas52.ori new file mode 100644 index 0000000..f86786d Binary files /dev/null and b/tests/t_bas52/t_bas52.ori differ -- cgit v1.2.3