;MATHE.ASM
;26.11.89 SONTOPSKI  2057 REINBEK   040/7223566
;CHIP: 80515 SIEMENS
;MATHEMATIKPROGRAMM FUER 80515
;BEI ALLEN ROUTINEN WERDEN DIE REGISTER
;WIE FOLGT VERWENDET:
;R0 = ADRESSE 1. OPERAND; QUELLE FUER MOV
;R1 = ADRESSE 2. OPERAND; ZIEL FUER MOV
;R2 = ANZAHL DER ZU BEARBEITENDEN BYTES
;R3 = ANZAHL DER SHIFTS
;R4 = ANZAHL DER ZU BEARBEITENDEN BITS
;**************************************************
;SPEICHERBELEGUNG: UNTERE ADRESSE   = MS-BYTE (MSB)
;                  HOECHSTE ADRESSE = LS-BYTE (LSB)
;**************************************************
;
;$NOMOD51
;#include <MATHE.EQU>


PUBLIC MOV_CODE,MOV_CODE_2,MOV_CODE_4
PUBLIC MOV_IRAM,MOV_IRAM_2,MOV_IRAM_4
PUBLIC BINADD,BINSUB
PUBLIC ADD_32,SUB_32
PUBLIC ADD_16_P,SUB_16_P
PUBLIC ADD_32_P,SUB_32_P
PUBLIC CHECK_0,CHECK_0_2,CHECK_0_4
PUBLIC CLR_HR,CLR_HR1,CLR_HR2,CLR_HR3
PUBLIC CLR_IRAM,CLR_IRAM_2,CLR_IRAM_4
PUBLIC CLR_OP,CLR_OP1,CLR_OP2
PUBLIC CLR_OP_8,CLR_OP_12,CLR_MATHE,CLR_ALL
PUBLIC COMP,COMP_2,COMP_4
PUBLIC COMP2,COMP2_2,COMP2_4
PUBLIC MUL_16,DIV_32
PUBLIC MUL_16_P,MUL_16_PK,DIV_32_P
PUBLIC SHIFTL,SHIFTL_4,SHIFTL_2_4
PUBLIC SHIFTL_0,SHIFTL_0_2,SHIFTL_0_4,SHIFTL_0_N
PUBLIC SHIFTR,SHIFTR_4
PUBLIC SHIFTR_0,SHIFTR_0_2,SHIFTR_0_4,SHIFTR_0_N
PUBLIC HR1,HR2
	
	
	
;-------------------------------------------------

MATHE_ROUTINES  SEGMENT  CODE
MATH_VAR		SEGMENT  IDATA
	
	RSEG  MATH_VAR
OP1:		DS	4	;1. OPERAND MSB	
DIVISOR:			;DIVISOR	
OP2:		DS	4	;2. OPERAND MSB
MULKANT	equ	OP2+2	;MULTIPLIKANT
MULKATOR:			;MULTIPLIKATOR
DIVIDEND:	DS	4	;DIVIDEND MSB
QUOTIENT:	DS	4	;QUOTIENT MSB
ABR:		DS	4	;ARBEITSREG.1 MSB
HR1:		DS	4	;HILFSREG.1 MSB
HR2:		DS	4	;HILFSREG.2 MSB
HR3:		DS	4	;HILFSREG.3 MSB

	RSEG  MATHE_ROUTINES
		
;------------------------------------------------

		USING 0
			
;------------------------------------------------
;
;MOV_IRAM_2 (MOVE 2 BYTES OF INTERNAL RAM SOURCE -> DESTINATION)
;BRINGT 2 BYTES DES INTERNEN RAMS VON QUELLE  -> ZIEL.
;ZU BEGINN: R0 = ADRESSE QUELLE (MSB)
;           R1 = ADRESSE ZIEL (MSB)
;
;MOV_IRAM_4 (MOVE 4 BYTES OF INTERNAL RAM SOURCE -> DESTINATION)
;BRINGT 4 BYTES DES INTERNEN RAMS VON QUELLE  -> ZIEL.
;ZU BEGINN: R0 = ADRESSE QUELLE (MSB)
;           R1 = ADRESSE ZIEL (MSB)
;
;MOV_IRAM (MOVE N BYTES OF INTERNAL RAM SOURCE -> DESTINATION)
;BRINGT N-BYTES DES INTERNEN RAMS VON QUELLE  -> ZIEL.
;ZU BEGINN: R0 = ADRESSE QUELLE (MSB)
;           R1 = ADRESSE ZIEL (MSB)
;           R2 = ANZAHL DER BYTES
;
MOV_IRAM_2:
        MOV     R2,#2
        SJMP    MOV_IRAM
MOV_IRAM_4:
        MOV     R2,#4
MOV_IRAM:
        MOV     A,@R0
        MOV     @R1,A
        INC     R0
        INC     R1
        DJNZ    R2,MOV_IRAM
        RET
			
			
;------------------------------------------------
;MOV_CODE_2 (MOVE 2 BYTES OF CODE -> INTERNAL RAM)
;BRINGT 2 BYTES AUS DEM CODE-BEREICH (ROM) INS
;INTERNE RAM.
;ZU BEGINN: DPTR = QUELLE (MSB)
;             R1 = ZIEL (MSB)
;
;MOV_CODE_4 (MOVE 4 BYTES OF CODE -> INTERNAL RAM)
;BRINGT 4 BYTES AUS DEM CODE-BEREICH (ROM) INS
;INTERNE RAM.
;ZU BEGINN: DPTR = QUELLE (MSB)
;             R1 = ZIEL (MSB)
;
;MOV_CODE (MOVE N BYTES OF CODE -> INTERNAL RAM)
;BRINGT N-BYTES AUS DEM CODE-BEREICH (ROM) INS
;INTERNE RAM.
;ZU BEGINN: DPTR = QUELLE (MSB)
;             R1 = ZIEL (MSB)
;             R2 = ANZAHL DER BYTES (N)
;
MOV_CODE_2:
        MOV     R2,#2
        SJMP    MOV_CODE
MOV_CODE_4:
        MOV     R2,#4
MOV_CODE:
        CLR     A
        MOVC    A,@A+DPTR       ;HOLE BYTE AUS CODEBEREICH
        MOV     @R1,A           ;SPEICHERE -> INTERNES RAM
        INC     DPTR            ;VERSCHIEBE ADR.ZEIGER
        INC     R1              ;   "          "
        DJNZ    R2,MOV_CODE
        RET

;------------------------------------------------
;CHECK_0_4 (CHECK 4 BYTES OF INT. RAM ON 0)
;TESTET EINEN 4 BYTE LANGEN OPERANDEN AUF 0.
;ZU BEGINN: R0 = ADRESSE 1. BYTE (MSB)
;AM ENDE  : F0 = 1 WENN 0, CY UNVERŽNDERT
;
;CHECK_0_2 (CHECK 2 BYTES OF INT. RAM ON 0)
;TESTET EINEN 2 BYTE LANGEN OPERANDEN AUF 0.
;ZU BEGINN: R0 = ADRESSE 1. BYTE (MSB)
;AM ENDE  : F0 = 1 WENN 0, CY UNVERŽNDERT
;
;CHECK_0 (CHECK N BYTES OF INT. RAM ON 0)
;TESTET EINEN N-BYTE LANGEN OPERANDEN AUF 0.
;ZU BEGINN: R0 = ADRESSE 1. BYTE (MSB)
;           R2 = ANZAHL DER BYTES (N)
;AM ENDE  : F0 = 1 WENN 0, CY UNVERŽNDERT
;
CHECK_0_4:
        MOV     R2,#4
        SJMP    CHECK_0
CHECK_0_2:
        MOV     R2,#2
CHECK_0:
        PUSH    ACC
CHK1:
        MOV     A,@R0
        CLR     F0              ;F0  = 0  WENN <> 0
        JNZ     CHK2
        INC     R0
        DJNZ    R2,CHK1
        CPL     F0              ;F0 = 1, WENN WERT = 0H
CHK2:
        POP     ACC
        RET


;------------------------------------------------
;CLR_OP1 (CLEAR OP1)
;LOESCHT OP1
;
;CLR_OP2 (CLEAR OP2)
;LOESCHT OP2
;
;CLR_HR1 (CLEAR HR1)
;LOESCHT HR1
;
;CLR_HR2 (CLEAR HR2)
;LOESCHT HR2
;
;CLR_HR3 (CLEAR HR3)
;LOESCHT HR3
;
;CLR_HR (CLEAR HR.S)
;LOESCHT ALLE HILFSREG.S AB HR1 BIS HR3+3
;
;CLR_OP_8 (CLEAR 8 BYTES WITH START-ADDR. OP1)
;LOESCHT 8 BYTES AB OP1 (MSB)
;
;CLR_OP_12 (CLEAR 12 BYTES WITH START-ADDR. OP1)
;LOESCHT 12 BYTES AB OP1 (MSB)
;
;CLR_MATHE (CLEAR 20 BYTES OF MATHE-WORKING-AREA)
;LOESCHT ALLE 20 BYTES FUER DIE MATHEROUTINEN
;AB OP1 BIS ABR+3
;
;CLR_ALL (CLEAR 32 BYTES OF WORKING-AREA)
;LOESCHT ALLE 32 BYTES FUER MATHE UND HILFSREG.S
;AB OP1 BIS HR3+3
;
;CLR_OP (CLEAR N BYTES WITH START-ADDR. OP1)
;LOESCHT N-BYTES AB OP1 (MSB)
;ZU BEGINN: R2 = ANZAHL DER ZU LOESCHENDEN BYTES
;
;CLR_IRAM_2 (CLEAR 2 BYTES OF INTERNAL RAM)
;LOESCHT 2 BYTES DES INTERNEN RAMS
;R0 = STARTADRESSE
;
;CLR_IRAM_4 (CLEAR 4 BYTES OF INTERNAL RAM)
;LOESCHT 4 BYTES DES INTERNEN RAMS
;R0 = STARTADRESSE
;
;CLR_IRAM (CLEAR INTERNAL RAM)
;LOESCHT EINEN N-BYTE LANGEN BEREICH DES INTERNEN RAMS.
;R0 = START-ADRESSE
;R2 = ANZAHL DER BYTES (N)

CLR_OP1:
        MOV     R2,#4
        SJMP    CLR_OP
CLR_OP2:
        MOV     B,R0
        MOV     R0,#OP2
        SJMP    CLR_IR_4
CLR_OP_8:
        MOV     R2,#8
        SJMP    CLR_OP
CLR_OP_12:
        MOV     R2,#12
        SJMP    CLR_OP
CLR_HR1:
        MOV     R2,#4
        SJMP    CLR_H
CLR_HR2:
        MOV     B,R0
        MOV     R0,#HR2
        SJMP    CLR_IR_4
CLR_HR3:
        MOV     B,R0
        MOV     R0,#HR3
CLR_IR_4:
        LCALL   CLR_IRAM_4
        MOV     R0,B
        RET
CLR_HR:
        MOV     R2,#12
CLR_H:
        MOV     B,R0
        MOV     R0,#HR1
        SJMP    CLR_IR
CLR_MATHE:
        MOV     R2,#20
        SJMP    CLR_OP
CLR_ALL:
        MOV     R2,#32
CLR_OP:
        MOV     B,R0
        MOV     R0,#OP1
CLR_IR:
        LCALL   CLR_IRAM
        MOV     R0,B
        RET
CLR_IRAM_2:
        MOV     R2,#2
        SJMP    CLR_IRAM
CLR_IRAM_4:
        MOV     R2,#4
CLR_IRAM:
        MOV     @R0,#0
        INC     R0
        DJNZ    R2,CLR_IRAM
        RET

;
;------------------------------------------------------
;SHIFTL_0_2 (SHIFT LEFT 2 BYTES WITH 0 -> LS-BIT)
;SCHIEBT 2 BYTES 1 * NACH LINKS INS CARRY.
;VON HINTEN WIRD 0 NACHGESCHOBEN.
;ZU BEGINN: R0 = ADRESSE LETZTES BYTES (LSB)
;
;SHIFTL_0_4 (SHIFT LEFT 4 BYTES WITH 0 -> LS-BIT)
;SCHIEBT 4 BYTES 1 * NACH LINKS INS CARRY.
;VON HINTEN WIRD 0 NACHGESCHOBEN.
;ZU BEGINN: R0 = ADRESSE LETZTES BYTES (LSB)
;
;SHIFTL_0  (SHIFT LEFT N BYTES WITH 0 -> LS-BIT)
;SCHIEBT EINE ANZAHL VON BYTES 1 * LINKS DURCHS CARRY
;VON HINTEN WIRD 0 NACHGESCHOBEN.
;ZU BEGINN: R2 = ANZAHL DER BYTES
;           R0 = ADRESSE LETZTES BYTE (LSB)
;
;SHIFTL (SHIFT LEFT N BYTES WITH CY -> LS-BIT)
;SCHIEBT EINE ANZAHL VON BYTES 1 * LINKS DURCHS CARRY
;DAS CARRY WIRD VON HINTEN NACHGESCHOBEN
;ZU BEGINN: R2 = ANZAHL DER BYTE
;           R0 = ADRESSE LETZTES BYTE (LSB)
;
SHIFTL_0_2:
        MOV     R2,#2
        SJMP    SHIFTL_0
SHIFTL_0_4:
        MOV     R2,#4
SHIFTL_0:
        CLR     C
SHIFTL:
        MOV     A,@R0           ;HOLE BYTE
        RLC     A               ;1*SHIFT LEFT
        MOV     @R0,A           ;SPEICHERE BYTE
        DEC     R0              ;ZEIGER -1
        DJNZ    R2,SHIFTL       ;SCHIEBE ALLE BYTES
        RET
;
;-------------------------------------------------
;
;SHIFTL_2_4 (SHIFT LEFT 2 BYTES 4 TIME LEFT)
;SCHIEBT 2 BYTES 4 * <-
;ZU BEGINN: R0 = ADRESSE LETZTES BYTE (LSB)
;
;SHIFTL_0_N (SHIFT LEFT N BYTES N-TIME WITH 0 -> LS-BIT)
;SCHIETE EINE ANZAHL VON BYTES N*MAL NACH LINKS
;DURCHS CARRY. VON HINTEN WERDEN NULLEN NACHGESCHOBEN.
;ZU BEGINN: R2 = ANZAHL DER BYTES
;           R3 = ANZAHL DER SHIFTS
;           R0 = ADRESSE LETZTES BYTE (LSB)
;
SHIFTL_2_4:
        MOV     R2,#2
        MOV     R3,#4
SHIFTL_0_N:
        MOV     A,R2            ;SICHERE BYTE-ZAEHLER
        PUSH    ACC
        MOV     A,R0
        PUSH    ACC               ;SICHERE ZEIGER
        LCALL   SHIFTL_0        ;1 * SHIFT LEFT
        POP     ACC               ;HOLE ZEIGER ZURUECK
        MOV     R0,A
        POP     ACC
        MOV     R2,A            ;HOLE BYTE-ZAEHLER ZURUECK
        DJNZ    R3,SHIFTL_0_N
        RET
;
;------------------------------------------------
;SHIFTL_4 (SHIFT LEFT 4 BYTES WITH CY -> LS-BIT)
;SCHIEBT 4 BYTES 1 * NACH LINKS INS CARRY.
;VON HINTEN WIRD DAS CARRY NACHGESCHOBEN.
;ZU BEGINN: R0 = ADRESSE LETZTES BYTES (LSB)
;
SHIFTL_4:
        MOV     R2,#4
        SJMP    SHIFTL

;------------------------------------------------------
;SHIFTR_0_2 (SHIFT RIGHT 2 BYTES WITH 0 -> MS-BIT)
;SCHIEBT 2 BYTES 1 * NACH RECHTS INS CARRY.
;VON VORN WIRD 0 NACHGESCHOBEN.
;ZU BEGINN: R0 = ADRESSE ERSTES BYTES (MSB)
;
;SHIFTR_0_4 (SHIFT RIGHT 4 BYTES WITH 0 -> MS-BIT)
;SCHIEBT 4 BYTES 1 * NACH RECHTS INS CARRY.
;VON VORN WIRD 0 NACHGESCHOBEN.
;ZU BEGINN: R0 = ADRESSE ERSTES BYTES (MSB)
;
;SHIFTR_0  (SHIFT RIGHT N BYTES WITH 0 -> MS-BIT)
;SCHIEBT EINE ANZAHL VON BYTES 1 * RECHTS DURCHS CARRY
;VON VORN WIRD 0 NACHGESCHOBEN.
;ZU BEGINN: R2 = ANZAHL DER BYTES
;           R0 = ADRESSE ERSTES BYTE (MSB)
;
;SHIFTR (SHIFT RIGHT N BYTES WITH CY -> MS-BIT)
;SCHIEBT EINE ANZAHL VON BYTES 1 * RECHTS DURCHS CARRY
;DAS CARRY WIRD VON VORN NACHGESCHOBEN
;ZU BEGINN: R2 = ANZAHL DER BYTE
;           R0 = ADRESSE ERSTES BYTE (MSB)
;
SHIFTR_0_2:
        MOV     R2,#2
        SJMP    SHIFTR_0
SHIFTR_0_4:
        MOV     R2,#4
SHIFTR_0:
        CLR     C
SHIFTR:
        MOV     A,@R0           ;HOLE BYTE
        RRC     A               ;1*SHIFT RIGHT
        MOV     @R0,A           ;SPEICHERE BYTE
        INC     R0              ;ZEIGER +1
        DJNZ    R2,SHIFTR       ;SCHIEBE ALLE BYTES
        RET
;
;-------------------------------------------------
;
;SHIFTR_0_N (SHIFT RIGHT N BYTES N-TIME WITH 0 -> MS-BIT)
;SCHIETE EINE ANZAHL VON BYTES N*MAL NACH RECHTS
;DURCHS CARRY. VON VORN WERDEN NULLEN NACHGESCHOBEN.
;ZU BEGINN: R2 = ANZAHL DER BYTES
;           R3 = ANZAHL DER SHIFTS
;           R0 = ADRESSE ERSTES BYTE (MSB)
;
SHIFTR_0_N:
        MOV     A,R2            ;SICHERE BYTE-ZAEHLER
        PUSH    ACC
        MOV     A,R0
        PUSH    ACC               ;SICHERE ZEIGER
        LCALL   SHIFTR_0        ;1 * SHIFT RIGHT
        POP     ACC               ;HOLE ZEIGER ZURUECK
        MOV     R0,A
        POP     ACC
        MOV     R2,A            ;HOLE BYTE-ZAEHLER ZURUECK
        DJNZ    R3,SHIFTR_0_N
        RET
;
;------------------------------------------------
;SHIFTR_4 (SHIFT RIGHT 4 BYTES WITH CY -> MS-BIT)
;SCHIEBT 4 BYTES 1 * NACH RECHTS INS CARRY.
;VON VORN WIRD DAS CARRY NACHGESCHOBEN.
;ZU BEGINN: R0 = ADRESSE ERSTES BYTES (MSB)
;
SHIFTR_4:
        MOV     R2,#4
        SJMP    SHIFTR

;------------------------------------------------
;COMP_2 (COMPLEMENT OF 2 BYTES)
;COMPLEMNETIERE 2 BYTES
;ZU BEGINN: R0 = ADRESSE ERSTES BYTE (MSB)
;
;COMP_4 (COMPLEMENT OF 4 BYTES)
;COMPLEMNETIERE 4 BYTES
;ZU BEGINN: R0 = ADRESSE ERSTES BYTE (MSB)
;
;COMP   (COMPLEMENT N BYTES)
;COMPLEMNETIERE N BYTES
;ZU BEGINN: R0 = ADRESSE ERSTES BYTE (MSB)
;           R2 = ANZAHL DER BYTES (N)
;
COMP_2:
        MOV     R2,#2           ;2BYTES
        SJMP    COMP
COMP_4:
        MOV     R2,#4
COMP:
        MOV     A,@R0           ;HOLE BYTE
        CPL     A               ;COMPLEMENTIERE ES
        MOV     @R0,A           ;BRINGE BYTE ZURUECK
        INC     R0              ;VERSCHIEBE ZEIGER
        DJNZ    R2,COMP         ;BEARBEITE ALLE BYTES
        RET
;
;------------------------------------------------
;COMP2_2 (TWO'S COMPLEMENT OF 2 BYTES)
;ZWEIERCOMPLEMENT VON 2 BYTES
;ZU BEGINN: R0 = ADRESSE ERSTES BYTE (MSB)
;
;COMP2_4 (TWO'S COMPLEMENT OF 4 BYTES)
;ZWEIERCOMPLEMENT VON 4 BYTES
;ZU BEGINN: R0 = ADRESSE ERSTES BYTE (MSB)
;
;COMP2 (TWO'S COMPLEMENT OF N BYTES)
;ZWEIERCOMPLEMENT VON N BYTES
;ZU BEGINN: R0 = ADRESSE ERSTES BYTE (MSB)
;           R2 = ANZAHL DER BYTES
;AM ENDE: : R0 = ADRESSE ERSTES BYTE (MSB)
;
COMP2_2:
        MOV     R2,#2           ;2 BYTES
        SJMP    COMP2
COMP2_4:
        MOV     R2,#4           ;4 BYTES
COMP2:
        MOV     B,R2            ;SICHERE ZAEHLER
        LCALL   COMP            ;COMPLEMENTIERE BYTES
        DEC     R0              ;KORRIGIERE ZEIGER
        MOV     A,#1
        CLR     C               ;CY = 0
COMP21:
        ADDC    A,@R0           ;ADDIERE EINS
        MOV     @R0,A           ; WERT -> WERT
        DEC     R0              ;VERSCHIEBE ZEIGER
        MOV     A,#0
        DJNZ    B,COMP21        ;BERUECKSICHTIGE ALLE BYTES
        INC     R0
        RET



;------------------------------------------------
;ADD_16_P (ADD 16 BIT, POINTER)
;ADDIERT 2 * 2-BYTES DES INTERNEN RAMS
;ZU BEGINN: R0 = ADRESSE 1. OPERAND (MSB)
;           R1 = ADRESSE 2. OPERAND (MSB)
;AM ENDE  : ERGEBNIS -> HR1
;DIE OPERANDEN WERDEN NICHT VERAENDERT
;
ADD_16_P:
        LCALL   CLR_OP_8
        MOV     B,R1
        MOV     R1,#OP1 + 2
        LCALL   MOV_IRAM_2      ;BRINGT 1.OPER. -> OP1
        MOV     R0,B
        MOV     R1,#OP2 +2
        LCALL   MOV_IRAM_2      ;BRINGT 2.OPER. -> OP2
        SJMP    ADD_P
;
;------------------------------------------------
;ADD_32_P (ADD 32 BIT, POINTER)
;ADDIERT 2 * 4-BYTES DES INTERNEN RAMS
;ZU BEGINN: R0 = ADRESSE 1. OPERAND (MSB)
;           R1 = ADRESSE 2. OPERAND (MSB)
;AM ENDE:   CY = 1 WENN UEBERLAUF
;           ERGEBNIS -> HR1
;DIE OPERANDEN WERDEN NICHT VERAENDERT
;
ADD_32_P:
        LCALL   CLR_OP_8
        MOV     B,R1
        MOV     R1,#OP1
        LCALL   MOV_IRAM_4      ;BRINGT 1.OPER. -> OP1
        MOV     R0,B
        MOV     R1,#OP2
        LCALL   MOV_IRAM_4      ;BRINGT 2.OPER. -> OP2
ADD_P:
        LCALL   ADD_32
        SJMP    MOV_R           ;ERGEBNIS -> HR1
;
;------------------------------------------------
;ADD_32 (ADD 32 BIT)
;ADDIERT 2 * 4-BYTES DES INTERNEN RAMS
;ZU BEGINN: 1.OPERAND STEHT AB OP1_0
;           2.OPERAND STEHT AB OP2_0
;AM ENDE  : (OP1 + OP2) -> OP1
;           CY = 1 WENN UEBERLAUF
;
;BINADD (BINAERE ADDITION)
;ADDIERT 2 * N-BYTES DES INTERNEN RAMS
;ZU BEGINN: R0 = ADRESSE 1.OPERAND (LSB)
;           R1 = ADRESSE 2.OPERAND (LSB)
;           R2 = ANZAHL DER BYTES (N)
;AM ENDE  : (1.OPERAND + 2.OPERAND) -> 1.OPERAND
;           CY = 1 WENN UEBERLAUF
;
ADD_32:
        MOV     R0,#OP1 +3
        MOV     R1,#OP2 +3
        MOV     R2,#4   ;4 BYTES
BINADD:
        CLR     C       ;CY = 0
ADD1:
        MOV     A,@R0
        ADDC    A,@R1
        MOV     @R0,A
        DEC     R0      ;VERSCHIEBE ADRESSZEIGER
        DEC     R1      ;    "           "
        DJNZ    R2,ADD1 ;BEARBEITE ALLE BYTES
        RET
;
;------------------------------------------------
;SUB_16_P (SUB 16 BIT, POINTER)
;SUBTRAHIERT 2 * 2-BYTES DES INTERNEN RAMS
;ZU BEGINN: R0 = ADRESSE 1. OPERAND (MSB)
;           R1 = ADRESSE 2. OPERAND (MSB)
;AM ENDE:   CY = 1 WENN NEGATIV
;           ERGEBNIS -> HR1
;DIE OPERANDEN WERDEN NICHT VERAENDERT
;
SUB_16_P:
        LCALL   CLR_OP_8
        MOV     B,R1
        MOV     R1,#OP1 + 2
        LCALL   MOV_IRAM_2      ;BRINGT 1.OPER. -> OP1
        MOV     R0,B
        MOV     R1,#OP2 +2
        LCALL   MOV_IRAM_2      ;BRINGT 2.OPER. -> OP2
        SJMP    SUB_P
;
;------------------------------------------------
;SUB_32_P (SUB 32 BIT, POINTER)
;SUBTRAHIERT 2 * 4-BYTES DES INTERNEN RAMS
;ZU BEGINN: R0 = ADRESSE 1. OPERAND (MSB)
;           R1 = ADRESSE 2. OPERAND (MSB)
;AM ENDE:   CY = 1 WENN NEGATIV
;           ERGEBNIS -> HR1
;DIE OPERANDEN WERDEN NICHT VERAENDERT
;
SUB_32_P:
        LCALL   CLR_OP_8
        MOV     B,R1
        MOV     R1,#OP1
        LCALL   MOV_IRAM_4      ;BRINGT 1.OPER. -> OP1
        MOV     R0,B
        MOV     R1,#OP2
        LCALL   MOV_IRAM_4      ;BRINGT 2.OPER. -> OP2
SUB_P:
        LCALL   SUB_32
MOV_R:
        MOV     R1,#HR1
MOV_R1:
        MOV     R0,#OP1
        LJMP    MOV_IRAM_4      ;BRINGT ERGEBNIS -> ERGEBNIS
;
;------------------------------------------------
;SUB_32 (SUB 32 BIT)
;SUBTRAHIERT 2 * 4-BYTES DES INTERNEN RAMS
;ZU BEGINN: 1.OPERAND STEHT AB OP1_0
;           2.OPERAND STEHT AB OP2_0
;AM ENDE  : (OP1 - OP2) -> OP1
;           CY = 1 WENN UEBERLAUF
;
;BINSUB
;SUBTRAHIERT 2 * N-BYTES DES INTERNEN RAMS
;ZU BEGINN: R0 = ADRESSE 1.OPERAND (LSB)
;           R1 = ADRESSE 2.OPERAND (LSB)
;           R2 = ANZAHL DER BYTES (N)
;AM ENDE  : (1.OPERAND + 2.OPERAND) -> 1.OPERAND
;           CY = 1 WENN UEBERLAUF
;
SUB_32:
        MOV     R0,#OP1 +3      ;ADRESSE OPERAND 1 (LSB)
        MOV     R1,#OP2 +3      ;ADRESSE OPERAND 2 (LSB)
        MOV     R2,#4           ;4 BYTES
BINSUB:
        CLR     C               ;CY = 0
SUB1:
        MOV     A,@R0
        SUBB    A,@R1
        MOV     @R0,A
        DEC     R0              ;VERSCHIEBE ADRESSZEIGER
        DEC     R1              ;    "           "
        DJNZ    R2,SUB1         ;BEARBEITE ALLE BYTES
        RET
;------------------------------------------------
;MUL_16_PK (MUL 16 BIT, POINTER)
;MULTIPLIZIERT 2-BYTES DES INTERNEN RAMS MIT
;2 BYTES EINER KONSTANTEN (CODE)
;ZU BEGINN: R0   = ADRESSE MULTIPLIKANT RAM (MSB)
;           DPTR = ADRESSE MULTIPLIKATOR CODE (MSB)
;AM ENDE:   ERGENIS -> HR2
;DIE OPERANDEN WERDEN NICHT VERAENDERT
;
MUL_16_PK:
        LCALL   CLR_OP_12       ;LOESCHT 12 BYTES AB OP1
        MOV     R1,#MULKANT
        LCALL   MOV_IRAM_2      ;BRINGT MULTIPLIKANT ->MULKANT
        MOV     R1,#MULKATOR
        LCALL   MOV_CODE_2      ;BRINGT MULTIPLIKATOR -> MULKATOR
        LCALL   MUL_16
        MOV     R1,#HR2
        SJMP    MOV_R1
;
;------------------------------------------------
;MUL_16_P (MUL 16 BIT, POINTER)
;MULTIPLIZIERT 2 * 2-BYTES DES INTERNEN RAMS
;ZU BEGINN: R0 = ADRESSE MULTIPLIKANT (MSB)
;           R1 = ADRESSE MULTIPLIKATOR (MSB)
;AM ENDE:   ERGENIS -> HR2
;DIE OPERANDEN WERDEN NICHT VERAENDERT
;
MUL_16_P:
        LCALL   CLR_OP_12       ;LOESCHT 12 BYTES AB OP1
        MOV     B,R1
        MOV     R1,#MULKANT
        LCALL   MOV_IRAM_2      ;BRINGT MULTIPLIKANT ->MULKANT
        MOV     R0,B
        MOV     R1,#MULKATOR
        LCALL   MOV_IRAM_2      ;BRINGT MULTIPLIKATOR -> MULKATOR
        LCALL   MUL_16
        MOV     R1,#HR2
        SJMP    MOV_R1
;
;------------------------------------------------
;MUL_16
;16 * 16 BIT MULTIPLIKATION
;MULTIPLIZERT DIE ZWEI BYTES VON MULKANT MIT DEN
;ZWEI BYTES VON MULKATOR
;PRODUKT -> OP1 (4 BYTES)
;
MUL_16:
        MOV     R2,#6           ;OP1 UND
        MOV     R0,#OP1         ;OP2+0, OP2+1 = 0
        LCALL   CLR_IRAM        ;
        MOV     R4,#16          ;16 BIT
MUL1:
        MOV     R0,#OP1 +3
        LCALL   SHIFTL_0_4      ;ERGEBNIS 1 * <-
        MOV     R0,#MULKATOR +3
        LCALL   SHIFTL_0_4      ;MULKATOR 1 * <-
        JNC     MUL2            ;WENN BIT = 0 -> MUL2
        LCALL   ADD_32          ;SONST ADDIERE 1 * MULKANT
MUL2:
        DJNZ    R4,MUL1         ;BEARBEITE ALLE BITS
        RET


;------------------------------------------------
;DIV_32_P (DIVISION 32 BIT, POINTER)
;DIVIDIERT 2 * 4-BYTES DES INTERNEN RAMS
;ZU BEGINN: R0 = ADRESSE DIVIDEND (MSB)
;           R1 = ADRESSE DIVISOR (MSB)
;AM ENDE:   ERGEBNIS -> QUOTIENT
;DIE OPERANDEN WERDEN NICHT VERAENDERT
;
DIV_32_P:
        LCALL   CLR_MATHE       ;LOESCHT MATHE-BEREICH
        MOV     B,R1
        MOV     R1,#DIVIDEND    ;BRINGT DIVIDEND
        LCALL   MOV_IRAM_4
        MOV     R0,B            ; UND
        MOV     R1,#DIVISOR     ;  DIVISOR
        LCALL   MOV_IRAM_4      ;   -> MATHE
;
;------------------------------------------------
;DIV_32 (32-BIT DIVISION)
;DIVIDIERT 32-BIT DURCH 32-BIT
;DER DIVIDEND MUSS BEI DIVIDEND UND DER DIVISOR
;BEI DIVISOR IM MATHE-BEREICH STEHEN.
;DAS ERGEBNIS STEHT BEI QUOTIENT IM MATHE-BEREICH.
;
;DIVIDEND : DIVISOR -> QUOTIENT
;CY = 1 WENN DIVISOR = 0
;
DIV_32:
        MOV     R0,#OP1
        LCALL   CLR_IRAM_4      ;LOESCHE 1. OPERANDENREG.
        MOV     R0,#QUOTIENT
        MOV     R2,#8           ;LOESCHE ERGEBNISREG. UND
        LCALL   CLR_IRAM        ;HR1
        MOV     R4,#32          ;BITZAEHLER INITI.
        MOV     R0,#DIVISOR
        LCALL   CHECK_0_4       ;DIVISOR = 0 ??
        JNB     F0,DIV1         ;WENN NEIN, FAHRE FORT
        RET                     ;F0 = 1, DIVISION / 0
DIV1:
        MOV     R0,#DIVIDEND +3 ;MS-BIT DES DIVIDENDEN
        LCALL   SHIFTL_0_4      ; VON HINTEN
        MOV     R0,#ABR +3      ;  INS ARBEITSREG.1
        LCALL   SHIFTL_4        ;   SCHIEBEN.
        MOV     R0,#ABR
        MOV     R1,#OP1
        LCALL   MOV_IRAM_4      ;ARBEITSREG.1 -> OP1
        LCALL   SUB_32          ;ABR - DIVISOR
        JC      DIV2            ;WENN -  -> DIV2
        MOV     R0,#OP1
        MOV     R1,#ABR         ;WENN + , DANN
        LCALL   MOV_IRAM_4      ; ERGEBNIS -> ABR
DIV2:
        CPL     C
        MOV     R0,#QUOTIENT +3
        LCALL   SHIFTL_4        ;CY VON HINTEN -> QUOTIENT
        DJNZ    R4,DIV1         ;ALLE BITS BEARBEITEN
        CLR     C               ;ALLE O.K. CY = 0
        RET
;

        END

