.FILE 'MPROC.ASM' .TITLE "GSP MULTI-PROCESSING SYSTEM VERSION 1.0 EUGENE P. JARVIS" ************************************************************************** * * * COPYRIGHT (C) 1988 WILLIAMS ELECTRONICS GAMES, INC. * * ALL RIGHTS RESERVED. * * * ************************************************************************** .WIDTH 132 .OPTION B,D,L,T .MNOLIST * *FILES REQUIRED FOR ASSEMBLY * .INCLUDE \video\GSP.INC ;GSP Assembler Equates .INCLUDE \video\SYS.INC ;Zunit System Equates .INCLUDE \video\MPROCEQU.ASM ;MPROC Equates .INCLUDE \video\DISPEQU.ASM * * SET UP FIXED PARAMETERS AT THE BEGINNING OF SCRATCHPAD * .SECT "FIXED" ACTIVE .LONG 0 FREE .LONG 0 * *GLOBAL PROCESS VARIABLES * .BSS TIMER,16 ;IRQ TIMER 16 MSEC. .BSS TIMETEMP,16 ;LAST TIMER VALUE .BSS OVERLOAD,16 ;OVERLOAD CHECKER .BSS PRCSTR,NPROC*PRCSIZ ;PROCESS STORE ALLOCATION * *MULTI-PROCESSING PROGRAM * .TEXT ;STORE IN PROGRAM ROM * *PROCESS DISPATCH * PRCDSP: MOVI ACTIVE,A13,L ;LONG WORD INIT SCAN PROCESS LIST PRCWTSRT CALLA YZSORT ;SORT DISPLAY LIST MOVE @TIMER,A0 JREQ PRCWTSRT ;BR = WAIT FOR TIMING FROM INTERRUPT, SORT MOVE A0,@TIMETEMP,W ;SAVE SLL 1,A0 MOVE @OVERLOAD,A1,W ADD A0,A1 SRL 1,A1 MOVE A1,@OVERLOAD,W CALLA L_TIMER CLR A0 MOVE A0,@TIMER JRUC PRCD1 * *PROCESS SLEEP *TOS IS WAKEUP ADDR ,A0 = SLEEP TIME * PRCSLP: MMFM SP,A7 ;CALLING PC->A7 PRCLSP: MMTM A12,A7,A8,A9,A10,A11 ;SAVE REGS MOVE A0,*A13(PTIME) ;SAVE SLEEP TIME MOVE A12,*A13(PSPTR),L ;SAVE STACK POINTER MOVE A13,A0 .if DEBUG ;this is for DEBUG only ADDI PSDATA,A0 CMP A0,A12 JRLT $ ;Stick on Stack overflow ADDI PRCSIZ-PSDATA,A0 CMP A0,A12 JRGT $ ;Stick on Stack underflow .endif PRCD1: MOVE @TIMETEMP,A1,W ;GET THE LAST TIMER VALUE PRCD1A MOVE *A13,A13,L JREQ PRCDX ;NULL LIST, EXIT MOVE *A13(PTIME),A0 ;GET COUNT SUB A1,A0 ************************************************************************** * * * DEC A0 ;DECREMENT COUNT * * * ************************************************************************** MOVE A0,*A13(PTIME) ;PUT IT BACK JRGT PRCD1A ;NOT READY, LOOP FOR NEXT *PROCESS IS READY FOR DISPATCH PRCD2: MOVE *A13(PSPTR),A12,L ;SET UP STACK POINTER MMFM A12,A7,A8,A9,A10,A11 ;GET SAVED REGS JUMP A7 ;GO DO IT *DONE WITH THE SCAN PRCDX: RETS * *PROCESS SUICIDE * SUCIDE: MOVI ACTIVE,A1,L SUCLP: MOVE A1,A2 ;SAVE PREVIOUS MOVE *A1,A1,L SUCERR: JREQ SUCERR ;PROCESS DOES NOT EXIST, ERROR CMP A1,A13 ;CHECK FOR MATCH TO CURRENT PROCESS JRNE SUCLP ;NOT FOUND KEEP LOOKING MOVE *A1,*A2,L ;LINK AROUND IN ACTIVE LIST MOVE @FREE,A0,L ;GET FREE POINTER MOVE A0,*A1,L ;LINK INTO FREE LIST AT START MOVE A1,@FREE,L MOVE A2,A13 ;SET CURRENT PROCESS TO PREVIOUS JRUC PRCD1 ;CONTINUE WITH DISPATCH * *PROCESS LIST INITIALIZE *A13 RETURNED POINTING TO ACTIVE LIST (CRPROC) PINIT: MMTM SP,A0,A1,A2,A3 ;SAVE REG MOVI NPROC,A3,W ;# OF PROCESSES TO INIT CLR A0 MOVE A0,@ACTIVE,L ;NULL ACTIVE LIST MOVI PRCSTR,A1,L MOVE A1,@FREE,L ;SETUP FREE LIST PINITL: MOVE A1,A2 ADDI PRCSIZ,A1,W MOVE A1,*A2,L ;LINK EM UP DSJS A3,PINITL ;CONTINUE FOR NPROC MOVE A0,*A2,L ;ZERO LAST LINK MOVI ACTIVE,A13,L ;INIT CURRENT PROCESS MMFM SP,A0,A1,A2,A3 ;RESTORE REGS RETS * *KILL PROCESS *A0 POINTS TO PROCESS TO KILL *IF PROCESS NOT PRESENT, CAUSES ERROR *TO KILL YOURSELF SUCIDE MUST BE USED, *IF YOU ATTEMPT TO KILL YOURSELF IT WILL JUST RETURN * KILL: CMP A0,A13 ;KILLING YOURSELF? JREQ KILLXXX ;BR = YES, JUST ESCAPE MMTM SP,A1,A2 MOVI ACTIVE,A1,L KILLP: MOVE A1,A2 ;SAVE PREVIOUS MOVE *A1,A1,L JRNZ KILLCHK CALLERR 2 ;LOG THE ERROR JRUC KILLX **** .if DEBUG ;this is for DEBUG only **** JREQ $ ;PROCESS DOES NOT EXIST, ERROR **** .endif KILLCHK CMP A1,A0 JRNE KILLP ;NOT FOUND KEEP LOOKING MOVE *A0,*A2,L ;LINK AROUND IN ACTIVE LIST MOVE @FREE,A1,L ;LINK INTO FREE LIST AT START MOVE A1,*A0,L MOVE A0,@FREE,L KILLX MMFM SP,A1,A2 KILLXXX RETS * *CREATE A PROCESS *A1=ID,A7=PC,A8,A9,A10,A11 PASSED PARAMETERS *A13=CURRENT PROCESS *A0 IS RETURNED POINTING TO CREATED PROCESS * GETPRC: MMTM SP,A2 MOVE @FREE,A0,L JREQ GETPX ;NONE AVAILABLE MOVE *A0,A2,L MOVE A2,@FREE,L ;REMOVE FROM FREE LIST MOVE *A13,*A0,L ;LINK INTO ACTIVE LIST AFTER CURRENT PROCESS MOVE A0,*A13,L ;CRPROC>>NEW PROC MOVE A1,*A0(PROCID) MOVE A0,A2 ADDI PRCSIZ,A2 ;FORM PROCESS STACK POINTER MMTM A2,A7,A8,A9,A10,A11 MOVE A2,*A0(PSPTR),L ;PUT IN STACK POINTER MOVK 1,A2 ;INIT SLEEP TIME MOVE A2,*A0(PTIME) GETPX: MMFM SP,A2 RETS ************************************************************************** * * * XFERPROC - TRANSFER CONTROL OF AN EXISTING PROCESS * * A0 = PTR OF PROCESS TO BE XFER'D * * A1 = NEW I.D. * * A7 = WAKE UP * * A8 - A11 = PASSED TO THE XFER'D PROC * * * ************************************************************************** XFERPROC PUSH A14 MOVE A1,*A0(PROCID),W MOVK 1,A14 MOVE A14,*A0(PTIME),W ;WAKE UP AS SOON AS POSSIBLE MOVE A0,A14 ADDI PRCSIZ,A14 ;RESET PROCESS STACK POINTER MMTM A14,A7,A8,A9,A10,A11 ;STUFF THE SHIT MOVE A14,*A0(PSPTR),L PULL A14 RETS * *KILL A CLASS OF PROCESSES *A0=PROCID (16 BITS) ,A1=MASK (16 BITS) *MASK BITS OF ZERO ARE DONT CARES *WILL NOT KILL CALLING PROCESS (A13) * KILALL: MMTM SP,A0,A1,A2,A3,A4,A5 AND A1,A0 ;FORM MATCH MOVI ACTIVE,A2,L KILALP: MOVE A2,A3 ;SAVE PREVIOUS MOVE *A2,A2,L ;GET NEXT JREQ KILALX ;ALL DONE MOVE *A2(PROCID),A4 AND A1,A4 ;CAN DONT CARE BITS CMP A0,A4 ;MATCH? JRNE KILALP ;NO CMP A2,A13 ;CURRENT PROCESS? JREQ KILALP ;YES DONT KILL MOVE *A2,*A3,L ;LINK AROUND IN ACTIVE LIST MOVE @FREE,A5,L ;LINK INTO FREE LIST AT START MOVE A5,*A2,L MOVE A2,@FREE,L ;POINT FREE TO CELL MOVE A3,A2 JRUC KILALP ;KILL THE REST KILALX: MMFM SP,A0,A1,A2,A3,A4,A5 RETS * *FIND IF AT LEAST ONE PROCESS, OTHER THAN CALLING PROCESS, *EXISTS. *A0=PROCID (16 BITS) ,A1=MASK (16 BITS) *MASK BITS OF ZERO ARE DONT CARES *RETURNS: * Z BIT SET = NO MATCH, A0 = 0 * Z BIT CLR = MATCH, A0 = PTR TO PROCESS * EXISTP: MMTM SP,A1,A2,A4 AND A1,A0 ;FORM MATCH MOVI ACTIVE,A2,L EXNXT: MOVE *A2,A2,L ;GET NEXT JREQ EXSC ;ALL DONE MOVE *A2(PROCID),A4 AND A1,A4 ;CAN DONT CARE BITS CMP A0,A4 ;MATCH? JRNE EXNXT ;NO CMP A2,A13 ;CURRENT PROCESS? JREQ EXNXT ;YES, THEN WE DON'T CARE EXSC MOVE A2,A0 MMFM SP,A1,A2,A4 RETS *GET A PRESERVED REGISTER FROM A SLEEPING PROCESS *A0 = PTR TO SLEEPER GETA11 MOVE A1,-*SP,L CLR A1 CALLR GETSLW MOVE A1,A11 MMFM SP,A1 RETS GETA10 MOVE A1,-*SP,L MOVI 20H,A1 CALLR GETSLW MOVE A1,A10 MMFM SP,A1 RETS GETA9 MOVE A1,-*SP,L MOVI 40H,A1 CALLR GETSLW MOVE A1,A9 MMFM SP,A1 RETS GETA8 MOVE A1,-*SP,L MOVI 60H,A1 CALLR GETSLW MOVE A1,A8 MMFM SP,A1 RETS *GET A LONG WORD FROM THE STACK OF A SLEEPING PROCESS *A0 = PTR TO SLEEPING PROC *A1 = OFFSET OF WORD FROM STACK POINTER *A2 = CURRENT STACK PTR *RETURN(S) *A1 = LONG WORD GETSLW MOVE A2,-*SP,L MOVE *A0(PSPTR),A2,L ;GET THE STACK POINTER ADD A1,A2 ;ADD THE OFFSET MOVE *A2,A1,L ;MOVE IN THE LONG WORD MOVE *SP+,A2,L RETS *PUT A REGISTER(A8-A11) INTO A SLEEPING PROCESS *A0 = PTR TO SLEEPER PUTA11 MMTM SP,A1,A2 CLR A1 MOVE A11,A2 JRUC PUTSLW PUTA10 MMTM SP,A1,A2 MOVI 20H,A1 MOVE A10,A2 JRUC PUTSLW PUTA9 MMTM SP,A1,A2 MOVI 40H,A1 MOVE A9,A2 JRUC PUTSLW PUTA8 MMTM SP,A1,A2 MOVI 60H,A1 MOVE A8,A2 *PUT A LONG WORD INTO THE STACK OF A SLEEPING PROCESS *A0 = PTR TO SLEEPING PROC *A1 = INDEX INTO STACK *A2 = VALUE TO PUT PUTSLW MMTM SP,A3 MOVE *A0(PSPTR),A3,L ;GET THE STACK POINTER ADD A1,A3 ;ADD THE OFFSET MOVE A2,*A3,L MMFM SP,A1,A2,A3 RETS .END