	.module kernel.c
	.area data
_main_frame_ptr::
	.blkb 2
	.area idata
	.word 0
	.area data
_main_frame_x_ptr::
	.blkb 2
	.area idata
	.word 0
	.area data
_temp_task_frame_ptr::
	.blkb 2
	.area idata
	.word 0
	.area data
_kdb_trace::
	.blkb 2
	.area idata
	.word 1
	.area data
_kdb_trace_cycle::
	.blkb 2
	.area idata
	.word 0
	.area data
	.area text
_error_msg::
	.byte 'u,'n,'i,'m,'p,'l,'i,'m,'e,'n,'t,'e,'d,32,'f,'u
	.byte 'n,'c,'t,'i,'o,'n,0
	.byte 0,0
	.byte 's,'y,'n,'t,'a,'x,32,'e,'r,'r,'o,'r,0
	.word 0,0,0,0,0
	.byte 0,0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'t,'a,'s,'k,32,'I,'D,0
	.byte 0,0,0,0,0,0,0,0,0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'t,'a,'s,'k,32,'s,'t,'a
	.byte 't,'e,0
	.byte 0,0,0,0,0,0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'t,'a,'s,'k,32,'p,'r,'i
	.byte 'o,'r,'i,'t,'y,0
	.byte 0,0,0
	.byte 'o,'u,'t,32,'o,'f,32,'m,'e,'m,'o,'r,'y,0
	.word 0,0,0,0,0
	.byte 0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'r,'e,'s,'o,'u,'r,'c,'e
	.byte 32,'I,'D,0
	.byte 0,0,0,0,0
	.byte 'i,'l,'l,'e,'g,'a,'l,32,'r,'e,'s,'o,'u,'r,'c,'e
	.byte 32,'s,'t,'a,'t,'e,0
	.byte 0,0
	.byte 'c,'a,'n,'n,'o,'t,32,'c,'r,'e,'a,'t,'e,32,'t,'a
	.byte 's,'k,0
	.byte 0,0,0,0,0,0
_error_src::
	.byte 'k,'e,'r,'n,'e,'l,32,'e,'r,'r,'o,'r,58,0
	.byte 0,0,0,0
	.byte 'k,'e,'r,'n,'e,'l,46,'c,32,'e,'r,'r,'o,'r,58,0
	.byte 0,0
	.byte 'k,'e,'r,'n,'e,'l,32,'R,'T,'I,32,'e,'r,'r,'o,'r
	.byte 58,0
	.byte 's,'h,'e,'l,'l,32,'e,'r,'r,'o,'r,58,0
	.byte 0,0,0,0,0
	.byte 's,'e,'m,'l,'i,'b,46,'c,32,'e,'r,'r,'o,'r,58,0
	.byte 0,0
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;          ?temp -> -19,x
;          ?temp -> -19,x
;          ?temp -> -19,x
;          ?temp -> -21,x
;          ?temp -> -19,x
;             id -> -17,x
;         result -> -15,x
; priority_check -> -13,x
;       deadline -> -12,x
;              i -> -10,x
_main::
	pshx
	tfr s,x
	leas -30,sp
; /*	RLPOS: RLPotter Operating System
; 
; 		   Version 0.7 for the 68HC12D60A microcontroller
; 		   by Ryan Potter
; 		   ryan@rlpotter.com
; 	
; 	
; 	v0.7 April 25, 2003: 11174 bytes:
; 		   - combined kernel.c & semlib.c with rlpos.c to make one big kernel.c
; 		   - changed context switch mechanism to give each task a dedicated
; 		   	 stack, making the kernel context switches >400% faster.
; 		   - added a basic timer task that will eventually keep system time/date.
; 		   
; 	v0.6 April 24, 2003: 11042 bytes
; 		   - made the task block and the task control block dynamic, so that
; 		   	 now tasks can create tasks, and can also start/stop them
; 		   - implemented the sysInit() task for kicking off a user system
; 		   - implemented a kernel debug command for tracing code execution
; 		   - implemented small msg box system in kernel for tasks
; 		   - implemented COP watchdog reset timer
; 		   - added system resources to semlib
; 		   - added skeleton ISR_handler() code for the other interrupts
; 		   - implemented _HC12Setup.c to initialize/harden the system
; 		   
; 	v0.5 April 16, 2003:
; 		   - added priority preemption
; 		   - finished kernel task state switcher 
; 		   - it is now officially a legitimate
; 		   	 	rate monotonic
; 				priority preemptive
; 				multitasking
; 				Real Time Operating System  :)
; 		   - made kernel.c and semlib.c consistent with the 
; 		   	 rest of the kernel
; 		   - included the early framework for a msg box system
; 			 
; 	v0.4 April 13, 2003: 8096 bytes
; 		   - gerneralized the shell command-line input parser: 
; 		   	 cmd <arg1, arg2, ... argn> (up to 32 chars)
; 		   - added kernel and shell functions
; 		   
; 	v0.3 April 12, 2003: 6155 bytes
; 		   - added a beginning shell user interface.
; 		   - added a resource control block and basic semaphore functions.
; 		   - added basic kernel functions
; 		   
; 	v0.2 April 9, 2003:
; 	  	   - able to round-robin with RTI interrupt.
; 		   - bonified/certified multitasking with 3 tasks. :)
; 		   
; 	v0.1 April 3, 2003:
; 	  	   - able to round-robin without interrupts.
; 		   - not multitasking, really.
; 		   
; 	v0.0 started April 1, 2003; 0 bytes
; 		   - no idea where to start.
; 		   - don't want to look at anyone else's work. ;0)
; 
; 
; 
; 	
; 	Architecture/C assumptions:
; 		1) 'D' register is the accumulator
; 		2) 'X' register points to the top of the current stack
; 		3) 'Y' register is for general use in indexed operations
; 		4) the heap grows upward and mem segments allocated by malloc,
; 		   realloc, and calloc are linear and contiguous.
; 		5) the stack grows downwards, and there is no boundary checking.
; 		   
; 	Potential problem areas:
; 		1) 'running' section of the kernel get's compiled using extra
; 		   push and pop instructions
; 		2) run out of ram (global + stack + heap)
; 		
; */
; 	
; 	
; 	
; #include <912d60.h>
; #include <stdio.h>
; #include <stdlib.h>
; #include <string.h>
; #include "kernel.h"
; 
; 
; 
; // FUNCTION PROTOTYPES
; void RTI_handler(void);
; void sysInit(void);
; void shell(void);
; void sysTime(void);
; void (*task_ptr[MAXTASKS])(void);
; 
; 
; 
; 
; // GLOBAL VARIABLES
; unsigned char *main_frame_ptr = NULL;	   	// bottom of main() frame
; unsigned char *main_frame_x_ptr = NULL;		// top of main() frame (x-reg ptr)
; unsigned char *temp_task_frame_ptr = NULL;	// temp CCR pointer for RTI
; 
; 
; unsigned int current;		   	 		    // current task id number
; unsigned long int system_tick;
; unsigned int cop_cycle;
; 
; unsigned long int time_tick;
; unsigned long int delta_t;
; unsigned long int last_time_mark;
; 
; 
; // task control block
; typedef struct task_block {
; 	 	void (*address)();			   		// Address of the task
; 	 	unsigned char id; 			  		// ID of task
; 		char name[9];	  					// Name
; 		enum task_state state;				// State
; 		unsigned char priority;				// Priority
; 		unsigned long int period_tick;		// for determining if deadline is up
; 		unsigned int interrupt_msg_box;		// flags for pending interrupts
; 		enum message_box message;			// misc flags
; 		unsigned char message_data[2];		// data for misc_msg_box flags
; 		unsigned int stack_size;			// heap allocated for task stack
; 	 	unsigned char *top_of_stack;			// top of task stack in the heap
; 		unsigned char *frame_ptr;			// CCR pointer in idle stack
; 		};
; 
; 
; // resource control block
; typedef struct resource_block {
; 		unsigned char id;	   				// ID of resource
; 		char name[5];	  					// Name of resource
; 		enum resource_state state;			// State (busy, free...)
; 		unsigned char owner;				// Current resource owner
; 		signed char queue[3];				// Tasks waiting on resource
; 		unsigned char queue_ptr;			// Next free spot in queue
; 		};
; 		
; 		
; struct task_block *task[MAXTASKS];
; struct resource_block resource[NUMRESOURCES];
; 
; 
; int kdb_trace = 1;
; int kdb_trace_cycle = 0;
; 
; 
; // global interrupt flags
; //unsigned int interrupt_flags_ADC;
; //unsigned int interrupt_flags_TC;
; 
; 
; 
; 
; // error massages
; const char error_msg[][25] = {"unimplimented function",	// error 0 
; 	 				  	"syntax error",				// error 1 
; 						"illegal task ID",			// error 2 
; 						"illegal task state",		// error 3 
; 						"illegal task priority",	// error 4 
; 						"out of memory",			// error 5 
; 						"illegal resource ID",		// error 6
; 						"illegal resource state",	// error 7
; 						"cannot create task"		// error 8
; 						};
; const char error_src[][18] = {"kernel error:",			// source 0
; 	 				  	"kernel.c error:",			// source 1
; 						"kernel RTI error:",		// source 2
; 						"shell error:",				// source 3
; 						"semlib.c error:"			// source 4
; 						};
; 						
; 						
; 
; 
; 
; main() {
; 
; 	 // LOCAL VARIABLES
; 	 int result, id, i;
; 	 unsigned char priority_check;
; 	 unsigned int deadline;
; 	 extern int _bss_end, _textmode;		   	 		
; 	  
; 	  
; 	 _textmode = 1;	 	  // maps '\n' to "CR/LF" for Windows terminals
	ldd #1
	std __textmode
; 	 current = 0;  	 	  // start the shell first
	ldd #0
	std _current
; 	 cop_cycle = 0;		  // fresh watchdog
	ldd #0
	std _cop_cycle
	ldd #0
	std -10,x
L4:
	ldd #12
	ldy -10,x
	emuls
	addd #_resource
	xgdy
	ldd -10,x
	stab 0,y
	ldd #12
	ldy -10,x
	emuls
	addd #_resource+6
	xgdy
	clr 0,y
	ldd #12
	ldy -10,x
	emuls
	addd #_resource+7
	xgdy
	ldab #255
	stab 0,y
	ldd #12
	ldy -10,x
	emuls
	addd #_resource+11
	xgdy
	clr 0,y
L5:
; 	 
; 	 
; 	 /* redundant... done by _startup()
; 	 // initialize the task pointer array and the tcb array.
; 	 for (i=0; i<MAXTASKS; i++) {
; 	 	 task_ptr[i] = NULL;
; 		 task[i] = NULL;
; 		 }
; 	 */
; 		 
; 		 
; 		 
; 	 // initialize the rcb pointer block
; 	 for (i=0; i<NUMRESOURCES; i++) {
	ldd -10,x
	addd #1
	std -10,x
	ldd -10,x
	cpd #4
	blt L4
; 	 	 resource[i].id = i;
; 		 resource[i].state = NOTBUSY;
; 		 resource[i].owner = 255;
; 		 resource[i].queue_ptr = 0;
; 		 }
; 
; 	 
; 	 
;  	 // save SP value for use in the RTI
; 	 asm("TFR s,d");
		TFR s,d

; 	 asm("STD _main_frame_ptr");
		STD _main_frame_ptr

; 	 // save X reg value for use in the RTI
; 	 asm("TFR x,d");
		TFR x,d

; 	 asm("STD _main_frame_x_ptr");
		STD _main_frame_x_ptr

; 	 
; 	 
; 	 
; 	 
; 	 // START/INITIALIZE the os
; 		// KDB_TRACE Section 1
; 	 
; 	 // create and initialize the heap (for dynamic (runtime) var allocation)
; 	 _NewHeap(&_bss_end, (char *)(&_bss_end) + (INITIAL_HEAP_SIZE));
	ldd #__bss_end+1344
	std 0,sp
	ldd #__bss_end
	jsr __NewHeap
; 	 
; 	 
; 	 // set up the serial port
; 	 setbaud(BAUD38K);	 	  // actually running at 19K baud due to xtal speed
	ldd #13
	jsr _setbaud
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-0");	 
; 	 #endif
; 	 
; 
; 	 // create the sysInit task
; 	 if (create_task("sysInit", &sysInit, 0, PENDING, 0) < 0)
	ldd #0
	std 6,sp
	ldd #1
	std 4,sp
	ldd #0
	std 2,sp
	ldd #_sysInit
	std 0,sp
	ldd #L14
	jsr _create_task
	cpd #0
	bge L12
; 	 	puts("sysInit failure");
	ldd #L15
	jsr _puts
L12:
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-1");	 
; 	 #endif 
; 
; 
; 		
; 	 // create the shell
; 	 if (create_task("shell", &shell, 0, PENDING, DEFAULT_SHELL_STACK_SIZE) < 0)
	ldd #255
	std 6,sp
	ldd #1
	std 4,sp
	ldd #0
	std 2,sp
	ldd #_shell
	std 0,sp
	ldd #L18
	jsr _create_task
	cpd #0
	bge L16
; 	 	puts("shell failure");
	ldd #L19
	jsr _puts
L16:
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-2");	 
; 	 #endif
; 
; 		
; 		
; 	 /*// create sysTime
; 	 create_task("sysTime", &sysTime, 5, PENDING);
; 	 #ifdef KDB_TRACE_LEVEL_1
; 		if (kdb_trace) puts("kDB1-3");	 
; 	 #endif*/
; 	 
; 
; 	 
; 	 // service the COP and system tick
; 	 COP_PET(0x55);
	ldab #85
	stab 0x17
; 	 COP_PET(0xAA);
	ldab #170
	stab 0x17
; 	 system_tick = 0;
	ldy #L20
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #_system_tick
	movw -4,x,0,y
	movw -2,x,2,y
; 	 
; 	 
; 	 // print the opening comments
; 	 puts("rlpOS v0.7\n\n");
	ldd #L21
	jsr _puts
	lbra L23
L22:
; 
; 	 
; 
; 	 
; 	 // MULTITASKING KERNEL: Priority Preemptive, Real Time, multitasking 
; 		// KDB_TRACE Section 2
; 	 while(1) {	 
; 	 	
; 		//-------------------------------
; 		/* REENTRY POINT after either 
; 		   	   1) task finishes, or 
; 		   	   2) RTI
; 		*/
; 		//-------------------------------
; 		
; 		
; 		if (kdb_trace_cycle >= KDB_CYCLES)
	ldd _kdb_trace_cycle
	cpd #4
	blt L25
; 		   kdb_trace = 0;
	ldd #0
	std _kdb_trace
L25:
; 		
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.1");	 
; 		#endif
; 		   
; 		   		
; 		/* No interrupts allowed inside of main().  Only allowed
; 		   inside of non-critical sections of tasks */ 
; 	 	INTR_OFF();	
		sei

; 		
; 		
; 		// PET THE DOG: cop watchdog reset timer (pet freq = 2x COP freq)
; 		if (cop_cycle == 4) {
	ldd _cop_cycle
	cpd #4
	bne L27
; 		   COP_PET(0x55);
	ldab #85
	stab 0x17
; 		   COP_PET(0xAA);
	ldab #170
	stab 0x17
; 		   cop_cycle = 0;
	ldd #0
	std _cop_cycle
; 		   }
L27:
	ldd #0
	std -10,x
L29:
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.2-1");	 
; 		#endif
; 		
; 		
; 		
; 		// CHANGE STATES ACCORDING TO MESSAGES
; 		// 'waiting' needs to have highest precedence here
; 		for (i=0; i<MAXTASKS; i++) {
; 			if (task[i] == NULL)
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L33
; 			   continue;
	bra L30
L33:
; 			if (task[i]->message && STATE_FLAG) {  
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	tst 20,y
	beq L35
; 			   // set task state to what the message says
; 		   	   task[i]->state = task[i]->message_data[STATE_BOX];
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -19,x
	ldy -19,x
	ldab 21,y
	ldy -19,x
	stab 12,y
; 			   // clear the STATE_FLAG
; 			   task[i]->message &= ~(STATE_FLAG);
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -21,x
	tfr d,y
	pshy ; spill
	ldy -21,x
	puly ; reload
	bclr 0,y,#0x1
; 			   #ifdef KDB_TRACE_LEVEL_2
; 				if (kdb_trace) puts("kDB2.3-2a");	 
; 			   #endif
; 			   }
L35:
L30:
	ldd -10,x
	addd #1
	std -10,x
	ldd -10,x
	cpd #8
	blt L29
	ldd #0
	std -10,x
L37:
; 			#ifdef KDB_TRACE_LEVEL_2
; 				if (kdb_trace) puts("kDB2.3-2b");	 
; 			#endif
; 			}
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.3-1");	 
; 		#endif
; 		
; 			
; 
; 		// RT PRIORITY BLOCK:
; 		// set the current task id based on priority and deadline
; 		
; 		// determine if the deadline is up for idle tasks
; 		/* deadline, is equal to period plus an initial time (t0) reference
; 		   (t0 = system_tick).  Period = priority + 1.  
; 		   Changing the state from idle to PENDING occurs here.  */
; 		for (i=0; i<MAXTASKS; i++) {
; 			if (task[i]->state == IDLE) {
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	tst 12,y
	bne L41
; 			   deadline = task[i]->period_tick + (task[i]->priority + 1);
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -19,x
	ldy -19,x
	ldab 13,y
	clra
	addd #1
	jsr __d2lreg2
	ldy -19,x
	leay 14,y
	movw 0,y,-4,x
	movw 2,y,-2,x
	jsr __ladd
	jsr __lreg2d
	std -12,x
; 			   if (system_tick >= deadline) {
	ldy #_system_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldd -12,x
	std -6,x
	movw #0,-8,x
	jsr __lcmp
	blo L43
; 			   	  task[i]->state = PENDING; 	  // change state at deadline
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #1
	stab 12,y
; 				  #ifdef KDB_TRACE_LEVEL_2
; 					if (kdb_trace) puts("kDB2.4-2");	 
; 				  #endif
; 			   	  } 	
L43:
; 				}
L41:
L38:
	ldd -10,x
	addd #1
	std -10,x
	ldd -10,x
	cpd #8
	blt L37
; 			 // if (task[i]->message) {} ???		
; 			 }
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.4-1");	 
; 		#endif			
; 		
; 		
; 		// set current = to highest priority pending/running task.
; 		priority_check = 255;   	  	  // lowest possible
	ldab #255
	stab -13,x
	ldd #0
	std -10,x
L45:
; 		
; 		for (i=0; i<MAXTASKS; i++) {
; 			if (!(task[i] == NULL)) {
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldd 0,y
	beq L49
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -19,x
	cpd #1
	beq L53
	ldd -19,x
	cpd #2
	bne L51
L53:
; 			   if ((task[i]->state == PENDING) || (task[i]->state == RUNNING)) {
; 			   	  if (task[i]->priority <= priority_check) {
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 13,y
	cmpb -13,x
	bhi L54
; 				  	 current = i;
	ldd -10,x
	std _current
; 				 	 priority_check = task[i]->priority;
	ldd -10,x
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 13,y
	stab -13,x
; 				 	 #ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) puts("kDB2.5-2");	 
; 				  	 #endif 
; 			   	 	 }
L54:
; 			   	   }
L51:
; 				}
L49:
L46:
	ldd -10,x
	addd #1
	std -10,x
	ldd -10,x
	cpd #8
	blt L45
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -19,x
	lbeq L57
	ldd -19,x
	cpd #1
	beq L60
	ldd -19,x
	cpd #2
	lbeq L61
	ldd -19,x
	cpd #3
	lbeq L57
	ldd -19,x
	cpd #4
	lbeq L57
	lbra L56
X0:
; 			 }
; 		#ifdef KDB_TRACE_LEVEL_1
; 			if (kdb_trace) puts("kDB2.5-1");	 
; 		#endif
; 		
; 		
; 		
; 		// DISPATCH, or otherwise deal with the current task
; 			// KDB_TRACE Section 3
; 
; 		#ifdef KDB_TRACE_LEVEL_2
; 		if (kdb_trace) {
; 			printf("task[%d]->state = %d\n", current, task[current]->state);
; 			printf("task[%d]->prior = %d\n", current, task[current]->priority);
; 			}
; 		#endif
; 		
; 		switch (task[current]->state) {
; 			   case IDLE:			   // skip task
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.1-1");
; 					#endif
; 					break;
L60:
; 			   case PENDING:		   // ready and waiting to run
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.2-1");
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
; 							//puts("kDB3.2-2");
; 							putchar('S');
; 							putchar(current+48);
; 							putchar('\n');
; 						    }
; 					#endif  
; 					task[current]->state = RUNNING;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #2
	stab 12,y
; 					task[current]->period_tick = system_tick;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	leay 14,y
	pshy ; spill
	ldy #_system_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	puly ; reload
	movw -4,x,0,y
	movw -2,x,2,y
; 					temp_task_frame_ptr = task[current]->top_of_stack;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldy 25,y
	sty _temp_task_frame_ptr
; 					asm("LDS _temp_task_frame_ptr");		// set the SP
		LDS _temp_task_frame_ptr

; 			   		(*task_ptr[current])();	 	  			// start the task
	ldd _current
	lsld
	addd #_task_ptr
	xgdy
	ldy 0,y
	jsr 0,y
; 					asm("LDS _main_frame_ptr");				// reset the SP
		LDS _main_frame_ptr

; 					task[current]->state = IDLE;			// task finished
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	clr 12,y
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.3-1");
; 					#endif
; 					#ifdef KDB_TRACE_LEVEL_2
; 						if (kdb_trace) {
; 							//puts("kDB3.3-2");
; 							putchar('F');
; 							putchar(current+48);
; 							putchar('\n');
; 						    }
; 					#endif  				
; 			   		break;
	bra L57
L61:
; 			   case RUNNING:			// interrupted. continue running.
; 					// restore context and run
; 					temp_task_frame_ptr = task[current]->frame_ptr;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldy 27,y
	sty _temp_task_frame_ptr
; 					asm("LDS _temp_task_frame_ptr");
		LDS _temp_task_frame_ptr

; 					asm("RTI");
		RTI

; 			   		break;
	bra L57
X1:
; 			   case WAITING:   		   // waiting on a resource
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.5-1");
; 					#endif
; 			   		break;
; 			   case STOPPED:		   // done running until later
; 					#ifdef KDB_TRACE_LEVEL_1
; 						if (kdb_trace) puts("kDB3.6-1");
; 					#endif
; 			   		break;
L56:
; 			   default:	  			   // shouldn't happen, but, error if so.
; 			   		puts("KERNEL: task state error\n");
	ldd #L64
	jsr _puts
; 			   		exit(1);
	ldd #1
	jsr _exit
; 				}	// end switch
L57:
L23:
	lbra L22
X2:
; 		
; 	 		}		// end while(1)
; 	 
; 	 return 0;
	ldd #0
L3:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rts
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;      local_thp -> -14,x
;              i -> -12,x
;     frame_size -> -10,x
_RTI_handler::
	pshx
	tfr s,x
	leas -14,sp
; 	 
; }			 		// end main()
; 
; 
; 
; #pragma interrupt_handler RTI_handler()
; 
; void RTI_handler(void) {
; 
; 	 size_t frame_size;
; 	 unsigned int i;
; 	 unsigned char *local_thp;
; 	 
; 	 
; 	 //ACKNOWLEDGE THE INTERRUPT
; 	 RTIFLG = 0x0080;  	// acknowledge/clear the interrupt
	ldab #128
	stab 0x15
; 	 
; 	 
; 	 #ifdef KDB_TRACE_LEVEL_1
; 	  	if (kdb_trace) putchar('.');
; 	 #endif
; 	 
; 	 
; 	 // SET THE FRAME POINTER for the interupted task.
; 	 // should point to the CCR entry on the stack.
; 	 asm("TFR x,d");  		  	  	  	 // start of RTI stack
		TFR x,d

; 	 asm("ADDD #2");				  	 // adjust to CCR stack entry
		ADDD #2

; 	 asm("STD _temp_task_frame_ptr");	 // put into task_frame_ptr
		STD _temp_task_frame_ptr

; 	 task[current]->frame_ptr = temp_task_frame_ptr;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd _temp_task_frame_ptr
	std 27,y
; 	 
; 
; 	 
; 	 // update system time base and cop reset counter
; 	 system_tick++;
	ldy #_system_tick
	movw 0,y,-4,x
	movw 2,y,-2,x
	ldy #L66
	movw 0,y,-8,x
	movw 2,y,-6,x
	jsr __ladd
	ldy #_system_tick
	movw -4,x,0,y
	movw -2,x,2,y
; 	 cop_cycle++;
	ldd _cop_cycle
	addd #1
	std _cop_cycle
; 	 
; 	 
; 	 
; 	 // RETURN: simulate a RTS instruction
; 	 // set stack pointer for main()
; 	 asm("LDS _main_frame_ptr");
		LDS _main_frame_ptr

; 	 asm("LDX _main_frame_x_ptr");
		LDX _main_frame_x_ptr

; 	 /* return to main() at the reentry point
; 	    and must be adjusted after each kernel mod/compilation!!  */
; 	 asm("JMP $125B");
		JMP $125B

; 	 
; 
; 	 // return (0)  -- NOT used 
; 	 /* this ISR should never use the 'return x' command.
; 	    It doesn't make sense since it always interrupts a Task, but
; 	    never returns to it... but to main() instead.  */
; 	 	 
; }
L65:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rti
;             id -> 3,x
_get_task_address::
	pshd
	pshx
	tfr s,x
; 
; 
; 
; 
; 
; // KERNEL FUNCTIONS
; 
; int get_task_address(char id) {
; 
; 	return (int)task[id]->address;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd [0,y]
L67:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
_get_task_id::
; 
; }
; 
; 
; 
; 
; char get_task_id() { 
; 	 
; 	 return task[current]->id;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 2,y
	clra
L68:
	.dbline 0 ; func end
	rts
;             id -> 3,x
_get_task_name::
	pshd
	pshx
	tfr s,x
; }
; 
; 
; 
; char *get_task_name(unsigned char id) {
; 	 if (task[id] == NULL)
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L70
; 	 	return NULL;
	ldd #0
	bra L69
L70:
; 	 else
; 	 	return task[id]->name; 
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #3
L69:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;             id -> 3,x
_get_task_state::
	pshd
	pshx
	tfr s,x
; }
; 
; 
; 
; 
; int get_task_state(unsigned char id) { 
; 
; 	if (task[id] == NULL)
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L73
; 	   return -1;
	ldd #-1
	bra L72
L73:
; 	else if (id < MAXTASKS)
	ldab 3,x
	cmpb #8
	bhs L75
; 	 	return task[id]->state;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	bra L72
L75:
; 	else {
; 	 	  #ifdef KERNEL_ERROR_MSG
; 	 	  puts(error_src[1]); puts(error_msg[3]);
; 		  #endif
; 		  return -1;
	ldd #-1
L72:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;             id -> 3,x
_get_task_messages::
	pshd
	pshx
	tfr s,x
; 		  }
; 		  
; }
; 
; 
; 
; int get_task_messages(unsigned char id) {
; 
; 	if (task[id] == NULL)
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L78
; 	   return -1;
	ldd #-1
	bra L77
L78:
; 	else if (id < MAXTASKS)
	ldab 3,x
	cmpb #8
	bhs L80
; 	   return task[id]->message;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 20,y
	clra
	bra L77
L80:
; 	else {
; 		 #ifdef KERNEL_ERROR_MSG
; 	 	 puts(error_src[1]); puts(error_msg[3]);
; 		 #endif
; 		 return -1;
	ldd #-1
L77:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;             id -> 3,x
_get_task_priority::
	pshd
	pshx
	tfr s,x
; 		 }
; 
; }
; 
; 
; 
; int get_task_priority(unsigned char id) { 
; 
; 		 INTR_OFF();
		sei

; 		 
; 		 if (id < MAXTASKS) {
	ldab 3,x
	cmpb #8
	bhs L83
; 		 	INTR_ON();
		cli

; 		 	return task[id]->priority;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 13,y
	clra
	bra L82
L83:
; 			}
; 		 else {
; 	 	 	#ifdef KERNEL_ERROR_MSG
; 	 	 	puts(error_src[1]); puts(error_msg[4]);
; 			#endif
; 			INTR_ON();
		cli

; 			return -1;
	ldd #-1
L82:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;          ?temp -> -4,x
;          ?temp -> -4,x
;          ?temp -> -4,x
;          ?temp -> -4,x
;          ?temp -> -4,x
;          ?temp -> -2,x
;       newstate -> 7,x
;             id -> 3,x
_set_task_state::
	pshd
	pshx
	tfr s,x
	leas -4,sp
; 		 	}
; 
; }
; 
; 
; 
; int set_task_state(unsigned char id, unsigned char newstate) {
; 	
; 	
; 	INTR_OFF();
		sei

; 	
; 	
; 	// check id validity
; 	if (id < MAXTASKS) {
	ldab 3,x
	cmpb #8
	lbhs L86
; 
; 	   if (task[id] == NULL) {
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	bne L88
; 	   	  #ifdef KERNEL_ERROR_MSG
; 	 	  puts(error_src[1]); puts(error_msg[2]);
; 		  #endif
; 		  INTR_ON();
		cli

; 	 	  return -1;
	ldd #-1
	lbra L85
L88:
; 	   	  }
; 		  
; 		  
; 	   // check newstate validity
; 	   if ((newstate == RUNNING) || 
	ldab 7,x
	cmpb #2
	beq L93
	ldab 7,x
	cmpb #3
	beq L93
	ldab 7,x
	cmpb #4
	bls L90
L93:
; 	   	  (newstate == WAITING)  ||
; 	   	  (newstate > STOPPED)) { 
; 	      		 #ifdef KERNEL_ERROR_MSG
; 	 	 	  	 puts(error_src[1]); puts(error_msg[3]);
; 			  	 #endif
; 				 INTR_ON();
		cli

; 	 	  		 return -1;
	ldd #-1
	lbra L85
L90:
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 12,y
	clra
	std -2,x
	beq L97
	ldd -2,x
	cpd #1
	lbeq L104
	ldd -2,x
	cpd #2
	lbeq L111
	ldd -2,x
	cpd #4
	lbeq L114
	lbra L94
X3:
; 	   			 }
; 	 
; 	 		// referenced to the task's current state:
; 	   		switch (task[id]->state) {
L97:
; 		   	  	   case IDLE:
; 				   		if (newstate == IDLE) {	   // no change
	tst 7,x
	bne L98
; 						   INTR_ON();
		cli

; 				 		   return 0;
	ldd #0
	lbra L85
L98:
; 						   }
; 				 		else if (newstate == PENDING) {
	ldab 7,x
	cmpb #1
	bne L100
; 				 		   // pass msg to task[id]->msgbox;
; 						   task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  				   task[id]->message_data[STATE_BOX] = PENDING;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #1
	stab 21,y
; 						   INTR_ON();
		cli

; 					  	   return 0;
	ldd #0
	lbra L85
L100:
; 				 		   }
; 						else if (newstate == STOPPED) {
	ldab 7,x
	cmpb #4
	bne L102
; 							// pass msg to task[id]->msgbox;
; 						    task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  					task[id]->message_data[STATE_BOX] = STOPPED;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #4
	stab 21,y
; 							INTR_ON();
		cli

; 					  		return 0; 
	ldd #0
	lbra L85
L102:
; 						    }
; 				 		else {	  // nothing else is legal;
; 						   	 #ifdef KERNEL_ERROR_MSG
; 	 	 	  			   	 puts(error_src[1]); puts(error_msg[3]);
; 			  			   	 #endif
; 							 INTR_ON();
		cli

; 					  		 return -1;
	ldd #-1
	lbra L85
X4:
; 				 			 }
; 				 		break;
L104:
; 		   			case PENDING:
; 						 if (newstate == PENDING) {	// no change
	ldab 7,x
	cmpb #1
	bne L105
; 						 	INTR_ON();
		cli

; 				 		 	return 0;
	ldd #0
	lbra L85
L105:
; 							}
; 						 else if (newstate == IDLE) {
	tst 7,x
	bne L107
; 				   		 	  // pass msg to task[id]->msgbox;
; 						   	  #ifdef KERNEL_ERROR_MSG
; 	 	 	  			   	  puts(error_src[1]); puts(error_msg[0]);
; 			  			   	  #endif
; 							  INTR_ON();
		cli

; 					  		  return -1;
	ldd #-1
	lbra L85
L107:
; 							  }
; 						 else if (newstate == STOPPED) {
	ldab 7,x
	cmpb #4
	bne L109
; 				   		 	  	 // pass msg to task[id]->msgbox;
; 							  	 task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  					  	 task[id]->message_data[STATE_BOX] = STOPPED;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #4
	stab 21,y
; 							  	 INTR_ON();
		cli

; 					  		  	 return 0;
	ldd #0
	lbra L85
L109:
; 						 	  	 }	
; 						 else {
; 				   		 	  #ifdef KERNEL_ERROR_MSG
; 							  puts(error_src[1]); puts(error_msg[3]);
; 							  #endif
; 							  INTR_ON();
		cli

; 							  return -1;
	ldd #-1
	lbra L85
X5:
; 						 	  }
; 						 break;
L111:
; 					case RUNNING:
; 						 if (newstate == STOPPED) {
	ldab 7,x
	cmpb #4
	bne L112
; 						 	// pass msg to task[id]->msgbox;
; 							task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  					task[id]->message_data[STATE_BOX] = STOPPED;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #4
	stab 21,y
; 							
; 							INTR_ON();
		cli

; 					  		return 0;
	ldd #0
	lbra L85
L112:
; 						 	}
; 						 else {
; 				   		 	  #ifdef KERNEL_ERROR_MSG
; 							  puts(error_src[1]); puts(error_msg[3]);
; 							  #endif
; 							  INTR_ON();
		cli

; 							  return -1;
	ldd #-1
	lbra L85
X6:
; 						 	  }
; 						 break;
L114:
; 		   			case STOPPED:
; 		   				 if (newstate == STOPPED)	{ 	// no change
	ldab 7,x
	cmpb #4
	bne L115
; 				   		 	INTR_ON();
		cli

; 							return 0;
	ldd #0
	lbra L85
L115:
; 							}
; 						 else if (newstate == PENDING) {
	ldab 7,x
	cmpb #1
	bne L117
; 				   		 	  // pass msg to task[id]->msgbox;
; 							  task[id]->message |= STATE_FLAG;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -4,x
	tfr d,y
	pshy ; spill
	ldy -4,x
	puly ; reload
	bset 0,y,#1
; 		  					  task[id]->message_data[STATE_BOX] = PENDING;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #1
	stab 21,y
; 							  INTR_ON();
		cli

; 					  		  return 0;
	ldd #0
	bra L85
L117:
; 							  }
; 						 else {
; 					 	 	  #ifdef KERNEL_ERROR_MSG
; 							  puts(error_src[1]); puts(error_msg[3]);
; 							  #endif
; 							  INTR_ON();
		cli

; 							  return -1;
	ldd #-1
	bra L85
X7:
; 							  }
; 						 break;
L94:
; 		   			default:
; 		   		   			#ifdef KERNEL_ERROR_MSG
; 							puts(error_src[1]); puts(error_msg[3]);
; 							#endif
; 							INTR_ON();
		cli

; 							return -1;
	ldd #-1
	bra L85
X8:
; 				   			break;
L86:
; 							
; 	 				}	// end switch (task[id]->state)
; 					
; 	 		}		// if (id < MAXTASKS)
; 			
; 		   else {
; 		   		#ifdef KERNEL_ERROR_MSG
; 				puts(error_src[1]); puts(error_msg[2]);
; 				#endif
; 				INTR_ON();
		cli

; 				return -1;
	ldd #-1
	bra L85
X9:
; 				}
; 
; 	 INTR_ON();
		cli

; 	 return 0;
	ldd #0
L85:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;       priority -> 7,x
;             id -> 3,x
_set_task_priority::
	pshd
	pshx
	tfr s,x
; 
; }
; 
; 
; 
; int set_task_priority(unsigned char id, unsigned char priority) {
; 
; 	 if (priority == 0) 			 // priority 0 is reserved for the shell
	tst 7,x
	bne L120
; 	 	priority = 1;
	ldab #1
	stab 7,x
L120:
; 		
; 	 if (id >= (MAXTASKS)) {
	ldab 3,x
	cmpb #8
	blo L122
; 	 	#ifdef KERNEL_ERROR_MSG
; 		puts(error_src[1]); puts(error_msg[4]);
; 		#endif
; 		return -1;
	ldd #-1
	bra L119
L122:
	ldab 7,x
	cmpb #255
	bhi L126
	tst 7,x
	bhs L124
L126:
; 		}
; 	 else if ((priority > 255) || (priority < 0)) {
; 	 	#ifdef KERNEL_ERROR_MSG
; 		puts(error_src[1]); puts(error_msg[4]);
; 		#endif
; 		return -1;
	ldd #-1
	bra L119
L124:
; 		}
; 	 else {
; 	 	 task[id]->priority = priority;
	ldab 3,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 7,x
	stab 13,y
; 		 return 0;
	ldd #0
L119:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;  lreg1 -> -4,x
;  lreg2 -> -8,x
;          ?temp -> -15,x
;          ?temp -> -13,x
;          ?temp -> -11,x
;             id -> -9,x
;     stack_size -> 12,x
;          state -> 10,x
;       priority -> 9,x
;           addr -> 6,x
;           name -> 2,x
_create_task::
	pshd
	pshx
	tfr s,x
	leas -22,sp
; 		 }
; }
; 
; 
; 
; 
; int create_task(char *name, 
; 				void (*addr)(), 
; 				unsigned char priority, 
; 				int state,
; 				int stack_size) {
; 
; 	// LOCAL VARIABLES
; 	unsigned char id;
; 	
; 	
; 	INTR_OFF();	  // critical section	  
		sei

	clr -9,x
	bra L131
L128:
	ldab -9,x
	clra
	lsld
	addd #_task_ptr
	xgdy
	ldd 0,y
	beq L130
L129:
	ldab -9,x
	clra
	addd #1
	stab -9,x
L131:
; 	
; 	
; 	//if (get_free_memory() > 64) {
; 	
; 	// determine lowest free id available to assign to this task
; 	for (id=0; id<MAXTASKS; id++) {
	ldab -9,x
	cmpb #8
	blo L128
L130:
; 		if (task_ptr[id] != NULL)
; 		   continue;
; 		else
; 		   break;
; 		 }
; 
; 	
; 	// create task block
; 	if ((task[id] = malloc(sizeof(struct task_block))) == NULL) {
	ldd #29
	jsr _malloc
	std -18,x
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldd -18,x
	std 0,y
	ldd -18,x
	bne L134
; 	   #ifdef KERNEL_ERROR_MSG
; 	   puts(error_src[1]); puts(error_msg[5]);
; 	   #endif
; 	   return -1;
	ldd #-1
	lbra L127
L134:
; 	   }
; 	else { 
; 	 	 // put addr entry into task_ptr[]
; 		 task_ptr[id] = addr;
	ldab -9,x
	clra
	lsld
	addd #_task_ptr
	xgdy
	ldd 6,x
	std 0,y
; 		 
; 		 
; 	 	 // initialize the task structures
; 	 	 task[id]->address = addr;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd 6,x
	std 0,y
; 		 task[id]->id = id;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab -9,x
	stab 2,y
; 		 strcpy(task[id]->name, name);
	movw 2,x,0,sp
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #3
	jsr _strcpy
;  		 task[id]->state = state;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd 10,x
	stab 12,y
; 		 task[id]->priority = priority;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab 9,x
	stab 13,y
; 		 task[id]->period_tick = 0;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	leay 14,y
	pshy ; spill
	ldy #L20
	movw 0,y,-4,x
	movw 2,y,-2,x
	puly ; reload
	movw -4,x,0,y
	movw -2,x,2,y
; 		 task[id]->interrupt_msg_box = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd #0
	std 18,y
; 		 task[id]->message = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	clr 20,y
; 		 task[id]->message_data[0] = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	clr 21,y
; 		 task[id]->message_data[1] = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	clr 22,y
; 		 if (stack_size == 0) stack_size = DEFAULT_STACK_SIZE;
	ldd 12,x
	bne L136
	ldd #64
	std 12,x
L136:
; 		 task[id]->stack_size = stack_size;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd 12,x
	std 23,y
; 		 task[id]->top_of_stack = malloc(task[id]->stack_size); 
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -11,x
	ldy -11,x
	ldd 23,y
	jsr _malloc
	std -20,x
	ldy -11,x
	ldd -20,x
	std 25,y
; 		 task[id]->top_of_stack += task[id]->stack_size;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	sty -13,x
	ldd -13,x
	addd #25
	std -15,x
	ldy -13,x
	ldd 23,y
	addd [-15,x]
	ldy -15,x
	std 0,y
; 		 task[id]->frame_ptr = NULL;
	ldab -9,x
	clra
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldd #0
	std 27,y
; 	
; 	}
; 	//}
; 	INTR_ON();
		cli

; 	 
; 	return id;
	ldab -9,x
	clra
L127:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;            rid -> 3,x
_get_resource_state::
	pshd
	pshx
	tfr s,x
; 	 
; }
; 
; 
; 
; 
; int get_resource_state(unsigned char rid) {
; 
; 	if (rid < NUMRESOURCES) {
	ldab 3,x
	cmpb #4
	bhs L139
; 	 	return resource[rid].state;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+6
	xgdy
	ldab 0,y
	clra
	bra L138
L139:
; 		}
; 	else {
; 		 #ifdef KERNEL_ERROR_MSG
; 	 	 puts(error_src[1]); puts(error_msg[6]);
; 		 #endif
; 		 return -1;
	ldd #-1
L138:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;            rid -> 3,x
_get_resource_owner::
	pshd
	pshx
	tfr s,x
; 		 }
; 
; }
; 
; 
; 
; 
; 
; int get_resource_owner(unsigned char rid) {
; 
; 	if (rid < NUMRESOURCES) {
	ldab 3,x
	cmpb #4
	bhs L143
; 	 	return resource[rid].owner;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+7
	xgdy
	ldab 0,y
	clra
	bra L142
L143:
; 		}
; 	else {
; 		 #ifdef KERNEL_ERROR_MSG
; 	 	 puts(error_src[1]); puts(error_msg[6]);
; 		 #endif
; 		 return -1;
	ldd #-1
L142:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;            rid -> 3,x
_get_resource_queuelen::
	pshd
	pshx
	tfr s,x
; 		 }
; 
; }
; 
; 
; 
; 
; int get_resource_queuelen(unsigned char rid) {
; 
; 	if (rid < NUMRESOURCES) {
	ldab 3,x
	cmpb #4
	bhs L147
; 	 	return resource[rid].queue_ptr;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+11
	xgdy
	ldab 0,y
	clra
	bra L146
L147:
; 		}
; 	else {
; 		 #ifdef KERNEL_ERROR_MSG
; 	 	 puts(error_src[1]); puts(error_msg[6]);
; 		 #endif
; 		 return -1;
	ldd #-1
L146:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;           last -> -6,x
;         memory -> -4,x
;              i -> -2,x
_get_free_memory::
	pshx
	tfr s,x
	leas -8,sp
; 		 }
; 
; }
; 
; 
; 
; 
; int get_free_memory(void) {
; 
; 	// LOCAL VARIABLES
; 	char *memory, *last;
; 	int i;
; 	
; 	
; 	INTR_OFF();
		sei

	ldd #0
	std -2,x
L151:
; 	// check for largest free memory block
; 	for (i=0; i<INITIAL_HEAP_SIZE; i+=32) {
; 		if ((memory = malloc(i)) != NULL)
	ldd -2,x
	jsr _malloc
	std -8,x
	std -4,x
	ldd -8,x
	beq L153
; 		   last = memory;
	movw -4,x,-6,x
; 		else
; 		   break;
L156:
	ldd -6,x
	jsr _free
L152:
	ldd -2,x
	addd #32
	std -2,x
	ldd -2,x
	cpd #1344
	blt L151
L153:
; 		free(last);
; 		}
; 		
; 	INTR_ON();
		cli

; 	//printf("%d bytes\n", i);
; 	
; 	return (i-32);
	ldd -2,x
	subd #32
L150:
	tfr x,s
	pulx
	.dbline 0 ; func end
	rts
;          ?temp -> -6,x
;          ?temp -> -4,x
;          ?temp -> -2,x
;            rid -> 3,x
_sem_get::
	pshd
	pshx
	tfr s,x
	leas -8,sp
; 
; }
; 
; 
; 
; 
; int sem_get(char rid) {
; 
; 	 /* Gives a resource to a requesting task.
; 	 	returns the resource id number (0,1,2,...) if free.
; 	 	otherwise returns -1.
; 		
; 		At this point, semaphores are a procedural control
; 		that the tasks have to follow to avoid resource contention.
; 		There is no kernel control over resources yet.  */
; 	 
; 	 
; 	 // critical section
; 	 INTR_OFF();
		sei

; 	 
; 	 
; 	 
; 	 // GET SEMAPHORE
; 	 // give semaphore to task
; 	 if (resource[rid].state == NOTBUSY) {
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+6
	xgdy
	tst 0,y
	bne L158
; 	 	resource[rid].state = BUSY;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+6
	xgdy
	ldab #1
	stab 0,y
; 		resource[rid].owner = current;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+7
	xgdy
	ldd _current
	stab 0,y
; 		
; 		INTR_ON();
		cli

; 		return rid;
	ldab 3,x
	clra
	lbra L157
L158:
; 	 	}
; 	 
; 	 // resource is taken/busy so make task wait
; 	 else {
; 		  task[current]->message |= STATE_FLAG;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldd 0,y
	addd #20
	std -2,x
	tfr d,y
	pshy ; spill
	ldy -2,x
	puly ; reload
	bset 0,y,#1
; 		  task[current]->message_data[STATE_BOX] = WAITING;
	ldd _current
	lsld
	addd #_task
	xgdy
	ldy 0,y
	ldab #3
	stab 21,y
; 		
; 		  // put waiting task into the resources queue if there's space
; 		  if (resource[rid].queue_ptr < 3) {
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+11
	xgdy
	ldab 0,y
	cmpb #3
	bhs L163
; 		   	 resource[rid].queue[resource[rid].queue_ptr] = current;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	std -4,x
	addd #_resource+11
	xgdy
	ldab 0,y
	clra
	pshd ; spill
	ldd -4,x
	addd #_resource+8
	std -8,x
	puld ; reload
	addd -8,x
	xgdy
	ldab _current+1
	stab 0,y
; 		   	 resource[rid].queue_ptr++;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+11
	std -6,x
	tfr d,y
	ldab 0,y
	clra
	addd #1
	ldy -6,x
	stab 0,y
; 		   	 }
L163:
; 		
; 		  INTR_ON();
		cli

; 		  return -1;
	ldd #-1
L157:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
;            rid -> 3,x
_sem_give::
	pshd
	pshx
	tfr s,x
; 	 	  } 	 
; 		
; }
; 
; 
; 
; 
; int sem_give(char rid) {
; 
; 	/* Takes a resource back from a task.
; 	   will (eventually) pass a message to a waiting task.  
; 	   
; 	   	At this point, semaphores are a procedural control
; 		that the tasks have to follow to avoid resource contention.
; 		There is no kernel control over resources yet.  */
; 	
; 	
; 	// critical section
; 	INTR_OFF();
		sei

; 	
; 	
; 	// return the resource
; 	resource[rid].state = NOTBUSY;
	ldab 3,x
	clra
	xgdy
	ldd #12
	emuls
	addd #_resource+6
	xgdy
	clr 0,y
; 	//resource[rid].owner = NULL;
; 	
; 	INTR_ON();
		cli

; 	
; 	return 0;
	ldd #0
L169:
	tfr x,s
	pulx
	leas 2,sp
	.dbline 0 ; func end
	rts
	.area bss
_resource::
	.blkb 48
_task::
	.blkb 16
_last_time_mark::
	.blkb 4
_delta_t::
	.blkb 4
_time_tick::
	.blkb 4
_cop_cycle::
	.blkb 2
_system_tick::
	.blkb 4
_current::
	.blkb 2
_task_ptr::
	.blkb 16
	.area text
L66:
	.word 0,1
L64:
	.byte 'K,'E,'R,'N,'E,'L,58,32,'t,'a,'s,'k,32,'s,'t,'a
	.byte 't,'e,32,'e,'r,'r,'o,'r,10,0
L21:
	.byte 'r,'l,'p,'O,'S,32,'v,48,46,55,10,10,0
L20:
	.word 0,0
L19:
	.byte 's,'h,'e,'l,'l,32,'f,'a,'i,'l,'u,'r,'e,0
L18:
	.byte 's,'h,'e,'l,'l,0
L15:
	.byte 's,'y,'s,'I,'n,'i,'t,32,'f,'a,'i,'l,'u,'r,'e,0
L14:
	.byte 's,'y,'s,'I,'n,'i,'t,0

