license
 
 .S .( Into traps.html)
	\ Have ago at aborting process
	: _abort_access_error TRUE ABORT" Access Error" ;
 	interrupt: TRAP02
		save_fault_stack

		panic_cr
		panic" Access Error" 
		panic_stack_frame
		panic_cr
		panic" Offending code"
		_#int_A7 @int_stack_frame _#int_user_return + @ $40 panic_show
[ #BCM550h #BCM550j + [IF] ]T
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		['] _abort_access_error int_return!
	;interrupt

	\ Have an attempt at abort the offending process
	: _abort_address_error TRUE ABORT" Address Error" ; 
 	interrupt: TRAP03
		save_fault_stack
[ #BCM550h #BCM550j + [IF] ]T
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		panic_cr
		panic" Address Error" 
		panic_stack_frame
		panic_cr
		panic" Offending code"
		_#int_A7 @int_stack_frame _#int_user_return + @ $40 panic_show

		['] _abort_address_error int_return!

	;interrupt
	
	\ Have an attempt at aborting the offending process
	: _abort_illegial_instruction TRUE ABORT" Illegal Instruction" ;
	interrupt: TRAP04
		save_fault_stack
[ #BCM550h #BCM550j + [IF] ]T		
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		panic_cr
		panic" Illegal Instruction" 
		panic_stack_frame
		panic_cr
		panic" Offending code"
		_#int_A7 @int_stack_frame _#int_user_return + @ $40 panic_show

		['] _abort_illegial_instruction int_return!

	;interrupt


	\ have an attempt at aborting offending process
	: _abort_priv_violation TRUE ABORT" Privilege violation" ;
	interrupt: TRAP08
		save_fault_stack
[ #BCM550h #BCM550j + [IF] ]T		
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		panic_cr
		panic" Privilege violation" 
		panic_stack_frame
		panic_cr
		panic" Offending code"
		_#int_A7 @int_stack_frame _#int_user_return + @ $40 panic_show

		['] _abort_priv_violation int_return!
	;interrupt
    
	
	\ acceptable behavior
	interrupt: TRAP09
		save_fault_stack
[ #BCM550h #BCM550j +  [IF] ]T
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		panic_cr 
		panic" Trace"
		panic_stack_frame
	;interrupt

	\ Have a go at aborting offending process
	: _abort_line_a TRUE ABORT" Unimplemented line A code" ;
    interrupt: TRAP0A
		save_fault_stack
[ #BCM550h #BCM550j + [IF] ]T
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		panic_cr
		panic" Unimplemented line A code" 
		panic_stack_frame
		panic_cr
		panic" Offending code"
		_#int_A7 @int_stack_frame _#int_user_return + @  $40 panic_show

		['] _abort_line_a int_return!
	;interrupt



	\ have a go at oborting offending process
	: _abort_line_f  TRUE ABORT" Unimplemented line F code" ;
	interrupt: TRAP0B
		save_fault_stack
[ #BCM550h #BCM550j + [IF] ]T
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		panic_cr
		panic" Unimplemented line F code"
		panic_stack_frame
		panic_cr
		panic" Offending code"
		_#int_A7 @int_stack_frame _#int_user_return + @  $40 panic_show

		['] _abort_line_f int_return!
	
	;interrupt
    
	\ This is acceptable behavior
	interrupt: TRAP0C
		save_fault_stack
[ #BCM550h #BCM550j +  [IF] ]T
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		panic_cr
		panic" Debug interrupt" 
		panic_stack_frame
	;interrupt

	\ we are not likely to be able to recover from this one
	interrupt: TRAP0E
		save_fault_stack
[ #BCM550h #BCM550j +  [IF] ]T
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		panic_cr
		panic" Format error" 
		panic_stack_frame
	;interrupt
 
	\ just return from this
	interrupt: TRAP0F
		save_fault_stack
[ #BCM550h #BCM550j + [IF] ]T
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		panic_cr
		panic" Unimplemented interrupt"
		panic_stack_frame
	;interrupt

	: _abort_bus_error panic" In abort code" TRUE ABORT" Bus error" ;

 	interrupt: TRAP1F
		\ reset interrupt, must be a write
		zero _breg_int_reset_bus_error C! 
		save_fault_stack
		panic_cr
		panic" Bus Error" 
		panic_stack_frame
		panic_cr
		panic" Offending code"
		_#int_A7 @int_stack_frame _#int_user_return + @ $40 panic_show
[ #BCM550h #BCM550j + [IF] ]T
		_breg_SS1 C@
		_#SS1_processor_fault OR
		_breg_SS1 C!
[ [THEN] ]T
		['] _abort_bus_error int_return!
	;interrupt
	 

All this is being done on the stack of the task that was running at the time. It really is best done in assembler so the stack space that has to be provided by each task to interrupt service is kept to a minimum Oh for the 68k.

This is a task switch within a loop. The task switch can use registers as any normal forth word would. That is A0 A1 and W ok etc. Actually you can use more as LP, and OP have been saved off.

 
	CREATE TRAP22 assembler
		\ if we are not using the interrupt stack we have
		\ to have interrupts disabled, or switch back to user
		\ space, all this can be done in user space
		$0000 # SR MOV
		R )+ D0 MOV ( pop cpu status and format )
		R )+ A0  MOV     ( return address)
		\ the return address points to the instruction after
		\ the trap instruction, the trap instruction is two bytes.
		#activation_trap 2+  # A0 SUB  ( activation base address)
		
		#activation_task> 0) U MOV
		


		zero # D1 MOV
		#activation_status  0) D1 W. MOV  ( status)


		sleep # D1 CMP EQ IF
			\ we have to get the next tasks  trap instruction
			#activation_task_link 0) A0 MOV \ address next instruction
			A0 ) JMP
		THEN
		wake # D1 CMP EQ IF
			sleep # #activation_status  0) W. MOV    ( only one activation)
			(S) U) S MOV
			S )+ R MOV   
			S )+ OP MOV
			S )+ LP MOV
			EXIT
		THEN
		test # D1 CMP EQ IF
			#activation_task_link 0) A1 MOV     ( next task in loop)
			_task_restart_time user_base - U) D0 MOV    ( activation time)
			xclock- AB D0 ADD CS IF
					A1 ) JMP		  
			THEN  ( Go to next task if not ready)
			(S) U) S MOV   ( stack pointer restored)
			S )+ R MOV     ( return stack pointer)
			S )+ OP MOV
			S )+ LP MOV
			EXIT
		THEN
		\ For unknown codes treat as sleep
		\ we have to get the next tasks  trap instruction
 		#activation_task_link 0) A0 MOV \ address next instruction
		A0 ) JMP
	HOST

	\ Run user code in supervisor mode
	\ needed for cache flush
	ram_variable %super_execute
	CREATE TRAP23 assembler ( ?? instruction -- ??)
		\ if we are in supervisor mode and not using the 
		\ interrupt stack we have to have interrupts disabled.
		2700 # SR W. MOV       ( no interrupts)
		1 # D0 MOV
		D0 %super_execute AB ADD
		S )+ A0 MOV
		A0 ) JSR
	RTE

	??HEX
	\ stop the CPU    
	LABEL TRAP25 ( reset) assembler
		7 100 * 2000 + # STOP
		BEGIN 
			D0 D0 ADD 
		BRA
	HOST    

	\ start the tcp level; if running at a lower level the priority will be raised.
	\ if running at a high level the level will be run when priorities are lowered
	interrupt: TRAP26   
   			TRUE [ TSK9 _#level_head_restart_flag + ]T LITERAL W! 
			#tcp/ip  _set_new_task_level
	;interrupt

   
	 

Swap task levels

We enter this code with R set to a user stack. If there is a suspeneded level it will be stored on the system stack.

 

	\ These two flags are tested as one in the following code.
	_#level_head_restart_flag 2 + _#level_head_repeat_flag ??=

	ram_variable %restart_type1
    ram_variable %restart_type2
	ram_variable %restart_type3
	ram_variable %restart_type4
	LABEL TRAP27 assembler

		\ if we are in supervisor mode and not using the 
		\ interrupt stack we have to have interrupts disabled.
		2700 # SR W. MOV       ( no interrupts)
		

		\ see it current level needs re-running; this will only occure if tasks in the
		\ current level set the _#level_head_restart_flag. The TCP/IP level does this if
		\ an ip packet is generated.
		_xlevel AB D1 MOV
		_xheads # A0 MOV
		[ A0 D1 4 ] A1 MOV        ( first task address)

		_#level_head_restart_flag _#level_head_trap - 1) D2 MOV 
		NE IF
			1 # %restart_type1 AB ADD 
			8 # R ADD
			FALSE # _#level_head_restart_flag _#level_head_trap - 1) W. MOV
			( First task is linked into the level swiching entry)
			\ this will be a trap instruction
			#activation_task_link  1) A0 MOV
			A0 ) JMP
		THEN

		\ hardware interrupt frame. Need the entry address as 
		\ the switch level is stored in the word pointed to

		4 # R ADD \ don't need status
		R )+ A0 MOV \ need address for table entry

		\ switch to system stack, we have to save the user stack pointer
		\ it will be used later on if there is not a user state saved
		\ for this level.

		R A2 MOV
		_%int_stack_pointer AB R MOV

		0 # D1 MOV
		_#level_head_next_level _#level_head_trapPC - 0) D1 W. MOV         ( level to swap to)
		D1 _xlevel AB MOV       ( save as level we are about to run)
		 
		R ) D2 MOV              ( stacked cpu state, with level on top)

		\ level suspended

		D2 D1 CMP EQ IF         ( this level has been suspended)
			1 # %restart_type2 AB ADD
			4 # R ADD         ( drop level )
			\ restore the MAC registers
			R )+ D0 MOV
			D0 ACC MOV
			R )+ D0 MOV
		    D0 MASK MOV 
			R )+ D0 MOV
			D0 MACSR MOV
    		R ) \\ D0 A6 \\ MMOV
			8 7 + 4 * R) R LEA
			
			\ we now have to use the trap return frame that was there when 
			\ we suspended the task.
			\ Further _%int_stack_pointer has to be updated to 
			\ point to next frame.

			R )+ A0 MOV          \ user stack
			R _%int_stack_pointer AB MOV
			A0 R MOV

			R )+ A0 MOV
			\ because interrupts are disabled RTE will do
    		RTE           ( the return state was saved when the level was suspended)
		THEN
		\ ? level to be restarted, switch back to user stack and get things going
		A2 R MOV
		_xheads # A0 MOV
		[ A0 D1 4 ] A1 MOV        ( first task address)

		_#level_head_restart_flag _#level_head_trap - 1) D2 MOV 
		NE IF
			1 # %restart_type3 AB ADD
			FALSE # _#level_head_restart_flag _#level_head_trap - 1) W. MOV
			( First task is linked into the level swiching entry)
			#activation_task_link  1) A0 MOV
			A0 ) JMP
		THEN
		1 # %restart_type4 AB ADD
		( execute the head of the new level )
		( This will have us straight back to deal with the next.)
		A1 ) JMP

	HOST   
    
	( Change interrupt level)
	LABEL TRAP28
		\ if we are not using the interrupt stack we have
		\ to have interrupts disabled.
		$2700 # SR MOV
		%int_enable AB TST NE IF
			D0 R -) MOV
			6 R) D0 W. MOV
			$2000 # D0 AND NE IF
				R )+ D0 MOV
				\ if we were in supervisor state leave things as they are
				RTE
			THEN
			6 R) D0 W. MOV
    		$F8FF # D0 AND
			D0 6 R) W. MOV
			R )+ D0 MOV
		THEN 
	RTE
    HOST

	LABEL TRAP29	
		\ if we are not using the interrupt stack we have
		\ to have interrupts disabled.
		2700 # SR MOV
		%int_enable AB  TST NE IF
			D0 R -) MOV
			6 R) D0 W. MOV
			F8FF # D0 AND  
			0100 # D0 OR
			D0 6 R) W. MOV
			R )+ D0 MOV
		THEN 
	RTE
	HOST

	LABEL TRAP2A
		\ if we are not using the interrupt stack we have
		\ to have interrupts disabled.
		2700 # SR MOV
		%int_enable AB TST NE IF
			D0 R -) MOV
			6 R) D0 W. MOV
    		F8FF # D0 AND  
			0200 # D0 OR 
			D0 6 R) W. MOV
			R )+ D0 MOV 
		THEN 
	RTE
    HOST

	LABEL TRAP2B
		\ if we are not using the interrupt stack we have
		\ to have interrupts disabled.
		2700 # SR MOV
		%int_enable AB TST NE IF
			D0 R -) MOV
			6 R) D0 W. MOV
    		F8FF # D0 AND  
			0300 # D0 OR 
			D0 6 R) W. MOV
			R )+ D0 MOV 
		THEN 
	RTE
    HOST

	LABEL TRAP2C
		\ if we are not using the interrupt stack we have
		\ to have interrupts disabled.
		2700 # SR MOV
		%int_enable AB  TST NE IF
			D0 R -) MOV
			6 R) D0 W. MOV
    		F8FF # D0 AND  
			0400 # D0 OR
			D0 6 R) W. MOV
			R )+ D0 MOV 
		THEN 
	RTE
	HOST

	LABEL TRAP2D     
		\ if we are not using the interrupt stack we have
		\ to have interrupts disabled.
		2700 # SR MOV
		%int_enable AB  TST NE IF
			D0 R -) MOV
			6 R) D0 W. MOV
    		F8FF # D0 AND  
			0500 # D0 OR 
			D0 6 R) W. MOV
			R )+ D0 MOV 
		THEN 
	RTE
    HOST

	LABEL TRAP2E
		\ if we are not using the interrupt stack we have
		\ to have interrupts disabled.
		2700 # SR MOV
		%int_enable AB TST NE IF
			D0 R -) MOV
			6 R) D0 W. MOV	
    		F8FF # D0 AND  
			0600 # D0 OR 
			D0 6 R) W. MOV
			R )+ D0 MOV
		THEN 
	RTE
	HOST

	LABEL TRAP2F
		\ if we are not using the interrupt stack we have
		\ to have interrupts disabled.
		2700 # SR MOV
		D0 R -) MOV
		6 R) D0 W. MOV                    
		0700 # D0 OR 
		D0 6 R) W. MOV
		R )+ D0 MOV 
	RTE
    HOST
.S .( out of traps)