license

The structure may seem large but remember we are building a forth process to deal with the interrupt.

On interrupt: entry LP points to a data structure that describes the state of the system at the start of the interrupt. This describes that structure.

Note we do not save the MAC state, if interrupt code wishes to use the MAC saving and restoreing is the interrupts code problem.

 
	zero 
	DUP CONSTANT _#int_old_lp CELL+  \
	DUP CONSTANT _#int_format 2 +
	DUP CONSTANT _#int_status 2 +
	DUP CONSTANT _#int_PC     CELL+  
	DUP CONSTANT _#int_D0     CELL+  
	DUP CONSTANT _#int_D1     CELL+  
	DUP CONSTANT _#int_D2     CELL+ 
	DUP CONSTANT _#int_D3     CELL+  
	DUP CONSTANT _#int_D4     CELL+  
	DUP CONSTANT _#int_D5     CELL+  
	DUP CONSTANT _#int_D6     CELL+  
	DUP CONSTANT _#int_D7     CELL+  
	DUP CONSTANT _#int_A0     CELL+ 
	DUP CONSTANT _#int_A1     CELL+ 
	DUP CONSTANT _#int_A2     CELL+ 
	DUP CONSTANT _#int_A3     CELL+ 
	DUP CONSTANT _#int_A4     CELL+ 
	DUP CONSTANT _#int_A5     CELL+ 
	DUP CONSTANT _#int_A6     CELL+ 
	DUP CONSTANT _#int_A7     CELL+
	DROP 
	 

The value at _#int_A7 must be used as the base address of interrupt entry structure. See system_entry

Note this word cannot be used with local variables, it assumes LP still points to the interrupt: stack frame

 
	: @int_stack_frame ( offset -- value)
		@lp + @ 
	;
	 

When you enter interrupt code you can use assembler if you desire. The following words set up the FORTH environment.

 
	\ INT2
	494E5432 CONSTANT _#interrupt_magic
	\ DEND
	44454E44 CONSTANT #stack_end_magic
	\ DSTK
	4453544B CONSTANT #stack_start_magic
	ram_variable %interrupt_count
	: _interrupt_set_user ( --)
		#stack_start_magic \ leave on stack
		_#interrupt_magic interrupt_magic_number !
		@u DUP #activation_task> + !
		@u _activation> !
		
		1 %interrupt_count +!
		%interrupt_count @ _task_restart_time !

		zero 'buffer !
		zero 'output_file !
		zero 'input_file !
		zero 'abort_file !
		zero _error_pos? W!
		\ last location in user space; if not set at end of int then int stack overflow.
		#stack_end_magic data_guard !
		\ This sets things up so a THROW will bring us back here.
		\ If you want a little extra speed you can get rid of
		\ this, but the fault exception routines will work if this 
		\ is done.
		R@ 
		\ skip the branch
		4+ 
		\ the catch actually executes the interrupt code.
		CATCH DROP
		\ code following the code that called this is a branch to the ;interrupt
		\ call code
	;
	
	 

The user area and data stack are built on the return stack. You can use the local variable structure to create local data areas on the return stack if you desire. Obviously using it to describe input and output data stack items it a bit of a waste of time. There is no entry and exit data stack.

 
	_interrupt_end_user user_base - CONSTANT _#interrupt_user_size
	\ This is the length of the interrupt data stack, increase if
	\ required, but also increase _#system_stack_length
	80                              CONSTANT _#interrupt_data_stack
	 

Describe the return stack after registers saved

On entry A0 points to the entry stack.

 

forth	: interrupt:  ( --)
		HOST CREATE
		zero _%local_use !
		\ switch to the interrupt stack
		system_entry
		\ push all registers
		4FEF tw,
		FFC4 tw,           \ ##code 7 8 + 4 * NEGATE R) R LEA
		48D7 tw,           \ ##code \\ D0 A6 \\ R ) MMOV
		7FFF tw,		   \


		518F tw,           \ 08  # R SUB \ room for format and return
		\ this pushes a value onto the return stack
		4E55 tw,           \ ##code \\ LP nnn # LINK
		_#interrupt_user_size 
		_#interrupt_data_stack + NEGATE  tw,
		
		\ get info from user stack into registers                   
		4CD0 tw,	       \ A0 ) \\ D0 D2 \\ MMOV
		0007 tw,				   

		\ copy data from user registers to system stack
		\ this is done so systemstack contains relevent info
		\ should a fault occure
		2B40 tw, _#int_A0      tw, \ D0 _#int_A0 LP) MOV
		2B41 tw,  _#int_format tw, \ D1 _#int_format LP) MOV
		2B42 tw,  _#int_PC     tw, \ D2 _#int_pc LP) MOV

		\ set up user stack
		2C4D tw,           \ ##code LP S MOV
		\ set up user space
		264F tw,           \ ##code R U MOV
		
		\ jsr to first forth word this sets up the user area and 
		\ executes following code.
		4EB9 tw,           \ ##code _interrupt_set_user AB JSR
		['] _interrupt_set_user t,
		\ for the abort
		6000 tw, \ ##code BRA
		\ reserve space for address resolution and put values on stack that will 
		\ see the resolution done by code in ;intrerrupt
		HERE 0 tw,
		_#comp_code_if 
		\ start the forth compilation
		]T
		forth
	;

HOST
	: interrupt:  ( --)
		CREATE
		zero _%local_use !
		system_entry
		\ push all registers
		4FEF W,
		FFC4 W,           \ ##code 7 8 + 4 * NEGATE R) R LEA
		48D7 W,           \ ##code \\ D0 A6 \\ R ) MMOV
		7FFF W,
		518F W,           \ _#int_D0 _#int_format -  # R SUB \ room for format and return
		4E55 W,           \ ##code \\ LP nnn # LINK
		_#interrupt_user_size 
		_#interrupt_data_stack + NEGATE  W,
	
		\ get info from user stack into registers                   
		4CD0 W,	       \ A0 ) \\ D0 D2 \\ MMOV
		0007 W,				   

		\ copy data from user registers to system stack
		\ this is done so systemstack contains relevent info
		\ should a fault occure
		2B40 W,  _#int_A0 W, \ D0 _#int_A0 LP) MOV
		2B41 W, _#int_format W, \ D1 _#int_format LP) MOV
		2B42 W, _#int_PC W, \ D2 _#int_pc LP) MOV

	
		\ set up user stack
		2C4D W,           \ ##code LP S MOV
		\ set up user space
		264F W,           \ ##code R U MOV
		
		\ jsr to first forth word this sets up the user area and 
		\ executes following code.
		4EB9 W,           \ ##code _interrupt_set_user JSR
		['] _interrupt_set_user ,
		\ for the abort
		6000 W, \ ##code BRA
		HERE 0 W,
		_#comp_code_origin		
		\ start the forth compilation
		]
	;

forth : ;interrupt
		HOST 
		\ stop the compiler
		[COMPILE] [
		\ resolve the interrupt: reference
		_#comp_code_if 
		forth ?PAIR  
		HOST  HERE 
		forth OVER -  SWAP 
		HOST TW! 
		\ local variable exit code if required.
		forth _%local_use @ IF
			HOST
			4E5D tw, \ ##code LP UNLK
			target_previous
			_end_xlocal_dictionary
		forth THEN 
		HOST
		4E5D tw,     \ ##code LP UNLK
		508F tw,     \ _#int_D0 _#int_format - # R ADD
		4CD7 tw,     \ ##code R ) \\ D0 A6 \\ MMOV
		7FFF tw, 
		4FEF tw,     \ ##code 7 8 + 4 * R) R LEA
		003C tw,    
		system_rte
		forth
	; TARGET

HOST

	: ;interrupt 
		\ stop the compiler
		[COMPILE] [

		\ resolve the interrupt: reference
		_#comp_code_origin ?pair
		!forward

		\ word exit code
		\ We have to unlink LP if we used local variables as
		\ we need th previous value of LP to get out of the interrupt 
		\ code.

		_%local_use @ IF
			4E5D W,  \ ##code LP UNLK
			PREVIOUS
			_end_local_dictionary
		THEN 

		4E5D W,     \ ##code LP UNLK
		508F W,     \ _#int_D0 _#int_format - # R ADD
		4CD7 W,     \ ##code R ) \\ D0 A6 \\ MMOV
		7FFF W, 
		4FEF W,     \ ##code 7 8 + 4 * R) R LEA
		003C W,     

		system_rte

	; IMMEDIATE