Compare commits

...

3 Commits

Author SHA1 Message Date
veclav talica
55c5f2dcf6 restracturing to platform 2023-09-22 22:09:48 +05:00
veclav talica
95e4d54042 fixes and optimizations in x86-64 opcodes 2023-09-22 21:52:57 +05:00
veclav talica
511936220e cosmopolitan build 2023-09-21 12:10:46 +05:00
11 changed files with 90 additions and 24 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
**/*.o
**/*.a
**/*.lds
**/*.h
zig-out/
zig-cache/

0
.gitmodules vendored Normal file
View File

5
build-cosmo.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
zig build-obj ./src/platform/cosmopolitan/main.zig -fno-PIE -fno-PIC -fno-stack-check --mod nmvm::src/nmvm.zig --deps nmvm
ld.bfd main.o -o zig-out/bin/nmvm.com.dbg -T extern/cosmopolitan/ape.lds extern/cosmopolitan/crt.o extern/cosmopolitan/ape-copy-self.o \
extern/cosmopolitan/cosmopolitan.a -z common-page-size=0x1000 -z max-page-size=0x1000 --gc-sections

4
extern/cosmopolitan/get.sh vendored Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
wget wget https://justine.lol/cosmopolitan/cosmopolitan.tar.gz
unzip cosmopolitan.tar.gz

4
extern/get.sh vendored Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
cd ./cosmopolitan
./get.sh

7
prepare.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
cd ./extern
./get.sh
cd ../
zig translate-c ./extern/cosmopolitan/cosmopolitan.h > ./src/platform/cosmopolitan/cosmopolitan.zig

View File

@ -1,2 +1,2 @@
pub usingnamespace @import("x86-64/jedino-jedro.zig");
pub usingnamespace @import("x86-64/ve-sistema.zig");
pub usingnamespace @import("x86-64/zov/ve-sistema.zig");

View File

@ -14,6 +14,9 @@
// todo: Use ZF flag as conditional register so to not involve stack?
// Alternatively we could keep boolean word, but implement it in vector semantics.
//
// ZF flag route can be achieved with using LEA instead of ADD as it doesn't touch flags,
// but we would need to store the flag when doing other calling convention calls.
// Resources:
// https://mort.coffee/home/fast-interpreters/
@ -23,10 +26,25 @@
// https://ziglang.org/documentation/master/#toc-Assembly
// https://csiflabs.cs.ucdavis.edu/~ssdavis/50/att-syntax.htm
// https://stackoverflow.com/questions/37639993/is-this-assembly-function-call-safe-complete
// https://groups.csail.mit.edu/pag/OLD/parg/piumarta98optimizing.pdf
// https://dl.acm.org/doi/pdf/10.1145/1328195.1328197
// https://www.agner.org/optimize/instruction_tables.pdf
// https://stackoverflow.com/questions/6323027/lea-or-add-instruction
// Neat things:
// https://joryanick.com/retro-fast-x86-memcpy.php
// https://www.codeproject.com/Articles/1110153/Apex-memmove-the-fastest-memcpy-memmove-on-x-x-EVE
// https://www.usenix.org/legacy/publications/library/proceedings/jvm01/gagnon/gagnon_html/node19.html#piumarta
// https://www.agner.org/optimize/optimizing_assembly.pdf
// http://sebastianmihai.com/x86-assembly-optimization.html
// todo: Opcode for fast integer divisions with statically known divider.
// todo: Opcodes taking operands based on offset from top of stack, without consuming.
// todo: Certain constant multiplication optimization by LEA:
// LEA EAX, [EAX * 2 + EAX] ;EAX = EAX * 3
// LEA EAX, [EAX * 4 + EAX] ;EAX = EAX * 5
// LEA EAX, [EAX * 8 + EAX] ;EAX = EAX * 9
//
const tolmac = @import("../../tolmac.zig");
const Word = tolmac.Word;
@ -35,7 +53,7 @@ const Word = tolmac.Word;
/// (iw | -- iw)
pub fn opPushWord() callconv(.Naked) noreturn {
asm volatile (
\\ add $0x10, %%r12
\\ addq $0x10, %%r12
\\ pushq -8(%%r12)
\\ jmpq *(%%r12)
);
@ -45,7 +63,7 @@ pub fn opPushWord() callconv(.Naked) noreturn {
/// (w)
pub fn opSinkWord() callconv(.Naked) noreturn {
asm volatile (
\\ add $0x08, %%r12
\\ addq $0x08, %%r12
\\ addq $0x08, %%rsp
\\ jmpq *(%%r12)
);
@ -65,20 +83,29 @@ pub fn opSinkWord() callconv(.Naked) noreturn {
// @call(.always_tail, binary[2].function, .{ &binary[2], cond });
// }
// todo: Generate operation permutations procedurally.
// todo: Jump on overflow instead of cond setting?
/// (w1 w2 -- sum overflow)
pub fn opSumWordsWithOverflow() callconv(.Naked) noreturn {
// https://www.felixcloutier.com/x86/adc
// https://www.felixcloutier.com/x86/add
// https://www.felixcloutier.com/x86/setcc
// idea: Could https://www.felixcloutier.com/x86/cmovcc be better for overflow push?
asm volatile (
\\ addq $0x08, %%r12
\\ movq (%%rsp), %%rax
\\ adcq 8(%%rsp), %%rax
\\ movq (%%rsp), %%rbx
\\ movq %%rbx, %%rax
\\ addq 8(%%rsp), %%rax
\\ movq %%rax, 8(%%rsp)
\\ setc %%al
\\ movb %%al, (%%rsp)
\\ xorq %%rbx, (%%rsp)
\\ setc (%%rsp)
\\ jmpq *(%%r12)
);
}
/// (w1 w2 -- sum)
pub fn opSumWords() callconv(.Naked) noreturn {
asm volatile (
\\ addq $0x08, %%r12
\\ popq %%rax
\\ addq (%%rsp), %%rax
\\ movq %%rax, (%%rsp)
\\ jmpq *(%%r12)
);
}
@ -92,9 +119,6 @@ pub fn opSumWordsWithOverflow() callconv(.Naked) noreturn {
// @call(.always_tail, binary[offset].function, .{ &binary[offset], cond });
// }
// todo: Complex call op that would receive immediate mask that would tell
// which positions of stack to duplicate, as well as mixing of plain immediate operands.
// Or we could decouple it from call, it might be useful at other places.
/// (iw |)
pub fn opCall() callconv(.Naked) noreturn {
asm volatile (

View File

@ -1,12 +1,16 @@
//! ve sistema (.ve-sistema:x86-64)
//! .zov.ve-sistema:x86-64
//!
//! Provides entry opcodes for System V calling convention, optimized for specific prototypes.
//!
// https://refspecs.linuxbase.org/elf/x86_64-abi-0.99.pdf
// todo: Provide opcode that would dynamically dispatch based on marshaled C prototypes,
// which will be sufficient for rare prototypes sporadically used, so to not bloat
// the binary with all possible permutations or ask for them on comptime, which is unreasonable.
const std = @import("std");
const tolmac = @import("../../tolmac.zig");
const tolmac = @import("../../../tolmac.zig");
/// Used for stack parameter passing.
pub const WordLimit = 128;
@ -111,8 +115,8 @@ pub fn generateOpZovSysvFromPrototype(prototype: anytype) !*const fn () callconv
;
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;
const IntegerAllocations = [_][]const u8{ "rdi", "rsi", "rdx", "rcx", "r8", "r9" };
// var sse_allocation: enum { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 } = .xmm0;
var class_buffer = [_]Class{.void} ** ClassBufferLimit;

1
src/nmvm.zig Normal file
View File

@ -0,0 +1 @@
pub const tolmac = @import("tolmac.zig");

View File

@ -1,20 +1,29 @@
const std = @import("std");
const tolmac = @import("tolmac.zig");
const tolmac = @import("nmvm").tolmac;
const cosmo = @import("cosmopolitan.zig");
fn printInt3(int: u64, other: u32, another: u16) callconv(.SysV) void {
@setAlignStack(16);
std.debug.print("test: {}, {}, {}\n", .{ int, other, another });
_ = cosmo.printf("%u\n", @as(c_uint, @intCast(int + other + another)));
}
fn printInt2(int: u64, other: u8) callconv(.SysV) void {
@setAlignStack(16);
std.debug.print("test: {}, {}\n", .{ int, other });
_ = cosmo.printf("%u\n", @as(c_uint, @intCast(int + other)));
}
const opPrintInt3Zov = tolmac.generateOpZovSysvFromPrototype(printInt3) catch unreachable;
const opPrintInt2Zov = tolmac.generateOpZovSysvFromPrototype(printInt2) catch unreachable;
pub fn main() !void {
comptime {
@export(cosmopolitanMain, .{ .name = "main" });
}
// todo: No cosmopolitan main.
fn cosmopolitanMain(argc: c_int, argv: [*][*:0]u8) callconv(.SysV) c_int {
_ = argc;
_ = argv;
const add = [_]tolmac.Word{
@as(tolmac.Word, @intFromPtr(&tolmac.opSumWordsWithOverflow)),
@as(tolmac.Word, @intFromPtr(&tolmac.opReturn)),
@ -43,8 +52,10 @@ pub fn main() !void {
};
tolmac.execute(&entry, 0);
return 0;
}
test {
_ = @import("tolmac.zig");
_ = @import("nmvm").tolmac;
}