168 lines
5.2 KiB
Plaintext
168 lines
5.2 KiB
Plaintext
import t, c
|
||
|
||
|
||
def cli():
|
||
c.Asm("cli", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def sti():
|
||
c.Asm("sti", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def hlt():
|
||
c.Asm("hlt", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def nop():
|
||
c.Asm("nop", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def pause():
|
||
c.Asm("pause", op=[t.ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def inb(port: t.CUInt16T) -> t.CUInt8T:
|
||
value: t.CUInt32T
|
||
# 模板内必须引用输出占位符 $0(DSL 约定,见 atom.vp),否则输出寄存器由 LLVM
|
||
# 任意分配而结果取自硬编码 eax → 读到未定义寄存器;同时 in al,dx 改写 AL,
|
||
# 需显式声明 ~{rax} clobber。
|
||
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
||
in al, dx
|
||
movzx $0, al""",
|
||
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
|
||
op =[t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
|
||
return t.CUInt8T(value)
|
||
|
||
def outb(port: t.CUInt16T, value: t.CUInt8T):
|
||
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
||
mov eax, {c.AsmInp(t.CUInt32T(value), t.ASM_DESCR.REG_ANY)}
|
||
out dx, al""",
|
||
op = [t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
|
||
|
||
|
||
def inw(port: t.CUInt16T) -> t.CUInt16T:
|
||
value: t.CUInt32T
|
||
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
||
in ax, dx
|
||
movzx eax, ax
|
||
mov {c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)}, eax""",
|
||
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
|
||
op =[t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
|
||
return t.CUInt16T(value)
|
||
|
||
def outw(port: t.CUInt16T, value: t.CUInt16T):
|
||
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
||
mov eax, {c.AsmInp(t.CUInt32T(value), t.ASM_DESCR.REG_ANY)}
|
||
out dx, ax""",
|
||
op = [t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
|
||
|
||
def inl(port: t.CUInt16T) -> t.CUInt32T:
|
||
value: t.CUInt32T
|
||
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
||
in eax, dx
|
||
mov {c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)}, eax""",
|
||
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
|
||
op =[t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
|
||
return value
|
||
|
||
def outl(port: t.CUInt16T, value: t.CUInt32T):
|
||
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
|
||
mov eax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)}
|
||
out dx, eax""",
|
||
op = [t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
|
||
|
||
def io_wait():
|
||
c.Asm(f"mov dx, 0x80; out dx, al",
|
||
op = [t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_DX])
|
||
|
||
# [N10 约束] pushall/popall 必须成对使用:push 块内 RSP 下移 120 字节,而 LLVM
|
||
# 的 clobber 列表**不允许声明 RSP**(保留寄存器)⇒ 编译器无从得知 RSP 已被改写,
|
||
# 若两块之间出现任何编译器生成的栈使用(spill/调用),会覆盖刚压栈的寄存器值。
|
||
# 故只可在**编译期不产生任何栈使用**的上下文(如 naked 汇编区)里成对使用。
|
||
inline def pushall():
|
||
c.Asm(f"""
|
||
push rax
|
||
push rbx
|
||
push rcx
|
||
push rdx
|
||
push rsi
|
||
push rdi
|
||
push rbp
|
||
push r8
|
||
push r9
|
||
push r10
|
||
push r11
|
||
push r12
|
||
push r13
|
||
push r14
|
||
push r15""",
|
||
[t.ASM_DESCR.CLOBBER_MEMORY]
|
||
)
|
||
|
||
inline def popall():
|
||
c.Asm(f"""
|
||
pop r15
|
||
pop r14
|
||
pop r13
|
||
pop r12
|
||
pop r11
|
||
pop r10
|
||
pop r9
|
||
pop r8
|
||
pop rbp
|
||
pop rdi
|
||
pop rsi
|
||
pop rdx
|
||
pop rcx
|
||
pop rbx
|
||
pop rax""",
|
||
[t.ASM_DESCR.CLOBBER_MEMORY]
|
||
)
|
||
|
||
# [N10 说明] 本块把当前寄存器压入 old_stack、再从 new_stack 弹出全部寄存器:
|
||
# 对本线程而言寄存器值被原样恢复(每个线程在各自的保存点继续),因此**不声明**
|
||
# 寄存器 clobber 是有意为之,而非疏漏。另:输入约束 REG_ANY='r' 是"仅寄存器",
|
||
# 若改成声明 15 个通用寄存器 clobber,LLVM 将无寄存器可分配给输入 → 编译期
|
||
# "ran out of registers";RSP 亦无法声明。当前全仓无调用点。
|
||
def cpu_switch_context(old_stack: t.CUInt64T | t.CPtr, new_stack: t.CUInt64T):
|
||
c.Asm(f"""
|
||
push rax
|
||
push rbx
|
||
push rcx
|
||
push rdx
|
||
push rsi
|
||
push rdi
|
||
push rbp
|
||
push r8
|
||
push r9
|
||
push r10
|
||
push r11
|
||
push r12
|
||
push r13
|
||
push r14
|
||
push r15
|
||
mov [{c.AsmInp(old_stack, t.ASM_DESCR.REG_ANY)}], rsp
|
||
mov rsp, {c.AsmInp(new_stack, t.ASM_DESCR.REG_ANY)}
|
||
pop r15
|
||
pop r14
|
||
pop r13
|
||
pop r12
|
||
pop r11
|
||
pop r10
|
||
pop r9
|
||
pop r8
|
||
pop rbp
|
||
pop rdi
|
||
pop rsi
|
||
pop rdx
|
||
pop rcx
|
||
pop rbx
|
||
pop rax""",
|
||
op=[t.ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def BSSClean():
|
||
c.Asm(
|
||
"lea rdi, [rip + __bss_start]\n"
|
||
"lea rcx, [rip + __bss_end]\n"
|
||
"sub rcx, rdi\n"
|
||
"xor eax, eax\n"
|
||
"cld\n"
|
||
"rep stosb",
|
||
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RDI, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RAX]
|
||
)
|