cosmopolitan/third_party/compiler_rt/divmodti4.c
Justine Tunney f4f4caab0e 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
2020-08-25 04:43:42 -07:00

64 lines
2.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to division, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "third_party/compiler_rt/int_lib.h"
/**
* Divides 128-bit signed integers w/ remainder.
*
* @param a is numerator
* @param b is denominator
* @param opt_out_rem receives euclidean division remainder if not null
* @return quotient or result of division
* @note rounds towards zero
*/
COMPILER_RT_ABI ti_int __divmodti4(ti_int a, ti_int b, tu_int *opt_out_rem) {
int k;
tu_int r;
ti_int sa, sb, sq, sr, x, y, q;
k = sizeof(ti_int) * CHAR_BIT - 1;
if (b < 0 && a == ((ti_int)1 << k)) {
volatile int x = 0;
x = 1 / x; // raise(SIGFPE)
}
sa = a >> k; // sa = a < 0 ? -1 : 0
sb = b >> k; // sb = b < 0 ? -1 : 0
x = (a ^ sa) - sa; // negate if sa == -1
y = (b ^ sb) - sb; // negate if sb == -1
sq = sa ^ sb; // sign of quotient
sr = sa; // sign of remainder
q = __udivmodti4(x, y, &r); // unsigned divide
q = (q ^ sq) - sq; // fix quotient sign
r = (r ^ sr) - sr; // fix remainder sign
if (opt_out_rem) *opt_out_rem = r;
return q;
}
/*
Intel Kabylake i9-9900 @ 3.10GHz Client Grade
idiv32 l: 27𝑐 9𝑛𝑠
idiv64 l: 27𝑐 9𝑛𝑠
divmodti4 small / small l: 42𝑐 14𝑛𝑠
divmodti4 small / large l: 14𝑐 5𝑛𝑠
divmodti4 large / small l: 92𝑐 30𝑛𝑠
divmodti4 large / large l: 209𝑐 68𝑛𝑠
Intel Kabylake i3-8100 @ 3.60GHz Client Grade
idiv32 l: 51𝑐 14𝑛𝑠
idiv64 l: 51𝑐 14𝑛𝑠
divmodti4 small / small l: 83𝑐 23𝑛𝑠
divmodti4 small / large l: 26𝑐 7𝑛𝑠
divmodti4 large / small l: 175𝑐 48𝑛𝑠
divmodti4 large / large l: 389𝑐 107𝑛𝑠
*/