hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 080d6d83136b1a7955e35f6f2bff74a0b3760cb7
parent 0177a332c666be1c03b59e8524fc425196147efe
Author: Armin Preiml <apreiml@strohwolke.at>
Date:   Fri, 26 Nov 2021 13:34:04 +0100

add cpuid for x86_64 to check flags and vendor

Signed-off-by: Armin Preiml <apreiml@strohwolke.at>

Diffstat:
Art/+x86_64/cpuid.ha | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Art/+x86_64/cpuid_native.s | 41+++++++++++++++++++++++++++++++++++++++++
Mscripts/gen-stdlib | 10+++++++++-
Mstdlib.mk | 20++++++++++++++++++--
4 files changed, 187 insertions(+), 3 deletions(-)

diff --git a/rt/+x86_64/cpuid.ha b/rt/+x86_64/cpuid.ha @@ -0,0 +1,119 @@ +export type cpuid_vendor = enum { + AMD, + INTEL, + WINCHIP, + TRANSMETA, + CYRIX, + CENTAUR, + NEXGEN, + UMC, + SIS, + NSC, + RISE, + VORTEX, + VIA, + ZHAOXIN, + HYGON, + MCST_ELBRUS, + + // Virtual Machines. + VMWARE, + XENHVM, + MICROSOFT_HV, + PARALLELS, +}; + +export type cpuid_unknownvendor = !void; + +// cpuid vendor list taken from https://wiki.osdev.org/CPUID and +// https://en.wikipedia.org/wiki/CPUID +// Order and len matches the entries in the cpuid_vendor enum. +const vendors: [_]str = [ + "AuthenticAMD", + "GenuineIntel", + "CentaurHauls", + "GenuineTMx86", + "CyrixInstead", + "CentaurHauls", + "NexGenDriven", + "UMC UMC UMC ", + "SiS SiS SiS ", + "Geode by NSC", + "RiseRiseRise", + "Vortex86 SoC", + "VIA VIA VIA ", + " Shanghai ", + "HygonGenuine", + "E2K MACHINE", + "VMwareVMware", + "XenVMMXenVMM", + "Microsoft Hv", + " lrpepyh vr", +]; + +def VENDOR_OLDAMD: str = "AMDisbetter!"; +def VENDOR_OLDTRANSMETA: str = "TransmetaCPU"; + +export type cpuid_edxflags = enum uint { + SSE = 1 << 25, + SSE2 = 1 << 26, +}; + +export type cpuid_ecxflags = enum uint { + SSE3 = 1 << 0, + AES = 1 << 25, +}; + +fn cpuid_getvendorstr(v: *[12]u8) void; + +fn cpuid_getfeatureflags(flags: *[2]u32) void; + +// Figures out cpu vendor using cpuid +export fn cpuid_getvendor() (cpuid_vendor | cpuid_unknownvendor) = { + let vstr: [12]u8 = [0...]; + cpuid_getvendorstr(&vstr); + + for (let i = 0z; i < len(vendors); i += 1) { + if (bytes_equal(vstr, strings_toutf8(vendors[i]))) { + return i: cpuid_vendor; + }; + }; + + // some vendors changed their strings in between cpu revisions + if (bytes_equal(vstr, strings_toutf8(VENDOR_OLDAMD))) { + return cpuid_vendor::AMD; + }; + + if (bytes_equal(vstr, strings_toutf8(VENDOR_OLDTRANSMETA))) { + return cpuid_vendor::TRANSMETA; + }; + + return cpuid_unknownvendor; +}; + +// Checks if cpu has given features. See [[cpuid_edxflags]] and +// [[cpuid_ecxflags]] for available options. +export fn cpuid_hasflags(edx: u32, ecx: u32) bool = { + let flags: [2]u32 = [0...]; + cpuid_getfeatureflags(&flags); + + return flags[0] & edx == edx && flags[1] & ecx == ecx; +}; + +// we can't use strings in rt so we add a helper here +fn strings_toutf8(s: str) []u8 = { + return *(&s: *[]u8); +}; + +fn bytes_equal(a: []u8, b: []u8) bool = { + if (len(a) != len(b)) { + return false; + }; + + for (let i = 0z; i < len(a); i += 1) { + if (a[i] != b[i]) { + return false; + }; + }; + return true; +}; diff --git a/rt/+x86_64/cpuid_native.s b/rt/+x86_64/cpuid_native.s @@ -0,0 +1,41 @@ +.global rt.cpuid_getvendorstr +.type rt.cpuid_getvendorstr,@function +rt.cpuid_getvendorstr: + pushq %rdx + pushq %rcx + pushq %rbx + + cpuid + movl %ebx, (%rdi) + movl %edx, 4(%rdi) + movl %ecx, 8(%rdi) + + popq %rbx + popq %rcx + popq %rdx + ret + +.global rt.cpuid_getfeatureflags +.type rt.cpuid_getfeatureflags,@function +rt.cpuid_getfeatureflags: + + pushq %rdx + pushq %rcx + pushq %rbx + + movl $1, %eax + cpuid + + movq %rdi, -0x8(%rsp) + movq -0x8(%rsp), %rax + movl %edx, (%rax) + + movq -0x8(%rsp), %rax + add $0x4, %rax + movl %ecx, (%rax) + + popq %rbx + popq %rcx + popq %rdx + ret + diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -35,6 +35,7 @@ gensrcs_rt() { '+$(ARCH)'/jmp.ha \ '+$(ARCH)'/backtrace.ha \ fenv_defs.ha \ + +x86_64/cpuid.ha \ ensure.ha \ jmp.ha \ malloc.ha \ @@ -57,6 +58,7 @@ gensrcs_rt() { +'$(ARCH)'/jmp.ha \ +'$(ARCH)'/backtrace.ha \ fenv_defs.ha \ + +x86_64/cpuid.ha \ ensure.ha \ jmp.ha \ malloc.ha \ @@ -98,7 +100,8 @@ ${stdlib}_asm=\$($cache)/rt/syscall.o \\ \$($cache)/rt/restore.o \\ \$($cache)/rt/getfp.o \\ \$($cache)/rt/fenv.o \\ - \$($cache)/rt/start.o + \$($cache)/rt/start.o \\ + \$($cache)/rt/cpuid_native.o \$($cache)/rt/syscall.o: \$(STDLIB)/rt/+\$(PLATFORM)/syscall+\$(ARCH).s @printf 'AS \t\$@\n' @@ -130,6 +133,11 @@ ${stdlib}_asm=\$($cache)/rt/syscall.o \\ @mkdir -p \$($cache)/rt @\$(AS) -o \$@ \$< +\$($cache)/rt/cpuid_native.o: \$(STDLIB)/rt/+\$(ARCH)/cpuid_native.s + @printf 'AS \t\$@\n' + @mkdir -p \$($cache)/rt + @\$(AS) -o \$@ \$< + \$($cache)/rt/rt-linux.a: \$($cache)/rt/rt-linux.o \$(${stdlib}_asm) @printf 'AR\t\$@\n' @\$(AR) -csr \$@ \$($cache)/rt/rt-linux.o \$(${stdlib}_asm) diff --git a/stdlib.mk b/stdlib.mk @@ -19,6 +19,7 @@ stdlib_rt_linux_srcs= \ $(STDLIB)/rt/+$(ARCH)/jmp.ha \ $(STDLIB)/rt/+$(ARCH)/backtrace.ha \ $(STDLIB)/rt/fenv_defs.ha \ + $(STDLIB)/rt/+x86_64/cpuid.ha \ $(STDLIB)/rt/ensure.ha \ $(STDLIB)/rt/jmp.ha \ $(STDLIB)/rt/malloc.ha \ @@ -44,6 +45,7 @@ stdlib_rt_freebsd_srcs= \ $(STDLIB)/rt/+$(ARCH)/jmp.ha \ $(STDLIB)/rt/+$(ARCH)/backtrace.ha \ $(STDLIB)/rt/fenv_defs.ha \ + $(STDLIB)/rt/+x86_64/cpuid.ha \ $(STDLIB)/rt/ensure.ha \ $(STDLIB)/rt/jmp.ha \ $(STDLIB)/rt/malloc.ha \ @@ -77,7 +79,8 @@ stdlib_asm=$(HARECACHE)/rt/syscall.o \ $(HARECACHE)/rt/restore.o \ $(HARECACHE)/rt/getfp.o \ $(HARECACHE)/rt/fenv.o \ - $(HARECACHE)/rt/start.o + $(HARECACHE)/rt/start.o \ + $(HARECACHE)/rt/cpuid_native.o $(HARECACHE)/rt/syscall.o: $(STDLIB)/rt/+$(PLATFORM)/syscall+$(ARCH).s @printf 'AS \t$@\n' @@ -109,6 +112,11 @@ $(HARECACHE)/rt/getfp.o: $(STDLIB)/rt/+$(ARCH)/getfp.s @mkdir -p $(HARECACHE)/rt @$(AS) -o $@ $< +$(HARECACHE)/rt/cpuid_native.o: $(STDLIB)/rt/+$(ARCH)/cpuid_native.s + @printf 'AS \t$@\n' + @mkdir -p $(HARECACHE)/rt + @$(AS) -o $@ $< + $(HARECACHE)/rt/rt-linux.a: $(HARECACHE)/rt/rt-linux.o $(stdlib_asm) @printf 'AR\t$@\n' @$(AR) -csr $@ $(HARECACHE)/rt/rt-linux.o $(stdlib_asm) @@ -1910,6 +1918,7 @@ testlib_rt_linux_srcs= \ $(STDLIB)/rt/+$(ARCH)/jmp.ha \ $(STDLIB)/rt/+$(ARCH)/backtrace.ha \ $(STDLIB)/rt/fenv_defs.ha \ + $(STDLIB)/rt/+x86_64/cpuid.ha \ $(STDLIB)/rt/ensure.ha \ $(STDLIB)/rt/jmp.ha \ $(STDLIB)/rt/malloc.ha \ @@ -1939,6 +1948,7 @@ testlib_rt_freebsd_srcs= \ $(STDLIB)/rt/+$(ARCH)/jmp.ha \ $(STDLIB)/rt/+$(ARCH)/backtrace.ha \ $(STDLIB)/rt/fenv_defs.ha \ + $(STDLIB)/rt/+x86_64/cpuid.ha \ $(STDLIB)/rt/ensure.ha \ $(STDLIB)/rt/jmp.ha \ $(STDLIB)/rt/malloc.ha \ @@ -1976,7 +1986,8 @@ testlib_asm=$(TESTCACHE)/rt/syscall.o \ $(TESTCACHE)/rt/restore.o \ $(TESTCACHE)/rt/getfp.o \ $(TESTCACHE)/rt/fenv.o \ - $(TESTCACHE)/rt/start.o + $(TESTCACHE)/rt/start.o \ + $(TESTCACHE)/rt/cpuid_native.o $(TESTCACHE)/rt/syscall.o: $(STDLIB)/rt/+$(PLATFORM)/syscall+$(ARCH).s @printf 'AS \t$@\n' @@ -2008,6 +2019,11 @@ $(TESTCACHE)/rt/getfp.o: $(STDLIB)/rt/+$(ARCH)/getfp.s @mkdir -p $(TESTCACHE)/rt @$(AS) -o $@ $< +$(TESTCACHE)/rt/cpuid_native.o: $(STDLIB)/rt/+$(ARCH)/cpuid_native.s + @printf 'AS \t$@\n' + @mkdir -p $(TESTCACHE)/rt + @$(AS) -o $@ $< + $(TESTCACHE)/rt/rt-linux.a: $(TESTCACHE)/rt/rt-linux.o $(testlib_asm) @printf 'AR\t$@\n' @$(AR) -csr $@ $(TESTCACHE)/rt/rt-linux.o $(testlib_asm)