home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacFormat 1994 November
/
macformat-018.iso
/
Utility Spectacular
/
Developer
/
macgambit-20-compiler-src-p2
/
Runtime (.scm & .s)
/
_kernel.s
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
Text File
|
1994-07-26
|
124.3 KB
|
5,526 lines
|
[
TEXT/gamI
]
/*---------------------------------------------------------------------------*/
/* file: "_kernel.s" */
/*-----------------------------------------------------------------------------
GAMBIT kernel.
This file should be assembled with 'AS' to produce '_kernel.O'.
'kernel.O' is the first object file to be loaded into the system. The
first object in the file (which must be a procedure) is responsible
for setting up the runtime context and running all the other modules
that were loaded. This procedure is special because it uses the C
calling convention.
-----------------------------------------------------------------------------*/
/* Main parameters: */
/* Define MIN_C_CONTEXT if C's context is kept only in A5, A6 and SP */
#define MIN_C_CONTEXT
/* Define DETERMINE_IS_STRICT if 'determine!' should touch its second arg */
#define DETERMINE_IS_STRICT
#define LIGITIMACY
/* Define MESSAGE_PASSING_STEAL if tasks are stolen with message passing */
/* protocol (otherwise, shared memory protocol is used) */
#define MESSAGE_PASSING_STEAL
/* Define SYNCHRONOUS_STEAL if thief processor waits for reply from victim */
#define SYNCHRONOUS_STEAL
/* Define MAINTAIN_TASK_STATUS if the status of the tasks should be updated. */
/* There are 4 possible states: READY to run (status=pointer to queue entry),*/
/* RUNNING (status=pointer to processor state), WAITING (status=null) and */
/* DEAD (status=false). */
#define MAINTAIN_TASK_STATUS
/* MAX_FRAME_CHUNK_SIZE is the maximum number of slots in a stack frame */
/* chunk (i.e. a group of contiguous stack frames) */
#define MAX_FRAME_CHUNK_SIZE 25
#define MAX_FRAME_CHUNK_SIZEzzz 1024
/* MAX_TASK_FRAME_CHUNK_SIZE is the maximum number of slots in a stack frame */
/* chunk which contains lazy tasks. MIN_VICTIM_TASKS is the minimum number */
/* of lazy tasks to leave the victim when there is a steal of more than one */
/* task. */
#define MAX_TASK_FRAME_CHUNK_SIZEzzz 25
#define MIN_VICTIM_TASKSzzz 20
#define MAX_TASK_FRAME_CHUNK_SIZE 25
#define MIN_VICTIM_TASKS 20
/* Interrupt checking latencies (1 = soonest possible) */
#define INTR_LATENCY_AFTER_STEAL 5
/*---------------------------------------------------------------------------*/
/* DYN_ENV_FS is the size of a dynamic environment frame */
#define DYN_ENV_FS 2
/*---------------------------------------------------------------------------*/
/* String concatenation depends on style of preprocessing... */
#ifdef __STDC__
#define MAKE_LBL(x,y)y##__##x
#else
#define QUOTE(x)x
#define MAKE_LBL(x,y)QUOTE(QUOTE(y)__)x
#endif
#ifdef hpux
/* HPUX assembler definitions... */
#define OBJECT_FILE_BEGIN _object_file_begin: global _object_file_begin
#define OBJECT_FILE_END _object_file_end: global _object_file_end
#define DISP(r,n) n(r)
#define INXW(r,i,n) n(r,i.w)
#define PC_IND(lab) LBL(lab)(%pc)
#define ALIGN2 lalign 2
#define ALIGN4 lalign 4
#define ALIGN8 lalign 8
#define SET(a,b) set a,b
#define CONST(n) LBL($consts)+(n*4)(%pc)
#define REG(x) %x
#define IMM(x) &x
#define PINC(r) (r)+
#define PDEC(r) -(r)
#define IND(r) (r)
#define BYTE byte
#define WORD short
#define LONG long
#define ASCIZ asciz
#define movb move.b
#define movw move.w
#define movl move.l
#define extl ext.l
#define addw add.w
#define addl add.l
#define addqw addq.w
#define addql addq.l
#define subw sub.w
#define subl sub.l
#define subqw subq.w
#define subql subq.l
#define negl neg.l
#define clrb clr.b
#define clrl clr.l
#define muluw mulu.w
#define notw not.w
#define andw and.w
#define andl and.l
#define aslw asl.w
#define asll asl.l
#define asrw asr.w
#define asrl asr.l
#define lsrw lsr.w
#define lsrl lsr.l
#define tstw tst.w
#define tstl tst.l
#define CMPW(x,y) cmp.w y,x
#define CMPL(x,y) cmp.l y,x
#define DBRA(r,lab) dbra r,LBL(lab)
#define BRAS(lab) bra.b LBL(lab)
#define BEQS(lab) beq.b LBL(lab)
#define BEQW(lab) beq.w LBL(lab)
#define BNES(lab) bne.b LBL(lab)
#define BNEW(lab) bne.w LBL(lab)
#define BMIS(lab) bmi.b LBL(lab)
#define BMIW(lab) bmi.w LBL(lab)
#define BPLS(lab) bpl.b LBL(lab)
#define BPLW(lab) bpl.w LBL(lab)
#define BLES(lab) ble.b LBL(lab)
#define BLEW(lab) ble.w LBL(lab)
#define BGES(lab) bge.b LBL(lab)
#define BCCS(lab) bcc.b LBL(lab)
#define BCCW(lab) bcc.w LBL(lab)
#define BCSS(lab) bcs.b LBL(lab)
#define BCSW(lab) bcs.w LBL(lab)
#define BLSS(lab) bls.b LBL(lab)
#define BHIS(lab) bhi.b LBL(lab)
#define BGTS(lab) bgt.b LBL(lab)
#define BGTW(lab) bgt.w LBL(lab)
#define BLTS(lab) blt.b LBL(lab)
#define BRAW(lab) bra.w LBL(lab)
#define BSRW(lab) bsr.w LBL(lab)
#define fmovel fmov.l
#define FPCR %fpcr
#define FPSR %fpsr
#else
/* SUN3 assembler definitions... */
#define OBJECT_FILE_BEGIN _object_file_begin: .globl _object_file_begin
#define OBJECT_FILE_END _object_file_end: .globl _object_file_end
#define DISP(r,n) r@(n:w)
#define INXW(r,i,n) r@(n:w,i:w)
#define PC_IND(lab) pc@(-2-(.-LBL(lab)):w)
#define ALIGN2 .even
#define ALIGN4 .=(.-_object_file_begin+3)/4*4
#define ALIGN8 .=(.-_object_file_begin+7)/8*8
#define SET(a,b) a = b
#define CONST(n) pc@((n*4)-2-(.-LBL($consts)):w)
#define REG(r) r
#define IMM(x) #x
#define PINC(r) r@+
#define PDEC(r) r@-
#define IND(r) r@
#define BYTE .byte
#define WORD .word
#define LONG .long
#define ASCIZ .asciz
#define muluw mulu
#define CMPW(x,y) cmpw x,y
#define CMPL(x,y) cmpl x,y
#define DBRA(r,lab) dbra r,LBL(lab)
#define BRAS(lab) BYTE 0x60,LBL(lab)-.-2
#define BEQS(lab) BYTE 0x67,LBL(lab)-.-2
#define BEQW(lab) WORD 0x6700,LBL(lab)-.-2
#define BNES(lab) BYTE 0x66,LBL(lab)-.-2
#define BNEW(lab) WORD 0x6600,LBL(lab)-.-2
#define BMIS(lab) BYTE 0x6b,LBL(lab)-.-2
#define BMIW(lab) WORD 0x6b00,LBL(lab)-.-2
#define BPLS(lab) BYTE 0x6a,LBL(lab)-.-2
#define BPLW(lab) WORD 0x6a00,LBL(lab)-.-2
#define BLES(lab) BYTE 0x6f,LBL(lab)-.-2
#define BLEW(lab) WORD 0x6f00,LBL(lab)-.-2
#define BGES(lab) BYTE 0x6c,LBL(lab)-.-2
#define BCCS(lab) BYTE 0x64,LBL(lab)-.-2
#define BCCW(lab) WORD 0x6400,LBL(lab)-.-2
#define BCSS(lab) BYTE 0x65,LBL(lab)-.-2
#define BCSW(lab) WORD 0x6500,LBL(lab)-.-2
#define BLSS(lab) BYTE 0x63,LBL(lab)-.-2
#define BHIS(lab) BYTE 0x62,LBL(lab)-.-2
#define BGTS(lab) BYTE 0x6e,LBL(lab)-.-2
#define BGTW(lab) WORD 0x6e00,LBL(lab)-.-2
#define BLTS(lab) BYTE 0x6d,LBL(lab)-.-2
#define BRAW(lab) WORD 0x6000,LBL(lab)-.-2
#define BSRW(lab) WORD 0x6100,LBL(lab)-.-2
#define FPCR fpcr
#define FPSR fpsr
.data
#endif
/* General definitions... */
#define PRIMITIVE(name) \
%NEWLINE% LONG PRIM_PROC+(INDEX_MASK*8) \
%NEWLINE% ASCIZ name \
%NEWLINE% ALIGN2
#define BEGIN(name) \
%NEWLINE% LONG PRIM_PROC_PREFIX \
%NEWLINE% WORD INDEX_MASK \
%NEWLINE% ASCIZ name \
%NEWLINE% ALIGN2 \
%NEWLINE% WORD LBL($header) \
%NEWLINE% ALIGN8 \
%NEWLINE% WORD LBL($code_len_tag) \
%NEWLINE%LBL($entry):
#define CONSTS(n) \
%NEWLINE% ALIGN4 \
%NEWLINE%LBL($consts): \
%NEWLINE% WORD END_OF_CODE_TAG \
%NEWLINE% SET(LBL($nb_consts),n+2)
#define END \
%NEWLINE% LONG SCM_false \
%NEWLINE% LONG LBL($nb_consts)*8 \
%NEWLINE% SET(LBL($code_len),LBL($consts)-LBL($entry)) \
%NEWLINE% SET(LBL($code_len_tag),LBL($code_len)/2) \
%NEWLINE% SET(LBL($header),HEADER(LBL($nb_consts)*4)+LBL($code_len)-2)
#define HEADER(l) ((l)+0x8000)
#define GLOB_OFFS(x) (((x)*8)-(MAX_NB_GLOBALS*10)-(NB_TRAPS*8)+0x8000)
#define TRAP_OFFS(x) (((x)-NB_TRAPS)*8+0x8000)
#define STAT_OFFS(x) (((x)-MAX_NB_STATS)*4)
#define SLOT(x) ((x)*4)
#define RETURN(lab,fs,link) \
%NEWLINE% ALIGN8 \
%NEWLINE% LONG 0 \
%NEWLINE% WORD (fs)*4 \
%NEWLINE% WORD ((fs)-(link))*4 \
%NEWLINE% WORD -0x8002-(.-LBL($entry)) \
%NEWLINE%LBL(lab)
#define RETURN_LAZY(lab,fs,link) \
%NEWLINE% ALIGN8 \
%NEWLINE% LONG 0 \
%NEWLINE% WORD -0x8000+(fs)*4 \
%NEWLINE% WORD ((fs)-(link))*4 \
%NEWLINE% WORD -0x8002-(.-LBL($entry)) \
%NEWLINE%LBL(lab)
#define SUBPROC(lab) \
%NEWLINE% ALIGN8 \
%NEWLINE% WORD -0x8002-(.-LBL($entry)) \
%NEWLINE%LBL(lab)
#define WRONG_NB_ARGS(x,n,lab) \
%NEWLINE% jsr DISP(TABLE_REG,TRAP_OFFS(x)) \
%NEWLINE% WORD n \
%NEWLINE% WORD .-LBL(lab)
#define TRAP(x,lab,fs,link) \
%NEWLINE% BRAS( lab) \
%NEWLINE% nop \
%NEWLINE% ALIGN8 \
%NEWLINE%LBL(lab): \
%NEWLINE% jsr DISP(TABLE_REG,TRAP_OFFS(x)) \
%NEWLINE% WORD fs*4 \
%NEWLINE% WORD (fs-link)*4 \
%NEWLINE% WORD -0x8002-(.-LBL($entry))
#define GET_TRAP_RETURN(nb_args) \
%NEWLINE% GET_TRAP_RET(nb_args) \
%NEWLINE% addql IMM(SCM_type_PROCEDURE),DTEMP1
#define GET_TRAP_RET(nb_args) \
%NEWLINE% moveq IMM(11+(nb_args*2)),DTEMP1 \
%NEWLINE% addl PINC(SP),DTEMP1 \
%NEWLINE% andw IMM(-8),DTEMP1
#define MOVE_ARGS_TO_STACK(arg_count) \
%NEWLINE% movw arg_count,DTEMP1 \
%NEWLINE% BPLS( not_1_arg) \
%NEWLINE% moveq IMM(1),DTEMP1 /* 1 arg passed */ \
%NEWLINE% movl PVM1_REG,PDEC(SP) \
%NEWLINE% BRAS( args_pushed) \
%NEWLINE%LBL(not_1_arg): \
%NEWLINE% BNES( not_1_or_2_args) \
%NEWLINE% moveq IMM(2),DTEMP1 /* 2 args passed */ \
%NEWLINE% movl PVM1_REG,PDEC(SP) \
%NEWLINE% movl PVM2_REG,PDEC(SP) \
%NEWLINE% BRAS( args_pushed) \
%NEWLINE%LBL(not_1_or_2_args): \
%NEWLINE% subqw IMM(1),DTEMP1 \
%NEWLINE% BEQS( args_pushed) \
%NEWLINE% movl PVM1_REG,PDEC(SP) /* 3 or more args passed */\
%NEWLINE% movl PVM2_REG,PDEC(SP) \
%NEWLINE% movl PVM3_REG,PDEC(SP) \
%NEWLINE%LBL(args_pushed):
#define RESET_STACK \
%NEWLINE% movl DISP(PSTATE_REG,SLOT(STACK_TOP)),SP \
%NEWLINE% movl DISP(PSTATE_REG,SLOT(Q_BOT)),LTQ_TAIL_REG \
%NEWLINE% movl SP,PINC(LTQ_TAIL_REG) \
%NEWLINE% movl LTQ_TAIL_REG,DISP(PSTATE_REG,SLOT(LTQ_HEAD)) \
%NEWLINE% movl DISP(PSTATE_REG,SLOT(Q_TOP)),ATEMP1 \
%NEWLINE% movl SP,PDEC(ATEMP1) \
%NEWLINE% movl ATEMP1,DISP(PSTATE_REG,SLOT(DEQ_TAIL)) \
%NEWLINE% movl ATEMP1,DISP(PSTATE_REG,SLOT(DEQ_HEAD))
#define MAKE_TEMP_TASK \
%NEWLINE% clrl PDEC(HEAP_REG) /* Make legitimacy PH */ \
%NEWLINE% clrl PDEC(HEAP_REG) \
%NEWLINE% movl NULL_REG,PDEC(HEAP_REG) \
%NEWLINE% lea DISP(HEAP_REG,SCM_type_PLACEHOLDER-4),ATEMP2 \
%NEWLINE% movl ATEMP2,PDEC(HEAP_REG) \
%NEWLINE% clrl PDEC(HEAP_REG) /* Make value PH */ \
%NEWLINE% clrl PDEC(HEAP_REG) \
%NEWLINE% movl NULL_REG,PDEC(HEAP_REG) \
%NEWLINE% lea DISP(HEAP_REG,SCM_type_PLACEHOLDER-4),ATEMP1 \
%NEWLINE% movl ATEMP1,PDEC(HEAP_REG) \
%NEWLINE% clrl PDEC(HEAP_REG) /* Make task */ \
%NEWLINE% clrl PDEC(HEAP_REG) \
%NEWLINE% movl FALSE_REG,PDEC(HEAP_REG) \
%NEWLINE% movl ATEMP1,PDEC(HEAP_REG) \
%NEWLINE% movl ATEMP1,PDEC(HEAP_REG) \
%NEWLINE% movl ATEMP2,PDEC(HEAP_REG) \
%NEWLINE% clrl PDEC(HEAP_REG) \
%NEWLINE% clrl PDEC(HEAP_REG) \
%NEWLINE% clrl PDEC(HEAP_REG) \
%NEWLINE% movl IMM(TASK_SIZE*0x400+(SCM_subtype_TASK*8)),PDEC(HEAP_REG) \
%NEWLINE% lea DISP(HEAP_REG,SCM_type_SUBTYPED),ATEMP1 \
%NEWLINE% movl ATEMP1,DISP(PSTATE_REG,SLOT(TEMP_TASK))
#ifdef STATS
#define STAT(n,x) \
%NEWLINE% addql IMM(n),DISP(PSTATE_REG,STAT_OFFS(x))
#define STAT_DTEMP1(x) \
%NEWLINE% addl DTEMP1,DISP(PSTATE_REG,STAT_OFFS(x))
#else
#define STAT(n,x)
#define STAT_DTEMP1(x)
#endif
#ifdef butterfly
#define ATOMCTA16 0 = a0, mask/incr = d1, adr = d0
#define ATOMADD32 1
#define ATOMAND32 2
#define ATOMIOR32 3
#define DO_ATOMIC \
%NEWLINE% trap IMM(0xe)
#define DO_BTRANSFER \
%NEWLINE% trap IMM(0xc)
#define DO_GETRTC \
%NEWLINE% trap IMM(0xd)
#define ADD_TO_DTEMP1() \
%NEWLINE% /* d0 = address, d1 = value */\
%NEWLINE% movw IMM(ATOMADD32),PVM0_REG /* a0 = atomadd32 command */\
%NEWLINE% DO_ATOMIC /* d0,a0,a1 not preserved */
#define READ_AND_CLEAR_DTEMP1 \
%NEWLINE% /* d0 = address */\
%NEWLINE% movw IMM(ATOMAND32),PVM0_REG /* a0 = atomand32 command */\
%NEWLINE% moveq IMM(0),PVM1_REG /* d1 = mask */\
%NEWLINE% DO_ATOMIC /* d0,a0,a1 not preserved */
#define READ_AND_SET_DTEMP1 \
%NEWLINE% /* d0 = address */\
%NEWLINE% movw IMM(ATOMIOR32),PVM0_REG /* a0 = atomior32 command */\
%NEWLINE% moveq IMM(-1),PVM1_REG /* d1 = mask */\
%NEWLINE% DO_ATOMIC /* d0,a0,a1 not preserved */
#define LOCK_ATEMP1(lab) \
%NEWLINE% movl ATEMP1,PVM4_REG \
%NEWLINE%LBL(lab): \
%NEWLINE% movw IMM(ATOMIOR32),PVM0_REG /* a0 = atomior32 command */\
%NEWLINE% movl PVM4_REG,DTEMP1 /* d0 = address */\
%NEWLINE% moveq IMM(-1),PVM1_REG /* d1 = mask */\
%NEWLINE% DO_ATOMIC /* d0,a0,a1 not preserved */\
%NEWLINE% CMPL( DTEMP1,PVM1_REG) \
%NEWLINE% BEQS( lab) \
%NEWLINE% movl PVM4_REG,ATEMP1 \
#define LOCK_ATEMP2(lab) \
%NEWLINE%LBL(lab): \
%NEWLINE% movw IMM(ATOMIOR32),PVM0_REG /* a0 = atomior32 command */\
%NEWLINE% movl ATEMP2,DTEMP1 /* d0 = address */\
%NEWLINE% moveq IMM(-1),PVM1_REG /* d1 = mask */\
%NEWLINE% DO_ATOMIC /* d0,a0,a1 not preserved */\
%NEWLINE% CMPL( DTEMP1,PVM1_REG) \
%NEWLINE% BEQS( lab)
#define BTRANSFER(lab) \
%NEWLINE% DO_BTRANSFER /* a0 = src, d0 = dest, d1 = nb of bytes */\
%NEWLINE% /* d0,d1,a1 not preserved */
#ifdef ELOG
#define LOG(event_num,lab) \
%NEWLINE% DO_GETRTC /* d0 = real time clock value */ \
%NEWLINE% movl DISP(PSTATE_REG,SLOT(ELOG_PTR)),ATEMP1 \
%NEWLINE% CMPL( DISP(PSTATE_REG,SLOT(ELOG_BOT)),ATEMP1) \
%NEWLINE% BEQS( lab) \
%NEWLINE% movl DTEMP1,PDEC(ATEMP1) \
%NEWLINE% movb IMM(event_num),IND(ATEMP1) \
%NEWLINE% movl ATEMP1,DISP(PSTATE_REG,SLOT(ELOG_PTR)) \
%NEWLINE%LBL(lab):
#define PREV_LOG(n,lab) \
%NEWLINE% DO_GETRTC /* d0 = real time clock value */ \
%NEWLINE% movl DISP(PSTATE_REG,SLOT(ELOG_PTR)),ATEMP1 \
%NEWLINE% CMPL( DISP(PSTATE_REG,SLOT(ELOG_BOT)),ATEMP1) \
%NEWLINE% BEQS( lab) \
%NEWLINE% movl DTEMP1,PDEC(ATEMP1) \
%NEWLINE% movb DISP(ATEMP1,4*n),IND(ATEMP1) \
%NEWLINE% movl ATEMP1,DISP(PSTATE_REG,SLOT(ELOG_PTR)) \
%NEWLINE%LBL(lab):
#else
#define LOG(x,lab)
#define PREV_LOG(x,lab)
#endif
#else
#define ADD_TO_DTEMP1
#define READ_AND_CLEAR_DTEMP1 \
%NEWLINE% movl DTEMP1,ATEMP1 \
%NEWLINE% movl IND(ATEMP1),DTEMP1 \
%NEWLINE% clrl IND(ATEMP1)
#define READ_AND_SET_DTEMP1 \
%NEWLINE% movl DTEMP1,ATEMP1 \
%NEWLINE% movl IND(ATEMP1),DTEMP1 \
%NEWLINE% movl IMM(-1),IND(ATEMP1)
#define LOCK_ATEMP1(lab) \
%NEWLINE% movl IND(ATEMP1),DTEMP1
#define LOCK_ATEMP2(lab) \
%NEWLINE% movl IND(ATEMP2),DTEMP1
#define BTRANSFER(lab) \
%NEWLINE% movl DTEMP1,ATEMP1 \
%NEWLINE% lsrl IMM(2),PVM1_REG \
%NEWLINE% subql IMM(1),PVM1_REG \
%NEWLINE%LBL(lab): \
%NEWLINE% movl PINC(PVM0_REG),PINC(ATEMP1) \
%NEWLINE% DBRA( PVM1_REG,lab)
#define LOG(x,lab)
#define PREV_LOG(x,lab)
#endif
#define WORK_REQUEST THIEF
/* Registers... */
#define PVM0_REG REG(a0)
#define PVM1_REG REG(d1)
#define PVM2_REG REG(d2)
#define PVM3_REG REG(d3)
#define PVM4_REG REG(d4)
#define CLOSURE_REG REG(d4)
#define INTR_TIMER_REG REG(d5)
#define NULL_REG REG(d6)
#define PLACEHOLDER_REG REG(d6)
#define FALSE_REG REG(d7)
#define PAIR_REG REG(d7)
#define DTEMP1 REG(d0)
#define ATEMP1 REG(a1)
#define ATEMP2 REG(a2)
#define HEAP_REG REG(a3)
#define LTQ_TAIL_REG REG(a4)
#define PSTATE_REG REG(a5)
#define TABLE_REG REG(a6)
#define SP REG(a7)
/*---------------------------------------------------------------------------*/
/* Start of kernel... */
OBJECT_FILE_BEGIN
WORD OFILE_VERSION_MAJOR /* Stamp with appropriate version */
WORD OFILE_VERSION_MINOR
/*---------------------------------------------------------------------------*/
/*
*** The first procedure (i.e. '###_kernel') is called from C as in:
***
*** kernel_startup( table, pstate, os_M68881 );
*/
#undef LBL
#define LBL(x)MAKE_LBL(00,x)
BEGIN("###_kernel")
movl CONST(0),PVM0_REG /* jump to #_kernel.startup */
jmp IND(PVM0_REG)
/* Reserve space for saving C's context */
LONG 0 /* C's D2 register */
LONG 0 /* C's D3 register */
LONG 0 /* C's D4 register */
LONG 0 /* C's D5 register */
LONG 0 /* C's D6 register */
LONG 0 /* C's D7 register */
LONG 0 /* C's A2 register */
LONG 0 /* C's A3 register */
LONG 0 /* C's A4 register */
LONG 0 /* C's A5 register */
LONG 0 /* C's A6 register */
LONG 0 /* C's SP register */
SET(C_D2,6)
SET(C_D3,10)
SET(C_D4,14)
SET(C_D5,18)
SET(C_D6,22)
SET(C_D7,26)
SET(C_A2,30)
SET(C_A3,34)
SET(C_A4,38)
SET(C_A5,42)
SET(C_A6,46)
SET(C_SP,50)
CONSTS(1)
PRIMITIVE("###_kernel.startup")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(01,x)
BEGIN("###_kernel.trap_0")
/* global_jump */
movl IMM(SCM_false),FALSE_REG /* d7 was clobbered so restore it */
movw DTEMP1,PDEC(SP) /* save argument count temporarily */
movl ATEMP1,DTEMP1
addl IMM((MAX_NB_GLOBALS*2)+(NB_TRAPS*8-0x8000)),DTEMP1
subl TABLE_REG,DTEMP1
asll IMM(2),DTEMP1
addl TABLE_REG,DTEMP1
subl IMM((MAX_NB_GLOBALS*10)+(NB_TRAPS*8-0x8000)),DTEMP1
movl DTEMP1,ATEMP1
movl PINC(ATEMP1),DTEMP1
movl DTEMP1,ATEMP2
addql IMM(SCM_type_PAIR-SCM_type_PROCEDURE),DTEMP1
btst DTEMP1,PAIR_REG
BNES( not_a_proc)
movl ATEMP2,IND(ATEMP1) /* replace trap adr by procedure adr */
movw PINC(SP),DTEMP1 /* restore argument count and set flags */
jmp IND(ATEMP2) /* jump to procedure */
LBL(not_a_proc):
subql IMM(4),ATEMP1 /* compute 'global variable index' */
addl IMM((MAX_NB_GLOBALS*10)+(NB_TRAPS*8-0x8000)),ATEMP1
subl TABLE_REG,ATEMP1
MOVE_ARGS_TO_STACK(PINC(SP))
/* make room for 'global variable index' argument */
movw DTEMP1,PVM1_REG
movl SP,ATEMP2
subql IMM(4),SP
BRAS( loop_entry)
LBL(loop):
movl PINC(ATEMP2),DISP(ATEMP2,-8)
LBL(loop_entry):
DBRA( PVM1_REG,loop)
movl ATEMP1,DISP(ATEMP2,-4)
addqw IMM(1),DTEMP1
movl CONST(0),ATEMP1 /* apply ##exception.global-jump */
movl CONST(1),ATEMP2
jmp IND(ATEMP2)
CONSTS(2)
PRIMITIVE("##exception.global-jump")
PRIMITIVE("###_kernel.apply")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(02,x)
BEGIN("###_kernel.trap_1")
/* touch d0 */
movl DTEMP1,ATEMP2
GET_TRAP_RETURN(0)
movl DTEMP1,PVM0_REG
LBL(touch):
movl DISP(ATEMP2,SLOT(PH_VALUE)-SCM_type_PLACEHOLDER),DTEMP1
CMPL( ATEMP2,DTEMP1)
BNES( determined)
LOG(EVENT_TOUCH_UNDET,log1)
#ifdef DETERMINE_IS_STRICT
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
LBL(determined):
#else
movl PVM0_REG,PDEC(SP)
lea PC_IND(ret),PVM0_REG
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
RETURN(ret,1,1):
movl PINC(SP),PVM0_REG
LBL(determined):
btst DTEMP1,PLACEHOLDER_REG
BNES( touched)
movl DTEMP1,ATEMP2
BRAS( touch)
LBL(touched):
#endif
jmp IND(PVM0_REG)
CONSTS(1)
PRIMITIVE("###_kernel.touch")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(03,x)
BEGIN("###_kernel.trap_2")
/* touch d1 */
GET_TRAP_RETURN(0)
movl DTEMP1,PVM0_REG
LBL(touch):
movl PVM1_REG,ATEMP2
movl DISP(ATEMP2,SLOT(PH_VALUE)-SCM_type_PLACEHOLDER),PVM1_REG
CMPL( ATEMP2,PVM1_REG)
BNES( determined)
LOG(EVENT_TOUCH_UNDET,log1)
#ifdef DETERMINE_IS_STRICT
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
LBL(determined):
#else
movl PVM0_REG,PDEC(SP)
lea PC_IND(ret),PVM0_REG
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
RETURN(ret,1,1):
movl PINC(SP),PVM0_REG
LBL(determined):
btst PVM1_REG,PLACEHOLDER_REG
BEQS( touch)
#endif
jmp IND(PVM0_REG)
CONSTS(1)
PRIMITIVE("###_kernel.touch")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(04,x)
BEGIN("###_kernel.trap_3")
/* touch d2 */
GET_TRAP_RETURN(0)
movl DTEMP1,PVM0_REG
LBL(touch):
movl PVM2_REG,ATEMP2
movl DISP(ATEMP2,SLOT(PH_VALUE)-SCM_type_PLACEHOLDER),PVM2_REG
CMPL( ATEMP2,PVM2_REG)
BNES( determined)
LOG(EVENT_TOUCH_UNDET,log1)
#ifdef DETERMINE_IS_STRICT
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
LBL(determined):
#else
movl PVM0_REG,PDEC(SP)
lea PC_IND(ret),PVM0_REG
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
RETURN(ret,1,1):
movl PINC(SP),PVM0_REG
LBL(determined):
btst PVM2_REG,PLACEHOLDER_REG
BEQS( touch)
#endif
jmp IND(PVM0_REG)
CONSTS(1)
PRIMITIVE("###_kernel.touch")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(05,x)
BEGIN("###_kernel.trap_4")
/* touch d3 */
GET_TRAP_RETURN(0)
movl DTEMP1,PVM0_REG
LBL(touch):
movl PVM3_REG,ATEMP2
movl DISP(ATEMP2,SLOT(PH_VALUE)-SCM_type_PLACEHOLDER),PVM3_REG
CMPL( ATEMP2,PVM3_REG)
BNES( determined)
LOG(EVENT_TOUCH_UNDET,log1)
#ifdef DETERMINE_IS_STRICT
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
LBL(determined):
#else
movl PVM0_REG,PDEC(SP)
lea PC_IND(ret),PVM0_REG
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
RETURN(ret,1,1):
movl PINC(SP),PVM0_REG
LBL(determined):
btst PVM3_REG,PLACEHOLDER_REG
BEQS( touch)
#endif
jmp IND(PVM0_REG)
CONSTS(1)
PRIMITIVE("###_kernel.touch")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(06,x)
BEGIN("###_kernel.trap_5")
/* touch d4 */
GET_TRAP_RETURN(0)
movl DTEMP1,PVM0_REG
LBL(touch):
movl PVM4_REG,ATEMP2
movl DISP(ATEMP2,SLOT(PH_VALUE)-SCM_type_PLACEHOLDER),PVM4_REG
CMPL( ATEMP2,PVM4_REG)
BNES( determined)
LOG(EVENT_TOUCH_UNDET,log1)
#ifdef DETERMINE_IS_STRICT
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
LBL(determined):
#else
movl PVM0_REG,PDEC(SP)
lea PC_IND(ret),PVM0_REG
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
RETURN(ret,1,1):
movl PINC(SP),PVM0_REG
LBL(determined):
btst PVM4_REG,PLACEHOLDER_REG
BEQS( touch)
#endif
jmp IND(PVM0_REG)
CONSTS(1)
PRIMITIVE("###_kernel.touch")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(07,x)
BEGIN("###_kernel.trap_6")
/* non_proc_jump */
MOVE_ARGS_TO_STACK(DTEMP1)
/* make room for 'procedure' argument */
movw DTEMP1,PVM1_REG
movl SP,ATEMP2
subql IMM(4),SP
BRAS( loop_entry)
LBL(loop):
movl PINC(ATEMP2),DISP(ATEMP2,-8)
LBL(loop_entry):
DBRA( PVM1_REG,loop)
movl ATEMP1,DISP(ATEMP2,-4) /* put 'procedure' argument */
addqw IMM(1),DTEMP1
movl CONST(0),ATEMP1 /* apply ##exception.non-proc-jump */
movl CONST(1),ATEMP2
jmp IND(ATEMP2)
CONSTS(2)
PRIMITIVE("##exception.non-proc-jump")
PRIMITIVE("###_kernel.apply")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(08,x)
BEGIN("###_kernel.trap_7")
/* rest_params */
movl PINC(SP),ATEMP1
MOVE_ARGS_TO_STACK(DTEMP1)
/* we know that nb-args < min or nb-args >= nb-parms */
CMPW( IND(ATEMP1),DTEMP1) /* nb-args < min ? */
BLTS( too_few_args)
/* build rest parameter */
movl NULL_REG,PVM1_REG /* PVM1_REG = () */
subw DISP(ATEMP1,2),DTEMP1 /* DTEMP1 = nb of extra args */
subqw IMM(1),DTEMP1
LBL(next_arg):
movl PINC(SP),PDEC(HEAP_REG) /* cons up the rest parameter list */
movl PVM1_REG,PDEC(HEAP_REG) /* NOTE: no overflow possible due to */
movl HEAP_REG,PVM1_REG /* limit on number of arguments */
addql IMM(4),PVM1_REG
DBRA( DTEMP1,next_arg)
movw DISP(ATEMP1,2),DTEMP1 /* get nb_parms-1 */
BEQS( return_parms) /* if 1 parm, parms are ok */
movl PVM1_REG,PVM2_REG /* else, must shuffle parameters */
subqw IMM(1),DTEMP1
BEQS( setup_parm1) /* if 2 parms, only 1 parm to move */
movl PVM1_REG,PVM3_REG /* rest parameter is in reg(3) */
movl PINC(SP),PVM2_REG /* next to last parameter in reg(2) */
LBL(setup_parm1):
movl PINC(SP),PVM1_REG
LBL(return_parms):
jmp DISP(ATEMP1,6) /* return from trap */
/* signal error */
LBL(too_few_args):
addql IMM(4),ATEMP1
movw IND(ATEMP1),PVM1_REG
extl PVM1_REG
addl PVM1_REG,ATEMP1
movl CONST(0),ATEMP2 /* jump to ###_kernel.wrong-nb-arg */
jmp IND(ATEMP2)
CONSTS(1)
PRIMITIVE("###_kernel.wrong-nb-arg")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(09,x)
BEGIN("###_kernel.trap_8")
/* rest_params_closed */
movl PINC(SP),ATEMP1
MOVE_ARGS_TO_STACK(DTEMP1)
/* we know that nb-args < min or nb-args >= nb-parms */
CMPW( IND(ATEMP1),DTEMP1) /* nb-args < min ? */
BLTS( too_few_args)
/* build rest parameter */
movl NULL_REG,PVM1_REG /* PVM1_REG = () */
subw DISP(ATEMP1,2),DTEMP1 /* DTEMP1 = nb of extra args */
subqw IMM(1),DTEMP1
LBL(next_arg):
movl PINC(SP),PDEC(HEAP_REG) /* cons up the rest parameter list */
movl PVM1_REG,PDEC(HEAP_REG) /* NOTE: no overflow possible due to */
movl HEAP_REG,PVM1_REG /* limit on number of arguments */
addql IMM(4),PVM1_REG
DBRA( DTEMP1,next_arg)
movw DISP(ATEMP1,2),DTEMP1 /* get nb_parms-1 */
BEQS( return_parms) /* if 1 parm, parms are ok */
movl PVM1_REG,PVM2_REG /* else, must shuffle parameters */
subqw IMM(1),DTEMP1
BEQS( setup_parm1) /* if 2 parms, only 1 parm to move */
movl PVM1_REG,PVM3_REG /* rest parameter is in reg(3) */
movl PINC(SP),PVM2_REG /* next to last parameter in reg(2) */
LBL(setup_parm1):
movl PINC(SP),PVM1_REG
LBL(return_parms):
jmp DISP(ATEMP1,4) /* return from trap */
/* signal error */
LBL(too_few_args):
movl PVM4_REG,ATEMP1
movl CONST(0),ATEMP2 /* jump to ###_kernel.wrong-nb-arg */
jmp IND(ATEMP2)
CONSTS(1)
PRIMITIVE("###_kernel.wrong-nb-arg")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(10,x)
BEGIN("###_kernel.trap_9")
/* wrong_nb_arg1 */
movl DTEMP1,ATEMP2
movl PINC(SP),ATEMP1 /* get pointer to procedure */
addql IMM(2),ATEMP1
movw IND(ATEMP1),DTEMP1
extl DTEMP1
addl DTEMP1,ATEMP1
MOVE_ARGS_TO_STACK(ATEMP2)
movl CONST(0),ATEMP2 /* jump to ###_kernel.wrong-nb-arg */
jmp IND(ATEMP2)
CONSTS(1)
PRIMITIVE("###_kernel.wrong-nb-arg")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(11,x)
BEGIN("###_kernel.trap_10")
/* wrong_nb_arg1_closed */
movl CLOSURE_REG,ATEMP1
addql IMM(4),SP /* discard trap address */
MOVE_ARGS_TO_STACK(DTEMP1)
movl CONST(0),ATEMP2 /* jump to ###_kernel.wrong-nb-arg */
jmp IND(ATEMP2)
CONSTS(1)
PRIMITIVE("###_kernel.wrong-nb-arg")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(12,x)
BEGIN("###_kernel.trap_11")
/* wrong_nb_arg2 */
movl DTEMP1,ATEMP2
movl PINC(SP),ATEMP1 /* get pointer to procedure */
addql IMM(4),ATEMP1
movw IND(ATEMP1),DTEMP1
extl DTEMP1
addl DTEMP1,ATEMP1
MOVE_ARGS_TO_STACK(ATEMP2)
movl CONST(0),ATEMP2 /* jump to ###_kernel.wrong-nb-arg */
jmp IND(ATEMP2)
CONSTS(1)
PRIMITIVE("###_kernel.wrong-nb-arg")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(13,x)
BEGIN("###_kernel.trap_12")
/* wrong_nb_arg2_closed */
movl CLOSURE_REG,ATEMP1
addql IMM(4),SP /* discard trap address */
MOVE_ARGS_TO_STACK(DTEMP1)
movl CONST(0),ATEMP2 /* jump to ###_kernel.wrong-nb-arg */
jmp IND(ATEMP2)
CONSTS(1)
PRIMITIVE("###_kernel.wrong-nb-arg")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(14,x)
BEGIN("###_kernel.trap_13")
/* heap_alloc1 */
moveq IMM(0),DTEMP1
movl CONST(0),ATEMP2 /* jump to ###_kernel.trap_14 */
jmp IND(ATEMP2)
CONSTS(1)
PRIMITIVE("###_kernel.trap_14")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(15,x)
BEGIN("###_kernel.trap_14")
/* heap_alloc2 */
addl DTEMP1,HEAP_REG /* restore correct heap ptr */
movl DTEMP1,ATEMP2
GET_TRAP_RETURN(0)
movl DTEMP1,PDEC(SP)
movl PVM0_REG,PDEC(SP)
movl PVM1_REG,PDEC(SP)
movl PVM2_REG,PDEC(SP)
movl PVM3_REG,PDEC(SP)
movl PVM4_REG,PDEC(SP)
movl ATEMP2,PDEC(SP)
BRAS( gc_and_allocate)
RETURN(gc_and_allocate,7,1):
lea PC_IND(ret),PVM0_REG
movl CONST(0),ATEMP1 /* jump to ##gc */
moveq IMM(1),DTEMP1 /* passing 0 argument */
jmp IND(ATEMP1)
RETURN(ret,7,1):
/* Is there a heap overflow with the current heap margin? */
movl PINC(SP),DTEMP1
CMPL( DTEMP1,HEAP_REG)
subl DTEMP1,HEAP_REG /* allocate space and check heap overflow */
BCSS( overflow_on_alloc)
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG)
BCCS( allocated)
LBL(overflow_on_alloc):
addl DTEMP1,HEAP_REG /* restore correct heap ptr */
/* Then use a smaller heap margin and signal a heap overflow */
movl DISP(PSTATE_REG,SLOT(HEAP_MARGIN)),DTEMP1
BEQS( fatal_overflow)
subl DTEMP1,DISP(PSTATE_REG,SLOT(HEAP_LIM))
moveq IMM(0),DTEMP1
movl DTEMP1,DISP(PSTATE_REG,SLOT(HEAP_MARGIN))
/* continuation must be discarded... */
movl DISP(PSTATE_REG,SLOT(BOS_RET)),PVM0_REG
movl CONST(1),ATEMP1 /* jump to ##exception.heap-overflow proc */
moveq IMM(1),DTEMP1 /* passing 0 argument */
jmp IND(ATEMP1)
LBL(fatal_overflow):
movl DISP(PSTATE_REG,SLOT(BOS_RET)),PVM0_REG
movl CONST(2),ATEMP1
moveq IMM(1),DTEMP1
jmp IND(ATEMP1)
LBL(allocated):
/* Check to see if we can grow the heap margin */
movl DISP(PSTATE_REG,SLOT(HEAP_LIM)),DTEMP1
subl DISP(PSTATE_REG,SLOT(HEAP_MARGIN)),DTEMP1
addl DISP(PSTATE_REG,SLOT(HEAP_MAX_MARGIN)),DTEMP1
CMPL( DTEMP1,HEAP_REG)
BCSS( cant_grow)
movl DTEMP1,DISP(PSTATE_REG,SLOT(HEAP_LIM))
movl DISP(PSTATE_REG,SLOT(HEAP_MAX_MARGIN)),DISP(PSTATE_REG,SLOT(HEAP_MARGIN))
LBL(cant_grow):
movl PINC(SP),PVM4_REG
movl PINC(SP),PVM3_REG
movl PINC(SP),PVM2_REG
movl PINC(SP),PVM1_REG
movl PINC(SP),PVM0_REG
rts
CONSTS(3)
PRIMITIVE("##gc")
PRIMITIVE("##exception.heap-overflow")
PRIMITIVE("##fatal-heap-overflow")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(16,x)
BEGIN("###_kernel.trap_15")
/* closure_alloc */
movl DTEMP1,ATEMP2
GET_TRAP_RETURN(0)
movl DTEMP1,PDEC(SP)
movl ATEMP2,DTEMP1
movl DTEMP1,PDEC(SP)
addl IMM(CLOSURE_BLOCK_LENGTH+CACHE_LINE_LENGTH),DTEMP1
subl DTEMP1,HEAP_REG
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG) /* heap overflow */
BCCS( ok)
TRAP(heap_alloc2_trap,alloc,2,1)
LBL(ok):
movl HEAP_REG,DTEMP1
addl IMM(CACHE_LINE_LENGTH),DTEMP1
andw IMM(-CACHE_LINE_LENGTH),DTEMP1
movl DTEMP1,ATEMP1
movl ATEMP1,DISP(PSTATE_REG,SLOT(CLOSURE_LIM))
addl IMM(CLOSURE_BLOCK_LENGTH),ATEMP1
movl ATEMP1,DISP(PSTATE_REG,SLOT(CLOSURE_PTR))
addl PINC(SP),ATEMP1
/* init closure block: */
movl IMM(0x80080000+JSR_OP),DTEMP1
lea PC_IND(closure_trampoline),ATEMP2
BRAS( loop_entry)
LBL(loop):
subql IMM(CACHE_LINE_LENGTH-8),ATEMP1
movl ATEMP2,PDEC(ATEMP1)
movl DTEMP1,PDEC(ATEMP1)
LBL(loop_entry):
CMPL( ATEMP1,HEAP_REG)
BLTS( loop)
movl DISP(PSTATE_REG,SLOT(FLUSH_WRITES)),PDEC(SP)
jsr DISP(TABLE_REG,TRAP_OFFS(C_TRAP_trap))
movl DISP(PSTATE_REG,SLOT(CLOSURE_PTR)),ATEMP2
rts
LBL(closure_trampoline):
movl IND(SP),ATEMP1
movl PDEC(ATEMP1),ATEMP1
jmp IND(ATEMP1)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(17,x)
BEGIN("###_kernel.trap_16")
/* delay_future */
GET_TRAP_RETURN(0)
movl DTEMP1,PVM0_REG
/* Allocate special "DELAY" frame. */
moveq IMM(11+4+PH_SIZE*4),DTEMP1
addw DISP(PVM0_REG,-6),DTEMP1 /* get fs */
andw IMM(-8),DTEMP1
subl DTEMP1,HEAP_REG
/* Check need to GC. */
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG)
BCCS( space_allocated)
LBL(gc_needed):
movl PVM0_REG,PDEC(SP)
TRAP(heap_alloc2_trap,alloc,1,1)
movl PINC(SP),PVM0_REG
LBL(space_allocated):
addw IMM(PH_SIZE*4),HEAP_REG
moveq IMM(4),DTEMP1
addw DISP(PVM0_REG,-6),DTEMP1
asll IMM(8),DTEMP1
movb IMM(SCM_subtype_VECTOR*8),DTEMP1
movl DTEMP1,IND(HEAP_REG)
/* Copy the frame. */
lsrl IMM(8),DTEMP1
lsrl IMM(2),DTEMP1
subql IMM(2),DTEMP1
moveq IMM(0),PVM1_REG
movw DISP(PVM0_REG,-4),PVM1_REG /* get link */
movl INXW(SP,PVM1_REG,0),ATEMP2
lea DISP(HEAP_REG,SLOT(1)),ATEMP1
movl PVM0_REG,PINC(ATEMP1)
LBL(copy_loop):
movl PINC(SP),PINC(ATEMP1)
DBRA( DTEMP1,copy_loop)
/* Make placeholder. */
lea DISP(HEAP_REG,SCM_type_SUBTYPED),ATEMP1
clrl PDEC(HEAP_REG)
movl ATEMP1,PDEC(HEAP_REG)
movl NULL_REG,PDEC(HEAP_REG)
lea DISP(HEAP_REG,SCM_type_PLACEHOLDER-4),ATEMP1
movl ATEMP1,PDEC(HEAP_REG)
/* Return placeholder. */
movl ATEMP1,PVM1_REG
jmp IND(ATEMP2)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(18,x)
BEGIN("###_kernel.trap_17")
/* eager_future */
GET_TRAP_RETURN(0)
movl DTEMP1,PVM0_REG
/* broken... */
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(19,x)
BEGIN("###_kernel.trap_18")
/* steal_conflict */
GET_TRAP_RETURN(0)
movl DTEMP1,ATEMP2
/* get consistent value for LTQ_HEAD */
movl FALSE_REG,DISP(PSTATE_REG,SLOT(STEAL_LOCKO))
/*
tstl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
BEQS( locked)
addql IMM(8),DISP(PSTATE_REG,SLOT(56))
*/
LBL(lock_steal):
tstl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
BNES( lock_steal)
LBL(locked):
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),ATEMP1
clrl DISP(PSTATE_REG,SLOT(STEAL_LOCKO))
/* Who won the race for the continuation? */
CMPL( ATEMP1,LTQ_TAIL_REG)
BCSS( thief_won)
/* Continue normally */
jmp IND(ATEMP2)
LBL(thief_won):
movl SP,PINC(LTQ_TAIL_REG)
movl CONST(0),ATEMP1
addw IMM(16),ATEMP1
movl ATEMP1,DISP(PSTATE_REG,SLOT(PARENT_RET))
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
movl DISP(PSTATE_REG,SLOT(BOS_RET)),ATEMP1
jmp IND(ATEMP1)
CONSTS(1)
PRIMITIVE("###_kernel.task")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(20,x)
BEGIN("###_kernel.trap_19")
BRAS( $entry)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(21,x)
BEGIN("###_kernel.trap_20")
BRAS( $entry)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(22,x)
BEGIN("###_kernel.trap_21")
BRAS( $entry)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(23,x)
BEGIN("###_kernel.trap_22")
/* C_TRAP */
movl REG(a4),PDEC(SP)
movl REG(a3),PDEC(SP)
movl REG(a2),PDEC(SP)
movl REG(a1),PDEC(SP)
movl REG(a0),PDEC(SP)
movl DISP(SP,4+SLOT(5)),REG(a0)
movl REG(d7),PDEC(SP)
movl REG(d6),PDEC(SP)
movl REG(d5),PDEC(SP)
movl REG(d4),PDEC(SP)
movl REG(d3),PDEC(SP)
movl REG(d2),PDEC(SP)
movl REG(d1),PDEC(SP)
movl REG(d0),PDEC(SP)
movl SP,DISP(PSTATE_REG,SLOT(STACK_PTR))
movl CONST(0),REG(a1) /* restore C's registers */
#ifndef MIN_C_CONTEXT
movl DISP(REG(a1),C_D2),REG(d2)
movl DISP(REG(a1),C_D3),REG(d3)
movl DISP(REG(a1),C_D4),REG(d4)
movl DISP(REG(a1),C_D5),REG(d5)
movl DISP(REG(a1),C_D6),REG(d6)
movl DISP(REG(a1),C_D7),REG(d7)
movl DISP(REG(a1),C_A2),REG(a2)
movl DISP(REG(a1),C_A3),REG(a3)
movl DISP(REG(a1),C_A4),REG(a4)
#endif
movl DISP(REG(a1),C_A5),REG(a5)
movl DISP(REG(a1),C_A6),REG(a6)
movl DISP(REG(a1),C_SP),SP
jsr IND(REG(a0)) /* call C procedure */
movl CONST(0),REG(a2)
movl DISP(REG(a2),C_SP),ATEMP1 /* get TABLE_REG & PSTATE_REG */
movl DISP(ATEMP1,4),TABLE_REG /* restore Scheme context */
movl DISP(ATEMP1,8),PSTATE_REG
movl DISP(PSTATE_REG,SLOT(STACK_PTR)),SP
movl PINC(SP),REG(d0)
movl PINC(SP),REG(d1)
movl PINC(SP),REG(d2)
movl PINC(SP),REG(d3)
movl PINC(SP),REG(d4)
movl PINC(SP),REG(d5)
movl PINC(SP),REG(d6)
movl PINC(SP),REG(d7)
movl PINC(SP),REG(a0)
movl PINC(SP),REG(a1)
movl PINC(SP),REG(a2)
movl PINC(SP),REG(a3)
movl PINC(SP),REG(a4)
movl PINC(SP),IND(SP)
rts
CONSTS(1)
PRIMITIVE("###_kernel")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(24,x)
BEGIN("###_kernel.trap_23")
/* C_CALL */
movl CONST(0),REG(a2)
movl DISP(REG(a2),C_SP),ATEMP2
movl IMM(SCM_marker),PDEC(ATEMP2)
tstw DTEMP1
BMIS( passed_1arg)
BEQS( passed_2args)
subqw IMM(3),DTEMP1
BMIS( move_remaining_args)
movl PVM3_REG,PDEC(ATEMP2)
subqw IMM(1),DTEMP1
LBL(passed_2args):
movl PVM2_REG,PDEC(ATEMP2)
subqw IMM(1),DTEMP1
LBL(passed_1arg):
movl PVM1_REG,PDEC(ATEMP2)
subqw IMM(1),DTEMP1
LBL(move_remaining_args):
addqw IMM(2),DTEMP1
BRAS( loop_entry)
LBL(loop):
movl PINC(SP),PDEC(ATEMP2)
LBL(loop_entry):
DBRA( DTEMP1,loop)
movl PVM0_REG,PDEC(SP) /* save Scheme context */
pea PC_IND(default_return_proc)
movl SP,DISP(PSTATE_REG,SLOT(STACK_PTR))
movl LTQ_TAIL_REG,DISP(PSTATE_REG,SLOT(LTQ_TAIL))
movl HEAP_REG,DISP(PSTATE_REG,SLOT(HEAP_PTR))
movl ATEMP2,SP
movl ATEMP1,ATEMP2
LOG(EVENT_C_CALL,log1)
movl ATEMP2,REG(a0)
movl CONST(0),REG(a1) /* restore C's registers */
#ifndef MIN_C_CONTEXT
movl DISP(REG(a1),C_D2),REG(d2)
movl DISP(REG(a1),C_D3),REG(d3)
movl DISP(REG(a1),C_D4),REG(d4)
movl DISP(REG(a1),C_D5),REG(d5)
movl DISP(REG(a1),C_D6),REG(d6)
movl DISP(REG(a1),C_D7),REG(d7)
movl DISP(REG(a1),C_A2),REG(a2)
movl DISP(REG(a1),C_A3),REG(a3)
movl DISP(REG(a1),C_A4),REG(a4)
#endif
movl DISP(REG(a1),C_A5),REG(a5)
movl DISP(REG(a1),C_A6),REG(a6)
jsr IND(REG(a0)) /* call C procedure */
movl DTEMP1,PVM1_REG /* get result */
movl CONST(0),REG(a2)
movl DISP(REG(a2),C_SP),ATEMP1 /* get TABLE_REG & PSTATE_REG */
movl DISP(ATEMP1,4),TABLE_REG /* restore Scheme context */
movl DISP(ATEMP1,8),PSTATE_REG
movl DISP(PSTATE_REG,SLOT(STACK_PTR)),SP
movl DISP(PSTATE_REG,SLOT(HEAP_PTR)),HEAP_REG
movl DISP(PSTATE_REG,SLOT(LTQ_TAIL)),LTQ_TAIL_REG
moveq IMM(0),INTR_TIMER_REG /* check interrupts as soon as possible */
movl IMM(SCM_null),NULL_REG
movl IMM(SCM_false),FALSE_REG
moveq IMM(0),PVM2_REG
moveq IMM(0),PVM3_REG
moveq IMM(0),PVM4_REG
PREV_LOG(2,log2)
movl PINC(SP),ATEMP1
movl PINC(SP),PVM0_REG
moveq IMM(-1),DTEMP1
jmp IND(ATEMP1)
SUBPROC(default_return_proc):
jmp IND(PVM0_REG)
CONSTS(1)
PRIMITIVE("###_kernel")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(25,x)
BEGIN("###_kernel.interrupt")
/* intr */
GET_TRAP_RET(0)
movl DTEMP1,ATEMP1
/* Clear interrupt flag. */
movl DISP(PSTATE_REG,SLOT(STACK_LIM)),IND(PSTATE_REG)
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#ifdef MESSAGE_PASSING_STEAL
/* Check if steal request. */
#ifdef SYNCHRONOUS_STEAL
movl DISP(PSTATE_REG,SLOT(THIEF)),DTEMP1
BEQS( not_steal)
#else
movl DISP(PSTATE_REG,SLOT(WORK_REQUEST)),DTEMP1
BEQS( not_steal)
clrl DISP(PSTATE_REG,SLOT(WORK_REQUEST))
#endif
/* Check if anything to steal. */
CMPL( DISP(PSTATE_REG,SLOT(LTQ_HEAD)),LTQ_TAIL_REG)
BNES( steal)
/* Nothing to steal, so immediately respond to steal request. */
#ifdef SYNCHRONOUS_STEAL
clrl DISP(PSTATE_REG,SLOT(THIEF))
clrl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
movl DTEMP1,ATEMP2
clrl DISP(ATEMP2,SLOT(RESPONSE))
#endif
LBL(not_steal):
#endif
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
CMPL( DISP(PSTATE_REG,SLOT(STACK_LIM)),SP)
BCSW( check_other_intrs1)
movl DISP(PSTATE_REG,SLOT(INTR_OTHER)),DTEMP1
BNEW( check_other_intrs1)
LBL(quick_return):
jmp DISP(ATEMP1,SCM_type_PROCEDURE)
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#ifdef MESSAGE_PASSING_STEAL
LBL(steal):
pea DISP(ATEMP1,SCM_type_PROCEDURE)
LOG(EVENT_INTERRUPT,log1)
movl PVM0_REG,PDEC(SP)
movl PVM1_REG,PDEC(SP)
movl PVM2_REG,PDEC(SP)
movl PVM3_REG,PDEC(SP)
movl PVM4_REG,PDEC(SP)
LBL(steal_again):
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),ATEMP1
movl DISP(ATEMP1,-SLOT(1)),DTEMP1
subl DISP(LTQ_TAIL_REG,-SLOT(1)),DTEMP1
addl IMM((TASK_SIZE+1)+(PH_SIZE*2)+4),DTEMP1
asll IMM(2),DTEMP1
CMPL( DTEMP1,HEAP_REG)
subl DTEMP1,HEAP_REG /* allocate space for frames and check heap */
BCSS( gc_needed)
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG) /* overflow */
BCCS( space_allocated)
LBL(gc_needed):
#ifdef SYNCHRONOUS_STEAL
movl DISP(PSTATE_REG,SLOT(THIEF)),ATEMP1
clrl DISP(PSTATE_REG,SLOT(THIEF))
clrl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
clrl DISP(ATEMP1,SLOT(RESPONSE))
#endif
PREV_LOG(2,log2)
TRAP(heap_alloc1_trap,alloc,6,1)
LOG(EVENT_INTERRUPT,log3)
BRAW( check_other_intrs2)
LBL(space_allocated):
addl DTEMP1,HEAP_REG
/* At this point, we know that there is at least one task on the LTQ and */
/* that there is enough free space on the heap to copy the frames. */
/* Transfer one task chunk to thief (or workq). */
/* Call ###_kernel.transfer-lazy-task-chunk-to-heap. */
#ifdef SYNCHRONOUS_STEAL
movl DISP(PSTATE_REG,SLOT(THIEF)),PVM2_REG
clrl DISP(PSTATE_REG,SLOT(THIEF))
clrl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
#else
moveq IMM(0),PVM2_REG /* specify direct transfer to workq */
#endif
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),ATEMP1
movl DISP(ATEMP1,-SLOT(1)),PVM3_REG
pea PC_IND(task_chunk_transferred)
movl CONST(1),ATEMP2
jmp IND(ATEMP2)
LBL(task_chunk_transferred):
moveq IMM(0),PVM1_REG
movl PVM1_REG,PVM0_REG
movl PVM1_REG,PVM3_REG
/* Check again if steal request. */
#ifdef SYNCHRONOUS_STEAL
movl DISP(PSTATE_REG,SLOT(THIEF)),DTEMP1
BEQS( check_other_intrs2)
#else
movl DISP(PSTATE_REG,SLOT(WORK_REQUEST)),DTEMP1
BEQS( check_other_intrs2)
clrl DISP(PSTATE_REG,SLOT(WORK_REQUEST))
#endif
/* Check if anything to steal. */
CMPL( DISP(PSTATE_REG,SLOT(LTQ_HEAD)),LTQ_TAIL_REG)
BNEW( steal_again)
/* Nothing to steal, so immediately respond to steal request. */
#ifdef SYNCHRONOUS_STEAL
clrl DISP(PSTATE_REG,SLOT(THIEF))
clrl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
movl DTEMP1,ATEMP2
clrl DISP(ATEMP2,SLOT(RESPONSE))
#endif
BRAS( check_other_intrs2)
#endif
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
LBL(check_other_intrs1):
pea DISP(ATEMP1,SCM_type_PROCEDURE)
LOG(EVENT_INTERRUPT,log4)
movl PVM0_REG,PDEC(SP)
movl PVM1_REG,PDEC(SP)
movl PVM2_REG,PDEC(SP)
movl PVM3_REG,PDEC(SP)
movl PVM4_REG,PDEC(SP)
LBL(check_other_intrs2):
clrl DISP(PSTATE_REG,SLOT(INTR_OTHER))
/* Check if there was a stack overflow. */
CMPL( DISP(PSTATE_REG,SLOT(STACK_LIM)),SP)
BCCS( stack_checked)
moveq IMM(0),DTEMP1
movl DTEMP1,DISP(PSTATE_REG,SLOT(STACK_MARGIN))
movl DISP(PSTATE_REG,SLOT(STACK_BOT)),DTEMP1
addl IMM(SLOT(STACK_ALLOCATION_FUDGE)),DTEMP1
addl DISP(PSTATE_REG,SLOT(STACK_MARGIN)),DTEMP1
movl DTEMP1,DISP(PSTATE_REG,SLOT(STACK_LIM))
lea PC_IND(ret1),PVM0_REG
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
RETURN(ret1,6,1):
movl DISP(PSTATE_REG,SLOT(STACK_MAX_MARGIN)),DISP(PSTATE_REG,SLOT(STACK_MARGIN))
movl DISP(PSTATE_REG,SLOT(STACK_BOT)),DTEMP1
addl IMM(SLOT(STACK_ALLOCATION_FUDGE)),DTEMP1
addl DISP(PSTATE_REG,SLOT(STACK_MARGIN)),DTEMP1
movl DTEMP1,DISP(PSTATE_REG,SLOT(STACK_LIM))
LBL(stack_checked):
/* Check each of the interrupt flags in turn. */
tstl DISP(PSTATE_REG,SLOT(INTR_BARRIER))
BEQS( ret2)
clrl DISP(PSTATE_REG,SLOT(INTR_BARRIER))
lea PC_IND(ret2),PVM0_REG
movl CONST(2),ATEMP1 /* Call ##barrier */
moveq IMM(1),DTEMP1
jmp IND(ATEMP1)
RETURN(ret2,6,1):
tstl DISP(PSTATE_REG,SLOT(INTR_TIMER))
BEQS( ret3)
clrl DISP(PSTATE_REG,SLOT(INTR_TIMER))
lea PC_IND(ret3),PVM0_REG
movl CONST(3),ATEMP1 /* Call ##exception.timer-interrupt */
moveq IMM(1),DTEMP1
jmp IND(ATEMP1)
RETURN(ret3,6,1):
tstl DISP(PSTATE_REG,SLOT(INTR_USER))
BEQS( ret4)
clrl DISP(PSTATE_REG,SLOT(INTR_USER))
lea PC_IND(ret4),PVM0_REG
movl CONST(4),ATEMP1 /* Call ##exception.user-interrupt */
moveq IMM(1),DTEMP1
jmp IND(ATEMP1)
RETURN(ret4,6,1):
movl PINC(SP),PVM4_REG
movl PINC(SP),PVM3_REG
movl PINC(SP),PVM2_REG
movl PINC(SP),PVM1_REG
movl PINC(SP),PVM0_REG
PREV_LOG(2,log5)
rts
CONSTS(5)
PRIMITIVE("###_kernel.flush-stack")
PRIMITIVE("###_kernel.transfer-lazy-task-chunk-to-heap")
PRIMITIVE("##barrier")
PRIMITIVE("##exception.timer-interrupt")
PRIMITIVE("##exception.user-interrupt")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(26,x)
BEGIN("###_kernel.apply")
tstw DTEMP1 /* how many arguments to pass? */
BEQS( pass_0arg)
subqw IMM(2),DTEMP1
BMIS( pass_1arg)
BEQS( pass_2args)
movl PINC(SP),PVM3_REG
movl PINC(SP),PVM2_REG
movl PINC(SP),PVM1_REG
addqw IMM(3),DTEMP1
jmp IND(ATEMP1) /* jump to procedure (with >= 3 args) */
LBL(pass_0arg):
moveq IMM(1),DTEMP1
jmp IND(ATEMP1) /* jump to procedure (with no arg) */
LBL(pass_1arg):
movl PINC(SP),PVM1_REG
moveq IMM(-1),DTEMP1
jmp IND(ATEMP1) /* jump to procedure (with 1 arg) */
LBL(pass_2args):
movl PINC(SP),PVM2_REG
movl PINC(SP),PVM1_REG
moveq IMM(0),DTEMP1
jmp IND(ATEMP1) /* jump to procedure (with 2 args) */
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(27,x)
BEGIN("###_kernel.wrong-nb-arg")
/* make room for 'procedure' argument */
movw DTEMP1,PVM1_REG
movl SP,ATEMP2
subql IMM(4),SP
BRAS( loop_entry)
LBL(loop):
movl PINC(ATEMP2),DISP(ATEMP2,-8)
LBL(loop_entry):
DBRA( PVM1_REG,loop)
movl ATEMP1,DISP(ATEMP2,-4) /* put 'procedure' argument */
addqw IMM(1),DTEMP1
movl CONST(0),ATEMP1 /* apply ##exception.wrong-nb-arg */
movl CONST(1),ATEMP2
jmp IND(ATEMP2)
CONSTS(2)
PRIMITIVE("##exception.wrong-nb-arg")
PRIMITIVE("###_kernel.apply")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(28,x)
BEGIN("###_kernel.switch-task")
CMPL( DISP(PSTATE_REG,SLOT(LTQ_HEAD)),LTQ_TAIL_REG)
BNES( there_are_other_tasks)
CMPL( DISP(PSTATE_REG,SLOT(WORKQ_TAIL)),NULL_REG)
BNES( there_are_other_tasks)
movl FALSE_REG,PVM1_REG /* no other tasks to switch to */
jmp IND(PVM0_REG)
LBL(there_are_other_tasks):
LOG(EVENT_TASK_SWITCH,log1)
movl PVM0_REG,PDEC(SP)
/* Call ###_kernel.transfer-lazy-tasks-to-heap. */
pea PC_IND(ret1)
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
RETURN(ret1,1,1):
/* Call ###_kernel.transfer-stack-to-heap. */
/* ###_kernel.transfer-lazy-tasks-to-heap has reserved enough */
/* space, so no GC check required. */
pea PC_IND(ret2)
movl CONST(1),ATEMP1
jmp IND(ATEMP1)
LBL(ret2):
/* Save state of current task. */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP1
movl PINC(SP),PVM0_REG
movl PVM0_REG,DISP(ATEMP1,SLOT(TASK_CONT_RET)+4-SCM_type_SUBTYPED)
movl PVM2_REG,DISP(ATEMP1,SLOT(TASK_CONT_FRAME)+4-SCM_type_SUBTYPED)
movl DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV)),DISP(ATEMP1,SLOT(TASK_CONT_DYN_ENV)+4-SCM_type_SUBTYPED)
movl IMM(SCM_true),DISP(ATEMP1,SLOT(TASK_VALUE)+4-SCM_type_SUBTYPED)
/* Add task to workq. */
movl ATEMP1,PDEC(HEAP_REG)
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to READY */
movl HEAP_REG,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
movl FALSE_REG,DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(lock_workq):
tstl DISP(PSTATE_REG,SLOT(WORKQ_LOCKV))
BNES( lock_workq)
movl DISP(PSTATE_REG,SLOT(WORKQ_TAIL)),ATEMP1
CMPL( ATEMP1,NULL_REG)
BNES( non_empty_queue)
movl HEAP_REG,DISP(PSTATE_REG,SLOT(WORKQ_HEAD))
BRAS( fix_tail)
LBL(non_empty_queue):
movl HEAP_REG,PDEC(ATEMP1)
LBL(fix_tail):
movl HEAP_REG,DISP(PSTATE_REG,SLOT(WORKQ_TAIL))
movl NULL_REG,PDEC(HEAP_REG)
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
/* Go idle. */
moveq IMM(0),PVM1_REG
movl CONST(2),ATEMP1
jmp IND(ATEMP1)
CONSTS(3)
PRIMITIVE("###_kernel.transfer-lazy-tasks-to-heap")
PRIMITIVE("###_kernel.transfer-stack-to-heap")
PRIMITIVE("###_kernel.idle")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(29,x)
BEGIN("###_kernel.idle")
#ifdef MAINTAIN_TASK_STATUS
BEQS( find_work)
movl PVM1_REG,ATEMP1
/* Check if task is really READY */
lea DISP(ATEMP1,SLOT(TASK_LOCKV)+4-SCM_type_SUBTYPED),ATEMP1
LBL(lock_task1):
LOCK_ATEMP1(lock1)
tstl DISP(ATEMP1,SLOT(TASK_LOCKO-TASK_LOCKV))
BEQS( task_locked1)
clrl IND(ATEMP1)
BRAS( lock_task1)
LBL(task_locked1):
movl DISP(ATEMP1,SLOT(TASK_STATUS-TASK_LOCKV)),DTEMP1
btst DTEMP1,PAIR_REG
BNES( task_not_ready1)
movl DTEMP1,ATEMP2 /* remove task from workq */
movl FALSE_REG,IND(ATEMP2)
/* Change task's status to RUNNING */
movl PSTATE_REG,DISP(ATEMP1,SLOT(TASK_STATUS-TASK_LOCKV))
clrl IND(ATEMP1)
lea DISP(ATEMP1,-(SLOT(TASK_LOCKV)+4-SCM_type_SUBTYPED)),ATEMP1
#ifdef debug
/*****/ movl IMM(1),DISP(PSTATE_REG,SLOT(58))
#endif
BRAW( resume_task)
LBL(task_not_ready1):
clrl IND(ATEMP1)
#endif
LBL(find_work):
LOG(EVENT_IDLE,log1)
LBL(try_our_workq):
/* Try removing task from our own workq. */
movl FALSE_REG,DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(lock_workq1):
tstl DISP(PSTATE_REG,SLOT(WORKQ_LOCKV))
BNES( lock_workq1)
movl DISP(PSTATE_REG,SLOT(WORKQ_HEAD)),ATEMP1
CMPL( ATEMP1,NULL_REG)
BEQS( empty_queue1)
movl PDEC(ATEMP1),ATEMP2
movl ATEMP2,DISP(PSTATE_REG,SLOT(WORKQ_HEAD))
CMPL( ATEMP2,NULL_REG)
BNES( done1)
movl ATEMP2,DISP(PSTATE_REG,SLOT(WORKQ_TAIL))
LBL(done1):
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
/* Check if task is really READY */
movl DISP(ATEMP1,SLOT(1)),ATEMP1
#ifdef MAINTAIN_TASK_STATUS
CMPL( ATEMP1,FALSE_REG)
BEQS( try_our_workq)
lea DISP(ATEMP1,SLOT(TASK_LOCKV)+4-SCM_type_SUBTYPED),ATEMP1
LBL(lock_task2):
LOCK_ATEMP1(lock2)
tstl DISP(ATEMP1,SLOT(TASK_LOCKO-TASK_LOCKV))
BEQS( task_locked2)
clrl IND(ATEMP1)
BRAS( lock_task2)
LBL(task_not_ready2):
clrl IND(ATEMP1)
BRAS( try_our_workq)
LBL(task_locked2):
movl DISP(ATEMP1,SLOT(TASK_STATUS-TASK_LOCKV)),DTEMP1
btst DTEMP1,PAIR_REG
BNES( task_not_ready2)
movl DTEMP1,ATEMP2 /* remove task from workq */
movl FALSE_REG,IND(ATEMP2)
/* Change task's status to RUNNING */
movl PSTATE_REG,DISP(ATEMP1,SLOT(TASK_STATUS-TASK_LOCKV))
clrl IND(ATEMP1)
lea DISP(ATEMP1,-(SLOT(TASK_LOCKV)+4-SCM_type_SUBTYPED)),ATEMP1
#endif
#ifdef debug
/*****/ movl IMM(2),DISP(PSTATE_REG,SLOT(58))
#endif
BRAW( resume_task)
LBL(empty_queue1):
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(our_workq_empty):
movl FALSE_REG,DISP(PSTATE_REG,SLOT(CURRENT_TASK))
movl FALSE_REG,DISP(PSTATE_REG,SLOT(PARENT_RET))
movl FALSE_REG,DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl FALSE_REG,DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
moveq IMM(INTR_LATENCY_AFTER_STEAL-1),INTR_TIMER_REG
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#ifdef MESSAGE_PASSING_STEAL
/* Prevent other processors from trying to steal from us. */
movl LTQ_TAIL_REG,DISP(PSTATE_REG,SLOT(LTQ_TAIL))
#ifdef SYNCHRONOUS_STEAL
LBL(wait_for_request):
tstl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
BEQS( no_steal)
movl DISP(PSTATE_REG,SLOT(THIEF)),DTEMP1
BEQS( wait_for_request)
clrl DISP(PSTATE_REG,SLOT(THIEF))
clrl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
movl DTEMP1,ATEMP1
clrl DISP(ATEMP1,SLOT(RESPONSE))
LBL(no_steal):
#endif
#endif
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
LBL(try_to_steal_from_other_workq):
movl DISP(PSTATE_REG,SLOT(STEAL_SCAN)),PVM2_REG
lea DISP(PSTATE_REG,SLOT(PS+MAX_NB_PROC)),ATEMP2
addl PVM2_REG,ATEMP2
LBL(next_processor):
subql IMM(4),PVM2_REG
BLEW( scan_done)
LBL(check_workq):
subql IMM(4),ATEMP2
LBL(check_same_workq):
movl IND(ATEMP2),ATEMP1
CMPL( DISP(ATEMP1,SLOT(WORKQ_HEAD)),NULL_REG)
BEQW( empty_queue3)
lea DISP(ATEMP1,SLOT(WORKQ_LOCKV)),ATEMP1
LBL(lock_workq2):
LOCK_ATEMP1(lock3)
tstl DISP(ATEMP1,SLOT(WORKQ_LOCKO-WORKQ_LOCKV))
BEQS( workq_locked)
clrl IND(ATEMP1)
BRAS( lock_workq2)
LBL(workq_locked):
movl DISP(ATEMP1,SLOT(WORKQ_HEAD-WORKQ_LOCKV)),PVM0_REG
CMPL( PVM0_REG,NULL_REG)
BEQW( empty_queue2)
movl PDEC(PVM0_REG),DTEMP1
movl DTEMP1,DISP(ATEMP1,SLOT(WORKQ_HEAD-WORKQ_LOCKV))
CMPL( DTEMP1,NULL_REG)
BNES( done2)
movl DTEMP1,DISP(ATEMP1,SLOT(WORKQ_TAIL-WORKQ_LOCKV))
LBL(done2):
clrl IND(ATEMP1)
/* Check if task is really READY */
movl DISP(PVM0_REG,SLOT(1)),ATEMP1
#ifdef MAINTAIN_TASK_STATUS
CMPL( ATEMP1,FALSE_REG)
BEQS( check_same_workq)
lea DISP(ATEMP1,SLOT(TASK_LOCKV)+4-SCM_type_SUBTYPED),ATEMP1
LBL(lock_task3):
LOCK_ATEMP1(lock4)
tstl DISP(ATEMP1,SLOT(TASK_LOCKO-TASK_LOCKV))
BEQS( task_locked3)
clrl IND(ATEMP1)
BRAS( lock_task3)
LBL(task_not_ready3):
clrl IND(ATEMP1)
BRAS( check_same_workq)
LBL(task_locked3):
movl DISP(ATEMP1,SLOT(TASK_STATUS-TASK_LOCKV)),DTEMP1
btst DTEMP1,PAIR_REG
BNES( task_not_ready3)
movl DTEMP1,ATEMP2 /* remove task from workq */
movl FALSE_REG,IND(ATEMP2)
/* Change task's status to RUNNING */
movl PSTATE_REG,DISP(ATEMP1,SLOT(TASK_STATUS-TASK_LOCKV))
clrl IND(ATEMP1)
lea DISP(ATEMP1,-(SLOT(TASK_LOCKV)+4-SCM_type_SUBTYPED)),ATEMP1
#endif
movl PVM2_REG,DISP(PSTATE_REG,SLOT(STEAL_SCAN))
#ifdef debug
/*****/ movl IMM(3),DISP(PSTATE_REG,SLOT(58))
#endif
LBL(resume_task):
/* Resume task. */
movl ATEMP1,DISP(PSTATE_REG,SLOT(CURRENT_TASK))
movl DISP(ATEMP1,SLOT(TASK_CONT_RET)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_RET))
movl DISP(ATEMP1,SLOT(TASK_CONT_FRAME)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl DISP(ATEMP1,SLOT(TASK_CONT_DYN_ENV)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
movl DISP(ATEMP1,SLOT(TASK_VALUE)+4-SCM_type_SUBTYPED),PVM1_REG
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl DISP(PSTATE_REG,SLOT(BOS_RET)),DISP(PSTATE_REG,SLOT(57))
#endif
movl PVM1_REG,PVM0_REG
movl PVM1_REG,PVM2_REG
movl PVM1_REG,PVM3_REG
movl PVM1_REG,PVM4_REG
LOG(EVENT_WORKING,log2)
movl DISP(PSTATE_REG,SLOT(BOS_RET)),ATEMP1
jmp IND(ATEMP1)
LBL(empty_queue2):
clrl IND(ATEMP1)
lea DISP(ATEMP1,-SLOT(WORKQ_LOCKV)),ATEMP1
LBL(empty_queue3):
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#ifdef MESSAGE_PASSING_STEAL
/* Check if anything to steal. */
movl DISP(ATEMP1,SLOT(LTQ_HEAD)),DTEMP1
CMPL( DISP(ATEMP1,SLOT(LTQ_TAIL)),DTEMP1)
BEQW( next_processor)
#ifdef SYNCHRONOUS_STEAL
movl ATEMP1,PVM4_REG
/* Try to become thief. */
movl ATEMP1,DTEMP1
addl IMM(SLOT(STEAL_LOCKV)),DTEMP1
READ_AND_SET_DTEMP1
tstl DTEMP1
BNEW( next_processor)
movl PVM4_REG,ATEMP1
movl DISP(ATEMP1,SLOT(LTQ_HEAD)),DTEMP1
CMPL( DISP(ATEMP1,SLOT(LTQ_TAIL)),DTEMP1)
BNES( we_are_thief)
clrl DISP(ATEMP1,SLOT(STEAL_LOCKV))
BRAW( next_processor)
LBL(we_are_thief):
/* Send steal message to victim. */
movl FALSE_REG,DISP(PSTATE_REG,SLOT(RESPONSE))
movl PSTATE_REG,DISP(ATEMP1,SLOT(THIEF))
movl IMM(-1),IND(ATEMP1)
LOG(EVENT_STEALING,log3)
/* Wait for response. */
movl PVM2_REG,DISP(PSTATE_REG,SLOT(STEAL_SCAN))
LBL(wait):
tstl DISP(PSTATE_REG,SLOT(INTR_BARRIER))
BEQS( ret3)
clrl DISP(PSTATE_REG,SLOT(INTR_BARRIER))
lea PC_IND(ret3),PVM0_REG
movl PVM0_REG,PVM1_REG
movl PVM0_REG,PVM2_REG
movl PVM0_REG,PVM3_REG
movl PVM0_REG,PVM4_REG
movl CONST(0),ATEMP1 /* Call ##barrier */
moveq IMM(1),DTEMP1
jmp IND(ATEMP1)
RETURN(ret3,0,0):
movl DISP(PSTATE_REG,SLOT(RESPONSE)),ATEMP1
CMPL( ATEMP1,FALSE_REG)
BEQS( wait)
clrl DISP(PSTATE_REG,SLOT(RESPONSE))
#ifdef debug
/*****/ movl ATEMP1,DISP(PSTATE_REG,SLOT(58))
#endif
movl ATEMP1,DTEMP1
BNEW( resume_task)
LOG(EVENT_IDLE,log4)
BRAW( try_to_steal_from_other_workq)
#else
/* ASYNCHRONOUS_STEAL */
movl FALSE_REG,DISP(ATEMP1,SLOT(WORK_REQUEST))
movl IMM(-1),IND(ATEMP1)
BRAW( next_processor)
#endif
/*---------------------------------------------------------------------------*/
#else
/* SHARED_MEMORY_STEAL */
/* acquire steal_lock */
movl DISP(ATEMP1,SLOT(STEAL_LOCKO)),DTEMP1
BNEW( next_processor)
movl ATEMP1,PVM4_REG
/* Try to become thief. */
movl ATEMP1,DTEMP1
addl IMM(SLOT(STEAL_LOCKV)),DTEMP1
READ_AND_SET_DTEMP1
tstl DTEMP1
BNEW( next_processor)
movl PVM4_REG,ATEMP1
movl DISP(ATEMP1,SLOT(STEAL_LOCKO)),DTEMP1
BNES( fail)
movl DISP(ATEMP1,SLOT(LTQ_HEAD)),PVM0_REG
addql IMM(4),PVM0_REG
movl PVM0_REG,DISP(ATEMP1,SLOT(LTQ_HEAD))
movl DISP(PVM0_REG,-SLOT(1)),DTEMP1
BNES( we_are_thief)
subql IMM(4),PVM0_REG
movl PVM0_REG,DISP(ATEMP1,SLOT(LTQ_HEAD))
LBL(fail):
clrl DISP(ATEMP1,SLOT(STEAL_LOCKV))
BRAW( next_processor)
LBL(we_are_thief):
movl PVM2_REG,DISP(PSTATE_REG,SLOT(STEAL_SCAN))
/* setup parent task */
movl DISP(PSTATE_REG,SLOT(TEMP_TASK)),PVM2_REG
movl PVM2_REG,DISP(PSTATE_REG,SLOT(CURRENT_TASK))
movl PVM2_REG,ATEMP2
movl DISP(ATEMP2,SLOT(TASK_SYNC_PH)+4-SCM_type_SUBTYPED),PVM1_REG
#ifdef MAINTAIN_TASK_STATUS
/* Link placeholder to current task so that it can get resumed when the */
/* placeholder is touched (and the task is READY). */
movl PVM1_REG,ATEMP2
movl DISP(ATEMP1,SLOT(CURRENT_TASK)),DISP(ATEMP2,SLOT(PH_TASK)-SCM_type_PLACEHOLDER)
movl PVM2_REG,ATEMP2
movl PSTATE_REG,DISP(ATEMP2,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
/* DTEMP1 = lazy task frame pointer */
movl DTEMP1,ATEMP2 /* get task's return address */
movl IND(ATEMP2),PVM3_REG
movl DISP(ATEMP1,SLOT(PARENT_RET)),DISP(PSTATE_REG,SLOT(PARENT_RET))
movl DISP(ATEMP1,SLOT(PARENT_FRAME)),DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl DISP(ATEMP1,SLOT(CURRENT_DYN_ENV)),DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
movl PVM3_REG,DISP(ATEMP1,SLOT(PARENT_RET))
subql IMM(8),PVM3_REG /* convert return adr to normal one */
/* Make child's continuation frame. */
movl PVM3_REG,PDEC(HEAP_REG)
movl PVM2_REG,PDEC(HEAP_REG)
/* katz/weise continuations would require stolen stack frame to be put on heap
movl DISP(ATEMP1,SLOT(PARENT_FRAME)),PDEC(HEAP_REG)
*/
movl FALSE_REG,PDEC(HEAP_REG)
movl IMM(3*0x400+(SCM_subtype_FRAME*8)),PDEC(HEAP_REG)
lea DISP(HEAP_REG,SCM_type_SUBTYPED),ATEMP2
movl ATEMP2,DISP(ATEMP1,SLOT(PARENT_FRAME))
/* copy victim's stack */
movl DISP(PVM0_REG,-SLOT(2)),PVM0_REG /* get base of continuation */
movl DTEMP1,ATEMP2
movl PVM0_REG,DTEMP1
subl ATEMP2,DTEMP1 /* DTEMP1 = length of stack area to copy */
subl DTEMP1,SP
movl SP,PVM0_REG
lsrl IMM(2),DTEMP1
subql IMM(1),DTEMP1
LBL(loop):
movl PINC(ATEMP2),PINC(PVM0_REG)
DBRA( DTEMP1,loop)
/* unlock steal_lock */
clrl DISP(ATEMP1,SLOT(STEAL_LOCKV))
addql IMM(8),DISP(PSTATE_REG,SLOT(COUNT1))
MAKE_TEMP_TASK
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl PVM3_REG,DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
movl PVM3_REG,ATEMP2
/* Resume task. */
movl PVM1_REG,PVM0_REG
movl PVM1_REG,PVM2_REG
movl PVM1_REG,PVM3_REG
movl PVM1_REG,PVM4_REG
LOG(EVENT_WORKING,log5)
jmp IND(ATEMP2)
#endif
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
LBL(scan_done):
movl DISP(PSTATE_REG,SLOT(NB_PROCESSORS)),PVM2_REG
asrl IMM(1),PVM2_REG
movl PVM2_REG,DISP(PSTATE_REG,SLOT(STEAL_SCAN))
tstl DISP(PSTATE_REG,SLOT(INTR_BARRIER))
BEQS( ret4)
clrl DISP(PSTATE_REG,SLOT(INTR_BARRIER))
lea PC_IND(ret4),PVM0_REG
movl PVM0_REG,PVM1_REG
movl PVM0_REG,PVM2_REG
movl PVM0_REG,PVM3_REG
movl PVM0_REG,PVM4_REG
movl CONST(0),ATEMP1 /* Call ##barrier */
moveq IMM(1),DTEMP1
jmp IND(ATEMP1)
RETURN(ret4,0,0):
BRAW( try_to_steal_from_other_workq)
CONSTS(1)
PRIMITIVE("##barrier")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(30,x)
BEGIN("###_kernel.determine!")
#ifdef DETERMINE_IS_STRICT
btst PVM2_REG,PLACEHOLDER_REG
BNES( touched)
movl PVM0_REG,PDEC(SP)
movl PVM1_REG,PDEC(SP)
TRAP(TOUCH_trap+2,touch,2,1)
movl PINC(SP),PVM1_REG
movl PINC(SP),PVM0_REG
LBL(touched):
#endif
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
CONSTS(1)
PRIMITIVE("###_kernel.non-strict-determine!")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(31,x)
BEGIN("###_kernel.non-strict-determine!")
movl PVM0_REG,PDEC(SP)
LOG(EVENT_DETERMINE,log1)
btst PVM1_REG,PLACEHOLDER_REG
BNES( already_determined)
movl PVM1_REG,ATEMP2
lea DISP(ATEMP2,SLOT(PH_QUEUE)-SCM_type_PLACEHOLDER),ATEMP2
LOCK_ATEMP2(lock1)
CMPL( DTEMP1,FALSE_REG)
BNES( undetermined)
movl DTEMP1,IND(ATEMP2)
LBL(already_determined):
PREV_LOG(2,log2)
movl PINC(SP),PVM0_REG
movl CONST(0),ATEMP1 /* jump to ##exception.placeholder-already-determined */
moveq IMM(1),DTEMP1 /* passing 0 argument */
jmp IND(ATEMP1)
LBL(undetermined):
movl PVM2_REG,DISP(ATEMP2,SLOT(PH_VALUE-PH_QUEUE))
movl FALSE_REG,IND(ATEMP2)
/* DTEMP1 is list of tasks to restart. */
btst DTEMP1,PAIR_REG
BNES( tasks_restarted)
movl DTEMP1,PVM4_REG
LBL(next_task):
movl DTEMP1,ATEMP2
/* Setup task's return value. */
movl IND(ATEMP2),ATEMP1
movl PVM2_REG,DISP(ATEMP1,SLOT(TASK_VALUE)+4-SCM_type_SUBTYPED)
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to READY */
movl ATEMP2,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
movl DISP(ATEMP2,SLOT(-1)),DTEMP1
btst DTEMP1,PAIR_REG
BEQS( next_task)
/* Add tasks to workq. */
movl FALSE_REG,DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(lock_workq):
tstl DISP(PSTATE_REG,SLOT(WORKQ_LOCKV))
BNES( lock_workq)
movl DISP(PSTATE_REG,SLOT(WORKQ_TAIL)),ATEMP1
CMPL( ATEMP1,NULL_REG)
BNES( non_empty_queue)
movl PVM4_REG,DISP(PSTATE_REG,SLOT(WORKQ_HEAD))
BRAS( fix_tail)
LBL(non_empty_queue):
movl PVM4_REG,PDEC(ATEMP1)
LBL(fix_tail):
movl ATEMP2,DISP(PSTATE_REG,SLOT(WORKQ_TAIL))
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(tasks_restarted):
movl PVM2_REG,PVM1_REG
movl PVM2_REG,PVM3_REG
movl PVM2_REG,PVM4_REG
movl PINC(SP),PVM0_REG
PREV_LOG(2,log3)
movl PVM2_REG,DTEMP1 /* Required for the case of a return from a touch of d0 */
jmp IND(PVM0_REG)
CONSTS(1)
PRIMITIVE("##exception.placeholder-already-determined")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(32,x)
BEGIN("###_kernel.determine!-then-idle")
movl PVM0_REG,PDEC(SP)
#ifdef DETERMINE_IS_STRICT
btst PVM2_REG,PLACEHOLDER_REG
BNES( touched)
movl PVM1_REG,PDEC(SP)
movl PVM3_REG,PDEC(SP)
TRAP(TOUCH_trap+2,touch,3,1)
movl PINC(SP),PVM3_REG
movl PINC(SP),PVM1_REG
LBL(touched):
#endif
LOG(EVENT_DETERMINE,log1)
btst PVM1_REG,PLACEHOLDER_REG
BNES( already_determined)
movl PVM1_REG,ATEMP2
lea DISP(ATEMP2,SLOT(PH_QUEUE)-SCM_type_PLACEHOLDER),ATEMP2
LOCK_ATEMP2(lock1)
CMPL( DTEMP1,FALSE_REG)
BNES( undetermined)
movl DTEMP1,IND(ATEMP2)
LBL(already_determined):
PREV_LOG(2,log2)
movl PINC(SP),PVM0_REG
movl CONST(1),ATEMP1 /* jump to ##exception.placeholder-already-determined */
moveq IMM(1),DTEMP1 /* passing 0 argument */
jmp IND(ATEMP1)
LBL(no_task_to_restart):
movl PVM3_REG,PVM1_REG
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
LBL(undetermined):
movl PINC(SP),PVM0_REG
movl PVM2_REG,DISP(ATEMP2,SLOT(PH_VALUE-PH_QUEUE))
movl FALSE_REG,IND(ATEMP2)
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to DEAD */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP1
movl FALSE_REG,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
/* DTEMP1 is list of tasks to restart. */
btst DTEMP1,PAIR_REG
BNES( no_task_to_restart)
movl DTEMP1,ATEMP2
movl IND(ATEMP2),PVM3_REG
movl PDEC(ATEMP2),DTEMP1
btst DTEMP1,PAIR_REG
BNES( tasks_restarted)
movl DTEMP1,PVM4_REG
LBL(next_task):
movl DTEMP1,ATEMP2
/* Setup task's return value. */
movl IND(ATEMP2),ATEMP1
movl PVM2_REG,DISP(ATEMP1,SLOT(TASK_VALUE)+4-SCM_type_SUBTYPED)
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to READY */
movl ATEMP2,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
movl DISP(ATEMP2,SLOT(-1)),DTEMP1
btst DTEMP1,PAIR_REG
BEQS( next_task)
/* Add tasks to workq. */
movl FALSE_REG,DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(lock_workq):
tstl DISP(PSTATE_REG,SLOT(WORKQ_LOCKV))
BNES( lock_workq)
movl DISP(PSTATE_REG,SLOT(WORKQ_TAIL)),ATEMP1
CMPL( ATEMP1,NULL_REG)
BNES( non_empty_queue)
movl PVM4_REG,DISP(PSTATE_REG,SLOT(WORKQ_HEAD))
BRAS( fix_tail)
LBL(non_empty_queue):
movl PVM4_REG,PDEC(ATEMP1)
LBL(fix_tail):
movl ATEMP2,DISP(PSTATE_REG,SLOT(WORKQ_TAIL))
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(tasks_restarted):
movl PVM3_REG,ATEMP1
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to RUNNING */
movl PSTATE_REG,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
/* Resume task. */
movl ATEMP1,DISP(PSTATE_REG,SLOT(CURRENT_TASK))
movl DISP(ATEMP1,SLOT(TASK_CONT_RET)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_RET))
movl DISP(ATEMP1,SLOT(TASK_CONT_FRAME)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl DISP(ATEMP1,SLOT(TASK_CONT_DYN_ENV)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl DISP(PSTATE_REG,SLOT(BOS_RET)),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
movl PVM2_REG,PVM1_REG
movl PVM1_REG,PVM0_REG
movl PVM1_REG,PVM3_REG
movl PVM1_REG,PVM4_REG
LOG(EVENT_WORKING,log3)
movl DISP(PSTATE_REG,SLOT(BOS_RET)),ATEMP1
jmp IND(ATEMP1)
CONSTS(2)
PRIMITIVE("###_kernel.idle")
PRIMITIVE("##exception.placeholder-already-determined")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(33,x)
BEGIN("###_kernel.touch")
movl PVM0_REG,PDEC(SP)
movl ATEMP2,PVM4_REG
/* Check if the placeholder was generated by a DELAY. */
tstl DISP(ATEMP2,SLOT(PH_DELAY)-SCM_type_PLACEHOLDER)
BEQS( not_delay_ph2)
lea DISP(ATEMP2,SLOT(PH_QUEUE)-SCM_type_PLACEHOLDER),ATEMP2
LOCK_ATEMP2(lock1)
movl DISP(ATEMP2,SLOT(PH_DELAY)-SLOT(PH_QUEUE)),PVM1_REG
BEQS( not_delay_ph1)
clrl DISP(ATEMP2,SLOT(PH_DELAY)-SLOT(PH_QUEUE))
movl DTEMP1,IND(ATEMP2)
movl PVM4_REG,PDEC(SP)
/* Restore delayed computation. */
subql IMM(SCM_type_SUBTYPED),PVM1_REG
movl PVM1_REG,ATEMP1
movl PINC(ATEMP1),DTEMP1
lsrl IMM(8),DTEMP1
subql IMM(4),DTEMP1
subl DTEMP1,SP
lsrl IMM(2),DTEMP1
movl PINC(ATEMP1),PVM0_REG
subql IMM(1),DTEMP1
movl SP,ATEMP2
LBL(copy):
movl PINC(ATEMP1),PINC(ATEMP2)
DBRA( DTEMP1,copy)
lea PC_IND(ret1),ATEMP1
moveq IMM(0),PVM1_REG
movw DISP(PVM0_REG,-4),PVM1_REG /* get link */
movl ATEMP1,INXW(SP,PVM1_REG,0)
PREV_LOG(2,log1)
movl PVM2_REG,PVM1_REG
jmp IND(PVM0_REG)
RETURN(ret1,2,1):
movl PVM1_REG,PVM2_REG
movl PINC(SP),PVM1_REG
movl PINC(SP),PVM0_REG
movl CONST(3),ATEMP1 /* jump to ###_kernel.determine! */
jmp IND(ATEMP1)
LBL(not_delay_ph1):
movl DTEMP1,IND(ATEMP2)
LBL(not_delay_ph2):
/* Call ###_kernel.transfer-lazy-tasks-to-heap. */
pea PC_IND(ret2)
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
RETURN(ret2,1,1):
/* Call ###_kernel.transfer-stack-to-heap. */
/* ###_kernel.transfer-lazy-tasks-to-heap has reserved enough */
/* space, so no GC check required. */
pea PC_IND(ret3)
movl CONST(1),ATEMP1
jmp IND(ATEMP1)
LBL(ret3):
/* Save state of current task. */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP1
movl PINC(SP),PVM0_REG
movl PVM0_REG,DISP(ATEMP1,SLOT(TASK_CONT_RET)+4-SCM_type_SUBTYPED)
movl PVM2_REG,DISP(ATEMP1,SLOT(TASK_CONT_FRAME)+4-SCM_type_SUBTYPED)
movl DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV)),DISP(ATEMP1,SLOT(TASK_CONT_DYN_ENV)+4-SCM_type_SUBTYPED)
movl FALSE_REG,DISP(ATEMP1,SLOT(TASK_VALUE)+4-SCM_type_SUBTYPED)
movl ATEMP1,PDEC(HEAP_REG)
movl HEAP_REG,PVM3_REG
/* Final check for determinedness. */
btst PVM4_REG,PLACEHOLDER_REG
BNES( already_determined)
movl PVM4_REG,ATEMP2
lea DISP(ATEMP2,SLOT(PH_QUEUE)-SCM_type_PLACEHOLDER),ATEMP2
LOCK_ATEMP2(lock2)
CMPL( DTEMP1,FALSE_REG)
BNES( undetermined)
movl DTEMP1,IND(ATEMP2)
movl DISP(ATEMP2,SLOT(PH_VALUE-PH_QUEUE)),PVM4_REG
LBL(already_determined):
addql IMM(4),HEAP_REG
/* Resume task. */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP2
movl DISP(ATEMP2,SLOT(TASK_CONT_RET)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_RET))
movl DISP(ATEMP2,SLOT(TASK_CONT_FRAME)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl DISP(ATEMP2,SLOT(TASK_CONT_DYN_ENV)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl DISP(PSTATE_REG,SLOT(BOS_RET)),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
movl PVM4_REG,PVM0_REG
movl PVM4_REG,PVM1_REG
movl PVM4_REG,PVM2_REG
movl PVM4_REG,PVM3_REG
PREV_LOG(2,log2)
movl DISP(PSTATE_REG,SLOT(BOS_RET)),ATEMP1
jmp IND(ATEMP1)
LBL(undetermined):
movl DTEMP1,PDEC(HEAP_REG)
movl PVM3_REG,IND(ATEMP2)
addql IMM(8),DISP(PSTATE_REG,SLOT(COUNT2))
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to WAITING */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP1
movl NULL_REG,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
/* Resume placeholder's task if possible (i.e. if it is READY) */
movl DISP(ATEMP2,SLOT(PH_TASK-PH_QUEUE)),PVM1_REG
movl CONST(2),ATEMP1
jmp IND(ATEMP1)
#else
moveq IMM(0),PVM1_REG
movl CONST(2),ATEMP1
jmp IND(ATEMP1)
#endif
CONSTS(4)
PRIMITIVE("###_kernel.transfer-lazy-tasks-to-heap")
PRIMITIVE("###_kernel.transfer-stack-to-heap")
PRIMITIVE("###_kernel.idle")
PRIMITIVE("###_kernel.determine!")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(34,x)
BEGIN("###_kernel.transfer-lazy-task-chunk-to-heap")
/* On entry: */
/* top of stack = exit address */
/* PVM2_REG = processor to respond to or task list */
/* PVM3_REG = stack base */
/* ATEMP1 = LTQ_HEAD */
/* On exit: */
/* PVM2_REG = new task list */
/* PVM4_REG preserved */
/* PVM0_REG, PVM1_REG, PVM3_REG, DTEMP1, ATEMP1, ATEMP2 modified */
/* It is assumed that: */
/* - there is at least one lazy task on the lazy task queue */
/* - no GC will be required (there is enough free space in the heap) */
#ifndef MESSAGE_PASSING_STEAL
movl ATEMP1,PVM1_REG
#endif
addql IMM(4),ATEMP1 /* adjust LTQ_HEAD as though taking one task */
lea DISP(LTQ_TAIL_REG,-SLOT(MIN_VICTIM_TASKS)),PVM0_REG
CMPL( ATEMP1,PVM0_REG)
BLSS( found_split_point2)
movl DISP(PVM0_REG,-SLOT(1)),DTEMP1
movl PVM3_REG,ATEMP2
lea DISP(ATEMP2,-SLOT(MAX_TASK_FRAME_CHUNK_SIZE)),ATEMP2
CMPL( DTEMP1,ATEMP2)
BLSS( found_split_point1)
LBL(loop1):
CMPL( PINC(ATEMP1),ATEMP2)
BLSS( loop1)
subql IMM(4),ATEMP1
BRAS( found_split_point2)
LBL(found_split_point1):
movl PVM0_REG,ATEMP1
LBL(found_split_point2):
#ifndef MESSAGE_PASSING_STEAL
movl PVM1_REG,ATEMP2
LBL(loop2):
addql IMM(4),ATEMP2
clrl DISP(ATEMP2,-SLOT(2))
CMPL( ATEMP2,ATEMP1)
BNES( loop2)
#endif
movl CONST(0),ATEMP2
jmp IND(ATEMP2)
CONSTS(1)
PRIMITIVE("###_kernel.transfer-lazy-task-to-heap")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(35,x)
BEGIN("###_kernel.transfer-lazy-task-to-heap")
/* On entry: */
/* top of stack = exit address */
/* PVM2_REG = processor to respond to or task list */
/* PVM3_REG = stack base */
/* ATEMP1 = LTQ split point */
/* On exit: */
/* PVM2_REG = new task list */
/* PVM4_REG preserved */
/* PVM0_REG, PVM1_REG, PVM3_REG, DTEMP1, ATEMP1, ATEMP2 modified */
/* It is assumed that: */
/* - there is at least one lazy task on the lazy task queue */
/* - no GC will be required (there is enough free space in the heap) */
movl ATEMP1,DISP(PSTATE_REG,SLOT(LTQ_HEAD))
movl DISP(ATEMP1,-SLOT(1)),ATEMP2
movl IND(ATEMP2),DTEMP1
/* DTEMP1 = task's return adr, ATEMP2 = task boundary */
/* Now, we must replace the child's return address with the 'bottom of stack'*/
/* return address. Because we don't really know where the return address */
/* is (but we do know its value) we must scan the child's stack until we */
/* have found the address. */
movl ATEMP2,ATEMP1
LBL(loop1):
CMPL( PDEC(ATEMP1),DTEMP1)
BNES( loop1)
movl DISP(PSTATE_REG,SLOT(BOS_RET)),PVM0_REG
movl PVM0_REG,IND(ATEMP1)
/* Similarly, replace 'bottom of stack' return address by correct one */
movl PVM3_REG,ATEMP1
LBL(loop2):
CMPL( PDEC(ATEMP1),PVM0_REG)
BNES( loop2)
movl DISP(PSTATE_REG,SLOT(PARENT_RET)),IND(ATEMP1)
/* Next, we must find the dynamic environment of the parent. */
movl DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV)),PDEC(SP) /*guard*/
movl DISP(PSTATE_REG,SLOT(DEQ_TAIL)),PVM0_REG
movl SP,PDEC(PVM0_REG)
movl DISP(PSTATE_REG,SLOT(DEQ_HEAD)),PVM0_REG
LBL(loop3):
CMPL( PDEC(PVM0_REG),ATEMP2)
BCSS( loop3)
addql IMM(4),PVM0_REG
movl PVM0_REG,DISP(PSTATE_REG,SLOT(DEQ_HEAD))
/* Setup parent task. */
movl DISP(PSTATE_REG,SLOT(TEMP_TASK)),ATEMP1
movl PDEC(PVM0_REG),PVM0_REG
movl IND(PVM0_REG),DISP(ATEMP1,SLOT(TASK_CONT_DYN_ENV)+4-SCM_type_SUBTYPED)
subql IMM(8),DTEMP1 /* convert return adr to normal one */
movl DTEMP1,DISP(ATEMP1,SLOT(TASK_CONT_RET)+4-SCM_type_SUBTYPED)
#ifdef MAINTAIN_TASK_STATUS
/* Link placeholder to current task so that it can get resumed when the */
/* placeholder is touched (and the task is READY). */
movl DISP(ATEMP1,SLOT(TASK_SYNC_PH)+4-SCM_type_SUBTYPED),PVM0_REG
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),DISP(PVM0_REG,SLOT(PH_TASK)-SCM_type_PLACEHOLDER)
#endif
addql IMM(4),SP
/* Allocate a single frame object for task's continuation */
/* Compute size of frame object */
subl ATEMP2,PVM3_REG
addql IMM(4),PVM3_REG
/* Allocate frame object. */
movl PVM3_REG,PVM1_REG
addw IMM(11),PVM1_REG
andw IMM(-8),PVM1_REG
subl PVM1_REG,HEAP_REG
asll IMM(8),PVM3_REG
movb IMM(SCM_subtype_FRAME*8),PVM3_REG
movl PVM3_REG,IND(HEAP_REG)
clrl DISP(HEAP_REG,SLOT(1))
lea DISP(HEAP_REG,SCM_type_SUBTYPED),PVM0_REG
movl PVM0_REG,DISP(ATEMP1,SLOT(TASK_CONT_FRAME)+4-SCM_type_SUBTYPED)
/* Make child's continuation frame. */
movl DTEMP1,PDEC(HEAP_REG)
movl ATEMP1,PDEC(HEAP_REG)
movl PVM0_REG,PDEC(HEAP_REG)
movl IMM(3*0x400+(SCM_subtype_FRAME*8)),PDEC(HEAP_REG)
movl PVM0_REG,DTEMP1
/* Check were parent task should go. */
movl PVM2_REG,PVM1_REG
BEQS( transfer_to_workq)
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#ifdef MESSAGE_PASSING_STEAL
#ifdef SYNCHRONOUS_STEAL
andw IMM(7),PVM2_REG
BNES( transfer_to_task_list)
LBL(transfer_to_thief):
/* Transfer task to thief processor. */
movl PVM1_REG,PVM0_REG
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to RUNNING */
movl PVM0_REG,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
movl ATEMP1,DISP(PVM0_REG,SLOT(RESPONSE))
BRAS( copy_stack)
LBL(transfer_to_task_list):
#endif
#endif
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/* Add parent task to head of task list. */
movl ATEMP1,PDEC(HEAP_REG)
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to READY */
movl HEAP_REG,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
movl HEAP_REG,PVM2_REG
movl PVM1_REG,PDEC(HEAP_REG)
BRAS( copy_stack)
LBL(transfer_to_workq):
/* Add parent task to workq. */
movl ATEMP1,PDEC(HEAP_REG)
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to READY */
movl HEAP_REG,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
movl FALSE_REG,DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(lock_workq):
tstl DISP(PSTATE_REG,SLOT(WORKQ_LOCKV))
BNES( lock_workq)
movl DISP(PSTATE_REG,SLOT(WORKQ_TAIL)),ATEMP1
CMPL( ATEMP1,NULL_REG)
BNES( non_empty_queue)
movl HEAP_REG,DISP(PSTATE_REG,SLOT(WORKQ_HEAD))
BRAS( fix_tail)
LBL(non_empty_queue):
movl HEAP_REG,PDEC(ATEMP1)
LBL(fix_tail):
movl HEAP_REG,DISP(PSTATE_REG,SLOT(WORKQ_TAIL))
movl NULL_REG,PDEC(HEAP_REG)
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(copy_stack):
/* Copy stack to frame object. */
/* PVM3_REG=frame_header, ATEMP2=start_of_stack, DTEMP1=frame_object */
lsrl IMM(8),PVM3_REG
lsrl IMM(2),PVM3_REG
subql IMM(2),PVM3_REG
movl DTEMP1,ATEMP1
addql IMM(SLOT(2)-SCM_type_SUBTYPED),ATEMP1
LBL(copy_loop):
movl PINC(ATEMP2),PINC(ATEMP1)
DBRA( PVM3_REG,copy_loop)
movl DTEMP1,ATEMP1
movl DISP(PSTATE_REG,SLOT(PARENT_FRAME)),DISP(ATEMP1,SLOT(1)-SCM_type_SUBTYPED)
/* Setup new parent continuation. */
lea DISP(ATEMP1,-SLOT(4)),ATEMP1
movl ATEMP1,DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl CONST(0),ATEMP1
addw IMM(16),ATEMP1
movl ATEMP1,DISP(PSTATE_REG,SLOT(PARENT_RET))
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl IND(SP),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
/* Return. */
addql IMM(8),DISP(PSTATE_REG,SLOT(COUNT1))
MAKE_TEMP_TASK
rts
CONSTS(1)
PRIMITIVE("###_kernel.task")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(36,x)
BEGIN("###_kernel.task")
/* This is the code that is run every time the child's continuation is */
/* returned from. */
RETURN(child_ret,2,1):
/* First, check if this is the first return from the child. */
movl IND(SP),ATEMP2 /* ATEMP2 = parent task */
movl PVM1_REG,PDEC(SP)
movl ATEMP2,DTEMP1
addl IMM(SLOT(TASK_SYNC_PH)+4-SCM_type_SUBTYPED),DTEMP1
READ_AND_CLEAR_DTEMP1
btst DTEMP1,PLACEHOLDER_REG
BNES( not_first_ret)
/* If it is the first return, determine the synchronization placeholder */
/* and propagate the legitimacy. */
movl DTEMP1,PDEC(SP)
#ifdef LEGITIMACY
movl DISP(ATEMP2,SLOT(TASK_LEGIT)+4-SCM_type_SUBTYPED),PVM1_REG
/* Legitimacy placeholders can be determined with placeholders. */
/* So, it is wise to chase the placeholder before doing the determine. */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP2
movl DISP(ATEMP2,SLOT(TASK_LEGIT)+4-SCM_type_SUBTYPED),PVM2_REG
LBL(next):
btst PVM2_REG,PLACEHOLDER_REG
BNES( end_of_chase)
movl PVM2_REG,ATEMP1
movl DISP(ATEMP1,SLOT(PH_VALUE)-SCM_type_PLACEHOLDER),PVM2_REG
CMPL( ATEMP1,PVM2_REG)
BNES( next)
LBL(end_of_chase):
lea PC_IND(ret),PVM0_REG
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
RETURN(ret,4,1):
#endif
/* Determine value placeholder */
movl PINC(SP),PVM1_REG
movl PINC(SP),PVM2_REG
movl PINC(SP),PVM3_REG
movl PINC(SP),PVM0_REG
movl CONST(1),ATEMP1
jmp IND(ATEMP1)
LBL(not_first_ret):
movl PINC(SP),PVM1_REG
addql IMM(4),SP
rts
CONSTS(2)
PRIMITIVE("###_kernel.non-strict-determine!")
PRIMITIVE("###_kernel.determine!-then-idle")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(37,x)
BEGIN("###_kernel.transfer-lazy-tasks-to-heap")
/* On entry: */
/* top of stack = exit address */
/* On exit: */
/* PVM2_REG = task list */
/* PVM4_REG preserved */
/* PVM0_REG, PVM1_REG, PVM3_REG, DTEMP1, ATEMP2 modified */
/* We must make sure that there is enough free space for all the frames (so */
/* that we can avoid to check for GC on every one). If each frame is copied */
/* independently, the heap space required could be as much as 4 times the */
/* space used on the stack plus a certain amount for every lazy task. */
#ifndef MESSAGE_PASSING_STEAL
movl FALSE_REG,DISP(PSTATE_REG,SLOT(STEAL_LOCKO))
LBL(lock_steal1):
tstl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
BNES( lock_steal1)
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),ATEMP1
movl DISP(ATEMP1,-SLOT(1)),DTEMP1
clrl DISP(PSTATE_REG,SLOT(STEAL_LOCKO))
#else
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),ATEMP1
movl DISP(ATEMP1,-SLOT(1)),DTEMP1
#endif
subl SP,DTEMP1
asll IMM(2),DTEMP1
movl LTQ_TAIL_REG,PVM1_REG
subl ATEMP1,PVM1_REG
muluw IMM((TASK_SIZE+1)+(PH_SIZE*2)+PAIR_SIZE+6),PVM1_REG
addl PVM1_REG,DTEMP1
andw IMM(-8),DTEMP1
CMPL( DTEMP1,HEAP_REG)
subl DTEMP1,HEAP_REG /* allocate space for frames and check heap */
BCSS( do_gc)
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG) /* overflow */
BCCS( enough_space)
LBL(do_gc):
moveq IMM(0),PVM1_REG
movl DTEMP1,PDEC(SP)
TRAP(heap_alloc2_trap,alloc,2,1)
movl PINC(SP),DTEMP1
CMPL( DTEMP1,HEAP_REG)
subl DTEMP1,HEAP_REG /* allocate space for frames and check heap */
BCSS( stack_overflow)
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG) /* overflow */
BCCS( enough_space)
LBL(stack_overflow):
addl DTEMP1,HEAP_REG
/* continuation must be discarded... */
movl DISP(PSTATE_REG,SLOT(BOS_RET)),PVM0_REG
movl CONST(2),ATEMP1 /* jump to ##exception.stack-overflow proc */
moveq IMM(1),DTEMP1 /* passing 0 argument */
jmp IND(ATEMP1)
LBL(enough_space):
addl DTEMP1,HEAP_REG
/* At this point, we know that there is enough free space on the heap to */
/* copy the frames. */
/* Transfer a first task. */
movl NULL_REG,PVM2_REG /* specify task list up to now */
#ifndef MESSAGE_PASSING_STEAL
movl FALSE_REG,DISP(PSTATE_REG,SLOT(STEAL_LOCKO))
LBL(lock_steal2):
tstl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
BNES( lock_steal2)
/* fix PARENT_RET if it is a lazy future return point */
movl DISP(PSTATE_REG,SLOT(PARENT_RET)),PVM0_REG
tstw DISP(PVM0_REG,-6)
BPLS( fixed)
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),ATEMP1
movl DISP(ATEMP1,-SLOT(1)),ATEMP1
LBL(loop1):
CMPL( PDEC(ATEMP1),PVM0_REG)
BNES( loop1)
movl DISP(PSTATE_REG,SLOT(BOS_RET)),IND(ATEMP1)
movl CONST(3),PVM0_REG
addw IMM(16),PVM0_REG
movl PVM0_REG,DISP(PSTATE_REG,SLOT(PARENT_RET))
LBL(fixed):
#endif
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),ATEMP1
movl DISP(ATEMP1,-SLOT(1)),PVM3_REG
CMPL( LTQ_TAIL_REG,ATEMP1)
BEQS( tasks_transferred)
addql IMM(4),ATEMP1 /* adjust LTQ_HEAD by one task */
pea PC_IND(ret)
movl CONST(0),ATEMP2
jmp IND(ATEMP2)
LBL(ret):
movl PVM2_REG,DISP(PSTATE_REG,SLOT(TEMP1)) /* save first task */
/* Transfer the rest. */
LBL(loop2):
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),ATEMP1
movl DISP(ATEMP1,-SLOT(1)),PVM3_REG
CMPL( LTQ_TAIL_REG,ATEMP1)
BEQS( done)
pea PC_IND(loop2)
movl CONST(1),ATEMP2
jmp IND(ATEMP2)
LBL(done):
/* Put the tasks on the workq. */
movl FALSE_REG,DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(lock_workq):
tstl DISP(PSTATE_REG,SLOT(WORKQ_LOCKV))
BNES( lock_workq)
movl DISP(PSTATE_REG,SLOT(WORKQ_TAIL)),ATEMP1
CMPL( ATEMP1,NULL_REG)
BNES( non_empty_queue)
movl PVM2_REG,DISP(PSTATE_REG,SLOT(WORKQ_HEAD))
BRAS( fix_tail)
LBL(non_empty_queue):
movl PVM2_REG,PDEC(ATEMP1)
LBL(fix_tail):
movl DISP(PSTATE_REG,SLOT(TEMP1)),DISP(PSTATE_REG,SLOT(WORKQ_TAIL))
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(tasks_transferred):
#ifndef MESSAGE_PASSING_STEAL
clrl DISP(PSTATE_REG,SLOT(STEAL_LOCKO))
#endif
rts
CONSTS(4)
PRIMITIVE("###_kernel.transfer-lazy-task-to-heap")
PRIMITIVE("###_kernel.transfer-lazy-task-chunk-to-heap")
PRIMITIVE("##exception.stack-overflow")
PRIMITIVE("###_kernel.task")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(38,x)
BEGIN("###_kernel.transfer-stack-to-heap")
/* On entry: */
/* top of stack = exit address */
/* next on stack = continuation's return address */
/* On exit: */
/* top of stack = continuation's return address */
/* PVM2_REG = continuation's first frame */
/* PVM4_REG preserved */
/* PVM0_REG, PVM1_REG, PVM3_REG, DTEMP1, ATEMP1, ATEMP2 modified */
/* It is assumed that: */
/* - no GC will be required (there is enough free space in the heap) */
/* - there are no tasks on the stack */
movl DISP(PSTATE_REG,SLOT(BOS_RET)),PVM3_REG
lea DISP(SP,SLOT(1)),ATEMP2
movl PINC(ATEMP2),PVM0_REG
CMPL( PVM0_REG,PVM3_REG)
BNES( non_empty_stack)
movl DISP(PSTATE_REG,SLOT(PARENT_RET)),DISP(SP,SLOT(1))
movl DISP(PSTATE_REG,SLOT(PARENT_FRAME)),PVM2_REG
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl IND(SP),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
rts
LBL(non_empty_stack):
/* Chunk frames together. */
lea DISP(ATEMP2,SLOT(MAX_FRAME_CHUNK_SIZE)),ATEMP1
moveq IMM(0),PVM1_REG
movw DISP(PVM0_REG,-6),PVM1_REG /* get fs */
BGTS( normal_ret_a1)
#ifdef debug
/*****/ BEQS( dyn_env_ret_a1)
/*****/ jmp 3
/*****/LBL(dyn_env_ret_a1):
#endif
movw IMM(SLOT(DYN_ENV_FS)),PVM1_REG
LBL(normal_ret_a1):
addl ATEMP2,PVM1_REG
BRAS( try_to_add_next_frame1)
LBL(not_bottom_of_stack1):
movl PVM1_REG,ATEMP2
moveq IMM(0),PVM1_REG
movw DISP(PVM0_REG,-6),PVM1_REG /* get fs */
BGTS( normal_ret_b1)
#ifdef debug
/*****/ BEQS( dyn_env_ret_b1)
/*****/ jmp 5
/*****/LBL(dyn_env_ret_b1):
#endif
movw IMM(SLOT(DYN_ENV_FS)),PVM1_REG
LBL(normal_ret_b1):
addl ATEMP2,PVM1_REG
CMPL( ATEMP1,PVM1_REG)
BHIS( chunk_found1)
LBL(try_to_add_next_frame1):
addw DISP(PVM0_REG,-4),ATEMP2 /* add link */
movl IND(ATEMP2),PVM0_REG
CMPL( PVM0_REG,PVM3_REG) /* bottom of stack? */
BNES( not_bottom_of_stack1)
movl DISP(PSTATE_REG,SLOT(PARENT_RET)),IND(ATEMP2)
movl PVM1_REG,ATEMP2
LBL(chunk_found1): /* ATEMP2 = chunk's upper limit */
/* Now, compute size of frame object to hold chunk. */
movl ATEMP2,PVM1_REG
lea DISP(ATEMP1,-SLOT(MAX_FRAME_CHUNK_SIZE)),ATEMP2
subl ATEMP2,PVM1_REG
addql IMM(4),PVM1_REG
/* Allocate frame object. */
movl PVM1_REG,DTEMP1
addw IMM(11),DTEMP1
andw IMM(-8),DTEMP1
subl DTEMP1,HEAP_REG
asll IMM(8),PVM1_REG
movb IMM(SCM_subtype_FRAME*8),PVM1_REG
movl PVM1_REG,IND(HEAP_REG)
/* Remember where first frame object is. */
movl HEAP_REG,PVM2_REG
addql IMM(SCM_type_SUBTYPED),PVM2_REG
LBL(copy_stack):
/* Copy stack to frame object. */
/* PVM1_REG=frame_header, ATEMP2=start_of_chunk, HEAP_REG=frame_object */
lsrl IMM(8),PVM1_REG
lsrl IMM(2),PVM1_REG
subql IMM(2),PVM1_REG
lea DISP(HEAP_REG,SLOT(2)),ATEMP1
LBL(copy_loop):
movl PINC(ATEMP2),PINC(ATEMP1)
DBRA( PVM1_REG,copy_loop)
CMPL( PVM0_REG,PVM3_REG) /* bottom of stack? */
BNES( next_chunks)
movl DISP(PSTATE_REG,SLOT(PARENT_FRAME)),DISP(HEAP_REG,SLOT(1))
rts
LBL(next_chunks):
/* Process next chunk(s). */
lea DISP(ATEMP2,SLOT(MAX_FRAME_CHUNK_SIZE)),ATEMP1
moveq IMM(0),PVM1_REG
movw DISP(PVM0_REG,-6),PVM1_REG /* get fs */
BGTS( normal_ret_a2)
#ifdef debug
/*****/ BEQS( dyn_env_ret_a2)
/*****/ jmp 7
/*****/LBL(dyn_env_ret_a2):
#endif
movw IMM(SLOT(DYN_ENV_FS)),PVM1_REG
LBL(normal_ret_a2):
addl ATEMP2,PVM1_REG
BRAS( try_to_add_next_frame2)
LBL(not_bottom_of_stack2):
movl PVM1_REG,ATEMP2
moveq IMM(0),PVM1_REG
movw DISP(PVM0_REG,-6),PVM1_REG /* get fs */
BGTS( normal_ret_b2)
#ifdef debug
/*****/ BEQS( dyn_env_ret_b2)
/*****/ jmp 9
/*****/LBL(dyn_env_ret_b2):
#endif
movw IMM(SLOT(DYN_ENV_FS)),PVM1_REG
LBL(normal_ret_b2):
addl ATEMP2,PVM1_REG
CMPL( ATEMP1,PVM1_REG)
BHIS( chunk_found2)
LBL(try_to_add_next_frame2):
addw DISP(PVM0_REG,-4),ATEMP2 /* add link */
movl IND(ATEMP2),PVM0_REG
CMPL( PVM0_REG,PVM3_REG) /* bottom of stack? */
BNES( not_bottom_of_stack2)
movl DISP(PSTATE_REG,SLOT(PARENT_RET)),IND(ATEMP2)
movl PVM1_REG,ATEMP2
LBL(chunk_found2): /* ATEMP2 = chunk's upper limit */
/* Now, compute size of frame object to hold chunk. */
movl ATEMP2,PVM1_REG
lea DISP(ATEMP1,-SLOT(MAX_FRAME_CHUNK_SIZE)),ATEMP2
subl ATEMP2,PVM1_REG
addql IMM(4),PVM1_REG
/* Remember previous frame object */
movl HEAP_REG,ATEMP1
/* Allocate frame object. */
movl PVM1_REG,DTEMP1
addw IMM(11),DTEMP1
andw IMM(-8),DTEMP1
subl DTEMP1,HEAP_REG
asll IMM(8),PVM1_REG
movb IMM(SCM_subtype_FRAME*8),PVM1_REG
movl PVM1_REG,IND(HEAP_REG)
/* Link with previous frame object */
addql IMM(SCM_type_SUBTYPED),HEAP_REG
movl HEAP_REG,DISP(ATEMP1,SLOT(1))
subql IMM(SCM_type_SUBTYPED),HEAP_REG
BRAW( copy_stack)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(39,x)
BEGIN("###_kernel.flush-stack")
movl PVM0_REG,PDEC(SP)
/* Call ###_kernel.transfer-lazy-tasks-to-heap. */
pea PC_IND(ret1)
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
RETURN(ret1,1,1):
/* Call ###_kernel.transfer-stack-to-heap. */
/* ###_kernel.transfer-lazy-tasks-to-heap has reserved enough */
/* space, so no GC check required. */
pea PC_IND(ret2)
movl CONST(1),ATEMP1
jmp IND(ATEMP1)
LBL(ret2):
/* Setup 'hidden' parent continuation. */
movl IND(SP),DISP(PSTATE_REG,SLOT(PARENT_RET))
movl PVM2_REG,DISP(PSTATE_REG,SLOT(PARENT_FRAME))
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl DISP(PSTATE_REG,SLOT(BOS_RET)),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
/* Return to parent */
moveq IMM(0),PVM1_REG
movl PVM1_REG,PVM2_REG
movl PVM1_REG,PVM3_REG
movl DISP(PSTATE_REG,SLOT(BOS_RET)),PVM0_REG
jmp IND(PVM0_REG)
CONSTS(2)
PRIMITIVE("###_kernel.transfer-lazy-tasks-to-heap")
PRIMITIVE("###_kernel.transfer-stack-to-heap")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(40,x)
BEGIN("##call-with-current-continuation")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
movl PVM1_REG,PVM4_REG
movl PVM0_REG,PDEC(SP)
/* Call ###_kernel.transfer-lazy-tasks-to-heap. */
pea PC_IND(ret1)
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
RETURN(ret1,1,1):
/* Call ###_kernel.transfer-stack-to-heap. */
/* ###_kernel.transfer-lazy-tasks-to-heap has reserved enough */
/* space, so no GC check required. */
pea PC_IND(ret2)
movl CONST(1),ATEMP1
jmp IND(ATEMP1)
LBL(ret2):
/* Setup 'hidden' parent continuation. */
movl PINC(SP),PVM0_REG
movl PVM0_REG,DISP(PSTATE_REG,SLOT(PARENT_RET))
movl PVM2_REG,DISP(PSTATE_REG,SLOT(PARENT_FRAME))
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl DISP(PSTATE_REG,SLOT(BOS_RET)),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
/* Return to parent */
movl DISP(PSTATE_REG,SLOT(BOS_RET)),PDEC(SP)
moveq IMM(0),PVM1_REG
movl PVM1_REG,PVM3_REG
/* Allocate closure for 'first-class' continuation. */
movl DISP(PSTATE_REG,SLOT(CLOSURE_PTR)),ATEMP2
moveq IMM(32),DTEMP1
subl DTEMP1,ATEMP2
CMPL( DISP(PSTATE_REG,SLOT(CLOSURE_LIM)),ATEMP2)
BCCS( closure_allocated)
moveq IMM(0),PVM1_REG
TRAP(closure_alloc_trap,closure_alloc,1,1)
LBL(closure_allocated):
movl ATEMP2,DISP(PSTATE_REG,SLOT(CLOSURE_PTR))
/* Init closure. */
movw IMM(0x8010),PINC(ATEMP2)
movl ATEMP2,PVM1_REG
addql IMM(2),ATEMP2
lea PC_IND(closure),ATEMP1
movl ATEMP1,PINC(ATEMP2)
movl PVM0_REG,PINC(ATEMP2)
movl PVM2_REG,PINC(ATEMP2)
movl DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV)),IND(ATEMP2)
movl PINC(SP),PVM0_REG
movl PVM4_REG,ATEMP1
moveq IMM(-1),DTEMP1
jmp IND(ATEMP1)
/* This code is executed when the 'first-class' continuation is restored. */
SUBPROC(closure):
movl PINC(SP),CLOSURE_REG
subql IMM(6),CLOSURE_REG
tstw DTEMP1
BMIS( closure_was_passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_closed_trap,1,closure)
LBL(closure_was_passed_1arg):
/* Call ###_kernel.transfer-lazy-tasks-to-heap. */
CMPL( DISP(PSTATE_REG,SLOT(LTQ_HEAD)),LTQ_TAIL_REG)
BEQS( tasks_transferred)
movl PVM0_REG,PDEC(SP)
movl PVM1_REG,PDEC(SP)
pea PC_IND(ret3)
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
RETURN(ret3,2,1):
movl PINC(SP),PVM1_REG
movl PINC(SP),PVM0_REG
moveq IMM(0),PVM3_REG
LBL(tasks_transferred):
/* Setup 'hidden' parent continuation. */
movl CLOSURE_REG,ATEMP1
movl DISP(ATEMP1,6),DISP(PSTATE_REG,SLOT(PARENT_RET))
movl DISP(ATEMP1,10),DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl DISP(ATEMP1,14),DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl DISP(PSTATE_REG,SLOT(BOS_RET)),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
/* Restore parent continuation. */
movl DISP(PSTATE_REG,SLOT(BOS_RET)),ATEMP1
jmp IND(ATEMP1)
CONSTS(2)
PRIMITIVE("###_kernel.transfer-lazy-tasks-to-heap")
PRIMITIVE("###_kernel.transfer-stack-to-heap")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(41,x)
BEGIN("##apply")
BEQS( passed_2args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,2,$entry)
LBL(passed_2args):
movl PVM1_REG,ATEMP1
movl PVM2_REG,PVM3_REG
moveq IMM(0),DTEMP1
BRAS( loop_entry)
/* copy values from list to the stack */
LBL(loop):
movl PVM3_REG,ATEMP2
movl IND(ATEMP2),PDEC(SP) /* push car to the stack */
movl PDEC(ATEMP2),PVM3_REG /* get cdr */
addqw IMM(1),DTEMP1
CMPW( IMM(MAX_NB_ARGS),DTEMP1)
BGTS( max_args_reached)
LBL(loop_entry):
btst PVM3_REG,PAIR_REG /* pair? */
BEQS( loop)
moveq IMM(0),INTR_TIMER_REG /* check interrupts as soon as possible */
tstw DTEMP1 /* how many arguments to pass? */
BEQS( pass_0arg)
subqw IMM(2),DTEMP1
BMIS( pass_1arg)
BEQS( pass_2args)
movl PINC(SP),PVM3_REG
movl PINC(SP),PVM2_REG
movl PINC(SP),PVM1_REG
addqw IMM(3),DTEMP1
jmp IND(ATEMP1) /* jump to procedure (with >= 3 args) */
LBL(pass_0arg):
moveq IMM(1),DTEMP1
jmp IND(ATEMP1) /* jump to procedure (with no arg) */
LBL(pass_1arg):
movl PINC(SP),PVM1_REG
moveq IMM(-1),DTEMP1
jmp IND(ATEMP1) /* jump to procedure (with 1 arg) */
LBL(pass_2args):
movl PINC(SP),PVM2_REG
movl PINC(SP),PVM1_REG
moveq IMM(0),DTEMP1
jmp IND(ATEMP1) /* jump to procedure (with 2 args) */
LBL(max_args_reached):
aslw IMM(2),DTEMP1
addw DTEMP1,SP /* restore original SP */
movl CONST(0),ATEMP1 /* jump to ##exception.apply-arg-limit */
moveq IMM(0),DTEMP1 /* passing 2 arguments */
jmp IND(ATEMP1)
CONSTS(1)
PRIMITIVE("##exception.apply-arg-limit")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(42,x)
BEGIN("##global-var")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
movl PVM1_REG,ATEMP2
movl DISP(ATEMP2,SLOT(SYMBOL_GLOBAL)+4-SCM_type_SUBTYPED),PVM1_REG
CMPL( PVM1_REG,FALSE_REG)
BEQS( alloc_glob)
jmp IND(PVM0_REG)
LBL(alloc_glob):
movl DISP(TABLE_REG,GLOB_OFFS(GLOBAL_VAR_COUNT)),ATEMP1
movl ATEMP1,PVM1_REG
addql IMM(8),ATEMP1
CMPL( IMM(MAX_NB_GLOBALS*8),ATEMP1)
BLES( ok)
movl FALSE_REG,PVM1_REG
jmp IND(PVM0_REG)
LBL(ok):
movl ATEMP1,DISP(TABLE_REG,GLOB_OFFS(GLOBAL_VAR_COUNT))
movl PVM1_REG,DISP(ATEMP2,SLOT(SYMBOL_GLOBAL)+4-SCM_type_SUBTYPED)
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(43,x)
BEGIN("##global-var-ref")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
movl PVM1_REG,ATEMP1
addl TABLE_REG,ATEMP1
subl IMM((NB_TRAPS*8-0x8000)+(MAX_NB_GLOBALS*10)),ATEMP1
movl IND(ATEMP1),PVM1_REG
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(44,x)
BEGIN("##global-var-set!")
BEQS( passed_2args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,2,$entry)
LBL(passed_2args):
movl PVM1_REG,DTEMP1
asrl IMM(2),DTEMP1
addl TABLE_REG,DTEMP1
subl IMM(NB_TRAPS*8-0x8000),DTEMP1
subl IMM(MAX_NB_GLOBALS*2),DTEMP1
movl PVM1_REG,ATEMP1
addl TABLE_REG,ATEMP1
subl IMM(NB_TRAPS*8-0x8000),ATEMP1
subl IMM(MAX_NB_GLOBALS*10),ATEMP1
movl PVM2_REG,PINC(ATEMP1)
movl DTEMP1,IND(ATEMP1)
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(45,x)
BEGIN("##make-vector")
BEQS( passed_2args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,2,$entry)
LBL(passed_2args):
movl PVM1_REG,DTEMP1
asrl IMM(1),DTEMP1
addl IMM(11),DTEMP1
andw IMM(-8),DTEMP1 /* DTEMP1 = total bytes needed for vector */
CMPL( DTEMP1,HEAP_REG)
subl DTEMP1,HEAP_REG /* allocate space for vector and check heap overflow */
BCSS( gc)
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG)
BCCS( ok)
LBL(gc):
movl PVM0_REG,PDEC(SP)
TRAP(heap_alloc2_trap,alloc1,1,1)
movl PINC(SP),PVM0_REG
LBL(ok):
movl PVM1_REG,DTEMP1
asll IMM(7),DTEMP1
movb IMM(SCM_subtype_VECTOR*8),DTEMP1
movl DTEMP1,IND(HEAP_REG)
/* init vector: */
movl PVM1_REG,DTEMP1
asrl IMM(1),DTEMP1
lea DISP(HEAP_REG,4),ATEMP1
LBL(loop):
movl PVM2_REG,PINC(ATEMP1)
subql IMM(4),DTEMP1
BGTS( loop)
movl HEAP_REG,PVM1_REG
addql IMM(SCM_type_SUBTYPED),PVM1_REG
jmp IND(PVM0_REG) /* return to caller */
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(46,x)
BEGIN("##make-string")
BEQS( passed_2args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,2,$entry)
LBL(passed_2args):
movl PVM1_REG,DTEMP1
asrl IMM(3),DTEMP1
addl IMM(11),DTEMP1
andw IMM(-8),DTEMP1 /* DTEMP1 = total bytes needed for string */
CMPL( DTEMP1,HEAP_REG)
subl DTEMP1,HEAP_REG /* allocate space for string and check heap overflow */
BCSS( gc)
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG)
BCCS( ok)
LBL(gc):
movl PVM0_REG,PDEC(SP)
TRAP(heap_alloc2_trap,alloc1,1,1)
movl PINC(SP),PVM0_REG
LBL(ok):
movl PVM1_REG,DTEMP1
asll IMM(5),DTEMP1
movb IMM(SCM_subtype_STRING*8),DTEMP1
movl DTEMP1,IND(HEAP_REG)
/* init string: */
movl PVM2_REG,DTEMP1
asrw IMM(3),DTEMP1
andw IMM(0xff),DTEMP1
movw DTEMP1,ATEMP2
aslw IMM(8),DTEMP1
addw ATEMP2,DTEMP1
movw DTEMP1,ATEMP2
swap DTEMP1
movw ATEMP2,DTEMP1
movl DTEMP1,ATEMP2 /* ATEMP2 = initial value of chars */
movl PVM1_REG,DTEMP1
asrl IMM(3),DTEMP1
lea DISP(HEAP_REG,4),ATEMP1
LBL(loop):
movl ATEMP2,PINC(ATEMP1)
subql IMM(4),DTEMP1
BGTS( loop)
movl HEAP_REG,PVM1_REG
addql IMM(SCM_type_SUBTYPED),PVM1_REG
jmp IND(PVM0_REG) /* return to caller */
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(47,x)
BEGIN("##make-vector16")
BEQS( passed_2args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,2,$entry)
LBL(passed_2args):
movl PVM1_REG,DTEMP1
asrl IMM(2),DTEMP1
addl IMM(11),DTEMP1
andw IMM(-8),DTEMP1 /* DTEMP1 = total bytes needed for vector */
CMPL( DTEMP1,HEAP_REG)
subl DTEMP1,HEAP_REG /* allocate space for vector and check heap overflow */
BCSS( gc)
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG)
BCCS( ok)
LBL(gc):
movl PVM0_REG,PDEC(SP)
TRAP(heap_alloc2_trap,alloc1,1,1)
movl PINC(SP),PVM0_REG
LBL(ok):
movl PVM1_REG,DTEMP1
asll IMM(6),DTEMP1
movb IMM(SCM_subtype_STRING*8),DTEMP1
movl DTEMP1,IND(HEAP_REG)
/* init vector: */
movl PVM2_REG,DTEMP1
asrl IMM(3),DTEMP1
movw DTEMP1,ATEMP2
swap DTEMP1
movw ATEMP2,DTEMP1
movl DTEMP1,ATEMP2 /* ATEMP2 = initial value of words */
movl PVM1_REG,DTEMP1
asrl IMM(2),DTEMP1
lea DISP(HEAP_REG,4),ATEMP1
LBL(loop):
movl ATEMP2,PINC(ATEMP1)
subql IMM(4),DTEMP1
BGTS( loop)
movl HEAP_REG,PVM1_REG
addql IMM(SCM_type_SUBTYPED),PVM1_REG
jmp IND(PVM0_REG) /* return to caller */
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(48,x)
BEGIN("##dynamic-env-bind")
BEQS( passed_2args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,2,$entry)
LBL(passed_2args):
/* save current dynamic environment */
movl PVM0_REG,PDEC(SP)
movl DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV)),PDEC(SP)
/* set new dynamic environment */
movl PVM1_REG,DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
/* push dynamic environment marker (only if none other pushed for this future) */
movl DISP(PSTATE_REG,SLOT(DEQ_TAIL)),ATEMP2
movl IND(ATEMP2),PVM0_REG
movl DISP(LTQ_TAIL_REG,-SLOT(1)),ATEMP1
CMPL( ATEMP1,PVM0_REG)
BCSS( pushed)
movl SP,PDEC(ATEMP2)
movl ATEMP2,DISP(PSTATE_REG,SLOT(DEQ_TAIL))
LBL(pushed):
lea PC_IND(ret),PVM0_REG
movl PVM2_REG,ATEMP1
moveq IMM(1),DTEMP1
jmp IND(ATEMP1)
RETURN(ret,DYN_ENV_FS-DYN_ENV_FS,1-DYN_ENV_FS):
/* A fs of 0 is a special return point marker. Here it indicates a return */
/* point for dyn env frames. The frame size is really 2 (DYN_ENV_FS). */
/* pop dynamic environment marker */
movl DISP(PSTATE_REG,SLOT(DEQ_TAIL)),ATEMP2
movl PINC(ATEMP2),ATEMP1
CMPL( ATEMP1,SP)
BNES( popped)
movl ATEMP2,DISP(PSTATE_REG,SLOT(DEQ_TAIL))
LBL(popped):
/* restore current dynamic environment */
movl PINC(SP),DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
rts
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(49,x)
BEGIN("##dynamic-env-ref")
CMPW( IMM(1),DTEMP1)
BEQS( passed_0arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,0,$entry)
LBL(passed_0arg):
movl DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV)),PVM1_REG
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(50,x)
BEGIN("##atomic-car")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
andw IMM(-8),PVM1_REG
movl PVM1_REG,ATEMP2
moveq IMM(-1),DTEMP1
LBL(loop):
movl DISP(ATEMP2,4),PVM1_REG
CMPL( PVM1_REG,DTEMP1)
BEQS( loop)
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(51,x)
BEGIN("##atomic-set-car!")
BEQS( passed_2args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,2,$entry)
LBL(passed_2args):
movl PVM0_REG,PVM4_REG
movl PVM1_REG,DTEMP1
andw IMM(-8),DTEMP1
addql IMM(4),DTEMP1
movl DTEMP1,ATEMP2
LOCK_ATEMP2(lock)
movl PVM2_REG,IND(ATEMP2)
movl DTEMP1,PVM1_REG
movl PVM4_REG,PVM0_REG
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(52,x)
BEGIN("##atomic-cdr")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
andw IMM(-8),PVM1_REG
movl PVM1_REG,ATEMP2
moveq IMM(-1),DTEMP1
LBL(loop):
movl IND(ATEMP2),PVM1_REG
CMPL( PVM1_REG,DTEMP1)
BEQS( loop)
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(53,x)
BEGIN("##atomic-set-cdr!")
BEQS( passed_2args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,2,$entry)
LBL(passed_2args):
movl PVM0_REG,PVM4_REG
movl PVM1_REG,DTEMP1
andw IMM(-8),DTEMP1
movl DTEMP1,ATEMP2
LOCK_ATEMP2(lock)
movl PVM2_REG,IND(ATEMP2)
movl DTEMP1,PVM1_REG
movl PVM4_REG,PVM0_REG
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(54,x)
BEGIN("##atomic-set-car-if-eq?!")
CMPW( IMM(4),DTEMP1)
BEQS( passed_3args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,3,$entry)
LBL(passed_3args):
movl PVM0_REG,PVM4_REG
movl PVM1_REG,DTEMP1
andw IMM(-8),DTEMP1
addql IMM(4),DTEMP1
movl DTEMP1,ATEMP2
LOCK_ATEMP2(lock)
CMPL( DTEMP1,PVM3_REG)
BNES( not_eq)
movl PVM2_REG,IND(ATEMP2)
movl IMM(SCM_true),PVM1_REG
movl PVM4_REG,PVM0_REG
jmp IND(PVM0_REG)
LBL(not_eq):
movl DTEMP1,IND(ATEMP2)
movl FALSE_REG,PVM1_REG
movl PVM4_REG,PVM0_REG
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(55,x)
BEGIN("##atomic-set-cdr-if-eq?!")
CMPW( IMM(4),DTEMP1)
BEQS( passed_3args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,3,$entry)
LBL(passed_3args):
movl PVM0_REG,PVM4_REG
movl PVM1_REG,DTEMP1
andw IMM(-8),DTEMP1
movl DTEMP1,ATEMP2
LOCK_ATEMP2(lock)
CMPL( DTEMP1,PVM3_REG)
BNES( not_eq)
movl PVM2_REG,IND(ATEMP2)
movl IMM(SCM_true),PVM1_REG
movl PVM4_REG,PVM0_REG
jmp IND(PVM0_REG)
LBL(not_eq):
movl DTEMP1,IND(ATEMP2)
movl FALSE_REG,PVM1_REG
movl PVM4_REG,PVM0_REG
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(550,x)
BEGIN("##make-queue")
CMPW( IMM(1),DTEMP1)
BEQS( passed_0arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,0,$entry)
LBL(passed_0arg):
subql IMM(4),HEAP_REG
movl NULL_REG,PDEC(HEAP_REG)
movl NULL_REG,PDEC(HEAP_REG)
movl IMM(QUEUE_SIZE*0x400+(SCM_subtype_QUEUE*8)),PDEC(HEAP_REG)
lea DISP(HEAP_REG,SCM_type_SUBTYPED),ATEMP1
movl ATEMP1,PVM1_REG
/* check heap overflow */
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG)
BCCS( ok)
movl PVM0_REG,PDEC(SP)
TRAP(heap_alloc1_trap,alloc1,1,1)
movl PINC(SP),PVM0_REG
LBL(ok):
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(551,x)
BEGIN("##queue-peek-list")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
movl PVM1_REG,ATEMP2
movl DISP(ATEMP2,SLOT(QUEUE_HEAD)+4-SCM_type_SUBTYPED),PVM1_REG
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(552,x)
BEGIN("##queue-get-list!")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
movl PVM1_REG,ATEMP2
lea DISP(ATEMP2,SLOT(QUEUE_TAIL)+4-SCM_type_SUBTYPED),ATEMP2
movl PVM0_REG,PVM3_REG
LOCK_ATEMP2(lock)
movl PVM3_REG,PVM0_REG
CMPL( DTEMP1,NULL_REG)
BEQS( empty)
movl DISP(ATEMP2,SLOT(QUEUE_HEAD-QUEUE_TAIL)),PVM1_REG
movl NULL_REG,DISP(ATEMP2,SLOT(QUEUE_HEAD-QUEUE_TAIL))
movl NULL_REG,IND(ATEMP2)
jmp IND(PVM0_REG)
LBL(empty):
movl NULL_REG,PVM1_REG
movl NULL_REG,IND(ATEMP2)
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(553,x)
BEGIN("##queue-get!")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
movl PVM1_REG,ATEMP2
lea DISP(ATEMP2,SLOT(QUEUE_TAIL)+4-SCM_type_SUBTYPED),ATEMP2
movl PVM0_REG,PVM3_REG
LOCK_ATEMP2(lock)
movl PVM3_REG,PVM0_REG
CMPL( DTEMP1,NULL_REG)
BEQS( empty1)
movl DISP(ATEMP2,SLOT(QUEUE_HEAD-QUEUE_TAIL)),PVM1_REG
movl PVM1_REG,ATEMP1
movl PDEC(ATEMP1),PVM4_REG
movl NULL_REG,IND(ATEMP1)
movl PVM4_REG,DISP(ATEMP2,SLOT(QUEUE_HEAD-QUEUE_TAIL))
CMPL( PVM4_REG,NULL_REG)
BEQS( empty2)
movl DTEMP1,IND(ATEMP2)
jmp IND(PVM0_REG)
LBL(empty1):
movl FALSE_REG,PVM1_REG
LBL(empty2):
movl NULL_REG,IND(ATEMP2)
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(554,x)
BEGIN("##queue-put!")
BEQS( passed_2args)
WRONG_NB_ARGS(wrong_nb_arg1_trap,2,$entry)
LBL(passed_2args):
movl PVM2_REG,PDEC(HEAP_REG)
movl HEAP_REG,PVM2_REG
movl NULL_REG,PDEC(HEAP_REG)
movl PVM1_REG,ATEMP2
lea DISP(ATEMP2,SLOT(QUEUE_TAIL)+4-SCM_type_SUBTYPED),ATEMP2
movl PVM0_REG,PVM3_REG
movl PVM1_REG,PVM4_REG
LOCK_ATEMP2(lock)
movl PVM4_REG,PVM1_REG
movl PVM3_REG,PVM0_REG
CMPL( DTEMP1,NULL_REG)
BEQS( empty)
movl DTEMP1,ATEMP1
movl PVM2_REG,PDEC(ATEMP1)
BRAS( unlock)
LBL(empty):
movl PVM2_REG,DISP(ATEMP2,SLOT(QUEUE_HEAD-QUEUE_TAIL))
LBL(unlock):
movl PVM2_REG,IND(ATEMP2)
/* check heap overflow */
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG)
BCCS( ok)
movl PVM0_REG,PDEC(SP)
TRAP(heap_alloc1_trap,alloc1,1,1)
movl PINC(SP),PVM0_REG
LBL(ok):
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(56,x)
BEGIN("##make-semaphore")
CMPW( IMM(1),DTEMP1)
BEQS( passed_0arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,0,$entry)
LBL(passed_0arg):
movl IMM(1*8),PDEC(HEAP_REG)
movl NULL_REG,PDEC(HEAP_REG)
movl NULL_REG,PDEC(HEAP_REG)
movl IMM(SEMAPHORE_SIZE*0x400+(SCM_subtype_SEMAPHORE*8)),PDEC(HEAP_REG)
lea DISP(HEAP_REG,SCM_type_SUBTYPED),ATEMP1
movl ATEMP1,PVM1_REG
/* check heap overflow */
CMPL( DISP(PSTATE_REG,SLOT(HEAP_LIM)),HEAP_REG)
BCCS( ok)
movl PVM0_REG,PDEC(SP)
TRAP(heap_alloc1_trap,alloc1,1,1)
movl PINC(SP),PVM0_REG
LBL(ok):
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(57,x)
BEGIN("##semaphore-wait")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
movl PVM1_REG,PVM4_REG
movl PVM4_REG,ATEMP2
lea DISP(ATEMP2,SLOT(SEMAPHORE_COUNT)+4-SCM_type_SUBTYPED),ATEMP2
movl PVM0_REG,PVM3_REG
LOCK_ATEMP2(lock1)
movl PVM3_REG,PVM0_REG
clrl IND(ATEMP2) /* semaphore count now 0 */
tstl DTEMP1 /* semaphore count was 0? */
BEQS( count_was_0)
movl FALSE_REG,PVM1_REG
jmp IND(PVM0_REG)
LBL(count_was_0):
/* suspend task on semaphore */
movl PVM0_REG,PDEC(SP)
/* Call ###_kernel.transfer-lazy-tasks-to-heap. */
pea PC_IND(ret1)
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
RETURN(ret1,1,1):
/* Call ###_kernel.transfer-stack-to-heap. */
/* ###_kernel.transfer-lazy-tasks-to-heap has reserved enough */
/* space, so no GC check required. */
pea PC_IND(ret2)
movl CONST(1),ATEMP1
jmp IND(ATEMP1)
LBL(ret2):
/* Save state of current task. */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP1
movl PINC(SP),PVM0_REG
movl PVM0_REG,DISP(ATEMP1,SLOT(TASK_CONT_RET)+4-SCM_type_SUBTYPED)
movl PVM2_REG,DISP(ATEMP1,SLOT(TASK_CONT_FRAME)+4-SCM_type_SUBTYPED)
movl DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV)),DISP(ATEMP1,SLOT(TASK_CONT_DYN_ENV)+4-SCM_type_SUBTYPED)
movl FALSE_REG,DISP(ATEMP1,SLOT(TASK_VALUE)+4-SCM_type_SUBTYPED)
movl ATEMP1,PDEC(HEAP_REG)
movl HEAP_REG,PVM3_REG
movl NULL_REG,PDEC(HEAP_REG)
/* Final check for availability. */
movl PVM4_REG,ATEMP2
lea DISP(ATEMP2,SLOT(SEMAPHORE_COUNT)+4-SCM_type_SUBTYPED),ATEMP2
LOCK_ATEMP2(lock2)
tstl DTEMP1 /* semaphore count was 0? */
BEQS( semaphore_still_not_free)
clrl IND(ATEMP2) /* semaphore count now 0 */
addql IMM(8),HEAP_REG /* discard cons cell */
/* Resume task. */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP2
movl DISP(ATEMP2,SLOT(TASK_CONT_RET)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_RET))
movl DISP(ATEMP2,SLOT(TASK_CONT_FRAME)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl DISP(ATEMP2,SLOT(TASK_CONT_DYN_ENV)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
movl PVM4_REG,PVM0_REG
movl PVM4_REG,PVM1_REG
movl PVM4_REG,PVM2_REG
movl PVM4_REG,PVM3_REG
movl DISP(PSTATE_REG,SLOT(BOS_RET)),ATEMP1
jmp IND(ATEMP1)
LBL(semaphore_still_not_free):
#ifndef butterfly
CMPL( DISP(PSTATE_REG,SLOT(WORKQ_TAIL)),NULL_REG) /* anything else runnable? */
BNES( no_deadlock)
/* Resume task. */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP2
movl DISP(ATEMP2,SLOT(TASK_CONT_RET)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_RET))
movl DISP(ATEMP2,SLOT(TASK_CONT_FRAME)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl DISP(ATEMP2,SLOT(TASK_CONT_DYN_ENV)+4-SCM_type_SUBTYPED),DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
movl PVM4_REG,PVM0_REG
movl PVM4_REG,PVM1_REG
movl PVM4_REG,PVM2_REG
movl PVM4_REG,PVM3_REG
movl DISP(PSTATE_REG,SLOT(BOS_RET)),PVM0_REG
movl CONST(3),ATEMP1 /* jump to ##exception.deadlock */
moveq IMM(1),DTEMP1 /* passing 0 argument */
jmp IND(ATEMP1)
LBL(no_deadlock):
#endif
/* add task to tail of waiting queue */
movl DISP(ATEMP2,SLOT(SEMAPHORE_TAIL-SEMAPHORE_COUNT)),DTEMP1
CMPL( DTEMP1,NULL_REG)
BEQS( empty)
movl DTEMP1,ATEMP1
movl PVM3_REG,PDEC(ATEMP1)
BRAS( done)
LBL(empty):
movl PVM3_REG,DISP(ATEMP2,SLOT(SEMAPHORE_HEAD-SEMAPHORE_COUNT))
LBL(done):
movl PVM3_REG,DISP(ATEMP2,SLOT(SEMAPHORE_TAIL-SEMAPHORE_COUNT))
clrl IND(ATEMP2) /* semaphore count now 0 */
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to WAITING */
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP1
movl NULL_REG,DISP(ATEMP1,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
moveq IMM(0),PVM1_REG
movl CONST(2),ATEMP1
jmp IND(ATEMP1)
CONSTS(4)
PRIMITIVE("###_kernel.transfer-lazy-tasks-to-heap")
PRIMITIVE("###_kernel.transfer-stack-to-heap")
PRIMITIVE("###_kernel.idle")
PRIMITIVE("##exception.deadlock")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(58,x)
BEGIN("##semaphore-signal")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
movl PVM1_REG,PVM4_REG
movl PVM4_REG,ATEMP2
lea DISP(ATEMP2,SLOT(SEMAPHORE_COUNT)+4-SCM_type_SUBTYPED),ATEMP2
movl PVM0_REG,PVM3_REG
LOCK_ATEMP2(lock1)
movl PVM3_REG,PVM0_REG
movl DISP(ATEMP2,SLOT(SEMAPHORE_TAIL-SEMAPHORE_COUNT)),DTEMP1
CMPL( DTEMP1,NULL_REG)
BNES( restart_task)
movl IMM(1*8),IND(ATEMP2) /* semaphore count now 1 */
movl FALSE_REG,PVM1_REG
jmp IND(PVM0_REG)
LBL(restart_task):
/* remove first task from waiting queue */
movl DISP(ATEMP2,SLOT(SEMAPHORE_HEAD-SEMAPHORE_COUNT)),ATEMP1
movl DISP(ATEMP1,SLOT(-1)),PVM1_REG
movl PVM1_REG,DISP(ATEMP2,SLOT(SEMAPHORE_HEAD-SEMAPHORE_COUNT))
CMPL( PVM1_REG,NULL_REG)
BNES( done)
movl NULL_REG,DISP(ATEMP2,SLOT(SEMAPHORE_TAIL-SEMAPHORE_COUNT))
LBL(done):
clrl IND(ATEMP2) /* semaphore count now 0 */
#ifdef MAINTAIN_TASK_STATUS
/* Change task's status to READY */
movl IND(ATEMP1),ATEMP2
movl ATEMP1,DISP(ATEMP2,SLOT(TASK_STATUS)+4-SCM_type_SUBTYPED)
#endif
/* add task to work queue */
movl FALSE_REG,DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(lock_workq):
tstl DISP(PSTATE_REG,SLOT(WORKQ_LOCKV))
BNES( lock_workq)
movl DISP(PSTATE_REG,SLOT(WORKQ_TAIL)),ATEMP2
CMPL( ATEMP2,NULL_REG)
BNES( non_empty_queue)
movl ATEMP1,DISP(PSTATE_REG,SLOT(WORKQ_HEAD))
BRAS( fix_tail)
LBL(non_empty_queue):
movl ATEMP1,PDEC(ATEMP2)
LBL(fix_tail):
movl ATEMP1,DISP(PSTATE_REG,SLOT(WORKQ_TAIL))
movl NULL_REG,PDEC(ATEMP1)
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
/* return */
movl FALSE_REG,PVM1_REG
jmp IND(PVM0_REG)
CONSTS(0)
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(59,x)
BEGIN("##legitimacy-barrier")
CMPW( IMM(1),DTEMP1)
BEQS( passed_0arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,0,$entry)
LBL(passed_0arg):
movl DISP(PSTATE_REG,SLOT(CURRENT_TASK)),ATEMP1
movl DISP(ATEMP1,SLOT(TASK_LEGIT)+4-SCM_type_SUBTYPED),PVM1_REG
/* touch legitimacy placeholder */
btst PVM1_REG,PLACEHOLDER_REG
BEQS( touch)
jmp IND(PVM0_REG)
LBL(touch):
movl PVM1_REG,ATEMP2
movl DISP(ATEMP2,SLOT(PH_VALUE)-SCM_type_PLACEHOLDER),PVM1_REG
CMPL( ATEMP2,PVM1_REG)
BNES( determined)
LOG(EVENT_TOUCH_UNDET,log1)
/* legitimacy placeholders can be determined to placeholders, so must chase */
movl PVM0_REG,PDEC(SP)
lea PC_IND(ret),PVM0_REG
movl CONST(0),ATEMP1
jmp IND(ATEMP1) /* jump to ###_kernel.touch */
RETURN(ret,1,1):
movl PINC(SP),PVM0_REG
LBL(determined):
btst PVM1_REG,PLACEHOLDER_REG
BEQS( touch)
jmp IND(PVM0_REG)
CONSTS(1)
PRIMITIVE("###_kernel.touch")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(60,x)
BEGIN("##sequentially")
BMIS( passed_1arg)
WRONG_NB_ARGS(wrong_nb_arg1_trap,1,$entry)
LBL(passed_1arg):
movl PVM0_REG,PDEC(SP)
/* Call ###_kernel.transfer-lazy-tasks-to-heap. */
CMPL( DISP(PSTATE_REG,SLOT(LTQ_HEAD)),LTQ_TAIL_REG)
BEQS( tasks_transferred)
movl PVM1_REG,PDEC(SP)
pea PC_IND(ret1)
movl CONST(0),ATEMP1
jmp IND(ATEMP1)
RETURN(ret1,2,1):
movl PINC(SP),PVM1_REG
moveq IMM(0),PVM3_REG
LBL(tasks_transferred):
movl PVM1_REG,ATEMP2
/* Remove tasks from workq */
movl FALSE_REG,DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(lock_workq1):
tstl DISP(PSTATE_REG,SLOT(WORKQ_LOCKV))
BNES( lock_workq1)
movl DISP(PSTATE_REG,SLOT(WORKQ_HEAD)),PDEC(SP)
movl NULL_REG,DISP(PSTATE_REG,SLOT(WORKQ_HEAD))
movl NULL_REG,DISP(PSTATE_REG,SLOT(WORKQ_TAIL))
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
/* Call procedure */
lea PC_IND(ret2),PVM0_REG
moveq IMM(1),DTEMP1
jmp IND(ATEMP2)
RETURN(ret2,2,1):
/* Restore tasks to workq */
movl PINC(SP),PVM2_REG
btst PVM2_REG,PAIR_REG /* pair? */
BNES( done)
movl PVM2_REG,DTEMP1 /* get tail */
LBL(loop):
movl DTEMP1,ATEMP2
movl PDEC(ATEMP2),DTEMP1
btst DTEMP1,PAIR_REG
BEQS( loop)
movl FALSE_REG,DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(lock_workq2):
tstl DISP(PSTATE_REG,SLOT(WORKQ_LOCKV))
BNES( lock_workq2)
CMPL( DISP(PSTATE_REG,SLOT(WORKQ_TAIL)),NULL_REG)
BNES( non_empty_queue)
movl NULL_REG,PINC(ATEMP2)
movl ATEMP2,DISP(PSTATE_REG,SLOT(WORKQ_TAIL))
BRAS( fix_head)
LBL(non_empty_queue):
movl DISP(PSTATE_REG,SLOT(WORKQ_HEAD)),PINC(ATEMP2)
LBL(fix_head):
movl PVM2_REG,DISP(PSTATE_REG,SLOT(WORKQ_HEAD))
clrl DISP(PSTATE_REG,SLOT(WORKQ_LOCKO))
LBL(done):
rts
CONSTS(1)
PRIMITIVE("###_kernel.transfer-lazy-tasks-to-heap")
END
/*---------------------------------------------------------------------------*/
#undef LBL
#define LBL(x)MAKE_LBL(61,x)
BEGIN("###_kernel.startup")
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Save C's context: */
movl CONST(0),REG(a1)
#ifndef MIN_C_CONTEXT
movl REG(d2),DISP(REG(a1),C_D2)
movl REG(d3),DISP(REG(a1),C_D3)
movl REG(d4),DISP(REG(a1),C_D4)
movl REG(d5),DISP(REG(a1),C_D5)
movl REG(d6),DISP(REG(a1),C_D6)
movl REG(d7),DISP(REG(a1),C_D7)
movl REG(a2),DISP(REG(a1),C_A2)
movl REG(a3),DISP(REG(a1),C_A3)
movl REG(a4),DISP(REG(a1),C_A4)
#endif
movl REG(a5),DISP(REG(a1),C_A5)
movl REG(a6),DISP(REG(a1),C_A6)
movl SP,DISP(REG(a1),C_SP)
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Get parameters: */
movl DISP(SP,4),TABLE_REG /* always = ptr to glob/code table */
movl DISP(SP,8),PSTATE_REG /* always = ptr to processor state */
movl DISP(SP,12),DTEMP1 /* init 68881 coprocessor */
BEQS( no_68881)
fmovel IMM(0),FPSR
fmovel IMM(0),FPCR
LBL(no_68881):
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Setup registers: */
moveq IMM(0),INTR_TIMER_REG
movl IMM(SCM_null),NULL_REG
movl IMM(SCM_false),FALSE_REG
movl DISP(PSTATE_REG,SLOT(HEAP_PTR)),HEAP_REG
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Setup stack structure: */
movl DISP(PSTATE_REG,SLOT(STACK_BOT)),DTEMP1
addl IMM(SLOT(STACK_ALLOCATION_FUDGE)),DTEMP1
addl DISP(PSTATE_REG,SLOT(STACK_MARGIN)),DTEMP1
movl DTEMP1,DISP(PSTATE_REG,SLOT(STACK_LIM))
movl IMM(-1),DISP(PSTATE_REG,SLOT(INTR_FLAG))
movl DISP(PSTATE_REG,SLOT(STACK_PTR)),SP
movl DISP(PSTATE_REG,SLOT(LTQ_TAIL)),LTQ_TAIL_REG
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Setup 'bottom of stack' return address: */
lea PC_IND(bos_ret),PVM0_REG
movl PVM0_REG,DISP(PSTATE_REG,SLOT(BOS_RET))
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Start processors: */
MAKE_TEMP_TASK
movl DISP(PSTATE_REG,SLOT(ID)),DTEMP1
BEQS( processor0)
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Startup other processors: */
moveq IMM(0),PVM1_REG
movl CONST(1),ATEMP1
jmp IND(ATEMP1)
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Startup processor 0: */
LBL(processor0):
/* Make root task. */
clrl PDEC(HEAP_REG)
clrl PDEC(HEAP_REG)
movl PSTATE_REG,PDEC(HEAP_REG)
clrl PDEC(HEAP_REG)
clrl PDEC(HEAP_REG)
movl IMM(SCM_true),PDEC(HEAP_REG)
clrl PDEC(HEAP_REG)
clrl PDEC(HEAP_REG)
clrl PDEC(HEAP_REG)
movl IMM(TASK_SIZE*0x400+(SCM_subtype_TASK*8)),PDEC(HEAP_REG)
lea DISP(HEAP_REG,SCM_type_SUBTYPED),ATEMP1
movl ATEMP1,DISP(PSTATE_REG,SLOT(CURRENT_TASK))
/* Make root continuation. */
subql IMM(4),HEAP_REG
movl FALSE_REG,PDEC(HEAP_REG)
movl FALSE_REG,PDEC(HEAP_REG)
movl IMM(2*0x400+SCM_subtype_FRAME*8),PDEC(HEAP_REG)
lea DISP(HEAP_REG,SCM_type_SUBTYPED),ATEMP2
lea PC_IND(root_continuation),ATEMP1
movl ATEMP1,DISP(PSTATE_REG,SLOT(PARENT_RET))
movl ATEMP2,DISP(PSTATE_REG,SLOT(PARENT_FRAME))
movl NULL_REG,DISP(PSTATE_REG,SLOT(CURRENT_DYN_ENV))
movl DISP(PSTATE_REG,SLOT(BOS_RET)),PVM0_REG
#ifdef debug
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl DISP(PSTATE_REG,SLOT(BOS_RET)),DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
/* Clear PVM registers. */
moveq IMM(0),PVM1_REG
movl PVM1_REG,PVM2_REG
movl PVM1_REG,PVM3_REG
movl PVM1_REG,PVM4_REG
LOG(EVENT_WORKING,log1)
movl CONST(2),ATEMP1 /* jump to ##STARTUP proc */
moveq IMM(1),DTEMP1 /* passing 0 argument */
jmp IND(ATEMP1)
RETURN(root_continuation,1,1):
movl CONST(0),REG(a1) /* restore C's registers */
#ifndef MIN_C_CONTEXT
movl DISP(REG(a1),C_D2),REG(d2)
movl DISP(REG(a1),C_D3),REG(d3)
movl DISP(REG(a1),C_D4),REG(d4)
movl DISP(REG(a1),C_D5),REG(d5)
movl DISP(REG(a1),C_D6),REG(d6)
movl DISP(REG(a1),C_D7),REG(d7)
movl DISP(REG(a1),C_A2),REG(a2)
movl DISP(REG(a1),C_A3),REG(a3)
movl DISP(REG(a1),C_A4),REG(a4)
#endif
movl DISP(REG(a1),C_A5),REG(a5)
movl DISP(REG(a1),C_A6),REG(a6)
movl DISP(REG(a1),C_SP),SP
rts
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
RETURN(bos_ret,0,0):
/* A fs of 0 is a special return point marker. Here it indicates the return */
/* point in the oldest frame in the stack. */
movl PVM0_REG,DISP(PSTATE_REG,SLOT(TEMP1))
movl PVM1_REG,DISP(PSTATE_REG,SLOT(TEMP2))
#ifndef MESSAGE_PASSING_STEAL
movl FALSE_REG,DISP(PSTATE_REG,SLOT(STEAL_LOCKO))
LBL(lock_steal):
tstl DISP(PSTATE_REG,SLOT(STEAL_LOCKV))
BNES( lock_steal)
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),LTQ_TAIL_REG
movl DISP(PSTATE_REG,SLOT(Q_BOT)),ATEMP1
LBL(loop1):
clrl PDEC(LTQ_TAIL_REG)
CMPL( ATEMP1,LTQ_TAIL_REG)
BNES( loop1)
#endif
RESET_STACK
/* After RESET_STACK, ATEMP1 = DEQ_TAIL */
#ifdef debug
/*****/ movl DISP(PSTATE_REG,SLOT(PARENT_FRAME)),PDEC(SP)
/*****/ movl DISP(PSTATE_REG,SLOT(PARENT_RET)),PDEC(SP)
/*****/ movl DISP(PSTATE_REG,SLOT(56)),PDEC(SP)
/*****/ movl DISP(PSTATE_REG,SLOT(57)),PDEC(SP)
/*****/ movl DISP(PSTATE_REG,SLOT(58)),PDEC(SP)
#endif
movl DISP(PSTATE_REG,SLOT(PARENT_FRAME)),PVM0_REG
subql IMM(SCM_type_SUBTYPED),PVM0_REG
movl PINC(PVM0_REG),PVM1_REG
lsrl IMM(8),PVM1_REG
LBL(wait):
movl PINC(PVM0_REG),DISP(PSTATE_REG,SLOT(PARENT_FRAME))
BNES( copy_frame)
subql IMM(4),PVM0_REG
BRAS( wait)
LBL(copy_frame):
/* copy frame */
#ifdef RESTORE_PARENT_USING_BTRANSFER
broken...
subql IMM(4),PVM1_REG /* PVM1_REG = length of frame */
subl PVM1_REG,SP /* allocate space on stack */
movl SP,DTEMP1
BTRANSFER(copy)
#else
#ifdef debug
/*****/ addw IMM(5*4),SP
#endif
movl SP,DTEMP1
subql IMM(4),PVM1_REG /* PVM1_REG = length of frame */
subl PVM1_REG,SP /* allocate space on stack */
movl SP,ATEMP2
lsrl IMM(2),PVM1_REG
subql IMM(1),PVM1_REG
LBL(loop3):
movl PINC(PVM0_REG),PINC(ATEMP2)
DBRA( PVM1_REG,loop3)
#endif
/* Scan each frame of continuation... */
movl DISP(PSTATE_REG,SLOT(PARENT_RET)),PVM0_REG
movl SP,PVM1_REG
#ifdef debug
/*****/ movl DISP(PSTATE_REG,SLOT(PARENT_FRAME)),PDEC(SP)
/*****/ movl DISP(PSTATE_REG,SLOT(PARENT_RET)),PDEC(SP)
/*****/ movl DISP(PSTATE_REG,SLOT(56)),PDEC(SP)
/*****/ movl DISP(PSTATE_REG,SLOT(57)),PDEC(SP)
/*****/ movl DISP(PSTATE_REG,SLOT(58)),PDEC(SP)
#endif
LBL(loop4):
movl PVM1_REG,ATEMP2
moveq IMM(0),PVM1_REG
movw DISP(PVM0_REG,-6),PVM1_REG /* get fs */
BGTS( normal_ret)
BEQS( dyn_env_ret)
movl ATEMP2,PINC(LTQ_TAIL_REG) /* push task marker */
andw IMM(0x7fff),PVM1_REG
BRAS( normal_ret)
LBL(dyn_env_ret):
movl ATEMP2,PDEC(ATEMP1) /* push dyn env marker */
movw IMM(SLOT(DYN_ENV_FS)),PVM1_REG
LBL(normal_ret):
addl ATEMP2,PVM1_REG
addw DISP(PVM0_REG,-4),ATEMP2 /* add link */
movl IND(ATEMP2),PVM0_REG
CMPL( DTEMP1,PVM1_REG)
BNES( loop4)
movl DISP(PSTATE_REG,SLOT(BOS_RET)),IND(ATEMP2)
/* Slots of LTQ and DEQ are in reverse order, so reverse them... */
movl ATEMP1,DISP(PSTATE_REG,SLOT(DEQ_TAIL))
movl DISP(PSTATE_REG,SLOT(DEQ_HEAD)),ATEMP2
LBL(loop5):
movl PDEC(ATEMP2),DTEMP1
CMPL( ATEMP2,ATEMP1)
BCCS( deq_reversed)
movl IND(ATEMP1),IND(ATEMP2)
movl DTEMP1,PINC(ATEMP1)
BRAS( loop5)
LBL(deq_reversed):
movl LTQ_TAIL_REG,ATEMP1
movl DISP(PSTATE_REG,SLOT(LTQ_HEAD)),ATEMP2
LBL(loop6):
movl PDEC(ATEMP1),DTEMP1
CMPL( ATEMP1,ATEMP2)
BCCS( ltq_reversed)
movl IND(ATEMP2),IND(ATEMP1)
movl DTEMP1,PINC(ATEMP2)
BRAS( loop6)
LBL(ltq_reversed):
/* Setup correct return address for parent and return to restored cont */
movl DISP(PSTATE_REG,SLOT(PARENT_RET)),ATEMP2
movl PVM0_REG,DISP(PSTATE_REG,SLOT(PARENT_RET))
#ifndef MESSAGE_PASSING_STEAL
clrl DISP(PSTATE_REG,SLOT(STEAL_LOCKO))
#endif
#ifdef debug
/*****/ addw IMM(5*4),SP
/*****/ pea PC_IND($entry)
/*****/ movl PINC(SP),DISP(PSTATE_REG,SLOT(56))
/*****/ movl ATEMP2,DISP(PSTATE_REG,SLOT(57))
/*****/ movl IMM(0),DISP(PSTATE_REG,SLOT(58))
#endif
movl DISP(PSTATE_REG,SLOT(TEMP1)),PVM0_REG
movl DISP(PSTATE_REG,SLOT(TEMP2)),PVM1_REG
movl PVM1_REG,DTEMP1 /* Required for the case of a return from a touch of d0 */
jmp IND(ATEMP2)
CONSTS(3)
PRIMITIVE("###_kernel")
PRIMITIVE("###_kernel.idle")
PRIMITIVE("##startup")
END
/*---------------------------------------------------------------------------*/
OBJECT_FILE_END