	TITLE	BBC BASIC (C) R.T.RUSSELL 1981-2024
;
;BBC BASIC INTERPRETER - Z80 VERSION
;Z80 CPU ASSEMBLER MODULE - "ASMB"
;(C) COPYRIGHT R.T.RUSSELL 1981-2024
;
;THE NAME BBC BASIC IS USED WITH THE PERMISSION
;OF THE BRITISH BROADCASTING CORPORATION AND IS
;NOT TRANSFERRABLE TO A FORKED OR DERIVED WORK.
;
;VERSION 5.0, 14-05-2024
;
	GLOBAL	ASSEM
;
	EXTRN	TABIT
	EXTRN	CRLF
	EXTRN	OUT
	EXTRN	VAR
	EXTRN	ZERO
	EXTRN	STOREN
	EXTRN	ERROR
	EXTRN	EXPRI
	EXTRN	EXPRS
;
	EXTRN	LISTON
	EXTRN	COUNT
	EXTRN	ACCS
	EXTRN	OC
	EXTRN	PC
;
CR	EQU	0DH
TAND	EQU	80H
TOR	EQU	84H
TERROR	EQU	85H
TCALL	EQU	0D6H
TDEF	EQU	0DDH
;
;ASSEMBLER:
;LANGUAGE-INDEPENDENT CONTROL SECTION:
; Outputs: A=delimiter, carry set if syntax error.
;
ASSEM:	CALL	SKIP
	INC	IY
	CP	':'
	JR	Z,ASSEM
	CP	']'
	RET	Z
	CP	CR
	RET	Z
	DEC	IY
	LD	IX,(PC)		;PROGRAM COUNTER
	LD	HL,LISTON
	BIT	6,(HL)
	JR	Z,ASSEM0
	LD	IX,(OC)		;ORIGIN of CODE
ASSEM0:	PUSH	IX
	PUSH	IY
	CALL	ASMB
	POP	BC
	POP	DE
	RET	C
	CALL	SKIP
	SCF
	RET	NZ
	DEC	IY
ASSEM3:	INC	IY
	LD	A,(IY)
	CALL	TERM0
	JR	NZ,ASSEM3
	LD	A,(LISTON)
	PUSH	IX
	POP	HL
	OR	A
	SBC	HL,DE
	EX	DE,HL		;DE= NO. OF BYTES
	PUSH	HL
	LD	HL,(PC)
	PUSH	HL
	ADD	HL,DE
	LD	(PC),HL		;UPDATE PC
	BIT	6,A
	JR	Z,ASSEM5
	LD	HL,(OC)
	ADD	HL,DE
	LD	(OC),HL		;UPDATE OC
ASSEM5:	POP	HL		;OLD PC
	POP	IX		;CODE HERE
	BIT	4,A
	JR	Z,ASSEM
	LD	A,H
	CALL	HEX
	LD	A,L
	CALL	HEXSP
	XOR	A
	CP	E
	JR	Z,ASSEM2
ASSEM1:	LD	A,(COUNT)
	CP	17
	LD	A,5
	CALL	NC,TABIT	;NEXT LINE
	LD	A,(IX)
	CALL	HEXSP
	INC	IX
	DEC	E
	JR	NZ,ASSEM1
ASSEM2:	LD	A,18
	CALL	TABIT
	PUSH	IY
	POP	HL
	SBC	HL,BC
ASSEM4:	LD	A,(BC)
	CALL	OUT
	INC	BC
	DEC	L
	JR	NZ,ASSEM4
	CALL	CRLF
	JP	ASSEM
;
HEXSP:	CALL	HEX
	LD	A,' '
	JR	OUTCH1
HEX:	PUSH	AF
	RRCA
	RRCA
	RRCA
	RRCA
	CALL	HEXOUT
	POP	AF
HEXOUT:	AND	0FH
	ADD	A,90H
	DAA
	ADC	A,40H
	DAA
OUTCH1:	JP	OUT
;
;PROCESSOR-SPECIFIC TRANSLATION SECTION:
;
;REGISTER USAGE: B - TYPE OF MOST RECENT OPERAND
;                C - OPCODE BEING BUILT
;                D - (IX) OR (IY) FLAG
;                E - OFFSET FROM IX OR IY
;               HL - NUMERIC OPERAND VALUE
;               IX - CODE DESTINATION
;               IY - SOURCE TEXT POINTER
;   Inputs: A = initial character
;  Outputs: Carry set if syntax error.
;
ASMB:	CP	'.'
	JR	NZ,ASMB1
	INC	IY
	PUSH	IX
	CALL	VAR
	PUSH	AF
	CALL	ZERO
	EXX
	LD	HL,(PC)
	EXX
	LD	A,(LISTON)
	AND	20H
	JR	NZ,ASMB0
	LD	A,(IX)
	OR	(IX+1)
	LD	A,3
	JP	NZ,ERROR	;Multiple label
ASMB0:	POP	AF
	CALL	STOREN
	POP	IX
ASMB1:	CALL	SKIP
	RET	Z
	CP	TCALL
	LD	C,0C4H
	INC	IY
	JP	Z,GRPC
	DEC	IY
	LD	HL,OPCODS
	CALL	FIND
	RET	C
	LD	C,B	;ROOT OPCODE
	LD	D,0	;CLEAR IX/IY FLAG
;
;GROUP 0 - TRIVIAL CASES REQUIRING NO COMPUTATION
;GROUP 1 - AS GROUP 0 BUT WITH "ED" PREFIX
;
	SUB	39
	JR	NC,GROUP2
	CP	15-39
	CALL	NC,ED
	JR	BYTE0
;
;GROUP 2 - BIT, RES, SET
;GROUP 3 - RLC, RRC, RL, RR, SLA, SRA, SRL
;
GROUP2:	SUB	10
	JR	NC,GROUP4
	CP	3-10
	CALL	C,BIT
	RET	C
	CALL	REGLO
	RET	C
	CALL	CB
	JR	BYTE0
;
;GROUP 4 - PUSH, POP, EX (SP)
;
GROUP4:	SUB	3
	JR	NC,GROUP5
G4:	CALL	PAIR
	RET	C
	JR	BYTE0
;
;GROUP 5 - SUB, AND, XOR, OR, CP
;GROUP 6 - ADD, ADC, SBC
;
GROUP5:	SUB	8+2
	JR	NC,GROUP7
	CP	5-8
	LD	B,7
	CALL	NC,OPND
	LD	A,B
	CP	7
	JR	NZ,G6HL
G6:	CALL	REGLO
	LD	A,C
	JR	NC,BIND1
	XOR	46H
	CALL	BIND
DB:	CALL	NUMBER
	JR	VAL8
;
G6HL:	AND	3FH
	CP	12
	SCF
	RET	NZ
	LD	A,C
	CP	80H
	LD	C,9
	JR	Z,G4
	XOR	1CH
	RRCA
	LD	C,A
	CALL	ED
	JR	G4
;
;GROUP 7 - INC, DEC
;
GROUP7:	SUB	2
	JR	NC,GROUP8
	CALL	REGHI
	LD	A,C
BIND1:	JP	NC,BIND
	XOR	64H
	RLCA
	RLCA
	RLCA
	LD	C,A
	CALL	PAIR1
	RET	C
BYTE0:	LD	A,C
	JR	BYTE2
;
;GROUP 8 - IN
;GROUP 9 - OUT
;
GROUP8:	SUB	2
	JR	NC,GROUPA
	CP	1-2
	CALL	Z,CORN
	EX	AF,AF'
	CALL	REGHI
	RET	C
	EX	AF,AF'
	CALL	C,CORN
	INC	H
	JR	Z,BYTE0
	LD	A,B
	CP	7
	SCF
	RET	NZ
	LD	A,C
	XOR	3
	RLCA
	RLCA
	RLCA
	CALL	BYTE
	JR	VAL8
;
;GROUP 10 - JR, DJNZ
;
GROUPA:	SUB	2
	JR	NC,GROUPB
	CP	1-2
	CALL	NZ,COND
	LD	A,C
	JR	NC,GRPA
	LD	A,18H
GRPA:	CALL	BYTE
	CALL	NUMBER
	LD	DE,(PC)
	INC	DE
	SCF
	SBC	HL,DE
	LD	A,L
	RLA
	SBC	A,A
	CP	H
TOOFAR:	LD	A,1
	JP	NZ,ERROR	;"Out of range"
VAL8:	LD	A,L
	JR	BYTE2
;
;GROUP 11 - JP
;
GROUPB:	LD	B,A
	JR	NZ,GROUPC
	CALL	COND
	LD	A,C
	JR	NC,GRPB
	LD	A,B
	AND	3FH
	CP	6
	LD	A,0E9H
	JR	Z,BYTE2
	LD	A,0C3H
GRPB:	CALL	BYTE
	JR	ADDR
;
;GROUP 12 - CALL
;
GROUPC:	DJNZ	GROUPD
GRPC:	CALL	GRPE
ADDR:	CALL	NUMBER
VAL16:	CALL	VAL8
	LD	A,H
	JR	BYTE2
;
;GROUP 13 - RST
;
GROUPD:	DJNZ	GROUPE
	CALL	NUMBER
	AND	C
	OR	H
	JR	NZ,TOOFAR
	LD	A,L
	OR	C
BYTE2:	JR	BYTE1
;
;GROUP 14 - RET
;
GROUPE:	DJNZ	GROUPF
GRPE:	CALL	COND
	LD	A,C
	JR	NC,BYTE1
	OR	9
	JR	BYTE1
;
;GROUP 15 - LD
;
GROUPF:	DJNZ	MISC
	CALL	LDOP
	JR	NC,LDA
	CALL	REGHI
	EX	AF,AF'
	CALL	SKIP
	CP	'('
	JR	Z,LDIN
	EX	AF,AF'
	JP	NC,G6
	LD	C,1
	CALL	PAIR1
	RET	C
	LD	A,14
	CP	B
	LD	B,A
	CALL	Z,PAIR
	LD	A,B
	AND	3FH
	CP	12
	LD	A,C
	JR	NZ,GRPB
	LD	A,0F9H
	JR	BYTE1
;
LDIN:	EX	AF,AF'
	PUSH	BC
	CALL	NC,REGLO
	LD	A,C
	POP	BC
	JR	NC,BIND
	LD	C,0AH
	CALL	PAIR1
	CALL	LD16
	JR	NC,GRPB
	CALL	NUMBER
	LD	C,2
	CALL	PAIR
	CALL	LD16
	RET	C
	CALL	BYTE
	JR	VAL16
;
;OPT - SET OPTION
;
OPT:	DEC	B
	JP	Z,DB
	DJNZ	ADDR
	CALL	NUMBER
	LD	HL,LISTON
	LD	C,A
	RLD
	LD	A,C
	RRD
	RET
;
LDA:	CP	4
	CALL	C,ED
	LD	A,B
BYTE1:	JR	BYTE
;
;MISC - DEFB, DEFW, DEFM
;
MISC:	DJNZ	OPT
	PUSH	IX
	CALL	EXPRS
	POP	IX
	LD	HL,ACCS
DEFM1:	XOR	A
	CP	E
	RET	Z
	LD	A,(HL)
	INC	HL
	CALL	BYTE
	DEC	E
	JR	DEFM1
;
;SUBROUTINES:
;
LD16:	LD	A,B
	JR	C,LD8
	LD	A,B
	AND	3FH
	CP	12
	LD	A,C
	RET	Z
	CALL	ED
	LD	A,C
	OR	43H
	RET
;
LD8:	CP	7
	SCF
	RET	NZ
	LD	A,C
	OR	30H
	RET
;
CORN:	PUSH	BC
	CALL	OPND
	BIT	5,B
	POP	BC
	JR	Z,NUMBER
	LD	H,-1
ED:	LD	A,0EDH
	JR	BYTE
;
CB:	LD	A,0CBH
BIND:	CP	76H
	SCF
	RET	Z		;REJECT LD (HL),(HL)
	CALL	BYTE
	INC	D
	RET	P
	LD	A,E
	JR	BYTE
;
OPND:	PUSH	HL
	LD	HL,OPRNDS
	CALL	FIND
	POP	HL
	RET	C
	BIT	7,B
	RET	Z
	BIT	3,B
	PUSH	HL
	CALL	Z,OFFSET
	LD	E,L
	POP	HL
	LD	A,0DDH
	BIT	6,B
	JR	Z,OP1
	LD	A,0FDH
OP1:	OR	A
	INC	D
	LD	D,A
	RET	M
BYTE:	LD	(IX),A
	INC	IX
	OR	A
	RET
;
OFFSET:	LD	A,(IY)
	CP	')'
	LD	HL,0
	RET	Z
NUMBER:	CALL	SKIP
	PUSH	BC
	PUSH	DE
	PUSH	IX
	CALL	EXPRI
	POP	IX
	EXX
	POP	DE
	POP	BC
	LD	A,L
	OR	A
	RET
;
REG:	CALL	OPND
	RET	C
	LD	A,B
	AND	3FH
	CP	8
	CCF
	RET
;
REGLO:	CALL	REG
	RET	C
	JR	ORC
;
REGHI:	CALL	REG
	RET	C
	JR	SHL3
;
COND:	CALL	OPND
	RET	C
	LD	A,B
	AND	1FH
	SUB	16
	JR	NC,SHL3
	CP	-15
	SCF
	RET	NZ
	LD	A,3
	JR	SHL3
;
PAIR:	CALL	OPND
	RET	C
PAIR1:	LD	A,B
	AND	0FH
	SUB	8
	RET	C
	JR	SHL3
;
BIT:	CALL	NUMBER
	CP	8
	CCF
	RET	C
SHL3:	RLCA
	RLCA
	RLCA
ORC:	OR	C
	LD	C,A
	RET
;
LDOP:	LD	HL,LDOPS
FIND:	CALL	SKIP
EXIT:	LD	B,0
	SCF
	RET	Z
	CP	TDEF
	JR	Z,FIND0
	CP	TOR+1
	CCF
	RET	C
FIND0:	LD	A,(HL)
	OR	A
	JR	Z,EXIT
	XOR	(IY)
	AND	01011111B
	JR	Z,FIND2
FIND1:	BIT	7,(HL)
	INC	HL
	JR	Z,FIND1
	INC	HL
	INC	B
	JR	FIND0
;
FIND2:	PUSH	IY
FIND3:	BIT	7,(HL)
	INC	IY
	INC	HL
	JR	NZ,FIND5
	CP	(HL)
	CALL	Z,SKIP0
	LD	A,(HL)
	XOR	(IY)
	AND	01011111B
	JR	Z,FIND3
FIND4:	POP	IY
	JR	FIND1
;
FIND5:	CALL	DELIM
	CALL	NZ,SIGN
	JR	NZ,FIND4
FIND6:	LD	A,B
	LD	B,(HL)
	POP	HL
	RET
;
SKIP0:	INC	HL
SKIP:	CALL	DELIM
	RET	NZ
	CALL	TERM
	RET	Z
	INC	IY
	JR	SKIP
;
SIGN:	CP	'+'
	RET	Z
	CP	'-'
	RET
;
DELIM:	LD	A,(IY)		;ASSEMBLER DELIMITER
	CP	' '
	RET	Z
	CP	','
	RET	Z
	CP	')'
	RET	Z
TERM:	CP	';'		;ASSEMBLER TERMINATOR
	RET	Z
	CP	'\'
	RET	Z
TERM0:	CP	':'		;ASSEMBLER SEPARATOR
	RET	NC
	CP	CR
	RET
;
OPCODS:	DEFM	'NO'
	DEFB	'P'+80H
	DEFB	0
	DEFM	'RLC'
	DEFB	'A'+80H
	DEFB	7
	DEFM	'EX'
	DEFB	0
	DEFM	'AF'
	DEFB	0
	DEFM	'AF'
	DEFB	''''+80H
	DEFB	8
	DEFM	'RRC'
	DEFB	'A'+80H
	DEFB	0FH
	DEFM	'RL'
	DEFB	'A'+80H
	DEFB	17H
	DEFM	'RR'
	DEFB	'A'+80H
	DEFB	1FH
	DEFM	'DA'
	DEFB	'A'+80H
	DEFB	27H
	DEFM	'CP'
	DEFB	'L'+80H
	DEFB	2FH
	DEFM	'SC'
	DEFB	'F'+80H
	DEFB	37H
	DEFM	'CC'
	DEFB	'F'+80H
	DEFB	3FH
	DEFM	'HAL'
	DEFB	'T'+80H
	DEFB	76H
	DEFM	'EX'
	DEFB	'X'+80H
	DEFB	0D9H
	DEFM	'EX'
	DEFB	0
	DEFM	'DE'
	DEFB	0
	DEFM	'H'
	DEFB	'L'+80H
	DEFB	0EBH
	DEFM	'D'
	DEFB	'I'+80H
	DEFB	0F3H
	DEFM	'E'
	DEFB	'I'+80H
	DEFB	0FBH
;
	DEFM	'NE'
	DEFB	'G'+80H
	DEFB	44H
	DEFM	'IM'
	DEFB	0
	DEFB	'0'+80H
	DEFB	46H
	DEFM	'RET'
	DEFB	'N'+80H
	DEFB	45H
	DEFM	'RET'
	DEFB	'I'+80H
	DEFB	4DH
	DEFM	'IM'
	DEFB	0
	DEFB	'1'+80H
	DEFB	56H
	DEFM	'IM'
	DEFB	0
	DEFB	'2'+80H
	DEFB	5EH
	DEFM	'RR'
	DEFB	'D'+80H
	DEFB	67H
	DEFM	'RL'
	DEFB	'D'+80H
	DEFB	6FH
	DEFM	'LD'
	DEFB	'I'+80H
	DEFB	0A0H
	DEFM	'CP'
	DEFB	'I'+80H
	DEFB	0A1H
	DEFM	'IN'
	DEFB	'I'+80H
	DEFB	0A2H
	DEFM	'OUT'
	DEFB	'I'+80H
	DEFB	0A3H
	DEFM	'LD'
	DEFB	'D'+80H
	DEFB	0A8H
	DEFM	'CP'
	DEFB	'D'+80H
	DEFB	0A9H
	DEFM	'IN'
	DEFB	'D'+80H
	DEFB	0AAH
	DEFM	'OUT'
	DEFB	'D'+80H
	DEFB	0ABH
	DEFM	'LDI'
	DEFB	'R'+80H
	DEFB	0B0H
	DEFM	'CPI'
	DEFB	'R'+80H
	DEFB	0B1H
	DEFM	'INI'
	DEFB	'R'+80H
	DEFB	0B2H
	DEFM	'OTI'
	DEFB	'R'+80H
	DEFB	0B3H
	DEFM	'LDD'
	DEFB	'R'+80H
	DEFB	0B8H
	DEFM	'CPD'
	DEFB	'R'+80H
	DEFB	0B9H
	DEFM	'IND'
	DEFB	'R'+80H
	DEFB	0BAH
	DEFM	'OTD'
	DEFB	'R'+80H
	DEFB	0BBH
;
	DEFM	'BI'
	DEFB	'T'+80H
	DEFB	40H
	DEFM	'RE'
	DEFB	'S'+80H
	DEFB	80H
	DEFM	'SE'
	DEFB	'T'+80H
	DEFB	0C0H
;
	DEFM	'RL'
	DEFB	'C'+80H
	DEFB	0
	DEFM	'RR'
	DEFB	'C'+80H
	DEFB	8
	DEFM	'R'
	DEFB	'L'+80H
	DEFB	10H
	DEFM	'R'
	DEFB	'R'+80H
	DEFB	18H
	DEFM	'SL'
	DEFB	'A'+80H
	DEFB	20H
	DEFM	'SR'
	DEFB	'A'+80H
	DEFB	28H
	DEFM	'SR'
	DEFB	'L'+80H
	DEFB	38H
;
	DEFM	'PO'
	DEFB	'P'+80H
	DEFB	0C1H
	DEFM	'PUS'
	DEFB	'H'+80H
	DEFB	0C5H
	DEFM	'EX'
	DEFB	0
	DEFM	'(S'
	DEFB	'P'+80H
	DEFB	0E3H
;
	DEFM	'SU'
	DEFB	'B'+80H
	DEFB	90H
	DEFM	'AN'
	DEFB	'D'+80H
	DEFB	0A0H
	DEFM	'XO'
	DEFB	'R'+80H
	DEFB	0A8H
	DEFM	'O'
	DEFB	'R'+80H
	DEFB	0B0H
	DEFM	'C'
	DEFB	'P'+80H
	DEFB	0B8H
	DEFB	TAND
	DEFB	0A0H
	DEFB	TOR
	DEFB	0B0H
;
	DEFM	'AD'
	DEFB	'D'+80H
	DEFB	80H
	DEFM	'AD'
	DEFB	'C'+80H
	DEFB	88H
	DEFM	'SB'
	DEFB	'C'+80H
	DEFB	98H
;
	DEFM	'IN'
	DEFB	'C'+80H
	DEFB	4
	DEFM	'DE'
	DEFB	'C'+80H
	DEFB	5
;
	DEFM	'I'
	DEFB	'N'+80H
	DEFB	40H
	DEFM	'OU'
	DEFB	'T'+80H
	DEFB	41H
;
	DEFM	'J'
	DEFB	'R'+80H
	DEFB	20H
	DEFM	'DJN'
	DEFB	'Z'+80H
	DEFB	10H
;
	DEFM	'J'
	DEFB	'P'+80H
	DEFB	0C2H
;
	DEFM	'CAL'
	DEFB	'L'+80H
	DEFB	0C4H
;
	DEFM	'RS'
	DEFB	'T'+80H
	DEFB	0C7H
;
	DEFM	'RE'
	DEFB	'T'+80H
	DEFB	0C0H
;
	DEFM	'L'
	DEFB	'D'+80H
	DEFB	40H
;
	DEFB	TDEF AND 7FH
	DEFB	'M'+80H
	DEFB	0
;
	DEFB	TDEF AND 7FH
	DEFB	'B'+80H
	DEFB	0
;
	DEFM	'OP'
	DEFB	'T'+80H
	DEFB	0
;
	DEFB	TDEF AND 7FH
	DEFB	'W'+80H
	DEFB	0
;
	DEFB	0
;
OPRNDS:	DEFB	'B'+80H
	DEFB	0
	DEFB	'C'+80H
	DEFB	1
	DEFB	'D'+80H
	DEFB	2
	DEFB	'E'+80H
	DEFB	3
	DEFB	'H'+80H
	DEFB	4
	DEFB	'L'+80H
	DEFB	5
	DEFM	'(H'
	DEFB	'L'+80H
	DEFB	6
	DEFB	'A'+80H
	DEFB	7
	DEFM	'(I'
	DEFB	'X'+80H
	DEFB	86H
	DEFM	'(I'
	DEFB	'Y'+80H
	DEFB	0C6H
;
	DEFM	'B'
	DEFB	'C'+80H
	DEFB	8
	DEFM	'D'
	DEFB	'E'+80H
	DEFB	10
	DEFM	'H'
	DEFB	'L'+80H
	DEFB	12
	DEFM	'I'
	DEFB	'X'+80H
	DEFB	8CH
	DEFM	'I'
	DEFB	'Y'+80H
	DEFB	0CCH
	DEFM	'A'
	DEFB	'F'+80H
	DEFB	14
	DEFM	'S'
	DEFB	'P'+80H
	DEFB	14
;
	DEFM	'N'
	DEFB	'Z'+80H
	DEFB	16
	DEFB	'Z'+80H
	DEFB	17
	DEFM	'N'
	DEFB	'C'+80H
	DEFB	18
	DEFM	'P'
	DEFB	'O'+80H
	DEFB	20
	DEFM	'P'
	DEFB	'E'+80H
	DEFB	21
	DEFB	'P'+80H
	DEFB	22
	DEFB	'M'+80H
	DEFB	23
;
	DEFM	'('
	DEFB	'C'+80H
	DEFB	20H
;
	DEFB	0
;
LDOPS:	DEFM	'I'
	DEFB	0
	DEFB	'A'+80H
	DEFB	47H
	DEFM	'R'
	DEFB	0
	DEFB	'A'+80H
	DEFB	4FH
	DEFM	'A'
	DEFB	0
	DEFB	'I'+80H
	DEFB	57H
	DEFM	'A'
	DEFB	0
	DEFB	'R'+80H
	DEFB	5FH
	DEFM	'(BC'
	DEFB	0
	DEFB	'A'+80H
	DEFB	2
	DEFM	'(DE'
	DEFB	0
	DEFB	'A'+80H
	DEFB	12H
	DEFM	'A'
	DEFB	0
	DEFM	'(B'
	DEFB	'C'+80H
	DEFB	0AH
	DEFM	'A'
	DEFB	0
	DEFM	'(D'
	DEFB	'E'+80H
	DEFB	1AH
;
	DEFB	0
;
FIN:	END
