123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- #include "amd64.h"
- .code64
- /*
- * Port I/O.
- */
- .global inb
- inb:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- XORL %eax, %eax
- INB %dx
- RET
- .global insb
- insb:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- MOVQ %rsi, %rdi
- MOVL %edx, %ecx
- CLD
- REP; INSB
- RET
- .global ins
- ins:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- XORL %eax, %eax
- INW %dx
- RET
- .global inss
- inss:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- MOVQ %rsi, %rdi
- MOVL %edx, %ecx
- CLD
- REP; INSW
- RET
- .global inl
- inl:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- INL %dx
- RET
- .global insl
- insl:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- MOVQ %rsi, %rdi
- MOVL %edx, %ecx
- CLD
- REP; INSL
- RET
- .global outb
- outb:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- MOVL %esi, %eax
- OUTB %dx
- RET
- .global outsb
- outsb:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- MOVQ %rsi, %rdi
- MOVL %edx, %ecx
- CLD
- REP; OUTSB
- RET
- .global outs
- outs:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- MOVL %esi, %eax
- OUTW %dx
- RET
- .global outss
- outss:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- MOVL %edx, %ecx
- CLD
- REP; OUTSW
- RET
- .global outl
- outl:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- MOVL %esi, %eax
- OUTL %dx
- RET
- .global outsl
- outsl:
- MOVL %edi, %edx /* MOVL port+0(FP), DX */
- MOVQ %rsi, %rdi
- MOVL %edx, %ecx
- CLD
- REP; OUTSL
- RET
- /*
- * Load/store segment descriptor tables:
- * GDT - global descriptor table
- * IDT - interrupt descriptor table
- * TR - task register
- * GDTR and LDTR take an m16:m64 argument,
- * so shuffle the stack arguments to
- * get it in the right format.
- */
- .global gdtget
- gdtget:
- // panic.
- mov 0, %rax
- //sgdt %rdi
- // MOVL GDTR, (RARG) /* Note: 10 bytes returned */
- RET
- // Called with the address of gdt in rdi.
- // Load the gdt, then do a ret which will use the argument on the stack as
- // a segment #. This stuff is just crazy.
- // We have to push %rsi, then 16 bits(really!) of %rdi.
- .global gdtput
- gdtput:
- pushq %rsi
- movq %rdi, %rax
- pushw %ax
- mov %rsp, %rax
- lgdt (%rax)
- popw %ax
- popq %rax
- XORQ %rax, %rax
- MOVW %ax, %ds
- MOVW %ax, %es
- MOVW %ax, %fs
- MOVW %ax, %gs
- MOVW %ax, %ss
- POPQ %rax
- PUSHQ %rdx
- PUSHQ %rax
- lretq
- .global idtput
- idtput:
- // save %rdi, since we are going to modify it.
- pushq %rdi
- // Push the two quads onto the stack,
- // which arranges them in memory.
- pushq %rsi
- shlq $48, %rdi
- pushq %rdi
- movq %rsp, %rax
- addq $6, %rax
- lidt (%rax)
- popq %rdi
- popq %rsi
- popq %rdi
- RET
- .global trput
- trput:
- // panic
- mov 0, %rax
- //ltr %rdi
- RET
- /*
- * Read/write various system registers.
- */
- .global cr0get
- cr0get:
- MOVQ %cr0, %rax
- RET
- .global cr0put
- cr0put:
- MOVQ %rdi, %rax
- MOVQ %rax, %cr0
- RET
- .global cr2get
- cr2get:
- MOVQ %cr2, %rax
- RET
- .global cr3get
- cr3get:
- MOVQ %cr3, %rax
- RET
- .global cr3put
- cr3put:
- MOVQ %rdi, %rax
- MOVQ %rax, %CR3
- RET
- .global cr4get
- cr4get:
- MOVQ %CR4, %rax
- RET
- .global cr4put
- cr4put:
- MOVQ %rdi, %rax
- MOVQ %rax, %CR4
- RET
- .global read_bp
- read_bp:
- movq %rbp, %rax
- ret
- .global rdtsc
- rdtsc:
- RDTSC
- /* u64int rdtsc(void); */
- XCHGL %edx, %eax /* swap lo/hi, zero-extend */
- SHLQ $32, %rax /* hi<<32 */
- ORQ %rdx, %rax /* (hi<<32)|lo */
- RET
- .global rdmsr
- rdmsr:
- PUSHQ %rcx
- PUSHQ %rdx
- MOVL %edi, %ecx
- RDMSR
- /* u64int rdmsr(u32int); */
- XCHGL %edx, %eax /* swap lo/hi, zero-extend */
- SHLQ $32, %rax /* hi<<32 */
- ORQ %rdx, %rax /* (hi<<32)|lo */
- POPQ %rdx
- POPQ %rcx
- RET
- .global wrmsr
- wrmsr:
- PUSHQ %rax // do we need to do this?
- PUSHQ %rcx
- PUSHQ %rdx
- MOVL %edi, %ecx
- MOVL %esi, %eax
- MOVQ %rsi, %rdx
- SHRQ $32, %rdx
- WRMSR
- POPQ %rdx
- POPQ %rcx
- POPQ %rax
- RET
- .global invlpg
- invlpg:
- # MOVQ %rdi, va+0(FP)
- # INVLPG va+0(FP)
- RET
- .global wbinvd
- wbinvd:
- WBINVD
- RET
- /*
- * Serialisation.
- */
- .global lfence
- lfence:
- LFENCE
- RET
- .global mfence
- mfence:
- MFENCE
- RET
- .global sfence
- sfence:
- SFENCE
- RET
- /*
- * x86 convention is to use %rbp as the frame pointer,
- * so we just return that register
- */
- .global stackframe
- stackframe:
- movq %rbp, %rax
- retq
- /*
- * disable interrupts,
- * return old flags for splx()
- */
- .global splhi
- splhi:
- _splhi:
- PUSHFQ
- POPQ %rax
- TESTQ $If, %rax /* If - Interrupt Flag */
- JZ _alreadyhi
- movq 0(%rsp), %rdi
- movq %rdi, %gs:8 /* callerpc to m->splpc */
- _alreadyhi:
- CLI
- RET
- /*
- * enable interrupts,
- * return old flags for splx()
- */
- .global spllo
- spllo:
- _spllo:
- PUSHFQ
- POPQ %rax
- TESTQ $If, %rax /* If - Interrupt Flag */
- JNZ _alreadylo
- MOVQ $0, %gs:8 /* clear m->splpc */
- _alreadylo:
- STI
- RET
- /*
- * undo splhi or spllo,
- * %rdi has flags before splhi or spllo
- */
- .global splx
- splx:
- TESTQ $If, %rdi /* If - Interrupt Flag */
- JNZ _spllo /* If set: enable */
- JMP _splhi /* else: disable */
- .global spldone
- spldone:
- RET
- .global islo
- islo:
- PUSHFQ
- POPQ %rax
- ANDQ $If, %rax /* If - Interrupt Flag */
- RET
- .global infected_with_std
- infected_with_std:
- PUSHFQ
- POPQ %rax
- ANDQ $Df, %rax /* Df - Direction Flag */
- RET
- .global disinfect_std
- disinfect_std:
- CLD
- RET
- /*
- * Synchronisation
- */
- .global ainc
- ainc:
- MOVL $1, %eax
- LOCK; XADDL %eax, (%rdi)
- ADDL $1, %eax /* overflow if -ve or 0 */
- JG _return
- _trap:
- XORQ %rbx, %rbx
- MOVQ (%rbx), %rbx /* over under sideways down */
- _return:
- RET
- .global adec
- adec:
- MOVL $-1, %eax
- LOCK; XADDL %eax, (%rdi)
- SUBL $1, %eax /* underflow if -ve */
- JL _trap
- RET
- /*
- * Semaphores rely on negative values for the counter,
- * and don't have the same overflow/underflow conditions
- * as ainc/adec.
- */
- .global semainc
- semainc:
- MOVL $1, %eax
- LOCK; XADDL %eax, (%rdi)
- ADDL $1, %eax
- RET
- .global semadec
- semadec:
- MOVL $-1, %eax
- LOCK; XADDL %eax, (%rdi)
- SUBL $1, %eax
- RET
- .global tas32
- tas32:
- MOVL $0xdeaddead, %eax
- XCHGL %eax, (%rdi) /* */
- RET
- .global fas64
- fas64:
- MOVQ %rdi, %rax
- //LOCK; XCHGQ %eax, (%rdi) /* */
- RET
- // %rdi:&key, %esi:old, %edx:new
- // int cas32(void* %rdi, uint32_t %esi, uint32_t %edx);
- .global cas32
- cas32:
- movl %esi, %eax
- lock; cmpxchgl %edx, (%rdi)
- MOVL $1, %eax
- JNZ _cas32r0
- _cas32r1:
- RET
- _cas32r0:
- DECL %eax
- RET
- /*
- * Label consists of a stack pointer and a programme counter
- * 0(%rdi) is the SP, 8(%rdi) is the PC
- */
- .global gotolabel
- gotolabel:
- MOVQ %rdi, %rax
- MOVQ 0(%rdi), %rsp
- // Can't kill this quite yet.
- MOVQ (16+5*8)(%rdi), %rBP
- MOVQ 8(%rax), %rax /* put return PC on the stack */
- /* NOTE: replaces previous caller? */
- MOVQ %rax, (%rSP)
- MOVQ $1, %rax /* return 1 */
- RET
- /* save all registers on this stack, the save stack
- * in the label struct.
- */
- .global slim_setlabel
- slim_setlabel:
- // %rax is trashable.
- MOVQ 0(%rSP), %rax /* store return PC */
- MOVQ %rax, 8(%rdi)
- // Can't kill this quite yet.
- MOVQ %rBP, (16+5*8)(%rdi)
- MOVQ %rSP, 0(%rdi) /* store SP */
- MOVL $0, %eax /* return 0 */
- RET
- .global hardhalt
- hardhalt:
- STI
- HLT
- RET
- .global _monitor
- _monitor:
- MOVQ %rdi, %rax /* linear address to monitor */
- XORQ %rcx, %rcx /* no optional extensions yet */
- XORQ %rdx, %rdx /* no optional hints yet */
- .byte 0x0f; .byte 0x01; .byte 0xc8 /* MONITOR */
- RET
- .global _mwait
- _mwait:
- movq %rdi, %rcx /* optional extensions */
- .byte 0x0f; .byte 0x01; .byte 0xc9 /* MWAIT */
- RET
- .global k10mwait
- k10mwait:
- k10mwloop:
- MOVQ %rdi,%rcx
- MOVQ (%rcx), %rax
- CMPQ $0, %rax
- JNE k10mwdone
- MOVQ %rdi, %rax /* linear address to monitor */
- XORQ %rcx, %rcx /* no optional extensions yet */
- XORQ %rdx, %rdx /* no optional hints yet */
- .byte 0x0f; .byte 0x01; .byte 0xc8 /* MONITOR */
- MOVQ %rdi, %rcx
- MOVQ 0(%rcx), %rax
- CMPQ $0, %rax
- JNE k10mwdone
- XORQ %rcx, %rcx /* optional extensions */
- .byte 0x0f; .byte 0x01; .byte 0xc9 /* MWAIT */
- JMP k10mwloop
- k10mwdone:
- RET
- .global machp
- machp:
- pushfq
- popq %rax
- testq $If, %rax
- jnz _machp_bad
- _machp_out:
- movq %gs:0, %rax
- ret
- _machp_bad:
- pushq %rbp
- movq %rsp, %rbp
- callq machp_bad
- popq %rbp
- jmp _machp_out
- .global externup
- externup:
- movq %gs:40, %rax
- ret
- /* not needed.
- .global mul64fract
- mul64fract:
- MOVQ %rdi, %rax
- MULQ %rsi / * a*b *
- SHRQ $32, %rax:DX
- MOVQ %rax, (%rdi)
- RET
- */
- ///*
- // * Testing.
- // */
- //.global ud2
- ud2:
- // BYTE $0x0f; BYTE $0x0b
- // RET
- //
|