mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-12-01 02:51:04 +00:00
341 lines
8.9 KiB
Plaintext
341 lines
8.9 KiB
Plaintext
;
|
|
; File: SWIMIOP.aii
|
|
;
|
|
; Contains: Interface between the Kernel and Drivers for the SWIM IOP.
|
|
;
|
|
; Written by: Gary G. Davidian
|
|
;
|
|
; Copyright: © 1987-1990 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <2> 1/2/90 GGD NEEDED FOR ZONE-5: Adding Idle Loop Task Dispatching.
|
|
; <1.3> 11/2/89 GGD NEEDED FOR ZONE-5 Moved the routines HandleDMA1Int,
|
|
; HandleDMA2Int, SWIMShutDown, SWIMStopPolling, and SWIMGetIcon
|
|
; into SWIMDriver.aii
|
|
; <1.2> 7/8/89 CCH Added EASE comments to file.
|
|
; <•1.1> 6/15/89 GGD Updated to use equates for the latest rev of the IOP chip,
|
|
; re-formated tab stops in source.
|
|
; <1.0> 11/9/88 CCH Adding to EASE.
|
|
;
|
|
; To Do:
|
|
;
|
|
eject
|
|
title 'SWIM IOP - Kernel / Driver Interface for the SWIM IOP'
|
|
|
|
machine m65C02
|
|
codechk off
|
|
datachk off
|
|
longa off
|
|
longi off
|
|
print nomdir
|
|
include 'IOPDefs.aii'
|
|
include 'SWIMDefs.aii'
|
|
title 'SWIM IOP - Initialization and Unused Interrupt Handlers'
|
|
|
|
import InitADBDrvr
|
|
import InitSWIMDrvr
|
|
entry Primes
|
|
|
|
seg 'code'
|
|
SWIMIOP proc
|
|
|
|
export InitDrivers
|
|
InitDrivers lda #1*SCCISM+1*BYPASS
|
|
sta SCCControlReg ; initialize SCC Control Reg
|
|
lda #SwimIOCtlReg
|
|
sta IOControlReg ; initialize I/O Control Reg
|
|
lda #3 ; max send / receive
|
|
sta RCVMsgMax ; initialize receive max
|
|
sta XMTMsgMax ; initialize transmit max
|
|
jsr InitADBDrvr ; initialize the ADB Driver
|
|
jmp InitSWIMDrvr ; initialize the SWIM Driver and return
|
|
|
|
export HandleSCCInt
|
|
export HandleXMTMsg4
|
|
export HandleXMTMsg5
|
|
export HandleXMTMsg6
|
|
export HandleXMTMsg7
|
|
export HandleRCVMsg1
|
|
export HandleRCVMsg4
|
|
export HandleRCVMsg5
|
|
export HandleRCVMsg6
|
|
export HandleRCVMsg7
|
|
|
|
HandleSCCInt
|
|
HandleXMTMsg4
|
|
HandleXMTMsg5
|
|
HandleXMTMsg6
|
|
HandleXMTMsg7
|
|
HandleRCVMsg1
|
|
HandleRCVMsg4
|
|
HandleRCVMsg5
|
|
HandleRCVMsg6
|
|
HandleRCVMsg7
|
|
|
|
Unimplemented brk
|
|
bra Unimplemented
|
|
|
|
|
|
export RunIdleTasks
|
|
RunIdleTasks pha
|
|
phx
|
|
phy
|
|
jsr Primes ; look for primes
|
|
jsr @unused ; reserve space to patch in
|
|
jsr @unused ; a few more tasks
|
|
jsr @unused
|
|
ply
|
|
plx
|
|
pla
|
|
@unused rts
|
|
|
|
endproc
|
|
title 'SWIM IOP - Idle Task for Prime Number Computations'
|
|
|
|
ResultWidth equ 32
|
|
|
|
|
|
; Page zero variables
|
|
|
|
seg 'zdata'
|
|
PrimeVarsZ record
|
|
Remainder ds.b 1 ; byte
|
|
Numerator ds.b 4 ; long
|
|
endr
|
|
|
|
seg 'data'
|
|
PrimeVars record
|
|
PrimeVarsStart equ *
|
|
ds.b 1 ; 1 byte of padding for logic analyzer alignment
|
|
|
|
PrimesFound ds.b 4 ; long
|
|
PrimesFoundOff equ *-PrimeVarsStart
|
|
|
|
HighestPrime ds.b 4 ; long
|
|
HighestPrimeOff equ *-PrimeVarsStart
|
|
|
|
CurrentDenom ds.b 2 ; word
|
|
CurrentDenomOff equ *-PrimeVarsStart
|
|
|
|
ds.b 2 ; word
|
|
MaxDenom ds.b 2 ; word (2 bytes of zeros needed before)
|
|
MaxDenomOff equ *-PrimeVarsStart ; (2 bytes of zeros needed after)
|
|
ds.b 2 ; word
|
|
PossiblePrime ds.b 4 ; long (1 byte of zeros needed before)
|
|
PossiblePrimeOff equ *-PrimeVarsStart
|
|
|
|
MaxDenomSquared ds.b 4 ; long
|
|
MaxDenomSquaredOff equ *-PrimeVarsStart
|
|
|
|
PrimeVarsSize equ *-PrimeVarsStart ; number of bytes of PrimeVars
|
|
endr
|
|
|
|
|
|
|
|
seg 'code'
|
|
Primes proc
|
|
with PrimeVarsZ,PrimeVars; globals used throughout
|
|
|
|
; Depends upon memory being initialized to zeros at reset
|
|
|
|
lda CurrentDenom+1 ; get the last denom used
|
|
lsr a ; test the low bit
|
|
bcs Resume ; if odd, resume the computations
|
|
bne Suspend ; if even and non-zero, we found all primes
|
|
; if zero, it's initialization time
|
|
lda #3
|
|
sta PossiblePrime+3 ; PossiblePrime := 3
|
|
sta MaxDenom+1 ; MaxDenom := 3
|
|
lda #9
|
|
sta MaxDenomSquared+3 ; MaxDenomSquared := 9
|
|
inc PrimesFound+3 ; PrimesFound := 1
|
|
|
|
FoundPrime ldx #PossiblePrimeOff
|
|
ldy #HighestPrimeOff
|
|
jsr MoveLong ; HighestPrime := PossiblePrime
|
|
|
|
ldy #PrimesFoundOff
|
|
lda #1
|
|
jsr AddImmedLong ; PrimesFound := PrimesFound + 1
|
|
bra TryNextPossible ; goto TryNextPossible
|
|
|
|
PrimeCheckLoop ldy #CurrentDenomOff
|
|
lda #2
|
|
jsr AddImmedWord ; CurrentDenom := CurrentDenom + 2
|
|
|
|
CheckForPrime ldx #CurrentDenomOff
|
|
ldy #MaxDenomOff
|
|
jsr TestEqualWord ; if CurrentDenom = MaxDenom
|
|
beq FoundPrime ; then goto FoundPrime
|
|
|
|
; Before each divide, we return to the Idle Loop to give other tasks a chance
|
|
|
|
Suspend rts ; go back to idle loop
|
|
Resume ; retuned from idle loop
|
|
|
|
if ResultWidth <= 16 then
|
|
; Remainder := PossiblePrime MOD CurrentDenom
|
|
lda PossiblePrime+3 ; Numerator := PossiblePrime
|
|
sta <Numerator+3
|
|
lda PossiblePrime+2
|
|
sta <Numerator+2
|
|
|
|
lda #0 ; Remainder := 0
|
|
|
|
ldy #16 ; loop counter for 16/8 remainder
|
|
|
|
@RemLoop rol <Numerator+3 ; Shift Numerator into Remainder
|
|
rol <Numerator+2
|
|
rol a
|
|
bcs @RemSub
|
|
|
|
cpa CurrentDenom+1 ; compare denominator
|
|
blt @RemNext ; If Remainder < CurrentDenom, leave it
|
|
|
|
@RemSub sbc CurrentDenom+1 ; Remainder := Remainder - CurrentDenom
|
|
|
|
@RemNext dey ; decrement loop counter
|
|
bne @RemLoop ; loop for all 32 bits
|
|
|
|
tax ; test remainder for zero
|
|
; if PossiblePrime mod CurrentDenom <> 0
|
|
bne PrimeCheckLoop ; then goto PrimeCheckLoop
|
|
else
|
|
; Remainder := PossiblePrime MOD CurrentDenom
|
|
ldx #5 ; loop count/index for 5 byte copy
|
|
@RemCopyLoop lda PossiblePrime-1-1,x ; Numerator := PossiblePrime
|
|
sta <Remainder-1,x ; Remainder := 0
|
|
dex ; update loop count/index
|
|
bne @RemCopyLoop ; loop through all 5 bytes
|
|
|
|
ldy #32+1 ; loop counter for 32/15 remainder
|
|
* ldx #0 ; Remainder := 0 (from dex above)
|
|
|
|
@RemLoop txa ; get low byte of remainder
|
|
dey ; decrement loop counter
|
|
beq @RemDone ; loop for all 32 bits
|
|
|
|
@RemShift rol <Numerator+3 ; Shift Numerator into Remainder
|
|
rol <Numerator+2
|
|
rol <Numerator+1
|
|
rol <Numerator+0
|
|
rol a
|
|
tax
|
|
rol <Remainder+0
|
|
|
|
cpx CurrentDenom+1 ; compare low byte of remainder
|
|
lda <Remainder+0 ; get high byte of remainder
|
|
sbc CurrentDenom+0 ; subtract denominator
|
|
blt @RemLoop ; If Remainder < CurrentDenom, leave it
|
|
|
|
sta <Remainder+0 ; Remainder := Remainder - CurrentDenom
|
|
* sec ; setup carry for subtraction
|
|
txa ; get low byte of remainder
|
|
sbc CurrentDenom+1 ; subtract denominator
|
|
dey ; decrement loop counter
|
|
bne @RemShift ; loop for all 32 bits
|
|
|
|
@RemDone ora <Remainder+0 ; if PossiblePrime mod CurrentDenom <> 0
|
|
bne PrimeCheckLoop ; then goto PrimeCheckLoop
|
|
endif
|
|
|
|
TryNextPossible lda #3
|
|
sta CurrentDenom+1
|
|
stz CurrentDenom+0 ; CurrentDenom := 3
|
|
|
|
ldy #PossiblePrimeOff
|
|
lda #2
|
|
jsr AddImmedLong ; PossiblePrime := PossiblePrime + 2
|
|
|
|
ldx #PossiblePrimeOff
|
|
ldy #MaxDenomSquaredOff
|
|
jsr TestEqualLong ; if PossiblePrime <> MaxDenomSquared
|
|
bne CheckForPrime ; then goto CheckForPrime
|
|
|
|
ldy #MaxDenomOff
|
|
lda #2
|
|
if ResultWidth <= 16 then
|
|
jsr AddImmedByte ; MaxDenom := MaxDenom + 2
|
|
bne Done ; if carry out, we're done
|
|
else
|
|
; The divide algorithm used only allows 15 bit denominators, it would be
|
|
; considerrably slower and bigger to handle all 16 bits, so we exit when we
|
|
; reach 16 bits, which allows prime checking up to $3FFF0001 (1,073,676,289)
|
|
jsr AddImmedWord ; MaxDenom := MaxDenom + 2
|
|
lda MaxDenom ; see if carry into sign bit
|
|
bmi Done ; if negative, we're done
|
|
endif
|
|
|
|
; MaxDenomSquared := MaxDenom * MaxDenom
|
|
|
|
ldx #MaxDenomOff+2 ; MaxDenom High, Zeros Low
|
|
ldy #MaxDenomSquaredOff
|
|
jsr MoveLong ; MaxDenomSquared := MaxDenom High, Zeros Low
|
|
|
|
lda #16 ; loop counter for 16x16 multiply
|
|
@SquareLoop pha ; save loop counter
|
|
|
|
ldx #MaxDenomSquaredOff
|
|
jsr AddToMaxDenomSquared; MaxDenomSquared := MaxDenomSquared * 2
|
|
bcc @SquareNext ; if no carry, skip the add
|
|
|
|
ldx #MaxDenomOff
|
|
jsr AddToMaxDenomSquared; MaxDenomSquared := MaxDenomSquared + MaxDenom
|
|
|
|
@SquareNext pla ; restore loop counter
|
|
dea ; decrement loop counter
|
|
bne @SquareLoop ; loop for all 16 bits
|
|
|
|
bra TryNextPossible ; goto TryNextPossible
|
|
|
|
Done asl CurrentDenom+1 ; force an even, non-zero value
|
|
rts ; all done
|
|
|
|
|
|
MoveLong jsr MoveWord
|
|
MoveWord jsr MoveByte
|
|
MoveByte dex
|
|
lda PrimeVarsStart,x
|
|
dey
|
|
sta PrimeVarsStart,y
|
|
rts
|
|
|
|
AddImmedLong jsr AddImmedWord
|
|
AddImmedWord jsr AddImmedByte
|
|
AddImmedByte clc
|
|
dey
|
|
adc PrimeVarsStart,y
|
|
sta PrimeVarsStart,y
|
|
lda #0
|
|
rol a
|
|
rts
|
|
|
|
AddToMaxDenomSquared
|
|
ldy #4-1
|
|
clc
|
|
@AddLoop dex
|
|
lda PrimeVarsStart,x
|
|
adc MaxDenomSquared,y
|
|
sta MaxDenomSquared,y
|
|
dey
|
|
bpl @AddLoop
|
|
rts
|
|
|
|
TestEqualLong jsr TestEqualWord
|
|
bne NotEqual
|
|
TestEqualWord jsr TestEqualByte
|
|
bne NotEqual
|
|
TestEqualByte dex
|
|
lda PrimeVarsStart,x
|
|
dey
|
|
cpa PrimeVarsStart,y
|
|
NotEqual rts
|
|
|
|
endwith
|
|
endproc
|
|
|
|
end
|
|
|
|
|