mirror of
https://github.com/byteworksinc/ORCALib.git
synced 2025-01-31 02:29:51 +00:00
8533ea221c
This is normal for S16 programs or inits, and can happen with shell executables in certain cases like when being run from Prizm.
1041 lines
26 KiB
NASM
1041 lines
26 KiB
NASM
keep obj/cc
|
|
mcopy cc.macros
|
|
****************************************************************
|
|
*
|
|
* CC - C Specific Run Time Libraries
|
|
*
|
|
* October 1988
|
|
* Mike Westerfield
|
|
*
|
|
* Copyright 1988
|
|
* Byte Works, Inc.
|
|
*
|
|
****************************************************************
|
|
*
|
|
CC start dummy routine
|
|
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~CopyBF - Copy a bit field
|
|
* ~SaveBF - Save a bit field
|
|
*
|
|
* Inputs:
|
|
* addr - address to copy to
|
|
* bitDisp - displacement past the address
|
|
* bitNum - number of bits
|
|
* val - value to copy
|
|
*
|
|
****************************************************************
|
|
*
|
|
~CopyBF start
|
|
ret equ 2 return address
|
|
val equ 5 value to copy
|
|
bitNum equ 9 number of bits
|
|
bitDisp equ 11 displacement past the address
|
|
addr equ 13 address to copy to
|
|
|
|
lda #0 set the call type
|
|
bra lb1
|
|
~SaveBF entry
|
|
lda #1
|
|
lb1 phb
|
|
phk
|
|
plb
|
|
sta isSave
|
|
tsc set up the stack frame
|
|
phd
|
|
tcd
|
|
|
|
move4 val,lval save the value (for copybf only)
|
|
stz mask+2 set up the and mask
|
|
ldx bitNum
|
|
lda #0
|
|
lb2 sec
|
|
rol A
|
|
rol mask+2
|
|
dex
|
|
bne lb2
|
|
sta mask
|
|
and val and out extra bits in the mask
|
|
sta val
|
|
lda mask+2
|
|
and val+2
|
|
sta val+2
|
|
ldx bitDisp shift the mask and value
|
|
beq lb4
|
|
lda mask
|
|
lb3 asl A
|
|
rol mask+2
|
|
asl val
|
|
rol val+2
|
|
dex
|
|
bne lb3
|
|
sta mask
|
|
lb4 ldy #2 place the bits in memory
|
|
lda mask
|
|
eor #$FFFF
|
|
and [addr]
|
|
ora val
|
|
sta [addr]
|
|
lda mask+2
|
|
eor #$FFFF
|
|
and [addr],Y
|
|
ora val+2
|
|
sta [addr],Y
|
|
|
|
lda isSave branch based on call type
|
|
beq lb5
|
|
|
|
lda ret+1 return from save
|
|
sta addr+2
|
|
lda ret
|
|
sta addr+1
|
|
pld
|
|
plb
|
|
tsc
|
|
clc
|
|
adc #12
|
|
tcs
|
|
rtl
|
|
|
|
lb5 move4 lval,addr place the value back on the stack
|
|
lda ret+1 return from copy
|
|
sta bitDisp
|
|
lda ret
|
|
sta bitDisp-1
|
|
pld
|
|
plb
|
|
tsc
|
|
clc
|
|
adc #8
|
|
tcs
|
|
rtl
|
|
;
|
|
; local data
|
|
;
|
|
mask ds 4 bit mask
|
|
isSave ds 2 is the call a save? (or copy?)
|
|
lval ds 4 temp storage for val
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~C_ShutDown - do shut down peculiar to the C language
|
|
*
|
|
* Inputs:
|
|
* A - shell return code
|
|
*
|
|
****************************************************************
|
|
*
|
|
~C_ShutDown start
|
|
|
|
pha save the return code
|
|
jsr ~Exit do exit processing
|
|
pla quit
|
|
jml ~Quit
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~C_ShutDown2 - do shut down peculiar to the C language
|
|
*
|
|
* Inputs:
|
|
* A - shell return code
|
|
*
|
|
****************************************************************
|
|
*
|
|
~C_ShutDown2 start
|
|
|
|
pha save the return code
|
|
jsr ~Exit do exit processing
|
|
pla quit
|
|
jml ~RTL
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~C_StartUp - do startup peculiar to the C language
|
|
*
|
|
****************************************************************
|
|
*
|
|
~C_StartUp start
|
|
argv equ 11 argument vector
|
|
argc equ 9 argument count
|
|
cLine equ 1 command line address
|
|
|
|
TAB equ 9 TAB key code
|
|
|
|
phb remove our return address
|
|
phk
|
|
plb
|
|
plx
|
|
ply
|
|
pea targv|-16 make room for argc, argv
|
|
per targv (default argv = ptr to targv)
|
|
pea 0
|
|
phy put the return addr back on the stack
|
|
phx
|
|
ph4 ~CommandLine create some work space
|
|
tsc set up our stack frame
|
|
phd
|
|
tcd
|
|
|
|
stz ~ExitList no exit routines, yet
|
|
stz ~ExitList+2
|
|
case on
|
|
jsl ~InitIO reset standard I/O
|
|
case off
|
|
|
|
lda cLine if cLine == 0 then
|
|
ora cLine+2
|
|
bne lb0
|
|
stz targv argv[0] = NULL
|
|
stz targv+2
|
|
brl rtl exit
|
|
|
|
lb0 add4 cLine,#8 skip the shell identifier
|
|
ldx #0 count the arguments
|
|
txy
|
|
short M
|
|
* skip over white space
|
|
lb1 lda [cLine],Y
|
|
beq lb6
|
|
iny
|
|
cmp #' '
|
|
beq lb1
|
|
cmp #TAB
|
|
beq lb1
|
|
inx
|
|
cmp #'"'
|
|
beq lb3
|
|
|
|
* skip to next white space
|
|
lb2 anop
|
|
lda [cLine],y
|
|
beq lb6
|
|
iny
|
|
cmp #' '
|
|
beq lb1
|
|
cmp #TAB
|
|
beq lb1
|
|
bra lb2
|
|
|
|
* skip to next "
|
|
lb3 anop
|
|
lda [cLine],y
|
|
beq lb6
|
|
iny
|
|
cmp #'"'
|
|
beq lb1
|
|
bra lb3
|
|
|
|
|
|
lb6 long M
|
|
txa we need (X+1)*4 + strlen(cLine)+1 bytes
|
|
inc A
|
|
asl A
|
|
asl A
|
|
sta start
|
|
phy
|
|
sec
|
|
adc 1,S
|
|
ply
|
|
pha
|
|
pha
|
|
pea 0
|
|
pha
|
|
ph2 >~User_ID
|
|
ph2 #$C008
|
|
ph4 #0
|
|
_NewHandle
|
|
bcc lb7
|
|
puts #'Out of memory',cr=t,errout=t
|
|
lda #-1
|
|
jml ~Quit
|
|
|
|
lb7 pl4 argv get the pointer to the area
|
|
ldy #2
|
|
lda [argv],Y
|
|
tax
|
|
lda [argv]
|
|
sta targv
|
|
stx targv+2
|
|
clc get a pointer to the command line string
|
|
adc start
|
|
bcc lb8
|
|
inx
|
|
lb8 sta argv
|
|
stx argv+2
|
|
short M move the command line string
|
|
ldy #0
|
|
lb9 lda [cLine],Y
|
|
sta [argv],Y
|
|
beq lb10
|
|
iny
|
|
bra lb9
|
|
lb10 long M
|
|
move4 argv,cLine save the pointer
|
|
move4 targv,argv set up the pointer to argv
|
|
|
|
av1 lda [cLine] skip leading spaces
|
|
and #$00FF
|
|
beq av8
|
|
cmp #' '
|
|
beq av2
|
|
cmp #TAB
|
|
bne av3
|
|
av2 inc4 cLine
|
|
bra av1
|
|
av3 tax save the argument
|
|
cmp #'"' if the argument is quoted then
|
|
bne av4
|
|
inc4 cLine skip the quote
|
|
av4 ldy #2 save the address in argv
|
|
lda cLine
|
|
sta [argv]
|
|
lda cLine+2
|
|
sta [argv],Y
|
|
add4 argv,#4
|
|
inc argc inc the # of arguments
|
|
cpx #'"' if the string is quoted then
|
|
bne av6
|
|
av5 lda [cLine] skip to the next quote
|
|
and #$00FF
|
|
beq av8
|
|
cmp #'"'
|
|
beq av7
|
|
inc4 cLine
|
|
bra av5 else
|
|
av6 lda [cLine] skip to the next whitespace char
|
|
and #$00FF
|
|
beq av8
|
|
cmp #' '
|
|
beq av7
|
|
cmp #TAB
|
|
beq av7
|
|
inc4 cLine
|
|
bra av6
|
|
av7 short M null terminate the parameter
|
|
lda #0
|
|
sta [cLine]
|
|
long M
|
|
bra av2 get the next parameter
|
|
av8 lda #0 null terminate the arg list
|
|
sta [argv]
|
|
ldy #2
|
|
sta [argv],Y
|
|
move4 targv,argv set up the pointer to argv
|
|
|
|
rtl pld return
|
|
pla
|
|
pla
|
|
plb
|
|
rtl
|
|
|
|
targv ds 4
|
|
start ds 2 start of the command line string
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~C_StartUp2 - do C startup for RTL pragma programs
|
|
*
|
|
****************************************************************
|
|
*
|
|
~C_StartUp2 start
|
|
|
|
phb remove our return address
|
|
phk
|
|
plb
|
|
plx
|
|
ply
|
|
pea targv|-16 set argc = 0, argv to point to targv
|
|
per targv
|
|
pea 0
|
|
phy put the return addr back on the stack
|
|
phx
|
|
|
|
stz ~ExitList no exit routines, yet
|
|
stz ~ExitList+2
|
|
|
|
stz targv argv[0] = NULL
|
|
stz targv+2
|
|
|
|
plb return
|
|
rtl
|
|
|
|
targv ds 4
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~Exit - call exit routines and clean up open files
|
|
*
|
|
* Inputs:
|
|
* ~ExitList - list of exit routines
|
|
*
|
|
****************************************************************
|
|
*
|
|
~Exit start
|
|
ptr equ 3 pointer to exit routines
|
|
;
|
|
; Set up our stack frame
|
|
;
|
|
phb
|
|
phk
|
|
plb
|
|
ph4 ~ExitList set up our stack frame
|
|
phd
|
|
tsc
|
|
tcd
|
|
;
|
|
; Call the exit functions
|
|
;
|
|
lb1 lda ptr if the pointer is non-nil then
|
|
ora ptr+2
|
|
beq lb3
|
|
pea +(lb2-1)|-8 call the function
|
|
pea +(lb2-1)|8
|
|
phb
|
|
pla
|
|
ldy #5
|
|
lda [ptr],Y
|
|
pha
|
|
dey
|
|
dey
|
|
lda [ptr],Y
|
|
pha
|
|
phb
|
|
pla
|
|
rtl
|
|
lb2 ldy #2 dereference the pointer
|
|
lda [ptr],Y
|
|
tax
|
|
lda [ptr]
|
|
sta ptr
|
|
stx ptr+2
|
|
bra lb1
|
|
;
|
|
; Close (and flush) any open files
|
|
;
|
|
case on
|
|
lb3 lda >stderr+6 while there is a next file
|
|
ora >stderr+4
|
|
beq lb4
|
|
ph4 >stderr+4 close it
|
|
dc h'22' (jsl fclose, soft reference)
|
|
dc s3'fclose'
|
|
bra lb3
|
|
case off
|
|
;
|
|
; return
|
|
;
|
|
lb4 pld return
|
|
pla
|
|
pla
|
|
plb
|
|
rts
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~ExitList - list of exit routines
|
|
*
|
|
****************************************************************
|
|
*
|
|
~ExitList start
|
|
ds 4
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~IntChkC - check for integer math error
|
|
*
|
|
* Inputs:
|
|
* V - set for error
|
|
*
|
|
****************************************************************
|
|
*
|
|
~IntChkC start
|
|
|
|
bvc lb1 branch if no error
|
|
php
|
|
pha
|
|
phx
|
|
phy
|
|
error #9 integer math error
|
|
ply
|
|
plx
|
|
pla
|
|
plp
|
|
lb1 rtl
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~LoadBF - load a bit field
|
|
*
|
|
* Inputs:
|
|
* addr - address to load from
|
|
* bitDisp - displacement past the address
|
|
* bitNum - number of bits
|
|
*
|
|
****************************************************************
|
|
*
|
|
~LoadBF start
|
|
mask equ 1 bit mask
|
|
sign equ 5 sign mask
|
|
|
|
csubroutine (2:bitNum,2:bitDisp,4:addr),8
|
|
|
|
ldy #2 get the value
|
|
lda [addr],Y
|
|
tax
|
|
lda [addr]
|
|
sta addr
|
|
stx addr+2
|
|
ldx bitDisp normalize the value
|
|
beq lb2
|
|
lb1 lsr addr+2
|
|
ror addr
|
|
dex
|
|
bne lb1
|
|
lb2 stz mask form the bit and sign mask
|
|
lda #-1
|
|
sta sign
|
|
sta sign+2
|
|
lda #0
|
|
ldx bitNum
|
|
lb3 sec
|
|
rol A
|
|
rol mask
|
|
asl sign
|
|
rol sign+2
|
|
dex
|
|
bne lb3
|
|
sec adjust the sign flag
|
|
ror sign+2
|
|
ror sign
|
|
and addr and out the extra bits
|
|
sta addr
|
|
lda mask
|
|
and addr+2
|
|
sta addr+2
|
|
lda addr if the value is negative then
|
|
and sign
|
|
bne lb4
|
|
lda addr+2
|
|
and sign+2
|
|
beq lb5
|
|
lb4 lda addr or in the sign bits
|
|
ora sign
|
|
sta addr
|
|
lda addr+2
|
|
ora sign+2
|
|
sta addr+2
|
|
|
|
lb5 creturn 4:addr
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~LoadStruct - load a long value onto the stack
|
|
*
|
|
* Inputs:
|
|
* addr - address of the structure to load
|
|
* size - size of the structure
|
|
*
|
|
****************************************************************
|
|
*
|
|
~LoadStruct start
|
|
|
|
phb save the caller's data bank
|
|
pl4 >ret get the return address
|
|
plx get the transfer size
|
|
pla get the absolute save addr
|
|
sta >ad1+1
|
|
sta >ad2+1
|
|
plb set the data bank
|
|
phb remove the data bank & extra addr byte
|
|
pla
|
|
|
|
txa quit if there are no bytes to move
|
|
beq lb3
|
|
|
|
lsr a branch if the # of bytes is even
|
|
bcc lb1
|
|
dex move one byte
|
|
short M
|
|
ad1 lda ad1,X
|
|
pha
|
|
long M
|
|
txa
|
|
beq lb3
|
|
|
|
lb1 dex move the words
|
|
dex
|
|
bmi lb3
|
|
ad2 lda ad2,X
|
|
pha
|
|
bra lb1
|
|
|
|
lb3 ph4 >ret return to the caller
|
|
plb
|
|
rtl
|
|
;
|
|
; Local data
|
|
;
|
|
ret ds 4
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~LoadUBF - load an unsigned bit field
|
|
*
|
|
* Inputs:
|
|
* addr - address to load from
|
|
* bitDisp - displacement past the address
|
|
* bitNum - number of bits
|
|
*
|
|
****************************************************************
|
|
*
|
|
~LoadUBF start
|
|
mask equ 1 msw of bit mask
|
|
|
|
csubroutine (2:bitNum,2:bitDisp,4:addr),2
|
|
|
|
ldy #2 get the value
|
|
lda [addr],Y
|
|
tax
|
|
lda [addr]
|
|
sta addr
|
|
stx addr+2
|
|
ldx bitDisp normalize the value
|
|
beq lb2
|
|
lb1 lsr addr+2
|
|
ror addr
|
|
dex
|
|
bne lb1
|
|
lb2 stz mask form the bit mask
|
|
lda #0
|
|
ldx bitNum
|
|
lb3 sec
|
|
rol A
|
|
rol mask
|
|
dex
|
|
bne lb3
|
|
and addr and out the extra bits
|
|
sta addr
|
|
lda mask
|
|
and addr+2
|
|
sta addr+2
|
|
|
|
creturn 4:addr
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~LongMove2 - move some bytes
|
|
*
|
|
* Inputs:
|
|
* source - pointer to source bytes
|
|
* dest - pointer to destination bytes
|
|
* len - number of bytes to move
|
|
*
|
|
* Notes:
|
|
* This subroutine leaves the destination address on the
|
|
* stack. It is used by C for multiple assignment of
|
|
* arrays and structures. It differs from ~Move2 in that
|
|
* it can move 64K or more.
|
|
*
|
|
****************************************************************
|
|
*
|
|
~LongMove2 start
|
|
|
|
csubroutine (4:len,4:source),0
|
|
dest equ source+4
|
|
|
|
ldx len+2 move whole banks
|
|
beq lm2
|
|
ldy #0
|
|
lm1 lda [source],Y
|
|
sta [dest],Y
|
|
dey
|
|
dey
|
|
bne lm1
|
|
inc source+2
|
|
inc dest+2
|
|
dex
|
|
bne lm1
|
|
lm2 lda len move one byte if the move length is odd
|
|
lsr a
|
|
bcc lb1
|
|
short M
|
|
lda [source]
|
|
sta [dest]
|
|
long M
|
|
inc4 source
|
|
inc4 dest
|
|
dec len
|
|
lb1 ldy len move the bytes
|
|
beq lb4
|
|
dey
|
|
dey
|
|
beq lb3
|
|
lb2 lda [source],Y
|
|
sta [dest],Y
|
|
dey
|
|
dey
|
|
bne lb2
|
|
lb3 lda [source]
|
|
sta [dest]
|
|
lb4 creturn
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~LShr4 - Shift an unsigned long value right
|
|
*
|
|
* Inputs:
|
|
* A - value to shift
|
|
* X - # bits to shift by
|
|
*
|
|
* Outputs:
|
|
* A - result
|
|
*
|
|
****************************************************************
|
|
*
|
|
~LShr4 start
|
|
num1 equ 8 number to shift
|
|
num2 equ 4 # bits to shift by
|
|
|
|
tsc set up DP
|
|
phd
|
|
tcd
|
|
lda num2+2 if num2 < 0 then
|
|
bpl lb2
|
|
cmp #$FFFF shift left
|
|
bne zero
|
|
ldx num2
|
|
cpx #-34
|
|
blt zero
|
|
lb1 asl num1
|
|
rol num1+2
|
|
inx
|
|
bne lb1
|
|
bra lb4
|
|
zero stz num1 (result is zero)
|
|
stz num1+2
|
|
bra lb4
|
|
lb2 bne zero else shift right
|
|
ldx num2
|
|
beq lb4
|
|
cpx #33
|
|
bge zero
|
|
lb3 lsr num1+2
|
|
ror num1
|
|
dex
|
|
bne lb3
|
|
|
|
lb4 lda 0 fix stack and return
|
|
sta num2
|
|
lda 2
|
|
sta num2+2
|
|
pld
|
|
pla
|
|
pla
|
|
rtl
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~Move2 - move some bytes
|
|
*
|
|
* Inputs:
|
|
* source - pointer to source bytes
|
|
* dest - pointer to destination bytes
|
|
* len - number of bytes to move
|
|
*
|
|
* Notes:
|
|
* This subroutine leaves the destination address on the
|
|
* stack. It is used by C for multiple assignment of
|
|
* arrays and structures.
|
|
*
|
|
****************************************************************
|
|
*
|
|
~Move2 start
|
|
|
|
csubroutine (2:len,4:source),0
|
|
dest equ source+4
|
|
|
|
lda len move one byte if the move length is odd
|
|
lsr a
|
|
bcc lb1
|
|
short M
|
|
lda [source]
|
|
sta [dest]
|
|
long M
|
|
inc4 source
|
|
inc4 dest
|
|
dec len
|
|
lb1 ldy len move the bytes
|
|
beq lb4
|
|
dey
|
|
dey
|
|
beq lb3
|
|
lb2 lda [source],Y
|
|
sta [dest],Y
|
|
dey
|
|
dey
|
|
bne lb2
|
|
lb3 lda [source]
|
|
sta [dest]
|
|
lb4 creturn
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* extern pascal PDosInt(int callNum, void *parm)
|
|
*
|
|
* Make a ProDOS or shell call
|
|
*
|
|
* Inputs:
|
|
* callNum - ProDOS call number
|
|
* parm - address of the parameter block
|
|
*
|
|
****************************************************************
|
|
*
|
|
PDOSINT start
|
|
ProDOS equ $E100A8
|
|
|
|
csubroutine (4:parm,2:callNum),0
|
|
|
|
lda callNum
|
|
sta >lb1
|
|
lda parm
|
|
sta >lb2
|
|
lda parm+2
|
|
sta >lb2+2
|
|
jsl ProDOS
|
|
lb1 ds 2
|
|
lb2 ds 4
|
|
sta >~TOOLERROR
|
|
|
|
creturn
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~UDiv4 - Four byte unsigned integer divide
|
|
*
|
|
* Inputs:
|
|
* num1 - numerator
|
|
* X-A - denominator
|
|
*
|
|
* Outputs:
|
|
* ans - result
|
|
*
|
|
****************************************************************
|
|
*
|
|
~UDiv4 start
|
|
num1 equ 12 arguments
|
|
ans equ 1 answer
|
|
rem equ 5 remainder
|
|
return equ 9
|
|
;
|
|
; Initialize
|
|
;
|
|
tay place the values in the correct spot
|
|
pea 0 on the stack frame
|
|
pea 0
|
|
lda 10,S
|
|
pha
|
|
lda 10,S
|
|
pha
|
|
tsc set up DP
|
|
phd
|
|
tcd
|
|
sty num1
|
|
stx num1+2
|
|
tya check for division by zero
|
|
ora num1+2
|
|
beq dv10
|
|
|
|
lda num1+2 do 16 bit divides separately
|
|
ora ans+2
|
|
beq dv5
|
|
;
|
|
; 32 bit divide
|
|
;
|
|
ldy #32 32 bits to go
|
|
dv3 asl ans roll up the next number
|
|
rol ans+2
|
|
rol ans+4
|
|
rol ans+6
|
|
sec subtract for this digit
|
|
lda ans+4
|
|
sbc num1
|
|
tax
|
|
lda ans+6
|
|
sbc num1+2
|
|
bcc dv4 branch if minus
|
|
stx ans+4 turn the bit on
|
|
sta ans+6
|
|
inc ans
|
|
dv4 dey next bit
|
|
bne dv3
|
|
bra dv9 go do the sign
|
|
;
|
|
; 16 bit divide
|
|
;
|
|
dv5 lda #0 initialize the remainder
|
|
ldy #16 16 bits to go
|
|
dv6 asl ans roll up the next number
|
|
rol a
|
|
sec subtract the digit
|
|
sbc num1
|
|
bcs dv7
|
|
adc num1 digit is 0
|
|
dey
|
|
bne dv6
|
|
bra dv8
|
|
dv7 inc ans digit is 1
|
|
dey
|
|
bne dv6
|
|
|
|
dv8 sta ans+4 save the remainder
|
|
;
|
|
; Return the result
|
|
;
|
|
dv9 move4 ans,num1 move answer
|
|
dv10 pld return
|
|
tsc
|
|
clc
|
|
adc #8
|
|
tcs
|
|
rtl
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~UMod4 - Four byte unsigned integer remainder
|
|
*
|
|
* Inputs:
|
|
* num1 - numerator
|
|
* X-A - denominator
|
|
*
|
|
* Outputs:
|
|
* ans - result
|
|
*
|
|
****************************************************************
|
|
*
|
|
~UMod4 start
|
|
num1 equ 12 arguments
|
|
ans equ 1 answer
|
|
rem equ 5 remainder
|
|
return equ 9
|
|
;
|
|
; Initialize
|
|
;
|
|
tay place the values in the correct spot
|
|
pea 0 on the stack frame
|
|
pea 0
|
|
lda 10,S
|
|
pha
|
|
lda 10,S
|
|
pha
|
|
tsc set up DP
|
|
phd
|
|
tcd
|
|
sty num1
|
|
stx num1+2
|
|
tya check for division by zero
|
|
ora num1+2
|
|
beq dv10
|
|
|
|
lda num1+2 do 16 bit divides separately
|
|
ora ans+2
|
|
beq dv5
|
|
;
|
|
; 32 bit divide
|
|
;
|
|
ldy #32 32 bits to go
|
|
dv3 asl ans roll up the next number
|
|
rol ans+2
|
|
rol ans+4
|
|
rol ans+6
|
|
sec subtract for this digit
|
|
lda ans+4
|
|
sbc num1
|
|
tax
|
|
lda ans+6
|
|
sbc num1+2
|
|
bcc dv4 branch if minus
|
|
stx ans+4 turn the bit on
|
|
sta ans+6
|
|
inc ans
|
|
dv4 dey next bit
|
|
bne dv3
|
|
bra dv9 go do the sign
|
|
;
|
|
; 16 bit divide
|
|
;
|
|
dv5 lda #0 initialize the remainder
|
|
ldy #16 16 bits to go
|
|
dv6 asl ans roll up the next number
|
|
rol a
|
|
sec subtract the digit
|
|
sbc num1
|
|
bcs dv7
|
|
adc num1 digit is 0
|
|
dey
|
|
bne dv6
|
|
bra dv8
|
|
dv7 inc ans digit is 1
|
|
dey
|
|
bne dv6
|
|
|
|
dv8 sta ans+4 save the remainder
|
|
;
|
|
; Return the result
|
|
;
|
|
dv9 move4 ans+4,num1 move answer
|
|
dv10 pld return
|
|
tsc
|
|
clc
|
|
adc #8
|
|
tcs
|
|
rtl
|
|
end
|
|
|
|
****************************************************************
|
|
*
|
|
* ~Zero - zero an area of direct page memory
|
|
*
|
|
* Inputs:
|
|
* addr - address of the memory
|
|
* size - number of bytes to zero (must be > 1)
|
|
*
|
|
****************************************************************
|
|
*
|
|
~Zero start
|
|
|
|
csubroutine (2:size,4:addr),0
|
|
|
|
lda #0
|
|
sta [addr]
|
|
ldx addr
|
|
txy
|
|
iny
|
|
lda size
|
|
dea
|
|
dea
|
|
phb
|
|
mvn 0,0
|
|
plb
|
|
|
|
creturn
|
|
end
|