/*
 *	Transputer style kernel in mixed C/asm
 *	Copyright (C) 1998 Jim Moores
 *	Based on the KRoC/sparc kernel Copyright (C) 1994-2000 D.C. Wood and P.H. Welch
 *	OOS hacks copyright (C) 2002 Fred Barnes and Brian Vinter
 *	Portions copyright (C) 1999-2005 Fred Barnes <frmb@kent.ac.uk>
 *
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 *	This program is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program; if not, write to the Free Software
 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*{{{  includes, etc.*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#if defined(OOS_BUILD)
	#include <oos_funcs.h>
#else
	#include <stdio.h>
	#ifdef HAVE_STDLIB_H
	#include <stdlib.h>
	#endif	/* HAVE_STDLIB_H */
	#include <sys/types.h>
#endif

#define __SCHED_C

#include <sched_consts.h>
#include <arch/sched_types.h>
#include <arch/sched_asm_inserts.h>
#include <arch/occam_io.h>
#include <arch/timer.h>

#ifndef RTS_H
	#define RTS_H
	#include <rts.h>
#endif

#include <arch/deadlock.h>
#if !defined(OOS_BUILD)
	#ifdef BLOCKING_SYSCALLS
		#include <setjmp.h>
		#include <bsyscalls_if.h>
	#endif
#endif	/* !OOS_BUILD */

#ifdef USE_PTHREADS
	#include <pthread.h>
#endif

#include <dynproc.h>
#include <mobproc.h>
#include <pgroup.h>
#include <arch/atomics.h>
#include <dmem_if.h>

typedef void (*FUNCPTR)(void);

#include <debug.h>
#include <queues.h>

#ifdef USER_DEFINED_CHANNELS
#include <udc.h>
#endif
#ifdef LINUX_CSPDRIVER
#include <arch/cspdriver.h>
#endif

#if defined(BLOCKING_SYSCALLS) && !defined(OOS_BUILD)
	#include <arch/atomics.h>
	#include <arch/bsyscalls.h>
#endif

#if DEFAULT_SCHED_POLICY == SCHED_POLICY_US
	#define SCHED_POLICY(me,other) QUEUE(other)
#elif DEFAULT_SCHED_POLICY == SCHED_POLICY_OTHER
	#define SCHED_POLICY(me,other) QUEUE(me); me = other
#elif DEFAULT_SCHED_POLICY == SCHED_POLICY_NEITHER_US
	#define SCHED_POLICY(me,other) QUEUE(me); QUEUE(other); me = GetNextProcess_NonEmptyQ()
#elif DEFAULT_SCHED_POLICY == SCHED_POLICY_NEITHER_OTHER
	#define SCHED_POLICY(me,other) QUEUE(other); QUEUE(me); me = GetNextProcess_NonEmptyQ()
#else
	#define SCHED_POLICY(me,other) fprintf(stderr, "BUG! " __FILE__ ":" #__LINE__ "\n");
#endif

#if defined(OOS_BUILD)
	#define MESSAGE(fmt,args...) oos_printk(fmt,##args)
#else
	#define MESSAGE(fmt,args...) fprintf(stderr,fmt,##args)
#endif
/*}}}*/

/*{{{  externs (defined by the translator)*/
/* used to notify STOP error-mode */
extern int _occam_errormode;
/*}}}*/
/*{{{  PUBLIC variables that are used elsewhere in the run time system */
#if defined(OOS_BUILD)
	int *inttab[OOS_NUM_INTERRUPTS];			/* interrupt process linkage (Wptr of waiting process) */
	volatile int intcount[OOS_NUM_INTERRUPTS];		/* count of interrupts received */
	volatile int intlast;			/* last interrupt received */
	volatile int *iq_fptr, *iq_bptr;	/* queue where awoken listeners sit */
	volatile long long ticount;		/* total number of interrupts */
#endif

#if defined(OOS_BUILD) || defined(ENABLE_CPU_TIMERS)
	unsigned long glob_cpufactor;		/* 2^32 / cpu-MHz */
	unsigned long glob_cpukhz;		/* cpu-MHz * 1024 */
#endif
#if defined(OOS_BUILD)
	unsigned int glob_cpuhz;
#endif
/*}}}*/
/*{{{  global variables (Wptr, etc.) */

sync_type sf;		/* this is 64-bits including Tptr, for which a macro is defined */

#ifdef PROCESS_PRIORITY

#if 1 || !defined(CAN_DO_SCHEDSTRUCT)
#define PPEmpty ((word)0xffffffff)
word *Fptr_q[MAX_PRIORITY_LEVELS];
word *Bptr_q[MAX_PRIORITY_LEVELS];
word PPriority;		/* current process priority _and_ process group */
word PState;		/* state of queues (bitset) */
#endif

#endif	/* PROCESS_PRIORITY */

#if defined(CAN_DO_SCHEDSTRUCT)
sched_vars_type svars;
#else
word *Fptr, *Bptr;
word *Wptr;
#endif

#if defined(CAN_DO_SCHEDSTRUCT)
void DEBUG_do_set_svars (void)
{
	svars.wptr = (word *)0;
	svars.fptr = (word *)1;
	svars.bptr = (word *)2;
	svars.ppriority = 3;
	svars.pstate = 4;
	svars.fptrq[0] = (word *)5;
	svars.bptrq[0] = (word *)6;
	return;
}
#endif


/*}}}*/
/*{{{  paramter passing variables */
#if 0
/* at some point, this will have to be cleaned up... (frmb) */
typedef struct {
	word **Vchannel_address;
	word Vreturn_address;
	byte *Vsource_address;
	byte *Vdestination_address;
	word Vcount;
	Time Vwait_time;
	word Vstart_address;
	word Vstart_offset;
	word Vguard;
	word Vprocess_address;
	word Vcode_offset;
	word Vprecondition;
	word *Vusage;
	Time Vtimeout;
	word Vresult;
} param_sched_vars;



static param_sched_vars psvars;

#define channel_address psvars.Vchannel_address
#define return_address psvars.Vreturn_address
#define source_address psvars.Vsource_address
#define destination_address psvars.Vdestination_address
#define count psvars.Vcount
#define wait_time psvars.Vwait_time
#define start_address psvars.Vstart_address
#define start_offset psvars.Vstart_offset
#define guard psvars.Vguard
#define process_address psvars.Vprocess_address
#define code_offset psvars.Vcode_offset
#define precondition psvars.Vprecondition
#define usage psvars.Vusage
#define timeout psvars.Vtimeout
#define parm_result psvars.Vresult
#endif
#if 1
static word **channel_address;
static word return_address;
static byte *source_address;
static byte *destination_address;
static word count;
static Time wait_time;
static word start_offset;
static word guard;
static word process_address;
static word code_offset;
static word precondition;
static word *usage;
Time timeout;
static word parm_result;
#endif

/*}}}*/
/*{{{  pseudo private variables (there names are externally visible, but they should not be used*/
Time now; /* must be int to work (signed) */
word temp1;
word *temp_ptr;
word *other_workspace;
#if defined(OOS_BUILD)
word *occam_current;
#undef current
#define current occam_current
#else
word *current;
#endif
word *previous;
word fired;
word trapval_A, trapval_B, trapval_C;
word filename_addr, procedure_addr;
word overflow_info2, overflow_info;
word zerodiv_info2, zerodiv_info;
word floaterr_info2, floaterr_info, floaterr_fpustatus;
word range_info1, range_info2;
word seterr_info1, seterr_info2;
word b_param, b_func;
word res_ptr;
word dmem_index, dmem_size;
word *dmem_ptr;
word kr_param, ds_param, *kr_wptr;
d_process *kr_dptr;

word mdparam1, mdparam2, mdparam3, mdparam4, mdparam5, mdparam6;
int tmpint_a, tmpint_b, tmpint_c;
long long tmplonglong;

word *sp_aptr;
word *sp_bptr;
word *sp_cptr;

word the_stackptr2;
word the_stackptr;

#ifdef USER_DEFINED_CHANNELS
ext_chan_t *extchan;
#endif

int occam_finished = 0;
/*}}}*/
/*{{{  ENTRY_TRACE macros*/
#ifdef ENABLE_KTRACES
	#ifdef PROCESS_PRIORITY
		#define ENTRY_TRACE(X, FMT, args...) \
			LOAD_ESP (the_stackptr); \
			MESSAGE ("<enter>   "#X" [0x%x,0x%8.8x,%p,%p,%p,%p] (esp=%8.8x) [%d:%d] ", (unsigned int)PPriority, (unsigned int)PState, Wptr, Fptr, Bptr, Tptr, the_stackptr, \
					(mdparam1 == 0xffffffff) ? 0 : ((mdparam1 >> 16) & 0xffff), (mdparam1 == 0xffffffff) ? 0 : (mdparam1 & 0xffff)); \
			if ((MaskedPPriority < 0) || (MaskedPPriority >= MAX_PRIORITY_LEVELS)) { MESSAGE ("b0rked!\n"); occam_exit(0,(int)Wptr); } \
			MESSAGE ("(" FMT ")\n", ##args)
		#define ENTRY_TRACE0(X) \
			LOAD_ESP (the_stackptr); \
			MESSAGE ("<enter>   "#X" [0x%x,0x%8.8x,%p,%p,%p,%p] (esp=%8.8x) [%d:%d]\n", (unsigned int)PPriority, (unsigned int)PState, Wptr, Fptr, Bptr, Tptr, the_stackptr, \
					(mdparam1 == 0xffffffff) ? 0 : ((mdparam1 >> 16) & 0xffff), (mdparam1 == 0xffffffff) ? 0 : (mdparam1 & 0xffff))
	#else	/* !PROCESS_PRIORITY */
		#define ENTRY_TRACE(X, FMT, args...) \
			LOAD_ESP (the_stackptr); \
			MESSAGE ("<enter>   "#X" [%p,%p,%p,%p] (esp=%8.8x) ", Wptr, Fptr, Bptr, Tptr, the_stackptr); \
			MESSAGE ("(" FMT ")\n", ##args)
		#define ENTRY_TRACE0(X) \
			LOAD_ESP (the_stackptr); \
			MESSAGE ("<enter>   "#X" [%p,%p,%p,%p] (esp=%8.8x)\n", Wptr, Fptr, Bptr, Tptr, the_stackptr)
	#endif	/* !PROCESS_PRIORITY */
#else	/* !ENABLE_KTRACES */
	#define ENTRY_TRACE(X, FMT, args...)
	#define ENTRY_TRACE0(X)
#endif	/* !ENABLE_KTRACES */
/*}}}*/

#ifdef BLOCKING_SYSCALLS
/*{{{  blocking syscalls vars (and externs)*/
	word b_return_address;
	#if 0 && defined(LINUX_CSPDRIVER)
		extern volatile word *volatile q_mfptr;
	#endif
/*}}}*/
#endif

#ifdef BLOCKING_PROFILE
/*{{{  blocking syscall profile vars*/
	volatile long long signal_time;
	long long collect_time;
/*}}}*/
#endif

#ifdef BLOCKING_SYSCALLS
/*{{{  int scheduler_can_do_bsyscalls (void)*/
/* dummy function */
int scheduler_can_do_bsyscalls (void)
{
	return 1;
}
/*}}}*/
#endif
#ifdef ENABLE_CPU_TIMERS
/*{{{  int scheduler_can_do_cputimers (void)*/
/* dummy function */
int scheduler_can_do_cputimers (void)
{
	return 1;
}
/*}}}*/
#endif
#ifdef DYNAMIC_PROCS
/*{{{  int scheduler_can_do_dynproc (void)*/
/* dummy function */
int scheduler_can_do_dynproc (void)
{
	return 1;
}
/*}}}*/
#endif

#ifdef PROCESS_PRIORITY
/*{{{  static inline int bsf (int v)*/
/* bit-scan forward (for priorities) */
static inline int bsf (int v)
{
	int res = 32;

	ASM_BSF (v, res);
	return res;
}
/*}}}*/
#endif

/*{{{  void print_tq (void)*/
/* print out timer queue for debugging*/
void print_tq (void)
{
	word *tqptr = Tptr;

	MESSAGE ("Timer Queue dump.\n");
	while ((word)tqptr != NotProcess_p) {
		MESSAGE ("(Wptr = 0x%x, Wptr[Time_f] = %d, Wptr[State] = 0x%x)\n", (unsigned int)tqptr, tqptr[Time_f], (unsigned int)tqptr[State]);
		tqptr = (word*)tqptr[TLink];
	}
	MESSAGE ("--- end Timer queue dump.\n");
}
/*}}}*/
/*{{{  void kernel_panic(void) */
/* kernel panic function*/
void kernel_panic (void)
{
	MESSAGE ("Kernel Panic: called kernel function not implemented.\n");
#if defined(OOS_BUILD)
	oos_exit (1);
#else
	exit(1);
#endif
}
/*}}}*/
/*{{{  void zerodiv_happened (void)*/
/* divide-by-zero handling function*/
void zerodiv_happened (void)
{
	int line_num, file_num, proc_num;
	char *div_filename, *div_procname;
	int *div_fc, *div_off;
	int *pvr_fc, *pvr_off;

	div_filename = div_procname = NULL;
	line_num = zerodiv_info & 0xffff;
	file_num = (zerodiv_info2 >> 16) & 0xffff;
	proc_num = zerodiv_info2 & 0xffff;
	div_fc = (int *)filename_addr;
	if (file_num > *div_fc) {
		MESSAGE ("KRoC: filename table inconsistent!\n");
		file_num = -1;
	} else {
		div_off = div_fc + (file_num + 1);
		div_filename = (char *)filename_addr + *div_off;
	}
	pvr_fc = (int *)procedure_addr;
	if (proc_num > *pvr_fc) {
		MESSAGE ("KRoC: procedure table inconsistent!\n");
		proc_num = -1;
	} else {
		pvr_off = pvr_fc + (proc_num + 1);
		div_procname = (char *)procedure_addr + *pvr_off;
	}
	MESSAGE ("KRoC: divide-by-zero in PROC \"%s\" in file \"%s\" near line %d\n", (proc_num >= 0) ? div_procname : "<unknown>",
		(file_num >= 0) ? div_filename : "<unknown>", line_num);
	return;
}
/*}}}*/
/*{{{  void overflow_happened (void)*/
/* overflow handling function*/
void overflow_happened (void)
{
	static char *overflow_ops[] = { "INVALID", "ADD", "SUB", "MUL", "DIV", "REM", "LADD", "LSUB", "ADC", "STOP", "LDIV", "FMUL", "FPCHKI32", "FPCHKI64" };
	static int num_overflow_ops = 14;
	int ovr_idx, line_num, file_num, proc_num;
	char *ovr_filename, *ovr_procname;
	int *ovr_fc, *ovr_off;
	int *pvr_fc, *pvr_off;

	ovr_filename = ovr_procname = NULL;
	ovr_idx = (overflow_info >> 24) & 0xff;
	line_num = overflow_info & 0xffff;
	file_num = (overflow_info2 >> 16) & 0xffff;
	proc_num = overflow_info2 & 0xffff;
	if ((ovr_idx >= num_overflow_ops) || (ovr_idx < 0)) {
		ovr_idx = 0;
	}
	ovr_fc = (int *)filename_addr;
	if (file_num > *ovr_fc) {
		MESSAGE ("KRoC: filename table inconsistent!\n");
		file_num = -1;
	} else {
		ovr_off = ovr_fc + (file_num + 1);
		ovr_filename = (char *)filename_addr + *ovr_off;
	}
	pvr_fc = (int *)procedure_addr;
	if (proc_num > *pvr_fc) {
		MESSAGE ("KRoC: procedure table inconsistent!\n");
		proc_num = -1;
	} else {
		pvr_off = pvr_fc + (proc_num + 1);
		ovr_procname = (char *)procedure_addr + *pvr_off;
	}
	MESSAGE ("KRoC: overflow on operation %s in PROC \"%s\" in file \"%s\" near line %d\n",
		overflow_ops[ovr_idx], (proc_num >= 0) ? ovr_procname : "<unknown>", (file_num >= 0) ? ovr_filename : "<unknown>", line_num);
	return;
}
/*}}}*/
/*{{{  void floaterr_happened (void)*/
/* floating-point error handling*/
void floaterr_happened (void)
{
	int line_num, file_num, proc_num;
	char *flt_filename, *flt_procname;
	int *flt_fc, *flt_fo;
	int *flt_pc, *flt_po;
	static char *fpuerrs[] = {"invalid-op", "denormalised-operand", "divide-by-zero", "overflow", "underflow", "inexact-result"};
	int num_fpuerrs = 6;
	int i;

	flt_filename = flt_procname = NULL;
	line_num = floaterr_info & 0xfff;
	file_num = (floaterr_info2 >> 16) & 0xffff;
	proc_num = floaterr_info2 & 0xffff;
	flt_fc = (int *)filename_addr;
	if (file_num > *flt_fc) {
		MESSAGE ("KRoC: filename table inconsistent!\n");
		file_num = -1;
	} else {
		flt_fo = flt_fc + (file_num + 1);
		flt_filename = (char *)filename_addr + *flt_fo;
	}
	flt_pc = (int *)procedure_addr;
	if (proc_num > *flt_pc) {
		MESSAGE ("KRoC: procedure table inconsistent!\n");
		proc_num = -1;
	} else {
		flt_po = flt_pc + (proc_num + 1);
		flt_procname = (char *)procedure_addr + *flt_po;
	}
	MESSAGE ("KRoC: floating-point error (");
	floaterr_fpustatus &= 0x3f;
	for (i=0; i<num_fpuerrs; i++) {
		if (floaterr_fpustatus & (1 << i)) {
			MESSAGE ("%s", fpuerrs[i]);
			floaterr_fpustatus &= ~(1 << i);
			if (floaterr_fpustatus) {
				MESSAGE (",");
			}
		}
	}
	MESSAGE (") in PROC \"%s\" in file \"%s\" near line %d\n", 
		(proc_num >= 0) ? flt_procname : "<unknown>", (file_num >= 0) ? flt_filename : "<unknown>", line_num);
	return;
}
/*}}}*/
/*{{{  void handle_range_error (void)*/
/* range error handling */
void handle_range_error (void)
{
	static char *rangerr_ops[] = { "INVALID", "SHIFT", "CSNGL", "CSUB0", "CCNT1", "CWORD" };
	static int num_rangerr_ops = 6;
	int range_op, line_num, file_num, proc_num;
	char *range_file, *range_proc;
	int rt_bits;

	range_op = (range_info1 >> 24) & 0xff;
	rt_bits = (range_info1 >> 16) & 0xff;
	line_num = range_info1 & 0xffff;
	if (rt_bits != 0xff) {
		MESSAGE ("KRoC: Range error (debug data incorrect - rt_bits=%x)\n", rt_bits);
		return;
	}
	if ((range_op >= num_rangerr_ops) || (range_op < 0)) {
		MESSAGE ("KRoC: Range error (debug data incorrect - range_op=%d)\n", range_op);
		return;
	}
	file_num = (range_info2 >> 16) & 0xffff;
	proc_num = range_info2 & 0xffff;
	range_file = (char *)filename_addr;
	range_proc = (char *)procedure_addr;
	if ((file_num >= *(int *)(range_file)) || (file_num < 0)) {
		MESSAGE ("KRoC: Range error (debug data incorrect - file_num=%d)\n", file_num);
		return;
	}
	if ((proc_num >= *(int *)(range_proc)) || (proc_num < 0)) {
		MESSAGE ("KRoC: Range error (debug data incorrect - proc_num=%d)\n", proc_num);
		return;
	}
	range_file += *(int *)(range_file + (4 * (file_num+1)));
	range_proc += *(int *)(range_proc + (4 * (proc_num+1)));
	MESSAGE ("KRoC: Range error on operation %s in PROC \"%s\" in file \"%s\" near line %d\n",
		rangerr_ops[range_op], range_proc, range_file, line_num);
	return;
}
/*}}}*/
/*{{{  void handle_seterr (void)*/
/* seterr error handling */
void handle_seterr (void)
{
	int line_num, file_num, proc_num;
	char *seterr_file, *seterr_proc;
	int rt_bits;

	rt_bits = (seterr_info1 >> 16) & 0xffff;
	line_num = seterr_info1 & 0xffff;
	if (rt_bits != 0xfb00) {
		MESSAGE ("KRoC: SetErr: application level error (debug data incorrect - rt_bits=%4.4x)\n", rt_bits);
		return;
	}
	file_num = (seterr_info2 >> 16) & 0xffff;
	proc_num = seterr_info2 & 0xffff;
	seterr_file = (char *)filename_addr;
	seterr_proc = (char *)procedure_addr;
	if ((file_num >= *(int *)(seterr_file)) || (file_num < 0)) {
		MESSAGE ("KRoC: SetErr: application level error (debug data incorrect - file_num=%d)\n", file_num);
		return;
	}
	if ((proc_num >= *(int *)(seterr_proc)) || (proc_num < 0)) {
		MESSAGE ("KRoC: SetErr: application level error (debug data incorrect - proc_num=%d)\n", proc_num);
		return;
	}
	seterr_file += *(int *)(seterr_file + (4 * (file_num+1)));
	seterr_proc += *(int *)(seterr_proc + (4 * (proc_num+1)));
	MESSAGE ("KRoC: SetErr: application level error in PROC \"%s\", in file \"%s\" near line %d\n",
		seterr_proc, seterr_file, line_num);
	return;
}
/*}}}*/
/*{{{  void show_last_debug_insert (void)*/
/* show_last_debug_insert*/
void show_last_debug_insert (void)
{
	void (*setup_fcn)(void);
	int file_num, line_num;
	char *insert_file;

	if ((mdparam1 != 0xffffffff) && (mdparam2 != 0xffffffff) && mdparam1 && mdparam2) {
		file_num = (mdparam1 >> 16) & 0xffff;
		line_num = mdparam1 & 0xffff;
		/* mdparam2 holds address of setup code */
		setup_fcn = (void (*)(void))mdparam2;
		setup_fcn ();
		insert_file = (char *)mdparam1;
		if ((file_num >= *(int *)(insert_file)) || (file_num < 0)) {
			MESSAGE ("KRoC: debug insert: invalid file number (file_num=%d)\n", file_num);
			return;
		}
		insert_file += *(int *)(insert_file + (4 * (file_num+1)));
		MESSAGE ("KRoC: last debug position was in file \"%s\" near line %d\n", insert_file, line_num);
	}
	if ((mdparam3 != 0xffffffff) && (mdparam4 != 0xffffffff) && mdparam3 && mdparam4) {
		file_num = (mdparam3 >> 16) & 0xffff;
		line_num = mdparam3 & 0xffff;
		/* mdparam2 holds address of setup code */
		setup_fcn = (void (*)(void))mdparam4;
		setup_fcn ();
		insert_file = (char *)mdparam1;
		if ((file_num >= *(int *)(insert_file)) || (file_num < 0)) {
			MESSAGE ("KRoC: debug insert: invalid file number (file_num=%d)\n", file_num);
			return;
		}
		insert_file += *(int *)(insert_file + (4 * (file_num+1)));
		MESSAGE ("KRoC: last position before CALL was in file \"%s\" near line %d\n", insert_file, line_num);
	}
	return;
}
/*}}}*/
/*{{{  void err_no_bsyscalls (word *wptr, int ra)*/
/* err_no_bsyscalls*/
void err_no_bsyscalls (word *wptr, int ra)
{
	MESSAGE ("KRoC: blocking system calls not enabled in this kernel. (Wptr=0x%x)\n", (unsigned int)wptr);
	occam_exit (1, ra);
	return;
}
/*}}}*/
/*{{{  int not_on_any_queue (unsigned int ws_base, unsigned int ws_limit)*/
/* not_on_run_queue*/
int not_on_any_queue (unsigned int ws_base, unsigned int ws_limit)
{
	word *tmp;
	int not_on_queue;

	not_on_queue = 1;
	if (Fptr) {
		for (tmp=Fptr; tmp != Bptr; tmp=(word *)tmp[Link]) {
			if (((unsigned int)tmp >= ws_base) && ((unsigned int)tmp < ws_limit)) {
#if 0
fprintf (stderr, "** workspace range [0x%x, 0x%x] lurks on run-queue %p\n", ws_base, ws_limit, tmp);
#endif
				not_on_queue = 0;
				break;
			}
		}
		if (((unsigned int)tmp >= ws_base) && ((unsigned int)tmp < ws_limit)) {
#if 0
fprintf (stderr, "** workspace range [0x%x, 0x%x] lurks on run-queue %p\n", ws_base, ws_limit, tmp);
#endif
			not_on_queue = 0;
		}
	}
	if (not_on_queue && Tptr) {
		for (tmp=Tptr; tmp != NotProcess_p; tmp=(word *)tmp[TLink]) {
			if (((unsigned int)tmp >= ws_base) && ((unsigned int)tmp < ws_limit)) {
#if 0
fprintf (stderr, "** workspace range [0x%x, 0x%x] lurks on timer-queue %p\n", ws_base, ws_limit, tmp);
#endif
				not_on_queue = 0;
				break;
			}
		}
	}
	#ifdef PROCESS_PRIORITY
		if (not_on_queue) {
			int i;

			/* test all priority queues */
			for (i=0; not_on_queue && (i < MAX_PRIORITY_LEVELS); i++) {
				for (tmp = Fptr_q[i]; tmp && (tmp != Bptr_q[i]); tmp = (word *)tmp[Link]) {
					if (((unsigned int)tmp >= ws_base) && ((unsigned int)tmp < ws_limit)) {
						not_on_queue = 0;
						break;
					}
				}
				if (tmp && ((unsigned int)tmp >= ws_base) && ((unsigned int)tmp < ws_limit)) {
					not_on_queue = 0;
					break;
				}
			}
		}
	#endif	/* !PROCESS_PRIORITY */
	return not_on_queue;
}
/*}}}*/
/*{{{  int remove_from_any_queue (unsigned int ws_base, unsigned int ws_limit)*/
/* remove_from_any_queue */
int remove_from_any_queue (unsigned int ws_base, unsigned int ws_limit)
{
	word *tmp, *follow;
	int not_on_queue = 1;

	if (Fptr) {
		follow = NULL;
		for (tmp=Fptr; tmp != Bptr; follow = tmp, tmp=(word *)tmp[Link]) {
			if (((unsigned int)tmp >= ws_base) && ((unsigned int)tmp < ws_limit)) {
#if 0
fprintf (stderr, "** removing run-queue process %p from workspace range [0x%x, 0x%x]\n", tmp, ws_base, ws_limit);
#endif
				if (follow) {
					follow[Link] = tmp[Link];
				} else {
					Fptr = (word *)tmp[Link];
				}
				not_on_queue = 0;
				break;
			}
		}
		if (((unsigned int)tmp >= ws_base) && ((unsigned int)tmp < ws_limit)) {
#if 0
fprintf (stderr, "** removing run-queue process %p from workspace range [0x%x, 0x%x]\n", tmp, ws_base, ws_limit);
#endif
			if (follow) {
				follow[Link] = tmp[Link];
			} else {
				Fptr = (word *)tmp[Link];
			}
			not_on_queue = 0;
		}
	}
	if (Tptr) {
		follow = NULL;
		for (tmp=Tptr; tmp != NotProcess_p; follow = tmp, tmp=(word *)tmp[TLink]) {
			if (((unsigned int)tmp >= ws_base) && ((unsigned int)tmp < ws_limit)) {
#if 0
fprintf (stderr, "** removing timer-queue process %p from workspace range [0x%x, 0x%x]\n", tmp, ws_base, ws_limit);
#endif
				if (follow) {
					follow[TLink] = tmp[TLink];
				} else {
					Tptr = (word *)tmp[TLink];
				}
				not_on_queue = 0;
				break;
			}
		}
	}
	return not_on_queue;
}
/*}}}*/
/*{{{  void do_queue_process (word *ws)*/
/* do_queue_process*/
void do_queue_process (word *ws)
{
	#ifdef PROCESS_PRIORITY
	if ((PriMasked (ws[Priority]) < 0) || (PriMasked (ws[Priority]) >= MAX_PRIORITY_LEVELS)) {
		MESSAGE ("KRoC: invalid priority %d for do_queue_process(%p)\n", ws[Priority], ws);
		occam_exit (1, (int)Wptr);
	} else if (PriMasked (ws[Priority]) < MaskedPPriority) {
		PQUEUE (PriMasked (ws[Priority]), ws);
		sf.u.s.priority_sync = 1;
	} else if (PriMasked (ws[Priority]) != MaskedPPriority) {
		PQUEUE (PriMasked (ws[Priority]), ws);
	} else {
		QUEUE (ws);
	}
	#else
	QUEUE (ws);
	#endif
	return;
}
/*}}}*/

/* entry-points */

/*{{{  void kernel_X_zero_div (void)*/
/*
 *	void kernel_X_zero_div (void)
 *	entry point for integer division-by-zero
 */
void kernel_X_zero_div (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_FOUR_IN (X_zero_div, zerodiv_info2, zerodiv_info, procedure_addr, filename_addr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_zero_div);
	LOADWPTR;
	LOADRETURN;
	FOURPARAMS(zerodiv_info2, zerodiv_info, procedure_addr, filename_addr);
	ENTRY_TRACE (X_zero_div, "%x, %x, %p, %p", zerodiv_info2, zerodiv_info, (void *)procedure_addr, (void *)filename_addr);
#endif	/* !TARGET_CPU_SPARC */

	zerodiv_happened();

#if defined (DYNAMIC_PROCS) && !defined(OOS_BUILD)
	/* check for dynamic proc */
	if (faulting_dynproc ((word **)&Wptr, (word **)&return_address, "zero_div", &kr_dptr)) {
		MESSAGE ("KRoC: Dynamic process generated a fault, killed it.\n");
	} else
#endif
	{
		if (_occam_errormode) {
			/* reschedule next process.. */
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#ifdef PROCESS_PRIORITY
	if (PriMasked (kr_dptr->holding_priority) < MaskedPPriority) {
		/* resuming higher priority process -- switch queues */
		SAVE_PRIORITY_QUEUE (MaskedPPriority);
		PPriority = kr_dptr->holding_priority;
		LOAD_PRIORITY_QUEUE (MaskedPPriority);
	} else if (PriMasked (kr_dptr->holding_priority) > MaskedPPriority) {
		/* resuming lower priority process */
		sf.u.s.priority_sync = 1;
	}
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_overflow (void)*/
/*
 *	void kernel_X_overflow (void)
 *	arithmetic overflow entry point
 */
void kernel_X_overflow (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_FOUR_IN (X_overflow, overflow_info2, overflow_info, procedure_addr, filename_addr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_overflow);
	LOADWPTR;
	LOADRETURN;
	FOURPARAMS(overflow_info2, overflow_info, procedure_addr, filename_addr);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_overflow, "%x, %x, %p, %p", overflow_info2, overflow_info, (void *)procedure_addr, (void *)filename_addr);
	overflow_happened();		/* Parameters dealt with (they're visible throughout) */

#if defined(DYNAMIC_PROCS) && !defined(OOS_BUILD)
	/* check for dynamic proc */
	if (faulting_dynproc ((word **)&Wptr, (word **)&return_address, "overflow", &kr_dptr)) {
		MESSAGE ("KRoC: Dynamic process generated a fault, killed it.\n");
	} else
#endif
	{
		if (_occam_errormode) {
			/* reschedule next process.. */
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#ifdef PROCESS_PRIORITY
	if (PriMasked (kr_dptr->holding_priority) < MaskedPPriority) {
		/* resuming higher priority process -- switch queues */
		SAVE_PRIORITY_QUEUE (MaskedPPriority);
		PPriority = kr_dptr->holding_priority;
		LOAD_PRIORITY_QUEUE (MaskedPPriority);
	} else if (PriMasked (kr_dptr->holding_priority) > MaskedPPriority) {
		/* resuming lower priority process */
		sf.u.s.priority_sync = 1;
	}
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_floaterr (void)*/
/*
 *	void kernel_X_floaterr (void)
 *	floating-point error entry point
 */
void kernel_X_floaterr (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_FIVE_IN (X_floaterr, floaterr_info2, floaterr_info, procedure_addr, filename_addr, floaterr_fpustatus);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_floaterr);
	LOADWPTR;
	LOADRETURN;
	FIVEPARAMS(floaterr_info2, floaterr_info, procedure_addr, filename_addr, floaterr_fpustatus);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_floaterr, "%x, %x, %p, %p, %x", floaterr_info2, floaterr_info, (void *)procedure_addr, (void *)filename_addr, floaterr_fpustatus);

	floaterr_happened ();

#if defined(DYNAMIC_PROCS) && !defined(OOS_BUILD)
	/* check for dynamic proc */
	if (faulting_dynproc ((word **)&Wptr, (word **)&return_address, "floaterr", &kr_dptr)) {
		MESSAGE ("KRoC: Dynamic process generated a fault, killed it.\n");
	} else
#endif
	{
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#ifdef PROCESS_PRIORITY
	if (PriMasked (kr_dptr->holding_priority) < MaskedPPriority) {
		/* resuming higher priority process -- switch queues */
		SAVE_PRIORITY_QUEUE (MaskedPPriority);
		PPriority = kr_dptr->holding_priority;
		LOAD_PRIORITY_QUEUE (MaskedPPriority);
	} else if (PriMasked (kr_dptr->holding_priority) > MaskedPPriority) {
		/* resuming lower priority process */
		sf.u.s.priority_sync = 1;
	}
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_Seterr (void)*/
/*
 *	void kernel_X_Seterr (void)
 *	SETERR entry-point
 */
void kernel_X_Seterr (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_FOUR_IN (X_Seterr, procedure_addr, filename_addr, seterr_info2, seterr_info1);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_Seterr);
	LOADWPTR;
	LOADRETURN;
	FOURPARAMS (procedure_addr, filename_addr, seterr_info2, seterr_info1);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_Seterr, "%p, %p, %x, %x", (void *)procedure_addr, (void *)filename_addr, seterr_info2, seterr_info1);
	handle_seterr ();

#if defined(DYNAMIC_PROCS) && !defined(OOS_BUILD)
	/* check for dynamic proc */
	if (faulting_dynproc ((word **)&Wptr, (word **)&return_address, "Seterr", &kr_dptr)) {
		MESSAGE ("KRoC: Dynamic process generated a fault, killed it.\n");
	} else
#endif
	{
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#ifdef PROCESS_PRIORITY
	if (PriMasked (kr_dptr->holding_priority) < MaskedPPriority) {
		/* resuming higher priority process -- switch queues */
		SAVE_PRIORITY_QUEUE (MaskedPPriority);
		PPriority = kr_dptr->holding_priority;
		LOAD_PRIORITY_QUEUE (MaskedPPriority);
	} else if (PriMasked (kr_dptr->holding_priority) > MaskedPPriority) {
		/* resuming lower priority process */
		sf.u.s.priority_sync = 1;
	}
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_BSeterr (void)*/
/*
 *	void kernel_X_BSeterr (void)
 *	basic SETERR entry-point
 */
void kernel_X_BSeterr (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ZERO_IN (X_BSeterr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_BSeterr);
	LOADWPTR;
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_BSeterr);

#if defined(DYNAMIC_PROCS) && !defined(OOS_BUILD)
	/* oki, if this is a dynamic proc, we're safe.. */
	if (faulting_dynproc ((word **)&Wptr, (word **)&return_address, "BSeterr", &kr_dptr)) {
		MESSAGE ("KRoC: Dynamic process generated a fault, killed it.\n");
	} else
#endif
	{
		MESSAGE ("KRoC: Application level error at 0x%x, Wptr = 0x%x.\n", return_address, (unsigned int)Wptr);
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#ifdef PROCESS_PRIORITY
	if (PriMasked (kr_dptr->holding_priority) < MaskedPPriority) {
		/* resuming higher priority process -- switch queues */
		SAVE_PRIORITY_QUEUE (MaskedPPriority);
		PPriority = kr_dptr->holding_priority;
		LOAD_PRIORITY_QUEUE (MaskedPPriority);
	} else if (PriMasked (kr_dptr->holding_priority) > MaskedPPriority) {
		/* resuming lower priority process */
		sf.u.s.priority_sync = 1;
	}
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_BNSeterr (void)*/
/*
 *	void kernel_X_BNSeterr (void)
 *	basic SETERR entry-point, but no return address expected
 */
void kernel_X_BNSeterr (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ZERO_IN (X_BNSeterr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_BNSeterr);
	LOADWPTR;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_BNSeterr);

#if defined(DYNAMIC_PROCS) && !defined(OOS_BUILD)
	/* check for faulting dynamic proc */
	if (faulting_dynproc ((word **)&Wptr, (word **)&return_address, "BNSeterr", &kr_dptr)) {
		MESSAGE ("KRoC: Dynamic process generated a fault, killed it.\n");
	} else
#endif
	{
		MESSAGE ("KRoC: Application level error, Wptr = 0x%x.\n", (unsigned int)Wptr);
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, 0);
	}
#ifdef PROCESS_PRIORITY
	if (PriMasked (kr_dptr->holding_priority) < MaskedPPriority) {
		/* resuming higher priority process -- switch queues */
		SAVE_PRIORITY_QUEUE (MaskedPPriority);
		PPriority = kr_dptr->holding_priority;
		LOAD_PRIORITY_QUEUE (MaskedPPriority);
	} else if (PriMasked (kr_dptr->holding_priority) > MaskedPPriority) {
		/* resuming lower priority process */
		sf.u.s.priority_sync = 1;
	}
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_RangeCheckError (void)*/
/*
 *	void kernel_X_RangeCheckError (void)
 *	Range error entry-point
 */
void kernel_X_RangeCheckError (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_FOUR_IN (X_RangeCheckError, procedure_addr, filename_addr, range_info2, range_info1);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_RangeCheckError);
	LOADWPTR;
	LOADRETURN;
	FOURPARAMS (procedure_addr, filename_addr, range_info2, range_info1);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_RangeCheckError, "%p, %p, %x, %x", (void *)procedure_addr, (void *)filename_addr, range_info2, range_info1);

	handle_range_error ();
#if defined(DYNAMIC_PROCS) && !defined(OOS_BUILD)
	/* check for faulting dynproc */
	if (faulting_dynproc ((word **)&Wptr, (word **)&return_address, "RangeCheckError", &kr_dptr)) {
		MESSAGE ("KRoC: dynamic process generated a fault, killed it.\n");
	} else
#endif
	{
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#ifdef PROCESS_PRIORITY
	if (PriMasked (kr_dptr->holding_priority) < MaskedPPriority) {
		/* resuming higher priority process -- switch queues */
		SAVE_PRIORITY_QUEUE (MaskedPPriority);
		PPriority = kr_dptr->holding_priority;
		LOAD_PRIORITY_QUEUE (MaskedPPriority);
	} else if (PriMasked (kr_dptr->holding_priority) > MaskedPPriority) {
		/* resuming lower priority process */
		sf.u.s.priority_sync = 1;
	}
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_BasicRangeError (void)*/
/*
 *	void kernel_X_BasicRangeError (void)
 *	basic range error entry point
 */
void kernel_X_BasicRangeError (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ZERO_IN (X_BasicRangeError);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_BasicRangeError);
	LOADWPTR;
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_BasicRangeError);
	MESSAGE ("KRoC: Range error.\n");

#if defined(DYNAMIC_PROCS) && !defined(OOS_BUILD)
	/* check for faulting dynproc */
	if (faulting_dynproc ((word **)&Wptr, (word **)&return_address, "BasicRangeError", &kr_dptr)) {
		MESSAGE ("KRoC: dynamic process generated a fault, killed it.\n");
	} else
#endif
	{
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#ifdef PROCESS_PRIORITY
	if (PriMasked (kr_dptr->holding_priority) < MaskedPPriority) {
		/* resuming higher priority process -- switch queues */
		SAVE_PRIORITY_QUEUE (MaskedPPriority);
		PPriority = kr_dptr->holding_priority;
		LOAD_PRIORITY_QUEUE (MaskedPPriority);
	} else if (PriMasked (kr_dptr->holding_priority) > MaskedPPriority) {
		/* resuming lower priority process */
		sf.u.s.priority_sync = 1;
	}
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void dump_trap_info (word a_val, word b_val, word c_val)*/
/* dump_trap_info for dumping on TRAP*/
void dump_trap_info (word a_val, word b_val, word c_val)
{
	int i;

	MESSAGE ("** KRoC: TRAP **\n");
	MESSAGE ("\tWptr  0x%8.8x    raddr 0x%8.8x\n", (unsigned int)Wptr, (unsigned int)return_address);
	MESSAGE ("\tFptr  0x%8.8x    Bptr  0x%8.8x\n", (unsigned int)Fptr, (unsigned int)Bptr);
	MESSAGE ("\tAreg  0x%8.8x    Iptr  0x%8.8x\n", (unsigned int)a_val, (unsigned int)Wptr[Iptr]);
	MESSAGE ("\tBreg  0x%8.8x    Creg  0x%8.8x\n", (unsigned int)b_val, (unsigned int)c_val);
	for (i=6; i >= -5; i-=2) {
		MESSAGE ("\tWptr[%-2d] @ (0x%8.8x) = 0x%8.8x", i, (unsigned int)&(Wptr[i]), (unsigned int)Wptr[i]);
		MESSAGE ("\tWptr[%-2d] @ (0x%8.8x) = 0x%8.8x\n", i-1, (unsigned int)&(Wptr[i-1]), (unsigned int)Wptr[i-1]);
	}
	show_last_debug_insert ();
	return;
}
/*}}}*/

#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
	/*{{{  void kernel_X_b_dispatch (void)*/
	/*
	 *	void kernel_X_b_dispatch (void)
	 *	dispatches a blocking call
	 */
	void kernel_X_b_dispatch (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN (X_b_dispatch, b_func, b_param);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL (X_b_dispatch);
		LOADWPTR;
		LOADRETURN;
		TWOPARAMS(b_func, b_param);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (X_b_dispatch, "%p, %p", (void *)b_func, (void *)b_param);
		/* adjust workspace for return */
		#ifdef BLOCKING_DEBUG
			MESSAGE ("X_b_dispatch: entry: return_address = %p, b_param = %p, b_func = %p, WPtr = %p\n",
				(void *)return_address, (void *)b_param, (void *)b_func, (void *)Wptr);
		#endif
		/* (char *)Wptr = (char *)Wptr + 16; */
		#ifdef BLOCKING_DEBUG
		{
			int dummy, i;
			(void)&dummy;
			MESSAGE ("X_b_dispatch: return_address = %p, b_param = %p, b_func = %p, Wptr = %p\n",
				(void *)return_address, (void *)b_param, (void *)b_func, (void *)Wptr);
			for (i=6; i >= -5; i-=2) {
				MESSAGE ("\tWptr[%-2d] @ (0x%8.8x) = 0x%8.8x", i, (unsigned int)&(Wptr[i]), (unsigned int)Wptr[i]);
				MESSAGE ("\tWptr[%-2d] @ (0x%8.8x) = 0x%8.8x\n", i-1, (unsigned int)&(Wptr[i-1]), (unsigned int)Wptr[i-1]);
			}
		}
		#endif
		#ifdef PROCESS_PRIORITY
		bsyscalls_dispatch ((word *)Wptr, (char *)return_address, PPriority, (word *)b_param, (void (*)(word *))b_func, 0);
		#else
		bsyscalls_dispatch ((word *)Wptr, (char *)return_address, (word *)b_param, (void (*)(word *))b_func, 0);
		#endif
		K_JUMP(X_scheduler);
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_X_bx_dispatch (void)*/
	/*
	 *	void kernel_X_bx_dispatch (void)
	 *	dispatches a terminateable blocking call
	 */
	void kernel_X_bx_dispatch (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN (X_bx_dispatch, b_func, b_param);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL(X_bx_dispatch);
		LOADWPTR;
		LOADRETURN;
		/* (char *)Wptr = (char *)Wptr + 16; */
		TWOPARAMS(b_func, b_param);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (X_bx_dispatch, "%p, %p", (void *)b_func, (void *)b_param);
		#ifdef BLOCKING_DEBUG
		{
			int dummy;
			(void)&dummy;
			MESSAGE ("X_bx_dispatch: return_address = %p, Wptr[Iptr] = %p, b_param = %p, b_func = %p, Wptr = %p\n",
				(void *)return_address, (void *)(Wptr[Iptr]), (void *)b_param, (void *)b_func, (void *)Wptr);
		}
		#endif
		#ifdef PROCESS_PRIORITY
		bsyscalls_dispatch ((word *)Wptr, (char *)return_address, PPriority, (word *)b_param, (void (*)(word *))b_func, 4);
		#else
		bsyscalls_dispatch ((word *)Wptr, (char *)return_address, (word *)b_param, (void (*)(word *))b_func, 4);
		#endif
		K_JUMP(X_scheduler);
		barrier ();
	}
/*}}}*/
#else	/* OOS_BUILD || !BLOCKING_SYSCALLS */
	/*{{{  void kernel_X_no_bsyscalls (void)*/
	/*
	 *	void kernel_X_no_bsyscalls (void)
	 *	no blocking-system calls functionality entry-point
	 */
	void kernel_X_no_bsyscalls (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ZERO_IN (X_no_bsyscalls);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL(X_no_bsyscalls);
		LOADWPTR;
		LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE0 (X_no_bsyscalls);
		err_no_bsyscalls (Wptr, return_address);
		barrier ();
	}
	/*}}}*/
#endif	/* OOS_BUILD || !BLOCKING_SYSCALLS */


#if !defined(OOS_BUILD) && defined(DYNAMIC_PROCS)
	extern void _X_dynproc_exit (void);
	/*{{{  void kernel_X_kernel_run (void)*/
	/*
	 *	void kernel_X_kernel_run (void)
	 *	dynamic kernel run entry point (and resume point)
	 */
	void kernel_X_kernel_run (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ONE_IN (X_kernel_run, kr_param);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL (X_kernel_run);
		LOADWPTR;
		LOADRETURN;
		PARAM (kr_param);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (X_kernel_run, "%p", (void *)kr_param);
		kr_dptr = dynproc_startprocess ((int *)kr_param, (void *)_X_dynproc_exit);
		kr_dptr->holding_wptr = (int)Wptr;
		kr_dptr->holding_raddr = return_address;
		#ifdef PROCESS_PRIORITY
		kr_dptr->holding_priority = PPriority;
		#endif

		if (kr_dptr->suspended) {
			return_address = (int)kr_dptr->suspended->return_addr;
			Wptr = (word *)kr_dptr->suspended->wptr;
			#ifdef PROCESS_PRIORITY
			SAVE_PRIORITY_QUEUE (MaskedPPriority);
			PPriority = kr_dptr->suspended->priority;
			LOAD_PRIORITY_QUEUE (MaskedPPriority);
			PState |= (1 << MaskedPPriority);
			if (bsf (PState) < MaskedPPriority) {
				sf.u.s.priority_sync = 1;
			}
			#endif
			*(kr_dptr->suspended->result) = DPROCESS_RESUMED;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
			RESTORE;
			EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
		}
		#ifdef DEBUG_DYNPROC
			MESSAGE ("X_kernel_run: running process [%p] at %p (Fptr = %p, Bptr = %p), &Fptr = %p, func = %p\n", kr_dptr, kr_dptr->ws_ptr, Fptr, Bptr, &Fptr, kr_dptr->entrypoint);
			MESSAGE ("X_kernel_run: ->holding_wptr = 0x%8.8x,  ->holding_raddr = 0x%8.8x\n", kr_dptr->holding_wptr, kr_dptr->holding_raddr);
		#endif
		Wptr = kr_dptr->ws_ptr;
		return_address = (word)kr_dptr->entrypoint;
		KERNEL_RUN_CODE (Wptr, return_address);

		#ifdef DEBUG_DYNPROC
			MESSAGE ("X_kernel_run: should not get here!\n");
		#endif
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_X_dynproc_suspend (void)*/
	/*
	 *	void kernel_X_dynproc_suspend (void)
	 *	entered when a dynamic process is suspending
	 */
	void kernel_X_dynproc_suspend (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ONE_IN (X_dynproc_suspend, ds_param);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL (X_dynproc_suspend);
		LOADWPTR;
		LOADRETURN;
		PARAM (ds_param);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (X_dynproc_suspend, "%p", (void*)ds_param);
		/* ds_param should point at the argument-set (VAL DPROCESS p, INT result) */
#ifdef PROCESS_PRIORITY
		temp1 = (word)dynproc_suspendprocess ((d_process *)(((word *)ds_param)[0]), (int *)(((word *)ds_param)[1]), Wptr, (char *)return_address, PPriority);
#else
		temp1 = (word)dynproc_suspendprocess ((d_process *)(((word *)ds_param)[0]), (int *)(((word *)ds_param)[1]), Wptr, (char *)return_address);
#endif
		if (temp1) {
			/* failed */
#if 0
fprintf (stderr, "scheduler (X_dynproc_suspend): dynproc_suspendprocess returned %d\n", (int)temp1);
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
			RESTORE;
			EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
		}
		K_JUMP (X_scheduler);
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_X_dynproc_exit (void)*/
	/*
	 *	void kernel_X_dynproc_exit (void)
	 *	entered when dynamic process finishes
	 */
	void kernel_X_dynproc_exit (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ZERO_IN (X_dynproc_exit);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL (X_dynproc_exit);
		LOADWPTR;
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE0 (X_dynproc_exit);
		kr_wptr = (word *)((int)Wptr - 16);		/* adjust Wptr */
		#ifdef DEBUG_DYNPROC
			MESSAGE ("in _X_dynproc_exit: kr_wptr = %p\n", kr_wptr);
		#endif
		kr_dptr = dynproc_endprocess ((int *)kr_wptr);
		*(kr_dptr->result) = DPROCESS_FINISHED;
		Wptr = (word *)kr_dptr->holding_wptr;
		return_address = kr_dptr->holding_raddr;
		#ifdef PROCESS_PRIORITY
		SAVE_PRIORITY_QUEUE (MaskedPPriority);
		PPriority = kr_dptr->holding_priority;
		LOAD_PRIORITY_QUEUE (MaskedPPriority);
		PState |= (1 << MaskedPPriority);
		if (bsf(PState) < MaskedPPriority) {
			sf.u.s.priority_sync = 1;
		}
		#endif
		#ifdef DEBUG_DYNPROC
			MESSAGE ("_X_dynproc_exit: returning to occam\n");
			MESSAGE ("_X_dynproc_exit: ->holding_wptr = 0x%8.8x,  ->holding_raddr = 0x%8.8x\n", kr_dptr->holding_wptr, kr_dptr->holding_raddr);
		#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
	/*}}}*/
#else	/* defined(OOS_BUILD) || !defined(DYNAMIC_PROCS) */
	/*{{{  void kernel_no_dynprocs (void)*/
	/*
	 *	void kernel_no_dynprocs (void)
	 *	no dynamic process support entry point
	 */
	void kernel_no_dynprocs (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ONE_IN (X_no_dynprocs, kr_param);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL (X_no_dynprocs);
		LOADWPTR;
		LOADRETURN;
		PARAM (kr_param);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (X_no_dynprocs, "%p", kr_param);
		no_dynamic_process_support ();
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
	/*}}}*/
#endif	/* defined(OOS_BUILD) || !defined(DYNAMIC_PROCS) */

/*{{{  void kernel_X_mnew (void)*/
/*
 *	void kernel_X_mnew (void)
 *	allocates memory from a given pool
 */
void kernel_X_mnew (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_mnew, dmem_index);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_mnew);
	LOADWPTR;
	LOADRETURN;
	PARAM(dmem_index);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_mnew, "%d", dmem_index);
	/* mangled to call dmem_alloc with the pool size for that index (better, really.) */
	dmem_ptr = (word *)dmem_alloc (dmem_slot_to_size (dmem_index));
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (dmem_ptr);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL ((word)dmem_ptr);
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_mfree (void)*/
/*
 *	void kernel_X_mfree (void)
 *	frees memory to a given pool
 */
void kernel_X_mfree (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_mfree, dmem_ptr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_mfree);
	LOADWPTR;
	LOADRETURN;
	PARAM (dmem_ptr);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_mfree, "%p", dmem_ptr);
	dmem_release ((void *)dmem_ptr);
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_malloc (void)*/
/*
 *	void kernel_X_malloc (void)
 *	allocates memory of a given size
 */
void kernel_X_malloc (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_malloc, dmem_size);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_malloc);
	LOADWPTR;
	LOADRETURN;
	PARAM (dmem_size);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_malloc, "%d", dmem_size);

#if 0
	show_last_debug_insert ();
#endif
	if (dmem_size) {
		dmem_ptr = (void *)dmem_alloc (dmem_size);
	} else {
		dmem_ptr = NULL;
	}
	ENTRY_TRACE (X_malloc_out, "%p", dmem_ptr);
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (dmem_ptr);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL (dmem_ptr);
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_mrelease (void)*/
/*
 *	void kernel_X_mrelease (void)
 *	frees memory allocated from _X_malloc()
 */
void kernel_X_mrelease (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_mrelease, dmem_ptr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_mrelease);
	LOADWPTR;
	LOADRETURN;
	PARAM (dmem_ptr);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_mrelease, "%p", dmem_ptr);
	dmem_release ((void *)dmem_ptr);
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_mreleasep (void)*/
/*
 *	void kernel_X_mreleasep (void)
 *	frees a process whos workspace was allocated by _X_malloc(), first adjusting by the parameter
 */
void kernel_X_mreleasep (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_mreleasep, dmem_size);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_mreleasep);
	LOADWPTR;
	LOADRETURN;
	PARAM (dmem_size);		/* actually workspace adjust (in words) */
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_mreleasep, "%d", dmem_size);

	dmem_ptr = (word *)(((char *)Wptr) + ((int)dmem_size * sizeof(word)));
	dmem_release ((void *)dmem_ptr);
	K_JUMP (X_scheduler);
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_mtnew (void)*/
/*
 *	allocates a new mobile type and initialises it
 */
void kernel_X_mtnew (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_mtnew, dmem_size);
#else
	K_SETGLABEL (X_mtnew);
	LOADWPTR;
	LOADRETURN;
	PARAM (dmem_size);		/* actually a pointer to the type description */
#endif
	ENTRY_TRACE (X_mtnew, "%p", (unsigned int *)dmem_size);

	dmem_ptr = dmem_mtnew ((unsigned int *)dmem_size);

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (dmem_ptr);
#else
	RETURNVAL (dmem_ptr);
	RESTORE;
	EJUMP (return_address);
#endif
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_mtfree (void)*/
/*
 *	frees a mobile type
 */
void kernel_X_mtfree (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_mtfree, dmem_size, dmem_ptr);
#else
	K_SETGLABEL (X_mtfree);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS (dmem_size, dmem_ptr);
#endif
	ENTRY_TRACE (X_mtfree, "%p, %p", (unsigned int *)dmem_size, dmem_ptr);

	dmem_mtfree ((unsigned int *)dmem_size, dmem_ptr);

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else
	RESTORE;
	EJUMP (return_address);
#endif
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_mtclone (void)*/
/*
 *	clones a mobile type
 */
void kernel_X_mtclone (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_mtclone, dmem_size, dmem_ptr);
#else
	K_SETGLABEL (X_mtclone);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS (dmem_size, dmem_ptr);
#endif
	ENTRY_TRACE (X_mtfree, "%p, %p", (unsigned int *)dmem_size, dmem_ptr);

	dmem_ptr = dmem_mtclone ((unsigned int *)dmem_size, dmem_ptr);

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (dmem_ptr);
#else
	RETURNVAL (dmem_ptr);
	RESTORE;
	EJUMP (return_address);
#endif
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_trap (void)*/
/*
 *	void kernel_X_trap (void)
 *	trap entry-point
 */
void kernel_X_trap (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (X_trap, trapval_A, trapval_B, trapval_C);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_trap);
	LOADWPTR;
	LOADRETURN;
	THREEPARAMS(trapval_A,trapval_B,trapval_C);
#endif	/* !TARGET_CPU_SPARC */

	ENTRY_TRACE (X_trap, "0x%x, 0x%x, 0x%x", trapval_A, trapval_B, trapval_C);
	dump_trap_info (trapval_A, trapval_B, trapval_C);

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_THREE_OUT (trapval_A, trapval_B, trapval_C);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(trapval_C);
	RETURNVAL(trapval_B);
	RETURNVAL(trapval_A);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
#if defined(DM_DEBUG) && (DM_DEBUG == 1)
/*{{{  void hop_verify_ord_mem (void)*/
extern void verify_ord_mem (void *, int);

void hop_verify_ord_mem (void)
{
	verify_ord_mem ((void *)trapval_A, (int)trapval_B);
}
/*}}}*/
/*{{{  void kernel_X_memchk (void)*/
void kernel_X_memchk (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_memchk, trapval_B, trapval_A);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_memchk);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS(trapval_B, trapval_A);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_memchk, "0x%x (%d)", trapval_A, trapval_B);
	hop_verify_ord_mem ();
	barrier ();
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
#endif
/*{{{  void kernel_X_savel (void)*/
/*
 *	void kernel_X_savel (void)
 *	retreive queue pointers
 */
void kernel_X_savel (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_savel, temp_ptr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_savel);
	LOADWPTR;
	LOADRETURN;
	PARAM(temp_ptr);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_savel, "%p", temp_ptr);
	/*
	 * so that MINT, DIFF and CJ work properly
	 */
	temp_ptr[1] = (word)Bptr;
	temp_ptr[0] = (word)Fptr;
	DBGMSG( "savel: temp_ptr[0] (Fptr) = 0x%lx, temp_ptr[1] (Bptr) = 0x%lx\n", temp_ptr[0], temp_ptr[1] );
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_stlf (void)*/
/*
 *	void kernel_X_stlf (void)
 *	store Fptr for low-pri queue
 */
void kernel_X_stlf (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_stlf, temp_ptr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_stlf);
	LOADWPTR;
	LOADRETURN;
	PARAM(temp_ptr);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_stlf, "%p", temp_ptr);
	/*
	 * See above.
	 */
	if( (word)temp_ptr == (word)0x80000000 ) {
		temp_ptr = 0;
	}
	Fptr = temp_ptr;
	DBGMSG( "stlf: Fptr set to 0x%lx\n", Fptr );
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_stlb (void)*/
/*
 *	void kernel_X_stlb (void)
 *	stoare Bptr for low-pri queue
 */
void kernel_X_stlb (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_stlb, temp_ptr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_stlb);
	LOADWPTR;
	LOADRETURN;
	PARAM(temp_ptr);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_stlb, "%p", temp_ptr);
	Bptr = temp_ptr;
	DBGMSG ("stlb: Bptr set to 0x%lx\n", temp_ptr);
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_norm (void)*/
/*
 *	void kernel_X_norm (void)
 *	normalises 64-bit double-length integer (Breg:Areg)
 */
void kernel_X_norm (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_norm, trapval_A, trapval_B);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_norm);
	LOADWPTR;
	LOADRETURN;
	/* use trapval_[ABC] since we're dealing with unsigned stuff */
	/* this could be made efficient in assembler, but keep in C for some portability.. */
	TWOPARAMS(trapval_A,trapval_B);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_norm, "0x%x, 0x%x", trapval_A, trapval_B);
	trapval_C = 0;
	if (!trapval_A && !trapval_B) {
		trapval_C = 64;
	} else {
		while (!(trapval_B & 0x80000000)) {
			trapval_B <<= 1;
			if (trapval_A & 0x80000000) {
				trapval_B |= 1;
			}
			trapval_A <<= 1;
			trapval_C++;
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_THREE_OUT (trapval_A, trapval_B, trapval_C);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(trapval_C);
	RETURNVAL(trapval_B);
	RETURNVAL(trapval_A);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_fmul (void)*/
/*
 *	void kernel_X_fmul (void)
 *	FMUL implementation (easier in C..)
 */
void kernel_X_fmul (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_fmul, tmpint_a, tmpint_b);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_fmul);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS(tmpint_a, tmpint_b);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_fmul, "%d, %d", tmpint_a, tmpint_b);
	/* do calculation */
	{
		long long tmp_long;
		int hi_word, lo_word;

		tmp_long = (long long)tmpint_a * (long long)tmpint_b;
		hi_word = (int)((tmp_long >> 32) & 0xffffffff);
		lo_word = (int)(tmp_long & 0xffffffff);
		hi_word  = (int)((unsigned int)hi_word << 1);
		if ((unsigned int)lo_word & 0x80000000) {
			hi_word |= 1;
		}
		lo_word = (int)((unsigned int)lo_word << 1);
		if (lo_word >= 0) {
			tmpint_c = hi_word;
		} else if (lo_word != 0x80000000) {
			tmpint_c = hi_word + 1;
		} else if (hi_word & 1) {
			tmpint_c = hi_word + 1;
		} else {
			tmpint_c = hi_word;
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (tmpint_c);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(tmpint_c);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/

#if defined(ENABLE_FASTCALLS) && defined(PROCESS_PRIORITY)
/*{{{  void kernel_Y_savepri (void)*/
void kernel_Y_savepri (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (Y_savepri, guard, temp_ptr);
#else
	K_SETGLABEL_TWO_IN (Y_savepri, guard, temp_ptr);
	LOADRETURN;
#endif

	ENTRY_TRACE (Y_savepri, "%d, %p", guard, temp_ptr);
	guard &= 0x1f;		/* 32 priority levels */
	if (guard == MaskedPPriority) {
		temp_ptr[1] = (word)Bptr;
		temp_ptr[0] = (word)Fptr;
	} else {
		temp_ptr[1] = (word)Bptr_q[guard];
		temp_ptr[0] = (word)Fptr_q[guard];
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_stprif (void)*/
void kernel_Y_stprif (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (Y_stprif, guard, temp_ptr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (Y_stprif, guard, temp_ptr);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */

	ENTRY_TRACE (Y_stprif, "%d, %p", guard, temp_ptr);

	/* fixup for broken code */
	if ((word)temp_ptr == (word)0x80000000) {
		temp_ptr = 0;
	}
	guard &= 0x1f;		/* 32 priority levels */
	if (guard == MaskedPPriority) {
		Fptr = temp_ptr;
	} else {
		Fptr_q[guard] = temp_ptr;
		if ((Fptr_q[guard] != NotProcess_p) && (guard < MaskedPPriority)) {
			/* adjusting queue at higher priority, set flag */
			sf.u.s.priority_sync = 1;
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_stprib (void)*/
void kernel_Y_stprib (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (Y_stprib, guard, temp_ptr);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (Y_stprib, guard, temp_ptr);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */

	ENTRY_TRACE (Y_stprib, "%d, %p", guard, temp_ptr);

	/* fixup for broken code */
	if ((word)temp_ptr == (word)0x80000000) {
		temp_ptr = 0;
	}
	guard &= 0x1f;		/* 32 priority levels */
	if (guard == MaskedPPriority) {
		Bptr = temp_ptr;
	} else {
		Bptr_q[guard] = temp_ptr;
		if ((Bptr_q[guard] != NotProcess_p) && (guard < MaskedPPriority)) {
			/* adjusting queue at higher priority, set flag */
			sf.u.s.priority_sync = 1;
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
#endif

#ifndef BLOCKING_SYSCALLS
#ifndef TARGET_CPU_SPARC
/*{{{  void kernel_kbd_process (void)*/
/*
 *	void kernel_kbd_process (void)
 *	the keyboard process
 */
void kernel_kbd_process (void)
{
	K_SETGLABEL (kbd_process);
	DBGMSG("kbd_process: started.  Calling read_the_kbd.\n");
	temp1 = read_the_kbd();
	Wptr = kbd_workspace;
	DBGMSG("kbd_process: received keypress as 0x%x. Calling OutByte.\n", temp1);
	PUSH(&kbd_chan);
	PUSH(temp1);
	RESTORE; /* get Wptr into ebp */
	CALL_X_OUTBYTE_CODE;
	/* ((FUNCPTR)(occam_table[Table_OutByte]))(); */
	DBGMSG("kbd_process: returned from OutByte, acknowledging keypress.\n");
	acknowledge();
	DBGMSG("kbd_process: calling scheduler.\n");
	K_JUMP(X_scheduler);
	barrier ();
}
/*}}}*/
#endif	/* !TARGET_CPU_SPARC -- only do this on intel, sparc must use bsyscalls */
#endif	/* !BLOCKING_SYSCALLS */

#ifdef ENABLE_FASTCALLS
	/*{{{  void kernel_Y_outbyte (void)*/
	/*
	 *	void kernel_Y_outbyte (void)
	 *	output (new interface)
	 */
	void kernel_Y_outbyte (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_outbyte, temp_ptr, channel_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_outbyte, temp_ptr, channel_address);
#endif	/* !TARGET_CPU_SPARC */
		Wptr[0] = (word)temp_ptr;
		#ifdef TARGET_BIGENDIAN
		source_address = ((byte *)Wptr + 3);
		#else	/* !TARGET_BIGENDIAN */
		source_address = (byte *)Wptr;
		#endif	/* !TARGET_BIGENDIAN */
		count = 1;

		ENTRY_TRACE (Y_outbyte, "%d, %p, %p (ready = %s)", count, channel_address, source_address, ((*channel_address == NotProcess_p) ? "no" : "yes"));
		temp_ptr = *channel_address;
		if (temp_ptr == NotProcess_p) {
			*channel_address = Wptr;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			if (temp_ptr[State] <= Ready_p) {
				*channel_address = Wptr;
				if (temp_ptr[State] == Waiting_p) {
					#ifdef PROCESS_PRIORITY
						if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
							sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
							PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						} else {
							QUEUE (temp_ptr);
						}
					#else
						QUEUE (temp_ptr);
					#endif	/* !PROCESS_PRIORITY */
				}
				temp_ptr[State] = Ready_p;
				Wptr[Pointer] = (word)source_address;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			} else {
				*channel_address = NotProcess_p;
				destination_address = (byte *)(temp_ptr[Pointer]);
				*(byte *)destination_address = *(byte *)source_address;
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
						SCHED_POLICY (Wptr, temp_ptr);
					} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
						/* we sleep and the other wakes up (go via scheduler for actual change) */
						sf.u.s.priority_sync = 1;
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						Wptr[Priority] = PPriority;
						QUEUE (Wptr);
						K_JUMP (X_scheduler);
					} else {
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					}
				#else	/* !PROCESS_PRIORITY */
					SCHED_POLICY (Wptr, temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
				K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
				RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
			}
		}
		barrier ();
	}
	/*}}}*/
#endif	/* ENABLE_FASTCALLS */

/*{{{  void kernel_X_outbyte (void)*/
/*
 *	void kernel_X_outbyte (void)
 *	output a byte
 */
void kernel_X_outbyte (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_outbyte, temp_ptr, channel_address);
	Wptr[0] = (word)temp_ptr;
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_outbyte);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS(Wptr[0], channel_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_outbyte, "%x, %p (ready = %s)", Wptr[0], channel_address, ((*channel_address == NotProcess_p) ? "no" : "yes"));

	#ifdef TARGET_BIGENDIAN
	source_address = ((byte *)Wptr + 3);
	#else	/* !TARGET_BIGENDIAN */
	source_address = (byte *)Wptr;
	#endif	/* !TARGET_BIGENDIAN */
	count = 1;

	/* out (copy of)*/
	DBGMSG("outbyte: channel address = 0x%x\n" \
		"         count = %d\n" \
		"         source = 0x%x\n" \
		"         return_address = 0x%x\n", \
		channel_address, count, source_address, \
		return_address);

	temp_ptr = *channel_address;
	Wptr[Iptr] = return_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)source_address;
		Wptr[Iptr] = return_address; /* save return address in workspace. */
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP(X_scheduler);
	} else {
		DBGMSG("outbyte: other_process[State] = 0x%x\n", temp_ptr[State]);

		/* mask off priority bit */
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			/* debug*/
			DBGMSG( "outbyte: channel state is something ALTy.\n");

			if (temp_ptr[State] == Waiting_p) {
				DBGMSG ("outbyte: queuing ALTing process (%p)\n", temp_ptr);
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP(X_scheduler);
		} else {
			*channel_address = NotProcess_p; /* same as NULL */
			destination_address = (byte *)(temp_ptr[Pointer]);
			*(byte *)destination_address = *(byte *)source_address;
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		}
	}
	barrier ();
}
/*}}}*/

#ifdef ENABLE_FASTCALLS
	/*{{{  void kernel_Y_out32 (void)*/
	/*
	 *	void kernel_Y_out32 (void)
	 *	output 32 bits (new interface)
	 */
	void kernel_Y_out32 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_out32, channel_address, source_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_out32, channel_address, source_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_out32, "%p, %p", channel_address, source_address);

		temp_ptr = *channel_address;
		if (temp_ptr == NotProcess_p) {
			*channel_address = Wptr;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			if (temp_ptr[State] <= Ready_p) {
				*channel_address = Wptr;
				if (temp_ptr[State] == Waiting_p) {
					#ifdef PROCESS_PRIORITY
						if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
							sf.u.s.priority_sync |= (PriMasked (temp_ptr[Priority]) < MaskedPPriority);
							PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						} else {
							QUEUE (temp_ptr);
						}
					#else
						QUEUE (temp_ptr);
					#endif	/* !PROCESS_PRIORITY */
				}
				temp_ptr[State] = Ready_p;
				Wptr[Pointer] = (word)source_address;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			} else {
				*channel_address = NotProcess_p;
				destination_address = (byte *)(temp_ptr[Pointer]);
				*(word *)destination_address = *(word *)source_address;

				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
						SCHED_POLICY (Wptr, temp_ptr);
					} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
						/* we sleep and the other wakes up (go via scheduler for actual change) */
						sf.u.s.priority_sync = 1;
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						Wptr[Priority] = PPriority;
						QUEUE (Wptr);
						K_JUMP (X_scheduler);
					} else {
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					}
				#else	/* !PROCESS_PRIORITY */
					SCHED_POLICY (Wptr, temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
				K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
				RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
			}
		}
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_fastout32 (void)*/
	/*
	 *	void kernel_Y_fastout32 (void)
	 *	fast output 32 bits -- only when the channel is known non-empty
	 */
	void kernel_Y_fastout32 (void)
	{
		K_SETGLABEL_TWO_IN (Y_fastout32, channel_address, source_address);
		ENTRY_TRACE (Y_fastout32, "%p, %p", channel_address, source_address);
	
		temp_ptr = *channel_address;
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			*channel_address = NotProcess_p;
			destination_address = (byte *)(temp_ptr[Pointer]);
			*(word *)destination_address = *(word *)source_address;
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		}
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_out8 (void)*/
	/*
	 *	void kernel_Y_out8 (void)
	 *	output 8 bits (new interface)
	 */
	void kernel_Y_out8 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_out8, channel_address, source_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_out8, channel_address, source_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_out8, "%p, %p (ready = %s)", channel_address, source_address, ((*channel_address == NotProcess_p) ? "no" : "yes"));

		temp_ptr = *channel_address;
		if (temp_ptr == NotProcess_p) {
			*channel_address = Wptr;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			if (temp_ptr[State] <= Ready_p) {
				*channel_address = Wptr;
				if (temp_ptr[State] == Waiting_p) {
					#ifdef PROCESS_PRIORITY
						if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
							sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
							PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						} else {
							QUEUE (temp_ptr);
						}
					#else
						QUEUE (temp_ptr);
					#endif	/* !PROCESS_PRIORITY */
				}
				temp_ptr[State] = Ready_p;
				Wptr[Pointer] = (word)source_address;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			} else {
				*channel_address = NotProcess_p;
				destination_address = (byte *)(temp_ptr[Pointer]);
				*(byte *)destination_address = *(byte *)source_address;
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
						SCHED_POLICY (Wptr, temp_ptr);
					} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
						/* we sleep and the other wakes up (go via scheduler for actual change) */
						sf.u.s.priority_sync = 1;
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						Wptr[Priority] = PPriority;
						QUEUE (Wptr);
						K_JUMP (X_scheduler);
					} else {
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					}
				#else	/* !PROCESS_PRIORITY */
					SCHED_POLICY (Wptr, temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
				K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
				RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
			}
		}
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_fastout8 (void)*/
	/*
	 *	void kernel_Y_fastout8 (void)
	 *	fast output 8 bits
	 */
	void kernel_Y_fastout8 (void)
	{
		K_SETGLABEL_TWO_IN (Y_fastout8, channel_address, source_address);
		ENTRY_TRACE (Y_fastout8, "%p, %p", channel_address, source_address);
	
		temp_ptr = *channel_address;
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			*channel_address = NotProcess_p;
			destination_address = (byte *)(temp_ptr[Pointer]);
			*(byte *)destination_address = *(byte *)source_address;
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		}
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_outword (void)*/
	/*
	 *	void kernel_Y_outword (void)
	 *	output word (new interface)
	 */
	void kernel_Y_outword (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_outword, temp_ptr, channel_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_outword, temp_ptr, channel_address);
#endif	/* !TARGET_CPU_SPARC */
		Wptr[0] = (word)temp_ptr;
		source_address = (byte *)&(Wptr[0]);
		/* count = 4; */
		ENTRY_TRACE (Y_outword, "%p, %p, %p, %p (ready = %s)", Wptr, (void *)Wptr[Iptr], channel_address, source_address, ((*channel_address == NotProcess_p) ? "no" : "yes"));

		temp_ptr = *channel_address;
		if (temp_ptr == NotProcess_p) {
			*channel_address = Wptr;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			/* temp_ptr = (word *)((word)*channel_address & ~0x3); */
			if (temp_ptr[State] <= Ready_p) {
				*channel_address = Wptr;
				if (temp_ptr[State] == Waiting_p) {
					#ifdef PROCESS_PRIORITY
						if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
							sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
							PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						} else {
							QUEUE (temp_ptr);
						}
					#else
						QUEUE (temp_ptr);
					#endif	/* !PROCESS_PRIORITY */
				}
				temp_ptr[State] = Ready_p;
				Wptr[Pointer] = (word)source_address;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			} else {
				*channel_address = NotProcess_p;
				destination_address = (byte *)(temp_ptr[Pointer]);
				*(word *)destination_address = *(word *)source_address;
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
						SCHED_POLICY (Wptr, temp_ptr);
					} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
						/* we sleep and the other wakes up (go via scheduler for actual change) */
						sf.u.s.priority_sync = 1;
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						Wptr[Priority] = PPriority;
						QUEUE (Wptr);
						K_JUMP (X_scheduler);
					} else {
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					}
				#else	/* !PROCESS_PRIORITY */
					SCHED_POLICY (Wptr, temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
				K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
				RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
			}
		}
		barrier ();
	}
/*}}}*/
#endif	/* ENABLE_FASTCALLS */

/*{{{  void kernel_X_outword (void)*/
/*
 *	void kernel_X_outword (void)
 *	output a word
 */
void kernel_X_outword (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_outword, temp_ptr, channel_address);
	Wptr[0] = (word)temp_ptr;
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_outword);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS(Wptr[0], channel_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_outword, "%x, %p (ready = %s)", Wptr[0], channel_address, ((*channel_address == NotProcess_p) ? "no" : "yes"));

	source_address = (byte *)&(Wptr[0]);
	count = 4;
	DBGMSG("out: channel address = 0x%x\n" \
		"     count = %d\n" \
		"     source = 0x%x\n" \
		"     return_address = 0x%x\n", \
		channel_address, count, source_address, return_address);

	Wptr[Iptr] = return_address;
	temp_ptr = *channel_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)source_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP(X_scheduler);
	} else {
		DBGMSG("out: other_process[State] = 0x%x", temp_ptr[State]);
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			/* debug*/
			DBGMSG( "out: channel state is something ALTy.\n");
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP(X_scheduler);
		} else {
			*channel_address = NotProcess_p;
			destination_address = (byte *)(temp_ptr[Pointer]);
			/* copy */
			#ifdef DONT_USE_MEMCPY
				while (count--) {
					*(destination_address++) = *(source_address++);
				}
			#else
				MEMCPY(source_address, destination_address, count);
			#endif

			DBGMSG("in: queuing this process and other process.\n");
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */

			/* set up ebp = Wptr for occam */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		}
	}
	barrier ();
}
/*}}}*/

#ifdef ENABLE_FASTCALLS
/*{{{  void kernel_Y_fastout (void)*/
	/*
	 *	void kernel_Y_fastout (void)
	 *	fast output (new interface)
	 */
	void kernel_Y_fastout (void)
	{
		K_SETGLABEL_THREE_IN (Y_fastout, count, channel_address, source_address);
		ENTRY_TRACE (Y_fastout, "%d, %p, %p", count, channel_address, source_address);
	
		temp_ptr = *channel_address;
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			*channel_address = NotProcess_p;
			destination_address = (byte *)(temp_ptr[Pointer]);
			MEMCPY (source_address, destination_address, count);
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		}
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_out (void)*/
	/*
	 *	void kernel_Y_out (void)
	 *	output (new interface)
	 */
	void kernel_Y_out (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_THREE_IN_SR (Y_out, count, channel_address, source_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_THREE_IN (Y_out, count, channel_address, source_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_out, "%d, %p, %p", count, channel_address, source_address);

		temp_ptr = *channel_address;
		if (temp_ptr == NotProcess_p) {
			*channel_address = Wptr;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			if (temp_ptr[State] <= Ready_p) {
				*channel_address = Wptr;
				if (temp_ptr[State] == Waiting_p) {
					#ifdef PROCESS_PRIORITY
						if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
							sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
							PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						} else {
							QUEUE (temp_ptr);
						}
					#else
						QUEUE (temp_ptr);
					#endif	/* !PROCESS_PRIORITY */
				}
				temp_ptr[State] = Ready_p;
				Wptr[Pointer] = (word)source_address;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			} else {
				*channel_address = NotProcess_p;
				destination_address = (byte *)(temp_ptr[Pointer]);
				MEMCPY (source_address, destination_address, count);
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
						SCHED_POLICY (Wptr, temp_ptr);
					} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
						/* we sleep and the other wakes up (go via scheduler for actual change) */
						sf.u.s.priority_sync = 1;
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						Wptr[Priority] = PPriority;
						QUEUE (Wptr);
						K_JUMP (X_scheduler);
					} else {
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					}
				#else	/* !PROCESS_PRIORITY */
					SCHED_POLICY (Wptr, temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
				K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
				RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
			}
		}
		barrier ();
	}
	/*}}}*/
#endif	/* ENABLE_FASTCALLS */

/*{{{  void kernel_X_out (void)*/
/*
 *	void kernel_X_out (void)
 *	output
 */
void kernel_X_out (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (X_out, count, channel_address, source_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_out);
	LOADWPTR;
	LOADRETURN;
	THREEPARAMS(count, channel_address, source_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_out, "%d, %p, %p", count, channel_address, source_address);

	DBGMSG("out: channel address = 0x%x\n" \
		"     count = %d\n" \
		"     source = 0x%x\n" \
		"     return_address = 0x%x\n", \
		channel_address, count, source_address, \
		return_address);

	Wptr[Iptr] = return_address;
	temp_ptr = *channel_address;

	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)source_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP(X_scheduler);
	} else {
		DBGMSG("out: other_process[State] = 0x%x\n", temp_ptr[State]);
		/* mask off priority bit */
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			/* debug*/
			DBGMSG( "out: channel state is something ALTy.\n");
			if (temp_ptr[State] == Waiting_p) {
				DBGMSG ("out: queuing ALTing process (%p)\n", temp_ptr);
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP(X_scheduler);
		} else {
			*channel_address = NotProcess_p;
			destination_address = (byte *)(temp_ptr[Pointer]);

			/* copy */
			#ifdef DONT_USE_MEMCPY
				while (count--) {
					*(destination_address++) = *(source_address++);
				}
			#else
				MEMCPY(source_address, destination_address, count);
			#endif
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		}
	}
	barrier ();
}
/*}}}*/

#ifdef MOBILES
/*{{{  void kernel_X_mout (void)*/
/*
 *	void kernel_X_mout (void)
 *	MOBILE output
 */
void kernel_X_mout (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN_SR (X_mout, channel_address, source_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (X_mout, channel_address, source_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_mout, "%p, %p", channel_address, source_address);

	temp_ptr = *channel_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)source_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
	} else {
		if (temp_ptr[State] <= Ready_p) {
			/* something ALTy */
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			*channel_address = NotProcess_p;
			destination_address = (byte *)(temp_ptr[Pointer]);
			/* swap pointers */
			temp1 = *(word *)destination_address;
			*(word *)destination_address = *(word *)source_address;
			*(word *)source_address = temp1;
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_min (void)*/
/*
 *	void kernel_X_min (void)
 *	MOBILE input
 */
void kernel_X_min (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN_SR (X_min, channel_address, destination_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (X_min, channel_address, destination_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_min, "%p, %p", channel_address, destination_address);

	temp_ptr = *channel_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)destination_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
	} else {
		*channel_address = NotProcess_p;
		source_address = (byte *)((temp_ptr)[Pointer]);
		/* swap pointers */
		temp1 = *(word *)destination_address;
		*(word *)destination_address = *(word *)source_address;
		*(word *)source_address = temp1;

		#ifdef PROCESS_PRIORITY
			if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
				SCHED_POLICY (Wptr, temp_ptr);
			} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
				/* we sleep and the other wakes up (go via scheduler for actual change) */
				sf.u.s.priority_sync = 1;
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				Wptr[Priority] = PPriority;
				QUEUE (Wptr);
				K_JUMP (X_scheduler);
			} else {
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
			}
		#else	/* !PROCESS_PRIORITY */
			SCHED_POLICY (Wptr, temp_ptr);
		#endif	/* !PROCESS_PRIORITY */
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_mout64 (void)*/
/*
 *	void kernel_X_mout64 (void)
 *	MOBILE 64-bit output (for dynamic mobiles)
 */
void kernel_X_mout64 (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN_SR (X_mout64, channel_address, source_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (X_mout64, channel_address, source_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_mout64, "%p, %p", channel_address, source_address);

	temp_ptr = *channel_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)source_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
	} else {
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			/* something ALTy */
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)source_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			*channel_address = NotProcess_p;
			destination_address = (byte *)(temp_ptr[Pointer]);
			/* copy 64-bits */
			*(long long *)destination_address = *(long long *)source_address;
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_min64 (void)*/
/*
 *	void kernel_X_min64 (void)
 *	MOBILE 64-bit input (for dynamic MOBILEs)
 */
void kernel_X_min64 (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN_SR (X_min64, channel_address, destination_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (X_min64, channel_address, destination_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_min64, "%p, %p", channel_address, destination_address);

	temp_ptr = *channel_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)destination_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
	}
	*channel_address = NotProcess_p;
	source_address = (byte *)((temp_ptr)[Pointer]);
	/* copy 64-bits */
	*(long long *)destination_address = *(long long *)source_address;
	#ifdef PROCESS_PRIORITY
		if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
			SCHED_POLICY (Wptr, temp_ptr);
		} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
			/* we sleep and the other wakes up (go via scheduler for actual change) */
			sf.u.s.priority_sync = 1;
			PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
			Wptr[Priority] = PPriority;
			QUEUE (Wptr);
			K_JUMP (X_scheduler);
		} else {
			PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
		}
	#else	/* !PROCESS_PRIORITY */
		SCHED_POLICY (Wptr, temp_ptr);
	#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_minn (void)*/
/*
 *	void kernel_X_minn (void)
 *	MOBILE n-word input (for dynamic MOBILEs)
 */
void kernel_X_minn (void)
{
	K_SETGLABEL_THREE_IN (X_minn, count, channel_address, destination_address);
	ENTRY_TRACE (X_minn, "%d, %p, %p", count, channel_address, destination_address);

	temp_ptr = *channel_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)destination_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
#if defined(OUTPUT_ALTS)
	} else if (temp_ptr[State] <= Ready_p) {
		*channel_address = Wptr;
		/* something ALTy */
		if (temp_ptr[State] == Waiting_p) {
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
					sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				} else {
					QUEUE (temp_ptr);
				}
			#else
				QUEUE (temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
		}
		temp_ptr[State] = Ready_p;
		Wptr[Pointer] = (word)destination_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
#endif
	} else {
		*channel_address = NotProcess_p;
		source_address = (byte *)((temp_ptr)[Pointer]);
		/* copy count words */
		MEMCPY (source_address, destination_address, (count << WSH));
		#ifdef PROCESS_PRIORITY
			if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
				SCHED_POLICY (Wptr, temp_ptr);
			} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
				/* we sleep and the other wakes up (go via scheduler for actual change) */
				sf.u.s.priority_sync = 1;
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				Wptr[Priority] = PPriority;
				QUEUE (Wptr);
				K_JUMP (X_scheduler);
			} else {
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
			}
		#else	/* !PROCESS_PRIORITY */
			SCHED_POLICY (Wptr, temp_ptr);
		#endif	/* !PROCESS_PRIORITY */
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_moutn (void)*/
/*
 *	void kernel_X_moutn (void)
 *	MOBILE n-word output (for dynamic MOBILEs)
 */
void kernel_X_moutn (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN_SR (X_moutn, count, channel_address, source_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_THREE_IN (X_moutn, count, channel_address, source_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_moutn, "%d, %p, %p", count, channel_address, source_address);

	temp_ptr = *channel_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)source_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
	} else if (temp_ptr[State] <= Ready_p) {
		*channel_address = Wptr;
		/* something ALTy */
		if (temp_ptr[State] == Waiting_p) {
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
					sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				} else {
					QUEUE (temp_ptr);
				}
			#else
				QUEUE (temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
		}
		temp_ptr[State] = Ready_p;
		Wptr[Pointer] = (word)source_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
	} else {
		*channel_address = NotProcess_p;
		destination_address = (byte *)(temp_ptr[Pointer]);
		/* copy count words */
		MEMCPY (source_address, destination_address, (count << WSH));
		#ifdef PROCESS_PRIORITY
			if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
				SCHED_POLICY (Wptr, temp_ptr);
			} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
				/* we sleep and the other wakes up (go via scheduler for actual change) */
				sf.u.s.priority_sync = 1;
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				Wptr[Priority] = PPriority;
				QUEUE (Wptr);
				K_JUMP (X_scheduler);
			} else {
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
			}
		#else	/* !PROCESS_PRIORITY */
			SCHED_POLICY (Wptr, temp_ptr);
		#endif	/* !PROCESS_PRIORITY */
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
#endif	/* MOBILES */


#ifdef EXTENDED_RENDEZVOUS
/*{{{  void kernel_X_xable (void)*/
/*
 *	void kernel_X_xable (void)
 *	called to synchronise with outputting process
 */
void kernel_X_xable (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN_SR (X_xable, channel_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_ONE_IN (X_xable, channel_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_xable, "%p (ready = %d)", channel_address, (*channel_address != NotProcess_p));

	temp_ptr = *channel_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[State] = Waiting_p;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_xin (void)*/
/*
 *	void kernel_X_xin (void)
 *	extended input (doesn't queue blocked process)
 */
void kernel_X_xin (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN_SR (X_xin, count, channel_address, destination_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_THREE_IN (X_xin, count, channel_address, destination_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_xin, "%d, %p, %p", count, channel_address, destination_address);

	temp_ptr = *channel_address;
#if defined (OUTPUT_ALTS)
	if (temp_ptr[State] <= Ready_p) {
		/* cannot support this here! (outputting ALT) */

		MESSAGE ("KRoC: Application level error (ALTing output) at 0x%x, Wptr = 0x%x.\n", (unsigned int)(Wptr[Iptr]), (unsigned int)Wptr);
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#endif
	source_address = (byte *)(temp_ptr[Pointer]);
	MEMCPY (source_address, destination_address, count);
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/

#ifdef MOBILES
/*{{{  void kernel_X_xmin (void)*/
/*
 *	void kernel_X_xmin (void)
 *	extended mobile input (doesn't queue blocked process)
 */
void kernel_X_xmin (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN_SR (X_xmin, channel_address, destination_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (X_xmin, channel_address, destination_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_xmin, "%p, %p", channel_address, destination_address);

	temp_ptr = *channel_address;
#if defined (OUTPUT_ALTS)
	if (temp_ptr[State] <= Ready_p) {
		/* cannot support this here! (outputting ALT) */

		MESSAGE ("KRoC: Application level error (ALTing output) at 0x%x, Wptr = 0x%x.\n", (unsigned int)(Wptr[Iptr]), (unsigned int)Wptr);
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#endif
	source_address = (byte *)((temp_ptr)[Pointer]);
	/* swap pointers */
	temp1 = *(word *)destination_address;
	*(word *)destination_address = *(word *)source_address;
	*(word *)source_address = temp1;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_xmin64 (void)*/
/*
 *	void kernel_X_xmin64 (void)
 *	extended dynamic mobile input (doesn't queue blocked process)
 */
void kernel_X_xmin64 (void)
{
	K_SETGLABEL_TWO_IN (X_xmin64, channel_address, destination_address);
	ENTRY_TRACE (X_xmin64, "%p, %p", channel_address, destination_address);

	temp_ptr = *channel_address;
#if defined (OUTPUT_ALTS)
	if (temp_ptr[State] <= Ready_p) {
		/* cannot support this here! (outputting ALT) */

		MESSAGE ("KRoC: Application level error (ALTing output) at 0x%x, Wptr = 0x%x.\n", (unsigned int)(Wptr[Iptr]), (unsigned int)Wptr);
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#endif
	source_address = (byte *)((temp_ptr)[Pointer]);
	/* copy 64-bits */
	*(long long *)destination_address = *(long long *)source_address;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_xminn (void)*/
/*
 *	void kernel_X_xminn (void)
 *	extended dynamic mobile input for n-words (doesn't queue blocked process)
 */
void kernel_X_xminn (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN_SR (X_xminn, count, channel_address, destination_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_THREE_IN (X_xminn, count, channel_address, destination_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_xminn, "%d, %p, %p", count, channel_address, destination_address);

	temp_ptr = *channel_address;
#if defined (OUTPUT_ALTS)
	if (temp_ptr[State] <= Ready_p) {
		/* cannot support this here! (outputting ALT) */

		MESSAGE ("KRoC: Application level error (ALTing output) at 0x%x, Wptr = 0x%x.\n", (unsigned int)(Wptr[Iptr]), (unsigned int)Wptr);
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#endif
	source_address = (byte *)((temp_ptr)[Pointer]);
	/* copy count words */
	MEMCPY (source_address, destination_address, (count << WSH));
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
#endif	/* MOBILES */

/*{{{  void kernel_X_xend (void)*/
/*
 *	void kernel_X_xend (void)
 *	called to resume outputting process
 */
void kernel_X_xend (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_xend, channel_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_xend);
	LOADWPTR;
	LOADRETURN;
	PARAM (channel_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_xend, "%p (process = %p)", channel_address, (word *)*channel_address);

	temp_ptr = *channel_address;
	#ifdef PROCESS_PRIORITY
		if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
			sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
			PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
		} else {
			QUEUE (temp_ptr);
		}
	#else
		QUEUE (temp_ptr);
	#endif	/* !PROCESS_PRIORITY */
	*channel_address = NotProcess_p;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
#endif	/* EXTENDED_RENDEZVOUS */

#if defined(USER_DEFINED_CHANNELS) && defined(ENABLE_FASTCALLS)
/*{{{  external channel handling*/
/*{{{  void kernel_Y_extin (void)*/
	/*
	 *	void kernel_Y_extin{,8,32} (void)
	 *	external inputs
	 */
	void kernel_Y_extin (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_THREE_IN_SR (Y_extin, count, extchan, destination_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_THREE_IN (Y_extin, count, extchan, destination_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extin, "%d, %p, %p", count, extchan, destination_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTIN\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_read) {
			MESSAGE ("KRoC: fatal: channel not for reading\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, use a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_INPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)destination_address, (void *)count, (void (*)(word *, void *, void *))extchan->chan_read);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)destination_address, (void *)count, (void (*)(word *, void *, void *))extchan->chan_read);
				#endif
				K_JUMP(X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_read (extchan, (char *)destination_address, count)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extin8 (void)*/
	void kernel_Y_extin8 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extin8, extchan, destination_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extin8, extchan, destination_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extin8, "%p, %p", extchan, destination_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTIN8\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_read) {
			MESSAGE ("KRoC: fatal: channel not for reading\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, use a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_INPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)destination_address, (void *)1, (void (*)(word *, void *, void *))extchan->chan_read);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)destination_address, (void *)1, (void (*)(word *, void *, void *))extchan->chan_read);
				#endif
				K_JUMP(X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_read (extchan, (char *)destination_address, 1)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extin32 (void)*/
	void kernel_Y_extin32 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extin32, extchan, destination_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extin32, extchan, destination_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extin32, "%p, %p", extchan, destination_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTIN32\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_read) {
			MESSAGE ("KRoC: fatal: channel not for reading\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, use a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_INPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)destination_address, (void *)4, (void (*)(word *, void *, void *))extchan->chan_read);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)destination_address, (void *)4, (void (*)(word *, void *, void *))extchan->chan_read);
				#endif
				K_JUMP(X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_read (extchan, (char *)destination_address, 4)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  external MOBILEs handling*/
#ifdef MOBILES
/*{{{  void kernel_Y_extmin (void)*/
	/*
	 *	void kernel_Y_extmin (void)
	 *	external MOBILE input
	 */
	void kernel_Y_extmin (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extmin, extchan, destination_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extmin, extchan, destination_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extmin, "%p, %p", extchan, destination_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTMIN\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_min) {
			MESSAGE ("KRoC: fatal: channel not for MOBILE input\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, use a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_INPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char*)Wptr[Iptr], PPriority, (word *)extchan, (void *)destination_address, NULL, (void (*)(word *, void *, void *))extchan->chan_min);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char*)Wptr[Iptr], (word *)extchan, (void *)destination_address, NULL, (void (*)(word *, void *, void *))extchan->chan_min);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_min (extchan, (void **)destination_address)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extmin64 (void)*/
	/*
	 *	void kernel_Y_extmin64 (void)
	 *	external dynamic MOBILE input
	 */
	void kernel_Y_extmin64 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extmin64, extchan, destination_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extmin64, extchan, destination_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extmin64, "%p, %p", extchan, destination_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTMIN64\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_min64) {
			MESSAGE ("KRoC: fatal: channel not for dynamic MOBILE input\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, dispatch a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_INPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char*)Wptr[Iptr], PPriority, (word *)extchan, (void *)destination_address, NULL, (void (*)(word *, void *, void *))extchan->chan_min64);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char*)Wptr[Iptr], (word *)extchan, (void *)destination_address, NULL, (void (*)(word *, void *, void *))extchan->chan_min64);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_min64 (extchan, (unsigned long long *)destination_address)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extminn (void)*/
	/*
	 *	void kernel_Y_extminn (void)
	 *	external dynamic multi-dimensional MOBILE input
	 */
	void kernel_Y_extminn (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_THREE_IN_SR (Y_extminn, count, extchan, destination_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_THREE_IN (Y_extminn, count, extchan, destination_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extminn, "%d, %p, %p", count, extchan, destination_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTMINN\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_minn) {
			MESSAGE ("KRoC: fatal: channel not for multi-dimensional dynamic MOBILE input\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, dispatch a bsyscall to handle it, otherwiseplain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_INPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)destination_address, (void *)count, (void (*)(word *, void *, void *))extchan->chan_minn);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)destination_address, (void *)count, (void (*)(word *, void *, void *))extchan->chan_moutn);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_minn (extchan, (unsigned int *)destination_address, (int)count)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extmout (void)*/
	/*
	 *	void kernel_Y_extmout (void)
	 *	external MOBILE output
	 */
	void kernel_Y_extmout (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extmout, extchan, source_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extmout, extchan, source_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extmin64, "%p, %p", extchan, source_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTMOUT\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_mout) {
			MESSAGE ("KRoC: fatal: channel not for MOBILE output\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, dispatch a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_OUTPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char*)Wptr[Iptr], PPriority, (word *)extchan, (void *)source_address, NULL, (void (*)(word *, void *, void *))extchan->chan_mout);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char*)Wptr[Iptr], (word *)extchan, (void *)source_address, NULL, (void (*)(word *, void *, void *))extchan->chan_mout);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_mout (extchan, (void **)source_address)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extmout64 (void)*/
	/*
	 *	void kernel_Y_extmout64 (void)
	 *	external dynamic MOBILE output
	 */
	void kernel_Y_extmout64 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extmout64, extchan, source_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extmout64, extchan, source_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extmout64, "%p, %p", extchan, source_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTMOUT64\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_mout64) {
			MESSAGE ("KRoC: fatal: channel not for dynamic MOBILE output\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, dispatch a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_OUTPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char*)Wptr[Iptr], PPriority, (word *)extchan, (void *)source_address, NULL, (void (*)(word *, void *, void *))extchan->chan_mout64);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char*)Wptr[Iptr], (word *)extchan, (void *)source_address, NULL, (void (*)(word *, void *, void *))extchan->chan_mout64);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_mout64 (extchan, (unsigned long long *)source_address)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extmoutn (void)*/
	/*
	 *	void kernel_Y_extmoutn (void)
	 *	external multi-dimensional dynamic MOBILE output
	 */
	void kernel_Y_extmoutn (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_THREE_IN_SR (Y_extmoutn, count, extchan, source_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_THREE_IN (Y_extmoutn, count, extchan, source_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y-extoutn, "%d, %p, %p", count, extchan, source_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTMOUTN\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_moutn) {
			MESSAGE ("KRoC: fatal: channel not for multi-dimensional dynamic MOBILE output\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, dispatch a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_OUTPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)source_address, (void *)count, (void (*)(word *, void *, void *))extchan->chan_moutn);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)source_address, (void *)count, (void (*)(word *, void *, void *))extchan->chan_moutn);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_moutn (extchan, (unsigned int *)source_address, (int)count)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
#endif	/* MOBILES */
/*}}}*/
/*{{{  void kernel_Y_extout (void)*/
	/*
	 *	void kernel_Y_extout{,8,32,byte,word} (void)
	 *	external outputs
	 */
	void kernel_Y_extout (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_THREE_IN_SR (Y_extout, count, extchan, source_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_THREE_IN (Y_extout, count, extchan, source_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extout, "%d, %p, %p", count, extchan, source_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTOUT\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_write) {
			MESSAGE ("KRoC: fatal: channel not for writing\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, use a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_OUTPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)source_address, (void *)count, (void (*)(word *, void *, void *))extchan->chan_write);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)source_address, (void *)count, (void (*)(word *, void *, void *))extchan->chan_write);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_write (extchan, (char *)source_address, count)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extout8 (void)*/
	void kernel_Y_extout8 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extout8, extchan, source_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extout8, extchan, source_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extout8, "%p, %p", extchan, source_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTOUT8\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_write) {
			MESSAGE ("KRoC: fatal: channel not for writing\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, use a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_OUTPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)source_address, (void *)1, (void (*)(word *, void *, void *))extchan->chan_write);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)source_address, (void *)1, (void (*)(word *, void *, void *))extchan->chan_write);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_write (extchan, (char *)source_address, 1)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extout32 (void)*/
	void kernel_Y_extout32 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extout32, extchan, source_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extout32, extchan, source_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extout32, "%p, %p", extchan, source_address);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTOUT32\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_write) {
			MESSAGE ("KRoC: fatal: channel not for writing\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, use a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_OUTPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)source_address, (void *)4, (void (*)(word *, void *, void *))extchan->chan_write);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)source_address, (void *)4, (void (*)(word *, void *, void *))extchan->chan_write);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_write (extchan, (char *)source_address, 4)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extoutbyte (void)*/
	void kernel_Y_extoutbyte (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extoutbyte, temp_ptr, extchan);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extoutbyte, temp_ptr, extchan);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extoutbyte, "%d, %p", (word)temp_ptr, extchan);

		Wptr[0] = (word)temp_ptr;
		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTOUTBYTE\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_write) {
			MESSAGE ("KRoC: fatal: channel not for writing\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, use a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_OUTPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)Wptr, (void *)4, (void (*)(word *, void *, void *))extchan->chan_write);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)Wptr, (void *)4, (void (*)(word *, void *, void *))extchan->chan_write);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_write (extchan, (char *)Wptr, 4)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extoutword (void)*/
	void kernel_Y_extoutword (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_extoutword, temp_ptr, extchan);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extoutword, temp_ptr, extchan);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extoutword, "%d, %p", (word)temp_ptr, extchan);

		Wptr[0] = (word)temp_ptr;
		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTOUTWORD\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_write) {
			MESSAGE ("KRoC: fatal: channel not for writing\n");
			occam_exit (1, (int)extchan);
		}
		/* if marked as blocking, use a bsyscall to handle it, otherwise plain */
		#if !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS)
			if (extchan->flags & UDC_BLOCKING_OUTPUT) {
				#ifdef PROCESS_PRIORITY
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], PPriority, (word *)extchan, (void *)Wptr, (void *)1, (void (*)(word *, void *, void *))extchan->chan_write);
				#else
				bsyscalls_dispatch3 ((word *)Wptr, (char *)Wptr[Iptr], (word *)extchan, (void *)Wptr, (void *)1, (void (*)(word *, void *, void *))extchan->chan_write);
				#endif
				K_JUMP (X_scheduler);
			} else
		#endif	/* !defined(OOS_BUILD) && defined(BLOCKING_SYSCALLS) */
		{
			if (extchan->chan_write (extchan, (char *)Wptr, 1)) {
				extchan->chanword = Wptr;
				#ifdef PROCESS_PRIORITY
				Wptr[Priority] = PPriority;
				#endif
				K_JUMP (X_scheduler);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_X_extvrfy (void)*/
	/*
	 *	void kernel_X_extvrfy (void)
	 *	external channel verify
	 */
	void kernel_X_extvrfy (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN (X_extvrfy, count, extchan);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL (X_extvrfy);
		LOADWPTR;
		LOADRETURN;
		TWOPARAMS (count, extchan);
#endif	/* !TARGET_CPU_SPARC */

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTVRFY\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_verify) {
			MESSAGE ("KRoC: fatal: no verification function for channel\n");
			occam_exit (1, (int)extchan);
		}
		if (extchan->chantype && (count != extchan->chantype)) {
			MESSAGE ("KRoC: fatal: channel type set to something different\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chantype) {
			extchan->chantype = count;
		}
		if (extchan->chan_verify (extchan, count)) {
			MESSAGE ("KRoC: fatal: external channel verification failed\n");
			occam_exit (1, (int)extchan);
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  ext_chan_t *ccsp_udc_alloc_extchan (int extra_bytes)*/
	/*
	 *	ext_chan_t *ccsp_udc_alloc_extchan (int extra_bytes)
	 *	called by the user to allocate the structure, plus some space if needed.
	 */
	ext_chan_t *ccsp_udc_alloc_extchan (int extra_bytes)
	{
		ext_chan_t *e_chan;
		const int s_extchan = (sizeof (ext_chan_t) & ~0x3) + ((sizeof (ext_chan_t) & 0x3) ? 4 : 0);	/* round up to word */
		const int s_extra = (extra_bytes & ~0x3) + ((extra_bytes & 0x3) ? 4 : 0);			/* round up to word */

#if defined(OOS_BUILD)
		e_chan = (ext_chan_t *)oos_kmalloc (s_extchan + s_extra, 0);
#else
		e_chan = (ext_chan_t *)malloc (s_extchan + s_extra);
#endif
		if (!e_chan) {
			MESSAGE ("KRoC: fatal: unable to allocate external channel with %d extra bytes\n", extra_bytes);
			occam_exit (1, 0);
		}
		e_chan->chanword = NULL;
		e_chan->chantype = 0;
		e_chan->chanbxalt = NULL;
		e_chan->chansync = NULL;

		e_chan->chan_verify = NULL;
		e_chan->chan_read = NULL;
		e_chan->chan_write = NULL;
		e_chan->chan_alt_enable = NULL;
		e_chan->chan_alt_disable = NULL;
		#ifdef MOBILES
		e_chan->chan_min = NULL;
		e_chan->chan_mout = NULL;
		e_chan->chan_min64 = NULL;
		e_chan->chan_mout64 = NULL;
		e_chan->chan_minn = NULL;
		e_chan->chan_moutn = NULL;
		#endif	/* MOBILES */

		e_chan->magic = 0;
		if (extra_bytes) {
			e_chan->userptr = (void *)(((char *)e_chan) + s_extchan);
		} else {
			e_chan->userptr = NULL;
		}
		barrier ();
		return e_chan;
	}
/*}}}*/
/*{{{  void ccsp_udc_free_extchan (ext_chan_t *e_chan)*/
	/*
	 *	void ccsp_udc_free_extchan (ext_chan_t *e_chan)
	 *	called by the user to free a ext_chan_t structure
	 */
	void ccsp_udc_free_extchan (ext_chan_t *e_chan)
	{
		if (!e_chan) {
			MESSAGE ("KRoC: fatal: NULL external channel in ccsp_udc_free_extchan\n");
			occam_exit (1, (int)e_chan);
		}
#if defined(OOS_BUILD)
		oos_kfree (e_chan);
#else
		free (e_chan);
#endif
		barrier ();
		return;
	}
/*}}}*/
/*{{{  void ccsp_udc_resume_process (ext_chan_t *e_chan)*/
	/*
	 *	void ccsp_udc_resume_process (ext_chan_t *e_chan)
	 *	external resume process.  called from one of the user-provided functions to
	 *	un-block a process.
	 */
	void ccsp_udc_resume_process (ext_chan_t *e_chan)
	{
		word *process;

		if (!e_chan || (e_chan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in ccsp_udc_resume_process(%p)\n", e_chan);
			occam_exit (1, (int)e_chan);
		} else if (e_chan->flags & UDC_BLOCKING) {
			/* if calling from bsc, wrong thread!;  otherwise can't resume something which can't block in the channel */
			MESSAGE ("KRoC: fatal: in ccsp_udc_resume_process(%p), but channel marked for blocking-syscall!\n", e_chan);
			occam_exit (1, (int)e_chan);
		} else if (!e_chan->chanword) {
			MESSAGE ("KRoC: fatal: in ccsp_udc_resume_process(%p), but channel empty!\n", e_chan);
			occam_exit (1, (int)e_chan);
		}

		process = (word *)e_chan->chanword;
		if ((int)process & 1) {
			/* something ALTy */
			process = (word *)((unsigned int)process & ~1);
			if (process[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (process[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (process[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (process[Priority]), process);
					} else {
						QUEUE (process);
					}
				#else
					QUEUE (process);
				#endif	/* !PROCESS_PRIORITY */
			}
			process[State] = Ready_p;
		} else {
			#ifdef PROCESS_PRIORITY
				if (PriMasked (process[Priority]) != MaskedPPriority) {
					sf.u.s.priority_sync |= (byte)(PriMasked (process[Priority]) < MaskedPPriority);
					PQUEUE (PriMasked (process[Priority]), process);
				} else {
					QUEUE (process);
				}
			#else
				QUEUE (process);
			#endif	/* !PROCESS_PRIORITY */
		}
		e_chan->chanword = NULL;
		barrier ();
		return;
	}
/*}}}*/
/*{{{  void kernel_Y_extenbc (void)*/
	/*
	 *	void kernel_Y_extenbc (void)
	 *	called to enable a user-defined channel
	 */
	void kernel_Y_extenbc (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN (Y_extenbc, guard, extchan);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_extenbc, guard, extchan);
		/* LOADWPTR; */
		LOADRETURN;
		/* TWOPARAMS(guard, extchan); */
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extenbc, "%d, %p", guard, extchan);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTENBC\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_alt_enable) {
			MESSAGE ("KRoC: fatal: external channel does not support ALT\n");
			occam_exit (1, (int)extchan);
		}
		if (guard) {
			if (extchan->flags & UDC_BLOCKING_ALT) {
				extchan->chanbxalt = NULL;
				extchan->chansync = NULL;
			}
			if (extchan->chan_alt_enable (extchan)) {
				/* ready */
				Wptr[State] = Ready_p;
			} else {
				/* put ALTing process in channel */
				extchan->chanword = (void *)((unsigned int)Wptr | 1);
			}
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
		RETURNVAL (guard);
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_extndisc (void)*/
	/*
	 *	void kernel_Y_extndisc (void)
	 *	called to disable a user-defined channel
	 */
	void kernel_Y_extndisc (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_THREE_IN (Y_extndisc, process_address, guard, extchan);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_THREE_IN (Y_extndisc, process_address, guard, extchan);
		/* LOADWPTR; */
		LOADRETURN;
		/* THREEPARAMS(process_address, guard, extchan); */
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_extndisc, "%p, %d, %p", (void *)process_address, guard, extchan);

		if (!extchan || (extchan->magic != UDC_MAGIC)) {
			MESSAGE ("KRoC: fatal: damaged external channel in EXTNDISC\n");
			occam_exit (1, (int)extchan);
		} else if (!extchan->chan_alt_disable) {
			MESSAGE ("KRoC: fatal: external channel does not support ALT\n");
			occam_exit (1, (int)extchan);
		}
		if (!guard) {
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
			RETURNVAL (guard);
			RESTORE;
			EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
		}
		if (extchan->chan_alt_disable (extchan)) {
			/* channel ready */
			Wptr[Temp] = process_address;	/* actually offset */
			fired = true;
		} else {
			if (extchan->flags & UDC_BLOCKING_ALT) {
#if 0
fprintf (stderr, "X_extndisc: blocking ALT, synchronising with exiting process.\n");
#endif
				/* not ready, so we terminated the call, wait for it, fired will always be false */
				if (!extchan->chansync) {
					/* we're first */
#if 0
fprintf (stderr, "X_extndisc: blocking ALT still outstanding, waiting for it.  bsyscalls_pending() returns %d\n", bsyscalls_pending ());
#endif
					extchan->chanbxalt = (void *)return_address;
					extchan->chansync = Wptr;
					#ifdef PROCESS_PRIORITY
					Wptr[Priority] = PPriority;
					#endif
					K_JUMP (X_scheduler);
				}
				extchan->chansync = NULL;
			}
			extchan->chanword = NULL;
			fired = false;
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ONE_OUT (fired);
#else	/* !TARGET_CPU_SPARC */
		RETURNVAL (fired);
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
#if !defined(OOS_BUILD)
/*{{{  void kernel_X_udc_fallout (void)*/
	/*
	 *	void kernel_X_udc_fallout (void)
	 *	called by the thread which exits the blocking sys-call
	 */
	void kernel_X_udc_fallout (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ZERO_IN (X_udc_fallout);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL (X_udc_fallout);
		LOADWPTR;
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (X_udc_fallout, "silly, Wptr = %p", Wptr);
		/* adjust Wptr */

		if (Wptr[4] == 1) {
#if 0
fprintf (stderr, "looks like we should wake up alt!\n");
#endif
			temp_ptr = (word *)Wptr[5];
			if (temp_ptr[State] == Waiting_p) {
#if 0
fprintf (stderr, "ALT waiting (temp_ptr = %p), setting ready and queuing\n", temp_ptr);
#endif
				temp_ptr[State] = Ready_p;
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
		} else if (Wptr[4] == -1) {
#if 0
fprintf (stderr, "not waking up ALT, channel not ready\n");
#endif
		} else {
#if 0
fprintf (stderr, "not waking up ALT, probably killed\n");
#endif
		}
		/* set flag in channel to indicate we're done, wait it up if already there */
		extchan = (ext_chan_t *)(Wptr[7]);
		Wptr = &(Wptr[-4]);
		free (Wptr);
		Wptr = NotProcess_p;
		if (extchan->flags & UDC_BLOCKING_ALT) {
			if (extchan->chansync) {
				/* EXTNDISC blocked in here, waiting for termination -- we become the rest of that process (!) */
#if 0
fprintf (stderr, "X_udc_fallout: becomming rest of the EXTNDISC process..\n");
#endif
				return_address = (int)extchan->chanbxalt;
				Wptr = (word *)extchan->chansync;
				extchan->chansync = NULL;
				extchan->chanbxalt = 0;
				extchan->chanword = NULL;
				fired = false;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
				K_ONE_OUT (fired);
#else	/* !TARGET_CPU_SPARC */
				RETURNVAL (fired);
				RESTORE;
				EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
			}
#if 0
fprintf (stderr, "X_udc_fallout: EXTNDISC not here yet, setting flag so it knows we were here..\n");
#endif
			extchan->chansync = (void *)extchan;
		}
		/* reschedule */
		K_JUMP (X_scheduler);
		barrier ();
	}
/*}}}*/
extern void udc_alter_fallout_jumpcode (void);		/* in the KRoC interface stuff */
#ifdef BLOCKING_SYSCALLS
/*{{{  static void ccsp_udc_alter_stub (int *ws)*/
	/*
	 *	void ccsp_udc_alter_stub (int *ws)
	 *	small bit of stub-code which wraps up the call to the user-defined whatever
	 */
	static void ccsp_udc_alter_stub (int *ws)
	{
		void (*func)(void *, int *) = (void (*)(void *, int *))(ws[-2]);	/* get function address */

		func ((void *)(ws[0]), &(ws[1]));
		return;
	}
/*}}}*/
/*{{{  void ccsp_udc_start_alter (ext_chan_t *e_chan, void (*bfunc)(void *, int *), void *arg)*/
	/*
	 *	void ccsp_udc_start_alter (ext_chan_t *e_chan, void (*bfunc)(void *, int *), void *arg)
	 *	called to dispatch a blocking ALT thread.. (we are ultimatly in the context of occam, so PPriority is valid)
	 */
	void ccsp_udc_start_alter (ext_chan_t *e_chan, void (*bfunc)(void *, int *), void *arg)
	{
		word *alter_ws;

		alter_ws = (word *)malloc (12 * sizeof (word));
		if (!alter_ws) {
			MESSAGE ("KRoC: fatal: out of memory in ccsp_udc_start_alter\n");
			occam_exit (1, (int)e_chan);
		}
		alter_ws = &(alter_ws[4]);	/* adjust */
		#ifdef PROCESS_PRIORITY
		alter_ws[-3] = 0;		/* priority field */
		#endif
		alter_ws[-2] = 0;		/* link field */
		alter_ws[-1] = 0;		/* return address */
		alter_ws[0] = 0;		/* temporary */
		alter_ws[1] = (word)bfunc;	/* real user function to call */
		alter_ws[2] = (word)&(alter_ws[6]);		/* magic channel up here out of the way */
		alter_ws[3] = (word)arg;	/* this is what gets pointed at by "ws" in ccsp_udc_alter_stub() */
		alter_ws[4] = 0;		/* more magic */
		alter_ws[5] = (word)Wptr;	/* Wptr of the ALTing process (must be us!) */
		alter_ws[6] = 0;		/* the magic channel */
		alter_ws[7] = (word)e_chan;
		e_chan->chanbxalt = &(alter_ws[6]);
		#ifdef PROCESS_PRIORITY
		bsyscalls_dispatch ((word *)alter_ws, (char *)udc_alter_fallout_jumpcode, PPriority, &(alter_ws[2]), (void (*)(word *))ccsp_udc_alter_stub, 4);
		#else
		bsyscalls_dispatch ((word *)alter_ws, (char *)udc_alter_fallout_jumpcode, &(alter_ws[2]), (void (*)(word *))ccsp_udc_alter_stub, 4);
		#endif
		/* oki, that should be running happily... */
		return;
	}
/*}}}*/
/*{{{  int ccsp_udc_kill_alter (ext_chan_t *e_chan)*/
	/*
	 *	int ccsp_udc_kill_alter (ext_chan_t *e_chan)
	 *	called to kill a blocking ALT thread..
	 */
	int ccsp_udc_kill_alter (ext_chan_t *e_chan)
	{
		int args[2];
		int result;

		args[0] = (int)e_chan->chanbxalt;
		args[1] = (int)&result;
		_killcall (args);
#if 0
fprintf (stderr, "ccsp_udc_kill_alter: returning %d to EXTALT disable..\n", result);
#endif
		return result;
	}
/*}}}*/
#endif	/* BLOCKING_SYSCALLS */
#endif	/* !OOS_BUILD */
/*}}}*/
#endif	/* USER_DEFINED_CHANNELS && ENABLE_FASTCALLS*/

#if defined(ENABLE_FASTCALLS) && defined(PROCESS_PRIORITY)
/*{{{  void kernel_X_getpri (void)*/
	/*
	 *	void kernel_X_getpri (void)
	 *	get process priority (usually inlined by tranx86)
	 */
	void kernel_X_getpri (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ZERO_IN (X_getpri);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL (X_getpri);
		LOADWPTR;
		LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE0 (X_getpri);

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ONE_OUT (MaskedPPriority);
#else	/* !TARGET_CPU_SPARC */
		RETURNVAL (MaskedPPriority);
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
/*{{{  void kernel_Y_setpri (void)*/
	/*
	 *	void kernel_Y_setpri (void)
	 *	set process priority
	 */
	void kernel_Y_setpri (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ONE_IN_SR (Y_setpri, guard);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_ONE_IN (Y_setpri, guard);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_setpri, "%d", guard);

#if 0
fprintf (stderr, "KRoC: priority change from %d to %d.  PState = 0x%8.8x\n", PPriority, guard, PState);
#endif
		if (guard < 0) {
			guard = 0;
		} else if (guard >= MAX_PRIORITY_LEVELS) {
			guard = MAX_PRIORITY_LEVELS - 1;
		}
		if (guard != MaskedPPriority) {
			if (!Fptr) {
				/* loner here, remove bit */
				PState &= ~(1 << MaskedPPriority);
			}
			SAVE_PRIORITY_QUEUE (MaskedPPriority);

			/* save current process on right queue */
			Wptr[Priority] = (MaskedPGroup | guard);
			PQUEUE (guard, Wptr);

			/* select highest priority */
			PPriority = bsf (PState);
#if 0
fprintf (stderr, "KRoC: bsf (%d) returned %d\n", PState, PPriority);
#endif
			LOAD_PRIORITY_QUEUE (MaskedPPriority);
			Wptr = GetNextProcess ();

		}
		barrier ();
#if 0
fprintf (stderr, "KRoC: priority change out to %d.  PState = 0x%8.8x\n", PPriority, PState);
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
#endif	/* ENABLE_FASTCALLS && PROCESS_PRIORITY */

#ifdef ENABLE_FASTCALLS
/*{{{  void kernel_Y_in (void)*/
	/*
	 *	void kernel_Y_in (void)
	 *	new input entry-point
	 */
	void kernel_Y_in (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_THREE_IN_SR (Y_in, count, channel_address, destination_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_THREE_IN (Y_in, count, channel_address, destination_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_in, "%d, %p, %p", count, channel_address, destination_address);

		temp_ptr = *channel_address;
		if (temp_ptr == NotProcess_p) {
			*channel_address = Wptr;
			Wptr[Pointer] = (word)destination_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
#if defined (OUTPUT_ALTS)
		} else if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)destination_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
#endif
		} else {
			*channel_address = NotProcess_p;
			source_address = (byte *)(temp_ptr[Pointer]);
			MEMCPY (source_address, destination_address, count);
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		}
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_fastin (void)*/
	/*
	 *	void kernel_Y_fastin (void)
	 *	fast input entry-point
	 */
	void kernel_Y_fastin (void)
	{
		K_SETGLABEL_THREE_IN (Y_fastin, count, channel_address, destination_address);
		ENTRY_TRACE (Y_fastin, "%d, %p, %p", count, channel_address, destination_address);

		temp_ptr = *channel_address;
#if defined (OUTPUT_ALTS)
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)destination_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		}
#endif
		*channel_address = NotProcess_p;
		source_address = (byte *)(temp_ptr[Pointer]);
		MEMCPY (source_address, destination_address, count);
		#ifdef PROCESS_PRIORITY
			if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
				SCHED_POLICY (Wptr, temp_ptr);
			} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
				/* we sleep and the other wakes up (go via scheduler for actual change) */
				sf.u.s.priority_sync = 1;
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				/* Wptr[Priority] = PPriority; */
				QUEUE (Wptr);
				K_JUMP (X_scheduler);
			} else {
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
			}
		#else	/* !PROCESS_PRIORITY */
			SCHED_POLICY (Wptr, temp_ptr);
		#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_in32 (void)*/
	/*
	 *	void kernel_Y_in32 (void)
	 *	inputs a word
	 */
	void kernel_Y_in32 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_in32, channel_address, destination_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_in32, channel_address, destination_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_in32, "%p, %p, %p, %p (ready = %s)", Wptr, (void *)Wptr[Iptr], channel_address, destination_address, ((*channel_address == NotProcess_p) ? "no" : "yes"));

		temp_ptr = *channel_address;
		if (temp_ptr == NotProcess_p) {
			*channel_address = Wptr;
			Wptr[Pointer] = (word)destination_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
#if defined (OUTPUT_ALTS)
		} else if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)destination_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
#endif
		} else {
			*channel_address = NotProcess_p;
			source_address = (byte *)(temp_ptr[Pointer]);
			*(word *)destination_address = *(word *)source_address;
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		}
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_fastin32 (void)*/
	/*
	 *	void kernel_Y_fastin32 (void)
	 *	fast input word
	 */
	void kernel_Y_fastin32 (void)
	{
		K_SETGLABEL_TWO_IN (Y_fastin32, channel_address, destination_address);
		ENTRY_TRACE (Y_fastin32, "%p, %p", channel_address, destination_address);

		temp_ptr = *channel_address;
#if defined (OUTPUT_ALTS)
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)destination_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		}
#endif
		*channel_address = NotProcess_p;
		source_address = (byte *)(temp_ptr[Pointer]);
		*(word *)destination_address = *(word *)source_address;
		#ifdef PROCESS_PRIORITY
			if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
				SCHED_POLICY (Wptr, temp_ptr);
			} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
				/* we sleep and the other wakes up (go via scheduler for actual change) */
				sf.u.s.priority_sync = 1;
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				/* Wptr[Priority] = PPriority; */
				QUEUE (Wptr);
				K_JUMP (X_scheduler);
			} else {
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
			}
		#else	/* !PROCESS_PRIORITY */
			SCHED_POLICY (Wptr, temp_ptr);
		#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_in8 (void)*/
	/*
	 *	void kernel_Y_in8 (void)
	 *	inputs a byte
	 */
	void kernel_Y_in8 (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN_SR (Y_in8, channel_address, destination_address);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL_TWO_IN (Y_in8, channel_address, destination_address);
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE (Y_in8, "%p, %p (ready = %s)", channel_address, destination_address, ((*channel_address == NotProcess_p) ? "no" : "yes"));

		temp_ptr = *channel_address;
		if (temp_ptr == NotProcess_p) {
			*channel_address = Wptr;
			Wptr[Pointer] = (word)destination_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
#if defined (OUTPUT_ALTS)
		} else if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)destination_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
#endif
		} else {
			*channel_address = NotProcess_p;
			source_address = (byte *)(temp_ptr[Pointer]);
			*(byte *)destination_address = *(byte *)source_address;
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					SCHED_POLICY (Wptr, temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					/* we sleep and the other wakes up (go via scheduler for actual change) */
					sf.u.s.priority_sync = 1;
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					Wptr[Priority] = PPriority;
					QUEUE (Wptr);
					K_JUMP (X_scheduler);
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
			#else	/* !PROCESS_PRIORITY */
				SCHED_POLICY (Wptr, temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		}
		barrier ();
	}
	/*}}}*/
	/*{{{  void kernel_Y_fastin8 (void)*/
	/*
	 *	void kernel_Y_fastin8 (void)
	 *	fast input word
	 */
	void kernel_Y_fastin8 (void)
	{
		K_SETGLABEL_TWO_IN (Y_fastin8, channel_address, destination_address);
		ENTRY_TRACE (Y_fastin8, "%p, %p", channel_address, destination_address);

		temp_ptr = *channel_address;
#if defined (OUTPUT_ALTS)
		if (temp_ptr[State] <= Ready_p) {
			*channel_address = Wptr;
			if (temp_ptr[State] == Waiting_p) {
				#ifdef PROCESS_PRIORITY
					if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
						sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					} else {
						QUEUE (temp_ptr);
					}
				#else
					QUEUE (temp_ptr);
				#endif	/* !PROCESS_PRIORITY */
			}
			temp_ptr[State] = Ready_p;
			Wptr[Pointer] = (word)destination_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		}
#endif
		*channel_address = NotProcess_p;
		source_address = (byte *)(temp_ptr[Pointer]);
		*(byte *)destination_address = *(byte *)source_address;
		#ifdef PROCESS_PRIORITY
			if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
				SCHED_POLICY (Wptr, temp_ptr);
			} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
				/* we sleep and the other wakes up (go via scheduler for actual change) */
				sf.u.s.priority_sync = 1;
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				/* Wptr[Priority] = PPriority; */
				QUEUE (Wptr);
				K_JUMP (X_scheduler);
			} else {
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
			}
		#else	/* !PROCESS_PRIORITY */
			SCHED_POLICY (Wptr, temp_ptr);
		#endif	/* !PROCESS_PRIORITY */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
	/*}}}*/
#endif	/* ENABLE_FASTCALLS */

/*{{{  void kernel_X_in (void)*/
/*
 *	void kernel_X_in (void)
 *	input
 */
void kernel_X_in (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (X_in, count, channel_address, destination_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_in);
	LOADWPTR;
	LOADRETURN;
	THREEPARAMS(count, channel_address, destination_address);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_in, "%d, %p (ready = %s), %p", count, channel_address, ((*channel_address == NotProcess_p) ? "no" : "yes"), destination_address);
	/* debug*/
	DBGMSG("in: return address = 0x%x\n" \
		"    count = %d\n" \
		"    channel address = 0x%x\n" \
		"    destination address = 0x%x\n", \
		return_address, count, channel_address, \
		destination_address);

	temp_ptr = *channel_address;
	Wptr[Iptr] = return_address;
	if (temp_ptr == NotProcess_p) {
		*channel_address = Wptr;
		Wptr[Pointer] = (word)destination_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP(X_scheduler);
#if defined (OUTPUT_ALTS)
	} else if (temp_ptr[State] <= Ready_p) {
		*channel_address = Wptr;
		if (temp_ptr[State] == Waiting_p) {
			#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) != MaskedPPriority) {
					sf.u.s.priority_sync |= (byte)(PriMasked (temp_ptr[Priority]) < MaskedPPriority);
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				} else {
					QUEUE (temp_ptr);
				}
			#else
				QUEUE (temp_ptr);
			#endif	/* !PROCESS_PRIORITY */
		}
		temp_ptr[State] = Ready_p;
		Wptr[Pointer] = (word)destination_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
#endif
	} else {
		*channel_address = NotProcess_p;
		source_address = (byte*)(temp_ptr)[Pointer];
		/* copy ... */
		#ifdef DONT_USE_MEMCPY
			while (count) {
				*(destination_address++) = *(source_address++);
				count--;
			}
		#else
			MEMCPY(source_address, destination_address, count);
		#endif
		DBGMSG("in: queuing this process and other process.\n");
		#ifdef PROCESS_PRIORITY
			if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
				SCHED_POLICY (Wptr, temp_ptr);
			} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
				/* we sleep and the other wakes up (go via scheduler for actual change) */
				sf.u.s.priority_sync = 1;
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				Wptr[Priority] = PPriority;
				QUEUE (Wptr);
				K_JUMP (X_scheduler);
			} else {
				PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
			}
		#else	/* !PROCESS_PRIORITY */
			SCHED_POLICY (Wptr, temp_ptr);
		#endif	/* !PROCESS_PRIORITY */

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	}
	barrier ();
}
/*}}}*/
#if !defined(TARGET_CPU_SPARC) && !defined(TARGET_CPU_PPC64)
/*{{{  void kernel_X_pause (void)*/
/*
 *	void kernel_X_pause (void)
 *	called on loop-ends (optionally) to reschedule
 */
void kernel_X_pause (void)
{
	K_SETGLABEL (X_pause); /* called on loopend */
	K_JUMP (X_resched);
	barrier ();
}
/*}}}*/
#endif	/* !TARGET_CPU_SPARC */
/*{{{  void kernel_X_resched (void)*/
/*
 *	void kernel_X_resched (void)
 *	reschedule
 */
void kernel_X_resched (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL (X_pause);
	K_SETGLABEL_ZERO_IN_SR (X_resched);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_resched);
	LOADWPTRRET;
	/* LOADWPTR;
	LOADRETURN; */
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_resched);
	#ifdef PROCESS_PRIORITY
	Wptr[Priority] = PPriority;
	#endif
	QUEUE(Wptr);
	/* Inlined stopp more efficient */
	/* Wptr[Iptr] = return_address; */
	DBGMSG("X_resched: Wptr = 0x%x.  Entering scheduler.",Wptr);
	/* Jump on */
	K_JUMP(X_scheduler);
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_stopp (void)*/
/*
 *	void kernel_X_stopp
 *	stop process
 */
void kernel_X_stopp (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ZERO_IN_SR (X_stopp);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_stopp);
	LOADWPTRRET;
	/* LOADWPTR;
	LOADRETURN; */
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_stopp);
	/* Wptr[Iptr] = return_address; */
	#ifdef PROCESS_PRIORITY
	Wptr[Priority] = PPriority;
	#endif
	K_JUMP(X_scheduler);
	barrier ();
}
/*}}}*/

#ifdef ENABLE_FASTCALLS
/*{{{  void kernel_Y_fastscheduler (void)*/
	/*
	 *	void kernel_Y_fastscheduler (void)
	 *	fast scheduler entry point -- doesn't dequeue us, just runs next process
	 */
	void kernel_Y_fastscheduler (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ZERO_IN (Y_fastscheduler);
#else	/* !TARGET_CPU_SPARC */
		K_SETGLABEL (Y_fastscheduler);
		LOADQPTR;
#endif	/* !TARGET_CPU_SPARC */
		ENTRY_TRACE0 (Y_fastscheduler);

		if (NoProcesses ()) {
			K_JUMP (X_scheduler);
		}
		Wptr = GetNextProcess ();
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREJRET;
		/* RESTORE;
		EJUMP (Wptr[Iptr]); */
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
#endif	/* ENABLE_FASTCALLS */

/*{{{  void kernel_X_occscheduler_q (void)*/
void kernel_X_occscheduler_q (void)
{
	K_SETGLABEL_ZERO_IN (X_occscheduler_q);
	ENTRY_TRACE0 (X_occscheduler_q);

	#ifdef PROCESS_PRIORITY
	Wptr[Priority] = PPriority;
	#endif
	QUEUE(Wptr);
	K_JUMP (X_scheduler);
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_occscheduler (void)*/
void kernel_X_occscheduler (void)
{
	K_SETGLABEL_ZERO_IN (X_occscheduler);
	K_JUMP (X_scheduler);
	barrier ();
}
/*}}}*/
/*{{{  OOS stuff -- comment */
#if 0 && defined(OOS_BUILD)
static void show_number (char *here, int stride, unsigned int num)
{
	unsigned int i = num;
	int d;
	char *t = here;

	for (d = 7; d >= 0; d--) {
		if ((i & 0x0f) < 10) {
			t[d*stride] = '0' + (char)(i & 0x0f);
		} else {
			t[d*stride] = 'A' + (char)((i & 0x0f) - 10);
		}
		i >>= 4;
	}
	return;
}
#endif
/*}}}*/
#if defined(OOS_BUILD)
/*{{{  void ccsp_interrupt_handler (int irq, void *data, struct pt_regs *regs)*/
/*
 *	called by a lower level (asynchronously) when an interrupt is received
 *	according to the relevant docs, interrupts are disabled here
 */
void ccsp_interrupt_handler (int irq, void *data)
{
	ticount++;
	intcount[irq]++;
	intlast = irq;

	if (inttab[irq]) {
		/* process waiting, move it onto another queue */
		if (iq_fptr) {
			((word *)iq_bptr)[Link] = (word)(inttab[irq]);
			iq_bptr = inttab[irq];
		} else {
			((word *)(inttab[irq]))[Link] = NotProcess_p;
			iq_fptr = iq_bptr = inttab[irq];
		}
		inttab[irq] = NotProcess_p;
		/* tell the run-time kernel */
		sf.u.s.interrupt_sync = 1;
	}
	return;
}
/*}}}*/
/*{{{  void kernel_Y_ooswaitint (void)*/
/*
 *	void kernel_Y_ooswaitint (void)
 *	entry-point for an OOS process to wait for an interrupt
 *	called from C.oos.wait.int (VAL INT intr, RESULT INT count)
 *	intr is at Wptr[1], count at Wptr[2]
 */
void kernel_Y_ooswaitint (void)
{
	K_SETGLABEL (Y_ooswaitint);
	LOADWPTR;
	LOADRETURN;
	/* PARAM (kr_param); */
	ENTRY_TRACE (Y_ooswaitint, "0x%8.8X", (unsigned int)Wptr + 4);

	if (inttab[Wptr[1]]) {
		MESSAGE ("scheduler: ieee, someone already waiting for this interrupt!\n");
		barrier ();
		/* blind reschedule */
		K_JUMP (X_scheduler);
	}
	OOS_CLI;
	if (!intcount[Wptr[1]]) {
		/* no interrupt yet */
		Wptr[Iptr] = return_address;
		#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
		#endif
		inttab[Wptr[1]] = Wptr;
		OOS_STI;
		K_JUMP (X_scheduler);
	} else {
		*(int *)(Wptr[2]) = intcount[Wptr[1]];
		intcount[Wptr[1]] = 0;
		OOS_STI;
	}
	EJUMP (return_address);
	barrier ();
	return;
}
/*}}}*/
#endif	/* defined(OOS_BUILD) */

/*{{{  void kernel_X_scheduler (void)*/
/*
 *	void kernel_X_scheduler (void)
 *	scheduler proper
 *
 *	This routine cannot be "call'ed" because it doesn't deal with the stack, so
 *	it should never be called from C directly, only from assembler using a jump.
 *	It should not be called externally anyway...
 *	FOOTNOTE: But it is jumped to (now!) from CSPlib in ProcPar().
 *	NOTE: [CSPlib disabled in this scheduler]
 */
void kernel_X_scheduler (void)
{
	K_SETGLABEL (X_scheduler);

	ENTRY_TRACE (X_scheduler, "sync=%d",sf.u.combined_sync);
scheduler_resched:
	DBGMSG("scheduler: called with Wptr = 0x%x.\n", Wptr);
	/*{{{  OOS debugging */
	#if 0 && defined(OOS_BUILD)
	{
		static char *stuff = "-\\|/";
		static int count = 0, i = 0;
		static char *vgabuf = (char *)0xb8000;
		static int first = 100000;

		if (first) {
			first--;

			for (i=0; i<80; i++) {
				vgabuf[(i << 1) + 1] = 0x1f;	/* bright white on blue */
				vgabuf[(i << 1)] = ' ';		/* blank */
			}
		}
		vgabuf[0] = stuff[count++];
		vgabuf[2] = (Tptr == NotProcess_p) ? '.' : 'T';
		vgabuf[6] = (PPriority < 10) ? ('0' + (char)PPriority) : ((PPriority < MAX_PRIORITY_LEVELS) ? 'A' + ((char)(PPriority - 10)) : '!');
		count %= 4;

		now = Time_GetTime ();
		show_number (vgabuf + 10, 2, (unsigned int)now);
		show_number (vgabuf + 30, 2, (unsigned int)glob_cpufactor);
		if (Tptr) {
			show_number (vgabuf + 50, 2, (unsigned int)GetTimeField(Tptr));
		} else {
			for (i = 0; i < 8; i++) {
				vgabuf[50 + (i * 2)] = '-';
			}
		}

		__asm__ __volatile__ ("			\n" \
			"	push %%eax		\n" \
			"	.byte 0x0f, 0x31	\n" \
			"	popl %%eax		\n" \
			: "=d" (now) : : "cc", "memory");
		show_number (vgabuf + 70, 2, (unsigned int)now);

		__asm__ __volatile__ ("			\n" \
			"	push %%edx		\n" \
			"	.byte 0x0f, 0x31	\n" \
			"	popl %%edx		\n" \
			: "=a" (now) : : "cc", "memory");
		show_number (vgabuf + 90, 2, (unsigned int)now);

		show_number (vgabuf + 110, 2, (unsigned int)ticount | ((unsigned int)intlast << 24));

		/* debugging is getting extensive in here.. */
	}
	#endif	/* DEBUG */
	/*}}}*/
	#ifdef ENABLE_CPU_TIMERS
#if 0
LOAD_ESP (the_stackptr);
fprintf (stderr, "X_scheduler: CPU timers enabled (Tptr=0x%8.8x), %%esp = 0x%8.8x\n", (unsigned int)Tptr, (unsigned int)the_stackptr);
#endif
	if (Tptr && Time_PastTimeout()) {
		/*{{{  check for timeouts */
		now = Time_GetTime ();
		while ((Tptr != NotProcess_p) && !Time_AFTER (GetTimeField (Tptr), now)) {
			/* move process from timer queue to run queue */
			temp_ptr = Tptr;
			Tptr = (word *)Tptr[TLink];
			temp_ptr[TLink] = TimeSet_p;
			SetTimeField(temp_ptr, now);
			if (temp_ptr[State] != Ready_p) {
#if 0 && defined(PROCESS_PRIORITY)
fprintf (stderr, "process waking up from timer (State = %d), Pri-field is %d\n", temp_ptr[State], temp_ptr[Priority]);
#endif
				temp_ptr[State] = Ready_p;
				#ifdef PROCESS_PRIORITY
				if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
					QUEUE (temp_ptr);
				} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					sf.u.s.priority_sync = 1;
				} else {
					PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
				}
				#else
				QUEUE (temp_ptr);
				#endif
			}
		}
		if (Tptr != NotProcess_p) {
			Time_SetPastTimeout (Time_MINUS (GetTimeField (Tptr), now));
		}
		/*}}}*/
	}
	#endif
#if 0
LOAD_ESP (the_stackptr);
fprintf (stderr, "X_scheduler: at sync check (combined_sync = 0x%8.8x), %%esp = 0x%8.8x\n", (unsigned int)(sf.u.combined_sync), (unsigned int)the_stackptr);
#endif
	if (sf.u.combined_sync!=0) {
		DBGMSG("scheduler: one of the sync flags has been set.\n");
		/* one of the sync flags has been set */
		#ifndef BLOCKING_SYSCALLS
#ifndef TARGET_CPU_SPARC
			if (sf.u.s.kbd_sync) {
				/*{{{  old keyboard handler*/
				DBGMSG( "scheduler: it was the keyboard sync.\n");
				sf.u.s.kbd_sync = 0;
				K_JUMP (kbd_process);
				/* hmm, curiouser and curiouser -- FIXME: remove keyboard process crap and do pipe IO here. */
				/*}}}*/
			}
#endif	/* !TARGET_CPU_SPARC */
		#endif	/* !BLOCKING_SYSCALLS */
		#ifndef ENABLE_CPU_TIMERS
			if (sf.u.s.tim_sync) {
				/*{{{  timeout alarm */
				sf.u.s.tim_sync = 0;
				now = Time_GetTime();
				/* possible problem in following while loop in 2nd expr */
				while ((Tptr != NotProcess_p) && (!(Time_AFTER(GetTimeField(Tptr),now)))) {
					/* move first process on timer queue to the run queue */
					temp_ptr = Tptr;
					Tptr = (word *)Tptr[TLink];
					temp_ptr[TLink] = TimeSet_p;
					SetTimeField(temp_ptr, now);
					/* GetTimeField(temp_ptr) = now; */
					if (temp_ptr[State] != Ready_p) {
						temp_ptr[State] = Ready_p;
						#ifdef PROCESS_PRIORITY
						if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
							QUEUE (temp_ptr);
						} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
							PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
							sf.u.s.priority_sync = 1;
						} else {
							PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						}
						#else	/* !PROCESS_PRIORITY */
						QUEUE(temp_ptr);
						#endif	/* !PROCESS_PRIORITY */
					}
				}
				if (Tptr != NotProcess_p) {
					Time_SetAlarm( Time_MINUS(GetTimeField(Tptr), now) );
				} else {
					Time_ResetAlarm();
				}
				/*}}}*/
			}
		#endif	/* !ENABLE_CPU_TIMERS */
		#if defined(BLOCKING_SYSCALLS) && !defined(OOS_BUILD)
			if (sf.u.s.block_sync) {
				/*{{{  blocking syscall completion*/
#if 0
fprintf (stderr, "X_scheduler: it was a blocking sys-call :)\n");
#endif
				sf.u.s.block_sync = 0;
				#ifdef BLOCKING_DEBUG
					MESSAGE ("** %s:%d block_sync flag has been set (collect_qhead=%p, &collect_lock=%p).\n", __FILE__, __LINE__, collect_qhead, &collect_lock);
				#endif
				#ifdef BLOCKING_PROFILE
					LOADTIME (collect_time);
					ADDTOBUCKET (bp_finish_collect, signal_time, collect_time);
				#endif
				/* Join in */
#if 0
				barrier ();
				spl_lock (&queue_lock);
				barrier ();
				if (q_fptr) {
					#ifdef BLOCKING_DEBUG
						fprintf (stderr, "** %s:%d In lock q_fptr=0x%8.8x, q_bptr=0x%8.8x, num_queued=%d\n", __FILE__, __LINE__, (int)q_fptr, (int)q_bptr, num_queued);
					#endif
					#ifdef PROCESS_PRIORITY
					while (q_fptr) {
						temp_ptr = (word *)q_fptr[Link];
						if (PriMasked (q_fptr[Priority]) == MaskedPPriority) {
							QUEUE ((word *)q_fptr);
						} else if (PriMasked (q_fptr[Priority]) < MaskedPPriority) {
							PQUEUE(PriMasked ((word)q_fptr[Priority]), (word *)q_fptr);
							sf.u.s.priority_sync = 1;
						} else {
							PQUEUE(PriMasked ((word)q_fptr[Priority]), (word *)q_fptr);
						}
						q_fptr = temp_ptr;
					}
					#else	/* !PROCESS_PRIORITY */
					QUEUE_VQ (q_fptr, q_bptr);
					#endif	/* !PROCESS_PRIORITY */
					q_fptr = NotProcess_p;
					num_spare += num_queued;
					num_queued = 0;
				} else {
					fprintf (stderr, "KRoC: fatal! -- block_sync set, but no processes!\n");
					kernel_panic ();
				}
				#ifdef LINUX_CSPDRIVER
					/* q_mfptr might have some memory for us, tail is q_mbptr */
					if (q_mfptr) {
						bsyscalls_collect_qmem ();
					}
				#endif
				barrier ();
				spl_unlock (&queue_lock);
				barrier ();
#endif
				barrier ();
				spl_lock (&collect_lock);
				spl_lock (&fl_lock);
				barrier ();

				while (collect_qhead) {
					#ifdef BLOCKING_DEBUG
						MESSAGE ("** %s:%d collect_qhead=%p (ws_ptr=%p, raddr=%p, priority=%p).  PPriority=%d\n", __FILE__, __LINE__, collect_qhead, (void *)(collect_qhead->ws_ptr),
								(void *)(collect_qhead->raddr), collect_qhead->pri, (int)PPriority);
					#endif
					temp_ptr = (word *)(collect_qhead->ws_ptr);
					temp_ptr[Iptr] = (word)(collect_qhead->raddr);
					temp_ptr[Link] = NotProcess_p;

					#ifdef PROCESS_PRIORITY
					temp_ptr[Priority] = (word)(collect_qhead->pri);

					if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
						QUEUE (temp_ptr);
					} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
						sf.u.s.priority_sync = 1;
					} else {
						PQUEUE (PriMasked (temp_ptr[Priority]), temp_ptr);
					}
					#else
					QUEUE (temp_ptr);
					#endif

					/* move from collect-queue to free-list */
					if (collect_qhead == collect_qtail) {
						collect_qhead->next = (bsc_jobinfo *)fl_qhead;
						fl_qhead = collect_qhead;
						collect_qhead = NULL;
					} else {
						temp_ptr = (word *)(collect_qhead->next);
						collect_qhead->next = (bsc_jobinfo *)fl_qhead;
						collect_qhead = (bsc_jobinfo *)temp_ptr;
					}
				}

				barrier ();
				spl_unlock (&fl_lock);
				spl_unlock (&collect_lock);
				barrier ();
				#ifdef BLOCKING_DEBUG
					MESSAGE ("** %s:%d going to continue running now...\n", __FILE__, __LINE__);
					MESSAGE ("** first process is 0x%x (Iptr = 0x%x)\n", (unsigned int)Fptr, Fptr ? (unsigned int)(Fptr[Iptr]) : 0);
				#endif
				/*}}}*/
			}
		#endif	/* BLOCKING_SYSCALLS && !OOS_BUILD */
		#if defined(OOS_BUILD)
			if (sf.u.s.interrupt_sync) {
				/*{{{  OOS interrupt occured */
				OOS_CLI;
				temp_ptr = (word *)iq_fptr;
				iq_fptr = NotProcess_p;
				OOS_STI;

				if (temp_ptr) {
					while (temp_ptr) {
						/* temp_ptr[1] is the interrupt number, temp_ptr[2] is a pointer to where the count goes */
						*(int *)(temp_ptr[2]) = intcount[temp_ptr[1]];
						intcount[temp_ptr[1]] = 0;
						previous = (word *)temp_ptr[Link];
						#ifdef PROCESS_PRIORITY
						if (PriMasked (temp_ptr[Priority]) == MaskedPPriority) {
							QUEUE (temp_ptr);
						} else if (PriMasked (temp_ptr[Priority]) < MaskedPPriority) {
							PQUEUE (PriMasked ((word)temp_ptr[Priority]), (word *)temp_ptr);
							sf.u.s.priority_sync = 1;
						} else {
							PQUEUE (PriMasked ((word)temp_ptr[Priority]), (word *)temp_ptr);
						}
						#else	/* !PROCESS_PRIORITY */
						QUEUE (temp_ptr);
						#endif	/* !PROCESS_PRIORITY */
						temp_ptr = previous;
					}
					sf.u.s.interrupt_sync = 0;
				} else {
					MESSAGE ("KRoC: fatal! -- interrupt_sync set, but no processes!\n");
					kernel_panic ();
				}
				/*}}}*/
			}
		#endif	/* OOS_BUILD */
		#ifdef PROCESS_PRIORITY
			if (sf.u.s.priority_sync) {
				/*{{{  something higher than us is probably waiting to be run */
				sf.u.s.priority_sync = 0;

				if ((PPriority == PPEmpty) && !PState) {
					/* nothing to run, select empty queue */
					PPriority = 0;
					LOAD_PRIORITY_QUEUE (MaskedPPriority);
				} else if (PPriority == PPEmpty) {
					PPriority = bsf (PState);
					LOAD_PRIORITY_QUEUE (MaskedPPriority);
				} else {
					/* PPriority != MAX_PRIORITY_LEVELS */
					if (!Fptr) {
						PState &= ~(1 << MaskedPPriority);
					}
					SAVE_PRIORITY_QUEUE (MaskedPPriority);
					PPriority = bsf (PState);
					LOAD_PRIORITY_QUEUE (MaskedPPriority);
				}
				/*}}}*/
			}
		#endif	/* PROCESS_PRIORITY */
	}
	DBGMSG("scheduler: there are processes waiting?\n");
#if 0
	#ifdef BLOCKING_DEBUG
		fprintf (stderr, "%s:%d: run queue state: [Fptr=0x%x, Bptr=0x%x]\n", __FILE__, __LINE__, (int)Fptr, (int)Bptr);
	#endif
#endif
	if (NoProcesses()) {
#if 0
LOAD_ESP (the_stackptr);
fprintf (stderr, "X_scheduler: no processes to run, %%esp = 0x%8.8x\n", (unsigned int)the_stackptr);
#endif
		/*{{{  nothing to run, maybe sleep*/
		DBGMSG( "scheduler: Run queue empty.\n");
		#ifdef PROCESS_PRIORITY
			/* check for anything else to run */
			PState &= ~(1 << MaskedPPriority);
			SAVE_PRIORITY_QUEUE (MaskedPPriority);

			/* PPriority is invalid now. */
			PPriority = PPEmpty;
#if 0
fprintf (stderr, "scheduler: nothing left at priority %d, PState is 0x%8.8x\n", PPriority, PState);
#endif
			if (PState) {
				PPriority = bsf (PState);
				LOAD_PRIORITY_QUEUE (MaskedPPriority);
				goto scheduler_sched_now;	/* sorry.. */
			}
		#endif	/* PROCESS_PRIORITY */
		#if defined(OOS_BUILD)
			if (Tptr == NotProcess_p) {
				kernel_dead (0);
			}
		#else	/* !defined(OOS_BUILD) */
			if ((kbd_chan == NotProcess_p) || addr_in_kbdproc ((word)kbd_chan)) {
				if (Tptr == NotProcess_p) {
					#ifdef BLOCKING_SYSCALLS
						if (!bsyscalls_pending ()) {
							kernel_dead (0);
						} else if (bsyscalls_pending_call ((word)_read_keyboard) && (bsyscalls_pending() == 1)) {
							kernel_dead (0);
						}
					#else	/* !BLOCKING_SYSCALLS */
						kernel_dead (0);
					#endif	/* !BLOCKING_SYSCALLS */
				}
			}
			#ifdef ENABLE_KTRACES
			MESSAGE ("X_scheduler: calling safe_pause{_timeout}()\n");
			#endif
			#ifdef LINUX_CSPDRIVER
				if (cspdriver_enabled) {
					cspdriver_safe_pause ((Tptr == NotProcess_p) ? 0 : Time_MINUS (GetTimeField (Tptr), now));
				} else
			#endif	/* !LINUX_CSPDRIVER */
			#ifdef ENABLE_CPU_TIMERS
				if (Tptr != NotProcess_p) {
					#ifdef ENABLE_KTRACES
					MESSAGE ("X_scheduler: going into safe_pause_timeout (%u)\n", Time_MINUS(GetTimeField(Tptr), now));
					#endif
					safe_pause_timeout (Time_MINUS(GetTimeField(Tptr), now));
					now = Time_GetTime ();							/* with CPU timers, need to update our idea of "now" */
				} else {
					safe_pause ();
				}
			#else
				safe_pause();
			#endif
		#endif	/* !defined(OOS_BUILD) */
		/* okay okay, goto considered harmful etc. (but it's useful) */
		#ifdef PROCESS_PRIORITY
			sf.u.s.priority_sync = 1;
		#endif	/* PROCESS_PRIORITY */
		/*}}}*/
		goto scheduler_resched;
	}
#ifdef PROCESS_PRIORITY
scheduler_sched_now:
#endif
#if 0
LOAD_ESP (the_stackptr);
fprintf (stderr, "X_scheduler: scheduler_sched_now, %%esp = 0x%8.8x\n", (unsigned int)the_stackptr);
#endif
	barrier ();
	Wptr = GetNextProcess();
	ENTRY_TRACE (X_scheduler_dispatch, "sync=%d",sf.u.combined_sync);
	/* FIXME: debugging code */
#if 0
	{
		Wptr[Link] = 0x80000000;
		Wptr[Priority] = 0x80000000;
	}
#endif
	DBGMSG("scheduler: next process continues from 0x%x.\n", return_address);
#if 0
	#ifdef BLOCKING_DEBUG
		fprintf (stderr, "%s:%d: next process 0x%8x continues from 0x%8x [Fptr=0x%x, Bptr=0x%x]\n", __FILE__, __LINE__, (unsigned int)Wptr, (unsigned int)return_address,
			(unsigned int)Fptr, (unsigned int)Bptr);
	#endif
#endif
#if 0
LOAD_ESP (the_stackptr);
fprintf (stderr, "X_scheduler: about to return to occam, %%esp = 0x%8.8x\n", (unsigned int)the_stackptr);
#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT_JRET ();
#else	/* !TARGET_CPU_SPARC */
	RESTOREJRET;
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/

#ifdef ENABLE_FASTCALLS
/*{{{  void kernel_Y_endp (void)*/
	/*
	 *	void kernel_Y_endp (void)
	 *	end process (alternate interface)
	 */
	void kernel_Y_endp (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ONE_IN (Y_endp, usage);
#else
		K_SETGLABEL_ONE_IN (Y_endp, usage);
#endif
		ENTRY_TRACE (Y_endp, "%p", usage);
		usage[Count]--;

#if 0
fprintf (stderr, "EndP: looks like usage[SavedPriority] = 0x%x\n", (unsigned int)(usage[SavedPriority]));
#endif
#if 0 && defined(PROCESS_PRIORITY)
fprintf(stderr, "EndP... usage[SavedPriority] = %d\n", usage[SavedPriority]);
SHOW_QUEUES(stderr);
#endif
		if (usage[Count]) {
			K_JUMP (X_scheduler);
		} else {
			#ifdef PROCESS_PRIORITY
				if (MaskedPPriority != PriMasked (usage[SavedPriority])) {
					/* last ? */
					if (!Fptr) {
						PState &= ~(1 << MaskedPPriority);
					}
					SAVE_PRIORITY_QUEUE (MaskedPPriority);
					PPriority = usage[SavedPriority];
					LOAD_PRIORITY_QUEUE (MaskedPPriority);
					PState |= (1 << MaskedPPriority);
				}
			#endif
			Wptr = usage;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT_IRET ();
#else	/* !TARGET_CPU_SPARC */
			RESTOREIRET;
#endif	/* !TARGET_CPU_SPARC */
		}
		barrier ();
	}
/*}}}*/
#endif	/* ENABLE_FASTCALLS */

/*{{{  void kernel_X_endp (void)*/
/*
 *	void kernel_X_endp (void)
 *	end process
 */
void kernel_X_endp (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_endp, usage);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_endp);
	LOADWPTR;
	LOADRETURN; /* junk the return address */
	PARAM(usage); /* Wptr becomes successor_workspace */
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_endp, "%p", usage);
	usage[Count]--;
	if (usage[Count]) {
		DBGMSG ("endp: more to go.\n");
		K_JUMP(X_scheduler); /* Wptr is workspace so we don't need to set up ebp */
	} else {
		DBGMSG ("endp: last one, setting Wptr = %p\n", usage);
		#ifdef PROCESS_PRIORITY
			if (MaskedPPriority != PriMasked (usage[SavedPriority])) {
				/* last ? */
				if (!Fptr) {
					PState &= ~(1 << MaskedPPriority);
				}
				SAVE_PRIORITY_QUEUE (MaskedPPriority);
				PPriority = usage[SavedPriority];
				LOAD_PRIORITY_QUEUE (MaskedPPriority);
				PState |= (1 << MaskedPPriority);
			}
		#endif
		Wptr = usage; /* added to correctly update WPtr 091198 */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT_IRET ();
#else	/* !TARGET_CPU_SPARC */
		RESTOREIRET;
#endif	/* !TARGET_CPU_SPARC */
	}
	barrier ();
}
/*}}}*/

#ifdef ENABLE_FASTCALLS
/*{{{  void kernel_Y_startp (void)*/
	/*
	 *	void kernel_Y_startp (void)
	 *	start process
	 */
	void kernel_Y_startp (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_TWO_IN (Y_startp, other_workspace, start_offset);
#else
		K_SETGLABEL_THREE_IN (Y_startp, other_workspace, start_offset, return_address);
#endif
		ENTRY_TRACE (Y_startp, "%p, %d", other_workspace, start_offset);

		other_workspace[Iptr] = start_offset + return_address;
		#ifdef PROCESS_PRIORITY
		other_workspace[Priority] = PPriority;
		#endif
		QUEUE(other_workspace);
#if defined(PROCESS_GROUPS)
		PGroupOf(PPriority)->nprocs++;
#endif	/* defined(PROCESS_GROUPS) */
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
		RESTORE;
		EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
#endif	/* ENABLE_FASTCALLS */

/*{{{  void kernel_X_startp (void)*/
/*
 *	void kernel_X_startp (void)
 *	start process
 */
void kernel_X_startp (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_startp, other_workspace, start_offset);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_startp);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS(other_workspace, start_offset);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_startp, "%p, %d", other_workspace, start_offset);
	DBGMSG("startp: called with other_workspace = 0x%x, offset = 0x%x\n", other_workspace, start_offset);
	other_workspace[Iptr] = start_offset+return_address;
	#ifdef PROCESS_PRIORITY
	other_workspace[Priority] = PPriority;
	#endif
	QUEUE(other_workspace);
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/

#ifdef ENABLE_FASTCALLS
/*{{{  void kernel_Y_runp (void)*/
	/*
	 *	void kernel_Y_runp (void)
	 *	run process (fast interface)
	 */
	void kernel_Y_runp (void)
	{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_SETGLABEL_ONE_IN (Y_runp, other_workspace);
#else
		K_SETGLABEL_TWO_IN (Y_runp, other_workspace, return_address);
#endif
		ENTRY_TRACE (Y_runp, "%p", other_workspace);
		other_workspace = (word *)(((word)other_workspace) & (0xfffffffe));
		#ifdef PROCESS_PRIORITY
			if (PriMasked (other_workspace[Priority]) > MaskedPPriority) {
				PQUEUE (PriMasked (other_workspace[Priority]), other_workspace);
			} else if (PriMasked (other_workspace[Priority]) < MaskedPPriority) {
				PQUEUE (PriMasked (other_workspace[Priority]), other_workspace);
				sf.u.s.priority_sync = 1;
			} else {
				QUEUE (other_workspace);
			}
		#else
		QUEUE (other_workspace);
		#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
		RESTORE;
		EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
		barrier ();
	}
/*}}}*/
#endif	/* ENABLE_FASTCALLS */

/*{{{  void kernel_X_runp (void)*/
/*
 *	void kernel_X_runp (void)
 *	run process
 */
void kernel_X_runp (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_runp, other_workspace);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_runp);
	LOADWPTR;
	LOADRETURN;
	PARAM(other_workspace);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_runp, "%p", other_workspace);
	other_workspace = (word *)(((word)other_workspace) & (0xfffffffe));
	#ifdef PROCESS_PRIORITY
		if (PriMasked (other_workspace[Priority]) > MaskedPPriority) {
			PQUEUE (PriMasked (other_workspace[Priority]), other_workspace);
		} else if (PriMasked (other_workspace[Priority]) < MaskedPPriority) {
			PQUEUE (PriMasked (other_workspace[Priority]), other_workspace);
			sf.u.s.priority_sync = 1;
		} else {
			QUEUE (other_workspace);
		}
	#else
	QUEUE(other_workspace);
	#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_ldtimer (void)*/
/*
 *	void kernel_X_ldtimer (void)
 *	load timer
 */
void kernel_X_ldtimer (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ZERO_IN (X_ldtimer);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_ldtimer);
	LOADWPTR;
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_ldtimer);
	now = Time_GetTime();
	DBGMSG( "ldtimer: now = %d.\n", now);
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (now);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(now);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_tin (void)*/
/*
 *	void kernel_X_tin (void)
 *	timer input (delay)
 */
void kernel_X_tin (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_tin, wait_time);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_tin);
	LOADWPTR;
	LOADRETURN;
	PARAM (wait_time);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_tin, "%d", wait_time);

	now = Time_GetTime();
	DBGMSG( "tin: now= %d  ", now );
	DBGMSG( "wait_time= %d\n", wait_time );

	if (Time_AFTER (now, wait_time)) {
		DBGMSG( "tin: timer expired, returning to caller.\n");
		DBGMSG( "tin: wait time is %d, ", wait_time );
		DBGMSG( "now is %d, ", now );
		DBGMSG( "now-wt = %d,", (now-wait_time) );
		DBGMSG( "now-wt > 0 = %d\n", ((now-wait_time)>0) );
		#if 0
			fprintf(stderr, "tin: now-wait_time >0.\n");
		#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
		RESTORE;
		EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	}
	Wptr[Iptr] = return_address;
	Wptr[State] = Waiting_p; /* T9000 book says enabling */
	#ifdef PROCESS_PRIORITY
	Wptr[Priority] = PPriority;
	#endif
	wait_time++; /* from T9000 book... */
	SetTimeField(Wptr, wait_time);
	/* start of pseudo code in SPARC code */
	current = Tptr;
	previous = NotProcess_p;
	while ((current != NotProcess_p) && (Time_AFTER(wait_time,GetTimeField(current)))) {
		previous = current;
		current = (word *)current[TLink];
	}
	Wptr[TLink] = (word)current;
	if (previous != NotProcess_p) {
		previous[TLink] = (word)Wptr;
	} else {
		Tptr = Wptr;
		#ifdef ENABLE_CPU_TIMERS
			Time_SetPastTimeout (Time_MINUS (GetTimeField (Tptr), now));
		#else
			DBGMSG( "tin: setting alarm with delay %d.", (GetTimeField(Tptr)) - now);
			Time_SetAlarm(Time_MINUS(GetTimeField(Tptr), now));
		#endif
	}
	K_JUMP(X_scheduler);
	barrier ();
}
/*}}}*/
#ifdef ENABLE_FASTCALLS
/*{{{  void kernel_Y_fasttin (void)*/
/*
 *	void kernel_Y_fasttin (void)
 */
void kernel_Y_fasttin (void)
{
	K_SETGLABEL_ONE_IN (Y_fasttin, wait_time);
	ENTRY_TRACE (Y_fasttin, "%d", wait_time);
	#ifdef PROCESS_PRIORITY
	Wptr[Priority] = PPriority;
	#endif

	#ifdef ENABLE_CPU_TIMERS
	now = Time_GetTime();
	#endif
	current = Tptr;
	previous = NotProcess_p;

	while ((current != NotProcess_p) && (Time_AFTER (wait_time, GetTimeField (current)))) {
		previous = current;
		current = (word *)(current[TLink]);
	}
	Wptr[TLink] = (word)current;
	if (previous != NotProcess_p) {
		previous[TLink] = (word)Wptr;
	} else {
		Tptr = Wptr;
		#ifdef ENABLE_CPU_TIMERS
			Time_SetPastTimeout (Time_MINUS (GetTimeField (Tptr), now));
		#endif
	}
	K_JUMP (X_scheduler);
	barrier ();
}
/*}}}*/
#endif
/*{{{  void kernel_X_altstart (void)*/
/*
 *	void kernel_X_altstart (void)
 *	ALT start
 *	NOT USED AT PRESENT  [inlined in tranx86]
 */
void kernel_X_altstart (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ZERO_IN (X_altstart);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_altstart);
	LOADRETURN;
	LOADWPTR;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_altstart);
	Wptr[State] = Enabling_p;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_altend (void)*/
/*
 *	void kernel_X_altend (void)
 *	ALT end
 *	NOT USED AT PRESENT  [inlined in tranx86]
 */
void kernel_X_altend (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ZERO_IN (X_altend);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_altend);
	LOADWPTR;
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_altend);
	DBGMSG("altend: called.\n");
	return_address += Wptr[Temp];
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_altwt (void)*/
/*
 *	void kernel_X_altwt (void)
 *	ALT wait
 */
void kernel_X_altwt (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ZERO_IN (X_altwt);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_altwt);
	LOADWPTR;
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_altwt);
	DBGMSG("altwt: called.\n");
	Wptr[Temp] = NoneSelected_o;
	if (Wptr[State] == Ready_p) {
		DBGMSG("altwt: guard is Ready_p.  Returning to caller.\n");
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
		RESTORE;
		EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	} else {
		DBGMSG( "altwt: guard is not Ready_p.   Decheduling current process.\n");
		Wptr[State] = Waiting_p;
		Wptr[Iptr] = return_address;
		#ifdef PROCESS_PRIORITY
		Wptr[Priority] = PPriority;
		#endif
		K_JUMP (X_scheduler);
	}
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_taltwt (void)*/
/*
 *	void kernel_X_taltwt (void)
 *	timer ALT wait
 */
void kernel_X_taltwt (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ZERO_IN (X_taltwt);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_taltwt);
	LOADWPTR;
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE0 (X_taltwt);
	DBGMSG( "taltwt: called.\n");
	Wptr[Temp] = NoneSelected_o;
	if (Wptr[State] == Ready_p) {
		DBGMSG("taltwt: State is Ready_p so Wptr[Time_f] = now.\n");
		now = Time_GetTime ();
		SetTimeField (Wptr, now);
	} else {
		if (Wptr[TLink] == TimeNotSet_p) {
			DBGMSG("taltwt: TLink is TimeNotSet_p.  Descheduling.\n");
			Wptr[State] = Waiting_p;
			Wptr[Iptr] = return_address;
			#ifdef PROCESS_PRIORITY
			Wptr[Priority] = PPriority;
			#endif
			K_JUMP (X_scheduler);
		} else {
			DBGMSG("taltwt: TLink is TimeSet_p.\n");
			now = Time_GetTime();
			if (Time_AFTER(now, GetTimeField(Wptr))) { /* now AFTER Wptr^[Time_f] */
				DBGMSG("taltwt: now AFTER Wptr[Time_f].\n");
				Wptr[State] = Ready_p;                     /* from T9000 Instruction */
				SetTimeField (Wptr, now);                  /* Set p.436 */
			} else {
				DBGMSG("taltwt: now is not AFTER Wptr[Time_f].");
				DBGMSG("Inserting this process into timer queue.\n");
				IncTimeField (Wptr);
				/* ... insert this process in timer queue */
				current = Tptr;
				previous = (word *)NotProcess_p;
				while ( (current != NotProcess_p) &&
					(Time_AFTER(GetTimeField(Wptr), GetTimeField(current)))
					) {
					previous = current; /* deduce: previous <> NotProcess_p */
					current = (word *)current[TLink];
				}
				Wptr[TLink] = (word)current;
				if (previous != NotProcess_p) { /* iff: current <> Tptr */
					DBGMSG("taltwt: Inserting in middle of queue.\n");
					previous[TLink] = (word)Wptr;       /* insert in middle of queue */
				} else {
					DBGMSG("taltwt: Inserting at head of queue (and setting alarm).\n");
					DBGMSG("taltwt: Wptr[Time_f] = %d, now = %d", Wptr[Time_f], now);
					Tptr = Wptr;                  /* insert at head of queue */
					#ifdef ENABLE_CPU_TIMERS
						Time_SetPastTimeout (Time_MINUS (GetTimeField (Tptr), now));
					#else
						Time_SetAlarm(Time_MINUS(GetTimeField(Tptr), now));
					#endif
				}
				/* ... end insert */
				if (Wptr[State] != Ready_p) { /* redundant ? */
					#ifdef DEBUG_KERNEL
						DBGMSG("taltwt: Wptr[State] is not Ready_p, set to Waiting_p");
						DBGMSG("and deschedule.\n");
					#endif
					Wptr[State] = Waiting_p; /* see altwt */
					Wptr[Iptr] = return_address;
					#ifdef PROCESS_PRIORITY
					Wptr[Priority] = PPriority;
					#endif
					K_JUMP (X_scheduler);
				} else {
					impossible(1, return_address);
				}
			}
		}
	}
	DBGMSG( "taltwt:exiting to caller.\n");
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_dist (void)*/
/*
 *	void kernel_X_dist (void)
 *	disable timer
 */
void kernel_X_dist (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (X_dist, code_offset, precondition, timeout);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_dist);
	LOADWPTR;
	LOADRETURN;
	THREEPARAMS(code_offset, precondition, timeout);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_dist, "%d, %d, %d", code_offset, precondition, timeout);
	DBGMSG( "dist: entered.\n");
	if (!precondition) {
		DBGMSG( "dist: precondition is false.\n");
		parm_result = false;
		goto _dist_out;
	} else {
		DBGMSG( "dist: precondition is true.\n");
		if (Wptr[TLink] == TimeNotSet_p) {
			DBGMSG( "dist: no timer is ready.\n");
			parm_result = false;
			goto _dist_out;
		} else {
			if (Wptr[TLink] == TimeSet_p) {
				DBGMSG( "dist: some timer is ready...\n");
				/* some timer has gone off */
				precondition = Time_AFTER (GetTimeField (Wptr), (Time)timeout);
				if (!precondition) {
					DBGMSG( "dist: ... but not this one.");
					parm_result = false;
				} else {
					if (Wptr[Temp] != NoneSelected_o) {
						DBGMSG("dist: a previous guard was selected.\n");
						parm_result = false;
					} else {
						DBGMSG("dist: This is the first ready guard.\n");
						Wptr[Temp] = code_offset;
						parm_result = true;
					}
				}
				goto _dist_out;
			} else {
				/* cancel timer*/
				DBGMSG("dist: strage else condition - remove process from tq.\n");
				parm_result = false;
				/* remove process from timer queue */
				if (Tptr == Wptr) {
					DBGMSG( "dist: Process is at head of timer Q.\n");
					Tptr = (word *)Tptr[TLink];
					if (Tptr != NotProcess_p) {
						DBGMSG("dist: there is something else on the timer queue.\n");
						#ifndef ENABLE_CPU_TIMERS
							/* Tptr[Link] = NotProcess_p -- commented out in comment! */
							now = Time_GetTime();
							if (!(Time_AFTER(GetTimeField(Wptr), now))) { /*should be same as */
								/*if (((int)Tptr[Time_f] - now) <= 0) { */
								DBGMSG("dist: time out has happened.  Setting timer sync.\n");
								sf.u.s.tim_sync = 1;
							} else {
								DBGMSG("dist: timeout not happened yet, set alarm.\n");
								Time_SetAlarm(Time_MINUS(GetTimeField(Tptr), now));
							}
						#endif
					}
				} else {
					if (Tptr == NotProcess_p) {
						impossible(3, return_address);
					} else {
						DBGMSG( "dist: searching timer queue from 2nd element.\n");
						previous = Tptr; /* search from 2nd item on timer queue */
						current = (word *)Tptr[TLink];
						while ((current != NotProcess_p) && (current != Wptr)) {
							DBGMSG( "dist: onto next item...\n");
							previous = current;
							current = (word *)current[TLink];
						}
						if (current == NotProcess_p) {
							impossible(4, return_address);
						}
						/* deduce: current == Wptr */
						previous[TLink] = Wptr[TLink];
					}
				}
				DBGMSG("dist: Timer cancelled.\n");
				Wptr[TLink] = TimeNotSet_p; /* i.e. timer cancelled */
			}
		}
	}
_dist_out:
	ENTRY_TRACE0 (X_dist_out);
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (parm_result);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(parm_result);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_ndist (void)*/
/*
 *	void kernel_X_ndist (void)
 *	disable timer
 */
void kernel_X_ndist (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (X_ndist, process_address, guard, timeout);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_ndist);
	LOADWPTR;
	LOADRETURN;
	THREEPARAMS (process_address, guard, timeout);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_ndist, "%d, %d, %d", process_address, guard, timeout);

	if (!guard) {
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
		RETURNVAL (guard);
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	}
	if (Wptr[TLink] == TimeNotSet_p) {
		/* no timer ready */
		fired = false;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ONE_OUT (fired);
#else	/* !TARGET_CPU_SPARC */
		RETURNVAL (fired);
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	}
	if (Wptr[TLink] == TimeSet_p) {
		/* some timer went off */
		if (Time_AFTER (GetTimeField (Wptr), (Time)timeout)) {
			Wptr[Temp] = process_address;
			fired = true;
		} else {
			fired = false;
		}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ONE_OUT (fired);
#else	/* !TARGET_CPU_SPARC */
		RETURNVAL (fired);
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	}
	/* cancel timer */
	if (Tptr == Wptr) {
		Tptr = (word *)Tptr[TLink];
		if (Tptr != NotProcess_p) {
			#ifndef ENABLE_CPU_TIMERS
				now = Time_GetTime ();
				if (!(Time_AFTER (GetTimeField (Tptr), now))) {
					sf.u.s.tim_sync = 1;
				} else {
					Time_SetAlarm (Time_MINUS (GetTimeField (Tptr), now));
				}
			#endif
			#ifdef ENABLE_CPU_TIMERS
				/* removing first process from timer queue, so fixup sf.ftime */
				now = Time_GetTime ();
				if (Time_AFTER (GetTimeField (Tptr), now)) {
					Time_SetPastTimeout (Time_MINUS (GetTimeField (Tptr), now));
				}
			#endif
		}
	} else if (Tptr == NotProcess_p) {
		impossible (3, return_address);
	} else {
		previous = Tptr;
		current = (word *)Tptr[TLink];

		while ((current != NotProcess_p) && (current != Wptr)) {
			previous = current;
			current = (word *)current[TLink];
		}
		if (current == NotProcess_p) {
			impossible (4, return_address);
		}
		/* deduce/assume: current == Wptr */
		previous[TLink] = Wptr[TLink];
	}
	Wptr[TLink] = TimeNotSet_p;
	fired = false;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (fired);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL (fired);
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_enbs (void)*/
/*
 *	void kernel_X_enbs (void)
 *	enable skip guard
 *	NOT USED AT PRESENT  [inlined by tranx86]
 */
void kernel_X_enbs (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (X_enbs, guard);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_enbs);
	LOADWPTR;
	LOADRETURN;
	PARAM(guard);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_enbs, "%d", guard);
	if (guard) {
		Wptr[State] = Ready_p;
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(guard);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_enbc (void)*/
/*
 *	void kernel_Y_enbc (void)
 *	enable channel
 */
void kernel_Y_enbc (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (Y_enbc, guard, channel_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (Y_enbc, guard, channel_address);
	/* LOADWPTR; */
	LOADRETURN;
	/* TWOPARAMS(guard, channel_address); */
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (Y_enbc, "%d, %p (ready = %d)", guard, channel_address, guard && (*channel_address != NotProcess_p) && (*channel_address != Wptr));
	DBGMSG("enbc: guard = %d, channel address = 0x%x\n", guard, channel_address);
	if (guard) {
		if (*channel_address == NotProcess_p) {
			DBGMSG ("enbc: *channel_address == NotProcess_p, putting Wptr in channel\n");
			/* *channel_address = (word *)((word)Wptr | 1); */
			*channel_address = Wptr;
		} else {
			DBGMSG ("enbc: channel has process descriptor (%p)\n", (void *)*channel_address);
			/* if (*channel_address != (word *)((word)Wptr | 1)) */
			if (*channel_address != Wptr) {
				DBGMSG ("enbc: channel has descriptor (not us), setting Wptr[State] = Ready_p\n");
				Wptr[State] = Ready_p;
			}
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(guard);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_enbc3 (void)*/
/*
 *	void kernel_Y_enbc3 (void)
 *	enable channel (with ready address)
 */
void kernel_Y_enbc3 (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (Y_enbc3, process_address, guard, channel_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_THREE_IN(Y_enbc3, process_address, guard, channel_address);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (Y_enbc3, "%d, %p (ready = %d), %p", guard, channel_address, guard && (*channel_address != NotProcess_p) && (*channel_address != Wptr), (void *)process_address);
	if (guard) {
		if (*channel_address == NotProcess_p) {
			*channel_address = Wptr;
		} else if (*channel_address != Wptr) {
			Wptr[State] = Ready_p;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
			RESTORE;
			EJUMP (process_address);
#endif	/* !TARGET_CPU_SPARC */
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL (guard);
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_enbt (void)*/
/*
 *	void kernel_X_enbt (void)
 *	enable timer
 */
void kernel_X_enbt (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_enbt, guard, timeout);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_enbt);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS(guard, timeout);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_enbt, "%d, %d", guard, timeout);
	DBGMSG("enbt: entered. timeout = %d\n", timeout);
	if (guard) {
		if (Wptr[TLink] == TimeNotSet_p) {
			DBGMSG( "enbt: This is the first enbt.\n");
			Wptr[TLink] = TimeSet_p;
			SetTimeField (Wptr, (Time)timeout);
		} else {
			DBGMSG( "enbt: This is not the first enbt.\n");
			if (Wptr[TLink] == TimeSet_p) {
				if (Time_AFTER(GetTimeField(Wptr), (Time)timeout)) {
					#ifdef DEBUG_KERNEL
						DBGMSG( "enbt: This enbt has an earlier time.\n");
					#endif
					SetTimeField (Wptr, (Time)timeout);
				}
			}
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(guard);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_enbt3 (void)*/
/*
 *	void kernel_Y_enbt3 (void)
 *	enable timer (with ready address)
 */
void kernel_Y_enbt3 (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (Y_enbt3, process_address, guard, timeout);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_THREE_IN(Y_enbt3, process_address, guard, timeout);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (Y_enbt3, "%d, %d, %p", guard, timeout, (void *)process_address);
	if (guard) {
		now = Time_GetTime ();

		if (Wptr[TLink] == TimeNotSet_p) {
			Wptr[TLink] = TimeSet_p;
			SetTimeField (Wptr, (Time)timeout);
		} else if (Wptr[TLink] == TimeSet_p) {
			if (Time_AFTER (GetTimeField (Wptr), (Time)timeout)) {
				SetTimeField (Wptr, (Time)timeout);
			}
		}
		if ((Wptr[TLink] == TimeSet_p) && Time_AFTER (now, GetTimeField (Wptr))) {
			/* the earliest timeout has already passed, jump to disabling part */
			Wptr[State] = Ready_p;
			SetTimeField (Wptr, now);
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
			K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
			RESTORE;
			EJUMP (process_address);
#endif	/* !TARGET_CPU_SPARC */
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL (guard);
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_disc (void)*/
/*
 *	void kernel_Y_disc (void)
 *	disable channel
 */
void kernel_Y_disc (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (Y_disc, process_address, guard, channel_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_THREE_IN (Y_disc, process_address, guard, channel_address);
	/* LOADWPTR; */
	LOADRETURN;
	/* THREEPARAMS(process_address, guard, channel_address); */
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (Y_disc, "%p, %d, %p", (void *)process_address, guard, channel_address);
	DBGMSG( "disc: process_offset = 0x%x, guard = %d, channel address = 0x%x\n", process_address, guard, channel_address);
	if (!guard) {
		fired = false;
	} else {
		if (*channel_address == NotProcess_p) {
			fired = false;
		} else {
			/* if (*channel_address == (word *)((word)Wptr | 1)) */
			if (*channel_address == Wptr) {
				*channel_address = NotProcess_p;
				fired = false;
			} else {
				if (Wptr[Temp] == NoneSelected_o) {
					Wptr[Temp] = process_address; /* actually offset */
					fired = true;
				} else {
					fired = false;
				}
			}
		}
	}
	#ifdef DEBUG_KERNEL
		DBGMSG( "disc: fired = %d.\n", fired);
	#endif
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (fired);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(fired);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_ndisc (void)*/
/*
 *	void kernel_Y_ndisc (void)
 *	disable channel
 */
void kernel_Y_ndisc (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (Y_ndisc, process_address, guard, channel_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_THREE_IN (Y_ndisc, process_address, guard, channel_address);
	/* LOADWPTR; */
	LOADRETURN;
	/* THREEPARAMS (process_address, guard, channel_address); */
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (Y_ndisc, "%p, %d, %p", (void *)process_address, guard, channel_address);
	if (!guard) {
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
		RETURNVAL (guard);
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	}
	if ((*channel_address == Wptr) || (*channel_address == NotProcess_p)) {
		*channel_address = NotProcess_p;
		fired = false;
	} else {
		Wptr[Temp] = process_address;	/* actually offset */
		fired = true;
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (fired);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL (fired);
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_diss (void)*/
/*
 *	void kernel_X_diss (void)
 *	disable SKIP guard
 */
void kernel_X_diss (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_diss, process_address, guard);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_diss);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS(process_address, guard);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_diss, "%p, %d", (void *)process_address, guard);
	#ifdef DEBUG_KERNEL
		DBGMSG( "diss: entered.\n");
	#endif
	if (!guard) {
		fired = false;
	} else {
		if (Wptr[Temp] != NoneSelected_o) {
			fired = false;
		} else {
			Wptr[Temp] = process_address;
			fired = true;
		}
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (fired);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL(fired);
	RESTORE;
	EJUMP(return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_X_ndiss (void)*/
/*
 *	void kernel_X_ndiss (void)
 *	disables SKIP guard
 */
void kernel_X_ndiss (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (X_ndiss, process_address, guard);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL (X_ndiss);
	LOADWPTR;
	LOADRETURN;
	TWOPARAMS (process_address, guard);
#endif	/* !TARGET_CPU_SPARC */
	ENTRY_TRACE (X_ndiss, "%p, %d", (void *)process_address, guard);

	if (!guard) {
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
		K_ONE_OUT (guard);
#else	/* !TARGET_CPU_SPARC */
		RETURNVAL (guard);
		RESTORE;
		EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	}
	Wptr[Temp] = process_address;
	fired = 1;
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (fired);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL (fired);
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/

/*{{{  void kernel_Y_ldwsmap (void)*/
/*
 *	load workspace-map
 */
void kernel_Y_ldwsmap (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (Y_ldwsmap, process_address, code_offset);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (Y_ldwsmap, process_address, code_offset);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */

	mpcb_add_wsmap ((mp_ctrlblk *)process_address, (unsigned char *)code_offset);

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_ulwsmap (void)*/
/*
 *	unload workspace-map
 */
void kernel_Y_ulwsmap (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_TWO_IN (Y_ulwsmap, process_address, code_offset);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_TWO_IN (Y_ulwsmap, process_address, code_offset);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */

	mpcb_del_wsmap ((mp_ctrlblk *)process_address, (unsigned char *)code_offset);

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_rmwsmap (void)*/
/*
 *	delete workspace-map
 */
void kernel_Y_rmwsmap (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (Y_rmwsmap, process_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_ONE_IN (Y_rmwsmap, process_address);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */

	mpcb_rm_wsmap ((mp_ctrlblk *)process_address);

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_mppclone (void)*/
/*
 *	clone mobile process
 */
void kernel_Y_mppclone (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_ONE_IN (Y_mppclone, process_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_ONE_IN (Y_mppclone, process_address);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */

	process_address = (word)mpcb_mpp_clone ((mp_ctrlblk *)process_address);
	if (process_address == NotProcess_p) {
		MESSAGE ("KRoC: mobile process CLONE error at 0x%x, Wptr = 0x%x.\n", return_address, (unsigned int)Wptr);
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ONE_OUT (process_address);
#else	/* !TARGET_CPU_SPARC */
	RETURNVAL (process_address);
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_mppserialise (void)*/
/*
 *	serialise mobile process
 */
void kernel_Y_mppserialise (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (Y_mppserialise, count, destination_address, channel_address);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_THREE_IN (Y_mppserialise, count, destination_address, channel_address);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */

	/* actually pass a pointer to it, may need to nullify */
	process_address = ((word *)(*channel_address))[Pointer];
	if (!mpcb_mpp_serialise ((mp_ctrlblk **)process_address, (unsigned int *)process_address + 1, (int *)destination_address, (int *)count)) {
		MESSAGE ("KRoC: mobile process serialise error at 0x%x, Wptr = 0x%x.\n", return_address, (unsigned int)Wptr);
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/
/*{{{  void kernel_Y_mppdeserialise (void)*/
/*
 *	deserialise mobile process
 */
void kernel_Y_mppdeserialise (void)
{
#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_SETGLABEL_THREE_IN (Y_mppdeserialise, channel_address, source_address, count);
#else	/* !TARGET_CPU_SPARC */
	K_SETGLABEL_THREE_IN (Y_mppdeserialise, channel_address, source_address, count);
	LOADRETURN;
#endif	/* !TARGET_CPU_SPARC */

	/* pass a pointer to the ws locn */
	process_address = ((word *)(*channel_address))[Pointer];
	if (!mpcb_mpp_deserialise ((int)source_address, (int)count, (mp_ctrlblk **)process_address, (unsigned int *)process_address + 1)) {
		MESSAGE ("KRoC: mobile process serialise error at 0x%x, Wptr = 0x%x.\n", return_address, (unsigned int)Wptr);
		if (_occam_errormode) {
			K_JUMP (X_scheduler);
		}
		occam_exit (1, return_address);
	}

#if defined(TARGET_CPU_SPARC) || defined(TARGET_CPU_PPC64)
	K_ZERO_OUT ();
#else	/* !TARGET_CPU_SPARC */
	RESTORE;
	EJUMP (return_address);
#endif	/* !TARGET_CPU_SPARC */
	barrier ();
}
/*}}}*/


