Annotation of coherent/b/STREAMS/i386/as.s, revision 1.1.1.1

1.1       root        1:        .unixorder
                      2:        .llen   132
                      3:        .include        as.inc
                      4: 
                      5: IODELAY        .macro
                      6:        jmp     .+2             / DELAY
                      7:        jmp     .+2             / DELAY
                      8:        .endm
                      9: 
                     10: / Most places where %cr3 is refreshed, it can be done through a Ring 0 gate.
                     11: MMUUPD .macro
                     12:        pushfl
                     13:        cli
                     14:        lcall   $SEG_MMUUPD,$0  / gate to mmuupdfR0
                     15:        popfl
                     16:        .endm
                     17: 
                     18: /
                     19: / USTART and ESP_START map kernel stack and u area within top 4k page
                     20: / of virtual space.
                     21: / NDP context starts 0x100 bytes below u area.
                     22: / See also U_OFFSET, NDP_OFFSET in uproc.h
                     23: /
                     24:        .set    USTART,0xFFFFFB00
                     25:        .set    ESP0_START,0xFFFFF300
                     26:        .set    ESP1_START,USTART
                     27: 
                     28:        .set    u,USTART
                     29:        .set    PSW_VAL,0x1200  / set system IOPL to 1, enable IRQ
                     30: /      .set    PSW_VAL,0x3200  / set system IOPL to 3, enable IRQ
                     31: 
                     32: / (lgl-
                     33: /      The information contained herein is a trade secret of Mark Williams
                     34: /      Company, and  is confidential information.  It is provided  under a
                     35: /      license agreement,  and may be  copied or disclosed  only under the
                     36: /      terms of  that agreement.  Any  reproduction or disclosure  of this
                     37: /      material without the express written authorization of Mark Williams
                     38: /      Company or persuant to the license agreement is unlawful.
                     39: 
                     40: /      Copyright (c) 1982, 1992.
                     41: /      An unpublished work by Mark Williams Company, Chicago.
                     42: /      All rights reserved.
                     43: 
                     44: /      Intel 386 port and extensions
                     45: /      Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991
                     46: / -lgl)
                     47: / 
                     48: / $Log:        as.s,v $
                     49: / Revision 2.3  93/07/26  13:55:44  nigel
                     50: / Nigel's R80
                     51: /
                     52: / Revision 1.17  92/12/08  16:43:10  root
                     53: / ker 70
                     54: / 
                     55: / Revision 1.16  92/11/12  10:04:31  root
                     56: / Ker #68
                     57: / 
                     58: / Revision 1.15  92/11/09  17:08:28  root
                     59: / Just before adding vio segs.
                     60: / 
                     61: / Revision 1.13  92/10/06  23:47:48  root
                     62: / Ker #64
                     63: / 
                     64: / Revision 1.12  92/10/06  20:45:40  root
                     65: / Ker #63d
                     66: / 
                     67: / Revision 1.10  92/07/27  18:15:43  hal
                     68: / Kernel #59
                     69: / 
                     70: / Revision 1.9  92/07/16  16:38:14  hal
                     71: / Kernel #58
                     72: / 
                     73: / Revision 1.8  92/07/15  13:50:55  root
                     74: / COH 4.0.0
                     75: / 
                     76: / Revision 1.6  92/04/03  11:05:28  hal
                     77: / Fix missed IRQ bug.
                     78: / Add read_t0(), read_psw(), getusd(), putusd().
                     79: / 
                     80: 
                     81: ///////
                     82: / Machine language assist for
                     83: / Intel 80386/80486 Coherent. This contains the parts
                     84: / that are common to all machines as well as the machine-specific code
                     85: / for the IBM PC-386
                     86: 
                     87: 
                     88: ///////
                     89: 
                     90: / System entry point.
                     91: 
                     92: / When this code is entered, the boot program has done the following:
                     93: /      Relocate itself above where the kernel will be (e.g., 0x20600).
                     94: /      Load as.s binary; text at 0x02000, data at next paragraph (16-byte)
                     95: /              boundary at or beyond end of kernel text.
                     96: /      CS = 0x02000 <- start of kernel text ("physical" stext)
                     97: /      ES = 0x02xxx <- start of kernel data
                     98: /      SS,DS = 0x20xxx <- ....some address in boot data space....
                     99: 
                    100: / Due to the way the kernel has been linked (see ld.master), symbol "stext"
                    101: / has a value of 0xFFC0_0000, which is the start of the last 4 meg segment.
                    102: / This value is the address in linear space once we have entered paging mode,
                    103: / but until that time relocation arithmetic is necessary:
                    104: /
                    105: / Before segmentation is turned on, symbols in kernel text or data space
                    106: / must be relocated by -SBASE<<BPCSHIFT for memory reference instructions
                    107: / to work.
                    108: 
                    109: ///////
                    110: 
                    111: stext:                                 / kernel code starts at stext+0x100
                    112:        .org .+0x100                    / reserve stack space
                    113:        cli                             / No interrupts, please.
                    114: 
                    115: / put up a debugging "!" on the screen.  We can still use the BIOS.
                    116:        push    %si                      / Save registers.
                    117:        push    %di
                    118: 
                    119:        movb    $'!', %al
                    120: 
                    121:        movw    $0x0007, %bx             / Page 0, white on black
                    122:        movb    $0x0E, %ah               / Write TTY.
                    123:        int     $VIDEO                   / Call video I/O in ROM.
                    124:        pop     %di
                    125:        pop     %si
                    126: 
                    127:        / equipment status word to AX
                    128:        int     $0x11                   / Obtain int 11 value before printf().
                    129:        movl    %eax,%ecx               / esw -> cx
                    130: 
                    131:        / val11 is a long, initially zero, in the CS.
                    132:        / copy (long)esw to val11
                    133:        .byte   PX_ADDR                 / 32-bit address
                    134:        .byte   PX_OPND                 / 32-bit operand
                    135:        movl    %ecx,%cs:[[-SBASE]<<BPCSHIFT]+val11
                    136: 
                    137:                                        / last use of boot block's stack
                    138:        .byte   PX_ADDR                 / 32-bit address
                    139:        .byte   PX_OPND                 / 32-bit operand
                    140:        lgdtl   %cs:[[-SBASE]<<BPCSHIFT]+gdtinit
                    141: 
                    142:        / turn on lsbit of cr0 - Protection Enable
                    143:        mov     %cr0,%eax
                    144:        orb     $1,%al
                    145:        mov     %eax,%cr0
                    146: 
                    147:        / intersegment jump (48-bit address)
                    148:        / jumping flushes the cache...
                    149:        / 
                    150:        .byte   PX_OPND
                    151:        ljmp    $SEG_386_II, $next
                    152: 
                    153: next:
                    154:        movw    $SEG_386_ID, %ax
                    155:        movw    %ax, %ds
                    156:        movw    %ax, %es
                    157:        movw    %ax, %ss
                    158:        movw    $SEG_386_UD|R_USR, %ax
                    159:        movw    %ax, %fs
                    160:        mov     $stext+0x100,%eax       / 256 byte stack for initialization
                    161:        mov     %eax,%esp
                    162: 
                    163: / Enable the A20 address line, which is normally disabled by the ROM BIOS.
                    164: / This line is under the control of the 8042 keyboard interface controller.
                    165: 
                    166:        sub     %ecx, %ecx
                    167: loc0:  inb     $KBCTRL         / Wait for 8042 input buffer to empty.
                    168:        testb   $2,%al
                    169:        loopne  loc0
                    170:        IODELAY
                    171: 
                    172:        movb    $0xD1, %al      / Request next output byte to be
                    173:        outb    $KBCTRL         /       sent to the 8042 output port.
                    174:        IODELAY
                    175: 
                    176:        sub     %ecx, %ecx
                    177: loc1:  inb     $KBCTRL         / Wait for 8042 input buffer to empty.
                    178:        testb   $2, %al
                    179:        loopne  loc1
                    180:        IODELAY
                    181: 
                    182:        movb    $0xDF,%al       / Enable A20 address line.
                    183:        outb    $KBDATA         / See Page 1-44, IBM-AT Tech Ref.
                    184:        IODELAY
                    185: 
                    186:        sub     %ecx, %ecx
                    187: loc2:  inb     $KBCTRL         / Wait for 8042 input buffer to empty.
                    188:        testb   $2,%al          / NOTE: A20 not enabled for up to 20 us.
                    189:        loopne  loc2
                    190: 
                    191: 
                    192: / Reprogram the 8253 timer so that channel 0, 
                    193: / which is used as the clock, interrupts at exactly
                    194: / 100 HZ, instead of 18.2 HZ.
                    195: 
                    196:        movb    $0x36,%al       / Timer 0, LSB, MSB, mode 3
                    197:        outb    $PIT+3
                    198:        IODELAY
                    199:        movb    $0x9C,%al       / Lsb of 59659/5 = 11932
                    200:        outb    $PIT
                    201:        IODELAY
                    202:        movb    $0x2E,%al       / Msb of 59659/5 = 11932
                    203:        outb    $PIT
                    204:        IODELAY
                    205: 
                    206: / Reprogram the 1st programmable interrupt controller.
                    207: / Its default vector table collides with iAPX 286 protection vectors.
                    208:        movb    $0x11,%al       / ICW1 - edge, ICW4
                    209:        outb    $PIC
                    210:        IODELAY
                    211:        movb    $0x20,%al       / ICW2 - Reserve 1st 32 vectors for 286
                    212:        outb    $PICM
                    213:        IODELAY
                    214:        movb    $0x04,%al       / ICW3 - master level 2
                    215:        outb    $PICM
                    216:        IODELAY
                    217:        movb    $0x01,%al       / ICW4 - 8086 mode, master.
                    218:        outb    $PICM
                    219:        IODELAY
                    220: 
                    221: / NIGEL: The original code here (and related code in "i386/md.c") turned off
                    222: / the chain bit in the first PIC by default (and at every subsequent
                    223: / opportunity) even though all the mask bits in the slave PIC are set to off.
                    224: / In order to support an enhanced interrupt architecture for the STREAMS and
                    225: / DDI/DDK subsystems I want to remove the state knowledge from the code in
                    226: / "i386/md.c" so that the chain bit is always left on.
                    227: / In order to do this, I have modified the startup code below so that the
                    228: / system by default allows the slave PIC to interrupt (of course, it still
                    229: / won't interrupt unless it is enabled to; the masking I have removed was
                    230: / totally redundant).
                    231: 
                    232:        movb    $0xFA,%al       / Disable interrupts from master PIC.
                    233:        outb    $PICM           / (except for clock and slave PIC interrupt).
                    234: 
                    235:        movb    $0x11,%al       / ICW1 - edge, ICW4
                    236:        outb    $SPIC
                    237:        IODELAY
                    238:        movb    $0x70,%al       / ICW2 - slave starts at 0x70th interrupt
                    239:        outb    $SPICM
                    240:        IODELAY
                    241:        movb    $0x02,%al       / ICW3 - master level 2
                    242:        outb    $SPICM
                    243:        IODELAY
                    244:        movb    $0x01,%al       / ICW4 - 8086 mode.
                    245:        outb    $SPICM
                    246:        IODELAY
                    247:        movb    $0xFF,%al
                    248:        outb    $SPICM          / Disable interrupts from slave PIC.
                    249: /DEBUG
                    250:        xor     %ebp, %ebp      / Halt stack backtraces
                    251:        cli
                    252:        call    __cinit
                    253:        call    mchinit         / C initialization
                    254:        mov     %cr0,%eax       / Turn on paging
                    255: / use 80000001 to allow FP
                    256: /      or      $0x80000001,%eax
                    257: / use 80000005 to disallow FP
                    258:        or      $0x80000005,%eax
                    259:        mov     %eax,%cr0
                    260:        ljmp    $SEG_RNG0_TXT,$loc3     / clear pipeline; jump far, direct
                    261: 
                    262: /
                    263: / Ring 0 startup code
                    264: /
                    265: loc3:
                    266:        movw    $SEG_386_KD, %ax
                    267:        movw    %ax, %ds
                    268:        movw    $SEG_RNG0_STK, %ax
                    269:        movw    %ax, %ss
                    270:        movl    $ESP0_START,%esp        / Stack pointer for init
                    271:        clts                            / Clear task switched flag.
                    272: 
                    273: / Call the machine setup code.
                    274: / Call Coherent main.
                    275: / On return, send control off to the user
                    276: / at its entry point.
                    277: 
                    278:        sub     %eax, %eax      / Load local descriptor table register.
                    279:        lldt    %ax
                    280: 
                    281: /      movw    $tss,%ax        / Fix low 16 bits of tss base in gdt
                    282: /      movw    %ax,gdt+SEG_TSS+2
                    283: 
                    284:        / Fix tss base in gdt
                    285:        movl    $tss,%eax
                    286:        movw    %ax,gdt+SEG_TSS+2       / Fix bits  0..15
                    287:        rorl    $16,%eax                / Get tss bits 16..31
                    288:        movb    %al,gdt+SEG_TSS+4       / Fix bits 16..23
                    289:        movb    %ah,gdt+SEG_TSS+7       / Fix bits 24..31
                    290: 
                    291:        movw    $SEG_TSS,%ax            / Load task state segment register.
                    292:        ltr     %ax
                    293:        lidt    idtmap                  / Load interrupt descriptor table
                    294:        lgdt    gdtmap
                    295: 
                    296: /      movw    $ldt,%ax                / Relocate ldt in gdt
                    297: /      movw    %ax,gdt+SEG_LDT+2
                    298: 
                    299:        / Fix ldt base in gdt
                    300:        movl    $ldt,%eax
                    301:        movw    %ax,gdt+SEG_LDT+2       / Fix bits  0..15
                    302:        rorl    $16,%eax                / Get ldt bits 16..31
                    303:        movb    %al,gdt+SEG_LDT+4       / Fix bits 16..23
                    304:        movb    %ah,gdt+SEG_LDT+7       / Fix bits 24..31
                    305: 
                    306:        movw    $SEG_LDT,%ax 
                    307:        lldt    %ax
                    308: 
                    309:        call    i8086                   / i8086() does fixup of tss_sp0
                    310: 
                    311: /
                    312: / Enter Ring 1 kernel from Ring 0
                    313: /
                    314:        push    $SEG_RNG1_STK           / SS
                    315:        push    $ESP1_START             / ESP
                    316:        push    $PSW_VAL                / PSW
                    317:        push    $SEG_RNG1_TXT           / CS
                    318:        push    $__xmain__              / IP
                    319:        movw    $SEG_386_KD, %ax        / DS, ES
                    320:        movw    %ax, %ds                / Map data segment
                    321:        movw    %ax, %es                / Map extra segment
                    322:        iret                            / Go to ring 1
                    323: 
                    324: /
                    325: / Start of Ring 1 kernel.
                    326: / Need Ring 1 because interrupts are about to turn on, and all irpt gates
                    327: / have DPL (descriptor privilege level) 1.
                    328: /
                    329: __xmain__:
                    330:        sti                             / Interrupts on, and
                    331:        call    main                    / call Coherent mainline.
                    332:        cli                             / Interrupts off.
                    333: 
                    334: /
                    335: / Enter User mode from Ring 1 kernel
                    336: /
                    337:        push    $SEG_386_UD|R_USR       / SS
                    338:        push    $NBPC                   / ESP
                    339:        push    $PSW_VAL                / PSW
                    340:        push    $SEG_386_UI|R_USR       / CS
                    341:        push    $0                      / IP
                    342:        movw    $SEG_386_UD|R_USR, %ax  / DS, ES
                    343:        movw    %ax, %ds                / Map data segment
                    344:        movw    %ax, %es                / Map extra segment
                    345:        iret                            / Go to user state.
                    346: 
                    347: ///////
                    348: /
                    349: / Trap and interrupt save.
                    350: /
                    351: / This version of tsave runs from Ring 1 trap/irpt gates.
                    352: /
                    353: ///////
                    354:        .globl  disflag
                    355: 
                    356: tsave:                                 / What level of interrupt ? 
                    357:        pusha
                    358:        push    %ds                     / Save current state
                    359:        push    %es
                    360:        push    %fs
                    361:        push    %gs
                    362: 
                    363:        xor     %ebp, %ebp              / Halt backtraces
                    364: 
                    365:        movw    $SEG_386_KD, %ax        / Map ds
                    366:        movw    %ax, %ds
                    367:        movw    %ax, %es
                    368:        movw    $SEG_386_UD|R_USR, %ax  / Map es
                    369:        movw    %ax, %fs
                    370: 
                    371:        sti
                    372:        icall   X_TRAPNO(%esp)          / and call the caller
                    373:        cli
                    374: 
                    375: / if got here from user mode or from idle process, call stand()
                    376: / else just do cleanup and return
                    377: 
                    378:        movb    X_ERR+8(%esp),%al       / trapped CS:  user RPL?
                    379:        andb    $3,%al
                    380:        cmpb    $R_USR,%al
                    381:        je      tsave1a                 / jmp if user mode
                    382:        cmpl    $__idle__,X_ERR+4(%esp) / trapped EIP == idle process?
                    383:        jnz     tsave1b                 / Call stand() only if idle
                    384:        movl    $1,disflag
                    385: 
                    386: tsave1a:
                    387:        sti
                    388:        call    stand
                    389: tsave1b:
                    390:        cli                             / No more interrupts
                    391:        pop     %gs                     / Restore
                    392:        pop     %fs
                    393:        pop     %es
                    394:        pop     %ds
                    395:        popa
                    396:        add     $8,%esp                 / forget err, trapno
                    397:        iret                            / Done.
                    398: 
                    399: /
                    400: / Here is another version of tsave, called only from the GP vector (RING 0)
                    401: /
                    402: 
                    403: BYPASS .macro  addr
                    404:        cmpl    $addr,X_ERR+4(%esp)     / trapped EIP
                    405:        jz      tsave0b
                    406:        .endm
                    407:        
                    408: tsave0:                                        / What level of interrupt ? 
                    409:        pusha
                    410:        push    %ds                     / Save current state
                    411:        push    %es
                    412:        push    %fs
                    413:        push    %gs
                    414: 
                    415:        movw    $SEG_386_KD, %ax        / Map ds
                    416:        movw    %ax, %ds
                    417:        movw    %ax, %es
                    418:        movw    $SEG_386_UD|R_USR, %ax  / Map es
                    419:        movw    %ax, %fs
                    420: 
                    421:        jmp     tsave0b
                    422: 
                    423: //The following lines help find traps during startup.
                    424:        BYPASS  read_cr0
                    425:        BYPASS  read_cr2
                    426:        BYPASS  read_cr3
                    427: tsave0q:
                    428:        mov     52(%esp),%eax           / Print fault code.
                    429:        cmpb    $0x40,%al
                    430:        je      tsave0b                 / Skip over hardware interrupts.
                    431:        push    %eax
                    432:        call    print32
                    433:        pop     %ecx
                    434:  
                    435:        push    $' '
                    436:        call    mchirp
                    437:        pop     %ecx
                    438:  
                    439:        mov     56(%esp),%eax           / Print eip.
                    440:        push    %eax
                    441:        call    print32
                    442:        pop     %ecx
                    443: 
                    444:        push    $' '
                    445:        call    mchirp
                    446:        pop     %ecx
                    447: 
                    448:        push    %esp                    / Print esp.
                    449:        call    print32
                    450:        pop     %ecx
                    451:  
                    452:  tsave0a:      jmp     tsave0a
                    453:  tsave0b:
                    454: //
                    455: 
                    456:        icall   X_TRAPNO(%esp)          / and call the caller
                    457: 
                    458:        pop     %gs                     / Restore
                    459:        pop     %fs
                    460:        pop     %es
                    461:        pop     %ds
                    462:        popa
                    463:        add     $8,%esp                 / forget err, trapno
                    464:        iret                            / Done.
                    465: 
                    466: ///////
                    467: 
                    468: / Save the environment of a process
                    469: / envsave(p)
                    470: / MENV *p;
                    471: 
                    472: / Save the context of a process
                    473: / consave(p)
                    474: / MCON *p;
                    475: 
                    476: ///////
                    477: 
                    478: envsave:
                    479: consave:
                    480:        mov     %edi, %ecx              / Hide di.
                    481:        mov     4(%esp), %edi           / di at the MCON block.
                    482: 
                    483:        cld                             / Ensure increment.
                    484:        mov     %ecx, %eax              / Save di
                    485:        stosl
                    486:        mov     %esi, %eax              / Save si
                    487:        stosl
                    488:        mov     %ebx, %eax              / Save bx
                    489:        stosl
                    490:        mov     %ebp, %eax              / Save bp
                    491:        stosl
                    492:        mov     %esp, %eax              / Save sp
                    493:        stosl
                    494:        mov     (%esp), %eax            / Save ra as pc
                    495:        stosl
                    496:        pushfl                          / Save fw
                    497:        pop     %eax
                    498:        stosl
                    499:        xorl    %eax, %eax
                    500:        movw    %fs, %ax                / save space pointer
                    501:        stosl
                    502:        mov     %ecx, %edi              / Put di back,
                    503:        sub     %eax, %eax              / indicate a state save and
                    504:        ret                             / return to caller.
                    505: 
                    506: ///////
                    507: 
                    508: / Restore the environment of a process.
                    509: / envrest(p)
                    510: / MENV *p;
                    511: 
                    512: ///////
                    513: 
                    514: envrest:
                    515:        cli
                    516:        cld
                    517:        mov     4(%esp),%esi            / Pointer to context
                    518:        lodsl                           / Restore di
                    519:        mov     %eax, %edi
                    520:        lodsl                           / Restore si
                    521:        mov     %eax, %ecx              / Save for later
                    522:        lodsl                           / Restore bx
                    523:        mov     %eax, %ebx
                    524:        lodsl                           / Restore bp
                    525:        mov     %eax, %ebp
                    526:        lodsl                           / Restore sp
                    527:        mov     %eax, %esp
                    528:        push    %cs                     / Push current CS
                    529:        lodsl                           / Restore pc
                    530:        push    %eax
                    531:        lodsl                           / Restore flags
                    532:        mov     %eax, 8(%esp)           / Stack now in form PSW,CS,IP.
                    533:        lodsl
                    534:        movw    %ax, %fs                / Restore space
                    535:        mov     %ecx, %esi              / Restore si
                    536:        mov     $1,%eax                 / We are restoring
                    537:        iret                            / Return through PSW,CS,IP.
                    538: 
                    539: ///////
                    540: 
                    541: / Restore the context of a process.
                    542: / Called with interrupts disabled from dispatch.
                    543: / conrest(u, o)
                    544: / saddr_t u;
                    545: 
                    546: ///////
                    547: 
                    548: conrest:
                    549:        mov     8(%esp), %esi           / Fetch syscon offset
                    550: 
                    551:        cli                             / Interrupts on hold
                    552:        cld
                    553: 
                    554:        / Map new u area into linear space and update paging hardware
                    555: 
                    556:        mov     4(%esp),%eax            / Fetch new u area saddr_t
                    557:        orb     $SEG_SRW,%al
                    558:        mov     %eax,[PTABLE1_V<<BPCSHIFT]+UADDR
                    559: 
                    560:        lcall   $SEG_MMUUPD,$0  / strobe CR3
                    561: 
                    562:        / Restore context
                    563: 
                    564:        lodsl                           / Restore di
                    565:        mov     %eax,%edi
                    566:        lodsl                           / Restore si
                    567:        mov     %eax,%ecx               / Save for later
                    568:        lodsl                           / Restore bx
                    569:        mov     %eax,%ebx
                    570:        lodsl                           / Restore bp
                    571:        mov     %eax,%ebp
                    572:        lodsl                           / Restore sp
                    573:        mov     %eax,%esp
                    574:        push    %cs                     / Push current CS
                    575:        lodsl                           / Restore pc
                    576:        push    %eax
                    577: 
                    578:        lodsl                           / Restore flags
                    579:        mov     %eax,8(%esp)            / Stack now in form PSW,CS,IP.
                    580: 
                    581:        lodsl
                    582:        movw    %ax, %fs                / Restore space
                    583: 
                    584:        mov     %ecx,%esi               / Restore si
                    585:        mov     $1,%eax                 / We are restoring
                    586:        iret                            / Return through PSW,CS,IP.
                    587: 
                    588: / Save useful registers.
                    589: 
                    590: / msysgen(p)
                    591: / MGEN *p;
                    592: 
                    593: msysgen:
                    594:        ret                             / Nothing useful to save
                    595: 
                    596: / Disable interrupts.  Previous value is returned.
                    597: 
                    598: sphi:
                    599:        pushf                           / Save flags
                    600:        pop     %eax                    / Return current value
                    601:        cli                             / Disable interrupts
                    602:        ret                             / And return
                    603: 
                    604: / Enable interrupts.  Previous value is returned.
                    605: 
                    606: splo:
                    607:        pushf
                    608:        pop     %eax
                    609:        sti
                    610:        ret
                    611: 
                    612: / Change interrupt flag, with no return value. Since we want to test bit 10
                    613: / of the flags word, we test bit 2 of the second byte with a byte test.
                    614: / (An earlier version of this routine used IRET, which is a bad idea beacuse
                    615: / it is a) very slow, and b) dangerous).
                    616: 
                    617: spl:
                    618:                pushf                           / Transfer previous flags to
                    619:                pop     %eax                    / %eax by way of the stack
                    620:                testb   $0x2,5(%esp)            / Test argument interrupt flag
                    621:                je      ?cleari                 / Branch if flag was clear
                    622:                sti
                    623:                ret
                    624: ?cleari:
                    625:                cli
                    626:                ret
                    627: 
                    628: ///////
                    629: 
                    630: / Idle routine.
                    631: / Enable interupts, and wait for something to
                    632: / happen. Does not do anything to the 8259, bacause
                    633: / this will be set up correctly.
                    634: 
                    635: ///////
                    636:        .globl  idle
                    637: idle:
                    638:        sti                             / Interupts on.
                    639: __idle__:
                    640:        jmp     __idle__                / Wait for an interrupt
                    641:        ret                             / and return.
                    642: 
                    643: ///////
                    644: 
                    645: / The world is indeed grim.
                    646: / Hang. Keep the interrupts on so that the
                    647: / keyboard can get int.
                    648: 
                    649: ///////
                    650: 
                    651: halt:  sti                             / Be safe,
                    652: __halt__
                    653:        jmp     __halt__                / And hang.
                    654: 
                    655: ///////
                    656: 
                    657: / Basic port level I/O.
                    658: 
                    659: / Byte I/O (8 bits)
                    660: / int  inb(port);
                    661: / int  outb(port, data);
                    662: 
                    663: / Word I/O (16 bits)
                    664: / int  inw(port);
                    665: / int  outw(port, data);
                    666: 
                    667: / Long I/O (32 bits)
                    668: / int  inl(port);
                    669: / int  outl(port, data);
                    670: 
                    671: ///////
                    672: 
                    673: inb:   mov     4(%esp),%edx
                    674:        sub     %eax,%eax
                    675:        inb     (%dx)
                    676:        ret
                    677: 
                    678: outb:  movl    4(%esp),%edx
                    679:        movl    8(%esp),%eax
                    680:        outb    (%dx)
                    681:        ret
                    682: 
                    683: inw:   mov     4(%esp),%edx
                    684:        sub     %eax,%eax
                    685:        inw     (%dx)
                    686:        ret
                    687: 
                    688: outw:  movl    4(%esp),%edx
                    689:        movl    8(%esp),%eax
                    690:        outw    (%dx)
                    691:        ret
                    692: 
                    693: inl:   mov     4(%esp),%edx
                    694:        sub     %eax,%eax
                    695:        inl     (%dx)
                    696:        ret
                    697: 
                    698: outl:  movl    4(%esp),%edx
                    699:        movl    8(%esp),%eax
                    700:        outl    (%dx)
                    701:        ret
                    702: 
                    703: ///////
                    704: 
                    705: / AT Hard Disk Assembler Support
                    706: 
                    707: / atsend( va ) - send 512 bytes from virtual address to hard disk
                    708: / atrecv( va ) - receive 512 bytes from hard disk into virtual address
                    709: / DRQ is not checked.  DRQ must be true before atsend/atrecv are called.
                    710: 
                    711: / va is a system global address
                    712: ///////
                    713: 
                    714:        .globl  atsend
                    715: 
                    716: va             =       8               / va offset from %ebp
                    717: work0          =       -4              / work0 offset from %ebp
                    718: atsend:
                    719:        enter   $0,$4   / reserve 4 bytes (1 int) of local storage
                    720:        push    %esi
                    721:        call    workAlloc               / get a temp virt page
                    722:        movl    %eax, work0(%ebp)       / this is "work0" - a click number
                    723: 
                    724:        cld
                    725:        mov     va(%ebp), %eax          / fetch argument va
                    726:        shr     $BPCSHIFT,%eax          / get page table index from va
                    727:        mov     sysmem,%edx
                    728:        leal    (%edx,%eax,4),%esi      / base = sysmem.u.pbase + btocrd(va)
                    729: 
                    730: / Since the requested transfer may span a click boundary, have two clicks
                    731: / ready in the page table - the one containing the virtual address of the
                    732: / start of the user area, and the click which follows in virtual memory.
                    733: 
                    734:        lodsl                           / ptable1_V[WORK0] = *base++ | SEG_SRW
                    735:        or      $SEG_SRW,%eax
                    736:        movl    work0(%ebp), %edx       / work0
                    737:        movl    %eax,[PTABLE1_V<<BPCSHIFT](%edx,4)
                    738: 
                    739:        lodsl                           / ptable1_V[WORK1] = *base++ | SEG_SRW
                    740:        or      $SEG_SRW,%eax
                    741:        inc     %edx                    / work1
                    742:        movl    %eax,[PTABLE1_V<<BPCSHIFT](%edx,4)
                    743: 
                    744: / Now that page boundaries are set, work on the offsets.
                    745: 
                    746:        mov     va(%ebp), %esi          / va = ctob(WORK0) + (va & (NBPC-1))
                    747:        and     $NBPC-1,%esi            / get click offset part of va
                    748:        movl    work0(%ebp), %edx       / work0
                    749:        shl     $BPCSHIFT,%edx          / ctob(work0)
                    750:        add     %edx,%esi
                    751: 
                    752:        mov     $256, %ecx              / copy one disk block
                    753:        mov     $0x1F0, %edx
                    754: 
                    755: / Do the block transfer.
                    756: 
                    757:        rep
                    758:        outsw
                    759: 
                    760:        push    work0(%ebp)             / workFree(work0)
                    761:        call    workFree
                    762:        pop     %edx
                    763:        pop     %esi
                    764:        leave
                    765:        ret
                    766: 
                    767:        .globl  atrecv
                    768: atrecv:
                    769:        enter   $0,$4   / reserve 4 bytes (1 int) of local storage
                    770:        push    %esi
                    771:        call    workAlloc       / get a temp virt page
                    772:        movl    %eax, work0(%ebp)       / this is "work0" - a click number
                    773: 
                    774:        cld
                    775:        mov     va(%ebp), %eax
                    776:        shr     $BPCSHIFT,%eax
                    777:        mov     sysmem,%edx
                    778:        leal    (%edx,%eax,4),%esi      / base = sysmem.u.pbase + btocrd(va)
                    779: 
                    780:        lodsl                           / ptable1_V[WORK1] = *base++ | SEG_SRW
                    781:        or      $SEG_SRW,%eax
                    782:        movl    work0(%ebp), %edx       / work0
                    783:        movl    %eax,[PTABLE1_V<<BPCSHIFT](%edx,4)
                    784: 
                    785:        lodsl                           / ptable1_V[WORK1] = *base++ | SEG_SRW
                    786:        or      $SEG_SRW,%eax
                    787:        inc     %edx                    / work1
                    788:        movl    %eax,[PTABLE1_V<<BPCSHIFT](%edx,4)
                    789: 
                    790:        mov     va(%ebp), %esi          / va = ctob(WORK0) + (va & (NBPC-1))
                    791:        and     $NBPC-1,%esi
                    792:        movl    work0(%ebp), %edx       / work0
                    793:        shl     $BPCSHIFT,%edx          / ctob(work0)
                    794:        add     %edx,%esi
                    795: 
                    796:        mov     $256, %ecx              / copy one disk block
                    797:        mov     $0x1F0, %edx
                    798: 
                    799:        xchg    %esi,%edi
                    800:        rep                             / Value of the ECX register is not
                    801:        insw
                    802:        xchg    %esi,%edi               
                    803: 
                    804:        push    work0(%ebp)             / workFree(work0)
                    805:        call    workFree
                    806:        pop     %edx
                    807:        pop     %esi
                    808:        leave
                    809:        ret
                    810: 
                    811: ///////
                    812: 
                    813: / This dummy routine is put in vector
                    814: / table slots that are unused. All it does is
                    815: / return to the caller.
                    816: 
                    817: ///////
                    818: 
                    819: vret:  ret
                    820: 
                    821: / mmuupd() uses a call gate.
                    822: mmuupd:
                    823:        pushf
                    824:        cli
                    825:        lcall   $SEG_MMUUPD,$0  / gates to mmuupdfR0
                    826:        popf
                    827:        ret
                    828: 
                    829: / Ring 0 far mmu update.  Called via a gate.  Uses %eax.
                    830: / Want interrupts off when we arrive since the interrupt gates
                    831: / lead into Ring 1.
                    832: mmuupdfR0:
                    833:        mov     $PTABLE0_P<<BPCSHIFT,%eax
                    834:        mov     %eax,%cr3
                    835:        lret
                    836: 
                    837: / Ring 0 near mmu update.  Called from ring 0 startup.  Uses %eax.
                    838: mmuupdnR0:
                    839:        mov     $PTABLE0_P<<BPCSHIFT,%eax
                    840:        mov     %eax,%cr3
                    841:        ret
                    842: 
                    843: ///////
                    844: / Get cs selector - return 0 if in kernel, CS if not in kernel.
                    845: / This version is for resident drivers.
                    846: / There is a different version (cs_self.s) for loadable drivers.
                    847: / int  cs_sel();
                    848: ///////
                    849: 
                    850: cs_sel:
                    851:        sub     %eax, %eax
                    852:        ret
                    853: 
                    854: /      load the 'alternate address space register' (fs)
                    855: /      with the segment reference passed as an argument. 
                    856: 
                    857: /      The value returned is the old value of the 'fs' register
                    858: 
                    859: setspace:
                    860:        xorl    %eax, %eax
                    861:        movw    %fs, %ax
                    862:        movw    4(%esp), %fs
                    863:        ret
                    864: 
                    865: /////////////////////////
                    866: /
                    867: / From __xtrap_on__ to __xtrap_off__, GP fault and page fault will not
                    868: / cause panic.  Normally, these two traps coming from kernel text result
                    869: / in panic.
                    870: /
                    871: /////////////////////////
                    872:                .globl  __xtrap_on__
                    873:                .globl  __xtrap_break__
                    874:                .globl  __xtrap_off__
                    875: __xtrap_on__:
                    876: 
                    877: ///////
                    878: 
                    879: start_copy     .macro
                    880:                movl    %esp, %edx              / Frame pointer for copy code
                    881:                .endm
                    882: 
                    883: end_copy       .macro
                    884:                ret
                    885:                .endm
                    886: 
                    887: copy_frame     .define %edx
                    888: 
                    889: ///////
                    890: / Fetch a byte from the user's data space.
                    891: / getubd(u)
                    892: / char *u;
                    893: ///////
                    894: 
                    895: getubd:
                    896:                start_copy
                    897:                movl    %ss:4(copy_frame), %ecx
                    898:                movzxb  %fs:(%ecx), %eax
                    899:                end_copy
                    900: 
                    901: / Fetch a short from the user's data space.
                    902: /      Coherent 386 fetches a 16 bit short
                    903: / getusd(u)
                    904: / char *u;
                    905: ///////
                    906: 
                    907: getusd:
                    908:                start_copy
                    909:                movl    %ss:4(copy_frame), %ecx
                    910:                movzxw  %fs:(%ecx), %eax
                    911:                end_copy
                    912: 
                    913: ///////
                    914: / Fetch a word from the user's data space.
                    915: /      Coherent 386 fetches a 32 bit word
                    916: / getuwd(u)
                    917: / char *u;
                    918: ///////
                    919: 
                    920: getuwd:
                    921: getupd:
                    922:                start_copy
                    923:                movl    %ss:4(copy_frame), %ecx
                    924:                movl    %fs:(%ecx), %eax
                    925:                end_copy
                    926: 
                    927: ///////
                    928: / Store a byte into the user's data space.
                    929: / putubd(u, w)
                    930: / char *u;
                    931: / int w;
                    932: ///////
                    933: 
                    934: putubd:        
                    935:                start_copy
                    936:                movl    %ss:4(copy_frame), %ecx
                    937:                movb    %ss:8(copy_frame), %al
                    938:                movb    %al, %fs:(%ecx)
                    939:                end_copy
                    940: 
                    941: ///////
                    942: / Store a short into the user's data space.
                    943: /      Coherent 386 stores a 16 bit short
                    944: / putusd(u, w)
                    945: / char *u;
                    946: / int w;
                    947: ///////
                    948: 
                    949: putusd:
                    950:                start_copy
                    951:                movl    %ss:4(copy_frame), %ecx
                    952:                movw    %ss:8(copy_frame), %ax
                    953:                movw    %ax, %fs:(%ecx)
                    954:                end_copy
                    955: 
                    956: ///////
                    957: / Store a word into the user's data space.
                    958: /      Coherent 386 stores a 32 bit word
                    959: / putuwd(u, w)
                    960: / char *u;
                    961: / int w;
                    962: ///////
                    963: 
                    964: putuwi:
                    965: putuwd:
                    966:                start_copy
                    967:                movl    %ss:4(copy_frame), %ecx
                    968:                movl    %ss:8(copy_frame), %eax
                    969:                movl    %eax, %fs:(%ecx)
                    970:                end_copy
                    971: 
                    972: ///////
                    973: / Perform a block-clear of user-space memory
                    974: / size_t umemclear (caddr_t * dest, size_t size)
                    975: //////
                    976:                .globl  umemclear
                    977: umemclear:
                    978:                start_copy
                    979: 
                    980:                push    %ds                     / Preserve %ds
                    981:                push    %es                     / Preserve %es (?)
                    982:                pushl   %esi                    / Preserve %esi
                    983:                pushl   %edi                    / Preserve %esi
                    984: 
                    985:                movw    %fs, %ax
                    986:                movw    %ax, %es                / Dest segment
                    987: 
                    988:                movl    %ss:4(copy_frame), %edi / Dest
                    989: 
                    990:                movl    %ss:8(copy_frame), %ecx / Length
                    991:                sarl    $2, %ecx                / in longwords.
                    992: 
                    993:                xorl    %eax, %eax              / Zero-fill target
                    994:                rep stosl                       / If %ecx > 0, clear longwords
                    995: 
                    996:                movl    %ss:8(copy_frame), %ecx / Length
                    997:                andl    $3, %ecx                / residual byte count
                    998:                rep stosb                       / If %ecx > 0, clear bytes
                    999: 
                   1000:                movl    %ss:8(copy_frame), %eax / Return value
                   1001: 
                   1002:                popl    %edi                    / Restore registers
                   1003:                popl    %esi
                   1004:                pop     %es
                   1005:                pop     %ds
                   1006:                end_copy
                   1007: 
                   1008: ////////
                   1009: / Block transfer "n" bytes from location
                   1010: / "k" in the system map to location "u" in the
                   1011: / user's data space. Return the number of bytes
                   1012: / transferred.
                   1013: / kucopy(k, u, n)
                   1014: / char *k;
                   1015: / char *u;
                   1016: / int n;
                   1017: ///////
                   1018: 
                   1019: kucopy:
                   1020:                start_copy
                   1021: 
                   1022:                push    %ds                     / Preserve %ds
                   1023:                push    %es                     / Preserve %es (?)
                   1024:                pushl   %esi                    / Preserve %esi
                   1025:                pushl   %edi                    / Preserve %esi
                   1026: 
                   1027:                movw    %fs, %ax
                   1028:                movw    %ax, %es                / Dest segment
                   1029: 
                   1030:                movl    %ss:4(copy_frame), %esi / Source
                   1031:                movl    %ss:8(copy_frame), %edi / Dest
                   1032: 
                   1033:                movl    %ss:12(copy_frame), %eax / Return value
                   1034:                movl    %eax, %ecx              / Length
                   1035:                sarl    $2, %ecx                / in longwords.
                   1036:                rep movsl                       / If %ecx > 0, move longwords
                   1037: 
                   1038:                movl    %eax, %ecx              / Length
                   1039:                andl    $3, %ecx                / residual byte count
                   1040:                rep movsb                       / If %ecx > 0, move bytes
                   1041: 
                   1042:                popl    %edi                    / Restore registers
                   1043:                popl    %esi
                   1044:                pop     %es
                   1045:                pop     %ds
                   1046:                end_copy
                   1047: 
                   1048: 
                   1049: ///////
                   1050: / Block copy "n" bytes from location "u" in
                   1051: / the user data space to location "k" in the system
                   1052: / data space. Return the actual number of bytes
                   1053: / moved.
                   1054: / ukcopy(u, k, n)
                   1055: / char *u;
                   1056: / char *k;
                   1057: / int n;
                   1058: ///////
                   1059: 
                   1060: ukcopy:
                   1061:                start_copy
                   1062: 
                   1063:                push    %ds                     / Preserve %ds
                   1064:                push    %es                     / Preserve %es (assume == %ds)
                   1065:                pushl   %esi                    / Preserve %si
                   1066:                pushl   %edi                    / Preserve %di
                   1067: 
                   1068:                movw    %fs, %ax
                   1069:                movw    %ax, %ds                / Source segment
                   1070: 
                   1071:                mov     %ss:4(copy_frame), %esi / Source
                   1072:                mov     %ss:8(copy_frame), %edi / Dest
                   1073: 
                   1074:                movl    %ss:12(copy_frame), %eax / Return value
                   1075:                movl    %eax, %ecx              / Length
                   1076:                sarl    $2, %ecx                / in longwords
                   1077:                rep movsl                       / If %ecx > 0, move longwords
                   1078: 
                   1079:                movl    %eax, %ecx              / Length
                   1080:                andl    $3, %ecx                / residual byte count
                   1081:                rep movsb                       / if %ecx > 0, move bytes
                   1082: 
                   1083:                popl    %edi                    / Restore registers
                   1084:                popl    %esi
                   1085:                pop     %es
                   1086:                pop     %ds
                   1087:                end_copy                        / Return
                   1088: 
                   1089: ////////
                   1090: / Block copy "n" bytes from far location "src" in
                   1091: / an arbitrary (but valid) to location "dst" in 
                   1092: / data space. Return the actual number of bytes
                   1093: / moved.
                   1094: /
                   1095: / ffcopy(src, dst, n)
                   1096: / char far *src;
                   1097: / char far *dst;
                   1098: / int n;
                   1099: ////////
                   1100:                .globl  ffcopy
                   1101: ffcopy:
                   1102:                start_copy
                   1103: 
                   1104:                push    %ds                     / Preserve %ds
                   1105:                push    %es                     / Preserve %es
                   1106:                pushl   %esi                    / Preserve %esi
                   1107:                pushl   %edi                    / Preserve %edi
                   1108: 
                   1109:                les     %ss:12(copy_frame), %edi / Dest segment, length
                   1110:                lds     %ss:4(copy_frame), %esi / Source segment, length
                   1111: 
                   1112:                movl    %ss:20(copy_frame), %eax / Return value
                   1113:                movl    %eax, %ecx              / Length
                   1114:                sarl    $2, %ecx                / in longwords
                   1115:                rep movsl                       / if %ecx > 0, move longwords
                   1116: 
                   1117:                movl    %eax, %ecx              / Length
                   1118:                andl    $3, %ecx                / residual byte count
                   1119:                rep movsb                       / if %ecx > 0, move bytes
                   1120: 
                   1121:                popl    %edi
                   1122:                popl    %esi
                   1123:                pop     %es
                   1124:                pop     %ds
                   1125:                end_copy                        / Return
                   1126: 
                   1127: ////////
                   1128: / Read a byte from a selector and offset.
                   1129: /
                   1130: / ffbyte(off, sel)
                   1131: / unsigned long sel;
                   1132: / unsigned long off;
                   1133: ////////
                   1134:                .globl  ffbyte
                   1135: ffbyte:
                   1136:                start_copy
                   1137:                lgs     %ss:4(copy_frame), %ecx / Source seg:offset
                   1138:                movzxb  %gs:(%ecx), %eax        / Move with zero-fill
                   1139:                end_copy
                   1140: 
                   1141: ////////
                   1142: / Read a (short) word from a selector and offset.
                   1143: /
                   1144: / ffword(off, sel)
                   1145: / unsigned long sel;
                   1146: / unsigned long off;
                   1147: ////////
                   1148:                .globl  ffword
                   1149: ffword:
                   1150:                start_copy
                   1151:                lgs     %ss:4(copy_frame), %ecx / Source seg:offset
                   1152:                movzxw  %gs:(%ecx), %eax        / Move with zero-fill
                   1153:                end_copy
                   1154: 
                   1155: ////////
                   1156: / write a byte using a selector and offset.
                   1157: /
                   1158: / sfbyte(off, sel, byte)
                   1159: / unsigned long sel;
                   1160: / unsigned long off;
                   1161: / int byte;
                   1162: ////////
                   1163:                .globl  sfbyte
                   1164: sfbyte:
                   1165:                start_copy
                   1166:                lgs     %ss:4(copy_frame), %ecx / Dest seg:offset
                   1167:                movb    %ss:12(copy_frame), %al
                   1168:                movb    %al, %gs:(%ecx)
                   1169:                end_copy
                   1170: 
                   1171: ////////
                   1172: / write a (short) word using a selector and offset.
                   1173: /
                   1174: / sfword(off, sel, word)
                   1175: / unsigned long sel;
                   1176: / unsigned long off;
                   1177: / int word;
                   1178: ////////
                   1179:                .globl  sfword
                   1180: sfword:
                   1181:                start_copy
                   1182:                lgs     %ss:4(copy_frame), %ecx / Dest seg:offset
                   1183:                movw    %ss:12(copy_frame), %ax
                   1184:                movw    %ax, %gs:(%ecx)
                   1185:                end_copy
                   1186: 
                   1187: ///////
                   1188: / The n-element copy routines jump here with the stack untouched if they
                   1189: / detect a bounds error or page fault on a user address. The only routines
                   1190: / above that use the stack at all do so with a standard format, so we detect
                   1191: / what is on the stack and restore appropriately.
                   1192: / [ For simplicity, just assume that the pushed values will either all be
                   1193: /   there or not be there at all, which is a very good assumption. ]
                   1194: ///////
                   1195: 
                   1196: __xtrap_break__:
                   1197:                subl    %eax, %eax              / Return 0 to indicate error
                   1198:                                                / condition.
                   1199:                cmpl    %esp, %edx              / Anything on stack?
                   1200:                je      ?no_stack
                   1201: 
                   1202:                popl    %edi                    / Restore registers
                   1203:                popl    %esi
                   1204:                pop     %es
                   1205:                pop     %ds
                   1206: ?no_stack:
                   1207:                end_copy                        / Return
                   1208: 
                   1209: __xtrap_off__:                         / See __xtrap_on__ above.
                   1210: 
                   1211: /      seg2io(long nbytes, vaddr_t p, long port)
                   1212: 
                   1213: /      nbytes must be a short word multiple
                   1214: 
                   1215: seg2io:
                   1216:        movl    %esp,%edx
                   1217:        push    %esi
                   1218: 
                   1219:        mov     4(%edx),%ecx
                   1220:        mov     8(%edx),%esi
                   1221:        mov     12(%edx),%edx           / mov edx,2(dx)
                   1222:        sar     $1,%ecx                 / char to short
                   1223: 
                   1224:        cld
                   1225:        rep
                   1226:        outsw
                   1227: 
                   1228:        pop     %esi
                   1229:        ret
                   1230: 
                   1231: 
                   1232: 
                   1233: /      io2seg(long nbytes, vaddr_t p, long port)
                   1234: 
                   1235: /      nbytes must be a short word multiple
                   1236: 
                   1237: io2seg:
                   1238:        mov     %esp,%edx
                   1239:        push    %edi
                   1240: 
                   1241:        mov     4(%edx),%ecx
                   1242:        mov     8(%edx),%edi
                   1243:        mov     12(%edx),%edx           / mov edx,2(dx)
                   1244:        sar     $1,%ecx                 / char to short
                   1245: 
                   1246:        cld
                   1247:        rep                             / Value of the ECX register is not
                   1248:        insw
                   1249: 
                   1250:        pop     %edi
                   1251:        ret
                   1252: 
                   1253: 
                   1254: ///////
                   1255: /
                   1256: / Profile scaling - special multiply routine is used for speed.
                   1257: /
                   1258: / pscale(a,b) is product a*b shifted right 16 bits
                   1259: /
                   1260: ///////
                   1261: 
                   1262:        .globl  pscale
                   1263: pscale:
                   1264:        mov     4(%esp),%eax    / fetch first argument
                   1265:        mull    8(%esp)         / unsigned multiply by second argument
                   1266:        shrd    $16,%edx,%eax   / shift 64-bit product right 16 bits
                   1267:        ret
                   1268: 
                   1269: ///////
                   1270: 
                   1271: / Trap an interrupt linkage.
                   1272: / Each of the machine traps has a special little
                   1273: / linkage, that sets up the type code and sends
                   1274: / control off to the common trap processor. Device
                   1275: / interrupts, other than the clock (IR0), are
                   1276: / done here.
                   1277: 
                   1278: ///////
                   1279: 
                   1280: trap0:
                   1281:        push    $0x00                   / Divide error.
                   1282:        call    tsave
                   1283:        jmp     trap
                   1284: 
                   1285: / The debug vector is tricky.
                   1286: /
                   1287: / If single stepping user code, the vector must point into Ring 1 code
                   1288: / so that a ptraced child can be synchronized with its parent.
                   1289: /      use trap1_usr for this
                   1290: /
                   1291: / If single stepping the kernel, the vector must point into Ring 0 code
                   1292: / so context switches switch out the debug stack frame.
                   1293: /      use trap1_ker for this
                   1294: 
                   1295:        .globl  __debug_usr__
                   1296: trap1_usr:
                   1297:        push    $0x01                   / Single step.
                   1298:        call    tsave
                   1299:        jmp     __debug_usr__
                   1300: 
                   1301:        .globl  __debug_ker__
                   1302: trap1_ker:
                   1303:        push    $0x01                   / Single step.
                   1304:        call    tsave0
                   1305:        jmp     __debug_ker__
                   1306: 
                   1307: trap2:
                   1308:        push    $0x02                   / Non-maskable interrupt.
                   1309:        call    tsave
                   1310:        jmp     trap
                   1311: 
                   1312: trap3:
                   1313:        push    $0x03                   / INT 3 (breakpoint).
                   1314:        call    tsave
                   1315:        jmp     trap
                   1316: 
                   1317: trap4:
                   1318:        push    $0x04                   / Overflow.
                   1319:        call    tsave
                   1320:        jmp     trap
                   1321: 
                   1322: trap5:
                   1323:        push    $0x05                   / Bound check.
                   1324:        call    tsave
                   1325:        jmp     trap
                   1326: 
                   1327: trap6:
                   1328:        push    $0x06                   / Invalid opcode.
                   1329:        call    tsave
                   1330:        jmp     trap
                   1331: 
                   1332: trap7:
                   1333:        push    $0x07                   / Processor Extension not available.
                   1334:        call    tsave
                   1335:        jmp     emtrap
                   1336: 
                   1337: trap8:
                   1338: /      pop     %ss:trapcode            / Get error code from stack [always 0]
                   1339:        add     $4,%esp
                   1340:        push    $0x08                   / Double Exception detected
                   1341:        call    tsave
                   1342:        jmp     trap
                   1343: 
                   1344: trap9:
                   1345:        push    $0x09                   / Processor extension segment overrun
                   1346:        call    tsave
                   1347:        jmp     trap
                   1348: 
                   1349: trap10:
                   1350: /      pop     %ss:trapcode            / Get error code from stack
                   1351:        add     $4,%esp
                   1352:        push    $0x0A                   / Invalid task state segment
                   1353:        call    tsave
                   1354:        jmp     trap
                   1355: 
                   1356: trap11:
                   1357: /      pop     %ss:trapcode            / Get error code from stack
                   1358:        add     $4,%esp
                   1359:        push    $0x0B                   / Segment not present
                   1360:        call    tsave
                   1361:        jmp     trap
                   1362: 
                   1363: trap12:
                   1364: /      pop     %ss:trapcode            / Get error code from stack
                   1365:        add     $4,%esp
                   1366:        push    $0x0C                   / Stack segment overrun or not present
                   1367:        call    tsave
                   1368:        jmp     trap
                   1369: 
                   1370: trap13:
                   1371: /      pop     %ss:trapcode            / Get error code from stack
                   1372: /      add     $4,%esp
                   1373: /      push    $0x0D                   / General protection
                   1374:        call    tsave0
                   1375:        jmp     gpfault
                   1376: 
                   1377: trap14:
                   1378: /      pop     %ss:trapcode            / Get error code from stack
                   1379: /      add     $4,%esp
                   1380: /      push    $0x0E                   / Page Fault
                   1381:        call    tsave
                   1382:        jmp     pagefault
                   1383: 
                   1384: trap16:
                   1385:        push    $0x10                   / Floating point error
                   1386:        call    tsave
                   1387:        jmp     fptrap
                   1388: 
                   1389: syc:
                   1390:        push    $0x22                   / Old format system calls.
                   1391:        call    tsave
                   1392:        jmp     trap
                   1393: 
                   1394:        .set    FAKE_EFL,12
                   1395: syc32:
                   1396:        push    %eax                    / save %eax
                   1397:        pushf                           / modify current flags
                   1398:        pop     %eax
                   1399:        orw     $PSW_VAL,%ax            / set IF=1, IOPL=1 (user) on iret
                   1400:        mov     %eax,FAKE_EFL(%esp)
                   1401:        pop     %eax                    / restore %eax
                   1402:        push    $0x20                   / New format system calls.
                   1403:        call    tsave
                   1404:        jmp     trap
                   1405: 
                   1406: sig32:
                   1407:        push    %eax
                   1408:        pushf
                   1409:        pop     %eax
                   1410:        orw     $PSW_VAL,%ax
                   1411:        mov     %eax,FAKE_EFL(%esp)
                   1412:        pop     %eax
                   1413:        push    $0x20                   / New format signal return.
                   1414:        call    tsave
                   1415:        jmp     msigend
                   1416: 
                   1417: ran:
                   1418:        push    $0x21                   / Random trap.
                   1419:        call    tsave
                   1420:        jmp     trap
                   1421: 
                   1422: dev1:
                   1423:        push    $0x0140                 / Device 1: keyboard
                   1424:        call    tsave
                   1425:        icall   [1<<2]+vecs
                   1426:        jmp     eoi                     / Dismiss interrupt
                   1427: 
                   1428:                                        / Device 2: mapped into device 9
                   1429: dev3:
                   1430:        push    $0x0340                 / Device 3: al1
                   1431:        call    tsave
                   1432:        icall   [3<<2]+vecs
                   1433:        jmp     eoi                     / Dismiss interrupt
                   1434: 
                   1435: dev4:
                   1436:        push    $0x0440                 / Device 4: al0
                   1437:        call    tsave
                   1438:        icall   [4<<2]+vecs
                   1439:        jmp     eoi                     / Dismiss interrupt
                   1440: 
                   1441: dev5:
                   1442:        push    $0x0540                 / Device 5: hard disk
                   1443:        call    tsave
                   1444:        icall   [5<<2]+vecs
                   1445:        jmp     eoi                     / Dismiss interrupt
                   1446: 
                   1447: dev6:
                   1448:        push    $0x0640                 / Device 6: floppy
                   1449:        call    tsave
                   1450:        icall   [6<<2]+vecs
                   1451:        jmp     eoi                     / Dismiss interrupt
                   1452: 
                   1453: dev7:
                   1454:        push    $0x0740                 / Device 7: lp
                   1455:        call    tsave
                   1456:        icall   [7<<2]+vecs
                   1457:        jmp     eoi                     / Dismiss interrupt
                   1458: 
                   1459: dev8:
                   1460:        push    $0x0840                 / Device 8:
                   1461:        call    tsave
                   1462:        icall   [8<<2]+vecs
                   1463:        jmp     eoi2                    / Dismiss interrupt
                   1464: 
                   1465: dev9:
                   1466:        push    $0x0940                 / Device 9:
                   1467:        call    tsave
                   1468:        icall   [9<<2]+vecs
                   1469:        jmp     eoi2                    / Dismiss interrupt
                   1470: 
                   1471: dev10:
                   1472:        push    $0x0A40                 / Device 10:
                   1473:        call    tsave
                   1474:        icall   [10<<2]+vecs
                   1475:        jmp     eoi2                    / Dismiss interrupt
                   1476: 
                   1477: dev11:
                   1478:        push    $0x0B40                 / Device 11:
                   1479:        call    tsave
                   1480:        icall   [11<<2]+vecs
                   1481:        jmp     eoi2                    / Dismiss interrupt
                   1482: 
                   1483: dev12:
                   1484:        push    $0x0C40                 / Device 12:
                   1485:        call    tsave
                   1486:        icall   [12<<2]+vecs
                   1487:        jmp     eoi2                    / Dismiss interrupt
                   1488: 
                   1489:        .align  4
                   1490: dev13:
                   1491:        / Used to be coprocessor exception interrupt
                   1492:        / Coprocessor err had to be cleared by writing a 0 byte to port 0xF0
                   1493:        /
                   1494:        push    $0x0D40                 / Device 13:
                   1495:        call    tsave
                   1496:        icall   [13<<2]+vecs
                   1497:        jmp     eoi2                    / Dismiss interrupt
                   1498: 
                   1499: dev14:
                   1500:        push    $0x0E40                 / Device 14:
                   1501:        call    tsave
                   1502:        icall   [14<<2]+vecs
                   1503:        jmp     eoi2                    / Dismiss interrupt
                   1504: 
                   1505: dev15:
                   1506:        push    $0x0F40                 / Device 15:
                   1507:        call    tsave
                   1508:        icall   [15<<2]+vecs
                   1509:        jmp     eoi2                    / Dismiss interrupt
                   1510: 
                   1511: ///////
                   1512: 
                   1513: / Clock interrupt.
                   1514: 
                   1515: ///////
                   1516: 
                   1517: clk:
                   1518:        push    $0x0040
                   1519:        call    tsave                   / Perform trap save.
                   1520:        mov     X_ERR+12(%esp),%eax     / ECS at tick time
                   1521:        and     $3,%eax                 / This will be R_USR iff user mode
                   1522:        push    %eax
                   1523:        mov     X_ERR+12(%esp),%eax     / EIP at tick time
                   1524:        push    %eax
                   1525:        call    clock                   / clock(eip, umode)
                   1526:        add     $8,%esp                 / pop arguments.
                   1527:        jmp     eoi                     / Dismiss interrupt
                   1528: 
                   1529: ///////
                   1530: 
                   1531: / This co-routine is called to dismiss an interrupt.
                   1532: / The interrupt code is in X_ERR(%esp)
                   1533: 
                   1534: / Control returns to "tsave"
                   1535: 
                   1536: ///////
                   1537: 
                   1538:        .globl  eoi2
                   1539: eoi2:
                   1540:        cli
                   1541:        movb    $0x20,%al       / Send a non specific EOI
                   1542:        outb    $SPIC           / to the slave PIC.
                   1543:        IODELAY
                   1544:        movb    $0x0B,%al       / OCW3 - read isr
                   1545:        outb    $SPIC
                   1546:        IODELAY
                   1547: /      inb     $SPIC           / in-service register to %eax:8..15
                   1548: /      testb   %al,%al
                   1549: /      jnz     eoi2x           / no EOI to master if slave isr nonzero
                   1550: eoi:
                   1551:        cli
                   1552:        movb    $0x20,%al       / Send a non specific EOI
                   1553:        outb    $PIC            / to the master PIC.
                   1554:        IODELAY
                   1555: eoi2x: ret                     / Done.
                   1556: 
                   1557: ///////
                   1558: 
                   1559: / Read the equipment description. Use
                   1560: / the "int 11" interface, so that the IBM
                   1561: / ROM will do all the details.
                   1562: 
                   1563: ///////
                   1564: 
                   1565: int11: mov     %cs:val11,%eax          / Ask the ROM
                   1566:        ret                             / to put stuff in AX
                   1567: 
                   1568: ///////
                   1569: 
                   1570: / Bootstrap.
                   1571: / Called by the keyboard driver on control-alt-del.
                   1572: / Requests the 8042 controller to initiate a processor reset,
                   1573: / which is the only way to terminate protected mode operation.
                   1574: 
                   1575: /      Reference: IBM-AT Technical Reference Manual,
                   1576: /                      Real-time Clock/CMOS RAM [Page 1-45]
                   1577: /                      Keyboard controller [Page 1-40]
                   1578: /                      Test 3, Page 5-68.
                   1579: 
                   1580: ///////
                   1581: boot:
                   1582:        cli                             / Disable interrupts.
                   1583: 
                   1584:        subl    %ecx,%ecx
                   1585: loc12: inb     $KBCTRL                 / Wait for 8042 input buffer to empty.
                   1586:        testb   $2, %al
                   1587:        loopne  loc12
                   1588:        IODELAY
                   1589: 
                   1590:        movb    $0xFE,%al               / Issue a shutdown command
                   1591:        outb    $KBCTRL                 / to the 8042 control port.
                   1592: 
                   1593: loc13: hlt                             / Halt until processor reset occurs.
                   1594:        jmp     loc13
                   1595: 
                   1596:        .globl  putchar
                   1597: 
                   1598: /      Comment in the line below if debugging output is to go to the
                   1599: /      printer
                   1600: 
                   1601: /putchar:
                   1602: 
                   1603:        movb    4(%esp),%al
                   1604:        cmpb    $0xa,%al
                   1605:        jne     loc18
                   1606:        push    $0xd
                   1607:        call    putchar
                   1608:        add     $4,%esp
                   1609: loc18: mov     $LPSTAT,%edx
                   1610:        inb     (%dx)
                   1611:        testb   $IBMNBSY,%al
                   1612:        je      loc18
                   1613: 
                   1614:        mov     $LPCSR,%edx
                   1615:        movb    $SEL+NINIT, %al
                   1616:        outb    (%dx)
                   1617: 
                   1618:        mov     $LPDATA, %edx
                   1619:        movb    4(%esp),%al
                   1620:        outb    (%dx)
                   1621: 
                   1622:        mov     $LPCSR,%edx
                   1623:        movb    $SEL+NINIT+STROBE,%al 
                   1624:        outb    (%dx)
                   1625:        movb    $8, %cl
                   1626: l_1:   decb    %cl
                   1627:        jne     l_1
                   1628:        movb    $SEL+NINIT, %al
                   1629:        outb    (%dx)
                   1630:        ret
                   1631: 
                   1632: / long _canl(l) long l;
                   1633: / This is called by the routines that
                   1634: / transform longs to and from the
                   1635: / canonical formats.
                   1636: 
                   1637: _canl:
                   1638:        mov     4(%esp),%eax
                   1639:        rol     $16,%eax
                   1640:        ret
                   1641: 
                   1642: regcr2:        mov     %cr2,%eax
                   1643:        ret
                   1644: 
                   1645: regfp: mov     %ebp,%eax
                   1646:        ret
                   1647: 
                   1648: /      .align  4               / CPU resets if val11 isn't aligned.
                   1649:        .byte   0
                   1650: val11: .long   0               / Value obtained from int11 [in code].
                   1651: 
                   1652: aicodep:
                   1653:        sub     %ebx,%ebx
                   1654:        sub     $aicodep,%ebx
                   1655:        lea     fn(%ebx),%eax
                   1656:        mov     %eax,argl(%ebx)
                   1657:        lea     a1(%ebx),%eax
                   1658:        mov     %eax,argl+4(%ebx)
                   1659:        lea     argl+8(%ebx),%eax       / No environment
                   1660:        push    %eax
                   1661:        lea     argl(%ebx),%eax         / Argument list
                   1662:        push    %eax
                   1663:        lea     fn(%ebx),%eax           / File name
                   1664:        push    %eax
                   1665:        sub     $4,%esp                 / Dummy word for exec
                   1666:        movl    $59, %eax
                   1667:        lcall   $0x7,$0
                   1668:        jmp     .                       / Instant page fault if exec failed!
                   1669:        .alignoff
                   1670:        .align  2
                   1671: argl:  .long   0                       / argv[0] = "/etc/init";
                   1672:        .long   0                       / argv[1] = "";
                   1673:        .long   0                       / argv[2] = NULL;
                   1674: 
                   1675: fn:    .byte   "/etc/init",0
                   1676: a1:    .byte   0
                   1677: sb:
                   1678:        .set    aicodes, .-aicodep
                   1679: 
                   1680: ///////
                   1681: 
                   1682: / Task State Segment - Coherent runs as a single protected mode 386 task.
                   1683: 
                   1684: ///////
                   1685:        .alignon
                   1686:        .align  4
                   1687:        .globl  tss_sp0         / Use run-time fixup for tss_sp0
                   1688:        .globl  tssIoMap
                   1689:        .globl  tssIoEnd
                   1690: tss:                           / Task State Segment.
                   1691: tss_lnk:.long  0               /  0: Back link selector to TSS.
                   1692: tss_sp0:.long  ESP0_START      /  4: SP for CPL 0.
                   1693: tss_ss0:.long  SEG_RNG0_STK    /  8: SS for CPL 0.
                   1694: tss_sp1:.long  ESP1_START      /  C: SP for CPL 1.
                   1695: tss_ss1:.long  SEG_RNG1_STK    / 10: SS for CPL 1.
                   1696: tss_sp2:.long  u+NBPC          / 14: SP for CPL 2.
                   1697: tss_ss2:.long  SEG_386_KD      / 18: SS for CPL 2.
                   1698: tss_cr3:.long  PTABLE0_P<<BPCSHIFT / 1C: CR3 (PDBR)
                   1699: tss_ip:        .long   0               / 20: EIP (Entry point).
                   1700: tss_psw:.long  0               / 24: Flag word.
                   1701: tss_ax:        .long   0               / 28: Register AX.
                   1702: tss_cx:        .long   0               / 2C: Register CX.
                   1703: tss_dx:        .long   0               / 30: Register DX.
                   1704: tss_bx:        .long   0               / 34: Register BX.
                   1705: tss_bp:        .long   0               / 38: Register BP.
                   1706: tss_sp:        .long   0               / 3C: Register SP.
                   1707: tss_si:        .long   0               / 40: Register SI.
                   1708: tss_di:        .long   0               / 44: Register DI.
                   1709: tss_es:        .long   0               / 48: Register ES.
                   1710: tss_cs:        .long   0               / 4C: Register CS.
                   1711: tss_ss:        .long   0               / 50: Register SS.
                   1712: tss_ds:        .long   0               / 54: Register DS.
                   1713: tss_fs:        .long   0               / 58: Register FS.
                   1714: tss_gs:        .long   0               / 5C: Register GS.
                   1715: tss_ldt:.long  SEG_LDT         / 60: Task LDT Selector.
                   1716:        .long   TSS_IOMAP_OFF   / 64: T bit & I/O map base
                   1717: / I/O map is part of tss.
                   1718: / Bitmap up to port address TSS_IOMAP_LEN.
                   1719: / Initialize to all 1's, meaning no I/O allowed.
                   1720: / tss + 0x68 = tssIoMap
                   1721: tssIoMap:
                   1722:        .long   [[TSS_IOMAP_LEN + 31] .div 32] # -1
                   1723: tssIoEnd:
                   1724:        .long   [[0x1000 - TSS_IOMAP_LEN] .div 32] # -1
                   1725:        .long   -1
                   1726: ///////
                   1727: 
                   1728: / Data.
                   1729: 
                   1730: ///////
                   1731:        .data
                   1732: sdata:
                   1733: 
                   1734: vecs:  .long   16 # vret       / Interrupt vector table
                   1735: 
                   1736: trapcode:.long 0
                   1737: 
                   1738:        .text
                   1739: ///////
                   1740: 
                   1741: /       Read a byte from the CMOS.  Takes one argument--the
                   1742: /       CMOS address to read from as an int; returns the
                   1743: /       value read as a char.
                   1744: /
                   1745: /      int read_cmos(int addr);
                   1746: 
                   1747: read_cmos:
                   1748:        push    %esi
                   1749:        push    %edi
                   1750:         movb    12(%esp), %al  / Fetch address from stack.
                   1751:         outb    $CMOSA         / Send address to CMOS.
                   1752:        IODELAY
                   1753:        sub     %eax, %eax      / Zero out everything we don't want.
                   1754:         inb     $CMOSD         / Get Value from CMOS into al.
                   1755:        pop     %edi
                   1756:        pop     %esi
                   1757:         ret                     / Return from read_cmos().
                   1758: 
                   1759: /       Write a byte to the CMOS.
                   1760: /
                   1761: /      void write_cmos(int addr, int data)
                   1762: 
                   1763: write_cmos:
                   1764:        push    %esi
                   1765:        push    %edi
                   1766:         movb    12(%esp), %al  / Fetch address from stack.
                   1767:         outb    $CMOSA         / Send address to CMOS.
                   1768:        IODELAY
                   1769:         movb    16(%esp), %al  / Fetch address from stack.
                   1770:         outb     $CMOSD                / Get Value from CMOS into al.
                   1771:        IODELAY
                   1772:        pop     %edi
                   1773:        pop     %esi
                   1774:         ret                     / Return from read_cmos().
                   1775: 
                   1776: / Read timer channel 0 into int value.  
                   1777: / Clock counts down from 11932 to 0 with each clock tick.
                   1778:        .globl  read_t0
                   1779: read_t0:
                   1780:        pushfl
                   1781:        cli
                   1782:        xorl    %eax,%eax       / Counter latch timer 0 and clear return val
                   1783:        outb    $PIT+3
                   1784:        IODELAY
                   1785:        inb     $PIT            / low byte of counter latch
                   1786:        IODELAY
                   1787:        movb    %al,%ah
                   1788:        inb     $PIT            / high byte of counter latch
                   1789:        IODELAY
                   1790:        xchgb   %al,%ah
                   1791:        popfl
                   1792:        ret
                   1793: 
                   1794: / return current contents of psw
                   1795:        .globl  read_psw
                   1796: read_psw:
                   1797:        pushfl
                   1798:        popl    %eax
                   1799:        ret
                   1800: 
                   1801: 
                   1802: / return current contents of cr0
                   1803:        .globl  read_cr0
                   1804: read_cr0:
                   1805:        movl    %cr0,%eax
                   1806:        ret
                   1807: 
                   1808: / return current contents of cr2
                   1809:        .globl  read_cr2
                   1810: read_cr2:
                   1811:        movl    %cr2,%eax
                   1812:        ret
                   1813: 
                   1814: / return current contents of cr3
                   1815:        .globl  read_cr3
                   1816: read_cr3:
                   1817:        movl    %cr3,%eax
                   1818:        ret
                   1819: 
                   1820: /////////
                   1821: /
                   1822: / Debugging support.
                   1823: /
                   1824: /////////
                   1825:        .globl  write_dr0
                   1826:        .globl  write_dr1
                   1827:        .globl  write_dr2
                   1828:        .globl  write_dr3
                   1829:        .globl  write_dr6
                   1830:        .globl  write_dr7
                   1831: 
                   1832:        .globl  read_dr0
                   1833:        .globl  read_dr1
                   1834:        .globl  read_dr2
                   1835:        .globl  read_dr3
                   1836:        .globl  read_dr6
                   1837:        .globl  read_dr7
                   1838: 
                   1839: / write arg to dr0
                   1840: write_dr0:
                   1841:        movl    4(%esp),%eax
                   1842:        movl    %eax,%dr0
                   1843:        ret
                   1844: 
                   1845: / write arg to dr1
                   1846: write_dr1:
                   1847:        movl    4(%esp),%eax
                   1848:        movl    %eax,%dr1
                   1849:        ret
                   1850: 
                   1851: / write arg to dr2
                   1852: write_dr2:
                   1853:        movl    4(%esp),%eax
                   1854:        movl    %eax,%dr2
                   1855:        ret
                   1856: 
                   1857: / write arg to dr3
                   1858: write_dr3:
                   1859:        movl    4(%esp),%eax
                   1860:        movl    %eax,%dr3
                   1861:        ret
                   1862: 
                   1863: / write arg to dr6
                   1864: write_dr6:
                   1865:        movl    4(%esp),%eax
                   1866:        movl    %eax,%dr6
                   1867:        ret
                   1868: 
                   1869: / write arg to dr7
                   1870: write_dr7:
                   1871:        movl    4(%esp),%eax
                   1872:        movl    %eax,%dr7
                   1873:        ret
                   1874: 
                   1875: read_dr0:
                   1876:        movl    %dr0,%eax
                   1877:        ret
                   1878: 
                   1879: read_dr1:
                   1880:        movl    %dr1,%eax
                   1881:        ret
                   1882: 
                   1883: read_dr2:
                   1884:        movl    %dr2,%eax
                   1885:        ret
                   1886: 
                   1887: read_dr3:
                   1888:        movl    %dr3,%eax
                   1889:        ret
                   1890: 
                   1891: read_dr6:
                   1892:        movl    %dr6,%eax
                   1893:        ret
                   1894: 
                   1895: read_dr7:
                   1896:        movl    %dr7,%eax
                   1897:        ret
                   1898: 
                   1899: / write to the EM bit of CR0
                   1900: / this routine is a stub for the ring 0 code
                   1901: / argument is 0 or 1
                   1902: /
                   1903: /      void setEm(int bit)
                   1904:        .globl  setEm
                   1905: setEm:
                   1906:        movl    4(%esp),%eax    / fetch argument
                   1907:        pushf
                   1908:        cli
                   1909:        pushl   %eax
                   1910:        lcall   $SEG_SET_EM,$0  / gate to setEmfR0
                   1911:        / setEmfR0 will delete 4 bytes worth of args
                   1912:        popf
                   1913:        ret
                   1914: 
                   1915: / Ring 0 write to CR0 EM bit.  Called via a gate.
                   1916: / Want interrupts off when we arrive since the interrupt gates
                   1917: / lead into Ring 1.
                   1918: setEmfR0:
                   1919:        movb    8(%esp),%cl     / fetch argument
                   1920: 
                   1921:        cmpb    $0,%cl
                   1922:        movl    %cr0,%eax
                   1923:        jz      se00
                   1924:        orb     $4,%al          / set EM bit
                   1925:        andb    $0xDF,%al       / clear NE bit
                   1926:        jmp     se01
                   1927: se00:
                   1928:        andb    $0xFB,%al       / clear EM bit
                   1929:        orb     $0x20,%al       / set NE bit
                   1930: se01:
                   1931:        mov     %eax,%cr0
                   1932:        / make 4-byte arg list disappear
                   1933:        lret    $4
                   1934: 
                   1935: / return nonzero if paging is turned on
                   1936:        .globl  paging
                   1937: paging:
                   1938:        movl    (%esp),%eax             / fetch return address
                   1939:        cmpl    $[SBASE<<BPCSHIFT],%eax / is it >= unsigned FFC0_0000?
                   1940:        jae     pagingMaybe
                   1941:        xorl    %eax,%eax               / if not, no paging
                   1942:        ret
                   1943: pagingMaybe:
                   1944:        movw    %cs,%ax                 / if return addr high, cs is a selector
                   1945:        cmpw    $0x58,%ax               / selectors 58-6F are nonpaging
                   1946:        jb      pagingYes
                   1947:        cmpw    $0x6F,%ax               / selectors 58-6F are nonpaging
                   1948:        ja      pagingYes
                   1949:        xorl    %eax,%eax               / no paging
                   1950:        ret
                   1951: pagingYes:
                   1952:        movl    $1,%eax
                   1953:        ret

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.