Annotation of coherent/b/STREAMS/i386/as.s, revision 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.