/*
 * CPU specific code for Intel compatible chips
 */

#pragma inline
#include <asmrules.h>
#include <cpujmp.h>


int cpusetjmp(cpu_jmp_buf jmpb)
{
    /* save flags in bx */
    asm     pushf
    asm     pop     bx

    /* save es,di */
    asm     mov     dx, es
    asm     mov     cx, di

    /* reference the block */
    asm     les     di, jmpb
    asm     cld

    /* save sp, ss */
    asm     lea     ax, jmpb
    asm     stosw
    asm     mov     ax, SS
    asm     stosw

    /* remember, we saved the flags in bx, save to struct now */
    asm     xchg    ax,bx
    asm     stosw

    /* get CS and IP from caller stack, save 'em */
    asm     mov     ax, W1(jmpb-cPtrSize)   /* large code */
    asm     stosw
    asm     mov     ax, W0(jmpb-cPtrSize)
    asm     stosw


    /* save BP, DI, ES, SI */
    asm     mov     ax, [bp]
    asm     stosw                   /* BP */
    asm     xchg    ax, cx
    asm     stosw                   /* DI */
    asm     mov     ax, dx
    asm     stosw                   /* ES */
    asm     xchg    ax, si
    asm     stosw                   /* SI */

    asm     mov     ax, ds

    asm     stosw                   /* DS */
    asm     mov     es, dx          /* restore ES */
    return 0;
}

void cpulongjmp(cpu_jmp_buf jmpb, int retval)
{
    /* if (retval==0) retval=1; */
    asm     mov     dx, retval
    asm     cmp     dx, 1           /* generates carry if dx=0      */
    asm     adc     dx, 0           /* if was 0, now it's 1  */

    asm     LDS_    si, jmpb
    asm     cld

    /* Change context begins with changing stack */

    asm     pushf                   /* save state of interrupt flag */
    asm     pop     bx              /*  in bx */
    asm     lodsw                   /* sp */
    asm     cli
    asm     mov     ss, [si]        /* SS */
    asm     mov     sp, ax
    asm     push    bx              /* restore state of interrupt flag */
    asm     popf
    asm     lodsw                   /* skip SS */

    asm     lodsw                   /* flags */

        /* need to build link to setjmp's caller IP:CS:FLAGS */
    asm     push    ax              /* flags */
    asm     lodsw                   /* cs */
    asm     push    ax
    asm     lodsw                   /* ip */
    asm     push    ax

        /* restore remaining working registers */
    asm     lodsw                   /* bp */
    asm     xchg    bp, ax
    asm     lodsw                   /* di */
    asm     xchg    di, ax
    asm     lodsw                   /* es */
    asm     mov     es, ax
    asm     lodsw                   /* si */
    asm     mov     ds, [si]
    asm     xchg    si, ax

    asm     xchg    ax, dx          /* restore AX  */
    asm     iret                    /* return to original setjmp caller */
}

