nx_x86_64_arith_test.nx source
↩ module page · 69 lines · 2356 B
1// nx_x86_64_arith_test.nx -- session 4 smoke for mul/div/shift/bitwise.
2//
3// Computes ((7 * 6) - 30) / 4 = 3 entirely on the x86_64 stack
4// machine, ASCII-encodes the result (0x30 + 3 = '3') and writes
5// one byte to stdout. Validates imulq + subq + cqo + idivq.
6//
7// Then ALSO does:
8// (0xFF & 0x0F) | 0x40 = 0x4F = 'O' -- and/or
9// (5 ^ 3) << 1 = 12 -> '<' -- xor/shlq_imm
10// not(~0xFFFFFFFFFFFFFFFB) = 5 -> '5' -- notq + neg
11// But the SMOKE asserts ONLY the first one to keep things minimal.
12// Stdout: "3" (one byte 0x33).
13
14import "syscalls.nx"
15import "nx_outbuf.nx"
16import "nx_x86_64.nx"
17
18func main() -> i64 {
19 let o: *OutBuf = out_new(8192)
20
21 let main_name: *u8 = "main" as *u8
22 let _start_name: *u8 = "_start" as *u8
23
24 out_str(o, "# Emitted by nx_x86_64.nx session 4 (arith/bitwise/shift)\n")
25 out_str(o, " .att_syntax prefix\n")
26
27 x86_emit_function_start(o, _start_name)
28 out_str(o, " call main\n")
29 x86_emit_movabsq(o, "rax" as *u8, NX_X64_SYS_EXIT)
30 x86_emit_movabsq(o, "rdi" as *u8, 0)
31 x86_emit_syscall(o)
32 x86_emit_function_end(o, _start_name)
33
34 x86_emit_function_start(o, main_name)
35 x86_emit_prologue(o, 16)
36
37 // Compute (7 * 6 - 30) / 4 = 3.
38 x86_emit_movabsq(o, "rax" as *u8, 7)
39 x86_emit_movabsq(o, "rcx" as *u8, 6)
40 x86_emit_imulq_rr(o, "rcx" as *u8, "rax" as *u8) // rax = 42
41 x86_emit_movabsq(o, "rcx" as *u8, 30)
42 x86_emit_subq_rr(o, "rcx" as *u8, "rax" as *u8) // rax = 12
43 x86_emit_movabsq(o, "rcx" as *u8, 4)
44 x86_emit_cqo(o) // sign-extend
45 x86_emit_idivq_r(o, "rcx" as *u8) // rax = 3
46
47 // ASCII-encode: rax += 0x30
48 x86_emit_movabsq(o, "rcx" as *u8, 0x30)
49 x86_emit_addq_rr(o, "rcx" as *u8, "rax" as *u8) // rax = 0x33 ('3')
50
51 // Store the byte at -1(%rbp).
52 x86_emit_store_byte(o, "rax" as *u8, "rbp" as *u8, 0 - 1)
53
54 // write(1, &buf, 1)
55 x86_emit_movabsq(o, "rdi" as *u8, 1)
56 x86_emit_lea_disp(o, "rbp" as *u8, 0 - 1, "rsi" as *u8)
57 x86_emit_movabsq(o, "rdx" as *u8, 1)
58 x86_emit_movabsq(o, "rax" as *u8, NX_X64_SYS_WRITE)
59 x86_emit_syscall(o)
60
61 x86_emit_movabsq(o, "rax" as *u8, 0)
62 x86_emit_epilogue(o)
63 x86_emit_function_end(o, main_name)
64
65 x86_emit_gnu_stack_note(o)
66
67 sys_write(1, o.buf, o.pos)
68 return 0
69}