os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit bb2521efa29d3f3746ac04f148516f4f145d3402
parent 98221f3153817e479d4baf6deea9e07d5f5ebd9e
Author: erai <erai@omiltem.net>
Date:   Fri, 31 Jan 2025 02:51:02 +0000

remove the manual compiler

Diffstat:
Mas.om | 513-------------------------------------------------------------------------------
Mcc1.om | 436+------------------------------------------------------------------------------
Mir.om | 195+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 193 insertions(+), 951 deletions(-)

diff --git a/as.om b/as.om @@ -435,519 +435,6 @@ func add_symbol(c: *assembler, name: *byte, l: *label) { c.symbols = s; } -func emit_restorer(c: *assembler) { - as_modri(c, OP_MOVI, R_RAX, 15); - as_op(c, OP_SYSCALL); -} - -func emit_ptr(c: *assembler, l: *label) { - reserve(c, 16); - as_modrm(c, OP_LEA, R_RAX, R_RIP, 0, 0, 128); - addfixup(c, l); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_jmp(c: *assembler, l: *label) { - as_jmp(c, OP_JMP, l); -} - -func emit_num(c: *assembler, x: int) { - as_opri64(c, OP_MOVABS, R_RDX, x); - as_opr(c, OP_PUSHR, R_RDX); -} - -func emit_blob(c: *assembler, s: *byte, n: int) { - var a: *label; - var b: *label; - var i: int; - - a = mklabel(c); - b = mklabel(c); - - as_jmp(c, OP_JMP, b); - - fixup_label(c, a); - - i = 0; - loop { - if i == n { - break; - } - as_emit(c, s[i] as int); - i = i + 1; - } - as_emit(c, 0); - - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - - fixup_label(c, b); - emit_ptr(c, a); -} - -func emit_str(c: *assembler, s: *byte) { - var a: *label; - var b: *label; - var i: int; - - a = mklabel(c); - b = mklabel(c); - - as_jmp(c, OP_JMP, b); - - fixup_label(c, a); - - i = 0; - loop { - if (!s[i]) { - break; - } - as_emit(c, s[i] as int); - i = i + 1; - } - as_emit(c, 0); - - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - as_op(c, OP_NOP); - - fixup_label(c, b); - emit_ptr(c, a); -} - -func emit_pop(c: *assembler, n: int) { - as_modri(c, OP_ADDI, R_RSP, n << 3); -} - -func emit_kstart(c: *assembler) { - var hang: *label; - var do_iret: *label; - var do_ret: *label; - var done: *label; - - c.bits32 = 1; - - hang = mklabel(c); - do_iret = mklabel(c); - do_ret = mklabel(c); - done = mklabel(c); - - // Check for valid multiboot magic - as_modri(c, OP_MOVI, R_RDX, 0x2badb002); - as_modrr(c, OP_CMPRM, R_RAX, R_RDX); - as_jmp(c, OP_JCC + CC_NE, hang); - - // Setup an early stack - as_modri(c, OP_MOVI, R_RSP, 0x00300000); // FIXME bss - - // Align stack to page - as_modri(c, OP_ANDI, R_RSP, -0x1000); - - // pt3 -> 1g - as_modri(c, OP_SUBI, R_RSP, 0x1000); - as_modri(c, OP_MOVI, R_RAX, 0x83); - as_modri(c, OP_MOVI, R_RDX, 0); - as_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 0); - as_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 4); - as_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 510 * 8 + 0); - as_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 510 * 8 + 4); - - // pt4 -> pt3 - as_modrr(c, OP_MOVE, R_RAX, R_RSP); - as_modri(c, OP_SUBI, R_RSP, 0x1000); - as_modri(c, OP_ORI, R_RAX, 3); - as_modri(c, OP_MOVI, R_RDX, 0); - as_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 0); - as_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 4); - as_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 511 * 8 + 0); - as_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 511 * 8 + 4); - - // Load page table pt4 - as_modrr(c, OP_WRCRR, R_CR3, R_RSP); - - // Allocate space for the gdt - as_modri(c, OP_SUBI, R_RSP, 64); - as_modrr(c, OP_MOVE, R_RBP, R_RSP); - - // Null Segment - as_modri(c, OP_MOVI, R_RAX, 0x00000000); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 8); - as_modri(c, OP_MOVI, R_RAX, 0x00000000); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 12); - - // Kernel code segment - as_modri(c, OP_MOVI, R_RAX, 0x00000000); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 16); - as_modri(c, OP_MOVI, R_RAX, 0x00209800); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 20); - - // Kernel data segment - as_modri(c, OP_MOVI, R_RAX, 0x00000000); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 24); - as_modri(c, OP_MOVI, R_RAX, 0x00009200); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 28); - - // Load gdt - as_modri(c, OP_MOVI, R_RAX, 23); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 0); - as_modrm(c, OP_LEA, R_RAX, R_RBP, 0, 0, 8); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 2); - as_modm(c, OP_LGDTM, R_RBP, 0, 0, 0); - - // Load null lldt - as_modri(c, OP_MOVI, R_RAX, 0); - as_modr(c, OP_LLDTM, R_RAX); - - // Load null idt - as_modm(c, OP_LIDTM, R_RBP, 0, 0, 8); - - // Enable pae - as_modri(c, OP_MOVI, R_RAX, 0xa0); - as_modrr(c, OP_WRCRR, R_CR4, R_RAX); - - // Enable long mode - as_modri(c, OP_MOVI, R_RCX, (-1 << 32) + (0xc0 << 24) + 0x000080); - as_op(c, OP_RDMSR); - as_modri(c, OP_ORI, R_RAX, 0x100); - as_op(c, OP_WRMSR); - - // Enable paging - as_modrr(c, OP_RDCRR, R_CR0, R_RAX); - as_modri(c, OP_ORI, R_RAX, (-0x80000000) | 0x0001); - as_modrr(c, OP_WRCRR, R_CR0, R_RAX); - - // flags - as_modri(c, OP_MOVI, R_RAX, 0); - as_opr(c, OP_PUSHR, R_RAX); - // cs - as_modri(c, OP_MOVI, R_RAX, 8); - as_opr(c, OP_PUSHR, R_RAX); - // pointer - as_jmp(c, OP_CALL, do_iret); - - c.bits32 = 0; - - // Jump to top half - as_jmp(c, OP_CALL, do_ret); - - // Reload the gdt in the top half - as_modri(c, OP_ORI, R_RBP, -0x80000000); - as_modri(c, OP_MOVI, R_RAX, 23); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 0); - as_modrm(c, OP_LEA, R_RAX, R_RBP, 0, 0, 8); - as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 2); - as_modm(c, OP_LGDTM, R_RBP, 0, 0, 0); - - // Reload segments - as_modri(c, OP_MOVI, R_RAX, 16); - as_modrr(c, OP_WRSR, R_ES, R_RAX); - as_modrr(c, OP_WRSR, R_DS, R_RAX); - as_modrr(c, OP_WRSR, R_FS, R_RAX); - as_modrr(c, OP_WRSR, R_GS, R_RAX); - as_modrr(c, OP_WRSR, R_SS, R_RAX); - as_modrr(c, OP_MOVE, R_RSP, R_RSP); - - // Reload stack in the top half - as_modri(c, OP_ORI, R_RSP, -0x80000000); - - // Kill the lower mapping - as_modri(c, OP_MOVI, R_RAX, 0); - as_modrm(c, OP_LEA, R_RDI, R_RBP, 0, 0, 64); - as_modrm(c, OP_STORE, R_RAX, R_RDI, 0, 0, 4096); - as_modrm(c, OP_STORE, R_RAX, R_RDI, 0, 0, 0); - as_modri(c, OP_ANDI, R_RDI, 0x7fffffff); - as_modrr(c, OP_WRCRR, R_CR3, R_RDI); - - // Setup a call frame for _kstart - as_jmp(c, OP_JMP, done); - - // hlt forever - fixup_label(c, hang); - as_op(c, OP_CLI); - as_op(c, OP_HLT); - as_jmp(c, OP_JMP, hang); - - // iret to long mode - fixup_label(c, do_iret); - as_op(c, OP_IRET); - - // ret to top half - fixup_label(c, do_ret); - as_opr(c, OP_POPR, R_RAX); - as_modri(c, OP_ORI, R_RAX, -0x80000000); - as_opr(c, OP_PUSHR, R_RAX); - as_op(c, OP_RET); - - // Setup a call frame for _kstart - fixup_label(c, done); - as_modrr(c, OP_XORRM, R_RBP, R_RBP); - as_opr(c, OP_PUSHR, R_RBX); - as_modrr(c, OP_MOVE, R_RDI, R_RBX); - as_opr(c, OP_PUSHR, R_RBP); -} - -func emit_preamble(c: *assembler, n: int, pragma: int) { - var i: int; - if (pragma == 1) { - as_modrr(c, OP_XORRM, R_RBP, R_RBP); - as_modrm(c, OP_LOAD, R_RDI, R_RSP, 0, 0, 0); - as_modrm(c, OP_LEA, R_RSI, R_RSP, 0, 0, 8); - as_modrm(c, OP_LEA, R_RDX, R_RSI, R_RDI, 8, 8); - as_opr(c, OP_PUSHR, R_RDX); - as_opr(c, OP_PUSHR, R_RSI); - as_opr(c, OP_PUSHR, R_RDI); - as_opr(c, OP_PUSHR, R_RBP); - } else if (pragma > 1) { - emit_kstart(c); - } - as_opr(c, OP_PUSHR, R_RBP); - as_modrr(c, OP_MOVE, R_RBP, R_RSP); - i = 0; - loop { - if (i >= n) { - break; - } - emit_num(c, 0); - i = i + 8; - } -} - -func emit_store(c: *assembler, t: *type) { - as_opr(c, OP_POPR, R_RDI); - as_opr(c, OP_POPR, R_RAX); - if (t.kind == TY_BYTE) { - as_modrm(c, OP_STOREB, R_RAX, R_RDI, 0, 0, 0); - } else if (type_isprim(t)) { - as_modrm(c, OP_STORE, R_RAX, R_RDI, 0, 0, 0); - } else { - die("invalid store"); - } - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_load(c: *assembler, t: *type) { - as_opr(c, OP_POPR, R_RDI); - if (t.kind == TY_BYTE) { - as_modrr(c, OP_XORRM, R_RAX, R_RAX); - as_modrm(c, OP_LOADB, R_RAX, R_RDI, 0, 0, 0); - } else if (type_isprim(t)) { - as_modrm(c, OP_LOAD, R_RAX, R_RDI, 0, 0, 0); - } else { - die("invalid load"); - } - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_jz(c: *assembler, l: *label) { - as_opr(c, OP_POPR, R_RAX); - as_modrr(c, OP_TESTRM, R_RAX, R_RAX); - as_jmp(c, OP_JCC + CC_E, l); -} - -func emit_lea(c: *assembler, offset: int) { - as_modrm(c, OP_LEA, R_RAX, R_RBP, 0, 0, offset); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_and(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RDX); - as_modrr(c, OP_ANDRM, R_RAX, R_RDX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_or(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RDX); - as_modrr(c, OP_ORRM, R_RAX, R_RDX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_xor(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RDX); - as_modrr(c, OP_XORRM, R_RAX, R_RDX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_add(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RDX); - as_modrr(c, OP_ADDRM, R_RAX, R_RDX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_ud(c: *assembler) { - as_op(c, OP_UD2); -} - -func emit_ret(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_modrr(c, OP_MOVE, R_RSP, R_RBP); - as_opr(c, OP_POPR, R_RBP); - as_op(c, OP_RET); -} - -func emit_call(c: *assembler, n: int) { - as_opr(c, OP_POPR, R_RAX); - as_modr(c, OP_ICALLM, R_RAX); - emit_pop(c, n); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_lcall(c: *assembler, l: *label, n: int) { - as_jmp(c, OP_CALL, l); - emit_pop(c, n); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_gt(c: *assembler) { - as_opr(c, OP_POPR, R_RDX); - as_opr(c, OP_POPR, R_RCX); - as_modrr(c, OP_XORRM, R_RAX, R_RAX); - as_modrr(c, OP_CMPRM, R_RDX, R_RCX); - as_modrr(c, OP_SETCC + CC_G, 0, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_lt(c: *assembler) { - as_opr(c, OP_POPR, R_RDX); - as_opr(c, OP_POPR, R_RCX); - as_modrr(c, OP_XORRM, R_RAX, R_RAX); - as_modrr(c, OP_CMPRM, R_RDX, R_RCX); - as_modrr(c, OP_SETCC + CC_L, 0, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_ge(c: *assembler) { - as_opr(c, OP_POPR, R_RDX); - as_opr(c, OP_POPR, R_RCX); - as_modrr(c, OP_XORRM, R_RAX, R_RAX); - as_modrr(c, OP_CMPRM, R_RDX, R_RCX); - as_modrr(c, OP_SETCC + CC_GE, 0, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_le(c: *assembler) { - as_opr(c, OP_POPR, R_RDX); - as_opr(c, OP_POPR, R_RCX); - as_modrr(c, OP_XORRM, R_RAX, R_RAX); - as_modrr(c, OP_CMPRM, R_RDX, R_RCX); - as_modrr(c, OP_SETCC + CC_LE, 0, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_eq(c: *assembler) { - as_opr(c, OP_POPR, R_RDX); - as_opr(c, OP_POPR, R_RCX); - as_modrr(c, OP_XORRM, R_RAX, R_RAX); - as_modrr(c, OP_CMPRM, R_RDX, R_RCX); - as_modrr(c, OP_SETCC + CC_E, 0, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_ne(c: *assembler) { - as_opr(c, OP_POPR, R_RDX); - as_opr(c, OP_POPR, R_RCX); - as_modrr(c, OP_XORRM, R_RAX, R_RAX); - as_modrr(c, OP_CMPRM, R_RDX, R_RCX); - as_modrr(c, OP_SETCC + CC_NE, 0, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_sub(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RDX); - as_modrr(c, OP_SUBRM, R_RAX, R_RDX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_mul(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RCX); - as_modr(c, OP_IMULM, R_RCX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_div(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RCX); - as_modrr(c, OP_XORRM, R_RDX, R_RDX); - as_modrr(c, OP_TESTRM, R_RAX, R_RAX); - as_modrr(c, OP_SETCC + CC_S, 0, R_RDX); - as_modr(c, OP_NEGM, R_RDX); - as_modr(c, OP_IDIVM, R_RCX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_mod(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RCX); - as_modrr(c, OP_XORRM, R_RDX, R_RDX); - as_modrr(c, OP_TESTRM, R_RAX, R_RAX); - as_modrr(c, OP_SETCC + CC_S, 0, R_RDX); - as_modr(c, OP_NEGM, R_RDX); - as_modr(c, OP_IDIVM, R_RCX); - as_opr(c, OP_PUSHR, R_RDX); -} - -func emit_lsh(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RCX); - as_modr(c, OP_SHLM, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_rsh(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_opr(c, OP_POPR, R_RCX); - as_modr(c, OP_SHRM, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_not(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_modr(c, OP_NOTM, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_neg(c: *assembler) { - as_opr(c, OP_POPR, R_RAX); - as_modr(c, OP_NEGM, R_RAX); - as_opr(c, OP_PUSHR, R_RAX); -} - -func emit_align(c: *assembler, n: int, b: int) { - var pad: int; - - pad = c.at & (n - 1); - - if pad == 0 { - return; - } - - loop { - if pad == n { - break; - } - - as_emit(c, b); - - pad = pad + 1; - } -} - func emit_strtab_str(c: *assembler, s: *byte): int { var i: int; diff --git a/cc1.om b/cc1.om @@ -1299,283 +1299,6 @@ func gather_include(c: *compiler, filename: *byte, slen: *int): *byte { return blob; } -func compile_include(c: *compiler, n: *node) { - var blob: *byte; - var len: int; - - if n.b.a.kind != N_STR { - die("non literal include"); - } - - blob = gather_include(c, n.b.a.s, &len); - - as_opr(c.s, OP_POPR, R_RAX); - as_opr(c.s, OP_POPR, R_RDI); - as_opri64(c.s, OP_MOVABS, R_RAX, len); - as_modrm(c.s, OP_STORE, R_RAX, R_RDI, 0, 0, 0); - emit_blob(c.s, blob, len); - - free(c.a, blob); -} - -// Translate an expression -func compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { - var no: *label; - var out: *label; - var v: *decl; - var kind: int; - - update_place(c, n); - - kind = n.kind; - if (kind == N_STR) { - emit_str(c.s, n.s); - } else if (kind == N_NIL) { - emit_num(c.s, 0); - } else if (kind == N_NUM) { - emit_num(c.s, n.n); - } else if (kind == N_CHAR) { - emit_num(c.s, n.n); - } else if (kind == N_EXPRLIST) { - if (n.b) { - compile_expr(c, d, n.b, 1); - } - - compile_expr(c, d, n.a, 1); - } else if (kind == N_CALL) { - if (n.b) { - compile_expr(c, d, n.b, 1); - } - - if (n.a.kind == N_IDENT) { - v = find(c, n.a.s, nil, 0); - if (v && v.enum_defined) { - cdie(c, "type error"); - } - - v = find(c, d.name, n.a.s, 0); - if (v && v.var_defined) { - emit_lea(c.s, v.var_offset); - emit_load(c.s, n.a.t); - emit_call(c.s, count_args(c, n.a.t.arg)); - } else if !strcmp(n.a.s, "_include") { - v = find(c, n.a.s, nil, 0); - compile_include(c, n); - } else { - v = find(c, n.a.s, nil, 0); - emit_lcall(c.s, v.func_label, count_args(c, n.a.t.arg)); - } - } else { - compile_expr(c, d, n.a, 1); - emit_call(c.s, count_args(c, n.a.t.arg)); - } - - if (n.b) { - unify(c, n.a.t.arg, n.b.t); - } else { - unify(c, n.a.t.arg, nil); - } - } else if (kind == N_DOT) { - compile_expr(c, d, n.a, 0); - - if (n.a.t.kind == TY_PTR) { - v = find(c, n.a.t.val.st.name, n.b.s, 0); - emit_load(c.s, n.a.t); - } else { - v = find(c, n.a.t.st.name, n.b.s, 0); - } - - emit_num(c.s, v.member_offset); - emit_add(c.s); - - if (rhs) { - emit_load(c.s, n.t); - } - } else if (kind == N_IDENT) { - v = find(c, n.s, nil, 0); - if (v && v.enum_defined) { - emit_num(c.s, v.enum_value); - return; - } - - v = find(c, d.name, n.s, 0); - if (v && v.var_defined) { - emit_lea(c.s, v.var_offset); - if (rhs) { - emit_load(c.s, n.t); - } - return; - } - - v = find(c, n.s, nil, 0); - if (v && v.func_defined) { - emit_ptr(c.s, v.func_label); - return; - } - } else if (kind == N_ASSIGN) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 0); - - emit_store(c.s, n.t); - } else if (kind == N_SIZEOF) { - if (n.a.t.kind == TY_BYTE) { - emit_num(c.s, 1); - } else { - emit_num(c.s, type_sizeof(c, n.a.t)); - } - } else if (kind == N_REF) { - compile_expr(c, d, n.a, 0); - } else if (kind == N_DEREF) { - compile_expr(c, d, n.a, 1); - - if (rhs) { - emit_load(c.s, n.t); - } - } else if (kind == N_INDEX) { - compile_expr(c, d, n.a, 1); - compile_expr(c, d, n.b, 1); - - if (n.t.kind == TY_BYTE) { - emit_num(c.s, 1); - } else { - emit_num(c.s, type_sizeof(c, n.t)); - } - - emit_mul(c.s); - emit_add(c.s); - - if (rhs) { - emit_load(c.s, n.t); - } - } else if (kind == N_LT) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_lt(c.s); - } else if (kind == N_GT) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_gt(c.s); - } else if (kind == N_LE) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_le(c.s); - } else if (kind == N_GE) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_ge(c.s); - } else if (kind == N_EQ) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_eq(c.s); - } else if (kind == N_NE) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_ne(c.s); - } else if (kind == N_BNOT) { - no = mklabel(c.s); - out = mklabel(c.s); - - compile_expr(c, d, n.a, 1); - - emit_jz(c.s, no); - emit_num(c.s, 0); - emit_jmp(c.s, out); - fixup_label(c.s, no); - emit_num(c.s, 1); - fixup_label(c.s, out); - } else if (kind == N_BOR) { - no = mklabel(c.s); - out = mklabel(c.s); - - compile_expr(c, d, n.a, 1); - emit_jz(c.s, no); - emit_num(c.s, 1); - emit_jmp(c.s, out); - - fixup_label(c.s, no); - no = mklabel(c.s); - - compile_expr(c, d, n.b, 1); - emit_jz(c.s, no); - emit_num(c.s, 1); - emit_jmp(c.s, out); - - fixup_label(c.s, no); - emit_num(c.s, 0); - - fixup_label(c.s, out); - } else if (kind == N_BAND) { - no = mklabel(c.s); - out = mklabel(c.s); - - compile_expr(c, d, n.a, 1); - emit_jz(c.s, no); - - compile_expr(c, d, n.b, 1); - emit_jz(c.s, no); - - emit_num(c.s, 1); - emit_jmp(c.s, out); - - fixup_label(c.s, no); - emit_num(c.s, 0); - - fixup_label(c.s, out); - } else if (kind == N_POS) { - compile_expr(c, d, n.a, 1); - } else if (kind == N_NEG) { - compile_expr(c, d, n.a, 1); - emit_neg(c.s); - } else if (kind == N_NOT) { - compile_expr(c, d, n.a, 1); - emit_not(c.s); - } else if (kind == N_ADD) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_add(c.s); - } else if (kind == N_SUB) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_sub(c.s); - } else if (kind == N_MUL) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_mul(c.s); - } else if (kind == N_DIV) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_div(c.s); - } else if (kind == N_MOD) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_mod(c.s); - } else if (kind == N_LSH) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_lsh(c.s); - } else if (kind == N_RSH) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_rsh(c.s); - } else if (kind == N_AND) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_and(c.s); - } else if (kind == N_OR) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_or(c.s); - } else if (kind == N_XOR) { - compile_expr(c, d, n.b, 1); - compile_expr(c, d, n.a, 1); - emit_xor(c.s); - } else if (kind == N_CAST) { - compile_expr(c, d, n.a, 1); - } else { - cdie(c, "not an expression"); - } -} - func call_check(c: *compiler, n: *node): int { var result: int; var ret: int; @@ -1646,92 +1369,6 @@ func update_place(c: *compiler, n: *node) { c.s.lineno = n.lineno; } -// Compile a statement -func compile_stmt(c: *compiler, d: *decl, n: *node, top: *label, out: *label) { - var no: *label; - var ifout: *label; - var v: *decl; - var kind: int; - - if (!n) { - return; - } - - update_place(c, n); - - kind = n.kind; - if (kind == N_CONDLIST) { - ifout = mklabel(c.s); - no = nil; - loop { - if (no) { - fixup_label(c.s, no); - } - - if (!n) { - break; - } - - no = mklabel(c.s); - - if (n.a.a) { - compile_expr(c, d, n.a.a, 1); - emit_jz(c.s, no); - } - - compile_stmt(c, d, n.a.b, top, out); - emit_jmp(c.s, ifout); - - n = n.b; - } - fixup_label(c.s, ifout); - } else if (kind == N_STMTLIST) { - loop { - if (!n) { - break; - } - compile_stmt(c, d, n.a, top, out); - n = n.b; - } - } else if (kind == N_LOOP) { - top = mklabel(c.s); - out = mklabel(c.s); - fixup_label(c.s, top); - compile_stmt(c, d, n.a, top, out); - emit_jmp(c.s, top); - fixup_label(c.s, out); - } else if (kind == N_BREAK) { - if (!out) { - cdie(c, "break outside loop"); - } - emit_jmp(c.s, out); - } else if (kind == N_CONTINUE) { - if (!top) { - cdie(c, "continue outside loop"); - } - emit_jmp(c.s, top); - } else if (kind == N_RETURN) { - if (n.a) { - compile_expr(c, d, n.a, 1); - } else { - emit_num(c.s, 0); - } - emit_ret(c.s); - } else if (kind == N_LABEL) { - v = find(c, d.name, n.a.s, 0); - fixup_label(c.s, v.goto_label); - } else if (kind == N_GOTO) { - v = find(c, d.name, n.a.s, 0); - if (!v || !v.goto_defined) { - cdie(c, "label not defined"); - } - emit_jmp(c.s, v.goto_label); - } else if (kind != N_VARDECL) { - compile_expr(c, d, n, 1); - emit_pop(c.s, 1); - } -} - func emit_ssr(c: *compiler) { var d: *decl; var v: *decl; @@ -1987,8 +1624,8 @@ func emit_builtin(c: *compiler) { if (d.func_defined && !d.func_label.fixed) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); - as_op(c.s, OP_UD2); - emit_restorer(c.s); + as_modri(c.s, OP_MOVI, R_RAX, 15); + as_op(c.s, OP_SYSCALL); } d = find(c, "_include", nil, 1); @@ -2010,7 +1647,6 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RDI, R_RBP, 0, 0, 16); as_modrm(c.s, OP_LOAD, R_RAX, R_RDI, 0, 0, 0); as_modrm(c.s, OP_LOAD, R_RDI, R_RBP, 0, 0, 24); @@ -2029,7 +1665,6 @@ func emit_builtin(c: *compiler) { as_modrm(c.s, OP_LOAD, R_RDI, R_RBP, 0, 0, 40); as_modrm(c.s, OP_STORE, R_RBX, R_RDI, 0, 0, 0); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "inb", nil, 1); @@ -2037,11 +1672,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); as_op(c.s, OP_IN); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "outb", nil, 1); @@ -2049,12 +1682,10 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); as_op(c.s, OP_OUT); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "inw", nil, 1); @@ -2062,12 +1693,10 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); as_emit(c.s, OP_OS); as_op(c.s, OP_IND); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "outw", nil, 1); @@ -2075,13 +1704,11 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); as_emit(c.s, OP_OS); as_op(c.s, OP_OUTD); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "ind", nil, 1); @@ -2089,11 +1716,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); as_op(c.s, OP_IND); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "outd", nil, 1); @@ -2101,12 +1726,10 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RDX, R_RBP, 0, 0, 16); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); as_op(c.s, OP_OUTD); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "rdmsr", nil, 1); @@ -2114,14 +1737,12 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); as_op(c.s, OP_RDMSR); as_modri(c.s, OP_MOVI, R_RCX, 32); as_modr(c.s, OP_SHLM, R_RDX); as_modrr(c.s, OP_ORRM, R_RAX, R_RDX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "wrmsr", nil, 1); @@ -2129,7 +1750,6 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); as_modrr(c.s, OP_MOVE, R_RDX, R_RAX); as_modri(c.s, OP_MOVI, R_RCX, 32); @@ -2137,7 +1757,6 @@ func emit_builtin(c: *compiler) { as_modrm(c.s, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); as_op(c.s, OP_WRMSR); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "rdcr0", nil, 1); @@ -2145,10 +1764,8 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrr(c.s, OP_RDCRR, R_CR0, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "wrcr0", nil, 1); @@ -2156,11 +1773,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); as_modrr(c.s, OP_WRCRR, R_CR0, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "rdcr2", nil, 1); @@ -2168,10 +1783,8 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrr(c.s, OP_RDCRR, R_CR2, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "wrcr2", nil, 1); @@ -2179,11 +1792,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); as_modrr(c.s, OP_WRCRR, R_CR2, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "rdcr3", nil, 1); @@ -2191,10 +1802,8 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrr(c.s, OP_RDCRR, R_CR3, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "wrcr3", nil, 1); @@ -2202,11 +1811,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); as_modrr(c.s, OP_WRCRR, R_CR3, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "rdcr4", nil, 1); @@ -2214,10 +1821,8 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrr(c.s, OP_RDCRR, R_CR4, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "wrcr4", nil, 1); @@ -2225,11 +1830,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RCX, R_RBP, 0, 0, 16); as_modrr(c.s, OP_WRCRR, R_CR4, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "lgdt", nil, 1); @@ -2237,7 +1840,6 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modri(c.s, OP_SUBI, R_RSP, 16); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); as_modri(c.s, OP_SUBI, R_RAX, 1); @@ -2247,7 +1849,6 @@ func emit_builtin(c: *compiler) { as_modm(c.s, OP_LGDTM, R_RSP, 0, 0, 0); as_modri(c.s, OP_ADDI, R_RSP, 16); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "lidt", nil, 1); @@ -2255,7 +1856,6 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modri(c.s, OP_SUBI, R_RSP, 16); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); as_modri(c.s, OP_SUBI, R_RAX, 1); @@ -2265,7 +1865,6 @@ func emit_builtin(c: *compiler) { as_modm(c.s, OP_LIDTM, R_RSP, 0, 0, 0); as_modri(c.s, OP_ADDI, R_RSP, 16); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "lldt", nil, 1); @@ -2273,11 +1872,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); as_modr(c.s, OP_LLDTM, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "ltr", nil, 1); @@ -2285,11 +1882,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); as_modr(c.s, OP_LTRM, R_RAX); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "lseg", nil, 1); @@ -2297,7 +1892,6 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); // es ds fs gs as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); as_modrr(c.s, OP_WRSR, R_ES, R_RAX); @@ -2326,7 +1920,6 @@ func emit_builtin(c: *compiler) { as_emit(c.s, 0); as_op(c.s, OP_IRETQ); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "hlt", nil, 1); @@ -2334,10 +1927,8 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_op(c.s, OP_HLT); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "cli", nil, 1); @@ -2345,10 +1936,8 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_op(c.s, OP_CLI); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "sti", nil, 1); @@ -2356,10 +1945,8 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_op(c.s, OP_STI); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "rdflags", nil, 1); @@ -2367,9 +1954,7 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_op(c.s, OP_PUSHF); - emit_ret(c.s); } d = find(c, "wrflags", nil, 1); @@ -2377,12 +1962,10 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_op(c.s, OP_PUSHF); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); as_opr(c.s, OP_PUSHR, R_RAX); as_op(c.s, OP_POPF); - emit_ret(c.s); } d = find(c, "wbinvld", nil, 1); @@ -2390,11 +1973,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); as_modm(c.s, OP_WBINVD, R_RAX, 0, 0, 0); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "invlpg", nil, 1); @@ -2402,11 +1983,9 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 16); as_modm(c.s, OP_INVLPGM, R_RAX, 0, 0, 0); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "_ssr0", nil, 1); @@ -2430,12 +2009,10 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RSI, R_RBP, 0, 0, 16); as_emit(c.s, OP_GS); as_modrm(c.s, OP_LOAD, R_RAX, R_RSI, 0, 0, 0); as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "_r32", nil, 1); @@ -2443,13 +2020,11 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RSI, R_RBP, 0, 0, 16); c.s.bits32 = 1; as_modrm(c.s, OP_LOAD, R_RAX, R_RSI, 0, 0, 0); c.s.bits32 = 0; as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "_w32", nil, 1); @@ -2457,14 +2032,12 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RDI, R_RBP, 0, 0, 16); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); c.s.bits32 = 1; as_modrm(c.s, OP_STORE, R_RAX, R_RDI, 0, 0, 0); c.s.bits32 = 0; as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "_r16", nil, 1); @@ -2472,14 +2045,12 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RSI, R_RBP, 0, 0, 16); as_modrr(c.s, OP_XORRM, R_RAX, R_RAX); c.s.bits32 = 1; as_modrm(c.s, OP_LOAD16, R_RAX, R_RDI, 0, 0, 0); c.s.bits32 = 0; as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "_w16", nil, 1); @@ -2487,14 +2058,12 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_op(c.s, OP_UD2); - emit_preamble(c.s, 0, 0); as_modrm(c.s, OP_LOAD, R_RDI, R_RBP, 0, 0, 16); as_modrm(c.s, OP_LOAD, R_RAX, R_RBP, 0, 0, 24); c.s.bits32 = 1; as_modrm(c.s, OP_STORE16, R_RAX, R_RDI, 0, 0, 0); c.s.bits32 = 0; as_opr(c.s, OP_PUSHR, R_RAX); - emit_ret(c.s); } d = find(c, "_rdrand", nil, 1); @@ -2502,7 +2071,6 @@ func emit_builtin(c: *compiler) { fixup_label(c.s, d.func_label); add_symbol(c.s, d.name, d.func_label); as_modr(c.s, OP_RDRAND, R_RAX); - emit_ret(c.s); } d = find(c, "taskswitch", nil, 1); diff --git a/ir.om b/ir.om @@ -1374,6 +1374,192 @@ func irshow(out: *file, b: *irblock) { irreset(b); } +func emit_kstart(c: *assembler) { + var hang: *label; + var do_iret: *label; + var do_ret: *label; + var done: *label; + + c.bits32 = 1; + + hang = mklabel(c); + do_iret = mklabel(c); + do_ret = mklabel(c); + done = mklabel(c); + + // Check for valid multiboot magic + as_modri(c, OP_MOVI, R_RDX, 0x2badb002); + as_modrr(c, OP_CMPRM, R_RAX, R_RDX); + as_jmp(c, OP_JCC + CC_NE, hang); + + // Setup an early stack + as_modri(c, OP_MOVI, R_RSP, 0x00300000); // FIXME bss + + // Align stack to page + as_modri(c, OP_ANDI, R_RSP, -0x1000); + + // pt3 -> 1g + as_modri(c, OP_SUBI, R_RSP, 0x1000); + as_modri(c, OP_MOVI, R_RAX, 0x83); + as_modri(c, OP_MOVI, R_RDX, 0); + as_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 0); + as_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 4); + as_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 510 * 8 + 0); + as_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 510 * 8 + 4); + + // pt4 -> pt3 + as_modrr(c, OP_MOVE, R_RAX, R_RSP); + as_modri(c, OP_SUBI, R_RSP, 0x1000); + as_modri(c, OP_ORI, R_RAX, 3); + as_modri(c, OP_MOVI, R_RDX, 0); + as_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 0); + as_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 4); + as_modrm(c, OP_STORE, R_RAX, R_RSP, 0, 0, 511 * 8 + 0); + as_modrm(c, OP_STORE, R_RDX, R_RSP, 0, 0, 511 * 8 + 4); + + // Load page table pt4 + as_modrr(c, OP_WRCRR, R_CR3, R_RSP); + + // Allocate space for the gdt + as_modri(c, OP_SUBI, R_RSP, 64); + as_modrr(c, OP_MOVE, R_RBP, R_RSP); + + // Null Segment + as_modri(c, OP_MOVI, R_RAX, 0x00000000); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 8); + as_modri(c, OP_MOVI, R_RAX, 0x00000000); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 12); + + // Kernel code segment + as_modri(c, OP_MOVI, R_RAX, 0x00000000); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 16); + as_modri(c, OP_MOVI, R_RAX, 0x00209800); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 20); + + // Kernel data segment + as_modri(c, OP_MOVI, R_RAX, 0x00000000); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 24); + as_modri(c, OP_MOVI, R_RAX, 0x00009200); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 28); + + // Load gdt + as_modri(c, OP_MOVI, R_RAX, 23); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 0); + as_modrm(c, OP_LEA, R_RAX, R_RBP, 0, 0, 8); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 2); + as_modm(c, OP_LGDTM, R_RBP, 0, 0, 0); + + // Load null lldt + as_modri(c, OP_MOVI, R_RAX, 0); + as_modr(c, OP_LLDTM, R_RAX); + + // Load null idt + as_modm(c, OP_LIDTM, R_RBP, 0, 0, 8); + + // Enable pae + as_modri(c, OP_MOVI, R_RAX, 0xa0); + as_modrr(c, OP_WRCRR, R_CR4, R_RAX); + + // Enable long mode + as_modri(c, OP_MOVI, R_RCX, (-1 << 32) + (0xc0 << 24) + 0x000080); + as_op(c, OP_RDMSR); + as_modri(c, OP_ORI, R_RAX, 0x100); + as_op(c, OP_WRMSR); + + // Enable paging + as_modrr(c, OP_RDCRR, R_CR0, R_RAX); + as_modri(c, OP_ORI, R_RAX, (-0x80000000) | 0x0001); + as_modrr(c, OP_WRCRR, R_CR0, R_RAX); + + // flags + as_modri(c, OP_MOVI, R_RAX, 0); + as_opr(c, OP_PUSHR, R_RAX); + // cs + as_modri(c, OP_MOVI, R_RAX, 8); + as_opr(c, OP_PUSHR, R_RAX); + // pointer + as_jmp(c, OP_CALL, do_iret); + + c.bits32 = 0; + + // Jump to top half + as_jmp(c, OP_CALL, do_ret); + + // Reload the gdt in the top half + as_modri(c, OP_ORI, R_RBP, -0x80000000); + as_modri(c, OP_MOVI, R_RAX, 23); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 0); + as_modrm(c, OP_LEA, R_RAX, R_RBP, 0, 0, 8); + as_modrm(c, OP_STORE, R_RAX, R_RBP, 0, 0, 2); + as_modm(c, OP_LGDTM, R_RBP, 0, 0, 0); + + // Reload segments + as_modri(c, OP_MOVI, R_RAX, 16); + as_modrr(c, OP_WRSR, R_ES, R_RAX); + as_modrr(c, OP_WRSR, R_DS, R_RAX); + as_modrr(c, OP_WRSR, R_FS, R_RAX); + as_modrr(c, OP_WRSR, R_GS, R_RAX); + as_modrr(c, OP_WRSR, R_SS, R_RAX); + as_modrr(c, OP_MOVE, R_RSP, R_RSP); + + // Reload stack in the top half + as_modri(c, OP_ORI, R_RSP, -0x80000000); + + // Kill the lower mapping + as_modri(c, OP_MOVI, R_RAX, 0); + as_modrm(c, OP_LEA, R_RDI, R_RBP, 0, 0, 64); + as_modrm(c, OP_STORE, R_RAX, R_RDI, 0, 0, 4096); + as_modrm(c, OP_STORE, R_RAX, R_RDI, 0, 0, 0); + as_modri(c, OP_ANDI, R_RDI, 0x7fffffff); + as_modrr(c, OP_WRCRR, R_CR3, R_RDI); + + // Setup a call frame for _kstart + as_jmp(c, OP_JMP, done); + + // hlt forever + fixup_label(c, hang); + as_op(c, OP_CLI); + as_op(c, OP_HLT); + as_jmp(c, OP_JMP, hang); + + // iret to long mode + fixup_label(c, do_iret); + as_op(c, OP_IRET); + + // ret to top half + fixup_label(c, do_ret); + as_opr(c, OP_POPR, R_RAX); + as_modri(c, OP_ORI, R_RAX, -0x80000000); + as_opr(c, OP_PUSHR, R_RAX); + as_op(c, OP_RET); + + // Setup a call frame for _kstart + fixup_label(c, done); + as_modrr(c, OP_XORRM, R_RBP, R_RBP); + as_modrr(c, OP_MOVE, R_RDI, R_RBX); + as_opr(c, OP_PUSHR, R_RBP); +} + +func emit_align(c: *assembler, n: int, b: int) { + var pad: int; + + pad = c.at & (n - 1); + + if pad == 0 { + return; + } + + loop { + if pad == n { + break; + } + + as_emit(c, b); + + pad = pad + 1; + } +} + func output_ir(c: *compiler, d: *decl) { var ic: *irfunc; @@ -1389,9 +1575,12 @@ func output_ir(c: *compiler, d: *decl) { add_symbol(c.s, d.name, d.func_label); if strcmp(d.name, "_start") == 0 { - emit_preamble(c.s, 0, 1); + as_modrm(c.s, OP_LOAD, R_RDI, R_RSP, 0, 0, 0); + as_modrm(c.s, OP_LEA, R_RSI, R_RSP, 0, 0, 8); + as_modrm(c.s, OP_LEA, R_RDX, R_RSI, R_RDI, 8, 8); + as_opr(c.s, OP_PUSHR, R_RBP); } else if strcmp(d.name, "_kstart") == 0 { - emit_preamble(c.s, 0, 2); + emit_kstart(c.s); } //fputc(nil, '\n'); @@ -1922,11 +2111,9 @@ func output_irexpr(ic: *irfunc, b: *irblock, o: *irop) { } } -// line numbers // evaluator // instruction selection // register allocation -// assemble from ir // inline // intrinsics // common subexpression