Mercurial > hg > Members > kono > nitros9-code
diff level2/modules/os9p1.asm @ 0:6641a883d6b0
Initial revision
author | boisy |
---|---|
date | Thu, 04 Apr 2002 16:34:12 +0000 |
parents | |
children | a17a5e753f14 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/level2/modules/os9p1.asm Thu Apr 04 16:34:12 2002 +0000 @@ -0,0 +1,2387 @@ +******************************************************************** +* OS9p1 - OS-9 Level Two V3 P1 module +* +* $Id$ +* +* Ed. Comments Who YY/MM/DD +* ------------------------------------------------------------------ +* ?? Cleaned up some formatting KDM 87/05/15 +* ?? Added comments and added new defines KDM 87/03/31 +* 18a Added time of creation to process descriptor BRI 88/11/18 +* 18b Added F$AllTsk call error exit to F$Chain BRI 88/12/05 +* 18c Changed time tag to use F$Time - No ticks BRI 88/12/08 +* 18h Removed bogus assumptions regarding init BGP 98/10/05 +* module in order to shrink code size, added +* check for CRC bit in compabibility byte of +* init module. +* 18i Made minor optimizations as per Curtis Boyle's BGP 98/10/10 +* optimization document + + nam OS9p1 + ttl OS9 Level Two V3 P1 module + +* FastBoot flag turns off module CRC checking during boot +FastBoot equ 1 + + ifp1 + use defsfile + use scfdefs + endc + +rev set $09 +edition set 18 + + mod eom,name,Systm,ReEnt+rev,entry,msiz ++ + + org $0000 +msiz equ . + +name fcs "OS9p1" + fcb edition + +*------------------------------------------------* +* OS9p1 begins here: +*------------------------------------------------* +entry ldx #$100 clear rest of first 8k Block: ++ + ldy #8192-$100 ++ + clra + clrb +L001C std ,x++ + leay -2,y + bne L001C + + inca + std D.Tasks =$0100 task flags (32) + addb #$20 (DAT.TkCt) ++ + std D.TskIPt =$0120 temporary images ++ + + inca + aslb + std D.BlkMap+2 =$0240 end of block map + clrb + std D.BlkMap =$0200 mem block map (64) + + inca ++ + std D.SysDis =$0300 sys dispatch table + inca + std D.UsrDis =$0400 usr dispatch table + inca + std D.PrcDBT =$0500 proc desc pointers + inca + std D.SysPrc =$0600 original sys proc + std D.Proc =$0600 original proc + adda #P$Size/256 desc + tfr d,s SP=$0800 sys SP within sys desc + inca + std D.SysStk =$0900 main sys stack ptr + std D.SysMem =$0900 sys memmap + inca + std D.ModDir =$0A00 module dir + std D.ModEnd =$0A00 (grows upward) + adda #$06 + std D.ModDir+2 =$1000 module DAT images + std D.ModDAT =$1000 (grows downward) + std D.CCMem =$1000 CC3IO static memory ++ + + asla d=$2000 GrfDrv stack area ++ + + std D.CCStk ++ + +*------------------------------------------------* + leax Vectors,pcr put jmp[,x] vectors: + tfr x,d + ldx #D.SWI3 + +* used by top 256 to jmp to sys. + +L0065 std ,x++ + cmpx #D.NMI + bls L0065 + + leax >eo,pcr move secondary vectors + pshs x from end of rom: + leay >D.VECTRS,pcr + ldx #D.Clock (Tick-NMI) +L0079 ldd ,y++ get vector + addd ,s add offset + std ,x++ store + cmpx #D.XNMI done? + bls L0079 ..no + leas 2,s drop offset + + ldx D.XSWI2 set calls to sys + stx D.UsrSvc + ldx D.XIRQ set IRQ to sys + stx D.UsrIRQ + + leax SysCall,pcr set syscall handler + stx D.SysSvc + stx D.XSWI2 + + leax S.SysIRQ,pcr set sysirq handler + stx D.SysIRQ + stx D.XIRQ + + leax >S.SvcIRQ,pcr IRQ svc handler + stx D.SvcIRQ + leax >S.POLL,pcr default poll 'til IOMan + stx D.Poll + leax S.AltIRQ,pcr default keyboard till CC3io ++ + stx D.AltIRQ ++ + leax S.Flip0,pcr Grfdrv return vector ++ + stx D.Flip0 ++ + leax S.Flip1,pcr GrfDrv exec vector ++ + stx D.Flip1 ++ + + leay SysCalls,pcr enter os9p1 svc calls: + lbsr InstSSvc + +*------------------------------------------------* + ldu D.PrcDBT set up first proc desc: + ldx D.SysPrc + stx 0,u proc table entries + stx 1,u zero and one + + lda #1 sys proc id=01 + sta P$ID,x + lda #SysState set sys state + sta P$State,x + lda #SysTask sys task # ++ + sta D.SysTsk + sta P$Task,x +* optimization below saves one byte + ldd #$FFFF top priority/age + std P$Prior,x store it +* lda #$FF +* sta P$Prior,x +* sta P$Age,x + + leax P$DATImg,x point sysdat -> sys proc + stx D.SysDAT + clra + clrb + std ,x++ first block always sys + +* DAT.BlCt-ROMCount-RAMCount: + ldy #6 next 6 are unused ++ + ldd #DAT.Free +L00EF std ,x++ + leay -1,y + bne L00EF + + ldd #IOBlock last one is Kernel ++ + std ,x++ + + ldx D.Tasks first task# is sys's + inc 0,x + inc 1,x Task 1 is GrfDrv ++ + +*------------------------------------------------* +* set 1st 8K sys mem used + ldx D.SysMem + ldb D.CCStk (=$20) ++ +L0104 inc ,x+ + decb + bne L0104 + +*------------------------------------------------* +* determine size of CoCo's memory (128K/512K) + clr D.MemSz default is 128k ++ + ldd #$0313 blocks $03 and $13 ++ + std DAT.Regs+5 map at logical $A000 ++ + ldx #$A000 point to first block ++ + ldd #$DC78 get inverted sync bytes ++ + std ,x store at start of first block ++ + cmpd 8192,x in second block too? ++ + beq L0122 yes, just 128k ++ + inc D.MemSz else set 512k flag ++ + +L0122 ldy #$2000 point to second block in map ++ + ldx D.BlkMap X=$0200 + +* Check Memory Blocks Loop: + +L0128 pshs x save current map pointer + ldd ,s D=map ptr + subd D.BlkMap D=block number + cmpb #IOBlock is it sys? + bne L0136 ..no, test for 512k ++ + ldb #RAMinUse load marker ++ + bra L015B go set in map ++ + +L0136 lda D.MemSz 512k memory? ++ + bne L013E yes, continue ++ + cmpb #$0F end of 128k mem? ++ + bhs L0159 yes, set notram ++ + +L013E stb >DAT.Regs+1 set block at $2000 for test ++ + ldu ,y get two bytes + ldx #$00FF store test bytes + stx ,y + cmpx ,y same on read + bne L0159 ..end if no mem here + + ldx #$FF00 make sure again + stx ,y + cmpx ,y + bne L0159 ..bad mem + stu ,y restore original bytes + bra L015D do next + +* End of Memory: + +L0159 ldb #NotRAM set non-mem flag + +L015B stb [,s] store at ,X in table ++ + +L015D puls x get current map pointer + leax 1,x next block + cmpx D.BlkMap+2 end of map? + blo L0128 ..no, keep trying + +*------------------------------------------------* +* Search For ROM Modules: + + ldx D.BlkMap X=map strt (X=$0200) + inc ,x mark as RAMinUse + ldx D.BlkMap+2 start at end of map (X=$0240) + + leax -1,x back up 1 (X=$023F) + +*------------------------------------------------* + tfr x,d else D=block number (D=$023F) + subd D.BlkMap make into block number (D=$003F) + + pshs d save block number + leay ,s Y = var pointer for routine below + + ldx #$0D00 offset in block ++ + +*------------------------------------------------* +* Check Block for Modules Loop: + +L017F pshs x,y + lbsr L0AF0 set up Y for X offset + ldb 1,y B=block# from image + stb >DAT.Regs map into sys zero + lda ,x get byte from block + clr >DAT.Regs back to sys + puls x,y + cmpa #M$ID1 module? + bne L01A7 + + lbsr L0463 do verify + bcc L019D + cmpb #E$KwnMod 'Known Module'? + bne L01A7 ..no, continue +L019D ldd #M$Size else get mod size + lbsr lddxy + leax d,x skip over it + bra L01A9 + +* Not Known Module: + +L01A7 leax 1,x byte ptr+1 + +L01A9 cmpx #$1E00 don't overrun vector page! ++ + blo L017F ok to continue ++ + bsr L01D2 setup system mem map ++ + +*------------------------------------------------* +* OS9p1 init finished: + +L01B0 os9 F$Boot boot! + bcs Crash crash if problem + leax InitMod,pcr 'Init' + bsr LinkSys link to it + bcs Crash crash if error +L01BF stu D.Init save Init ptr +L01C1 leax OS9p2Nm,pcr 'OS9p2' + bsr LinkSys link to it + bcs Crash crash if not found... +L01D0 jmp ,y ...else do OS9p2... +Crash jmp D.Crash report boot failed + +* Setup system memory map. + +L01D2 ldx D.SysMem point to map ++ + leax $ED00/256,x kernel offset in map ++ + lda #NotRam mark IOPage ++ + sta 18,x as Not RAM ++ + ldb #$12 18 pages in kernel ++ + +L01DF lda #RAMinUse mark kernel ++ + +L01E1 sta ,x+ RAM as in use ++ + decb all done ++ + bne L01E1 no, continue + ldx D.BlkMap+2 end of map++ + sta -1,x mark block #3F ++ + rts exit ++ + +* Link to Module (X = ptr to mod name): +LinkSys lda #Systm system module + os9 F$Link try to find it + rts + +*------------------------------------------------* +* System Service Calls +*------------------------------------------------* +SysCalls fcb F$Link + fdb FLink-*-2 + fcb F$PrsNam + fdb FPrsNam-*-2 + fcb F$CmpNam + fdb FCmpNam-*-2 + fcb F$CmpNam+$80 (sys) + fdb SCmpNam-*-2 + fcb F$CRC + fdb FCRC-*-2 + fcb F$SRqMem+$80 + fdb FSRqMem-*-2 + fcb F$SRtMem+$80 + fdb FSRtMem-*-2 + fcb F$AProc+$80 + fdb FAProc-*-2 + fcb F$NProc+$80 + fdb FNProc-*-2 + fcb F$VModul+$80 + fdb FVModul-*-2 + fcb F$SSvc + fdb FSSvc-*-2 + fcb F$SLink+$80 + fdb FSLink-*-2 + fcb F$Boot+$80 + fdb FBoot-*-2 + fcb F$BtMem+$80 + fdb FBtMem-*-2 + fcb F$Move+$80 + fdb FMove-*-2 + fcb F$AllRam + fdb FAllRam-*-2 + fcb F$AllImg+$80 + fdb FAllImg-*-2 + fcb F$SetImg+$80 + fdb FSetImg-*-2 + fcb F$FreeLB+$80 + fdb FFreeLB-*-2 + fcb F$FreeHB+$80 + fdb FFreeHB-*-2 + fcb F$AllTsk+$80 + fdb FAllTsk-*-2 + fcb F$DelTsk+$80 + fdb FDelTsk-*-2 + fcb F$SetTsk+$80 + fdb FSetTsk-*-2 + fcb F$ResTsk+$80 + fdb FResTsk-*-2 + fcb F$RelTsk+$80 + fdb FRelTsk-*-2 + fcb F$DATLog+$80 + fdb FDATLog-*-2 + fcb F$LDAXY+$80 + fdb FLDAXY-*-2 + fcb F$LDDDXY+$80 + fdb FLDDDXY-*-2 + fcb F$LDABX+$80 + fdb FLDABX-*-2 + fcb F$STABX+$80 + fdb FSTABX-*-2 + fcb F$ELink+$80 + fdb FELink-*-2 + fcb F$FModul+$80 + fdb FFModul-*-2 + fcb F$AlHRam+$80 new call ++ + fdb FAlHRam-*-2 for CoCo3 ++ + fcb $80 End of Table + +*------------------------------------------------* +InitMod fcs "Init" +OS9p2Nm fcs "OS9p2" +BootMod fcs "Boot" + +*------------------------------------------------* +Vectors jmp [-16,x] goto irq routine + +*------------------------------------------------* +* User State SWI Vectors: +*------------------------------------------------* + +XSWI3 ldx D.Proc proc desc + ldu P$SWI3,x diff swi3 vector? + beq L028E ..no, do normal + +L027B lbra L0E5E else do usr call. + +XSWI2 ldx D.Proc X=proc desc + ldu P$SWI2,x swi2 svc ptr + beq L028E ..zero, do normal + bra L027B else do usr map + +XSWI ldx D.Proc proc desc + ldu P$SWI,x swi ptr + bne L027B ..do user, else: + +*------------------------------------------------* +* System SWI calls: (X=pd, U=svc) + +L028E ldd D.SysSvc set system state: + std D.XSWI2 + ldd D.SysIRQ + std D.XIRQ + lda P$State,x + ora #SysState + sta P$State,x + + sts P$SP,x and save user stack + leas P$Stack-R$Size,x get local sys stack + andcc #^IntMasks okay interrupts + leau ,s U=sys reg stack + bsr L02CB copy user stack here + + ldb P$Task,x B=task# + ldx R$PC,u X=PC ptr + lbsr FLDBBX get call byte from user map ++ + leax 1,x increment PC + stx R$PC,u past call + + ldy D.UsrDis Y=user dispatch table + lbsr L033B do the call + ldb R$CC,u okay interrupts + andb #^IntMasks on return + stb R$CC,u to user map + + ldx D.Proc + bsr L02DA copy back new user stack + lda P$State,x drop sys state + anda #^SysState + lbra L0D7C and return to user. + +*------------------------------------------------* +* Get Caller's Regs: + +L02CB pshs cc,x,y,u ++ + ldb P$Task,x A=user tsk# ++ + ldx P$SP,x X=from user stack + lbsr L0BF5 get offset in 8k space ++ + leax $A000,x +$A000 =logical address ++ + bra L02E9 get regs & rts. + +* Return Regs to Caller: + +L02DA pshs cc,x,y,u save state ++ + ldb P$Task,x B=user tsk# + ldx P$SP,x X=to user stack + lbsr L0BF5 get offset in 8k space ++ + leax $A000,x +$A000 =logical address ++ + exg x,u U=user, X=sys + +* move caller stack --> + +L02E9 pshs u save U ++ + lbsr L0C09 get DAT image pointer in U ++ + leau a,u point to block # in image ++ + leau 1,u point to LSB ++ +* lda ,u++ first block # in A ++ --BGP +* ldb ,u second block # in B ++ --BGP + lda ,u first block # in A ++ ++BGP + ldb 2,u second block # in B ++ ++BGP + ldu #DAT.Regs+5 $A000 logical ++ + orcc #IntMasks mask interrupts ++ + std ,u set DAT ++ + puls u recover U ++ + ldy #R$SIZE register stack size ++ + +L0303 ldd ,x++ move them ++ + std ,u++ ++ + leay -2,y done yet? ++ + bne L0303 no, continue ++ + ldx D.SysDAT system DAT image ++ + lda 11,x get real ++ + ldb 13,x system blocks ++ + std DAT.Regs+5 and restore system map ++ + puls cc,x,y,u,pc clean up and rts ++ + +*------------------------------------------------* +* Sys State OS Call: +*------------------------------------------------* +SysCall leau ,s U=reg stack + lda D.SSTskN get task image ++ + clr D.SSTskN set to system ++ + pshs a save old task # ++ + lda R$CC,u + tfr a,cc set CC=user CC + ldx R$PC,u get call + ldb ,s is task sys? ++ + beq L032F yes ++ + lbsr FLDBBX get call from user space ++ + leax 1,x point past it ++ + bra L0331 set as PC ++ + +L032F ldb ,x+ and increment PC + +L0331 stx R$PC,u past it + ldy D.SysDis Y=system dispatch table + bsr L033B do the call + lbra L0E2B end + +*------------------------------------------------* +* Do Svc Call(B), Y=table: + +L033B aslb index + bcc L0345 ..okay if not I/O + +* count I$ calls for current process (D.Proc) + pshs b save index into table + ldb #P$ICalls set up I$ counter + bsr IncCount go do it... (X is altered) + puls b recover index + + rorb else reset B + ldx $00FE,y else X=IOMan vector + bra L034F and do it. + +* count User Ticks, System Ticks, F$ calls, or I$ calls +* for current process (D.Proc) BRI +IncCount ldx <D.Proc get pointer to current proc desc + beq IncExit no current proc, go return + abx add offset to appropriate counter + inc 3,x 4 byte counter LSB + bne IncExit no overflow, go return + inc 2,x 4 byte counter lower middle byte + bne IncExit no overflow, go return + inc 1,x 4 byte counter upper middle byte + bne IncExit no overflow, go return + inc ,x 4 byte counter MSB (ignore overflow) +IncExit rts + +* (not I/O call) + +L0345 pshs b save index into table + ldb #P$FCalls set up F$ counter + bsr IncCount go do it... (X is altered) + puls b recover index + + clra A=00 + ldx d,y X=vector from table + bne L034F ..ok if one + comb else + ldb #E$UnkSvc 'Unknown Service Call' + bra L0355 bad end: return err + +*------------------------------------------------* +* Do Call Vector (X) + +L034F pshs u save reg ptr + jsr ,x do the call + puls u retrieve reg ptr + +L0355 tfr cc,a A=svc call CC + bcc L035B ..skip if no err + stb R$B,u else return err in reg.B +L035B ldb R$CC,u drop lsb nibble + andb #(Entire!IntMasks) + stb R$CC,u + anda #^(Entire!IntMasks) put in call's CC lsnibble + ora R$CC,u + sta R$CC,u + rts end service call. + + +*------------------------------------------------* +* F$SSvc +*------------------------------------------------* +FSSvc ldy R$Y,u Y=table address + bra InstSSvc do check first... + +* SSvc Loop: + +L036D clra A=00 + aslb B=table index (set C if >=$80) + tfr d,u U=index + ldd ,y++ D=new call vector offset + leax d,y X=actual vector + ldd D.SysDis D=sys dispatch table + stx d,u store new call vector + bcs InstSSvc ..skip if sys only + ldd D.UsrDis else put in user + stx d,u dispatch table also. + +* End of Table Check: + +InstSSvc ldb ,y+ get next call + cmpb #$80 is it end-of-table? + bne L036D ..no + rts yes, end. + + +*------------------------------------------------* +* F$SLink +*------------------------------------------------* +* Link modules into map. +* A=type,X=name,Y=DAT image ptr +FSLink ldy R$Y,u get DAT image ptr + bra SLink + + +*------------------------------------------------* +* F$ELink +*------------------------------------------------* +FELink pshs u + ldb R$B,u type + ldx R$X,u name of module + bra L03AF go link it + + +*------------------------------------------------* +* F$Link +*------------------------------------------------* +FLink ldx D.Proc proc desc + leay P$DATImg,x Y=DAT image ptr + +*------------------------------------------------* +SLink pshs u save reg ptr + ldx R$X,u X=module name + lda R$A,u A=module type + lbsr L068D search moddir + + bcs L041E ..err + + leay ,u Y=moddir entry + ldu ,s get back reg ptr + stx R$X,u return X + std R$D,u return type/lang + leax ,y X=moddir entry + +L03AF bitb #ReEnt is it shareable? + bne L03BB ..yes + ldd MD$Link,x any links? + beq L03BB ..no:ok, else + ldb #E$ModBsy 'Module Busy' err + bra L041E bad end. + +L03BB ldd MD$MPtr,x D=module ptr + pshs a,b,x save ptr,entry + ldy MD$MPDAT,x Y=DAT img for module + ldd MD$MBSiz,x D=mem block size + addd #$1FFF round up A ++ + tfr a,b to 8K block ++ + lsrb B/32 + lsrb + lsrb + lsrb + lsrb ++ + adda #2 (A+2)/32 ++ + lsra + lsra + lsra + lsra + lsra ++ + pshs a save blocks needed + leau ,y U=moddir entry + bsr L0422 find it in callers map? + bcc L03EB ..yes + + lda ,s blocks needed + lbsr L0A33 room to map in? + bcc L03E8 ..okay + leas 5,s else drop junk + bra L041E bad end. + +L03E8 lbsr L0A8C set DAT image +L03EB leax P$Links,x link cnt tble + sta ,s save block # + asla index + leau a,x U=link ptr + ldx ,u increment link cnt: + leax 1,x + beq L03FC + stx ,u +L03FC ldu 3,s U=moddir entry + ldx MD$Link,u increment link cnt: + leax 1,x + beq L0406 + stx MD$Link,u +L0406 puls b,x,y,u + lbsr L0AB0 dattolog + stx R$U,u return module addrss + ldx MD$MPtr,y mod ptr + ldy MD$MPDAT,y DAT image ptr + ldd #M$Exec get exec offset + lbsr LDDXY + addd R$U,u plus mod addrss + std R$Y,u = exec address + clrb okay + rts end. + +L041E orcc #Carry set error + puls u,pc + +*------------------------------------------------* +* See if moddir image in proc map already: +*------------------------------------------------* + +* B=block img #, U=moddir ptr + +L0422 ldx D.Proc proc desc + leay P$DATImg,x Y=DAT image ptr + clra A=00 + pshs a,b,x,y save #,proc,img + subb #DAT.BlCt + negb + aslb index + leay b,y + +* Image Compare Loop: + +L0430 ldx ,s X=block cnt + pshs y,u +L0434 ldd ,y++ does proc img + cmpd ,u++ match mod image? + bne L0449 ..no + leax -1,x yes, cnt-1 + bne L0434 ..done? + + puls a,b,u D=start ptr + subd 4,s -block cnt = offset + lsrb B/2 index + stb ,s save block # + clrb okay + puls a,b,x,y,pc rts. + +L0449 puls y,u Y=start ptr + leay -2,y back up one img + cmpy 4,s too far? + bcc L0430 ..no, try again + puls a,b,x,y,pc error end. + + +*------------------------------------------------* +* F$VModul +*------------------------------------------------* +FVModul pshs u + ldx R$X,u X=mod offset + ldy R$D,u Y=DAT img ptr + bsr L0463 do the verify + ldx ,s + stu R$U,x return moddir ptr + puls u,pc + +L0463 pshs x,y + lbsr L0586 check module crc + bcs L0493 ..err + + ldd #M$Type + lbsr LDDXY get type/rev bytes + andb #$0F save rev + pshs a,b + + ldd #M$Name get name offset + lbsr LDDXY + leax d,x X points to mod name + puls a + lbsr L068D + puls a + bcs L0497 + + pshs a + andb #$0F + subb ,s+ + bcs L0497 + ldb #E$KwnMod 'Known Module' + bra L0493 + +L0491 ldb #E$DirFul 'Module Dir Full' +L0493 orcc #Carry + puls x,y,pc + +*------------------------------------------------* +L0497 ldx ,s X=module addrss + lbsr L0524 + bcs L0491 + sty MD$MPDAT,u insert DAT image ptr + stx MD$MPtr,u and module ptr + clra + clrb + std MD$Link,u link count=00 + ldd #M$Size + lbsr LDDXY get module size + pshs x mod addrss + addd ,s++ plus size + std MD$MBSiz,u + ldy [MD$MPDAT,u] Y=mod images + ldx D.ModDir X=mod dir strt + pshs u save entry + bra L04BE + +L04BC leax MD$ESize,x next moddir entry +L04BE cmpx D.ModEnd last one? + bcc L04CD ..yes, end + cmpx ,s same entry? + beq L04BC ..yes, try again + cmpy [,x] same image ptr? + bne L04BC ..no, try again + bsr L04F2 + +*------------------------------------------------* +* Mark BlockMaps as Modules: + +L04CD puls u U=dir entry + ldx D.BlkMap X=mem block map + ldd MD$MBSiz,u D=mod block size + addd #$1FFF round up size ++ + lsra A/32 = number of blocks + lsra (8K) + lsra + lsra + lsra ++ + ldy MD$MPDAT,u Y=mod dat image + +L04DE pshs a,x save block size, blkmap + ldd ,y++ D=image block# + leax d,x X=blkmap ptr + ldb ,x get block marker + orb #ModBlock set module in block + stb ,x marker + puls a,x .. + deca count-1 + bne L04DE ..mark all blocks + + clrb okay + puls x,y,pc end. + +*------------------------------------------------* +* Clear entries: + +L04F2 pshs a,b,x,y,u + ldx ,x + pshs x + clra D=0000 + clrb +L04FA ldy ,x last entry? + beq L0503 ..yes + std ,x++ no, clear + bra L04FA and loop + +L0503 puls x + ldy 2,s + ldu MD$MPDAT,u U=mod images + puls a,b + +L050C cmpx ,y same image? + bne L051B ..no, try next + stu MD$MPDAT,y yes, set new image + cmpd MD$MBSiz,y new size bigger? + bcc L0519 ..yes, use it + ldd MD$MBSiz,y else use old size +L0519 std MD$MBSiz,y set modblock size +L051B leay MD$ESize,y next entry + cmpy D.ModEnd last? + bne L050C ..no + puls x,y,u,pc end. + +*------------------------------------------------* +L0524 pshs x,y,u save mod adrs,img, + ldd #M$Size get module size + lbsr LDDXY + addd ,s end = begin+size + addd #$1FFF round to block ++ + lsra A/32 + lsra + lsra + lsra + lsra ++, + tfr a,b A,B=number of blocks + pshs b save num + incb + aslb + negb + sex sign extend into D + bsr L054E make new dir entry + bcc L054C ..okay rts + + os9 F$GCMDir else get task# + ldu #$0000 set flag + stu 5,s + bsr L054E make new dir entry +L054C puls b,x,y,u,pc rts. + +*------------------------------------------------* +* Allocate module dir image: + +L054E ldx D.ModDAT X+D = mod DAT img pointer + leax d,x + cmpx D.ModEnd would it be below last dir? + bcs L0583 ..yes, err + + ldu 7,s get back old U + bne L056E .. + pshs x save new moddat ptr + ldy D.ModEnd Y=end of dir + leay MD$ESize,y plus new entry + cmpy ,s++ collide with moddat? + bhi L0583 ..yes, err + + sty D.ModEnd store new dir end + leay -MD$ESize,y Y=new dir entry ptr + sty 7,s return it to caller +L056E stx D.ModDAT store new moddat ptr + ldy 5,s + ldb 2,s B=block count + stx 5,s return dir datimg ptr + +L0577 ldu ,y++ copy images + stu ,x++ to new mod dat entry + decb + bne L0577 + + clr ,x zero flag + clr 1,x + rts end. + +L0583 orcc #Carry set err flag + rts end. + + +*------------------------------------------------* +* Calculate CRC of Module: +*------------------------------------------------* + +L0586 pshs x,y + clra D=offset of zero + clrb + lbsr LDDXY get 2 bytes + cmpd #M$ID12 is it module? + beq L0597 ..yes + ldb #E$BMID 'Bad Module Header' + bra L05F3 ..err end. + +* Check Module Header: + +L0597 leas -1,s make var + leax 2,x X=past sync bytes + lbsr L0AF0 set Y for X offset + ldb #$07 seven bytes + lda #$4A header crc +L05A2 sta ,s save crc + lbsr LDAXY get next byte + eora ,s do crc + decb more? + bne L05A2 ..loop + + leas 1,s drop var + inca $FF+1 = 00 + beq L05B5 ..okay header + ldb #E$BMHP 'Bad Module Header' + bra L05F3 err end. + +*------------------------------------------------* +* Do CRC across module: +* +* Added code to check init module for CRC check flag +L05B5 + ldx D.Init get Init module addr ++ BGP + +* Here the FastBoot definition says that if the INIT module cannot +* be found (as is the case when OS9p1 brings up the rest of the +* system with F$Boot), then don't do CRC checking. Note that +* module header checking above is still performed in this case. + ifeq FastBoot + beq L05CX if none, do CRC checking ++ BGP + else + beq NOCRC if none, DON'T DO CRC checking ++ BGP + endc + + lda Compat1,x get compat1 byte ++BGP + bita #CRCOn test CRCOn bit ++BGP + bne L05CX if set, check CRC ++BGP +NOCRC clra else clra ++BGP + clrb and clrb ++BGP + bra L05F5 branch to end of routine ++BGP +L05CX puls x,y + ldd #$0002 + lbsr LDDXY + pshs a,b,x,y + ldd #$FFFF set temp CRC register + pshs a,b + pshs b + lbsr L0AF0 set up Y for X offset + leau ,s +L05CB tstb + bne L05D8 + pshs x + ldx #$0001 + os9 F$Sleep + puls x +L05D8 lbsr LDAXY get a byte + bsr CRCCalc pass it through the CRC calculator + ldd 3,s + subd #$0001 + std 3,s + bne L05CB + puls b,x,y + cmpb #$80 + bne L05F1 + cmpx #$0FE3 + beq L05F5 +L05F1 ldb #E$BMCRC 'Bad Module CRC' +L05F3 orcc #Carry +L05F5 puls x,y,pc + +*------------------------------------------------* +* CRC Calculator: +*------------------------------------------------* + +* A = byte to be passed through accumulator +CRCCalc eora ,u + pshs a + ldd 1,u + std ,u + clra + ldb ,s + aslb + rola + eora 1,u + std 1,u + clrb + lda ,s + lsra + rorb + lsra + rorb + eora 1,u + eorb 2,u + std 1,u + lda ,s + asla + eora ,s + sta ,s + asla + asla + eora ,s + sta ,s + asla + asla + asla + asla + eora ,s+ + bpl L0635 + ldd #$8021 + eora ,u + sta ,u + eorb 2,u + stb 2,u +L0635 rts + +*------------------------------------------------* +* F$CRC +*------------------------------------------------* +FCRC ldd R$Y,u get byte count + beq L0677 ..zero + ldx R$X,u begin ptr + pshs a,b,x + leas -3,s + ldx D.Proc + lda P$Task,x + ldb D.SysTsk + ldx R$U,u + ldy #$0003 + leau ,s + pshs a,b,x,y + lbsr L0B2C + ldx D.Proc + leay P$DATImg,x + ldx 11,s + lbsr L0AF0 +L065D lbsr LDAXY + bsr CRCCalc pass byte through CRC calculator + ldd 9,s + subd #$0001 + std 9,s + bne L065D + puls a,b,x,y + exg a,b + exg x,u + lbsr L0B2C + leas 7,s +L0677 clrb + rts + +*------------------------------------------------* +* F$FModul +*------------------------------------------------* +* Find the Module named (X) with type (A) in Y +FFModul pshs u + lda R$A,u A=type request + ldx R$X,u X=name + ldy R$Y,u Y=DAT image ptr + bsr L068D find it + puls y + std R$D,y return type/attr + stx R$X,y updated name ptr + stu R$U,y module offset + rts + +L068D ldu #$0000 address flag + pshs a,b,u + bsr L0712 get first char + cmpa #PDELIM start with pathlist delimiter? + beq L070B ..bad name error + lbsr L0741 + bcs L070E + ldu D.ModEnd U=mod end ++ + bra L0700 + +*------------------------------------------------* +* Main Loop: + +L06A1 pshs a,b,x,y + pshs x,y + ldy MD$MPDAT,u Y=mod images + beq L06F6 + ldx MD$MPtr,u X=mod ptr + pshs x,y + ldd #M$Name get mod name + lbsr LDDXY offset + leax d,x X=name address + pshs x,y save add,images + leax 8,s + ldb 13,s + leay ,s + lbsr L07DE + leas 4,s + puls x,y + leas 4,s + bcs L06FE + ldd #M$Type get mod type/lang + lbsr LDDXY + sta ,s + stb 7,s + lda 6,s + beq L06ED + anda #$F0 + beq L06E1 + eora ,s + anda #$F0 + bne L06FE +L06E1 lda 6,s + anda #$0F + beq L06ED + eora ,s + anda #$0F + bne L06FE +L06ED puls a,b,x,y + abx + clrb + ldb 1,s + leas 4,s + rts + +*------------------------------------------------* +L06F6 leas 4,s + ldd 8,s + bne L06FE + stu 8,s +L06FE puls a,b,x,y + +* Moved back one ++ + +L0700 leau -MD$ESize,u next dir entry ++ + cmpu D.ModDir last one? ++ + bcc L06A1 ..no, loop ++ + +*------------------------------------------------* + ldb #E$MNF 'Module Not Found' + bra L070E + +L070B comb + ldb #E$BNam 'Bad Name' error +L070E stb 1,s return err code + puls a,b,u,pc + +*------------------------------------------------* +* Get Module Name: + +L0712 pshs y save image strt +L0714 lbsr L0AF0 point X to name in img(Y) + lbsr L0AC8 get char + leax 1,x ptr+1 + cmpa #C$SPAC was char space? + beq L0714 ..yes, skip + + leax -1,x ptr-1 + pshs a save char + tfr y,d D=image ptr + subd 1,s -images start + asrb block#=image/2 + lbsr L0AB0 ?? + puls a,y,pc rts. + + +*------------------------------------------------* +* F$PrsNam +*------------------------------------------------* +FPrsNam ldx D.Proc proc desc + leay P$DATImg,x Y=DAT image ptr + ldx R$X,u X=name string + bsr L0741 get it and length + std R$D,u return length in D + bcs L073E ..err + stx R$X,u and X at name begin + abx plus len +L073E stx R$Y,u return Y=end of name ptr + rts end. + +* Parse Name: + +L0741 pshs y save image ptr + lbsr L0AF0 find map block + pshs x,y save X offset within block and Y block pointer + lbsr LDAXY get A=byte(X) + cmpa #PDELIM is it a pathlist delimiter? + bne L0756 ..no, go keep X offset and block Y + leas 4,s + pshs x,y + lbsr LDAXY get next char +L0756 bsr L07A1 go check if valid first character... + bcs L076A not valid, go get next name start offset in X... + clrb initialize character counter +L075B incb incb add one character + tsta last character in name string? + bmi L0766 yes, go return valid... + lbsr LDAXY go get next character... + bsr L078A go check if valid character... + bcc L075B valid, go check if last character... +L0766 andcc #^Carry + bra L077C + +*------------------------------------------------* +L076A cmpa #C$COMA comma? + bne L0775 no, check for next character +L076E leas 4,s + pshs x,y + lbsr LDAXY +L0775 cmpa #C$SPAC is it a space? + beq L076E ..yes, go get next character + comb error, set Carry + ldb #E$BNam 'Bad Name' error +L077C puls x,y recover offset and pointer + pshs cc,a,b save Carry, character and count or error code + tfr y,d copy DAT image block pointer + subd 3,s subtract original DAT image pointer + asrb convert 2 byte/block count to block number + lbsr L0AB0 go get true map offset in X... + puls cc,a,b,y,pc recover registers and return... + +L078A pshs a save character + anda #$7F drop msbit + cmpa #PDIR period? + beq ValidChr yes, go return valid character... + cmpa #'0 is it control? + bcs InvalChr ..yes + cmpa #'9 is it number? + bls ValidChr ..yes + cmpa #'_ is it '_'? + bne L07A5 ..no +ValidChr clra clear carry + puls a,pc recover original character and return + +*---------------------------------------------- +L07A1 pshs a + anda #$7F drop msbit +L07A5 cmpa #'A less than "A"? + bcs InvalChr yes, go return invalid character... + cmpa #'Z less than or equal to "Z"? + bls ValidChr yes, go return valid character + cmpa #'a less than "a"? + bcs InvalChr yes, go return invalid character + cmpa #'z less than or equal to "z"? + bls ValidChr yes, go return valid character +InvalChr coma + puls a,pc + + +*------------------------------------------------* +* F$CmpNam +*------------------------------------------------* +FCmpNam ldx D.Proc proc desc + leay P$DATImg,x Y=caller DAT image ptr + ldx R$X,u X=first name + pshs x,y save name,img + bra L07CF do it + + +*------------------------------------------------* +* F$CmpNam (sys) +*------------------------------------------------* +SCmpNam ldx D.Proc proc desc + leay P$DATImg,x Y=images + ldx R$X,u X=first name + pshs x,y save name,imgs + ldy D.SysDAT Y=system DAT image ptr + +L07CF ldx R$Y,u X=second name + pshs x,y save name2,sysimg + ldd R$D,u D=match length + leax 4,s [X]=name1 + leay ,s [Y]=name2 + bsr L07DE compare them + leas 8,s drop vars + rts end. + +* Compare two strings: + +L07DE pshs a,b,x,y,u length,name1,name2,regs + ldu 2,s U=name1 ptr + pulu x,y get name,images + lbsr L0AF0 set X for img(Y) + pshu x,y save name1 offsets + ldu 4,s + pulu x,y + lbsr L0AF0 + bra L07F6 + +L07F2 ldu 4,s + pulu x,y +L07F6 lbsr LDAXY get name2 char + pshu x,y + pshs a save char + ldu 3,s + pulu x,y + lbsr LDAXY get name1 char + pshu x,y + eora ,s compare chars + tst ,s+ check result + bmi L0816 ..msb diff + decb len-1 + beq L0813 last? + anda #$DF + beq L07F2 do next char + +L0813 comb err + puls a,b,x,y,u,pc end. + +L0816 decb len-1 + bne L0813 ..err if >0 + anda #$5F + bne L0813 + clrb okay + puls a,b,x,y,u,pc end. + + +*------------------------------------------------* +* F$SRqMem / F$BtMem +*------------------------------------------------* +FSRqMem +FBtMem ldd R$D,u get # bytes wanted + addd #$00FF round up + clrb to page + std R$D,u return it + ldy D.SysMem Y=system mem map + leas -2,s + stb ,s +L082F ldx D.SysDAT X=system DAT image + aslb index block + ldd b,x D=DAT marker + cmpd #DAT.Free is it free? + beq L0847 ..yes + ldx D.BlkMap else look + lda d,x at block map byte + cmpa #RAMinUse is it in use? + bne L0848 ..yes + leay 32,y leave map ++ + bra L084F + +* Free Ram: + +L0847 clra + +* Ram Not in Use: + +L0848 ldb #32 count=32 pages ++ +L084A sta ,y+ mark the ram + decb + bne L084A + +L084F inc ,s + ldb ,s + cmpb #DAT.BlCt all blocks done? + bcs L082F +L0857 ldb R$A,u page count +L0859 cmpy D.SysMem back to map start? + bhi L0863 ..not yet + comb + ldb #E$NoRam was MemFul ++ + bra L0894 + +L0863 lda ,-y free page? + bne L0857 ..no,try again + decb else got page+1 + bne L0859 + sty ,s + lda 1,s + lsra + lsra + lsra + lsra + lsra ++ + ldb 1,s + andb #$1F ++ + addb R$A,u + addb #$1F ++ + lsrb + lsrb + lsrb + lsrb + lsrb ++ + ldx D.SysPrc + lbsr L09BE allocate ram images + bcs L0894 + ldb R$A,u +L088A inc ,y+ + decb + bne L088A + lda 1,s + std R$U,u return ptr to mem + clrb +L0894 leas 2,s + rts + + +*------------------------------------------------* +* F$SRtMem +*------------------------------------------------* +FSRtMem ldd R$D,u + beq L08F2 + addd #$00FF + ldb R$U+1,u + beq L08A6 + comb + ldb #E$BPAddr 'Boundary Error' + rts + +L08A6 ldb R$U,u + beq L08F2 + ldx D.SysMem + abx +L08AD ldb ,x + andb #^RAMinUse + stb ,x+ + deca + bne L08AD + ldx D.SysDAT + ldy #DAT.BlCt 16 blocks/space +L08BC ldd ,x + cmpd #DAT.Free free block? + beq L08EC ..yes + ldu D.BlkMap + lda d,u + cmpa #$01 + bne L08EC + tfr x,d + subd D.SysDAT + aslb + aslb + aslb + aslb ++ + ldu D.SysMem + leau d,u + ldb #32 16 blocks in sys space ++ +L08DA lda ,u+ + bne L08EC + decb + bne L08DA + ldd ,x + ldu D.BlkMap + clr d,u + ldd #DAT.Free + std ,x +L08EC leax 2,x + leay -1,y + bne L08BC +L08F2 clrb + rts + + +*------------------------------------------------* +* F$Boot +*------------------------------------------------* +FBoot comb + lda D.Boot booted already? + bne L0966 ..yes,rts. + inc D.Boot flag it +* ldx D.Init X=init module +* beq L0908 ..use default if no Init +* ldd BootStr,x offset to Boot name +* beq L0908 ..none +* leax d,x X=Init BootStrap name +* bra L090C use it + +L0908 leax BootMod,pcr default 'Boot' name +L090C lbsr LinkSys link to module + bcs L0966 ..err rts + jsr ,y do the boot + bcs L0966 ..err + std D.BtSz Bootfile size ++ + stx D.BtPtr Boot start address ++ + leau d,x + tfr x,d + anda #$E0 ++ + clrb + pshs a,b,u + lsra + lsra + lsra + lsra ++ + ldy D.SysDAT + leay a,y +*------------------------------------------------* +* Find & Verify Boot Modules: + +L092D ldd ,x get header + cmpd #M$ID12 (87CD) is it a module? + bne L0954 ..no + tfr x,d + subd ,s + tfr d,x + tfr y,d + os9 F$VModul + pshs b + ldd 1,s + leax d,x + puls b + bcc L094E + cmpb #E$KwnMod 'Known Module'? + bne L0954 ..no +L094E ldd 2,x + leax d,x + bra L0956 + +L0954 leax 1,x +L0956 cmpx 2,s end of boot mem? + bcs L092D ..no, try more + leas 4,s + ldx D.SysDAT ++ + ldb 13,x ++ + incb ++ + ldx D.BlkMap ++ + lbra L01DF ++ + +L0966 rts + + +*------------------------------------------------* +* F$AllRam +*------------------------------------------------* +FAllRam ldb R$B,u get # ram blocks desired + bsr L0970 + bcs L096F + std R$D,u +L096F rts + +*------------------------------------------------* +L0970 pshs a,b,x,y + ldx D.BlkMap X=block map start + +* Start at new block begin: + +L0974 leay ,x Y=start + ldb 1,s B=count +L0978 cmpx D.BlkMap+2 at end of block map? + bcc L0995 ..yes,end. + lda ,x+ is block free? + bne L0974 ..no, try new start + decb yes, count-1 + bne L0978 keep trying + +L0983 tfr y,d D=begin block ptr ++ + subd D.BlkMap D=begin block number + sta R$A-1,s return number on ,S + lda R$B-1,s A=count + stb R$B-1,s + +* mark off blocks + +L098D inc ,y+ mark as ram in use + deca + bne L098D + clrb + puls a,b,x,y,pc okay end. + +L0995 comb + ldb #E$NoRam 'Sys Ram Full' + stb 1,s return err + puls a,b,x,y,pc bad end. + +*------------------------------------------------* +* F$AlHRam +*------------------------------------------------* + +FALHRAM ldb R$B,u get block count ++ + bsr L09A5 find blocks ++ + bcs L09A4 error ++ + std R$D,u return count in D ++ + +L09A4 rts ++ + +L09A5 pshs a,b,x,y match up stack ++ + ldx D.BlkMap+2 point to end of map ++ + +L09A9 ldb R$B-1,s get block count ++ + +L09AB cmpx D.BlkMap at bottom of map? ++ + bls L0995 yes, error ++ + lda ,-x block free? ++ + bne L09A9 no ++ + decb found them all? ++ + bne L09AB no, continue ++ + tfr x,y match up registers ++ + bra L0983 allocate blocks ++ + +*------------------------------------------------* +* F$AllImg +*------------------------------------------------* +FAllImg ldd R$D,u A=begin blk#, B=# of blocks + ldx R$X,u X=proc desc +L09BE pshs a,b,x,y,u + asla + leay P$DATImg,x Y=DAT image ptr + leay a,y Y=image ptr + clra + tfr d,x + ldu D.BlkMap + pshs a,b,x,y,u +L09CD ldd ,y++ D=image + cmpd #DAT.Free unused? + beq L09E2 ..yes + lda d,u else what is it? + cmpa #RAMinUse ram? + puls a,b + bne L09F7 ..no + + subd #$0001 + pshs a,b +L09E2 leax -1,x + bne L09CD + ldx ,s++ + beq L0A00 +L09EA lda ,u+ + bne L09F2 + leax -1,x + beq L0A00 +L09F2 cmpu D.BlkMap+2 + bcs L09EA + +L09F7 ldb #E$MemFul 'Proc Memory Full' (207) + leas 6,s + stb R$B-1,s + comb + puls a,b,x,y,u,pc + +*------------------------------------------------* +L0A00 puls x,y,u +L0A02 ldd ,y++ + cmpd #DAT.Free + bne L0A16 +L0A0A lda ,u+ + bne L0A0A + inc ,-u + tfr u,d + subd D.BlkMap + std -2,y + +L0A16 leax -1,x + bne L0A02 + ldx 2,s + lda P$State,x get proc state & + ora #ImgChg flag image change + sta P$State,x . + clrb + puls a,b,x,y,u,pc + + +*------------------------------------------------* +* F$FreeHB +*------------------------------------------------* +FFreeHB ldb R$B,u B=block count + ldy R$Y,u + bsr L0A31 + bcs L0A30 + sta R$A,u +L0A30 rts + +L0A31 tfr b,a +L0A33 suba #$09 + nega + pshs x,b,a + ldd #$FFFF + pshs b,a + bra L0A58 + +FFreeLB ldb R$B,u + ldy R$Y,u + bsr L0A4B + bcs L0A4A + sta R$A,u +L0A4A rts + +L0A4B lda #$FF + pshs x,b,a + lda #$01 + subb #$09 + negb + pshs b,a + bra L0A58 + +L0A58 clra + ldb $02,s + addb ,s + stb $02,s + cmpb $01,s + bne L0A75 + ldb #$CF + cmpy <D.SysDAT + bne L0A6C + ldb #$ED +L0A6C stb $03,s + comb + bra L0A82 + +L0A71 tfr a,b + addb $02,s +L0A75 lslb + ldx b,y + cmpx #DAT.Free + bne L0A58 + inca + cmpa $03,s + bne L0A71 +L0A82 leas $02,s + puls pc,x,b,a + +FSetImg ldd R$A,u + ldx R$X,u + ldu R$U,u +L0A8C pshs u,y,x,b,a + leay P$DATImg,x + lsla + leay a,y +L0A94 ldx ,u++ + stx ,y++ + decb + bne L0A94 + ldx $02,s get proc desc ptr + lda P$State,x + ora #ImgChg + sta P$State,x + clrb + puls pc,u,y,x,b,a + +FDATLog ldb R$B,u + ldx R$X,u + bsr L0AB0 + stx R$X,u + clrb + rts + +*L0AB0 pshs x,b,a --BGP +L0AB0 pshs x,b ++BGP + lslb + lslb + lslb + lslb + lslb +* addb $02,s --BGP +* stb $02,s --BGP + addb 1,s ++BGP + stb 1,s ++BGP +* puls pc,x,b,a --BGP + puls pc,x,b ++BGP + +FLDAXY ldx R$X,u + ldy R$Y,u + bsr L0AC8 + sta R$A,u + clrb + rts + +L0AC8 pshs cc + lda $01,y + orcc #IntMasks + sta >DAT.Regs + lda ,x + clr >DAT.Regs + puls pc,cc + +LDAXY bsr L0AC8 + leax $01,x + bra L0AF0 + +L0AEA leax >-$2000,x + leay $02,y +L0AF0 cmpx #$2000 + bcc L0AEA + rts + +FLDDDXY ldd R$D,u + leau R$X,u + pulu y,x + bsr LDDXY + std -$07,u + clrb + rts +LDDXY pshs y,x + leax d,x + bsr L0AF0 + bsr LDAXY + pshs a + bsr L0AC8 + tfr a,b + puls pc,y,x,a + +FLDABX ldb R$B,u + ldx R$X,u + lbsr L0C12 + sta R$A,u + rts + +FSTABX ldd R$D,u + ldx R$X,u + lbra L0C28 + +FMove ldd R$D,u + ldx R$X,u + ldy R$Y,u + ldu R$U,u +L0B2C pshs u,y,x,b,a + leay ,y + lbeq L0BF2 + pshs y,b,a + tfr a,b + lbsr L0C0F + leay a,u + pshs y,x + ldb $09,s + ldx $0E,s + lbsr L0C0F + leay a,u + pshs y,x + ldd #$2000 + subd ,s + pshs b,a + ldd #$2000 + subd $06,s + pshs b,a + ldx $08,s + leax >-$6000,x + ldu $04,s + leau >-$4000,u +L0B6A pshs cc + ldd [<$07,s] + pshs b + ldd [<$0C,s] + pshs b + ldd <$11,s + cmpd $03,s + bls L0B82 + ldd $03,s +L0B82 cmpd $05,s + bls L0B89 + ldd $05,s +L0B89 cmpd #$0040 + bls L0B84 + ldd #$0040 +L0B84 std $0F,s + puls y + orcc #IntMasks + sty >$FFA5 + andb #$07 + beq L0B99 +L0B92 lda ,x+ + sta ,u+ + decb + bne L0B92 +L0B99 ldb $0E,s + lsrb + lsrb + lsrb + beq L0BBC + pshs b + exg x,u +L0BA4 pulu y,b,a + std ,x + sty $02,x + pulu y,b,a + std $04,x + sty $06,x + leax $08,x + dec ,s + bne L0BA4 + leas $01,s + exg x,u +L0BBC ldy <D.SysDAT + lda $0B,y + ldb $0D,y + std >$FFA5 + puls cc + ldd $0E,s + subd $0C,s + beq L0BEF + std $0E,s + ldd ,s + subd $0C,s + bne L0BD7 + ldd #$2000 + leax >-$2000,x + inc $0B,s + inc $0B,s +L0BD7 std ,s + ldd $02,s + subd $0C,s + bne L0BEA + ldd #$2000 + leau >-$2000,u + inc $07,s + inc $07,s +L0BEA std $02,s + lbra L0B6A +L0BEF leas <$10,s +L0BF2 clrb + puls pc,u,y,x,b,a + +L0BF5 pshs b + tfr x,d + anda #$1F + exg d,x + anda #$E0 + lsra + lsra + lsra + lsra +L0C07 puls pc,b +L0C0F bsr L0BF5 +*L0C09 pshs b --BGP +L0C09 + ldu <D.TskIPt + lslb + ldu b,u + rorb ++BGP +* puls pc,b --BGP + rts ++BGP + +L0C12 andcc #^Carry + pshs u,x,b,cc + bsr L0C0F + ldd a,u + orcc #IntMasks + stb >DAT.Regs + lda ,x + clr >DAT.Regs + puls pc,u,x,b,cc + +L0C28 andcc #^Carry + pshs u,x,b,a,cc + bsr L0C0F + ldd a,u + lda $01,s + orcc #IntMasks + stb >DAT.Regs + sta ,x + clr >DAT.Regs + puls pc,u,x,b,a,cc + +FLDBBX andcc #^Carry + pshs u,x,a,cc + bsr L0C0F + ldd a,u + orcc #IntMasks + stb >DAT.Regs + ldb ,x + clr >DAT.Regs + puls pc,u,x,a,cc + +FAllTsk ldx R$X,u +L0C58 ldb P$Task,x + bne L0C64 + cmpx <$004A + beq L0C64 + bsr L0CA6 + bcs L0C65 + stb P$Task,x + bsr L0C79 +L0C64 clrb +L0C65 rts + +FDelTsk ldx R$X,u get proc desc ptr +L0C68 ldb P$Task,x + beq L0C65 + clr P$Task,x + bra L0CC3 +L0C70 lda P$State,x + bita #ImgChg + bne L0C79 + rts + +FSetTsk ldx R$X,u +L0C79 lda P$State,x + anda #^ImgChg + sta P$State,x + andcc #^Carry + pshs u,y,x,b,a,cc + ldb P$Task,x + leax P$DATImg,x + ldu <D.TskIPt + lslb + stx b,u + cmpb #$02 + bgt L0C9F + ldu #DAT.Regs + leax 1,x + ldb #$08 +L0C98 lda ,x++ + sta ,u+ + decb + bne L0C98 +L0C9F puls pc,u,y,x,b,a,cc + +FResTsk bsr L0CA6 + stb R$B,u + rts + +L0CA6 pshs x + ldb #$02 + ldx <D.Tasks +L0CAC lda b,x + beq L0CBA + incb + cmpb #$20 + bne L0CAC + comb + ldb #$EF + bra L0CBF + +L0CBA inc b,x + clra +L0CBF puls pc,x + +FRelTsk ldb R$B,u +L0CC3 pshs x,b + tstb + beq L0CD0 + ldx <D.Tasks + clr b,x +L0CD0 puls pc,x,b + +* Control goes here when a tick interrupt comes in +Clock ldb #P$STicks assume system state + ldx <D.Proc get curr process + lda P$State,x get process state + bmi L0CDC branch if SysState + ldb #P$UTicks otherwise user state +L0CDC lbsr IncCount count ticks + ldx <D.SProcQ point to sleep queue + beq L0CFD branch if no process sleeping +* Process sleep queue here! +* Sleep queue is sorted by process closest to wake first, all the way +* to processes that are sleeping forever. + lda P$State,x get process' state + bita #TimSleep sleeping forever? + beq L0CFD yep, finished + ldu P$SP,x else get process' stack pointer + ldd R$X,u and get process' sleep tick counter + subd #$0001 subtract 1 from tick counter + std R$X,u save back to process' X + bne L0CFD branch if not ready to wake +L0CE7 ldu P$Queue,x else time to wake up! so... + bsr L0D11 activate this process + leax ,u point to next process + beq L0CFB + lda P$State,x + bita #TimSleep + beq L0CFB + ldu P$SP,x + ldd R$X,u + beq L0CE7 +L0CFB stx <D.SProcQ store new process pointer +L0CFD dec <D.Slice decrement slice + bne L0D0D branch if not at end of timeslice + inc <D.Slice + ldx <D.Proc get current process + beq L0D0D branch if none + lda P$State,x ...else get state + ora #TimOut and indicate it's out of time + sta P$State,x then restore it +L0D0D clrb + rts + +* X = address of process descriptor to put in active queue +FAProc ldx R$X,u +L0D11 clrb + pshs u,y,x,b,cc + lda P$Prior,x get priority of process + sta P$Age,x reset age to priority + orcc #IntMasks mask interrupts + ldu #$0045 + bra L0D29 +L0D1F inc $0B,u + bne L0D25 + dec $0B,u +L0D25 cmpa $0B,u + bhi L0D2B +L0D29 leay ,u +L0D2B ldu $0D,u + bne L0D1F + ldd $0D,y + stx $0D,y + std $0D,x + puls pc,u,y,x,b,cc + +* System IRQ service routine + +XIRQ ldx <D.Proc + sts P$SP,x + lds <D.SysStk + ldd <D.SysSvc + std <D.XSWI2 + ldd <D.SysIRQ + std <D.XIRQ + jsr [>D.SvcIRQ] + bcc L0D5B + ldx <D.Proc + ldb P$Task,x + ldx P$SP,x + lbsr L0C12 + ora #IntMasks + lbsr L0C28 +L0D5B orcc #IntMasks + ldx <D.Proc + lda P$State,x + bita #TimOut + bne L0D7C +L0D78 ldu $04,x + bra L0DB9 +L0D7C anda #$DF + sta $0C,x + lbsr L0C68 +L0D83 bsr L0D11 + +FNProc ldx <D.SysPrc + stx <D.Proc + lds <D.SysStk + andcc #^(IntMasks) + bra L0D93 + +L0D91 cwai #^(IntMasks) +L0D93 orcc #IntMasks + lda #Suspend + ldx #$0045 +L0D9A leay ,x + ldx $0D,y + beq L0D91 + bita P$State,x + bne L0D9A + ldd P$Queue,x + std $0D,y + stx <D.Proc + lbsr L0C58 + bcs L0D83 + lda <D.TSlice + sta <D.Slice + ldu P$SP,x + lda P$State,x + bmi L0E29 +L0DB9 bita #Condem + bne L0DFD + lbsr L0C70 + ldb P$Signal,x + beq L0DF2 + decb + beq L0DEF + leas -$0C,s + leau ,s + lbsr L02CB + lda P$Signal,x + sta $02,u + ldd P$SigVec,x + beq L0DFD + std $0A,u + ldd P$SigDat,x + std $08,u + ldd P$SP,x + subd #$000C + std P$SP,x + lbsr L02DA + leas $0C,s + ldu P$SP,x + clrb +L0DEF stb P$Signal,x +L0DF2 ldd <D.UsrSvc + std <D.XSWI2 + ldd <D.UsrIRQ + std <D.XIRQ + bra L0E4C +L0DFD lda P$State,x + ora #SysState + sta P$State,x + leas $0200,x + andcc #^(IntMasks) + ldb P$Signal,x + clr P$Signal,x + os9 F$Exit + +* Interrupts come through here when in system state +S.SysIRQ lda <D.SSTskN get system task number + clr <D.SSTskN clear system task number in globs + pshs a save on stack + jsr [>D.SvcIRQ] + puls a + bsr L0E39 + bcc XFIRQ + ldb R$CC,s + orb #IntMasks + stb R$CC,s +XFIRQ rti + +L0E29 clr ,-s +L0E2B ldx <D.SysPrc + lbsr L0C70 + orcc #IntMasks + puls a + bsr L0E39 + leas ,u + rti + +* A = task number +L0E39 sta <D.SSTskN + beq S.AltIRQ + ora <D.TINIT + sta <D.TINIT + sta DAT.Task +S.AltIRQ rts + +S.SvcIRQ jmp [>D.Poll] +S.POLL orcc #Carry + rts + +L0E4C ldb $06,x + orcc #IntMasks + bsr L0E8D + lda <D.TINIT + ora #$01 + sta <D.TINIT + sta DAT.Task + leas ,u + rti + +L0E5E ldb <D.TINIT + orb #$01 + stb <D.TINIT + stb DAT.Task + jmp ,u + +S.Flip0 pshs b,a + lda <D.TINIT + anda #$FE + sta <D.TINIT + sta DAT.Task + clr <D.SSTskN + puls b,a + tfr x,s + tfr a,cc + rts + +S.Flip1 ldb #$01 get task image entry number + bsr L0E8D copy over the DAT image + lda <D.TINIT get copy of GIME Task side + ora #$01 switch it to task one + sta <D.TINIT save it to image + sta DAT.Task save it to GIME register + inc <D.SSTskN increment system tstae task number + rti return + +L0E8D pshs u,x,b,a + ldx #$FFA8 get MMU start register for process + ldu <D.TskIPt get task image pointer table + lslb account for 2 bytes per entry + ldu b,u get address of MMU entry + leau $01,u + ldb #$08 +L0E9B lda ,u++ + sta ,x+ + decb + bne L0E9B + puls pc,u,x,b,a + +* SWI3.V - Control comes here upon a SWI3 interrupt +SWI3.V orcc #IntMasks mask interrupts + ldb #D.SWI3 get direct page global vector + bra IRQCntrl + +* SWI2.V - Control comes here upon a SWI2 interrupt +SWI2.V orcc #IntMasks mask interrupts + ldb #D.SWI2 get direct page global vector + bra IRQCntrl + +* FIRQ.V - Control comes here upon a FIRQ interrupt +FIRQ.V tst ,s + bmi L0EB0 + leas -$01,s + pshs y,x,dp,b,a + lda $08,s + stu $07,s + ora #$80 + pshs a +L0EB0 ldb #D.FIRQ + bra IRQCntrl + +* IRQ.V - Control comes here upon a IRQ interrupt +IRQ.V orcc #IntMasks mask interrupts + ldb #D.IRQ get direct page global vector +* B = address of vector from direct page +IRQCntrl clra clear A + tfr a,dp make DP point to 0 + sta DAT.Task redundancy??? + lda <D.TINIT get task register shadow + anda #$FE clear bit to use $FFA0-$FFA7 + sta <D.TINIT save in shadow + sta DAT.Task save in hardware (do it!) + clra clear A + tfr d,x D = addr of direct page vector + jmp [,x] transfer control to addr in passed vector + +* SWI.V - Control comes here upon a SWI interrupt +SWI.V ldb #D.SWI get direct page global vector + bra IRQCntrl + +* NMI.V - Control comes here upon a NMI interrupt +NMI.V ldb #D.NMI get direct page global vector + bra IRQCntrl + +* Filler bytes to get $ED9 +Filler fcb $39,$39,$39,$39,$39,$39,$39,$39,$39,$39 +* fcb $39,$39,$39,$39,$39,$39,$39,$39,$39,$39 + + emod +eom equ * + +* Direct Page vectors +D.VECTRS fdb $F100+Clock goes in D.Clock + fdb $F100+XSWI3 goes in D.XSWI3 + fdb $F100+XSWI2 goes in D.XSWI2 + fdb $F100+XFIRQ goes in D.XFIRQ + fdb $F100+XIRQ goes in D.XIRQ + fdb $F100+XSWI goes in D.XSWI + fdb $F100 goes in D.NMI + fcb $55 +* 6809 vectors +* This table starts at $FEEE. Each address is pointed to by the 6809 +* vectors at $FFF0 (defined in the CoCo 3 ROM). + lbra SWI3.V SWI3 + lbra SWI2.V SWI2 + lbra FIRQ.V FIRQ + lbra IRQ.V IRQ + lbra SWI.V SWI + lbra NMI.V NMI + +eo equ * + end