TITLE BBC BASIC (C) R.T.RUSSELL 1981-2024 NAME ('ASMB') ; ;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