Add x86_64-linux-gnu emulator

I wanted a tiny scriptable meltdown proof way to run userspace programs
and visualize how program execution impacts memory. It helps to explain
how things like Actually Portable Executable works. It can show you how
the GCC generated code is going about manipulating matrices and more. I
didn't feel fully comfortable with Qemu and Bochs because I'm not smart
enough to understand them. I wanted something like gVisor but with much
stronger levels of assurances. I wanted a single binary that'll run, on
all major operating systems with an embedded GPL barrier ZIP filesystem
that is tiny enough to transpile to JavaScript and run in browsers too.

https://justine.storage.googleapis.com/emulator625.mp4
This commit is contained in:
Justine Tunney 2020-08-25 04:23:25 -07:00
parent 467504308a
commit f4f4caab0e
1052 changed files with 65667 additions and 7825 deletions

View file

@ -28,6 +28,6 @@
/ @param esi second string
/ @param edx byte size
/ @return 0 if equal or nonzero
bcmp: jmp *hook$memcmp(%rip)
bcmp: jmp *__memcmp(%rip)
.endfn bcmp,globl
.source __FILE__

View file

@ -1,43 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Finds lowest set bit in 𝑥.
/
/ @param edi is 32-bit unsigned 𝑥 value
/ @return eax in range [0,32) or undefined if 𝑥 is 0
/ @see also treasure trove of nearly identical functions
/
/ uint32 𝑥 bsf(𝑥) tzcnt(𝑥) ffs(𝑥) bsr(𝑥) lzcnt(𝑥)
/ 0x00000000 wut 32 0 wut 32
/ 0x00000001 0 0 1 0 31
/ 0x80000001 0 0 1 31 0
/ 0x80000000 31 31 32 31 0
/ 0x00000010 4 4 5 4 27
/ 0x08000010 4 4 5 27 4
/ 0x08000000 27 27 28 27 4
/ 0xffffffff 0 0 1 31 0
/
bsf: .leafprologue
.profilable
bsf %edi,%eax
.leafepilogue
.endfn bsf,globl
.source __FILE__

View file

@ -3,18 +3,25 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
unsigned bsf(unsigned) libcesque pureconst;
unsigned bsfl(unsigned long) libcesque pureconst;
unsigned bsfmax(uintmax_t) libcesque pureconst;
/*
* BIT SCANNING 101
* ctz(𝑥) 31^clz(𝑥) clz(𝑥)
* uint32 𝑥 bsf(𝑥) tzcnt(𝑥) ffs(𝑥) bsr(𝑥) lzcnt(𝑥)
* 0x00000000 wut 32 0 wut 32
* 0x00000001 0 0 1 0 31
* 0x80000001 0 0 1 31 0
* 0x80000000 31 31 32 31 0
* 0x00000010 4 4 5 4 27
* 0x08000010 4 4 5 27 4
* 0x08000000 27 27 28 27 4
* 0xffffffff 0 0 1 31 0
*/
#define bsf(X) \
({ \
unsigned Res; \
typeof(X) Word; \
asm("bsf\t%1,%0" : "=r,r"(Word) : "r,m"(X)); \
Res = Word; \
Res; \
})
#define bsf(u) __builtin_ctz(u)
#define bsfl(u) __builtin_ctzl(u)
#define bsfll(u) __builtin_ctzll(u)
unsigned bsfmax(uintmax_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -1,44 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Finds lowest set bit in 𝑥.
/
/ @param rdi is 64-bit unsigned 𝑥 value
/ @return eax number in range [0,64) or undefined if 𝑥 is 0
/ @see also treasure trove of nearly identical functions
/
/ uint32 𝑥 bsf(𝑥) tzcnt(𝑥) ffs(𝑥) bsr(𝑥) lzcnt(𝑥)
/ 0x00000000 wut 32 0 wut 32
/ 0x00000001 0 0 1 0 31
/ 0x80000001 0 0 1 31 0
/ 0x80000000 31 31 32 31 0
/ 0x00000010 4 4 5 4 27
/ 0x08000010 4 4 5 27 4
/ 0x08000000 27 27 28 27 4
/ 0xffffffff 0 0 1 31 0
/
bsfl: .leafprologue
.profilable
bsf %rdi,%rax
.leafepilogue
.endfn bsfl,globl
.alias bsfl,bsfll
.source __FILE__

View file

@ -1,43 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Returns binary logarithm of integer 𝑥.
/
/ @param edi is 32-bit unsigned 𝑥 value
/ @return eax number in range [0,32) or undefined if 𝑥 is 0
/ @see also treasure trove of nearly identical functions
/
/ uint32 𝑥 bsf(𝑥) tzcnt(𝑥) ffs(𝑥) bsr(𝑥) lzcnt(𝑥)
/ 0x00000000 wut 32 0 wut 32
/ 0x00000001 0 0 1 0 31
/ 0x80000001 0 0 1 31 0
/ 0x80000000 31 31 32 31 0
/ 0x00000010 4 4 5 4 27
/ 0x08000010 4 4 5 27 4
/ 0x08000000 27 27 28 27 4
/ 0xffffffff 0 0 1 31 0
/
bsr: .leafprologue
.profilable
bsr %edi,%eax
.leafepilogue
.endfn bsr,globl
.source __FILE__

View file

@ -3,26 +3,25 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
unsigned bsr(unsigned) libcesque pureconst;
unsigned bsrl(unsigned long) libcesque pureconst;
unsigned bsrmax(uintmax_t) libcesque pureconst;
/*
* BIT SCANNING 101
* ctz(𝑥) 31^clz(𝑥) clz(𝑥)
* uint32 𝑥 bsf(𝑥) tzcnt(𝑥) ffs(𝑥) bsr(𝑥) lzcnt(𝑥)
* 0x00000000 wut 32 0 wut 32
* 0x00000001 0 0 1 0 31
* 0x80000001 0 0 1 31 0
* 0x80000000 31 31 32 31 0
* 0x00000010 4 4 5 4 27
* 0x08000010 4 4 5 27 4
* 0x08000000 27 27 28 27 4
* 0xffffffff 0 0 1 31 0
*/
#ifdef __GNUC__
#define bsr(X) \
({ \
unsigned Word; \
asm("bsrl\t%1,%0" : "=r,r"(Word) : "r,m"(X)); \
Word; \
})
#define bsrl(X) \
({ \
unsigned Res; \
unsigned long Word; \
asm("bsrq\t%1,%0" : "=r,r"(Word) : "r,m"(X)); \
Res = Word; \
Res; \
})
#endif
#define bsr(u) ((sizeof(unsigned) * 8 - 1) ^ __builtin_clz(u))
#define bsrl(u) ((sizeof(unsigned long) * 8 - 1) ^ __builtin_clzl(u))
#define bsrll(u) ((sizeof(unsigned long long) * 8 - 1) ^ __builtin_clzll(u))
unsigned bsrmax(uintmax_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -1,44 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Returns binary logarithm of integer 𝑥.
/
/ @param rdi is 32-bit unsigned 𝑥 value
/ @return eax number in range [0,64) or undefined if 𝑥 is 0
/ @see also treasure trove of nearly identical functions
/
/ uint32 𝑥 bsf(𝑥) tzcnt(𝑥) ffs(𝑥) bsr(𝑥) lzcnt(𝑥)
/ 0x00000000 wut 32 0 wut 32
/ 0x00000001 0 0 1 0 31
/ 0x80000001 0 0 1 31 0
/ 0x80000000 31 31 32 31 0
/ 0x00000010 4 4 5 4 27
/ 0x08000010 4 4 5 27 4
/ 0x08000000 27 27 28 27 4
/ 0xffffffff 0 0 1 31 0
/
bsrl: .leafprologue
.profilable
bsr %rdi,%rax
.leafepilogue
.endfn bsrl,globl
.alias bsrl,bsrll
.source __FILE__

View file

@ -30,6 +30,6 @@
/ @see memset(), explicit_bzero()
bzero: mov %rsi,%rdx
xor %esi,%esi
jmp _memset
jmp MemSet
.endfn bzero,globl
.source __FILE__

View file

@ -29,7 +29,10 @@ cmpsl: .leafprologue
.profilable
xor %eax,%eax
cmpsl
cmovl .Lone(%rip),%eax
/ mov (%rdi),%edi
/ mov (%rsi),%esi
/ cmp %edi,%esi
setl %al
cmovg .Lneg1(%rip),%eax
.leafepilogue
.endfn cmpsl,globl

17
libc/nexgen32e/crc32.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_CRC32_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_CRC32_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern const uint32_t kCrc32Tab[256];
void crc32init(uint32_t[hasatleast 256], uint32_t);
uint32_t crc32_z(uint32_t, const void *, size_t);
extern uint32_t (*const crc32c)(uint32_t, const void *, size_t) paramsnonnull();
uint32_t crc32c$pure(uint32_t, const void *, size_t) strlenesque hidden;
uint32_t crc32c$sse42(uint32_t, const void *, size_t) strlenesque hidden;
uint32_t crc32$pclmul(uint32_t, const void *, size_t) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_CRC32_H_ */

View file

@ -17,7 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/str/internal.h"
#include "libc/nexgen32e/crc32.h"
/**
* Computes Castagnoli CRC-32 on old computers.

View file

@ -23,11 +23,11 @@
* Hashes data with hardware acceleration at 10GBps.
* @note needs Nehalem+ c. 2008 or Bulldozer+ c. 2011
*/
uint32_t crc32c$sse42(uint32_t init, const void *data, size_t size) {
uint32_t crc32c$sse42(uint32_t init, const void *data, size_t n) {
const unsigned char *p = (const unsigned char *)data;
const unsigned char *pe = (const unsigned char *)data + size;
const unsigned char *pe = (const unsigned char *)data + n;
uint32_t h = init ^ 0xffffffff;
if (size >= 16 + 8) {
if (n >= 16 + 8) {
while ((uintptr_t)p & 7) asm("crc32b\t%1,%0" : "+r"(h) : "rm"(*p++));
uint64_t hl = h;
while (p < pe - 16ul) {

View file

@ -36,11 +36,9 @@ crc32c: .quad 0
.init.start 300,_init_crc32c
ezlea crc32c$pure,ax
#if !IsTiny()
ezlea crc32c$sse42,cx
testb X86_HAVE(SSE4_2)+kCpuids(%rip)
cmovnz %rcx,%rax
#endif
stosq
.init.end 300,_init_crc32c
.source __FILE__

View file

@ -50,7 +50,7 @@ crc32init:
dec %eax
mov %eax,(%rsp)
jnz 0b
movups (%rsp),%xmm1
movdqu (%rsp),%xmm1
1: mov $8,%ecx
movdqa %xmm1,%xmm3
2: movdqa %xmm3,%xmm4

View file

@ -18,9 +18,8 @@
02110-1301 USA
*/
#include "libc/bits/safemacros.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/str/internal.h"
#include "libc/str/str.h"
/**
* Computes Phil Katz CRC-32 used by zip/zlib/gzip/etc.

View file

@ -1,119 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Performs 128-bit div+mod by 10 without using div or mod.
/
/ If we didn't have this one-off function, our palandprintf()
/ implementation would cause nearly everything to need a soft
/ math library. It also somehow goes faster than 64-bit IDIV.
/
/ @param rdi:rsi is the number
/ @param rdx points to where remainder goes
/ @return rax:rdx is result of division
/ @see “Division by Invariant Integers using Multiplication”
/ @see llog10() and div10int64() is a tiny bit faster
div10: .leafprologue
.profilable
push %rbx
mov %rdx,%r8
test %rsi,%rsi
je 1f
bsr %rsi,%r10
xor $63,%r10d
mov $125,%r9d
sub %r10d,%r9d
cmp $64,%r9d
jne 6f
xor %eax,%eax
xor %r11d,%r11d
jmp 9f
1: test %r8,%r8
je 3f
movabs $0xcccccccccccccccd,%rcx
mov %rdi,%rax
mul %rcx
shr $3,%rdx
add %edx,%edx
lea (%rdx,%rdx,4),%eax
mov %edi,%ecx
sub %eax,%ecx
mov %ecx,(%r8)
3: movabs $0xcccccccccccccccd,%rcx
mov %rdi,%rax
mul %rcx
mov %rdx,%rax
shr $3,%rax
xor %edi,%edi
jmp 14f
6: mov %r9d,%ecx
neg %cl
cmp $62,%r10d
jb 8f
mov %rdi,%rdx
shl %cl,%rdx
mov %rsi,%rax
mov %r9d,%ecx
shr %cl,%rax
shrd %cl,%rsi,%rdi
xor %r11d,%r11d
mov %rdi,%rsi
mov %rdx,%rdi
jmp 9f
8: mov %rdi,%r11
shl %cl,%r11
mov %rsi,%rax
shl %cl,%rax
mov %r9d,%ecx
shr %cl,%rdi
or %rax,%rdi
shr %cl,%rsi
xor %eax,%eax
9: add $-125,%r10d
xor %ecx,%ecx
mov $9,%r9d
10: shld $1,%rsi,%rax
shld $1,%rdi,%rsi
shld $1,%r11,%rdi
mov %r11,%rdx
add %r11,%rdx
mov %rcx,%r11
or %rdx,%r11
cmp %rsi,%r9
mov $0,%ebx
sbb %rax,%rbx
sar $63,%rbx
mov %ebx,%ecx
and $1,%ecx
and $10,%ebx
sub %rbx,%rsi
sbb $0,%rax
inc %r10d
jne 10b
test %r8,%r8
je 13f
mov %esi,(%r8)
13: lea (%rcx,%r11,2),%rax
shld $1,%rdx,%rdi
14: mov %rdi,%rdx
pop %rbx
.leafepilogue
.endfn div10,globl,hidden
.source __FILE__

View file

@ -19,10 +19,10 @@
*/
#include "libc/macros.h"
/ Divides 64-bit integer by 1,000,000,000.
/ Divides 64-bit signed integer by 1,000,000,000.
/
/ @param rdi is number to divide
/ @return truncated numerator
/ @return quotient
div1000000000int64:
mov $0x1a,%cl
movabs $0x112e0be826d694b3,%rdx

View file

@ -19,10 +19,10 @@
*/
#include "libc/macros.h"
/ Divides 64-bit integer by 1,000,000.
/ Divides 64-bit signed integer by 1,000,000.
/
/ @param rdi is number to divide
/ @return truncated numerator
/ @return quotient
div1000000int64:
mov $0x12,%cl
movabs $0x431bde82d7b634db,%rdx

View file

@ -0,0 +1,31 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Divides 64-bit signed integer by 10,000.
/
/ @param rdi is number to divide
/ @return truncated quotient
div10000int64:
mov $11,%cl
movabs $0x346dc5d63886594b,%rdx
jmp tinydivsi
.endfn div10000int64,globl
.source __FILE__

View file

@ -19,10 +19,10 @@
*/
#include "libc/macros.h"
/ Divides 64-bit integer by 1,000.
/ Divides 64-bit signed integer by 1,000.
/
/ @param rdi is number to divide
/ @return truncated numerator
/ @return quotient
div1000int64:
mov $0x7,%cl
movabs $0x20c49ba5e353f7cf,%rdx

View file

@ -0,0 +1,36 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Divides 64-bit signed integer by 100.
/
/ @param rdi is number to divide
/ @return rax has quotient
div100int64:
mov %rdi,%rax
movabs $-6640827866535438581,%rdx
imul %rdx
lea (%rdx,%rdi),%rax
sar $63,%rdi
sar $6,%rax
sub %rdi,%rax
ret
.endfn div100int64,globl
.source __FILE__

View file

@ -19,12 +19,12 @@
*/
#include "libc/macros.h"
/ Divides 64-bit integer by 10.
/ Divides 64-bit signed integer by 10.
/
/ @param rdi is number to divide
/ @return truncated numerator
/ @return quotient
div10int64:
mov $0x2,%cl
mov $2,%cl
movabs $0x6666666666666667,%rdx
jmp tinydivsi
.endfn div10int64,globl

View file

@ -17,8 +17,6 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dce.h"
#include "libc/str/str.h"
#define N 32
typedef uint8_t uint8_v _Vector_size(N);

View file

@ -39,12 +39,12 @@ explicit_bzero:
xor %r9,%r9
xor %r10,%r10
xor %r11,%r11
xorps %xmm0,%xmm0
xorps %xmm1,%xmm1
xorps %xmm2,%xmm2
xorps %xmm3,%xmm3
xorps %xmm4,%xmm4
xorps %xmm5,%xmm5
pxor %xmm0,%xmm0
pxor %xmm1,%xmm1
pxor %xmm2,%xmm2
pxor %xmm3,%xmm3
pxor %xmm4,%xmm4
pxor %xmm5,%xmm5
.leafepilogue
.endfn explicit_bzero,globl
.source __FILE__

View file

@ -41,7 +41,7 @@ ffs: .leafprologue
bsf %edi,%eax
or $-1,%edx
cmovz %edx,%eax
inc %eax
add $1,%eax
.leafepilogue
.endfn ffs,globl
.source __FILE__

View file

@ -41,7 +41,7 @@ ffsl: .leafprologue
bsf %rdi,%rax
or $-1,%edx
cmovz %edx,%eax
inc %eax
add $1,%eax
.leafepilogue
.endfn ffsl,globl
.alias ffsl,ffsll

View file

@ -33,9 +33,10 @@
/ @param rax,rdx,xmm0,xmm1,st0,st1 is return value
/ @see test/libc/runtime/gc_test.c
/ <LIMBO>
__gc: decq __garbage(%rip)
mov __garbage(%rip),%r8
mov __garbage+16(%rip),%r9
CollectGarbage:
decq g_garbage(%rip)
mov g_garbage(%rip),%r8
mov g_garbage+16(%rip),%r9
js 9f
shl $5,%r8
lea (%r9,%r8),%r8
@ -45,28 +46,25 @@ __gc: decq __garbage(%rip)
/ </LIMBO>
push %rbp
mov %rsp,%rbp
sub $0x40,%rsp
sub $0x20,%rsp
push %rax
push %rdx
fstpl -0x40(%rbp)
fstpl -0x30(%rbp)
movaps %xmm0,-0x20(%rbp)
movaps %xmm1,-0x10(%rbp)
call *%r9
movaps -0x10(%rbp),%xmm1
movaps -0x20(%rbp),%xmm0
fldl -0x30(%rbp)
fldl -0x40(%rbp)
pop %rdx
pop %rax
leave
ret
9: call abort
.endfn __gc,globl,hidden
.endfn CollectGarbage,globl,hidden
.source __FILE__
.bss
.align 8
__garbage:
g_garbage:
.quad 0 # garbage.i
.quad 0 # garbage.n
.quad 0 # garbage.p
@ -76,16 +74,10 @@ __garbage:
.quad 0 # garbage.p[𝑖].arg
.quad 0 # garbage.p[𝑖].ret
.endr
.endobj __garbage,globl,hidden
.endobj g_garbage,globl,hidden
.previous
.init.start 100,_init_garbage
push %rdi
ezlea __garbage+8,di
pushpop INITIAL_CAPACITY,%rax
stosq
lea 8(%rdi),%rax
stosq
pop %rdi
movb $INITIAL_CAPACITY,g_garbage+8(%rip)
movl $g_garbage+24,g_garbage+16(%rip)
.init.end 100,_init_garbage
.source __FILE__

View file

@ -15,9 +15,9 @@ struct Garbages {
} * p;
};
hidden extern struct Garbages __garbage;
hidden extern struct Garbages g_garbage;
int64_t __gc(void) hidden;
int64_t CollectGarbage(void) hidden;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -33,8 +33,8 @@
gclongjmp:
.leafprologue
.profilable
.weak __garbage
lea __garbage(%rip),%r12
.weak g_garbage
lea g_garbage(%rip),%r12
test %r12,%r12
jnz .L.unwind.destructors
0: jmp longjmp

View file

@ -1,58 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/dce.h"
#include "libc/nexgen32e/cachesize.h"
#include "libc/nexgen32e/cpuid4.h"
static unsigned getcachesize$cpuid4(int type, int level) {
unsigned i, k;
static int once;
static unsigned char kCacheKey[8];
static unsigned kCacheSize[8];
if (!once) {
CPUID4_ITERATE(i, {
kCacheKey[i] = CPUID4_KEY;
kCacheSize[i] = CPUID4_CACHE_SIZE_IN_BYTES;
});
once = 1;
}
k = ((level & 7) << 5) | (type & 31);
for (i = 0; i < 8; ++i) {
if (kCacheKey[i] == k) {
return kCacheSize[i];
}
}
return 0;
}
/**
* Returns CPU cache size.
*
* @param type 1=data, 2=instruction, 3=unified
* @param level starts at 1
* @return size in bytes, or 0 if unknown
*/
unsigned getcachesize(enum CpuCacheType type, int level) {
assert(1 <= type && type <= 3);
assert(level >= 1);
return getcachesize$cpuid4(type, level);
}

View file

@ -1,39 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/bisect.h"
#include "libc/nexgen32e/x86info.h"
static int CmpX86ProcModelKey(const struct X86ProcessorModel *a,
const struct X86ProcessorModel *b) {
return a->key > b->key ? 1 : a->key < b->key ? -1 : 0;
}
/**
* Identifies microarchitecture of host processor.
*
* @param key can be kX86ProcessorModelKey for host info
* @see https://en.wikichip.org/wiki/intel/cpuid
* @see https://a4lg.com/tech/x86/database/x86-families-and-models.en.html
*/
const struct X86ProcessorModel *getx86processormodel(short key) {
return bisect(&(struct X86ProcessorModel){key}, kX86ProcessorModels,
kX86ProcessorModelCount, sizeof(struct X86ProcessorModel),
(void *)CmpX86ProcModelKey, NULL);
}

View file

@ -1,39 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/log/log.h"
#include "libc/nexgen32e/nexgen32e.h"
/**
* Sorts array of signed 32-bit integers.
* @see djbsort()
*/
textreal void insertionsort(size_t n, int32_t a[n]) {
int t;
unsigned i, j;
for (i = 1; i < n; ++i) {
j = i;
t = a[i];
while (j > 0 && t < a[j - 1]) {
a[j] = a[j - 1];
--j;
}
a[j] = t;
}
}

View file

@ -20,6 +20,7 @@
#include "libc/macros.h"
.rodata
.align 16
.source __FILE__
/ ibm cp437 unicode table w/ string literal safety
/
@ -70,7 +71,7 @@ kCp437:
.short 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047 #40:@ABCDEFG
.short 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f #48:HIJKLMNO
.short 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057 #50:PQRSTUVW
.short 0x0058,0x0059,0x005a,0x005b,0x2572,0x005d,0x005e,0x005f #58:XYZ[]^_
.short 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f #58:XYZ[\]^_
.short 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067 #60:`abcdefg
.short 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f #68:hijklmno
.short 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077 #70:pqrstuvw
@ -93,4 +94,3 @@ kCp437:
.short 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x03bb #f8:°·²λ
.endobj kCp437,globl
.previous
.source __FILE__

View file

@ -65,8 +65,8 @@ kCpuids:.long 0,0,0,0 # EAX=0 (Basic Processor Info)
2: pop %rax
test %eax,%eax # EAX = stacklist->pop()
jz 3f # EAX 0 (EOL sentinel)
cmp KCPUIDS(0H,EAX)(%r8),%eax # EAX CPUID.0 max leaf
jle 1b # CPUID too new to probe
cmp KCPUIDS(0H,EAX)(%r8),%al # EAX CPUID.0 max leaf
jbe 1b # CPUID too new to probe
add $4*4,%rdi
jmp 2b
3: nop

View file

@ -8,7 +8,7 @@
#define KCPUIDS_80000001H 4
#define KCPUIDS_80000007H 5
#define KCPUIDS_16H 6
#define _KCPUIDS_LEN 7
#define KCPUIDS_LEN 7
#define KCPUIDS_6H -1 /* TBD: Thermal and Power Management */
#define KCPUIDS_DH -1 /* TBD: Extended state features */
#define KCPUIDS_80000008H -1 /* TBD: AMD Miscellaneous */
@ -36,7 +36,7 @@ COSMOPOLITAN_C_START_
* @note Protected with PIRO
* @see X86_HAVE()
*/
extern const unsigned kCpuids[_KCPUIDS_LEN][4];
extern const unsigned kCpuids[KCPUIDS_LEN][4];
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -1,33 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "tool/viz/lib/knobs.h"
bool pf1_;
bool pf2_;
bool pf3_;
bool pf4_;
bool pf5_;
bool pf6_;
bool pf7_;
bool pf8_;
bool pf9_;
bool pf10_;
bool pf11_;
bool pf12_;

View file

@ -34,4 +34,5 @@ kStartTsc:
xchg %edx,%eax
stosl
.init.end 200,_init_kStartTsc
.source __FILE__

View file

@ -1,83 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/macros.h"
#include "libc/nexgen32e/x86info.h"
const struct X86ProcessorModel kX86ProcessorModels[] = {
/* <SORTED> */
{0x060F, X86_MARCH_CORE2, X86_GRADE_CLIENT},
{0x0616, X86_MARCH_CORE2, X86_GRADE_MOBILE},
{0x0617, X86_MARCH_CORE2, X86_GRADE_SERVER},
{0x061A, X86_MARCH_NEHALEM, X86_GRADE_DENSITY},
{0x061C, X86_MARCH_BONNELL, X86_GRADE_APPLIANCE},
{0x061D, X86_MARCH_CORE2, X86_GRADE_SERVER},
{0x061E, X86_MARCH_NEHALEM, X86_GRADE_CLIENT},
{0x061F, X86_MARCH_NEHALEM, X86_GRADE_DESKTOP},
{0x0625, X86_MARCH_WESTMERE, X86_GRADE_CLIENT},
{0x0626, X86_MARCH_BONNELL, X86_GRADE_TABLET},
{0x0627, X86_MARCH_SALTWELL, X86_GRADE_TABLET},
{0x062A, X86_MARCH_SANDYBRIDGE, X86_GRADE_CLIENT},
{0x062C, X86_MARCH_WESTMERE, X86_GRADE_DENSITY},
{0x062D, X86_MARCH_SANDYBRIDGE, X86_GRADE_SERVER},
{0x062E, X86_MARCH_NEHALEM, X86_GRADE_SERVER},
{0x062F, X86_MARCH_WESTMERE, X86_GRADE_SERVER},
{0x0635, X86_MARCH_SALTWELL, X86_GRADE_TABLET},
{0x0636, X86_MARCH_SALTWELL, X86_GRADE_APPLIANCE},
{0x0637, X86_MARCH_SILVERMONT, X86_GRADE_APPLIANCE},
{0x063A, X86_MARCH_IVYBRIDGE, X86_GRADE_CLIENT},
{0x063C, X86_MARCH_HASWELL, X86_GRADE_CLIENT},
{0x063D, X86_MARCH_BROADWELL, X86_GRADE_CLIENT},
{0x063E, X86_MARCH_IVYBRIDGE, X86_GRADE_SERVER},
{0x063F, X86_MARCH_HASWELL, X86_GRADE_SERVER},
{0x0645, X86_MARCH_HASWELL, X86_GRADE_MOBILE},
{0x0646, X86_MARCH_HASWELL, X86_GRADE_DESKTOP},
{0x0647, X86_MARCH_BROADWELL, X86_GRADE_DESKTOP},
{0x064A, X86_MARCH_SILVERMONT, X86_GRADE_TABLET},
{0x064C, X86_MARCH_AIRMONT, X86_GRADE_APPLIANCE},
{0x064D, X86_MARCH_SILVERMONT, X86_GRADE_DENSITY},
{0x064E, X86_MARCH_SKYLAKE, X86_GRADE_MOBILE},
{0x064F, X86_MARCH_BROADWELL, X86_GRADE_SERVER},
{0x0655, X86_MARCH_SKYLAKE, X86_GRADE_SERVER},
{0x0656, X86_MARCH_BROADWELL, X86_GRADE_DENSITY},
{0x0657, X86_MARCH_KNIGHTSLANDING, X86_GRADE_SCIENCE},
{0x065A, X86_MARCH_AIRMONT, X86_GRADE_TABLET},
{0x065C, X86_MARCH_GOLDMONT, X86_GRADE_APPLIANCE},
{0x065E, X86_MARCH_SKYLAKE, X86_GRADE_CLIENT},
{0x065F, X86_MARCH_GOLDMONT, X86_GRADE_DENSITY},
{0x0666, X86_MARCH_CANNONLAKE, X86_GRADE_MOBILE},
{0x066A, X86_MARCH_ICELAKE, X86_GRADE_SERVER},
{0x066C, X86_MARCH_ICELAKE, X86_GRADE_DENSITY},
{0x0675, X86_MARCH_AIRMONT, X86_GRADE_APPLIANCE},
{0x067A, X86_MARCH_GOLDMONTPLUS, X86_GRADE_APPLIANCE},
{0x067D, X86_MARCH_ICELAKE, X86_GRADE_CLIENT},
{0x067E, X86_MARCH_ICELAKE, X86_GRADE_MOBILE},
{0x0685, X86_MARCH_KNIGHTSMILL, X86_GRADE_SCIENCE},
{0x0686, X86_MARCH_TREMONT, X86_GRADE_APPLIANCE},
{0x068C, X86_MARCH_TIGERLAKE, X86_GRADE_MOBILE},
{0x068D, X86_MARCH_TIGERLAKE, X86_GRADE_CLIENT},
{0x068E, X86_MARCH_KABYLAKE, X86_GRADE_MOBILE},
{0x0696, X86_MARCH_TREMONT, X86_GRADE_APPLIANCE},
{0x069D, X86_MARCH_ICELAKE, X86_GRADE_SCIENCE},
{0x069E, X86_MARCH_KABYLAKE, X86_GRADE_CLIENT},
/* </SORTED> */
};
const size_t kX86ProcessorModelCount = ARRAYLEN(kX86ProcessorModels);

View file

@ -1,34 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/kompressor.h"
#include "libc/nexgen32e/lz4.h"
const unsigned char *lz4check(const void *data) {
const unsigned char *frame = data;
if (LZ4_MAGIC(frame) == LZ4_MAGICNUMBER && LZ4_FRAME_VERSION(frame) == 1 &&
LZ4_FRAME_BLOCKINDEPENDENCE(frame) == true &&
LZ4_FRAME_BLOCKCONTENTSIZEFLAG(frame) == true &&
LZ4_FRAME_RESERVED1(frame) == 0 && LZ4_FRAME_RESERVED2(frame) == 0 &&
LZ4_FRAME_RESERVED3(frame) == 0) {
return frame;
} else {
return NULL;
}
}

View file

@ -1,61 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/pushpop.h"
#include "libc/intrin/repmovsb.h"
#include "libc/nexgen32e/kompressor.h"
#include "libc/str/str.h"
/**
* Decompresses LZ4 block.
*
* This is a 103 byte implementation of the LZ4 algorithm. Please note
* LZ4 files are comprised of multiple frames, which may be decoded
* together using the wrapper function lz4decode().
*
* @see rldecode() for a 16-byte decompressor
*/
textstartup void *lz4cpy(void *dest, const void *blockdata, size_t blocksize) {
unsigned char *op, *ip, *ipe, *match;
unsigned token, length, fifteen, offset, matchlen;
for (op = dest, ip = blockdata, ipe = ip + blocksize;;) {
token = *ip++;
length = token >> 4;
fifteen = pushpop(15);
if (length == fifteen) {
do {
length += *ip;
} while (*ip++ == 255);
}
repmovsb(&op, &ip, length);
if (ip >= ipe) break;
offset = read16le(ip);
matchlen = token & fifteen;
ip += 2;
if (matchlen == fifteen) {
do {
matchlen += *ip;
} while (*ip++ == 255);
}
match = op - offset;
repmovsb(&op, &match, (matchlen += 4));
}
return op;
}

View file

@ -1,50 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/kompressor.h"
#include "libc/nexgen32e/lz4.h"
#include "libc/str/str.h"
/**
* Decompresses LZ4 file.
*
* We assume (1) the file is mmap()'d or was copied into into memory
* beforehand; and (2) folks handling untrustworthy data shall place
* 64kb of guard pages on the ends of each buffer, see mapanon(). We
* don't intend to support XXHASH; we recommend folks needing checks
* against data corruption consider crc32c(), or gzip since it's the
* best at file recovery. Dictionaries are supported; by convention,
* they are passed in the 64kb bytes preceding src.
*
* @return pointer to end of decoded data, similar to mempcpy()
* @see mapanon(), lz4check()
*/
void *lz4decode(void *dest, const void *src) {
const unsigned char *frame, *block;
frame = (const unsigned char *)src;
for (block = frame + LZ4_FRAME_HEADERSIZE(frame); !LZ4_BLOCK_ISEOF(block);
block += LZ4_BLOCK_SIZE(frame, block)) {
if (LZ4_BLOCK_ISCOMPRESSED(block)) {
dest = lz4cpy(dest, LZ4_BLOCK_DATA(block), LZ4_BLOCK_DATASIZE(block));
} else {
dest = mempcpy(dest, LZ4_BLOCK_DATA(block), LZ4_BLOCK_DATASIZE(block));
}
}
return dest;
}

View file

@ -28,6 +28,7 @@
/ @note AVX2 requires Haswell (2014+) or Excavator (2015+)
/ @see libc/nexgen32e/memcmp.S (for benchmarks)
/ @asyncsignalsafe
.align 16
memcmp$avx2:
.leafprologue
.profilable
@ -58,7 +59,7 @@ memcmp$avx2:
jz 5b
jmp 8f
7: xor %eax,%eax
8: vxorps %ymm0,%ymm0,%ymm0
8: vpxor %ymm0,%ymm0,%ymm0
.leafepilogue
.endfn memcmp$avx2,globl,hidden
.source __FILE__

View file

@ -29,9 +29,9 @@
/ @return unsigned char subtraction at stop index
/ @asyncsignalsafe
.initbss 300,_init_memcmp
hook$memcmp:
__memcmp:
.quad 0
.endobj hook$memcmp,globl,hidden
.endobj __memcmp,globl,hidden
.previous
.init.start 300,_init_memcmp

View file

@ -44,7 +44,7 @@ memcmp$sse2:
movdqu (%rsi,%rcx),%xmm1
pcmpeqb %xmm1,%xmm0
pmovmskb %xmm0,%eax
subl $0xffff,%eax
sub $0xffff,%eax
jz 1b
bsf %eax,%eax
add %rax,%rcx

View file

@ -26,7 +26,7 @@
/ @param edx byte size
/ @return unsigned char subtraction at stop index
/ @asyncsignalsafe
memcmp: jmp *hook$memcmp(%rip)
memcmp: jmp *__memcmp(%rip)
.endfn memcmp,globl
.source __FILE__

View file

@ -46,17 +46,17 @@
.source __FILE__
memcpy: mov %rdi,%rax
/ 𝑠𝑙𝑖𝑑𝑒
.endfn memcpy,globl
/ Copies memory w/ minimal impact ABI.
/
/ @param rdi is dest
/ @param rsi is src
/ @param rdx is number of bytes
/ @clob flags,xmm3
/ @clob flags,xmm3,xmm4
/ @mode long
.align 16
_memcpy:.leafprologue
.profilable
MemCpy: .leafprologue
push %rcx
mov $.Lmemcpytab.ro.size,%ecx
cmp %rcx,%rdx
@ -65,27 +65,29 @@ _memcpy:.leafprologue
.Lanchorpoint:
.L32r: cmp $1024,%rdx
jae .Lerms
.L32: mov $32,%rcx
.L32: vmovdqu -32(%rsi,%rdx),%ymm4
mov $32,%rcx
0: add $32,%rcx
vmovdqu -64(%rsi,%rcx),%ymm3
vmovdqu %ymm3,-64(%rdi,%rcx)
cmp %rcx,%rdx
ja 0b
vmovdqu -32(%rsi,%rdx),%ymm3
vmovdqu %ymm3,-32(%rdi,%rdx)
vxorps %ymm3,%ymm3,%ymm3
vmovdqu %ymm4,-32(%rdi,%rdx)
vpxor %ymm4,%ymm4,%ymm4
vpxor %ymm3,%ymm3,%ymm3
jmp .L0
.L16r: cmp $1024,%rdx
jae .Lerms
.L16: mov $16,%rcx
.L16: movdqu -16(%rsi,%rdx),%xmm4
mov $16,%rcx
0: add $16,%rcx
movdqu -32(%rsi,%rcx),%xmm3
movdqu %xmm3,-32(%rdi,%rcx)
cmp %rcx,%rdx
ja 0b
movdqu -16(%rsi,%rdx),%xmm3
movdqu %xmm3,-16(%rdi,%rdx)
xorps %xmm3,%xmm3
movdqu %xmm4,-16(%rdi,%rdx)
pxor %xmm4,%xmm4
pxor %xmm3,%xmm3
jmp .L0
.L8: push %rbx
mov (%rsi),%rcx
@ -134,10 +136,9 @@ _memcpy:.leafprologue
sfence
movdqu -16(%rsi,%rdx),%xmm3
movdqu %xmm3,-16(%rdi,%rdx)
xorps %xmm3,%xmm3
pxor %xmm3,%xmm3
jmp .L0
.endfn _memcpy,globl,hidden
.endfn memcpy,globl
.endfn MemCpy,globl,hidden
.initro 300,_init_memcpy
memcpytab.ro:

View file

@ -29,6 +29,7 @@
/ @param rdx is address of indirect branch
/ @param ecx is size of jump table
memjmpinit:
.leafprologue
setnz %r8b
shl %r8b
0: xor %eax,%eax
@ -44,6 +45,6 @@ memjmpinit:
add %rdx,%rax
stosq
lodsq
ret
.leafepilogue
.endfn memjmpinit,globl,hidden
.source __FILE__

View file

@ -28,10 +28,12 @@
/ @param rdx is number of bytes
/ @return original rdi copied to rax
/ @asyncsignalsafe
memmove:mov %rdi,%rax
memmove:
mov %rdi,%rax
/ 𝑠𝑙𝑖𝑑𝑒
.endfn MemMove,globl,hidden
_memmove:
MemMove:
.leafprologue
.profilable
push %rcx
@ -49,6 +51,5 @@ _memmove:
pop %rdi
pop %rcx
.leafepilogue
.endfn _memmove,globl,hidden
.endfn memmove,globl
.source __FILE__

View file

@ -18,6 +18,7 @@
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
/ Copies memory.
/
@ -27,7 +28,7 @@
/ @param rsi is src
/ @param rdx is number of bytes
/ @return original rdi + rdx copied to rax
mempcpy:lea (%rdi,%rdx),%rax
jmp _memcpy
mempcpy:
lea (%rdi,%rdx),%rax
jmp MemCpy
.endfn mempcpy,globl
.source __FILE__

View file

@ -36,6 +36,7 @@
/ @asyncsignalsafe
memset: mov %rdi,%rax
/ fallthrough
.endfn memset,globl
/ Sets memory w/ minimal-impact ABI.
/
@ -44,7 +45,7 @@ memset: mov %rdi,%rax
/ @param edx is the number of bytes to set
/ @clob flags,xmm3
/ @mode long
_memset:.leafprologue
MemSet: .leafprologue
.profilable
push %rbx
push %rcx
@ -64,7 +65,7 @@ _memset:.leafprologue
cmp %rcx,%rdx
ja 1b
vmovdqu %ymm3,-32(%rdi,%rdx)
vxorps %ymm3,%ymm3,%ymm3
vpxor %ymm3,%ymm3,%ymm3
jmp .L0
.L16r: cmp $1024,%rdx
jae .Lerms
@ -75,7 +76,7 @@ _memset:.leafprologue
cmp %rcx,%rdx
ja 1b
movdqu %xmm3,-16(%rdi,%rdx)
xorps %xmm3,%xmm3
pxor %xmm3,%xmm3
.L0: pop %rcx
pop %rbx
.leafepilogue
@ -103,8 +104,7 @@ _memset:.leafprologue
pop %rdi
pop %rax
jmp .L0
.endfn _memset,globl,hidden
.endfn memset,globl
.endfn MemSet,globl,hidden
.initro 300,_init_memset
memsettab.ro:

View file

@ -1,28 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bigword.h"
#include "libc/str/str.h"
#define wmemset memset16
#define T unsigned short
#define N (BIGWORD / sizeof(T))
#include "libc/nexgen32e/wmemset.inc"
#undef wmemset
#undef T
#undef N

View file

@ -8,14 +8,18 @@ void insertionsort(size_t n, int32_t[n]);
void *doublebytes(size_t, void *);
int64_t div10int64(int64_t) libcesque pureconst;
int64_t div100int64(int64_t) libcesque pureconst;
int64_t div1000int64(int64_t) libcesque pureconst;
int64_t div10000int64(int64_t) libcesque pureconst;
int64_t div1000000int64(int64_t) libcesque pureconst;
int64_t div1000000000int64(int64_t) libcesque pureconst;
int64_t mod10int64(int64_t) libcesque pureconst;
int64_t mod1000int64(int64_t) libcesque pureconst;
int64_t mod1000000int64(int64_t) libcesque pureconst;
int64_t mod1000000000int64(int64_t) libcesque pureconst;
int64_t rem10int64(int64_t) libcesque pureconst;
int64_t rem100int64(int64_t) libcesque pureconst;
int64_t rem1000int64(int64_t) libcesque pureconst;
int64_t rem10000int64(int64_t) libcesque pureconst;
int64_t rem1000000int64(int64_t) libcesque pureconst;
int64_t rem1000000000int64(int64_t) libcesque pureconst;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -1,66 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_NONTEMPORAL_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_NONTEMPORAL_H_
#include "libc/bits/emmintrin.h"
#include "libc/nexgen32e/x86feature.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define sfence() asm volatile("sfence" ::: "memory")
#define lfence() asm volatile("lfence" ::: "memory")
/**
* Stores memory asynchronously, e.g.
*
* for (i = 0; i < n; ++i)
* nontemporal_store(m[i], x);
* }
* sfence();
*
* @param MEM is an aligned xmm vector pointer
* @param REG is an xmm vector
* @return REG
*/
#define nontemporal_store(MEM, REG) \
_Generic((REG), __m128i \
: __movntdq, __m128 \
: __movntps, __m128d \
: __movntpd)(MEM, REG)
/**
* Loads memory asynchronously, e.g.
*
* x1 = nontemporal_load(m16[0]);
* x2 = nontemporal_load(m16[1]);
* x3 = nontemporal_load(m16[2]);
* x4 = nontemporal_load(m16[3]);
* lfence();
*
* @param REG is an xmm vector
* @param MEM is an aligned xmm vector pointer
* @return REG
*/
#define nontemporal_load(REG, MEM) __movntdqa(MEM)
#define __DECLARE_MOVNT(OS, TS) \
forceinline __m128##TS __movnt##OS(__m128##TS *mem, __m128##TS reg) { \
asm("movnt" #OS "\t%1,%0" : "=m"(*mem) : "x"(reg)); \
return reg; \
}
__DECLARE_MOVNT(ps, )
__DECLARE_MOVNT(dq, i)
__DECLARE_MOVNT(pd, d)
forceinline __m128i __movntdqa(const __m128i *mem) {
__m128i reg;
if (X86_HAVE(SSE4_1)) {
asm("movntdqa\t%1,%0" : "=x"(reg) : "m"(*mem));
} else {
asm("movdqa\t%1,%0" : "=x"(reg) : "m"(*mem));
}
return reg;
}
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_NONTEMPORAL_H_ */

View file

@ -22,8 +22,8 @@
/ Returns 𝑥 % 1,000,000,000.
/
/ @param rdi int64 𝑥
/ @return rax
mod1000000000int64:
/ @return rax has remainder
rem1000000000int64:
movabs $0x112e0be826d694b3,%rdx
mov %rdi,%rax
imul %rdx
@ -36,5 +36,5 @@ mod1000000000int64:
sub %rax,%rdi
mov %rdi,%rax
ret
.endfn mod1000000000int64,globl
.endfn rem1000000000int64,globl
.source __FILE__

View file

@ -19,7 +19,11 @@
*/
#include "libc/macros.h"
mod1000000int64:
/ Returns 𝑥 % 1,000,000.
/
/ @param rdi int64 𝑥
/ @return rax has remainder
rem1000000int64:
movabs $0x431bde82d7b634db,%rdx
mov %rdi,%rax
imul %rdx
@ -32,5 +36,5 @@ mod1000000int64:
sub %rax,%rdi
mov %rdi,%rax
ret
.endfn mod1000000int64,globl
.endfn rem1000000int64,globl
.source __FILE__

View file

@ -0,0 +1,40 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Returns 𝑥 % 10,000.
/
/ @param rdi int64 𝑥
/ @return rax has remainder
rem10000int64:
mov %rdi,%rax
movabsq $0x346dc5d63886594b,%rdx
imulq %rdx
mov %rdx,%rax
mov %rdi,%rdx
sar $11,%rax
sar $63,%rdx
sub %rdx,%rax
imulq $10000,%rax,%rax
sub %rax,%rdi
mov %rdi,%rax
ret
.endfn rem10000int64,globl
.source __FILE__

View file

@ -19,7 +19,11 @@
*/
#include "libc/macros.h"
mod1000int64:
/ Returns 𝑥 % 1,000.
/
/ @param rdi int64 𝑥
/ @return rax has remainder
rem1000int64:
movabs $0x20c49ba5e353f7cf,%rdx
mov %rdi,%rax
imul %rdx
@ -32,5 +36,5 @@ mod1000int64:
sub %rax,%rdi
mov %rdi,%rax
ret
.endfn mod1000int64,globl
.endfn rem1000int64,globl
.source __FILE__

View file

@ -0,0 +1,40 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Returns 𝑥 % 100.
/
/ @param rdi int64 𝑥
/ @return rax has remainder
rem100int64:
mov %rdi,%rax
movabsq $-6640827866535438581,%rdx
imul %rdx
lea (%rdx,%rdi),%rax
mov %rdi,%rdx
sar $6,%rax
sar $63,%rdx
sub %rdx,%rax
imul $100,%rax,%rax
sub %rax,%rdi
mov %rdi,%rax
ret
.endfn rem100int64,globl
.source __FILE__

View file

@ -19,7 +19,11 @@
*/
#include "libc/macros.h"
mod10int64:
/ Returns 𝑥 % 10.
/
/ @param rdi int64 𝑥
/ @return rax has remainder
rem10int64:
movabs $0x6666666666666667,%rdx
mov %rdi,%rax
imul %rdx
@ -33,5 +37,5 @@ mod10int64:
sub %rax,%rdi
mov %rdi,%rax
ret
.endfn mod10int64,globl
.endfn rem10int64,globl
.source __FILE__

24
libc/nexgen32e/slowcall.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_SLOWCALL_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_SLOWCALL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define slowcall(fn, arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
void *ax; \
asm volatile("push\t%7\n\t" \
"push\t%6\n\t" \
"push\t%5\n\t" \
"push\t%4\n\t" \
"push\t%3\n\t" \
"push\t%2\n\t" \
"push\t%1\n\t" \
"call\tslowcall" \
: "=a"(ax) \
: "g"(fn), "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), \
"g"(arg5), "g"(arg6) \
: "memory"); \
ax; \
})
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_SLOWCALL_H_ */

View file

@ -30,6 +30,7 @@ strtoupper:
mov $'A-'a,%edx # adding this uppers
mov $'a|'z<<8,%ecx # uint8_t range a..z
jmp strcaseconv
.endfn strtoupper,globl
/ Mutates string to lowercase roman characters.
/
@ -40,6 +41,7 @@ strtolower:
mov $'a-'A,%edx # adding this lowers
mov $'A|'Z<<8,%ecx # uint8_t range A..Z
/ 𝑠𝑙𝑖𝑑𝑒
.endfn strtolower,globl
/ Support code for strtolower() and strtoupper().
/
@ -64,16 +66,29 @@ strcaseconv:
test %al,%al # is it NUL?
jz 3f
cmp %cl,%al # is it in range?
jb 1b
jb 0b
cmp %ch,%al
ja 1b
ja 0b
add %dl,-1(%rsi)
jmp 1b
jmp 0b
.Lsse4: movd %ecx,%xmm1 # XMM1 = ['A,'Z,0,0,...]
movd %edx,%xmm2 # XMM2 = ['a-'A,'a-'A,...]
pbroadcastb %xmm2
xor %ecx,%ecx
2: movdqa (%rsi,%rcx),%xmm3
/ 0:index of the LEAST significant, set, bit is used
/ regardless of corresponding input element validity
/ intres2 is returned in least significant bits of xmm0
/ 1:index of the MOST significant, set, bit is used
/ regardless of corresponding input element validity
/ each bit of intres2 is expanded to byte/word
/ 0:negation of intres1 is for all 16 (8) bits
/ 1:negation of intres1 is masked by reg/mem validity
/ intres1 is negated (1s complement)
/ mode{equalany,ranges,equaleach,equalordered}
/ issigned
/ is16bit
/ u
pcmpistrm $0b01000100,%xmm3,%xmm1 # XMM0 8-bit byte mask
pand %xmm2,%xmm0 # won't mask after NUL
paddb %xmm0,%xmm3
@ -83,6 +98,4 @@ strcaseconv:
3: mov %rdi,%rax
.leafepilogue
.endfn strcaseconv
.endfn strtolower,globl
.endfn strtoupper,globl
.source __FILE__

View file

@ -43,7 +43,7 @@ strncmp$avx:
cmp %rsi,%rdi
je 1f
mov $-16,%rcx
vxorps %xmm0,%xmm0,%xmm0
vpxor %xmm0,%xmm0,%xmm0
vpcmpeqd %xmm1,%xmm1,%xmm1
3: add $16,%rcx
4: lea 16(%rcx),%rax

View file

@ -1,36 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h"
/**
* Returns prefix length, consisting of chars not in reject.
* a.k.a. Return index of first byte that's in charset.
* @asyncsignalsafe
*/
size_t(strcspn)(const char *s, const char *reject) {
size_t i;
for (i = 0; s[i]; ++i) {
if (HasCharacter(s[i], reject)) {
break;
}
}
return i;
}

View file

@ -1,28 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h"
#undef strcspn
#define char char16_t
#define HasCharacter HasCharacter16
#define strcspn strcspn16
#include "libc/nexgen32e/strcspn.c"

View file

@ -1,41 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h"
/**
* Returns pointer to first byte matching any in accept, or NULL.
* @asyncsignalsafe
*/
char *(strpbrk)(const char *s, const char *accept) {
size_t i;
if (accept[0]) {
if (!accept[1]) {
return strchr(s, accept[0]);
} else {
for (i = 0; s[i]; ++i) {
if (HasCharacter(s[i], accept)) {
return (/*unconst*/ char *)&s[i];
}
}
}
}
return NULL;
}

View file

@ -1,28 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h"
#undef strpbrk
#define char char16_t
#define HasCharacter HasCharacter16
#define strpbrk strpbrk16
#include "libc/nexgen32e/strpbrk.c"

View file

@ -18,6 +18,7 @@
02110-1301 USA
*/
#include "libc/nexgen32e/x86feature.h"
#include "libc/nexgen32e/macros.h"
#include "libc/macros.h"
.source __FILE__
@ -32,6 +33,7 @@ strchrnul:
.profilable
or $-1,%r9
jmp 0f
.endfn strchrnul,globl
/ Returns pointer to first instance of character, the BSD way.
/
@ -41,6 +43,7 @@ strchrnul:
/ @note this won't return NULL if search character is NUL
index: nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn index,globl
/ Returns pointer to first instance of character.
/
@ -56,6 +59,7 @@ strchr: .leafprologue
or $-1,%rsi
xor %r8,%r8
jmp strsak
.endfn strchr,globl
/ Returns pointer to first instance of character in range.
/
@ -65,6 +69,7 @@ strchr: .leafprologue
rawmemchr:
or $-1,%rdx
/ 𝑠𝑙𝑖𝑑𝑒
.endfn rawmemchr,globl
/ Returns pointer to first instance of character in range.
/
@ -80,6 +85,7 @@ memchr: .leafprologue
xor %r8,%r8
xor %r10,%r10
jmp strsak
.endfn memchr,globl
/ Returns length of NUL-terminated string w/ security blankets.
/
@ -97,6 +103,7 @@ strnlen_s:
test %rdi,%rdi
jnz 0f
.leafepilogue
.endfn strnlen_s,globl
/ Returns length of NUL-terminated string.
/
@ -105,6 +112,7 @@ strnlen_s:
/ @asyncsignalsafe
strlen: or $-1,%rsi
/ 𝑠𝑙𝑖𝑑𝑒
.endfn strlen,globl
/ Returns length of NUL-terminated memory, with limit.
/
@ -118,6 +126,7 @@ strnlen:.leafprologue
0: xor %edx,%edx
mov %rdi,%r8
/ 𝑠𝑙𝑖𝑑𝑒
.endfn strnlen,globl
/ Swiss army knife of string character scanning.
/ Sixteen fast functions in one.
@ -175,12 +184,8 @@ strsak: lea -1(%rdi),%rax
2: add %rcx,%rax
jmp .Lbyte
#if !X86_NEED(AVX2)
.Lsse2: punpcklbw %xmm0,%xmm0
pshuflw $0xe0,%xmm0,%xmm0
pshufd $0x00,%xmm0,%xmm0
punpcklbw %xmm1,%xmm1
pshuflw $0xe0,%xmm1,%xmm1
pshufd $0x00,%xmm1,%xmm1
.Lsse2: pbroadcastb %xmm0
pbroadcastb %xmm1
1: add $32,%rax
sub $32,%rsi
jb 9b
@ -203,14 +208,6 @@ strsak: lea -1(%rdi),%rax
jmp 2b
#endif
.endfn strsak,globl,hidden
.endfn strnlen,globl
.endfn strlen,globl
.endfn strnlen_s,globl
.endfn memchr,globl
.endfn rawmemchr,globl
.endfn strchr,globl
.endfn index,globl
.endfn strchrnul,globl
/* benchmarked on intel core i7-6700 @ 3.40GHz (skylake)
includes function call overhead (unless marked otherwise)

View file

@ -1,35 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h"
/**
* Returns prefix length, consisting of chars in accept.
* @asyncsignalsafe
*/
size_t(strspn)(const char *s, const char *accept) {
size_t i;
for (i = 0; s[i]; ++i) {
if (!HasCharacter(s[i], accept)) {
break;
}
}
return i;
}

View file

@ -1,28 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h"
#undef strspn
#define char char16_t
#define HasCharacter HasCharacter16
#define strspn strspn16
#include "libc/nexgen32e/strspn.c"

View file

@ -1,63 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.text.windows
/ Epilogues for calling functions w/ Microsoft x64 convention.
/
/ @param %rax is address of windows x64 function to call
/ @param %rsi is ignored
/ @param %rdx,%rcx,%r8,%r9,stack are params (unlimited)
/ @param %xmm0,%xmm1,%xmm2 are double params (limited to 3)
/ @return is in %rax, %xmm0, or %st
/ @note GCC 4.8+ and Clang can avoid this indirection
/ @note thunk that jumps here must setup frame
/ @note this is so much faster than nt2sysv()
__sysv2nt14:
pushq 72(%rbp)
pushq 64(%rbp)
__sysv2nt12:
pushq 56(%rbp)
pushq 48(%rbp)
__sysv2nt10:
pushq 40(%rbp)
pushq 32(%rbp)
__sysv2nt8:
pushq 24(%rbp)
pushq 16(%rbp)
__sysv2nt6:
push %r9
push %r8
__sysv2nt:
mov %rdx,%r8
mov %rcx,%r9
mov %rdi,%rcx
mov %rsi,%rdx
sub $32,%rsp
call *%rax
leave
ret
.endfn __sysv2nt,globl,hidden
.endfn __sysv2nt6,globl,hidden
.endfn __sysv2nt8,globl,hidden
.endfn __sysv2nt10,globl,hidden
.endfn __sysv2nt12,globl,hidden
.endfn __sysv2nt14,globl,hidden
.source __FILE__

View file

@ -21,17 +21,22 @@
/ Support code for fast integer division by Si units.
/
/ Division by magnums is described in Hacker's Delight and is
/ usually generated automatically by compilers, but sadly not
/ when we optimize for size and idiv goes at least 10x slower
/ so we do this which saves space while avoiding build tuning
/
/ @param rdi is number to divide
/ @param cl is magnum #1
/ @param rdx is magnum #2
/ @return truncated numerator
/ @return quotient
tinydivsi:
.leafprologue
mov %rdi,%rax
imul %rdx
mov %rdx,%rax
sar %cl,%rax
sar $0x3f,%rdi
sar $63,%rdi
sub %rdi,%rax
.leafepilogue
.endfn tinydivsi,globl

View file

@ -19,7 +19,7 @@
*/
#include "libc/macros.h"
/ Compares NUL-terminated strings w/o heavy-lifting.
/ Compares strings w/ no-clobber greg abi.
/
/ @param rdi is first non-null NUL-terminated string pointer
/ @param rsi is second non-null NUL-terminated string pointer
@ -30,7 +30,11 @@ tinystrcmp:
.leafprologue
push %rcx
push %rdx
xor %eax,%eax
xor %edx,%edx
xor %ecx,%ecx
cmp %rdi,%rsi
je 1f
0: movzbl (%rdi,%rcx,1),%eax
movzbl (%rsi,%rcx,1),%edx
test %al,%al

View file

@ -1,6 +1,16 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRLEN_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRLEN_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
int tinystrlen(const char *);
int tinystrnlen(const char *, size_t);
int tinystrlen16(const char16_t *);
int tinystrnlen16(const char16_t *, size_t);
int tinywcslen(const wchar_t *);
int tinywcsnlen(const wchar_t *, size_t);
#else
forceinline int tinystrlen(const char *s) {
unsigned ax;
@ -40,5 +50,6 @@ forceinline int tinywcsnlen(const wchar_t *s, size_t n) {
return ax;
}
#endif
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRLEN_H_ */

View file

@ -0,0 +1,56 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
/ Compares strings w/ limit & no-clobber greg abi.
/
/ @param %rdi is first string
/ @param %rsi is second string
/ @param %rdx is max length
/ @return <0, 0, or >0 depending on comparison
/ @clob flags only
/ @asyncsignalsafe
tinystrncmp:
.leafprologue
push %rbx
push %rcx
xor %eax,%eax
xor %ebx,%ebx
xor %ecx,%ecx
test %edx,%edx
jz 2f
cmp %rdi,%rsi
je 2f
0: cmp %edx,%ecx
jae 1f
movzbl (%rdi,%rcx,1),%eax
movzbl (%rsi,%rcx,1),%ebx
test %al,%al
jz 1f
cmp %bl,%al
jne 1f
inc %ecx
jmp 0b
1: sub %ebx,%eax
2: pop %rcx
pop %rbx
.leafepilogue
.endfn tinystrncmp,globl
.source __FILE__

View file

@ -1,35 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/limits.h"
#include "libc/nexgen32e/tinystrcmp.h"
/**
* Compares strings w/ limit & no-clobber abi guarantee.
*/
int(tinystrncmp)(const char *s1, const char *s2, size_t n) {
size_t i;
if (!n) return 0;
i = SIZE_MAX;
while (s1[++i]) {
if (s1[i] != s2[i]) break;
if (!--n) break;
}
return (int)(unsigned char)s1[i] - (int)(unsigned char)s2[i];
}

View file

@ -9,6 +9,7 @@
*
* GenuineIntel
* AuthenticAMD
* GenuineCosmo
* NexGenDriven
* AMDisbetter!
* CentaurHauls
@ -27,6 +28,7 @@
*
* G t = 0x33 Intel
* A A = 0x00 AMD
* G s = 0x34 Cosmopolitan
* N v = 0x38 NexGen (Modern x86)
* A e = 0x24 AMD (Rank & File)
* C u = 0x36 Via (DBA Centaur)
@ -53,10 +55,11 @@
*/
#define IsAuthenticAMD() (_KCPUIDS_VENDOR() == 0x00)
#define IsGenuineIntel() (_KCPUIDS_VENDOR() == 0x33)
#define IsGenuineCosmo() (_KCPUIDS_VENDOR() == 0x34)
#define _KCPUIDS_VENDOR() \
(((kCpuids[KCPUIDS_0][KCPUIDS_EBX] >> 000) & 0xff) ^ \
((kCpuids[KCPUIDS_0][KCPUIDS_ECX] >> 010) & 0xff))
#define _KCPUIDS_VENDOR() \
(((kCpuids[KCPUIDS_0H][KCPUIDS_EBX] >> 000) & 0xff) ^ \
((kCpuids[KCPUIDS_0H][KCPUIDS_EDX] >> 010) & 0xff))
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_VENDOR_H_ */

View file

@ -1,28 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h"
#undef strcspn
#define char wchar_t
#define HasCharacter HasCharacterWide
#define strcspn wcscspn
#include "libc/nexgen32e/strcspn.c"

View file

@ -1,28 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h"
#undef strpbrk
#define char wchar_t
#define HasCharacter HasCharacterWide
#define strpbrk wcspbrk
#include "libc/nexgen32e/strpbrk.c"

View file

@ -1,28 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h"
#undef strspn
#define char wchar_t
#define HasCharacter HasCharacterWide
#define strspn wcsspn
#include "libc/nexgen32e/strspn.c"

View file

@ -1,26 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bigword.h"
#include "libc/str/str.h"
#define T wchar_t
#define N (BIGWORD / sizeof(T))
#include "libc/nexgen32e/wmemset.inc"
#undef T
#undef N

View file

@ -72,6 +72,7 @@
#define X86_INVPCID 1H, EBX, 10, 0, _
#define X86_INVTSC 80000007H, EDX, 8, _X86_CC_POPCNT, _ /* i.e. not a K8 */
#define X86_LA57 7H, ECX, 16, 0, _
#define X86_LAHF_LM 80000001H, ECX, 0, 0, _
#define X86_LM 80000001H, EDX, 29, 0, _
#define X86_MCA 1H, EDX, 14, 0, _
#define X86_MCE 1H, EDX, 7, 0, _
@ -153,7 +154,6 @@
#define X86_FMA4 80000001H, ECX, 16, 0, _
#define X86_FXSR_OPT 80000001H, EDX, 25, 0, _
#define X86_IBS 80000001H, ECX, 10, 0, _
#define X86_LAHF_LM 80000001H, ECX, 0, 0, _
#define X86_LWP 80000001H, ECX, 15, 0, _
#define X86_MISALIGNSSE 80000001H, ECX, 7, 0, _
#define X86_MMXEXT 80000001H, EDX, 22, 0, _