home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1993-10-23 | 13.7 KB | 345 lines |
- IMPLEMENTATION MODULE Process[7];
-
- FROM SYSTEM IMPORT
- ADDRESS, WORD, BYTE, REG, SETREG, ADR, TSIZE, VAL, INLINE;
- (*FROM InOut IMPORT
- WriteString, WriteLn, WriteLongHex, Read;
- *)
-
- CONST
- ModuleBase = 12;
- ProcessBase = 13;
- FramPointer = 14;
- StackPointer = 15;
-
-
- CONST
- InitialStatus = M68000StatusRegister{sbIntMask0, sbIntMask1};
- (* Special for ATARI: all Processes are running on Interrupt Level 3 *)
- MinimumStackSize = 256; (* ??? *)
-
- TYPE
- InitialStack =
- RECORD
- Context : M68000Context;
- SavedReturnPC : PROC;
- END; (* InitialStack *)
-
- PROCEDURE LISTEN;
- (*
- LISTEN: move.w sr,d0
- trap #11 * switch to supervisormode
- move.w #$0300,sr * interrupt allowed, usermode
- nop
- nop
- trap #11
- move.w d0,sr * restore old SR
- *)
- BEGIN
- INLINE( 040C0H,04E4BH,046FCH,00300H,04E71H,04E71H,04E4BH,046C0H );
- END LISTEN;
-
- PROCEDURE CoRoutineEnd();
- BEGIN
- (* This Procedure is never called directly. An illegally terminating
- process will enter this procedure loading a return address from its
- stack, which has been saved there by NEWPROCESS
- *)
- IF MainPROCESSPtr <> NIL THEN
- TRANSFER( ErrorPROCESS, MainPROCESSPtr^ );
- ELSE HALT; END;
- END CoRoutineEnd;
-
-
- PROCEDURE NEWPROCESS (ProcessCode : PROC;
- WorkSpaceBase : ADDRESS;
- WorkSpaceSize : LONGCARD;
- VAR ProcessDesc : PROCESS );
- TYPE
- InitialStackPointer = POINTER TO InitialStack;
- LongIntPtr = POINTER TO LONGINT;
-
- VAR
- InitialStackPtr : InitialStackPointer;
- WorkSpacePtr,
- WorkSpaceEnd : LongIntPtr;
- savemask : CARDINAL;
-
- BEGIN
- (* Check process workspace *)
- IF ODD( WorkSpaceBase ) THEN HALT; END;
- IF WorkSpaceSize < VAL( LONGCARD, MinimumStackSize ) THEN HALT; END;
- IF ProcessDesc = NIL THEN (* Clear workspace for size and access test *)
- WorkSpacePtr := VAL( LongIntPtr, WorkSpaceBase );
- WorkSpaceEnd :=
- VAL( LongIntPtr, VAL( LONGCARD, WorkSpaceBase )
- + WorkSpaceSize
- - VAL( LONGCARD, 3 ) );
- WHILE VAL( LONGCARD, WorkSpacePtr ) < VAL( LONGCARD, WorkSpaceEnd ) DO
- WorkSpacePtr^ := 0;
- INC( VAL( LONGINT, WorkSpacePtr ), 4 );
- END; (* FOR *)
- END; (* IF *)
- InitialStackPtr := VAL( InitialStackPointer,
- VAL( LONGCARD, WorkSpaceBase)
- + WorkSpaceSize
- - VAL( LONGCARD, TSIZE(InitialStack))
- );
- WITH InitialStackPtr^ DO
- WITH Context DO
- ModuleBaseA4 := REG(ModuleBase);
- (* ProcessBase auf das obere Ende, (MODEP-Process-Descriptor) *)
- Valid := NIL; (*DS*)
- ProcessBaseA5 := WorkSpaceBase+VAL(ADDRESS,WorkSpaceSize); (*DS*)
- FramePointerA6 := NIL;
- StackPointerA7 := NIL;
- StatusRegister := InitialStatus;
- ProgramCounter := ProcessCode;
- END; (* WITH *)
- SavedReturnPC := CoRoutineEnd;
- END; (* WITH *)
- ProcessDesc := VAL( PROCESS, InitialStackPtr );
- END NEWPROCESS;
-
- PROCEDURE InstallTrap();
- (* Calling this Routine installs all Assembler routines *)
- (*
-
- *
- * - der SUPERVISORMODE ist nicht erlaubt (in MODEB nicht nötig)
- *
- * dadurch ergibt sich daß TRANSFER,IOTRANSFER nur vom Usermode aufgerufen
- * werden. Beim INT muß ein Unterscheidung sttatfinden und beim Übergangen
- * S -> U der USP bzw. bei U -> S der SSP gerettet werden. Der letzter Fall
- * kommt aber eigentlich nie vor. Sämtliche load's speicheren den zusätzs-
- * lichen Stackpointer gegebenenfalls zurück.
-
-
- trap3 = $8c * TRANSFER
- trap4 = $90 * IOTRANSFER
-
- call = $4eb9
- stop_int = $46fc2700
-
- magic = $04091964
-
- INIT: move.w sr,d0 * save old mode
- trap #11 * Supervisormode
- lea TRANSFER-*-2(pc),a0
- move.l a0,trap3
- lea IOTRANSFER-*-2(pc),a0
- move.l a0,trap4
- move.w d0,sr * now old mode again
- bra exit
-
- * in Usermode:
- *
- * (A0) USP -> ^To.l (A1)
- * ^From.l (A2)
- * :
- *
- * SSP -> Sr.w (D0)
- * Pc.l
- * :
- * only A4,A5,A6 must be saved !
-
- TRANSFER: move.w #$2700,sr * no interrupt allowed
- move.w (a7)+,d0 * get SR
-
- utrans: move.l usp,a0 * get USP
- move.l (a0)+,a1 * pointer to "to"
- move.l (a0),a2 * pointer to "from", USP now clean
- move.l (a7)+,(a0) * PC, SSP now clean
- move.w d0,-(a0) * SR
- clr.l -(a0) * Stack=NIL
- movem.l a4-a6,-(a0) * save important registers
- lea -$30(a0),a0 * rest of registers
- move.l #magic,-(a0) * MAGIC setzen
- move.l a0,usp * set new USP
- move.l (a1),a6 * load "to"
- move.l a0,(a2) * save "from"
- btst.b #5,$44(a6) * new process in supervisormode ?
- bne sload
-
- uload: lea $4a(a6),a0 * top of context
- move.l a0,usp * set new USP to "to"
- move.l $40(a6),d1 * get stack
- beq ul_nil * NIL, don't load
- move.l d1,a7 * load SSP
- ul_nil: move.l -(a0),-(a7) * PC
- move.w -(a0),-(a7) * SR
- clr.l (a6)+ * MAGIC löschen
- movem.l (a6)+,d0-a5 * restore registers
- move.l (a6),a6 * A6
- rte
-
- sload: move.l a6,a7 * set new SSP to "to"
- move.l $40(a7),d1 * get stack
- beq sl_nil * NIL, don't load
- move.l d1,a1
- move.l a1,usp * load USP
- sl_nil: clr.l (a7)+ * MAGIC löschen
- movem.l (a7)+,d0-a6 * restore registers
- tst.l (a7)+ * discharge stack
- rte
-
-
- * in Usermode:
- *
- * (A0) USP -> Vector.l (A1)
- * ^To.l (A2)
- * ^From.l (A3)
- * :
- *
- * SSP -> Sr.w (D0)
- * Pc.l
- * :
-
- IOTRANSFER: move.w #$2700,sr * no interrupt allowed
- move.w (a7)+,d0 * get SR
-
- uiotrans: move.l usp,a0 * get USP
- movem.l (a0)+,a1-a3 * clean up USP
- move.l (a7)+,-(a0) * PC, SSP now clean
- move.w d0,-(a0) * SR
- clr.l -(a0) * stack=NIL
- movem.l a4-a6,-(a0) * save important registers
- move.l a2,-(a0) * A3: Pointer to "to"
- lea -$2c(a0),a0 * rest of registers
- move.l #magic,-(a0) * MAGIC setzen
- move.l (a2),a6 * load "to"
- move.l a0,(a3) * save "from"
- lea INT-*-2(pc),a2 * interrupt routine
- move.l a2,-(a0) * push
- move.w #call,-(a0) * push JSR opcode
- move.l #stop_int,-(a0) * push MOVE.W #$2700,SR opcode
- move.l a0,(a1) * set vector
- move.l a0,usp * set new USP
- btst.b #5,$44(a6) * new process in supervisormode ?
- bne sioload
-
- uioload: lea $4a(a6),a0 * top of context
- move.l a0,usp * set new USP to "to"
- move.l $40(a6),d1 * get stack
- beq uio_nil * NIL, don't load
- move.l d1,a7 * load SSP
- uio_nil: move.l -(a0),-(a7) * PC
- move.w -(a0),-(a7) * SR
- clr.l (a6)+ * MAGIC löschen
- movem.l (a6)+,d0-a5 * restore registers
- move.l (a6),a6 * A6
- rte
-
- sioload: move.l a6,a7 * set new SSP to "to"
- move.l $40(a7),d1 * get stack
- beq sio_nil * NIL, don't load
- move.l d1,a1
- move.l a1,usp * load USP
- sio_nil: clr.l (a7)+ * MAGIC löschen
- movem.l (a7)+,d0-a6 * resore registers
- tst.l (a7)+ * discharge stack
- rte
-
- * SSP -> address of context to load (only A4-A6 important)
- * Sr.w
- * Pc.l
-
-
- INT: btst.b #5,4(a7) * process in supervisor mode ?
- bne sint
-
- uint: move.l a6,-(a7) * save A6
- move.l a5,-(a7) * save A5
- move.l usp,a6 * get USP
- lea -$12(a6),a6 * skip space for PC,SR,stack,A6,A5
- movem.l d0-a4,-(a6) * save registers
- move.l #magic,-(a6) * MAGIC setzen
- move.l a6,d0 * save context address
- move.l a6,usp * new USP
- lea $38(a6),a1 * get address for A5 in context
- move.l (a7)+,(a1)+ * A5
- move.l (a7)+,(a1)+ * A6
- clr.l (a1)+ * stack=NIL
- move.l (a7)+,a6 * context
- move.w (a7)+,(a1)+ * SR
- move.l (a7)+,(a1) * PC, SSP clean
- btst.b #5,$44(a6) * process in supervisormode ?
- beq uiload
- move.l a7,-6(a1) * save SSP
- bra siload
-
- uiload: lea $4a(a6),a0 * top of context
- move.l a0,usp * set USP
- clr.l (a6) * MAGIC löschen
- lea $30(a6),a1 * address of A3
- movem.l (a1)+,a3-a6 * restore registers
- move.l (a1),d1 * get stack
- beq ui_nil * NIL, don't load
- move.l d1,a7 * load SSP
- ui_nil: move.l d0,(a3) * save context in "to"
- move.l -(a0),-(a7) * PC
- move.w -(a0),-(a7) * SR
- rte
-
- sint: movem.l d0-a6,-(a7) * save registers
- move.l #magic,-(a7) * MAGIC setzen
- move.l a7,d0 * save context address
- move.l $40(a7),a6 * context to load
- clr.l $40(a7) * stack=NIL
- btst.b #5,$44(a6) * process in supervisormode ?
- bne siload
- move.l usp,a1
- move.l a1,$40(a7) * save USP
- bra uiload
-
- siload: lea $30(a6),a7 * address of A3
- clr.l (a6) * MAGIC löschen
- movem.l (a7)+,a3-a6 * restore registers
- move.l (a7)+,d1 * get stack
- beq si_nil * NIL, don't load
- move.l d1,a1
- move.l a1,usp * load USP
- si_nil: move.l d0,(a3) * save context in "to"
- rte
-
- exit: nop
-
- *)
- BEGIN
- INLINE( 040C0H,04E4BH,041FAH,018H,023C8H,00H,08CH,041FAH );
- INLINE( 06EH,023C8H,00H,090H,046C0H,06000H,016CH,046FCH );
- INLINE( 02700H,0301FH,04E68H,02258H,02450H,0209FH,03100H,042A0H );
- INLINE( 048E0H,0EH,041E8H,0FFD0H,0213CH,0409H,01964H,04E60H );
- INLINE( 02C51H,02488H,082EH,05H,044H,0661CH,041EEH,04AH );
- INLINE( 04E60H,0222EH,040H,06702H,02E41H,02F20H,03F20H,0429EH );
- INLINE( 04CDEH,03FFFH,02C56H,04E73H,02E4EH,0222FH,040H,06704H );
- INLINE( 02241H,04E61H,0429FH,04CDFH,07FFFH,04A9FH,04E73H,046FCH );
- INLINE( 02700H,0301FH,04E68H,04CD8H,0E00H,0211FH,03100H,042A0H );
- INLINE( 048E0H,0EH,0210AH,041E8H,0FFD4H,0213CH,0409H,01964H );
- INLINE( 02C52H,02688H,045FAH,04CH,0210AH,0313CH,04EB9H,0213CH );
- INLINE( 046FCH,02700H,02288H,04E60H,082EH,05H,044H,0661CH );
- INLINE( 041EEH,04AH,04E60H,0222EH,040H,06702H,02E41H,02F20H );
- INLINE( 03F20H,0429EH,04CDEH,03FFFH,02C56H,04E73H,02E4EH,0222FH );
- INLINE( 040H,06704H,02241H,04E61H,0429FH,04CDFH,07FFFH,04A9FH );
- INLINE( 04E73H,082FH,05H,04H,06654H,02F0EH,02F0DH,04E6EH );
- INLINE( 04DEEH,0FFEEH,048E6H,0FFF8H,02D3CH,0409H,01964H,0200EH );
- INLINE( 04E66H,043EEH,038H,022DFH,022DFH,04299H,02C5FH,032DFH );
- INLINE( 0229FH,082EH,05H,044H,06706H,0234FH,0FFFAH,06042H );
- INLINE( 041EEH,04AH,04E60H,04296H,043EEH,030H,04CD9H,07800H );
- INLINE( 02211H,06702H,02E41H,02680H,02F20H,03F20H,04E73H,048E7H );
- INLINE( 0FFFEH,02F3CH,0409H,01964H,0200FH,02C6FH,040H,042AFH );
- INLINE( 040H,082EH,05H,044H,06608H,04E69H,02F49H,040H );
- INLINE( 060BEH,04FEEH,030H,04296H,04CDFH,07800H,0221FH,06704H );
- INLINE( 02241H,04E61H,02680H,04E73H );
- END InstallTrap;
-
-
- BEGIN
- SETREG(ProcessBase, NIL); (* ProcessBase A5 for Main not yet used *)
- (* In Klevel register A5 for MainProcess and its KProcessDesc
- should be initialized for consistent process management *)
- MainPROCESSPtr := NIL;
- InstallTrap();
- END Process.
-
-