*** empty log message ***

This commit is contained in:
keie 1984-12-17 11:03:13 +00:00
parent 66d68121c8
commit b097fe72a7
93 changed files with 2954 additions and 0 deletions

31
mach/6500/libem/aar.s Normal file
View file

@ -0,0 +1,31 @@
.define Aar
! This subroutine gets the address of the array element
Aar:
stx ADDR ! address of descriptor (lowbyte)
sta ADDR+1 ! address of descriptor (highbyte)
ldy #0
lda (ADDR),y ! lowerbound (lowbyte)
tax
iny
lda (ADDR),y ! lowerbound (highbyte)
jsr Sbi2 ! index - lowerbound
jsr Push
2: ldy #4
lda (ADDR),y ! objectsize (lowbyte)
sta NBYTES
tax
iny
lda (ADDR),y ! objectsize (highbyte)
sta NBYTES+1
bne 5f
cpx #1 ! objectsize = 1 then return
bne 5f ! arrayaddress + index
jsr Pop
jmp Adi2
5: jsr Mli2 ! objectsize > 1 then return
jmp Adi2 ! arrayaddress + index * objectsize

27
mach/6500/libem/addsub.s Normal file
View file

@ -0,0 +1,27 @@
.define Addsub
! This subroutine is used by the fourbyte addition and subtraction
! routines.
! It puts the address of the second operand into
! the zeropage locations ADDR and ADDR+1
! The address of the first operand is put into
! zeropage locations ADDR+2 and ADDR+3.
Addsub:
clc
lda SP+2
sta ADDR ! address of second operand (lowbyte)
adc #4
sta SP+2
sta ADDR+2 ! address of first operand (lowbyte)
lda SP+1
sta ADDR+1 ! address of second operand (highbyte)
adc #0
sta ADDR+3 ! address of first operand (highbyte)
sta SP+1
ldy #0
ldx #0FCh ! do it 4 times
rts

22
mach/6500/libem/adi.s Normal file
View file

@ -0,0 +1,22 @@
.define Adi2
! This subroutine adds two twobyte integers.
! The first operand is on the top of the stack, the second operand
! is in the AX registerpair.
! The result is returned in registerpair AX.
Adi2:
sta ARTH+1 ! second operand (highbyte)
stx ARTH ! second operand (lowbyte)
jsr Pop ! get first operand
pha ! save A
clc
txa
adc ARTH ! add lowbytes
tax
pla ! get A
adc ARTH+1 ! add the highbytes
rts

20
mach/6500/libem/adi4.s Normal file
View file

@ -0,0 +1,20 @@
.define Adi4
! This subroutine adds two fourbyte integers, which are on the stack.
! The addresses are initiated by the subroutine Addsub.
! Also the loopvariable (register X) is initiated by that routine.
! The result is pushed back onto the stack
Adi4:
jsr Addsub ! initiate addresses
clc
1: lda (ADDR+2),y ! get byte first operand
adc (ADDR),y ! add to byte second operand
sta (ADDR+2),y ! push on real stack
iny
inx
bne 1b ! do it 4 times
rts

34
mach/6500/libem/and.s Normal file
View file

@ -0,0 +1,34 @@
.define And
! This subroutine performs the logical and on two groups of
! atmost 254 bytes. The number of bytes is in register Y.
! The two groups are on the stack.
! First the value of the stackpointer is saved in zeropage
! locations ADDR, ADDR+1. Then an offset of Y is added
! and stored in ADDR+2, ADDR+3.
! The result is pushed back on the stack.
And:
lda SP+1
sta ADDR+1 ! address of first group (lowbyte)
lda SP+2
sta ADDR ! address of first group (highbyte)
clc
tya
adc SP+2
sta SP+2 ! new stackpointer (lowbyte)
sta ADDR+2 ! stackpointer + Y (lowbyte)
lda #0
adc SP+1
sta SP+1 ! new stackpointer (highbyte)
sta ADDR+3 ! stackpointer + Y (highbyte)
1: dey
lda (ADDR),y ! get byte first group
and (ADDR+2),y ! perform logical and with second group
sta (ADDR+2),y ! push result on real_stack
tya
bne 1b ! do it n times
rts

20
mach/6500/libem/asp.s Normal file
View file

@ -0,0 +1,20 @@
.define Asp
! This subroutine adds an offset to the stackpointer,
! e.g. after the return from a procedurecall.
! The offset is in registerpair AX, and is added to the
! stackpointer.
Asp:
tay ! save A
txa ! get X
clc
adc SP+2 ! add adjustment (lowbyte)
sta SP+2 ! new stackpointer (lowbyte)
tya ! get A
adc SP+1 ! add adjustment (highbyte)
sta SP+1 ! get stackpointer (highbyte)
rts

33
mach/6500/libem/blm.s Normal file
View file

@ -0,0 +1,33 @@
.define Blm, Blmnp
! This subroutine copies bytes from one place in memory to
! another. The source address is in registerpair AX and is stored
! in zeropage locations ADDR and ADDR+1.
! The destination address is popped from the stack and stored in
! zeropage locations ADDR+2 and ADDR+3.
! The number of bytes to be copied is in register Y (lowbyte) and
! zeropage location NBYTES+1 (highbyte).
! The subroutine Blmnp is used when the source and destination
! addresses are already in zeropage.
Blm:
stx ADDR+2 ! source address (lowbyte)
sta ADDR+3 ! source address (highbyte)
jsr Pop
stx ADDR ! destination address (lowbyte)
sta ADDR+1 ! destination address (highbyte)
Blmnp: ldx NBYTES+1
1: dey
lda (ADDR),y ! get source byte
sta (ADDR+2),y ! copy to destination
tya
bne 1b
dec ADDR+1 ! 256 bytes copied
dec ADDR+3 ! decrement source and destination address
ldy #0
dex
bne 1b ! do it n times
rts

50
mach/6500/libem/cii.s Normal file
View file

@ -0,0 +1,50 @@
.define Cii
! This subroutine converts integers to integers.
! Convertions of integers with the same source size as destination
! size aren't done, there just return the source.
! A convertion from 4 bytes to 2 bytes just strips the two
! most significant bytes.
! A convertion from 2 bytes to 4 bytes tests the sign of the
! source so that sign extentension takes place if neccesairy.
Cii:
cpx #2
beq Cii_2 ! a conversion from ? to 2
jsr Pop ! a conversion from 4 to ?
cpx #4
beq 8f ! a conversion 4 to 4 (skip)
jsr Pop
tay ! save A for sign test
pha ! save A
txa
pha ! save X
tya ! test on negative
bmi 1f ! negative means sign extension
lda #0 ! no sign extension here
tax
beq 2f
1: lda #0FFh ! sign extension here
tax
2: jsr Push ! push twobyte integer
pla
tax ! get X
pla ! get A
jmp Push
Cii_2: ! a conversion from 2 to ?
jsr Pop
cpx #2
beq 8f ! a conversion from 2 to 2 (skip)
jsr Pop ! a conversion from 4 to 2
pha ! save A
txa
pha ! save X
jsr Pop ! strip most significant bytes
pla ! get X
tax
pla ! get A
jmp Push ! push result
8: rts

26
mach/6500/libem/cmi.s Normal file
View file

@ -0,0 +1,26 @@
.define Cmi
! This subroutine compares on two integers.
! If T is pushed first and than S, the routine will return:
! -1 if S < T,
! 0 if S = T,
! 1 if S > T.
Cmi:
jsr Sbi2 ! subtract operands (T - S)
bpl 1f ! S >= T
lda #0FFh ! S < T
tax ! AX becomes -1
rts
1: beq 2f
3: lda #0 ! S > T
ldx #1 ! AX becomes 1
rts
2: txa
bne 3b
lda #0 ! S = T
tax ! AX becomes 0
rts

37
mach/6500/libem/cmi4.s Normal file
View file

@ -0,0 +1,37 @@
.define Cmi4
! This subroutine compares on fourbyte integers.
! If T is pushed first and than S, the routine will return:
! -1 if S < T,
! 0 if S = T,
! 1 if S > T.
Cmi4:
jsr Sbi4 ! subtract operands (T - S)
jsr Pop ! get result (lowbyte, lowbyte+1)
stx ARTH ! store lowbyte
sta ARTH+1 ! store lowbyte+1
jsr Pop ! get result (lowbyte+2, lowbyte+3)
tay ! test lowbyte+3
bpl 1f ! S >= T
lda #0FFh ! S < T
tax ! AX becomes -1
rts
1: cmp #0 ! test lowbyte+3 on zero
bne 2f
cpx #0 ! test lowbyte+2 on zero
bne 2f
lda #0
cmp ARTH+1 ! test lowbyte+1 on zero
bne 2f
cmp ARTH ! test lowbyte on zero
bne 2f
lda #0 ! S = T
tax ! AX becomes 0
rts
2: lda #0 ! S > T
ldx #1 ! AX becomes 1
rts

46
mach/6500/libem/cms.s Normal file
View file

@ -0,0 +1,46 @@
.define Cms
! This subroutine compares two groups of bytes, bit for bit.
! The groups can consist of 2 or 4 bytes. This number is in
! register Y.
! The address of the first group is stored in zeropage locations
! ADDR and ADDR+1, the address of the second group in ADDR+2 and ADDR+3
! The routine returns a 0 on equality, a 1 otherwise.
Cms:
lda SP+2
ldx SP+1
sta ADDR ! address of first group (lowbyte)
stx ADDR+1 ! address of second group (highbyte)
clc
tya
adc SP+2
sta SP+2
sta ADDR+2 ! address of second group (lowbyte)
txa
adc #0
sta ADDR+3 ! address of second group (highbyte)
tax
clc
tya
adc SP+2
sta SP+2 ! new stackpointer (lowbyte)
txa
adc #0
sta SP+1 ! new stackpointer (highbyte)
1: dey
lda (ADDR),y ! get byte first group
cmp (ADDR+2),y ! compare bit for bit with byte second group
bne 2f
tya
bne 1b
lda #0 ! both groups are equal
tax
rts
2: lda #0 ! there is a difference between the groups
ldx #1
rts

30
mach/6500/libem/cmu.s Normal file
View file

@ -0,0 +1,30 @@
.define Cmu2
! This subroutine compares two unsigned twobyte integers.
! If T is the first pushed and than S, the routine will return:
! -1 if S < T,
! 0 if S = T,
! 1 if S > T.
Cmu2:
stx EXG ! S (lowbyte)
sta EXG+1 ! S (highbyte)
jsr Pop ! get T
cmp EXG+1
beq 2f ! S (highbyte) = T (highbyte)
bcc 1f
4: lda #0 ! S > T
ldx #1
rts
1: lda #0FFh ! S < T
tax
rts
2: cpx EXG
bne 3f
lda #0 ! S = T
tax
rts
3: bcc 1b
bcs 4b

45
mach/6500/libem/cmu4.s Normal file
View file

@ -0,0 +1,45 @@
.define Cmu4
! This subroutine compares two unsigned fourbyte integers.
! If T is first pushed and than S the routine will return:
! -1 if S < T,
! 0 if S = T,
! 1 if S > T.
Cmu4:
lda #ARTH
sta ADDR
lda #0
sta ADDR+1
jsr Sdo ! store S in zeropage ARTH - ARTH+3
lda #ARTH+4
sta ADDR
jsr Sdo ! store T in zeropage ARTH+4 - ARTH+7
lda ARTH+7
cmp ARTH+3
bcc 3f ! S (lowbyte+3) < T (lowbyte+3)
bne 2f ! S (lowbyte+3) < T (lowbyte+3)
lda ARTH+6
cmp ARTH+2
bcc 3f ! S (lowbyte+2) < T (lowbyte+2)
bne 2f ! S (lowbyte+2) < T (lowbyte+2)
lda ARTH+5
cmp ARTH+1
bcc 3f ! S (lowbyte+1) < T (lowbyte+1)
bne 2f ! S (lowbyte+1) < T (lowbyte+1)
lda ARTH+4
cmp ARTH
bcc 3f ! S (lowbyte+0) < T (lowbyte+0)
bne 2f ! S (lowbyte+0) < T (lowbyte+0)
lda #0
tax ! S = T
rts
2: lda #0 ! S > T
ldx #1
rts
3: lda #0FFh ! S < T
tax
rts

21
mach/6500/libem/com.s Normal file
View file

@ -0,0 +1,21 @@
.define Com
! This subroutine performs a one complement on
! a group of atmost 254 bytes (number in register Y).
! This group is on the top of the stack.
Com:
lda SP+1
sta ADDR+1 ! address (highbyte) of first byte
lda SP+2
sta ADDR ! address (lowbyte) of first byte
1: dey
lda (ADDR),y
eor #0FFh ! one complement
sta (ADDR),y
tya
bne 1b ! do it n times
rts

71
mach/6500/libem/csa.s Normal file
View file

@ -0,0 +1,71 @@
.define Csa
! This subroutine performs the case jump by indexing.
! The zeropage locations ADDR, ADDR+1 contain the address of
! the case descriptor which also is the address of the
! default pointer.
! The zeropage locations ADDR+2, ADDR+3 contain the address of the
! indextable which is the casedescriptor + 6.
Csa:
stx ADDR ! address of descriptor (lowbyte)
sta ADDR+1 ! address of descriptor (highbyte)
tay
txa
clc
adc #6
sta ADDR+2 ! address of index table (lowbyte)
tya
adc #0
sta ADDR+3 ! address of index table (highbyte)
jsr Pop ! fetch index
pha ! subtract lowerbound
txa
ldy #2
sec
sbc (ADDR),y
sta ARTH ! lowerbound (lowbyte)
pla
iny
sbc (ADDR),y
sta ARTH+1 ! lowerbound (highbyte)
bmi 1f ! index < lowerbound
ldy #5
lda (ADDR),y
cmp ARTH+1
bcc 1f ! index (highbyte) > upperbound - lowerbound
bne 2f ! index (highbyte) <= upperbound - lowerbound
dey
lda (ADDR),y
cmp ARTH
bcc 1f ! index (lowbyte) > upperbound - lowerbound
2: asl ARTH
rol ARTH+1 ! index * 2
clc
lda ADDR+2
adc ARTH
sta ADDR+2 ! address of pointer (lowbyte)
lda ADDR+3
adc ARTH+1
sta ADDR+3 ! address of pointer (highbyte)
ldy #0
lda (ADDR+2),y ! jump address (lowbyte)
tax
iny
lda (ADDR+2),y ! jump address (highbyte)
bne 3f
cpx #0
beq 1f
3: stx ADDR ! pointer <> 0
sta ADDR+1
jmp (ADDR) ! jump to address
1: ldy #0 ! pointer = 0
lda (ADDR),y ! get default pointer (lowbyte)
tax
iny
lda (ADDR),y ! get default pointer (highbyte)
bne 3b
cpx #0
bne 3b ! default pointer <> 0

62
mach/6500/libem/csb.s Normal file
View file

@ -0,0 +1,62 @@
.define Csb
! This subroutine performs the case jump by searching the table.
! The zeropage locations ADDR, ADDR+1 contain the address of the
! case descriptor, which also is the address of the default pointer.
! The zeropage locations ADDR+2, ADDR+3 are used to address the jump
! pointers.
Csb:
stx ADDR ! address of descriptor (lowbyte)
sta ADDR+1 ! address of descriptor (highbyte)
stx ADDR+2
sta ADDR+3
ldy #2
lda (ADDR),y ! number of entries (lowbyte)
pha
jsr Pop
stx ARTH ! index (lowbyte)
sta ARTH+1 ! index (highbyte)
pla
tax
inx
2: clc
lda #4
adc ADDR+2
sta ADDR+2 ! pointer (lowbyte)
bcc 1f
lda #0
adc ADDR+3
sta ADDR+3 ! pointer (highbyte)
1: ldy #0
lda (ADDR+2),y
cmp ARTH
bne 3f ! pointer (lowbyte) <> index (lowbyte)
iny
lda (ADDR+2),y
cmp ARTH+1
bne 3f ! pointer (highbyte) <> index (highbyte)
iny
lda (ADDR+2),y ! jump address (lowbyte)
tax
iny
lda (ADDR+2),y ! jump address (highbyte)
jmp 4f
3: dex
bne 2b
5: ldy #0
lda (ADDR),y ! default pointer (lowbyte)
tax
iny
lda (ADDR),y ! default pointer (highbyte)
beq 1f
4: bne 1f ! pointer (lowbyte) <> 0
cpx #0
bne 1f ! pointer (highbyte) <> 0
beq 5b ! get default pointer
1: stx ADDR
sta ADDR+1
jmp (ADDR) ! jump

36
mach/6500/libem/data.s Normal file
View file

@ -0,0 +1,36 @@
.define EARRAY,ERANGE,ESET,EIOVFL
.define ECONV,ESTACK
.define EHEAP,EODDZ,ECASE
.define EBADMON,EBADLIN,EBADGTO
! This file contains the global data used by the trap routine.
! DATA
.data
EARRAY:
.asciz "Array bound error\n\r"
ERANGE:
.asciz "Range bound error\n\r"
ESET:
.asciz "Set bound error\n\r"
EIOVFL:
.asciz "Integer overflow\n\r"
ECONV:
.asciz "Conversion error\n\r"
ESTACK:
.asciz "Stack overflow\n\r"
EHEAP:
.asciz "Heap overflow\n\r"
EODDZ:
.asciz "Illegal size argument\n\r"
ECASE:
.asciz "Case error\n\r"
EBADMON:
.asciz "Bad monitor call\n\r"
EBADLIN:
.asciz "Argument of LIN to high\n\r"
EBADGTO:
.asciz "GTO descriptor error\n\r"

41
mach/6500/libem/div4.s Normal file
View file

@ -0,0 +1,41 @@
.define Div4
! This subroutine performs a signed divide on two fourbyte integers.
! For more detail see dvi.s
! The only difference is that zeropage locations are twice as big.
Div4:
ldy #0
sty SIGN
jsr Pop
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
sta ARTH+3 ! divisor in ARTH - ARTH+3
tay
bpl 1f
lda #0
ldx #ARTH
jsr Ngi4
ldy #1
sty SIGN ! it's signed
1: jsr Pop
stx ARTH+4
sta ARTH+5
jsr Pop
stx ARTH+6
sta ARTH+7 ! dividend in ARTH+4 - ARTH+7
tay
bpl 1f
lda #0
ldx #ARTH+4
jsr Ngi4
lda SIGN
eor #1
sta SIGN
lda #1
sta NBYTES
1: jmp Duv4

View file

@ -0,0 +1,59 @@
.define Adf4
.define Adf8
.define Sbf4
.define Sbf8
.define Mlf4
.define Mlf8
.define Dvf4
.define Dvf8
.define Ngf4
.define Ngf8
.define Zrf4
.define Zrf8
.define Cmf4
.define Cmf8
.define Fef4
.define Fef8
.define Fif4
.define Fif8
.define Cfi
.define Cif
.define Cuf
.define Cff
.define Cfu
.define Lfr8
.define Ret8
! Dummy floating point package for 6500
! every EM floating point instruction results in an
! "Illegal EM instruction" trap.
Adf4:
Adf8:
Sbf4:
Sbf8:
Mlf4:
Mlf8:
Dvf4:
Dvf8:
Ngf4:
Ngf8:
Zrf4:
Zrf8:
Cmf4:
Cmf8:
Fef4:
Fef8:
Fif4:
Fif8:
Cfi:
Cif:
Cuf:
Cff:
Cfu:
Lfr8:
Ret8:
ldx #Eillins
lda #0
jsr Trap

30
mach/6500/libem/dup.s Normal file
View file

@ -0,0 +1,30 @@
.define Dup
! This subroutine duplicate's the top n (in register Y) bytes.
! N is atmost 256.
! The duplicating takes place as follows.
! The registerpair is filled with the bytes at stackpointer + N
! and stackpopinter + N-1.
! These two bytes then are pushed onto the stack.
! Next the offset N is decremented and the next two byte are taken
! care off. Until N = 0.
Dup:
lda SP+1
ldx SP+2
stx ADDR ! address of group (lowbyte)
sta ADDR+1 ! address of group (highbyte)
1: dey
lda (ADDR),y ! get lowbyte
pha
dey
lda (ADDR),y ! get highbyte
tax
pla
jsr Push ! push them
tya
bne 1b
rts

66
mach/6500/libem/duv4.s Normal file
View file

@ -0,0 +1,66 @@
.define Duv4
! This subroutine performs an unsigned division on two fourbyte
! unsigned integers.
! For more details see dvi.s
! The only difference is that zeropage locations are twice as big.
Duv4:
1: ldy #0
sty ARTH+8
sty ARTH+9
sty ARTH+10
sty ARTH+11
ldy #33
4: lda ARTH+11
cmp ARTH+3
bcc 1f ! no sub
bne 2f ! sub
lda ARTH+10
cmp ARTH+2
bcc 1f
bne 2f
lda ARTH+9
cmp ARTH+1
bcc 1f
bne 2f
lda ARTH+8
cmp ARTH
bcc 1f
2: sec
lda ARTH+8
sbc ARTH
sta ARTH+8
lda ARTH+9
sbc ARTH+1
sta ARTH+9
lda ARTH+10
sbc ARTH+2
sta ARTH+10
lda ARTH+11
sbc ARTH+3
sta ARTH+11
sec
rol ARTH+4
bne 3f
1: asl ARTH+4
3: rol ARTH+5
rol ARTH+6
rol ARTH+7
rol ARTH+8
rol ARTH+9
rol ARTH+10
rol ARTH+11
dey
bne 4b
ldy UNSIGN
beq 1f
ldy SIGN
beq 1f
lda #0
ldx #ARTH+4
jsr Ngi4
1: rts

82
mach/6500/libem/dvi.s Normal file
View file

@ -0,0 +1,82 @@
.define Dvi2, Div, Duv
! The subroutine Dvi2 performs a signed division.
! Its operands are on the stack.
! The subroutine Div performs also a signed division, ecxept that
! its operand are already in zeropage.
! The subroutine Duv performs a n unsigned division.
! For an explanation of the algoritm used see
! A. S. Tanenbaum's Structered Computer Organisation. 1976
Dvi2:
stx ARTH
sta ARTH+1 ! store divisor
jsr Pop
stx ARTH+2
sta ARTH+3 ! store dividend
ldy #1
sty UNSIGN ! used for result sign
Div:
ldy #0
sty SIGN
lda ARTH+1
bpl 1f ! if divisor is negative
ldx ARTH ! make it positive
jsr Ngi2
ldy #1
sty SIGN
stx ARTH
sta ARTH+1
1: lda ARTH+3
bpl 1f ! if dividend is negative
ldx ARTH+2 ! make it positive
jsr Ngi2
pha
lda SIGN
eor #1 ! excusive or with sign of divisor
sta SIGN
lda #1
sta NBYTES
pla
stx ARTH+2
sta ARTH+3
Duv:
1: ldy #0
sty ARTH+4
sty ARTH+5
ldy #17
4: lda ARTH+5
cmp ARTH+1
bcc 1f ! no subtraction
bne 2f ! divisor goes into dividend
lda ARTH+4
cmp ARTH
bcc 1f ! no subtraction
2: sec ! divisor goes into dividend
lda ARTH+4
sbc ARTH
sta ARTH+4
lda ARTH+5
sbc ARTH+1
sta ARTH+5 ! subtract divisor from dividend
sec
rol ARTH+2 ! a subtraction so shift in a 1
bne 3f
1: asl ARTH+2 ! no subtraction so shift in a 0
3: rol ARTH+3
rol ARTH+4
rol ARTH+5 ! shift dividend
dey
bne 4b
ldx ARTH+2
lda ARTH+3
ldy UNSIGN ! is it an unsigned division
beq 1f
ldy SIGN ! is the result negative
beq 1f
jsr Ngi2
1: rts

19
mach/6500/libem/dvi4.s Normal file
View file

@ -0,0 +1,19 @@
.define Dvi4
! This subroutine performs a fourbyte signed division.
! For more details see dvi.s
! The only difference is that zeropage locations are twice as big.
Dvi4:
ldy #1
sty UNSIGN
jsr Div4
lda ARTH+7
ldx ARTH+6
jsr Push
lda ARTH+5
ldx ARTH+4
jmp Push

17
mach/6500/libem/dvu.s Normal file
View file

@ -0,0 +1,17 @@
.define Dvu2
! This subroutine performs a twobyte unsigned division
! For more details see dvi.s.
Dvu2:
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
sta ARTH+3
ldy #0
sty UNSIGN
jmp Dvu

31
mach/6500/libem/dvu4.s Normal file
View file

@ -0,0 +1,31 @@
.define Dvu4
! This subroutine performs an unsigned division on fourbyte
! integers. For more details see dvi.s
! The only difference is that zeropage locations are twice as big.
Dvu4:
ldy #0
sty UNSIGN ! it is unsigned
jsr Pop
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
sta ARTH+3 ! divisor in ARTH - ARTH+3
jsr Pop
stx ARTH+4
sta ARTH+5
jsr Pop
stx ARTH+6
sta ARTH+7 ! dividend in ARTH+4 - ARTH+7
jsr Duv4
lda ARTH+7
ldx ARTH+6
jsr Push
lda ARTH+5
ldx ARTH+4
jmp Push ! store result

33
mach/6500/libem/exg.s Normal file
View file

@ -0,0 +1,33 @@
.define Exg
! This subroutine exchanges two groups of bytes on the top of the
! stack. The groups may consist of atmost 255 bytes.
! This number is in register Y.
! The exchange is from ADDR, ADDR+1 to ADDR+2, ADDR+3
Exg:
lda SP+1
ldx SP+2
stx ADDR ! address of first group (lowbyte)
sta ADDR+1 ! address of first group (highbyte)
sty Ytmp ! save number of bytes to be exchanged
clc
lda SP+2
adc Ytmp
sta ADDR+2 ! address of second group (lowbyte)
lda SP+1
adc #0
sta ADDR+3 ! address of second group (highbyte)
1: dey
lda (ADDR),y ! get byte from first group
pha ! temporary save
lda (ADDR+2),y ! get byte from second group
sta (ADDR),y ! store in first group
pla ! get temporary saved byte
sta (ADDR+2),y ! store in second group
tya
bne 1b ! perform n times
rts

23
mach/6500/libem/exg2.s Normal file
View file

@ -0,0 +1,23 @@
.define Exg2
! This subroutine exchanges two words on top of the stack.
! The top word of the stack is really in the AX registerpair.
! So this word is exchanged with the top of the real stack.
Exg2:
pha ! save A
txa
pha ! save X
jsr Pop ! get top real stack
stx EXG
sta EXG+1 ! save top of real stack
pla ! get X
tax
pla ! get A
jsr Push ! push on real stack
ldx EXG ! get new X
lda EXG+1 ! get new A
rts

65
mach/6500/libem/gto.s Normal file
View file

@ -0,0 +1,65 @@
.define Gto
! This subroutine performs the non_local goto.
! The address of the descriptor is stored in zeropage locations
! ADDR, ADDR+1.
! Since there are two stacks (hardware_stack and the real_stack),
! the stackpointer of the hard_stack is resetted by searching the
! new localbase in the real_stack while adjusting the hardware_stack.
Gto:
stx ADDR ! address of descripto (lowbyte)
sta ADDR+1 ! address of descriptor (highbyte)
pla ! remove
pla ! __gto return address.
ldy #4
lda (ADDR),y ! new localbase (lowbyte)
sta ARTH
tax
iny
lda (ADDR),y ! new localbase (highbyte)
sta ARTH+1
cmp LB+1
bne 1f
cpx LB
beq 2f ! goto within same procedure
1: ldy #0
lda (LB),y ! get localbase (lowbyte)
tax
iny
lda (LB),y ! get localbase (highbyte)
cmp ARTH+1
bne 3f
cpx ARTH
beq 2f ! found localbase
3: stx LB ! temporary save of localbase
sta LB+1
pla ! adjust
pla ! hardware_stack
jmp 1b
2: sta LB+1 ! store localbase (highbyte)
pha
stx LB ! store localbase (lowbyte)
sec
txa
sbc #BASE
sta LBl ! localbase - 240 (lowbyte)
pla
sbc #0
sta LBl+1 ! localbase - 240 (highbyte)
ldy #3
lda (ADDR),y ! new stackpointer (highbyte)
sta SP+1
dey
lda (ADDR),y ! new stackpointer (lowbyte)
sta SP+2
dey
lda (ADDR),y ! jump address (highbyte)
sta ADDR+3
dey
lda (ADDR),y ! jump address (lowbyte)
sta ADDR+2
jmp (ADDR+2) ! jump to address

13
mach/6500/libem/indir.s Normal file
View file

@ -0,0 +1,13 @@
.define Indir
! This subroutine performs an indirect procedurecall.
! This must be done this way since the jump instruction
! is the only one which can indirect change the programcounter.
! The address of the function must be in zeropage loactions
! ADDR, ADDR+1.
Indir:
jmp (ADDR)

55
mach/6500/libem/inn.s Normal file
View file

@ -0,0 +1,55 @@
.define Inn
! This subroutine checks if a certain bit is set in a set
! of n bytes on top of the stack.
Inn:
stx ARTH ! save bit number (lowbyte)
sta ARTH+1 ! save bit number (highbyte)
and #80h
beq 1f
lda #0 ! bit number is negative
sta ARTH+2 ! make it zero
beq 3f
1: txa
and #07h ! get bit number mod 8
tax
lda #1
cpx #0 ! bit number = 0
beq 2f ! no shifting to right place
1: asl a ! shift left until bit is in place
dex
bne 1b
2: sta ARTH+2 ! bit is one in place
ldx #3
1: lsr ARTH+1 ! shift left 3 times bit number (highbyte)
ror ARTH ! shift left 3 times bit number (lowbyte)
dex ! this is bit number div 8
bne 1b ! which is byte number
3: lda SP+1
ldx SP+2
stx ADDR ! address of the set (lowbyte)
sta ADDR+1 ! address of the set (highbyte)
iny
tya
bne 2f
inc SP+1
2: clc ! remove the set
adc SP+2
sta SP+2 ! new stackpointer (lowbyte)
lda #0
adc SP+1
sta SP+1 ! new stackpointer (highbyte)
ldy ARTH
lda (ADDR),y ! load the byte in A
bit ARTH+2 ! test bit
bne 1f
3: lda #0 ! bit is zero
tax
rts
1: lda #0 ! bit is one
ldx #1
rts

29
mach/6500/libem/ior.s Normal file
View file

@ -0,0 +1,29 @@
.define Ior
! This subroutine performs the logical inclusive or on two
! groups of bytes. The groups may consist of atmost 254 bytes.
! The two groups are on the stack.
Ior:
lda SP+1
sta ADDR+1 ! address of the first group (highbyte)
lda SP+2
sta ADDR ! address of the first group (lowbyte)
clc
tya
adc SP+2
sta SP+2 ! new stackpointer (lowbyte)
sta ADDR+2 ! address of second group (lowbyte)
lda #0
adc SP+1
sta SP+1 ! new stackpointer (highbyte)
sta ADDR+3 ! address of second group (highbyte)
1: dey
lda (ADDR),y ! get byte first group
ora (ADDR+2),y ! inclusive or with byte second group
sta (ADDR+2),y ! restore result on stack
tya
bne 1b ! perform n times
rts

25
mach/6500/libem/lar.s Normal file
View file

@ -0,0 +1,25 @@
.define Lar
! This subroutine performs the LAR instruction.
! For details see rapport IR-81.
Lar:
jsr Aar ! get object address
ldy NBYTES+1 ! the size of the object (highbyte)
bne 2f
ldy NBYTES ! the size of the object (lowbyte)
cpy #1
bne 1f ! object size is one byte
jsr Loi1 ! get object
jmp Push ! push on the stack
1: cpy #2
bne 1f ! object size is a word
jsr Loi ! get word
jmp Push ! push on the stack
1: cpy #4
bne 2f ! object size is four bytes
jmp Ldi ! get object
2: jmp Loil ! get object

19
mach/6500/libem/lcs.s Normal file
View file

@ -0,0 +1,19 @@
.define Lcs
! This subroutine creates space for locals on procedure entry
! by lowering the stackpointer.
Lcs:
sta ARTH ! number of locals (lowbyte)
stx ARTH+1 ! number of locals (highbyte)
sec
lda SP+2
sbc ARTH
sta SP+2 ! new stackpointer (lowbyte)
lda SP+1
sbc ARTH+1
sta SP+1 ! new stackpointer (highbyte)
rts

24
mach/6500/libem/ldi.s Normal file
View file

@ -0,0 +1,24 @@
.define Ldi, Ldo
! The subroutine Ldi pushes a four byte object onto the stack.
! The address is in registerpair AX.
! If the address is already in zeropage Ldo is used.
Ldi:
stx ADDR ! address of object (lowbyte)
sta ADDR+1 ! address of object (highbyte)
Ldo:
ldy #3
1: lda (ADDR),y ! get lowbyte
pha
dey
lda (ADDR),y ! get highbyte
tax
pla
jsr Push ! do the push
dey
bpl 1b ! perform 2 times
rts

18
mach/6500/libem/locaddr.s Normal file
View file

@ -0,0 +1,18 @@
.define Locaddr
! This routine gets the address of a local which offset is to big.
! The offset is in registerpair AX.
Locaddr:
pha ! save A
txa
clc
adc LB ! localbase + offset (lowbyte)
sta ADDR ! address (lowbyte)
pla
adc LB+1 ! localbase + offset (highbyte)
sta ADDR+1 ! address (highbyte)
rts

17
mach/6500/libem/loi.s Normal file
View file

@ -0,0 +1,17 @@
.define Loi, Lext
! This subroutine performs an indirect load on a word of two bytes.
! Lext is used when the address is already in zeropage.
Loi:
stx ADDR ! address of object (lowbyte)
sta ADDR+1 ! address of object (highbyte)
Lext:
ldy #0
lda (ADDR),y ! get lowbyte
tax
iny
lda (ADDR),y ! get highbyte
rts

15
mach/6500/libem/loi1.s Normal file
View file

@ -0,0 +1,15 @@
.define Loi1
! This routine loads a one byte object in registerpair AX.
Loi1:
stx ADDR ! address of byte (lowbyte)
sta ADDR+1 ! address of byte (highbyte)
ldy #0
lda (ADDR),y ! load byte
tax ! store byte in X
tya ! clear highbyte of AX
rts

23
mach/6500/libem/loil.s Normal file
View file

@ -0,0 +1,23 @@
.define Loil
! This subroutine pushes an object of size greater than four bytes
! onto the stack.
Loil:
sta ADDR+1 ! source address (lowbyte)
stx ADDR ! source address (highbyte)
sty NBYTES
sec
lda SP+2
sbc NBYTES
sta ADDR+2 ! destination address (lowbyte)
sta SP+2 ! new stackpointer
lda SP+1
sbc NBYTES+1
sta ADDR+3 ! destination address (highbyte)
sta SP+1 ! new stackpointer
inc NBYTES+1
jmp Blmnp ! do the move

16
mach/6500/libem/lol.s Normal file
View file

@ -0,0 +1,16 @@
.define Lol
! This subroutine loads a local in registerpair AX which
! offset from the localbase is to big.
Lol:
jsr Locaddr ! get the address of local
ldy #0
lda (ADDR),y ! get lowbyte
tax
iny
lda (ADDR),y ! get highbyte
rts

30
mach/6500/libem/los.s Normal file
View file

@ -0,0 +1,30 @@
.define Los
! This subroutine perfoms the LOS instruction.
! For detail see rapport IR-81.
Los:
cmp #0
bne 3f
cpx #1
bne 1f ! the size is one
jsr Pop ! get address
jsr Loi1 ! push it on the stack
jmp Push
1: cpx #2
bne 2f ! the size is two
jsr Pop ! get address
jsr Loi ! push it on the stack
jmp Push
2: cpx #4
bne 3f ! the size is four
jsr Pop ! get address
jmp Ldi ! push it on the stack
3: sta ARTH+1 ! the size is greater than four
txa
tay
jsr Pop ! get address
jmp Loil ! push it on the stack

15
mach/6500/libem/lxa1.s Normal file
View file

@ -0,0 +1,15 @@
.define Lxa1
! This subroutine loads the address of AB zero static levels back.
Lxa1:
ldy LB+1 ! load address of localbase (highbyte)
ldx LB ! load address of localbase (lowbyte)
inx
inx ! argumentbase = localbase + 2
bne 1f
iny
1: tya
rts

32
mach/6500/libem/lxa2.s Normal file
View file

@ -0,0 +1,32 @@
.define Lxa2
! This subroutine load the address of AB n (255 >= n > 0) static levels
! back.
Lxa2:
lda LB
sta ADDR ! address of localbase (lowbyte)
lda LB+1
sta ADDR+1 ! address of localbase (highbyte)
1: ldy #2
lda (ADDR),y ! static level LB (lowbyte)
pha
iny
lda (ADDR),y ! static level LB (highbyte)
sta ADDR+1 ! static level LB (highbyte)
pla
sta ADDR ! static level LB (lowbyte)
dex
bne 1b
tax
ldy ADDR+1
inx
inx ! argumentbase = localbase + 2
bne 1f
iny
1: tya
rts

25
mach/6500/libem/lxl.s Normal file
View file

@ -0,0 +1,25 @@
.define Lxl
! This subroutine loads LB n (255 => n > 0) static levels back.
Lxl:
lda LB
sta ADDR ! address of localbase (lowbyte)
lda LB+1
sta ADDR+1 ! address of localbase (highbyte)
1: ldy #2
lda (ADDR),y ! get localbase (lowbyte) 1 level back
pha
iny
lda (ADDR),y ! get localbase (highbyte) 1 level back
sta ADDR+1 ! new localbase (highbyte)
pla
sta ADDR ! new localbase (lowbyte)
dex
bne 1b ! n levels
tax
lda ADDR+1
rts

69
mach/6500/libem/mli.s Normal file
View file

@ -0,0 +1,69 @@
.define Mli2, Mlinp, Mul
! The subroutine Mli2 multiplies two signed integers. The integers
! are popped from the stack.
! The subroutine Mlinp expects the two integer to be in zeropage.
! While the subroutine Mul an unsigned multiply subroutine is.
! For the algoritme see A. S. Tanenbaum
! Structured Computer Organisation. 1976.
Mli2:
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
sta ARTH+3
Mlinp: ldy #1
sty UNSIGN ! it's signed
lda ARTH+1
bpl 3f ! multiplier negative so:
ldx ARTH
jsr Ngi2 ! negate multiplier
stx ARTH
sta ARTH+1
ldx ARTH+2
lda ARTH+3
jsr Ngi2 ! negate multiplicand
stx ARTH+2
sta ARTH+3
Mul:
3: lda #0
sta ARTH+4
sta ARTH+5
sta ARTH+6
sta ARTH+7 ! clear accumulator
ldy #16
1: lda #1h
bit ARTH
beq 2f ! multiplying by zero: no addition
clc
lda ARTH+6
adc ARTH+2
sta ARTH+6
lda ARTH+7
adc ARTH+3
sta ARTH+7
2: lsr ARTH+1
ror ARTH ! shift multiplier
lsr ARTH+7
ror ARTH+6
ror ARTH+5
ror ARTH+4 ! shift accumulator
lda UNSIGN
beq 3f ! unsigned multiply: so no shift in of signbit
lda ARTH+3
bpl 3f
lda #40h
bit ARTH+7
beq 3f
lda ARTH+7
ora #80h
sta ARTH+7
3: dey
bne 1b
ldx ARTH+4
lda ARTH+5
rts

33
mach/6500/libem/mli4.s Normal file
View file

@ -0,0 +1,33 @@
.define Mli4
! This subroutine multiplies two signed fourbyte integers
! For more detail see mli.s
! The only difference is that zeropage locations are twice as big.
Mli4:
ldy #1
sty UNSIGN
jsr Pop
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
sta ARTH+3 ! multiplier
jsr Pop
stx ARTH+4
sta ARTH+5
jsr Pop
stx ARTH+6
sta ARTH+7 ! multiplicand
lda ARTH+3
bpl 3f
lda #0
ldx #ARTH
jsr Ngi4
lda #0
ldx #ARTH+4
jsr Ngi4
3: jmp Mul4

17
mach/6500/libem/mlu.s Normal file
View file

@ -0,0 +1,17 @@
.define Mlu2
! This subroutine multiplies two unsigned fourbyte intergers.
! For more details see mli.s
Mlu2:
stx ARTH
sta ARTH+1 ! multiplier
jsr Pop
stx ARTH+2
sta ARTH+3 ! multiplicand
ldy #0
sty UNSIGN
jmp Mul

25
mach/6500/libem/mlu4.s Normal file
View file

@ -0,0 +1,25 @@
.define Mlu4
! This subroutine multiplies two fourbyte unsigned integers.
! For more details see mli.s
! The only difference is that zeropage locations are twice as big.
Mlu4:
ldy #0
sty UNSIGN
jsr Pop
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
sta ARTH+3 ! multiplier
jsr Pop
stx ARTH+4
sta ARTH+5
jsr Pop
stx ARTH+6
sta ARTH+7 ! multiplicand
jmp Mul4

35
mach/6500/libem/mon.s Normal file
View file

@ -0,0 +1,35 @@
.define Mon
! This subroutine performs some monitor calls.
! The exit call just resets the hardware_stackpointer so
! this routine will return to the operating system.
! The close call just returns a zero.
! The ioctl call just pops its arguments and returns a zero.
! The write routine is a real one.
Mon:
cpx #1
bne 1f ! exit
ldx STACK ! load stackpointer
dex
dex ! adjust stackpointer
txs ! set stackpointer
rts
1: cpx #4
bne 1f
jmp Mwrite
1: cpx #6 ! facked
bne 1f ! close
lda #0
tax ! return zero
rts
1: cpx #54
jsr Pop ! pop first argument (fildes)
jsr Pop ! pop second argument (request)
jsr Pop ! pop third argument (argp)
lda #0
tax ! return zero
rts

66
mach/6500/libem/mul4.s Normal file
View file

@ -0,0 +1,66 @@
.define Mul4
! This subroutine multiplies two fourbyte signed integers.
! For more details see mli.s
! The only difference is that zeropage locations are twice as big.
Mul4:
3: lda #0
sta ARTH+8
sta ARTH+9
sta ARTH+10
sta ARTH+11
sta ARTH+12
sta ARTH+13
sta ARTH+14
sta ARTH+15 ! clear accumulator
ldy #32
1: lda #1h
bit ARTH
beq 2f ! multiplying by zero: no addition
clc
lda ARTH+12
adc ARTH+4
sta ARTH+12
lda ARTH+13
adc ARTH+5
sta ARTH+13
lda ARTH+14
adc ARTH+6
sta ARTH+14
lda ARTH+15
adc ARTH+7
sta ARTH+15
2: lsr ARTH+3
ror ARTH+2
ror ARTH+1
ror ARTH ! shift multiplier
lsr ARTH+15
ror ARTH+14
ror ARTH+13
ror ARTH+12
ror ARTH+11
ror ARTH+10
ror ARTH+9
ror ARTH+8 ! shift accumulator
lda UNSIGN
beq 3f ! it's unsigned: so no shift in of signbit
lda ARTH+7
bpl 3f
lda #40h
bit ARTH+15
beq 3f
lda ARTH+15
ora #80h
sta ARTH+15
3: dey
bne 1b
ldx ARTH+10
lda ARTH+11
jsr Push
ldx ARTH+8
lda ARTH+9
jmp Push

19
mach/6500/libem/ngi.s Normal file
View file

@ -0,0 +1,19 @@
.define Ngi2
! This subroutine negates the integer in registerpair AX.
! The negation is a one's complement plus one.
Ngi2:
eor #0FFh ! one's complement A
tay
txa
eor #0FFh ! one's complement X
tax
inx ! increment X
bne 1f
iny ! increment A if neccesairy
1: tya
rts

30
mach/6500/libem/ngi4.s Normal file
View file

@ -0,0 +1,30 @@
.define Ngi4
! This subroutine takes a fourbyte interger and negates it.
! For more details see ngi2.s
Ngi4:
sta ADDR+1
stx ADDR
ldy #3
1: lda (ADDR),y
eor #0FFh ! one's complement lowbyte+y
sta (ADDR),y
dey
bpl 1b
ldx #0FDh
iny
clc
lda (ADDR),y
adc #1
sta (ADDR),y ! lowbyte+y
1: iny
lda (ADDR),y
adc #0
sta (ADDR),y ! (lowbyte+y)+0
inx
bne 1b
rts

22
mach/6500/libem/print.s Normal file
View file

@ -0,0 +1,22 @@
.define Mprint
! This subroutine prints a zero terminated ascii string.
! The registerpair AX contains the start of the string.
! The subroutine WRCH is a special routine on the BBC microcomputer
! which prints the character in A to the screen.
! The subroutine WRCH is a special one provided by the BBC
! microcomputer.
Mprint:
stx ADDR ! start address of string (lowbyte)
sta ADDR+1 ! start address of string (highbyte)
ldy #0
1: lda (ADDR),y ! get ascii character
beq 2f
jsr WRCH ! put it on the screen
iny
bne 1b
2: rts

View file

@ -0,0 +1,27 @@
.define Printhex
! This subroutine print the contents of register A to the screen
! in hexadecimal form.
! The subroutine WRCH is a special one provided by the BBC
! microcomputer.
Printhex:
pha ! save A
lsr a
lsr a
lsr a
lsr a ! get four high bits
jsr 1f
pla ! restore A
and #0Fh ! get four low bits
jsr 1f
rts
1: sed ! print in hex
clc
adc #90h
adc #40h
cld
jmp WRCH

View file

@ -0,0 +1,44 @@
.define Printstack
! This a special subroutine which prints some things to the
! monitorscreen for debugging.
Printstack:
ldy #0
2: lda (hol0+4),y
beq 1f
jsr WRCH ! print filename
iny
jmp 2b
1: lda #32
jsr WRCH ! print a space
lda hol0+1
jsr Printhex ! print line number (highbyte)
lda hol0
jsr Printhex ! print line number (lowbyte)
lda #32
jsr WRCH ! print a space
lda SP+1
jsr Printhex ! print stackpointer (highbyte)
lda SP+2
jsr Printhex ! print stackpointer (lowbyte)
lda #32
jsr WRCH ! print a space
lda LB+1
jsr Printhex ! print real localbase (highbyte)
lda LB
jsr Printhex ! print real localbase (lowbyte)
lda #32
jsr WRCH ! print a space
lda LBl+1
jsr Printhex ! print second lowerbase (highbyte)
lda LBl
jsr Printhex ! print second lowerbase (lowbyte)
lda #10
jsr WRCH ! print a newline
lda #13
jsr WRCH ! print a carriagereturn
rts

28
mach/6500/libem/pro.s Normal file
View file

@ -0,0 +1,28 @@
.define Pro
! This routine is called at the entry of a procedure.
! It saves the localbase of the invoking procedure, and sets the
! new localbase to the present value of the stackpointer.
! It then initializes the second localbase by subtracting
! BASE from the real one.
Pro:
ldx LB ! get localbase (lowbyte)
lda LB+1 ! get localbase (highbyte)
jsr Push ! push localbase onto the stack
ldx SP+2 ! get stackpointer (lowbyte)
lda SP+1 ! get stackpointer (highbyte)
stx LB ! new localbase (lowbyte)
sta LB+1 ! new localbse (highbyte)
tay
txa
sec
sbc #BASE
sta LBl ! second localbase (lowbyte)
tya
sbc #0
sta LBl+1 ! second localbase (highbyte)
rts

32
mach/6500/libem/read.s Normal file
View file

@ -0,0 +1,32 @@
.define Mread
! This subroutine reads characters from the standard input.
! It ignores the filedes.
! It reads atmost 255 characters. So the runtime system must
! provide a way of dealing with this.
! The subroutine RDCH is a special one provided by the BBC
! microcomputer.
Mread:
jsr Pop ! ignore filedescriptor
jsr Pop ! bufptr
stx ADDR ! address of character buffer (lowbyte)
sta ADDR+1 ! address of character buffer (highbyte)
jsr Pop ! number of characters
ldy #0 ! <= 255
inx
1: jsr RDCH ! read a character from the current inputstream
bcs 8f
sta (ADDR),y
iny
dex
bne 1b
8: tya
tax
lda #0
jsr Push ! number of characters red.
tax ! report a succesfull read.
rts

43
mach/6500/libem/ret.s Normal file
View file

@ -0,0 +1,43 @@
.define Ret
! This subroutine stores the returnvalue in the return area.
! This area is in zeropage.
! The size of the object to be returned is in zeropage location
! RETSIZE.
! It also restores the localbases and the stackpointer of the
! invoking procedure.
Ret:
sty RETSIZE ! save returnsize
beq 1f ! the return size is zero
lda #0 ! address of returnvalue area (highbyte)
ldx #RETURN ! address of returnvalue area (lowbyte)
cpy #2
bne 2f
jsr Sti ! store word
jmp 1f
2: cpy #4
jsr Sdi ! store fourbyte word
1: ldx LB ! get old stackpointer (lowbyte)
stx SP+2
lda LB+1 ! get old stackpointer (highbyte)
sta SP+1
inc LB
inc LB
bne 1f
inc LB+1
1: jsr Pop ! get old localbase
stx LB ! localbase (lowbyte)
sta LB+1 ! localbase (highbyte)
pha
sec
txa
sbc #BASE
sta LBl ! second localbase (lowbyte)
pla
sbc #0
sta LBl+1 ! second localbase (highbyte)
rts

27
mach/6500/libem/rmi.s Normal file
View file

@ -0,0 +1,27 @@
.define Rmi2
! This subroutine returns the remainder of a twobyte signed division.
! The sign of the result is as specified in the emtest.
Rmi2:
ldy #0
sty NBYTES ! for the sign of the result
stx ARTH
sta ARTH+1 ! first operand
jsr Pop
stx ARTH+2
sta ARTH+3 ! second operand
ldy #0
sty UNSIGN ! its signed arithmetic
jsr Div
lsr ARTH+5
ror ARTH+4 ! result must be shifted one time
ldx ARTH+4
lda ARTH+5
ldy NBYTES
beq 1f ! result must be positive
jmp Ngi2
1: rts

28
mach/6500/libem/rmi4.s Normal file
View file

@ -0,0 +1,28 @@
.define Rmi4
! This subroutine returns the remainder of a fourbyte division.
Rmi4:
ldy #0
sty NBYTES ! for the sign of the result
ldy #0
sty UNSIGN ! it is signed arithmetic
jsr Div4
lsr ARTH+11
ror ARTH+10
ror ARTH+9
ror ARTH+8 ! result must be shifted one time
ldy NBYTES
beq 1f ! result is positive
lda #0
ldx #ARTH+8
jsr Ngi4
1: lda ARTH+11
ldx ARTH+10
jsr Push
lda ARTH+9
ldx ARTH+8
jmp Push

22
mach/6500/libem/rmu.s Normal file
View file

@ -0,0 +1,22 @@
.define Rmu2
! This subroutine returns the remainder of an twobyte unsigned
! integer division.
Rmu2:
stx ARTH
sta ARTH+1 ! first operand
jsr Pop
stx ARTH+2
sta ARTH+3 ! second operand
ldy #1
sty UNSIGN ! it unsigned
jsr Duv
lsr ARTH+5
ror ARTH+4 ! shift result one time
ldx ARTH+4
lda ARTH+5
rts

34
mach/6500/libem/rmu4.s Normal file
View file

@ -0,0 +1,34 @@
.define Rmu4
! This subroutine returns the remainder of a fourbyte unsigned
! division.
Rmu4:
ldy #1
sty UNSIGN ! its unsigned
jsr Pop
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
sta ARTH+3 ! second operand
jsr Pop
stx ARTH+4
sta ARTH+5
jsr Pop
stx ARTH+6
sta ARTH+7 ! first operand
jsr Duv4
lsr ARTH+11
ror ARTH+10
ror ARTH+9
ror ARTH+8 ! shift result one time
lda ARTH+11
ldx ARTH+10
jsr Push
lda ARTH+9
ldx ARTH+8
jmp Push

26
mach/6500/libem/rol.s Normal file
View file

@ -0,0 +1,26 @@
.define Rol
! This subroutine rotates left an integer n times
! N is in register X.
! The result is returned in registerpair AX.
Rol:
txa
bne 1f
jmp Pop ! zero rotate return input
1: tay ! Y contains number of rotates
jsr Pop
stx Ytmp ! save lowbyte
2: clc
rol Ytmp ! rotate lowbyte
rol a ! rotate highbyte
bcc 1f ! no carry
inc Ytmp ! put carry in rightmost bit
1: dey
bne 2b
ldx Ytmp ! store lowbyte in X
rts

33
mach/6500/libem/rol4.s Normal file
View file

@ -0,0 +1,33 @@
.define Rol4
! This subroutine rotates left a fourbyte integer n times.
! N is in register X.
Rol4:
txa
bne 1f ! a zero rotate skip
rts
1: tay
jsr Pop
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
sta ARTH+3
2: asl ARTH
rol ARTH+1
rol ARTH+2
rol ARTH+3 ! rotate left
bcc 1f
inc ARTH ! put carry in rightmost bit
1: dey
bne 2b
ldx ARTH+2
lda ARTH+3
jsr Push
ldx ARTH
lda ARTH+1
jmp Push

25
mach/6500/libem/ror.s Normal file
View file

@ -0,0 +1,25 @@
.define Ror
! This subroutine rotates right a integer twobyte word.
! The number of rotates is in X.
! The result is returned in registerpair AX.
Ror:
txa
bne 1f ! a zero rotate just return input
jmp Pop
1: tay
jsr Pop ! get word
stx Ytmp ! save lowbyte
2: clc
ror a ! rotate highbyte
ror Ytmp ! rotate lowbyte
bcc 1f ! no carry
ora #80h ! put carry in leftmost bit
1: dey
bne 2b
ldx Ytmp ! get lowbyte
rts

35
mach/6500/libem/ror4.s Normal file
View file

@ -0,0 +1,35 @@
.define Ror4
! This subroutine rotates right a fourbyte word.
! The number of rotates is in X.
Ror4:
txa
bne 1f ! a zero rotate skip
rts
1: tay
jsr Pop
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
sta ARTH+3
2: lsr ARTH+3 ! rotate word
ror ARTH+2
ror ARTH+1
ror ARTH
bcc 1f ! no carry
lda #80h ! put carry in leftmost bit
ora ARTH+3
sta ARTH+3
1: dey
bne 2b
lda ARTH+3
ldx ARTH+2
jsr Push
lda ARTH+1
ldx ARTH
jmp Push ! push result onto the stack

21
mach/6500/libem/rtt.s Normal file
View file

@ -0,0 +1,21 @@
.define Rtt
! This subroutine performs the return from trap.
Rtt:
ldy #0
jsr Ret ! restore old stackpointer and localbase
jsr Pop ! remove trapnumber
jsr Pop
sta hol0+1
stx hol0 ! restore linenumber
jsr Pop
sta hol0+5
stx hol0+4 ! restore filename pointer
lda #0
ldx #RETURN
jsr Sdi ! restore return area
rts

23
mach/6500/libem/sar.s Normal file
View file

@ -0,0 +1,23 @@
.define Sar
! This subroutine performs the SAR instruction.
! For details see rapport IR-81.
Sar:
jsr Aar ! get object address
ldy NBYTES+1 ! the size of the object (highbyte)
bne 2f
ldy NBYTES ! the size of the object (lowbyte)
cpy #1
bne 1f ! object size is one byte
jmp Sti1 ! put it in array
1: cpy #2
bne 1f ! object size is two bytes
jmp Sti ! put it in array
1: cpy #4
bne 2f ! object size is fourbytes
jmp Sdi ! put it in array
2: jmp Stil ! put it in array

21
mach/6500/libem/sbi.s Normal file
View file

@ -0,0 +1,21 @@
.define Sbi2
! This subroutine subtracts two twobyte signed integers
! and returnes the result in registerpair AX.
Sbi2:
stx ARTH ! save second operand (lowbyte)
sta ARTH+1 ! save second operand (highbyte)
jsr Pop
pha
sec
txa ! get first operand (lowbyte)
sbc ARTH ! subtract second operand (lowbyte)
tax
iny
pla ! get first operand (highbyte)
sbc ARTH+1 ! subtract second operand (highbyte)
rts

17
mach/6500/libem/sbi4.s Normal file
View file

@ -0,0 +1,17 @@
.define Sbi4
! This subroutine subtracts two fourbyte signed integers.
Sbi4:
jsr Addsub ! initiate addresses
sec
1: lda (ADDR+2),y ! get lowbyte+y first operand
sbc (ADDR),y ! subtract lowbyte+y second operand
sta (ADDR+2),y ! put on stack lowbyte+y result
iny
inx
bne 1b
rts

25
mach/6500/libem/sdl.s Normal file
View file

@ -0,0 +1,25 @@
.define Sdi, Sdo
! The subroutine Sdi takes a fourbyte word and stores it
! at the address in registerpair AX.
! If the address is in zeropage, Sdo is used.
Sdi:
stx ADDR ! address (lowbyte)
sta ADDR+1 ! address (highbyte)
Sdo:
ldy #0
1: jsr Pop
pha
txa
sta (ADDR),y ! store lowbyte
iny
pla
sta (ADDR),y ! store highbyte
iny
cpy #4
bne 1b
rts

36
mach/6500/libem/set.s Normal file
View file

@ -0,0 +1,36 @@
.define Set
! This subroutine creates a set of n (n <= 256) bytes.
! In this set a certain bit, which number is in registerpair AX,
! is set. The rest is zero.
Set:
stx ARTH ! save bitnumber (lowbyte)
sta ARTH+1 ! save bitnumber (highbyte)
jsr Zer ! create n zerobytes
lda ARTH
and #07h ! n mod 8 (bitnumber in byte)
tax
lda #1
cpx #0
beq 2f
1: asl a ! set bit (n mod 8)
dex
bne 1b
2: sta ARTH+2
ldx #3
1: lsr ARTH+1 ! shiftright n 3 times (= n div 8)
ror ARTH ! this is the bytenumber
dex
bne 1b
ldy ARTH ! load bytenumber
lda SP+1
ldx SP+2
stx ADDR ! address of set (lowbyte)
sta ADDR+1 ! address of set (highbyte)
lda ARTH+2 ! get bit
sta (ADDR),y ! store byte with bit on
rts

23
mach/6500/libem/sli.s Normal file
View file

@ -0,0 +1,23 @@
.define Sli2
! This subroutine shifts a signed or unsigned interger to the
! left n times.
! N is in register X.
! The returned value is in registerpair AX.
Sli2:
txa
bne 1f
jmp Pop ! zero shift, return input
1: tay
jsr Pop ! get integer
stx Ytmp ! save lowbyte
2: asl Ytmp
rol a ! shift left
dey
bne 2b
ldx Ytmp ! get lowbyte
rts

35
mach/6500/libem/sli4.s Normal file
View file

@ -0,0 +1,35 @@
.define Sli4
! This subroutine shift a signed or unsigned fourbyte integer
! n times left. N is in register X.
Sli4:
cpx #0
beq 9f ! zero shift, return input
lda SP+2 ! the shifting is done on the stack
sta ADDR ! address of integer (lowbyte)
lda SP+1
sta ADDR+1 ! address of integer (highbyte)
2: ldy #0
clc
lda (ADDR),y
rol a
sta (ADDR),y
iny
lda (ADDR),y
rol a
sta (ADDR),y
iny
lda (ADDR),y
rol a
sta (ADDR),y
iny
lda (ADDR),y
rol a
sta (ADDR),y ! shift left
dex
bne 2b
9: rts

40
mach/6500/libem/sri.s Normal file
View file

@ -0,0 +1,40 @@
.define Sri2, Sru2
! The subroutine Sri2 shifts a signed integer n times right.
! In the case of a negative integer there is signextension.
! The subroutine Sru2 shifts right an unsigned integer.
! The returned value is in registerpair AX.
Sru2:
txa
bne 1f
jmp Pop ! zero shift, return input
1: tay
jsr Pop ! get integer
stx Ytmp ! save lowbyte
jmp 2f ! shift unsigned
Sri2:
txa
bne 1f
jmp Pop ! zero shift, return input
1: tay
jsr Pop ! get integer
stx Ytmp ! save lowbyte
tax
bmi 1f ! negative signextended shift
2: lsr a
ror Ytmp ! shift not signextended
dey
bne 2b
ldx Ytmp ! get lowbyte
rts
1: sec ! shift signextended
ror a
ror Ytmp
dey
bne 1b
ldx Ytmp ! get lowbyte
rts

52
mach/6500/libem/sri4.s Normal file
View file

@ -0,0 +1,52 @@
.define Sri4, Sru4
! The subroutine Sri4 shifts a signed fourbyte integer to the
! right n times
! N is in register X.
! The subroutine Sru4 shifts an unsigned fourbyte integer to the
! right n times.
Sru4:
txa
tay
bne 1f
rts
1: jsr Pop
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
jmp 2f
Sri4:
txa
tay
bne 1f
rts
1: jsr Pop
stx ARTH
sta ARTH+1
jsr Pop
stx ARTH+2
tax
bmi 1f
2: lsr a
ror ARTH+2
ror ARTH+1
ror ARTH
dey
bne 2b
beq 4f
1: sec
ror a
ror ARTH+2
ror ARTH+1
ror ARTH
3: dey
bne 1b
4: ldx ARTH+2
jsr Push
lda ARTH+1
ldx ARTH
jmp Push

24
mach/6500/libem/sti.s Normal file
View file

@ -0,0 +1,24 @@
.define Sti, Sext, Stii
! The subroutine Sti stores an twobyte word at the address which
! is in registerpair AX.
! The subroutine Sext is used when the address is already in
! zeropage.
! The subroutine Stii is used when the address is in zeropage
! and the registerpair AX contains the word.
Sti:
stx ADDR ! address of word (lowbyte)
sta ADDR+1 ! address of word (highbyte)
Sext:
jsr Pop ! get word
Stii:
ldy #1
sta (ADDR),y ! store highbyte
dey
txa
sta (ADDR),y ! store lowbyte
rts

16
mach/6500/libem/sti1.s Normal file
View file

@ -0,0 +1,16 @@
.define Sti1
! This subroutine stores an onebyte wordfractional at the address
! which is in registerpair AX.
Sti1:
stx ADDR ! address of byte (lowbyte)
sta ADDR+1 ! address of byte (highbyte)
jsr Pop ! get byte
ldy #0
txa
sta (ADDR),y ! store byte
rts

26
mach/6500/libem/stil.s Normal file
View file

@ -0,0 +1,26 @@
.define Stil
! This subroutine stores indirect a block of bytes if
! the number of bytes is greater than four.
! The destination address is in registerpair AX.
! The lowbyte of the number of bytes is in Y,
! the highbyte is in zeropage location NBYTES+1.
Stil:
sta ADDR+3 ! destination address (highbyte)
stx ADDR+2 ! destination address (lowbyte)
sty NBYTES ! number of bytes (lowbyte)
clc
lda SP+2
sta ADDR ! source address (lowbyte)
adc NBYTES
sta SP+2 ! new stackpointer (lowbyte)
lda SP+1
sta ADDR+1 ! source address (highbyte)
adc NBYTES+1
sta SP+1 ! new stackpointer (highbyte)
inc NBYTES+1
jmp Blmnp ! do the move

17
mach/6500/libem/stl.s Normal file
View file

@ -0,0 +1,17 @@
.define Stl
! This subroutine performs the storage of a local which offset
! is to big.
Stl:
jsr Locaddr ! get the local address
jsr Pop ! get the word
ldy #1
sta (ADDR),y ! store highbyte
dey
txa
sta (ADDR),y ! store lowbyte
rts

28
mach/6500/libem/sts.s Normal file
View file

@ -0,0 +1,28 @@
.define Sts
! This subroutine stores indirect a number of bytes.
! The number of bytes is in the registerpair AX.
Sts:
cmp #0
bne 3f ! number of bytes > 255
cpx #1
bne 1f ! onebyte storage
jsr Pop ! get the address
jmp Sti1 ! store the byte
1: cpx #2
bne 2f ! twobyte storage
jsr Pop ! get the address
jmp Sti ! store the word
2: cpx #4
bne 3f ! fourbyte storage
jsr Pop ! get the address
jmp Sdi ! store the double word
3: sta ARTH+1 ! objectsize > 4
txa
tay
jsr Pop ! get address
jmp Stil ! store the object

20
mach/6500/libem/teq.s Normal file
View file

@ -0,0 +1,20 @@
.define Teq
! This subroutine test if the value in registerpair AX is zero
! or nonzero.
! The returned value, a 1 or a 0, is in AX.
Teq:
tay
beq 1f ! A is zero
2: lda #0 ! AX is zero
tax
rts
1: txa
bne 2b ! X is zero
lda #0 ! AX is nonzero
ldx #1
rts

19
mach/6500/libem/test2.s Normal file
View file

@ -0,0 +1,19 @@
.define Test2
! This subroutine tests if the value on top of the stack is 2.
! It is used if the size is on top of the stack.
! The word which is to be handled is returned in registerpair AX.
Test2:
tay
bne 1f ! value > 255
cpx #2
bne 1f ! value <> 2
jsr Pop ! get word
rts
1: ldx #Eoddz
lda #0
jsr Trap

23
mach/6500/libem/testFFh.s Normal file
View file

@ -0,0 +1,23 @@
.define TestFFh
! This subroutine tests if the value on top of the stack is <= 256.
! It is used if the istruction argument is on top of the stack.
! The value is saved in Y.
TestFFh:
cmp #2
bpl 1f ! value > 256
cmp #0
beq 2f
cpx #0
bne 1f ! value is zero
2: dex
txa
tay
rts
1: ldx #Eoddz
lda #0
jsr Trap

18
mach/6500/libem/tge.s Normal file
View file

@ -0,0 +1,18 @@
.define Tge
! This subroutine test if the value in registerpair AX is
! greater than or equal to zero.
! The result is returned in AX.
Tge:
tay
bpl 1f ! A >= 0
lda #0 ! AX < 0
tax
rts
1: lda #0 ! AX >= 0
ldx #1
rts

21
mach/6500/libem/tgt.s Normal file
View file

@ -0,0 +1,21 @@
.define Tgt
! This subroutine tests if the value in registerpair AX is
! greater than zero.
! The value returned is in AX.
Tgt:
tay
bpl 1f ! A >= 0
3: lda #0 ! AX <= 0
tax
rts
1: beq 1f ! A = 0
2: lda #0 ! AX > 0
ldx #1
rts
1: txa
bne 2b ! X > 0
beq 3b ! X = 0

22
mach/6500/libem/tle.s Normal file
View file

@ -0,0 +1,22 @@
.define Tle
! This subroutine tests if the value in registerpair AX is
! less than or equal to zero.
! The value returned is in AX.
Tle:
tay
bpl 1f ! A >= 0
3: lda #0 ! AX <= 0
ldx #1
rts
1: beq 1f ! A = 0
2: lda #0 ! AX > 0
tax
rts
1: txa
bne 2b ! X > 0
beq 3b ! x = 0

18
mach/6500/libem/tlt.s Normal file
View file

@ -0,0 +1,18 @@
.define Tlt
! This subroutine tests if the value in registerpair AX is
! less than zero.
! The value returned is in AX.
Tlt:
tay
bpl 1f ! A >= 0
lda #0 ! AX < 0
ldx #1
rts
1: lda #0 ! AX >= 0
tax
rts

20
mach/6500/libem/tne.s Normal file
View file

@ -0,0 +1,20 @@
.define Tne
! This subroutine tests if the value in registerpair AX is
! not equal to zero.
! The value returned is in AX.
Tne:
tay
beq 1f ! A = 0
2: lda #0 ! AX <> 0
ldx #1
rts
1: txa
bne 2b ! X <> 0
lda #0 ! AX = 0
tax
rts

134
mach/6500/libem/trap.s Normal file
View file

@ -0,0 +1,134 @@
.define Trap
! This subroutine performs the trap instruction.
Trap:
txa
cmp #64
bcc 1f
2: jmp Dotrap
1: bmi 2b
pha
lda IGNMASK ! get bitmask (lowbyte)
sta ARTH
lda IGNMASK+1 ! get bitmask (highbyte)
2: lsr a
ror ARTH ! shiftright bitmask n times
dex
bne 2b
lda #1
and ARTH
bne 3f
pla ! clear hardware_stack
jmp Dotrap
3: pla ! clear hardware_stack
rts
Dotrap:
sta TRAPVAL
lda #0
cmp ERRPROC+1
bne 1f ! ERRPROC <> 0 (highbyte)
cmp ERRPROC
bne 1f ! ERRPROC <> 0 (lowbyte)
jmp Mtrap
1: lda #0
ldx #RETURN
jsr Ldi ! save return area
lda hol0+5
ldx hol0+4
jsr Push ! save filename pointer
lda hol0+1
ldx hol0
jsr Push ! save linenumber
lda ERRPROC
sta ADDR ! address of errorhandler (lowbyte)
lda ERRPROC+1
sta ADDR+1 ! address of errorhandler (highbyte)
lda #0
sta ERRPROC ! reset ERRPROC (lowbyte)
sta ERRPROC+1 ! reset ERRPROC (highbyte)
ldx TRAPVAL
jsr Push
jmp (ADDR) ! proceed with errorhandler
Mtrap:
cpx #0
bne 1f
lda #[EARRAY].h
ldx #[EARRAY].l
jsr Mprint
jmp errorend
1: cpx #1
bne 1f
lda #[ERANGE].h
ldx #[ERANGE].l
jsr Mprint
jmp errorend
1: cpx #2
bne 1f
lda #[ESET].h
ldx #[ESET].l
jsr Mprint
jmp errorend
1: cpx #3
bne 1f
lda #[EIOVFL].h
ldx #[EIOVFL].l
jsr Mprint
jmp errorend
1: cpx #10
bne 1f
lda #[ECONV].h
ldx #[ECONV].l
jsr Mprint
jmp errorend
1: cpx #16
bne 1f
lda #[ESTACK].h
ldx #[ESTACK].l
jsr Mprint
jmp errorend
1: cpx #17
bne 1f
lda #[EHEAP].h
ldx #[EHEAP].l
jsr Mprint
jmp errorend
1: cpx #19
bne 1f
lda #[EODDZ].h
ldx #[EODDZ].l
jsr Mprint
jmp errorend
1: cpx #20
bne 1f
lda #[ECASE].h
ldx #[ECASE].l
jsr Mprint
jmp errorend
1: cpx #25
bne 1f
lda #[EBADMON].h
ldx #[EBADMON].l
jsr Mprint
jmp errorend
1: cpx #26
bne 1f
lda #[EBADLIN].h
ldx #[EBADLIN].l
jsr Mprint
jmp errorend
1: cpx #27
bne errorend
lda #[EBADGTO].h
ldx #[EBADGTO].l
jsr Mprint
errorend:
ldx STACK
dex
dex
txs
rts

34
mach/6500/libem/write.s Normal file
View file

@ -0,0 +1,34 @@
.define Mwrite
! This subroutine performs the monitor call write.
! Writing is always done to standardoutput.
! A zero is returned on exit.
! The subroutine WRCH is a special routine of the BBC
! microcomputer.
Mwrite:
jsr Pop ! get fildes
jsr Pop ! get address of characterbuffer
stx ADDR ! bufferaddress (lowbyte)
sta ADDR+1 ! bufferaddress (highbyte)
jsr Pop ! number of characters to be writen.
ldy #0
1: lda (ADDR),y
cmp #10
bne 2f
pha
lda #13
jsr WRCH
pla
2: jsr WRCH
iny
dex
bne 1b
tya
tax
lda #0
jsr Push
tax
rts

30
mach/6500/libem/xor.s Normal file
View file

@ -0,0 +1,30 @@
.define Xor
! This subroutine performs the exclusive or on two groups of bytes.
! The groups consists of atmost 254 bytes.
! The result is on top of the stack.
Xor:
lda SP+1
sta ADDR+1 ! address of first group (lowbyte)
lda SP+2
sta ADDR ! address of first group (highbyte)
clc
tya
adc SP+2
sta SP+2 ! new stackpointer (lowbyte)
sta ADDR+2 ! address of second group (lowbyte)
lda #0
adc SP+1
sta SP+1 ! new stackpointer (highbyte)
sta ADDR+3 ! address of second group (highbyte)
1: dey
lda (ADDR),y ! get byte first group
eor (ADDR+2),y ! exclusive or with byte second group
sta (ADDR+2),y ! restore result
tya
bne 1b
rts

20
mach/6500/libem/zer.s Normal file
View file

@ -0,0 +1,20 @@
.define Zer
! This subroutine puts n (n <=256) zero bytes on top of
! the stack.
! The number of bytes minus one is in Y.
Zer:
tya
lsr a ! number of bytes div 2
tay
iny
lda #0
tax
2: jsr Push ! push two bytes
dey
bne 2b
rts

18
mach/6500/libem/zri.s Normal file
View file

@ -0,0 +1,18 @@
.define Zrl, Zro
! The subroutine Zrl makes a local zero which offset is to big.
! The offset of the local is in registerpair AX.
! The subroutine Zro is used if the address is already in zeropage.
Zrl:
jsr Locaddr ! get address of local
Zro:
lda #0
tay
sta (ADDR),y ! lowbyte = 0
iny
sta (ADDR),y ! highbyte = 0
rts