diff --git a/src/arch/x86-64/ve-sistema.zig b/src/arch/x86-64/ve-sistema.zig index 5f8b7d9..e59dee4 100644 --- a/src/arch/x86-64/ve-sistema.zig +++ b/src/arch/x86-64/ve-sistema.zig @@ -75,18 +75,15 @@ pub fn generateOpZovSysvFromPrototype(prototype: anytype) !*const fn () callconv var source_buffer = [_]u8{0} ** AsmBufferLimit; var source_needle: usize = 0; - // todo: Align callee frame to 16? - // > shrq $4, %%rsp - // > addq $1, %%rsp - // > shlq $4, %%rsp - // idea: Try using REP for big consequent memory pushes. // todo: In-stack returns by pointing %rdi directly to final destination. + // todo: Test whether aligning by shifting is better. const Prelude = \\ movq %%rsp, %%rbp # Move stack pointer in non-volatile %rbp to restore later - \\ subq $0x8, %%rsp + \\ andq $-16, %%rsp # Align stack so that %rsp + 8 in callee is 16 aligned. + \\ addq $0x{x}, %%rsp \\ ; @@ -102,9 +99,6 @@ pub fn generateOpZovSysvFromPrototype(prototype: anytype) !*const fn () callconv \\ ; - @memcpy(source_buffer[source_needle .. source_needle + Prelude.len], Prelude[0..]); - source_needle += Prelude.len; - var integer_allocation: usize = 0; const IntegerAllocations = [_][]const u8{ "rdi", "rsi", "rdx", "rcx", "r8", "r9", "stack" }; // var sse_allocation: enum { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, stack } = .xmm0; @@ -118,6 +112,12 @@ pub fn generateOpZovSysvFromPrototype(prototype: anytype) !*const fn () callconv parameter_stack_size += 8 * classes.len; } + source_needle += (try std.fmt.bufPrint( + source_buffer[source_needle..], + Prelude[0..], + .{if (parameter_stack_size % 16 == 0) 16 else 8}, + )).len; + // Push parameters to appropriate registers and stack positions. var stack_offset: usize = parameter_stack_size; for (func.params) |param| { diff --git a/src/main.zig b/src/main.zig index bfe27cf..2d0c1a1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,12 +1,18 @@ const std = @import("std"); const tolmac = @import("tolmac.zig"); -fn printInt(int: u64, other: u32, another: u16) callconv(.SysV) void { +fn printInt3(int: u64, other: u32, another: u16) callconv(.SysV) void { @setAlignStack(16); std.debug.print("test: {}, {}, {}\n", .{ int, other, another }); } -const opPrintIntZov = tolmac.generateOpZovSysvFromPrototype(printInt) catch unreachable; +fn printInt2(int: u64, other: u8) callconv(.SysV) void { + @setAlignStack(16); + std.debug.print("test: {}, {}\n", .{ int, other }); +} + +const opPrintInt3Zov = tolmac.generateOpZovSysvFromPrototype(printInt3) catch unreachable; +const opPrintInt2Zov = tolmac.generateOpZovSysvFromPrototype(printInt2) catch unreachable; pub fn main() !void { // todo: Mixing return addresses in stack poses a challenge, hm. @@ -27,9 +33,11 @@ pub fn main() !void { 10, @as(tolmac.Word, @intFromPtr(&tolmac.opPushWord)), 20, - @as(tolmac.Word, @intFromPtr(opPrintIntZov)), - @as(tolmac.Word, @intFromPtr(&printInt)), + @as(tolmac.Word, @intFromPtr(opPrintInt3Zov)), + @as(tolmac.Word, @intFromPtr(&printInt3)), @as(tolmac.Word, @intFromPtr(&tolmac.opSinkWord)), + @as(tolmac.Word, @intFromPtr(opPrintInt2Zov)), + @as(tolmac.Word, @intFromPtr(&printInt2)), @as(tolmac.Word, @intFromPtr(&tolmac.opSinkWord)), @as(tolmac.Word, @intFromPtr(&tolmac.opSinkWord)), @as(tolmac.Word, @intFromPtr(&tolmac.opReturn)),