.ad 8
.bm 8
.fm 4
.bt $Copyright by   Software AG, 1993$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $NME$Project Distributed Database System$vos71ka$
.tt 2 $$$
.tt 3 $R.Roedling$ N A M E $1996-07-05$
***********************************************************
.nf


    ========== licence begin LGPL
    Copyright (C) 2002 SAP AG

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    ========== licence end

.fo
.nf
.sp
Module  :
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :

.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :

.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :

.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  :
.sp
.cp 3
Created :
.sp
.cp 3
Version :
.sp
.cp 3
Release :  6.2 	 Date : 1996-07-05
.br
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:

.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:

.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:

.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :



&if  $MACH = ALPHA  AND $OS = WIN32
/****************************************************************************
 *                                                                          *
 *  D E C  /  A L P H A    ( W I N 3 2 )                                    *
 *                                                                          *
 ****************************************************************************/

.file   2 "vos71ka.s"
.text
.align  4

/*
 * typedef struct context_record
 *   {
 *   PUCHAR                          pStackPointer;
 *   PUCHAR                          pStackBase;
 *   PUCHAR                          pStackLimit;
 *   VOID                            (* pFunc) (VOID);
 *
 *   QWORD                           UKT_ra;
 *   QWORD                           UKT_fp;
 *   QWORD                           UKT_s0;
 *   QWORD                           UKT_s1;
 *   QWORD                           UKT_s2;
 *   QWORD                           UKT_s3;
 *   QWORD                           UKT_s4;
 *   QWORD                           UKT_s5;
 *   QWORD                           UKT_gp;
 *   QWORD                           UKT_f1;
 *   } CONTEXT_REC;
 *
 */


/*
 *  VOID sql71k_init_task_stack_frame ( CONTEXT_REC     *pContext,
 *                                      VOID            (* pFunc) () )
 *
 */

.globl  sql71k_init_task_stack_frame
.ent    sql71k_init_task_stack_frame

sql71k_init_task_stack_frame:

        stl     $a1,   12($a0)  /* 2nd arg: tasks function pointer           */
        stq     $zero, 16($a0)  /* init pContext->UKT_ra                     */
        stq     $zero, 24($a0)  /*      pContext->UKT_fp                     */
        stq     $zero, 32($a0)  /*      pContext->UKT_s0                     */
        stq     $zero, 40($a0)  /*      pContext->UKT_s1                     */
        stq     $zero, 48($a0)  /*      pContext->UKT_s2                     */
        stq     $zero, 56($a0)  /*      pContext->UKT_s3                     */
        stq     $zero, 64($a0)  /*      pContext->UKT_s4                     */
        stq     $zero, 72($a0)  /*      pContext->UKT_s5                     */
        stq     $zero, 80($a0)  /*      pContext->UKT_gp                     */
        stt     $f31,  88($a0)  /*      pContext->UKT_f2                     */

        ldl     $t0, 4($a0)     /* 1st arg: pContext->lStackBase is          */
                                /*          stack's last word                */

        ldiq    $t1, 0xfffa5a5afffa5a5a
        stq     $t1, 0($t0)     /* as float, causes floating point trap      */
        stq     $t1, 8($t0)     /* as ptr, causes addr or seg violation      */

        ret     $zero, ($ra), 1 /* return to caller                          */

 .end     sql71k_init_task_stack_frame


/*
 *
 *  BOOL sql71k_first_task_stack ( CONTEXT_REC     *pContext );
 *
 */

.globl  sql71k_first_task_stack
.ent    sql71k_first_task_stack

sql71k_first_task_stack:
        ldl     $t0, 0($a0)    /* change to task stack:                     */
                               /*       pContext->lStackPointer into t0     */

        /* Restore task's stack WITHOUT updating pContext->lStackPointer    */
        lda     $sp,  -0x10($t0)
        stq     $ra,  0($sp)
        trapb
.prologue 0

        stq     $ra, 16($a0)  /* init   pContext->UKT_ra                    */
        stq     $fp, 24($a0)  /*        pContext->UKT_fp                    */
        stq     $s0, 32($a0)  /*        pContext->UKT_s0                    */
        stq     $s1, 40($a0)  /*        pContext->UKT_s1                    */
        stq     $s2, 48($a0)  /*        pContext->UKT_s2                    */
        stq     $s3, 56($a0)  /*        pContext->UKT_s3                    */
        stq     $s4, 64($a0)  /*        pContext->UKT_s4                    */
        stq     $s5, 72($a0)  /*        pContext->UKT_s5                    */
        stq     $gp, 80($a0)  /*        pContext->UKT_gp                    */
        stt     $f2, 88($a0)  /*        pContext->UKT_f2                    */

        ldl     $t12,12($a0)  /* load  pContext->pFunc                      */
        jsr     $ra,($t12)
        ret     $ra

.end    sql71k_first_task_stack

/*
 *
 *  BOOL sql71k_first_task_stack_fp ( CONTEXT_REC     *pContext );
 *
 */
.globl  sql71k_first_task_stack_fp
.ent    sql71k_first_task_stack_fp
.frame $fp 0x10 $ra

sql71k_first_task_stack_fp:
        lda     $sp,  -0x10($sp)
        stq     $ra,  0($sp)
        stq     $fp,  8($sp)
        trapb
        bis     $zero,$sp,$fp
.prologue 0
        bsr     $ra, sql71k_first_task_stack
        ldq     $fp, 8($sp)
        ldq     $ra, 0($sp)
        lda     $sp, 0x10($sp)
        ret     $ra
.end    sql71k_first_task_stack_fp

/*
 *
 *  BOOL sql71k_chg_task_stack ( CONTEXT_REC     *pNewContext,
 *                               CONTEXT_REC     *pOldContext )
 *
 */

.globl  sql71k_chg_task_stack
.ent    sql71k_chg_task_stack

sql71k_chg_task_stack:
        lda     $sp, -0x50($sp) /* grow old task stack: ret addr & 7 regs    */

        /* Save regs and return addr for old task                            */
        stq     $s0, 0($sp)
        stq     $s1, 8($sp)
        stq     $s2, 16($sp)
        stq     $s3, 24($sp)
        stq     $s4, 32($sp)
        stq     $s5, 40($sp)
        stq     $ra, 48($sp)    /* return addr for old task                  */
        stq     $fp, 56($sp)
        stt     $f2, 64($sp)


        /* Make sure stack hasn't grown too much */
        ldl     $t0, 4($a1)     /* 2nd arg: pOldContext->lStackBase          */
                                /*          should be <= sp                  */
        cmpule  $t0, $sp, $t1   /* if pOldContext->lStackBase <= sp          */
                                /* then $2 = 1 else $2 = 0                   */
        beq     $t1,e71_chg_err /* stack has grown too big                   */

        /* Make sure end of stack hasn't been overwritten                    */
        ldl     $t0, 4($a1)      /* 2nd arg: pOldContext->lStackBase         */
        ldq     $t1, 0($t0)      /* get last word in stack                   */
        subq    $t1, 0xfffa5a5afffa5a5a, $t2
        bne     $t2, e71_chg_err /* subtraction result is in this reg        */
        ldq     $t1, 8($1)       /* get next-to-last word in stack           */
        subq    $t1, 0xfffa5a5afffa5a5a, $t2
        bne     $t2, e71_chg_err /* subtraction result is in this reg        */

        /* Finished with old task stack                                      */
        stl     $sp, 0($a1)      /* 2nd arg: sp into                                             */
                                 /* pOldContext->lStackPointer               */

        ldq     $t0, 16($a0)     /* pNewContext->ra                          */
        bne     $t0, e71_change  /* branch if task is already active         */

        /* load registers for inactive task                                  */
        ldq     $ra, 16($a1)     /* load pOldContext->UKT_ra                 */
        ldq     $fp, 24($a1)     /*      pOldContext->UKT_fp                 */
        ldq     $s0, 32($a1)     /*      pOldContext->UKT_s0                 */
        ldq     $s1, 40($a1)     /*      pOldContext->UKT_s1                 */
        ldq     $s2, 48($a1)     /*      pOldContext->UKT_s2                 */
        ldq     $s3, 56($a1)     /*      pOldContext->UKT_s3                 */
        ldq     $s4, 64($a1)     /*      pOldContext->UKT_s4                 */
        ldq     $s5, 72($a1)     /*      pOldContext->UKT_s5                 */
        ldq     $gp, 80($a1)     /*      pOldContext->UKT_gp                 */
        ldt     $f2, 88($a1)     /*      pOldContext->UKT_f2                 */


        jmp     $zero, sql71k_first_task_stack   /* startup task first time  */

e71_change:
        /* Change to new task stack, restore regs and return addr            */
        ldl     $sp, 0($a0)     /* pNewContext->lStackPointer into sp        */
        ldq     $s0, 0($sp)     /* restore regs for new task                 */
        ldq     $s1, 8($sp)
        ldq     $s2, 16($sp)
        ldq     $s3, 24($sp)
        ldq     $s4, 32($sp)
        ldq     $s5, 40($sp)
        ldq     $ra, 48($sp)    /* will return to new task's caller          */
        ldq     $t12,48($sp)    /* will return to new task's caller          */
        ldq     $fp, 56($sp)
        ldt     $f2, 64($sp)

        /* Restore new task's stack WITHOUT updating                         */
        /* pNewContext->lStackPointer                                        */
        lda     $sp, 0x50($sp)

        ldiq    $v0, 0          /* returnvalue 0 = ok                        */
        ret     $zero, ($ra), 1 /* return                                    */

e71_chg_err:
        lda     $sp, 0x50($sp)
        ldiq    $v0, 1          /* returnvalue 1 = overflow                  */
        ret     $zero, ($ra), 1 /* return                                    */

.end    sql71k_chg_task_stack

&else
&if  $MACH = MIPS AND $OS = WIN32

/****************************************************************************
 *                                                                          *
 *  M I P S   ( W I N 3 2 )                                                 *
 *                                                                          *
 ****************************************************************************/

#include   <kxmips.h>

/* typedef struct context_record
 *  {
 *  PUCHAR                          pStackPointer;
 *  PUCHAR                          pStackBase;
 *  PUCHAR                          pStackLimit;
 *  VOID                            (* pFunc) (VOID);
 *
 *  DWORD                           UKT_ra;
 *  DWORD                           UKT_v0;
 *  DWORD                           UKT_v1;
 *  DWORD                           UKT_s0;
 *  DWORD                           UKT_s1;
 *  DWORD                           UKT_s2;
 *  DWORD                           UKT_s3;
 *  DWORD                           UKT_s4;
 *  DWORD                           UKT_s5;
 *  DWORD                           UKT_s6;
 *  DWORD                           UKT_s7;
 *  DWORD                           UKT_s8;
 *  } CONTEXT_REC;
 */

/*
 *  VOID sql71k_init_task_stack_frame ( CONTEXT_REC     *pContext,
 *                                      VOID            (* pFunc) () )
 *
 */

.globl  sql71k_init_task_stack_frame
.ent    sql71k_init_task_stack_frame

sql71k_init_task_stack_frame:

                sw              a1,   12(a0)            //  pContext->pFunc := pFunc

                // Initialize pContext-structure with NULL
                sw              zero, 16(a0)            //  pContex->ra := 0                    ra: return address
                sw              zero, 20(a0)            //  pContex->v0
                sw              zero, 24(a0)            //  pContex->v1
                sw              zero, 28(a0)            //  pContex->s0
                sw              zero, 32(a0)            //  pContex->s1
                sw              zero, 36(a0)            //  pContex->s2
                sw              zero, 40(a0)            //  pContex->s3
                sw              zero, 44(a0)            //  pContex->s4
                sw              zero, 48(a0)            //  pContex->s5
                sw              zero, 52(a0)            //  pContex->s6
                sw              zero, 56(a0)            //  pContex->s7
                sw              zero, 60(a0)            //  pContex->s8

                lw              t0,  4(a0)                      //  t0 := pContext->StackBase
                lui             t1,     0xFFFA
                addiu   t1, t1, 0x5A5A                  //  t1 := 0x0FFFA5A5A
                sw              t1,  0(t0)              //  write t1 to Stackbase
                sw              t1,  4(t0)              //  write t1 to Stackbase + 4
                sw              t1,  8(t0)              //  write t1 to Stackbase + 8
                sw              t1, 12(t0)              //  write t1 to Stackbase + 12

                j               ra                      //  void function, so no return value

.end     sql71k_init_task_stack_frame


/*
 *
 *  BOOL sql71k_first_task_stack ( CONTEXT_REC *pContext );
 *
 */

.globl  sql71k_first_task_stack
.ent    sql71k_first_task_stack

sql71k_first_task_stack:

                // Change to new stack
                lw              t0, 0(a0)               // t0 := pContext->sp
                addiu   sp,t0,-0x10                     // sp := pCOntext->sp - 0x10

                // Put return address on stack
                sw              ra, 0(sp)               // ra on stack at sp

                // Store registers in context
                sw              ra, 16(a0)              // pContex->ra
                sw              v0, 20(a0)              // pContex->v0
                sw              v1, 24(a0)              // pContex->v1
                sw              s0, 28(a0)              // pContex->s0
                sw              s1, 32(a0)              // pContex->s1
                sw              s2, 36(a0)              // pContex->s2
                sw              s3, 40(a0)              // pContex->s3
                sw              s4, 44(a0)              // pContex->s4
                sw              s5, 48(a0)              // pContex->s5
                sw              s6, 52(a0)              // pContex->s6
                sw              s7, 56(a0)              // pContex->s7
                sw              s8, 60(a0)              // pContex->s8

                // Run new task
                lw              t1, 12(a0)              // t1 := pContext->pFunc
                j               t1                      // jump to pContext->pFunc

                addiu   v0,zero,1                       // return 1
                j               ra

.end    sql71k_first_task_stack

/*
 *
 *  BOOL sql71k_chg_task_stack ( CONTEXT_REC     *pNewContext,
 *                               CONTEXT_REC     *pOldContext )
 *
 */

.globl  sql71k_chg_task_stack
.ent    sql71k_chg_task_stack

sql71k_chg_task_stack:
        // Decrement stackpointer to save registers
        addiu   sp,sp,-80

        // Save registers on stack
        sw              v0,  0(sp)
        sw              v1,  4(sp)
        sw              s0,  8(sp)
        sw              s1, 12(sp)
        sw              s2, 16(sp)
        sw              s3, 20(sp)
        sw              s4, 24(sp)
        sw              s5, 28(sp)
        sw              s6, 32(sp)
        sw              s7, 36(sp)
        sw              s8, 40(sp)
        sw              ra, 44(sp)

        // Make sure stack hasn't grown too much
        lw              t0, 4(a1)               // t0 := pOldContext->StackBase
        slt             t1, t0, sp              // t1 := ( pOldContext->StackBase <= sp ? 1 : 0 )
        beq             t1, zero, e71_chg_err

        // Make sure end of stack hasn't been overridden
        lw              t0, 4(a1)               // t0 := pOldContext->StackBase
        lui             t2, 0xfffa              // t2 := fffa0000
        addiu   t2, t2, 0x5a5a  // t2 := t2 + 5a5a

        lw              t1, 0(t0)               // t1 := get last word of stack
        sub             t3, t2, t1              // t3 := t2 - t1                t3 has to be zero
        bne             t3, zero, e71_chg_err

        lw              t1, 4(t0)               // t1 := get 2nd last word of stack
        sub             t3, t2, t1              // t3 := t2 - t1                t3 has to be zero
        bne             t3, zero, e71_chg_err

        lw              t1, 8(t0)               // t1 := get 3rd last word of stack
        sub             t3, t2, t1              // t3 := t2 - t1                t3 has to be zero
        bne             t3, zero, e71_chg_err

        lw              t1, 12(t0)              // t1 := get 4th last word of stack
        sub             t3, t2, t1              // t3 := t2 - t1                t3 has to be zero
        bne             t3, zero, e71_chg_err


        // Save stackpointer to pOldContext
        sw              sp,0(a1)                // pOldContext->StackPointer := sp

        // Check new return adress if it is zero or not
        lw              t0,16(a0)               // t0 := pNewContext->ra
        bne             t0,zero, e71_change     // branch if task already active


        // Process new task

        // Load register from old context ...
        lw              ra, 16(a1)                      // pOldContex->ra
        lw              v0, 20(a1)                      // pOldContex->v0
        lw              v1, 24(a1)                      // pOldContex->v1
        lw              s0, 28(a1)                      // pOldContex->s0
        lw              s1, 32(a1)                      // pOldContex->s1
        lw              s2, 36(a1)                      // pOldContex->s2
        lw              s3, 40(a1)                      // pOldContex->s3
        lw              s4, 44(a1)                      // pOldContex->s4
        lw              s5, 48(a1)                      // pOldContex->s5
        lw              s6, 52(a1)                      // pOldContex->s6
        lw              s7, 56(a1)                      // pOldContex->s7
        lw              s8, 60(a1)                      // pOldContex->s8

        // ... and start task
        j               sql71k_first_task_stack         // with no return ...


e71_change:

        // Process active task ...

        // Load stackpointer
        lw              sp,0(a0)

        // Load register-set from stack
        lw              v0,  0(sp)
        lw              v1,  4(sp)
        lw              s0,  8(sp)
        lw              s1, 12(sp)
        lw              s2, 16(sp)
        lw              s3, 20(sp)
        lw              s4, 24(sp)
        lw              s5, 28(sp)
        lw              s6, 32(sp)
        lw              s7, 36(sp)
        lw              s8, 40(sp)
        lw              ra, 44(sp)

        // Restore stackpointer
        addiu   sp,sp,80

        addiu   v0,zero,0                       //  Return 0: No error
        j               ra

e71_chg_err:

        // Restore stackpointer
        addiu   sp,sp,80

        addiu   v0,zero,0                       //  Return 1: Error occurred
        j               ra

.end    sql71k_chg_task_stack

/* END of MIPS section */

&else
&if  $MACH = PPC AND $OS = WIN32

# ***************************************************************************
# *                                                                         *
# *  P o w e r P C   ( W I N 3 2 )                                          *
# *                                                                         *
# ***************************************************************************

#
#  vos71ka:    MotPPC section   PowerPC code (for Motorola PAS assembler)
#  inserted   1996.05.28    Klaus Fittges (kf)/ jh&p - infolytics
#  changed    1996.06.10ff    kf
#
# BOOL sql71k_first_task_stack      ( CONTEXT_REC *pNewContext );
# BOOL sql71k_chg_task_stack        ( CONTEXT_REC *pNewContext,
#                                     CONTEXT_REC *pOldContext );
# VOID sql71k_init_task_stack_frame ( CONTEXT_REC *pContext,
#                                     VOID   (* pFunc) (VOID) );
# typedef struct context_record
#  {
#   PUCHAR      pStackPointer;      Pos:   0
#   PUCHAR      pStackBase;         Pos:   4
#   PUCHAR      pStackLimit;        Pos:   8
#   VOID        (* pFunc) (VOID);   Pos:  12
#
#   DWORD       UKT_SP;             Pos:  16
#   DWORD       UKT_Rtoc;           Pos:  20
#   DWORD       UKT_Lr;             /* Link register */ Pos:  24
#   DWORD       UKT_Cr;             /* Condition register */Pos:  28
#   DWORD       UKT_Ctr;            /* Count register */  Pos:  32
#   DWORD       UKT_Xer;            /* Fixed point exc.reg */Pos:  36
#
#   double          UKT_Fprs[18];   Pos: 40 ..  183 (144 Bytes)
#   DWORD           UKT_Gprs[19];   Pos: 184 .. 259 ( 76 Bytes)
#   DWORD           UKT_Fpscr       Pos: 260
#  } CONTEXT_REC;
#
#
# sizes of context_rec and stack frame
	.set	CREC_SIZE,264
	.set	FRAME_SIZE,288
# offsets into stack
	.set	OS_FPR,8
	.set	OS_GPR,152
	.set	OS_LR,240
	.set	OS_CR,244
# offsets into context_rec
	.set	OC_GPR,184
	.set	OC_FPSCR,260
# module entries and global definitions
	.globl	..sql71k_first_task_stack
 	.globl	sql71k_first_task_stack
	.globl	..sql71k_chg_task_stack
	.globl	sql71k_chg_task_stack
	.globl	..sql71k_init_task_stack_frame
	.globl	sql71k_init_task_stack_frame
	.globl  sq71k_ft_do
	.globl  sq71k_save_gprs
	.globl  sq71k_rest_gprs
	.globl  sq71k_change
	.globl  sq71k_overflow
# function descriptors
	.tocd
sentinel:
	.byte   0xBB,0x99,0x88,0x11     # sentinel value for stack overflow
	.long	0
sql71k_first_task_stack:
	.long	..sql71k_first_task_stack
	.long	0
	.long	0
sql71k_chg_task_stack:
	.long	..sql71k_chg_task_stack
	.long	0
	.long	0
sql71k_init_task_stack_frame:
	.long	..sql71k_init_task_stack_frame
	.long	0
	.long	0

# function table entry definitions (Tag table index)
#  (for WindowsNT exception processing)
	.pdata
	.align	2
	.long	..sql71k_first_task_stack,sq71k_ft_end,0,0,sq71k_ft_body
	.long	..sql71k_chg_task_stack,sq71k_ct_end,0,0,sq71k_ct_body
#
	.text

#
# VOID   sql71k_init_task_stack_frame
#   (r3) = 1st parameter : CONTEXT_REC     *pContext
#   (r4) = 2nd parameter : VOID            (* pFunc) (VOID)
#
..sql71k_init_task_stack_frame:

	stw     r4,12(r3)	# store pointer to ukt procedure entry

	li      r5,0
	stw     r5,16(r3)	# clear special_regs part of context_rec
	stw     r5,20(r3)
	stw     r5,24(r3)
	stw     r5,28(r3)
	stw     r5,32(r3)
	stw     r5,36(r3)

# Store sentinel values at stack base (for stack checking)

	lwz     r4,4(r3)        # pre-defined 'stack base' value
	la      r6,[tocv]sentinel(rtoc)
	lwz     r5,0(r6)        # sentinel value '0x118899BB'
	stw     r5,0(r4)	# store ... (4 times, 16 bytes)
	stw     r5,4(r4)
	stw     r5,8(r4)
	stw     r5,12(r4)

	blr

# ... end of sql71k_init_task_stack_frame


#
# BOOL  sql71k_first_task_stack
# (r3) = 1st parameter : CONTEXT_REC     *pContext
#

..sql71k_first_task_stack:
	stw     r30,-8(r1)
	mflr    r30             # save return address in permanent register 31
	stw     r31,-4(r1)
	stw     r3,24(r1)       # parameter area of prev. stack
	stw     r2,8(r1)
	stwu    r1,-80(r1)      # establish new mini-frame
	ori     r31,r1,0        # seems to be VC++ usage
#
sq71k_ft_body:
	bl      sq71k_ft_do	# do the first task things ..
#
	la      r1,80(r1)	# back chain
	mtlr    r30
	lwz     r30,-8(r1)
	lwz     r31,-4(r1)
	lwz     r2,8(r1)
	blr
sq71k_ft_end:
	.long	0
#.. end of sql71k_first_task_stack
#
#
# do the task initialization ... (also called by _chg_stack)
sq71k_ft_do:
	mflr	r0
	lwz     r4,0(r3)   # get predefined value for Task stack pointer
	stw     r31,-4(r4)
	stw     r30,-8(r4)
	stw     r0,-12(r4) # temporarily save our return address

# save special registers in context_rec (not: SP register !)
	stw     r2,20(r3)
	stw     r0,24(r3)
	mfcr    r0
	stw     r0,28(r3)
	mfctr   r0
	stw     r0,32(r3)
	mfxer   r0
	stw     r0,36(r3)
# save nonvolatile Gprs in context_rec
	la      r12,OC_FPSCR(r3) # position after Gpr area
	bl      sq71k_save_gprs
	lwz     r0,-12(r4)
	mtlr    r0         # for Debugger call stack
	stw     r1,0(r4)   # pseudo 'frame chain'
#
	la      r1,-80(r4) #     !!!!  Context Switch  !!!!
#
	lwz     r4,12(r3)  # pointer to ukt procedure entry
	lwz     r0,0(r4)
	mtlr    r0         # move ukt procedure entry to Link Register
	blrl               # branch to Task
#
 	lwz     r0,80-12(r1)    # restore our return address
	lwz	r30,80-8(r1)
	lwz	r31,80-4(r1)
	mtlr    r0
	blr
# ... end of sq71k_ft_do
#

#
# BOOL sql71k_chg_task_stack ( CONTEXT_REC *pNewContext,    ... 0(r3) ...
#                              CONTEXT_REC *pOldContext );  ... 0(r4) ...
#

..sql71k_chg_task_stack:
# store registers on OLD task's stack
	mflr    r0
	la      r12,-OS_GPR(r1)
	bl      sq71k_save_gprs
	stw     r0,-OS_LR(r1)
	mfcr    r0
	stw     r0,-OS_CR(r1)
	stwu    r1,-FRAME_SIZE(r1) # establish new frame for OLD task
	ori     r31,r1,0
#
sq71k_ct_body:
	stw     r1,0(r4)	# save stack pointer for OLD task
# consistency check for OLD task's stack
	stw     r0,28(r4)       # condition register will be altered
	lwz     r6,4(r4)        # stack base
	cmp     cr7,0,r1,r6     # compare stack pointer to stack base
	blt     cr7,sq71k_overflow
#
	la      r7,[tocv]sentinel(rtoc) # addr of sentinel value 'BB998811'x
	lwz     r5,0(r7)
	lwz     r7,0(r6)        # should be sentinel value
	cmp     cr0,0,r7,r5     # test
	bne     sq71k_overflow  # jump if overwritten
	lwz     r7,4(r6)        # ... same
	cmp     cr0,0,r7,r5
	bne     sq71k_overflow
	lwz     r7,8(r6)        # ... same
	cmp     cr0,0,r7,r5
	bne     sq71k_overflow
	lwz     r7,12(r6)       # ... same
	cmp     cr0,0,r7,r5
	bne     sq71k_overflow
#
# test if new task is already active: look for stored Gpr2 value (==RTOC)
#  nonzero means: UKT task is already active
	lwz     r5,20(r3)       # Gpr2 value (from NewContext)
	cmpi	cr0,0,r5,0      # test for zero (= initial value)
	bne     sq71k_change    # if not 0 jump
#
#
# inactive tasks (value for Gpr2 (== RTOC) was zero)
	lwz     r0,28(r4)
	mtcr    r0              # restore CR

# restore Gprs for inactive task from Old (=new) context
	la      r12,OC_FPSCR(r4)
	bl      sq71k_rest_gprs
# load special registers for inactive task from Old (=new) context
	lwz     r30,24(r4)
	lwz     r0,28(r4)
	mtcr	r0
	lwz     r0,32(r4)
	mtctr   r0
	lwz     r0,36(r4)
	mtxer   r0
	mtlr	r30
# finally, set Gpr2 (TOC pointer)
	lwz     r2,20(r4)
# proceed as in 'first_task_stack'

	b       sq71k_ft_do
#
#
sq71k_overflow:  # OLD task stack overflow detected
	li      r5,1    # return code: error
	b       sq71k_return
#
#
sq71k_change:    # active task

# change to new task stack, restore registers and return address
# restore stack pointer
	lwz     r1,0(r3)        #  !!!!  Context Switch  !!!!
	ori     r31,r1,0
	li      r5,0    # return code: ok

sq71k_return:
# restore Gp registers and special registers (return address) from stack
	la      r12,-OS_GPR+FRAME_SIZE(r1)
	bl      sq71k_rest_gprs
	la      r12,FRAME_SIZE(r1)
	lwz     r0,-OS_CR(r12)
	mtcr	r0
	lwz     r0,-OS_LR(r12)	# LR, = return address
	mtlr    r0
	la      r1,FRAME_SIZE(r1)
	ori     r3,r5,0         # move return code to Gpr3
	blr       # return via link register

sq71k_ct_end:
	.long	0
#
#
# save and restore non-volatile GP registers (13..31)
sq71k_save_gprs:
	stw	r13,-4*(32-13)(r12)
	stw	r14,-4*(32-14)(r12)
	stw	r15,-4*(32-15)(r12)
	stw	r16,-4*(32-16)(r12)
	stw	r17,-4*(32-17)(r12)
	stw	r18,-4*(32-18)(r12)
	stw	r19,-4*(32-19)(r12)
	stw	r20,-4*(32-20)(r12)
	stw	r21,-4*(32-21)(r12)
	stw	r22,-4*(32-22)(r12)
	stw	r23,-4*(32-23)(r12)
	stw	r24,-4*(32-24)(r12)
	stw	r25,-4*(32-25)(r12)
	stw	r26,-4*(32-26)(r12)
	stw	r27,-4*(32-27)(r12)
	stw	r28,-4*(32-28)(r12)
	stw	r29,-4*(32-29)(r12)
	stw	r30,-4*(32-30)(r12)
	stw	r31,-4*(32-31)(r12)
	blr
sq71k_rest_gprs:
	lwz	r13,-4*(32-13)(r12)
	lwz	r14,-4*(32-14)(r12)
	lwz	r15,-4*(32-15)(r12)
	lwz	r16,-4*(32-16)(r12)
	lwz	r17,-4*(32-17)(r12)
	lwz	r18,-4*(32-18)(r12)
	lwz	r19,-4*(32-19)(r12)
	lwz	r20,-4*(32-20)(r12)
	lwz	r21,-4*(32-21)(r12)
	lwz	r22,-4*(32-22)(r12)
	lwz	r23,-4*(32-23)(r12)
	lwz	r24,-4*(32-24)(r12)
	lwz	r25,-4*(32-25)(r12)
	lwz	r26,-4*(32-26)(r12)
	lwz	r27,-4*(32-27)(r12)
	lwz	r28,-4*(32-28)(r12)
	lwz	r29,-4*(32-29)(r12)
	lwz	r30,-4*(32-30)(r12)
	lwz	r31,-4*(32-31)(r12)
	blr


/* END of PPC section */

&else
&if  $MACH = I386 AND $OS = WIN32

;****************************************************************************
;*                                                                          *
;*  I N T E L   ( W I N 3 2 )                                               *
;*                                                                          *
;****************************************************************************

 TITLE   ven71ka.asm
 PAGE    ,80
.386

.MODEL   SMALL,C
 SYSTEM_LINKAGE=1

 ASSUME  CS: CODE32

 CODE32 SEGMENT DWORD USE32 PUBLIC 'CODE'

 ;
 ;    typedef struct context_record
 ;      {
 ;      PUCHAR                          pStackPointer;         Pos:  0
 ;      PUCHAR                          pStackBase;            Pos:  4
 ;      PUCHAR                          pStackLimit;           Pos:  8
 ;
 ;      VOID                            (* pFunc) (VOID);      Pos:  12
 ;
 ;      DWORD                           UKT_ebp;               Pos:  16
 ;      DWORD                           UKT_esi;               Pos:  20
 ;      DWORD                           UKT_edi;               Pos:  24
 ;      DWORD                           UKT_edx;               Pos:  28
 ;      DWORD                           UKT_ecx;               Pos:  32
 ;      DWORD                           UKT_ebx;               Pos:  36
 ;      DWORD                           UKT_flags;             Pos:  40
 ;      DWORD                           UKT_return_addr;       Pos:  44
 ;      } CONTEXT_REC;
 ;
 ;  VOID sql71k_init_task_stack_frame ( CONTEXT_REC     *pContext,
 ;                                      VOID            (* pFunc) () )
 ;
 ;
 ;  ( no system linkage! )
 ;

ifdef STDCALL
 PUBLIC  sql71k_init_task_stack_frame@8

    sql71k_init_task_stack_frame@8 PROC NEAR
else
 PUBLIC  sql71k_init_task_stack_frame

    sql71k_init_task_stack_frame PROC NEAR
endif

       push    ebp                     ; enter-sequence
       mov     ebp , esp

      ifdef SYSTEM_LINKAGE
       mov     eax, [ebp + 08H]        ; get first parameter (pContext)
       mov     edx, [ebp + 0CH]        ; get second parameter (* pFunc)
      endif

ifdef STDCALL
       push    0                       ; parameter (popped with first "ret 8")
       push    0                       ; another parameter
endif
       mov     DWORD PTR[eax+12], edx  ; save address" of 'pFunc'
       mov     DWORD PTR[eax+16], 0    ; init UKT_ebp
       mov     DWORD PTR[eax+20], 0    ;      UKT_esi
       mov     DWORD PTR[eax+24], 0    ;      UKT_edi
       mov     DWORD PTR[eax+28], 0    ;      UKT_edx
       mov     DWORD PTR[eax+32], 0    ;      UKT_ecx
       mov     DWORD PTR[eax+36], 0    ;      UKT_ebx
       mov     DWORD PTR[eax+40], 0    ;      UKT_flags
       mov     DWORD PTR[eax+44], 0    ;      UKT_return_addr

       ;
       ;  Generate stack checking sequence!
       ;
       mov     esp, DWORD PTR[eax + 4] ; get stack base from struct context_record
       add     esp, 8
       push    0BB998811H
       push    0BB998811H

       leave
ifdef STDCALL
       ret     8                       ; remove 8 bytes parameter
else
       ret
endif

ifdef STDCALL
    sql71k_init_task_stack_frame@8 ENDP
else
    sql71k_init_task_stack_frame ENDP
endif


 ;
 ;
 ;  BOOL sql71k_first_task_stack ( CONTEXT_REC     *pContext )
 ;
 ;
ifdef STDCALL
 PUBLIC  sql71k_first_task_stack@4

    sql71k_first_task_stack@4 PROC NEAR
else
 PUBLIC  sql71k_first_task_stack

    sql71k_first_task_stack PROC NEAR
endif

       ifdef SYSTEM_LINKAGE
        mov     eax, [esp + 04H]       ; get parameter (pContext)
       endif

       push    edx                     ; save 'edx'

       mov     DWORD PTR[eax+16], ebp  ; set UKT_ebp
       mov     DWORD PTR[eax+20], esi  ;     UKT_esi
       mov     DWORD PTR[eax+24], edi  ;     UKT_edi
       mov     DWORD PTR[eax+28], edx  ;     UKT_edx
       mov     DWORD PTR[eax+32], ecx  ;     UKT_ecx
       mov     DWORD PTR[eax+36], ebx  ;     UKT_ebx

       pushfd                          ; store flags
       pop     edx                     ; get flags
       mov     DWORD PTR[eax+40], edx  ; set UKT_flags

       mov     edx, [esp + 04H]        ; get return address
       mov     DWORD PTR[eax+44], edx  ; set UKT_return_addr

       pop     edx                     ; restore 'edx'

       mov     esp, DWORD PTR[eax]     ; get stack pointer from struct context
       mov     edx, DWORD PTR[eax+44]  ; get UKT_return_addr
       push    edx                     ; push return address
       mov     edx, DWORD PTR[eax+12]  ; get 'pFunc' from struct context
       push    edx                     ; push address of 'pFunc'

       mov     edx, DWORD PTR[eax+28]  ; restore 'edx'

       ret

ifdef STDCALL
    sql71k_first_task_stack@8 ENDP
else
    sql71k_first_task_stack ENDP
endif


 ;
 ;
 ;  BOOL sql71k_chg_task_stack ( CONTEXT_REC     *pNewContext,
 ;                               CONTEXT_REC     *pOldContext )
 ;
 ;

ifdef STDCALL
 PUBLIC  sql71k_chg_task_stack@8

    sql71k_chg_task_stack@8 PROC NEAR
else
 PUBLIC  sql71k_chg_task_stack

    sql71k_chg_task_stack   PROC NEAR
endif

       push    ebp                     ; enter-sequence
       mov     ebp , esp

       pushfd                          ; save registers
       push    esi
       push    edi
       push    edx
       push    ecx
       push    ebx

      ifdef SYSTEM_LINKAGE
       mov     edx, [ebp + 0CH]        ; get second parameter (pOldContext)
      endif

       mov     DWORD PTR[edx], esp     ; save stack pointer into struct context_record

       ;
       ;  stack checking sequence of the OLD task
       ;
       mov     ecx, DWORD PTR[edx + 4]      ; get stack base from struct context_record
       cmp     esp, ecx                     ; check, if esp is below stack base
       jb      short sql71k_overflow        ; jump, if below
       cmp     DWORD PTR[ecx+0], 0BB998811H ; check last forelast word of stack area
       jne     short sql71k_overflow        ; jump, if overwritten
       cmp     DWORD PTR[ecx+4], 0BB998811H ; check prev. word of stack area
       jne     short sql71k_overflow        ; jump, if overwritten

      ifdef SYSTEM_LINKAGE
       mov     eax, [ebp + 08H]        ; get first parameter (pNewContext)
      endif

       mov     ebx, DWORD PTR[eax+16]  ; set UKT_ebp
       or      ebx, ebx                ; test for 0
       jne     short sq71k_chgstack_to ; if not 0 jump


       mov     ebx, DWORD PTR[edx+44]  ; get UKT_return_addr of pOldContext
       mov     DWORD PTR[eax+44], ebx  ; set UKT_return_addr of pNewContext
       mov     ebx, DWORD PTR[edx+40]  ; get UKT_flags of pOldContext
       mov     DWORD PTR[eax+40], ebx  ; set UKT_flags of pNewContext
       push    ebx                     ; push flags
       popfd                           ; restore flags

       push    eax                     ; save address of pNewContext

       mov     eax, edx
       mov     ebp, DWORD PTR[eax+16]  ; get UKT_ebp of pOldContext
       mov     esi, DWORD PTR[eax+20]  ;     UKT_esi
       mov     edi, DWORD PTR[eax+24]  ;     UKT_edi
       mov     edx, DWORD PTR[eax+28]  ;     UKT_edx
       mov     ecx, DWORD PTR[eax+32]  ;     UKT_ecx
       mov     ebx, DWORD PTR[eax+36]  ;     UKT_ebx

       pop     eax                     ; restore address of pNewContext

       mov     DWORD PTR[eax+16], ebp  ; set UKT_ebp of pNewContext
       mov     DWORD PTR[eax+20], esi  ;     UKT_esi
       mov     DWORD PTR[eax+24], edi  ;     UKT_edi
       mov     DWORD PTR[eax+28], edx  ;     UKT_edx
       mov     DWORD PTR[eax+32], ecx  ;     UKT_ecx
       mov     DWORD PTR[eax+36], ebx  ;     UKT_ebx

       mov     esp, DWORD PTR[eax]     ; get stack pointer from struct context
       mov     edx, DWORD PTR[eax+44]  ; get UKT_return_addr
       push    edx                     ; push return address
       mov     edx, DWORD PTR[eax+12]  ; get 'pFunc' from struct context
       push    edx                     ; push address of 'pFunc'

       mov     edx, DWORD PTR[eax+28]  ; restore 'edx'
       mov     eax, 0                  ; NO ERROR

       ret

    sq71k_chgstack_to:
       mov     esp, DWORD PTR[eax]     ; set stack pointer
       mov     eax, 0                  ; NO ERROR
       pop     ebx                     ; restore registers
       pop     ecx
       pop     edx
       pop     edi
       pop     esi
       popfd
       pop     ebp                     ; imcomplete leave-sequence
ifdef STDCALL
       ret     8                       ; remove 8 bytes parameter
else
       ret
endif


    sql71k_overflow:
       mov     eax, 1                  ; STACK OVERFLOW!
       pop     ebx                     ; restore registers
       pop     ecx
       pop     edx
       pop     edi
       pop     esi
       popfd
       leave
ifdef STDCALL
       ret     8                       ; remove 8 bytes parameter
else
       ret
endif

ifdef STDCALL
    sql71k_chg_task_stack@8 ENDP
else
    sql71k_chg_task_stack   ENDP
endif
  CODE32 ENDS
 END
&else

;****************************************************************************
;*                                                                          *
;*  I N T E L                                                               *
;*                                                                          *
;****************************************************************************

 TITLE   ven71ka.asm
 PAGE    ,80
.386
ifdef _WIN32
.MODEL   SMALL,C
 SYSTEM_LINKAGE=1
else
.MODEL   SMALL,PASCAL
endif

 ASSUME  CS: CODE32

 CODE32 SEGMENT DWORD USE32 PUBLIC 'CODE'

 ;
 ;    typedef struct context_record
 ;      {
 ;      LONG                            lStackPointer;
 ;      LONG                            lStackBase;
 ;      LONG                            lStackLimit;
 ;      } CONTEXT_REC;
 ;
 ;
 ;  BOOL sql71k_chg_task_stack ( CONTEXT_REC     *pNewContext,
 ;                               CONTEXT_REC     *pOldContext )
 ;
 ;

ifdef STDCALL
 PUBLIC  sql71k_chg_task_stack@8

    sql71k_chg_task_stack@8 PROC NEAR
else
 PUBLIC  sql71k_chg_task_stack

    sql71k_chg_task_stack   PROC NEAR
endif

       push    ebp                     ; enter-sequence
       mov     ebp , esp

       pushfd                          ; save registers
       push    esi
       push    edi
       push    edx
       push    ecx
       push    ebx

      ifdef SYSTEM_LINKAGE
       mov     edx, [ebp + 0CH]        ; get second parameter (pOldContext)
      endif

       or      edx, edx                ; test for NULL
       je      short sq71k_chgstack_to ; if NULL jump

       mov     DWORD PTR[edx], esp     ; save stack pointer into struct context_record

       ;
       ;  stack checking sequence of the OLD task
       ;
       mov     ecx, DWORD PTR[edx + 4]      ; get stack base from struct context_record
       cmp     esp, ecx                     ; check, if esp is below stack base
       jb      short sql71k_overflow        ; jump, if below
       cmp     DWORD PTR[ecx+0], 0BB998811H ; check last forelast word of stack area
       jne     short sql71k_overflow        ; jump, if overwritten
       cmp     DWORD PTR[ecx+4], 0BB998811H ; check prev. word of stack area
       jne     short sql71k_overflow        ; jump, if overwritten

    sq71k_chgstack_to:

      ifdef SYSTEM_LINKAGE
       mov     eax, [ebp + 08H]        ; get first parameter (pNewContext)
      endif

       or      eax, eax                ; test for NULL
       je      short sq71k_chgstack_ret; if NULL jump
       mov     esp, DWORD PTR[eax]     ; get stack pointer from struct context

    sq71k_chgstack_ret:
       mov     eax, 0                  ; NO ERROR
       pop     ebx                     ; restore registers
       pop     ecx
       pop     edx
       pop     edi
       pop     esi
       popfd
       pop     ebp                     ; imcomplete leave-sequence
ifdef STDCALL
       ret     8                       ; remove 8 bytes parameter
else
       ret
endif


    sql71k_overflow:
       mov     eax, 1                  ; STACK OVERFLOW!
       pop     ebx                     ; restore registers
       pop     ecx
       pop     edx
       pop     edi
       pop     esi
       popfd
       leave
ifdef STDCALL
       ret     8                       ; remove 8 bytes parameter
else
       ret
endif

ifdef STDCALL
    sql71k_chg_task_stack@8 ENDP
else
    sql71k_chg_task_stack   ENDP
endif


 ;
 ;  VOID sql71k_init_task_stack_frame ( CONTEXT_REC     *pContext,
 ;                                      VOID            (* pFunc) () )
 ;
 ;
 ;  ( no system linkage! )
 ;

ifdef STDCALL
 PUBLIC  sql71k_init_task_stack_frame@8

    sql71k_init_task_stack_frame@8 PROC NEAR
else
 PUBLIC  sql71k_init_task_stack_frame

    sql71k_init_task_stack_frame PROC NEAR
endif

       push    ebp                     ; enter-sequence
       mov     ebp , esp

      ifdef SYSTEM_LINKAGE
       mov     eax, [ebp + 08H]        ; get first parameter (pContext)
       mov     edx, [ebp + 0CH]        ; get second parameter (* pFunc)
      endif

       mov     esp, DWORD PTR[eax]     ; get stack pointer from struct context_record

ifdef STDCALL
       push    0                       ; parameter (popped with first "ret 8")
       push    0                       ; another parameter
endif
       push    edx                     ; push "return address" of 'pFunc'
       push    0                       ; old ebp: null-terminator
       pushfd                          ; eflags
       push    55555555H               ; esi
       push    55555555H               ; edi
       push    55555555H               ; edx
       push    55555555H               ; ecx
       push    55555555H               ; ebx

       mov     DWORD PTR[eax], esp     ; save stack pointer into struct context_record

       ;
       ;  Generate stack checking sequence!
       ;
       mov     esp, DWORD PTR[eax + 4] ; get stack base from struct context_record
       add     esp, 8
       push    0BB998811H
       push    0BB998811H

       leave
ifdef STDCALL
       ret     8                       ; remove 8 bytes parameter
else
       ret
endif

ifdef STDCALL
    sql71k_init_task_stack_frame@8 ENDP
else
    sql71k_init_task_stack_frame ENDP
endif
  CODE32 ENDS
 END
&endif
&endif
&endif
&endif

.CM *-END-* code ----------------------------------------
.SP 2
***********************************************************
.PA
