Add 'lib/runtime/' from commit 'db5cddbec10c4b7c086eda716d48d4711632901f'

git-subtree-dir: lib/runtime
git-subtree-mainline: 566a2341f5b726d86f5d42a72beb9c70b83f31b6
git-subtree-split: db5cddbec10c4b7c086eda716d48d4711632901f
This commit is contained in:
Mark Poliakov 2024-03-12 15:54:48 +02:00
commit 7a0d528cda
26 changed files with 1257 additions and 0 deletions

2
lib/runtime/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/Cargo.lock

32
lib/runtime/Cargo.toml Normal file
View File

@ -0,0 +1,32 @@
[package]
name = "yggdrasil-rt"
version = "0.1.0"
edition = "2021"
authors = ["Mark Poliakov <mark@alnyan.me>"]
build = "build.rs"
[dependencies]
yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" }
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" }
compiler_builtins = { version = "0.1", optional = true }
abi-lib = { git = "https://git.alnyan.me/yggdrasil/abi-generator.git" }
[build-dependencies]
abi-generator = { git = "https://git.alnyan.me/yggdrasil/abi-generator.git" }
yggdrasil-abi-def = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi-def.git" }
prettyplease = "0.2.15"
cc = "*"
[features]
default = []
alloc = ["dep:alloc", "yggdrasil-abi/alloc"]
rustc-dep-of-std = [
"core",
"alloc",
"compiler_builtins/rustc-dep-of-std",
"yggdrasil-abi/rustc-dep-of-std",
"abi-lib/rustc-dep-of-std"
]

65
lib/runtime/build.rs Normal file
View File

@ -0,0 +1,65 @@
use std::{fs, path::Path};
use abi_generator::{
abi::{ty::TypeWidth, AbiBuilder},
syntax::UnwrapFancy,
TargetEnv,
};
fn add_file<'a>(build: &'a mut cc::Build, name: &'a str) -> &'a mut cc::Build {
println!("cargo:rerun-if-changed={}", name);
build.file(name)
}
fn build_libm() {
println!("cargo:rerun-if-changed=libm/private.h");
let mut build = cc::Build::new();
build
.compiler("clang")
.flag("-ffreestanding")
.flag("-nostdlib");
add_file(&mut build, "libm/s_truncf.c");
add_file(&mut build, "libm/s_ceilf.c");
add_file(&mut build, "libm/s_floorf.c");
add_file(&mut build, "libm/s_fabsf.c");
add_file(&mut build, "libm/s_scalbnf.c");
add_file(&mut build, "libm/s_copysignf.c");
add_file(&mut build, "libm/e_powf.c");
add_file(&mut build, "libm/e_sqrtf.c");
add_file(&mut build, "libm/e_hypotf.c");
add_file(&mut build, "libm/e_fmodf.c");
add_file(&mut build, "libm/w_powf.c");
add_file(&mut build, "libm/w_hypotf.c");
add_file(&mut build, "libm/w_fmodf.c");
build.compile("m");
}
fn generate_abi() {
let output_dir = std::env::var("OUT_DIR").expect("$OUT_DIR not set");
let generated_calls = Path::new(&output_dir).join("generated_calls.rs");
let abi = AbiBuilder::from_string(
yggdrasil_abi_def::ABI_FILE,
TargetEnv {
thin_pointer_width: TypeWidth::U64,
fat_pointer_width: TypeWidth::U64,
},
)
.unwrap_fancy("Could not parse/read ABI file");
let calls = prettyplease::unparse(
&abi.emit_file(false, true)
.unwrap_fancy("Could not emit system calls"),
);
fs::write(generated_calls, calls).unwrap();
}
fn main() {
build_libm();
generate_abi();
}

View File

@ -0,0 +1,81 @@
#include <stdint.h>
#include "private.h"
static const float one = 1.0, Zero[] = {0.0, -0.0,};
float
__ieee754_fmodf(float x, float y)
{
int32_t n,hx,hy,hz,ix,iy,sx,i;
GET_FLOAT_WORD(hx,x);
GET_FLOAT_WORD(hy,y);
sx = hx&0x80000000; /* sign of x */
hx ^=sx; /* |x| */
hy &= 0x7fffffff; /* |y| */
/* purge off exception values */
if(hy==0||(hx>=0x7f800000)|| /* y=0,or x not finite */
(hy>0x7f800000)) /* or y is NaN */
return (x*y)/(x*y);
if(hx<hy) return x; /* |x|<|y| return x */
if(hx==hy)
return Zero[(uint32_t)sx>>31]; /* |x|=|y| return x*0*/
/* determine ix = ilogb(x) */
if(hx<0x00800000) { /* subnormal x */
for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1;
} else ix = (hx>>23)-127;
/* determine iy = ilogb(y) */
if(hy<0x00800000) { /* subnormal y */
for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1;
} else iy = (hy>>23)-127;
/* set up {hx,lx}, {hy,ly} and align y to x */
if(ix >= -126)
hx = 0x00800000|(0x007fffff&hx);
else { /* subnormal x, shift x to normal */
n = -126-ix;
hx = hx<<n;
}
if(iy >= -126)
hy = 0x00800000|(0x007fffff&hy);
else { /* subnormal y, shift y to normal */
n = -126-iy;
hy = hy<<n;
}
/* fix point fmod */
n = ix - iy;
while(n--) {
hz=hx-hy;
if(hz<0){hx = hx+hx;}
else {
if(hz==0) /* return sign(x)*0 */
return Zero[(uint32_t)sx>>31];
hx = hz+hz;
}
}
hz=hx-hy;
if(hz>=0) {hx=hz;}
/* convert back to floating value and restore the sign */
if(hx==0) /* return sign(x)*0 */
return Zero[(uint32_t)sx>>31];
while(hx<0x00800000) { /* normalize x */
hx = hx+hx;
iy -= 1;
}
if(iy>= -126) { /* normalize output */
hx = ((hx-0x00800000)|((iy+127)<<23));
SET_FLOAT_WORD(x,hx|sx);
} else { /* subnormal output */
n = -126 - iy;
hx >>= n;
SET_FLOAT_WORD(x,hx|sx);
x *= one; /* create necessary signal */
}
return x; /* exact output */
}

View File

@ -0,0 +1,65 @@
#include <stdint.h>
#include "private.h"
float
__ieee754_hypotf(float x, float y)
{
float a=x,b=y,t1,t2,yy1,y2,w;
int32_t j,k,ha,hb;
GET_FLOAT_WORD(ha,x);
ha &= 0x7fffffff;
GET_FLOAT_WORD(hb,y);
hb &= 0x7fffffff;
if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
SET_FLOAT_WORD(a,ha); /* a <- |a| */
SET_FLOAT_WORD(b,hb); /* b <- |b| */
if((ha-hb)>0xf000000) {return a+b;} /* x/y > 2**30 */
k=0;
if(ha > 0x58800000) { /* a>2**50 */
if(ha >= 0x7f800000) { /* Inf or NaN */
w = a+b; /* for sNaN */
if(ha == 0x7f800000) w = a;
if(hb == 0x7f800000) w = b;
return w;
}
/* scale a and b by 2**-60 */
ha -= 0x5d800000; hb -= 0x5d800000; k += 60;
SET_FLOAT_WORD(a,ha);
SET_FLOAT_WORD(b,hb);
}
if(hb < 0x26800000) { /* b < 2**-50 */
if(hb <= 0x007fffff) { /* subnormal b or 0 */
if(hb==0) return a;
SET_FLOAT_WORD(t1,0x3f000000); /* t1=2^126 */
b *= t1;
a *= t1;
k -= 126;
} else { /* scale a and b by 2^60 */
ha += 0x5d800000; /* a *= 2^60 */
hb += 0x5d800000; /* b *= 2^60 */
k -= 60;
SET_FLOAT_WORD(a,ha);
SET_FLOAT_WORD(b,hb);
}
}
/* medium size a and b */
w = a-b;
if (w>b) {
SET_FLOAT_WORD(t1,ha&0xfffff000);
t2 = a-t1;
w = __ieee754_sqrtf(t1*t1-(b*(-b)-t2*(a+t1)));
} else {
a = a+a;
SET_FLOAT_WORD(yy1,hb&0xfffff000);
y2 = b - yy1;
SET_FLOAT_WORD(t1,ha+0x00800000);
t2 = a - t1;
w = __ieee754_sqrtf(t1*yy1-(w*(-w)-(t1*y2+t2*b)));
}
if(k!=0) {
SET_FLOAT_WORD(t1,0x3f800000+(k<<23));
return t1*w;
} else return w;
}

227
lib/runtime/libm/e_powf.c Normal file
View File

@ -0,0 +1,227 @@
#include <stdint.h>
#include "private.h"
static const float huge = 1.0e+30, tiny = 1.0e-30;
static const float
bp[] = {1.0, 1.5,},
dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */
dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */
zero = 0.0,
one = 1.0,
two = 2.0,
two24 = 16777216.0, /* 0x4b800000 */
/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
L1 = 6.0000002384e-01, /* 0x3f19999a */
L2 = 4.2857143283e-01, /* 0x3edb6db7 */
L3 = 3.3333334327e-01, /* 0x3eaaaaab */
L4 = 2.7272811532e-01, /* 0x3e8ba305 */
L5 = 2.3066075146e-01, /* 0x3e6c3255 */
L6 = 2.0697501302e-01, /* 0x3e53f142 */
P1 = 1.6666667163e-01, /* 0x3e2aaaab */
P2 = -2.7777778450e-03, /* 0xbb360b61 */
P3 = 6.6137559770e-05, /* 0x388ab355 */
P4 = -1.6533901999e-06, /* 0xb5ddea0e */
P5 = 4.1381369442e-08, /* 0x3331bb4c */
lg2 = 6.9314718246e-01, /* 0x3f317218 */
lg2_h = 6.93145752e-01, /* 0x3f317200 */
lg2_l = 1.42860654e-06, /* 0x35bfbe8c */
ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */
cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */
cp_h = 9.6179199219e-01, /* 0x3f763800 =head of cp */
cp_l = 4.7017383622e-06, /* 0x369dc3a0 =tail of cp_h */
ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */
ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/
ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
float
__ieee754_powf(float x, float y)
{
float z,ax,z_h,z_l,p_h,p_l;
float yy1,t1,t2,r,s,t,u,v,w;
int32_t i,j,k,yisint,n;
int32_t hx,hy,ix,iy,is;
GET_FLOAT_WORD(hx,x);
GET_FLOAT_WORD(hy,y);
ix = hx&0x7fffffff; iy = hy&0x7fffffff;
/* y==zero: x**0 = 1 */
if(iy==0) return one;
/* +-NaN return x+y */
if(ix > 0x7f800000 ||
iy > 0x7f800000)
return x+y;
/* determine if y is an odd int when x < 0
* yisint = 0 ... y is not an integer
* yisint = 1 ... y is an odd int
* yisint = 2 ... y is an even int
*/
yisint = 0;
if(hx<0) {
if(iy>=0x4b800000) yisint = 2; /* even integer y */
else if(iy>=0x3f800000) {
k = (iy>>23)-0x7f; /* exponent */
j = iy>>(23-k);
if((j<<(23-k))==iy) yisint = 2-(j&1);
}
}
/* special value of y */
if (iy==0x7f800000) { /* y is +-inf */
if (ix==0x3f800000)
return y - y; /* inf**+-1 is NaN */
else if (ix > 0x3f800000)/* (|x|>1)**+-inf = inf,0 */
return (hy>=0)? y: zero;
else /* (|x|<1)**-,+inf = inf,0 */
return (hy<0)?-y: zero;
}
if(iy==0x3f800000) { /* y is +-1 */
if(hy<0) return one/x; else return x;
}
if(hy==0x40000000) return x*x; /* y is 2 */
if(hy==0x3f000000) { /* y is 0.5 */
if(hx>=0) /* x >= +0 */
return __ieee754_sqrtf(x);
}
ax = fabsf(x);
/* special value of x */
if(ix==0x7f800000||ix==0||ix==0x3f800000){
z = ax; /*x is +-0,+-inf,+-1*/
if(hy<0) z = one/z; /* z = (1/|x|) */
if(hx<0) {
if(((ix-0x3f800000)|yisint)==0) {
z = (z-z)/(z-z); /* (-1)**non-int is NaN */
} else if(yisint==1)
z = -z; /* (x<0)**odd = -(|x|**odd) */
}
return z;
}
/* (x<0)**(non-int) is NaN */
if(((((uint32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x);
/* |y| is huge */
if(iy>0x4d000000) { /* if |y| > 2**27 */
/* over/underflow if x is not close to one */
if(ix<0x3f7ffff8) return (hy<0)? huge*huge:tiny*tiny;
if(ix>0x3f800007) return (hy>0)? huge*huge:tiny*tiny;
/* now |1-x| is tiny <= 2**-20, suffice to compute
log(x) by x-x^2/2+x^3/3-x^4/4 */
t = ax-one; /* t has 20 trailing zeros */
w = (t*t)*((float)0.5-t*((float)0.333333333333-t*(float)0.25));
u = ivln2_h*t; /* ivln2_h has 16 sig. bits */
v = t*ivln2_l-w*ivln2;
t1 = u+v;
GET_FLOAT_WORD(is,t1);
SET_FLOAT_WORD(t1,is&0xfffff000);
t2 = v-(t1-u);
} else {
float s2,s_h,s_l,t_h,t_l;
n = 0;
/* take care subnormal number */
if(ix<0x00800000)
{ax *= two24; n -= 24; GET_FLOAT_WORD(ix,ax); }
n += ((ix)>>23)-0x7f;
j = ix&0x007fffff;
/* determine interval */
ix = j|0x3f800000; /* normalize ix */
if(j<=0x1cc471) k=0; /* |x|<sqrt(3/2) */
else if(j<0x5db3d7) k=1; /* |x|<sqrt(3) */
else {k=0;n+=1;ix -= 0x00800000;}
SET_FLOAT_WORD(ax,ix);
/* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
v = one/(ax+bp[k]);
s = u*v;
s_h = s;
GET_FLOAT_WORD(is,s_h);
SET_FLOAT_WORD(s_h,is&0xfffff000);
/* t_h=ax+bp[k] High */
SET_FLOAT_WORD(t_h,((ix>>1)|0x20000000)+0x0040000+(k<<21));
t_l = ax - (t_h-bp[k]);
s_l = v*((u-s_h*t_h)-s_h*t_l);
/* compute log(ax) */
s2 = s*s;
r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
r += s_l*(s_h+s);
s2 = s_h*s_h;
t_h = (float)3.0+s2+r;
GET_FLOAT_WORD(is,t_h);
SET_FLOAT_WORD(t_h,is&0xfffff000);
t_l = r-((t_h-(float)3.0)-s2);
/* u+v = s*(1+...) */
u = s_h*t_h;
v = s_l*t_h+t_l*s;
/* 2/(3log2)*(s+...) */
p_h = u+v;
GET_FLOAT_WORD(is,p_h);
SET_FLOAT_WORD(p_h,is&0xfffff000);
p_l = v-(p_h-u);
z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
z_l = cp_l*p_h+p_l*cp+dp_l[k];
/* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
t = (float)n;
t1 = (((z_h+z_l)+dp_h[k])+t);
GET_FLOAT_WORD(is,t1);
SET_FLOAT_WORD(t1,is&0xfffff000);
t2 = z_l-(((t1-t)-dp_h[k])-z_h);
}
s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
if(((((uint32_t)hx>>31)-1)|(yisint-1))==0)
s = -one; /* (-ve)**(odd int) */
/* split up y into yy1+y2 and compute (yy1+y2)*(t1+t2) */
GET_FLOAT_WORD(is,y);
SET_FLOAT_WORD(yy1,is&0xfffff000);
p_l = (y-yy1)*t1+y*t2;
p_h = yy1*t1;
z = p_l+p_h;
GET_FLOAT_WORD(j,z);
if (j>0x43000000) /* if z > 128 */
return s*huge*huge; /* overflow */
else if (j==0x43000000) { /* if z == 128 */
if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
}
else if ((uint32_t)j==0xc3160000){ /* z == -150 */
if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
}
else if ((j&0x7fffffff)>0x43160000) /* z <= -150 */
return s*tiny*tiny; /* underflow */
/*
* compute 2**(p_h+p_l)
*/
i = j&0x7fffffff;
k = (i>>23)-0x7f;
n = 0;
if(i>0x3f000000) { /* if |z| > 0.5, set n = [z+0.5] */
n = j+(0x00800000>>(k+1));
k = ((n&0x7fffffff)>>23)-0x7f; /* new k for n */
SET_FLOAT_WORD(t,n&~(0x007fffff>>k));
n = ((n&0x007fffff)|0x00800000)>>(23-k);
if(j<0) n = -n;
p_h -= t;
}
t = p_l+p_h;
GET_FLOAT_WORD(is,t);
SET_FLOAT_WORD(t,is&0xfffff000);
u = t*lg2_h;
v = (p_l-(t-p_h))*lg2+t*lg2_l;
z = u+v;
w = v-(z-u);
t = z*z;
t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
r = (z*t1)/(t1-two)-(w+z*w);
z = one-(r-z);
GET_FLOAT_WORD(j,z);
j = (int32_t)((uint32_t)j + ((uint32_t)n<<23));
if((j>>23)<=0) z = scalbnf(z,n); /* subnormal output */
else SET_FLOAT_WORD(z,j);
return s*z;
}

View File

@ -0,0 +1,71 @@
#include <stdint.h>
#include "private.h"
static const float one = 1.0, tiny=1.0e-30;
float
__ieee754_sqrtf(float x)
{
float z;
int32_t sign = (int)0x80000000;
int32_t ix,s,q,m,t,i;
uint32_t r;
GET_FLOAT_WORD(ix,x);
/* take care of Inf and NaN */
if((ix&0x7f800000)==0x7f800000) {
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
sqrt(-inf)=sNaN */
}
/* take care of zero */
if(ix<=0) {
if((ix&(~sign))==0) return x;/* sqrt(+-0) = +-0 */
else if(ix<0)
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
}
/* normalize x */
m = (ix>>23);
if(m==0) { /* subnormal x */
for(i=0;(ix&0x00800000)==0;i++) ix<<=1;
m -= i-1;
}
m -= 127; /* unbias exponent */
ix = (ix&0x007fffff)|0x00800000;
if(m&1) /* odd m, double x to make it even */
ix += ix;
m >>= 1; /* m = [m/2] */
/* generate sqrt(x) bit by bit */
ix += ix;
q = s = 0; /* q = sqrt(x) */
r = 0x01000000; /* r = moving bit from right to left */
while(r!=0) {
t = s+r;
if(t<=ix) {
s = t+r;
ix -= t;
q += r;
}
ix += ix;
r>>=1;
}
/* use floating add to find out rounding direction */
if(ix!=0) {
z = one-tiny; /* trigger inexact flag */
if (z>=one) {
z = one+tiny;
if (z>one)
q += 2;
else
q += (q&1);
}
}
ix = (q>>1)+0x3f000000;
ix += (m <<23);
SET_FLOAT_WORD(z,ix);
return z;
}

View File

@ -0,0 +1,34 @@
#pragma once
typedef union
{
float value;
uint32_t word;
} ieee_float_shape_type;
/* Get a 32 bit int from a float. */
#define GET_FLOAT_WORD(i,d) \
do { \
ieee_float_shape_type gf_u; \
gf_u.value = (d); \
(i) = gf_u.word; \
} while (/*CONSTCOND*/0)
/* Set a float from a 32 bit int. */
#define SET_FLOAT_WORD(d,i) \
do { \
ieee_float_shape_type sf_u; \
sf_u.word = (i); \
(d) = sf_u.value; \
} while (/*CONSTCOND*/0)
float __ieee754_sqrtf(float x);
float __ieee754_powf(float x, float y);
float __ieee754_hypotf(float x, float y);
float __ieee754_fmodf(float x, float y);
float scalbnf(float x, int n);
float copysignf(float x, float y);
float fabsf(float x);

View File

@ -0,0 +1,35 @@
#include <stdint.h>
#include "private.h"
static const float huge = 1.0e30;
float
ceilf(float x)
{
int32_t i0,jj0;
uint32_t i;
GET_FLOAT_WORD(i0,x);
jj0 = ((i0>>23)&0xff)-0x7f;
if(jj0<23) {
if(jj0<0) { /* raise inexact if x != 0 */
if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
if(i0<0) {i0=0x80000000;}
else if(i0!=0) { i0=0x3f800000;}
}
} else {
i = (0x007fffff)>>jj0;
if((i0&i)==0) return x; /* x is integral */
if(huge+x>(float)0.0) { /* raise inexact flag */
if(i0>0) i0 += (0x00800000)>>jj0;
i0 &= (~i);
}
}
} else {
if(jj0==0x80) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
SET_FLOAT_WORD(x,i0);
return x;
}

View File

@ -0,0 +1,13 @@
#include <stdint.h>
#include "private.h"
float
copysignf(float x, float y)
{
uint32_t ix,iy;
GET_FLOAT_WORD(ix,x);
GET_FLOAT_WORD(iy,y);
SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000));
return x;
}

View File

@ -0,0 +1,12 @@
#include <stdint.h>
#include "private.h"
float
fabsf(float x)
{
uint32_t ix;
GET_FLOAT_WORD(ix,x);
SET_FLOAT_WORD(x,ix&0x7fffffff);
return x;
}

View File

@ -0,0 +1,35 @@
#include <stdint.h>
#include "private.h"
static const float huge = 1.0e30;
float
floorf(float x)
{
int32_t i0,jj0;
uint32_t i;
GET_FLOAT_WORD(i0,x);
jj0 = ((i0>>23)&0xff)-0x7f;
if(jj0<23) {
if(jj0<0) { /* raise inexact if x != 0 */
if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */
if(i0>=0) {i0=0;}
else if((i0&0x7fffffff)!=0)
{ i0=0xbf800000;}
}
} else {
i = (0x007fffff)>>jj0;
if((i0&i)==0) return x; /* x is integral */
if(huge+x>(float)0.0) { /* raise inexact flag */
if(i0<0) i0 += (0x00800000)>>jj0;
i0 &= (~i);
}
}
} else {
if(jj0==0x80) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
SET_FLOAT_WORD(x,i0);
return x;
}

View File

@ -0,0 +1,37 @@
#include <stdint.h>
#include "private.h"
static const float
two25 = 3.355443200e+07, /* 0x4c000000 */
twom25 = 2.9802322388e-08, /* 0x33000000 */
huge = 1.0e+30,
tiny = 1.0e-30;
float
scalbnf(float x, int n)
{
int32_t k,ix;
GET_FLOAT_WORD(ix,x);
k = (ix&0x7f800000)>>23; /* extract exponent */
if (k==0) { /* 0 or subnormal x */
if ((ix&0x7fffffff)==0) return x; /* +-0 */
x *= two25;
GET_FLOAT_WORD(ix,x);
k = ((ix&0x7f800000)>>23) - 25;
if (n< -50000) return tiny*x; /*underflow*/
}
if (k==0xff) return x+x; /* NaN or Inf */
k = k+n;
if (k > 0xfe) return huge*copysignf(huge,x); /* overflow */
if (k > 0) /* normal result */
{SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;}
if (k <= -25) {
if (n > 50000) /* in case integer overflow in n+k */
return huge*copysignf(huge,x); /*overflow*/
else return tiny*copysignf(tiny,x); /*underflow*/
}
k += 25; /* subnormal result */
SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23));
return x*twom25;
}

View File

@ -0,0 +1,29 @@
#include <stdint.h>
#include "private.h"
static const float huge = 1.0e30F;
float truncf(float x) {
int32_t i0,jj0;
uint32_t i;
GET_FLOAT_WORD(i0,x);
jj0 = ((i0>>23)&0xff)-0x7f;
if(jj0<23) {
if(jj0<0) { /* raise inexact if x != 0 */
if(huge+x>0.0F) /* |x|<1, so return 0*sign(x) */
i0 &= 0x80000000;
} else {
i = (0x007fffff)>>jj0;
if((i0&i)==0) return x; /* x is integral */
if(huge+x>0.0F) /* raise inexact flag */
i0 &= (~i);
}
} else {
if(jj0==0x80) return x+x; /* inf or NaN */
else return x; /* x is integral */
}
SET_FLOAT_WORD(x,i0);
return x;
}

View File

@ -0,0 +1,20 @@
#include <stdint.h>
#include "private.h"
float
fmodf(float x, float y) /* wrapper fmodf */
{
// #ifdef _IEEE_LIBM
return __ieee754_fmodf(x,y);
// #else
// float z;
// z = __ieee754_fmodf(x,y);
// if(_LIB_VERSION == _IEEE_ ||isnanf(y)||isnanf(x)) return z;
// if(y==(float)0.0) {
// /* fmodf(x,0) */
// return (float)__kernel_standard((double)x,(double)y,127);
// } else
// return z;
// #endif
}

View File

@ -0,0 +1,21 @@
#include <stdint.h>
#include "private.h"
float
hypotf(float x, float y) /* wrapper hypotf */
{
// #ifdef _IEEE_LIBM
return __ieee754_hypotf(x,y);
// #else
// float z;
// z = __ieee754_hypotf(x,y);
// if(_LIB_VERSION == _IEEE_) return z;
// if((!finitef(z))&&finitef(x)&&finitef(y))
// /* hypot overflow */
// return (float)__kernel_standard((double)x,(double)y,104);
// else
// return z;
// #endif
}

45
lib/runtime/libm/w_powf.c Normal file
View File

@ -0,0 +1,45 @@
#include <stdint.h>
#include "private.h"
float
powf(float x, float y) /* wrapper powf */
{
// #ifdef _IEEE_LIBM
return __ieee754_powf(x,y);
// #else
// float z;
// z=__ieee754_powf(x,y);
// if(_LIB_VERSION == _IEEE_|| isnanf(y)) return z;
// if(isnanf(x)) {
// if(y==(float)0.0)
// /* powf(NaN,0.0) */
// return (float)__kernel_standard((double)x,(double)y,142);
// else
// return z;
// }
// if(x==(float)0.0){
// if(y==(float)0.0)
// /* powf(0.0,0.0) */
// return (float)__kernel_standard((double)x,(double)y,120);
// if(finitef(y)&&y<(float)0.0)
// /* powf(0.0,negative) */
// return (float)__kernel_standard((double)x,(double)y,123);
// return z;
// }
// if(!finitef(z)) {
// if(finitef(x)&&finitef(y)) {
// if(isnanf(z))
// /* powf neg**non-int */
// return (float)__kernel_standard((double)x,(double)y,124);
// else
// /* powf overflow */
// return (float)__kernel_standard((double)x,(double)y,121);
// }
// }
// if(z==(float)0.0&&finitef(x)&&finitef(y))
// /* powf underflow */
// return (float)__kernel_standard((double)x,(double)y,122);
// return z;
// #endif
}

51
lib/runtime/src/debug.rs Normal file
View File

@ -0,0 +1,51 @@
//! Debug tracing module
use core::fmt;
///
#[macro_export]
macro_rules! debug_trace {
($($args:tt)+) => {
$crate::debug::_debug_trace(format_args!($($args)+))
};
}
struct TracePrinter {
buf: [u8; 512],
len: usize,
}
impl fmt::Write for TracePrinter {
fn write_str(&mut self, s: &str) -> fmt::Result {
for &c in s.as_bytes() {
self.buf[self.len] = c;
self.len += 1;
}
Ok(())
}
}
/// Trace raw message into the kernel's log. If the message is not a valid unicode string, it will
/// get discarded.
pub fn trace_raw(data: &[u8]) {
if let Ok(str) = core::str::from_utf8(data) {
unsafe {
crate::sys::debug_trace(str);
}
}
}
#[doc(hidden)]
pub fn _debug_trace(a: core::fmt::Arguments<'_>) {
use fmt::Write;
let mut printer = TracePrinter { buf: [0; 512], len: 0 };
printer.write_fmt(a).ok();
if printer.len != 0 {
unsafe {
let s = core::str::from_utf8_unchecked(&printer.buf[..printer.len]);
crate::sys::debug_trace(s);
}
}
}

27
lib/runtime/src/io.rs Normal file
View File

@ -0,0 +1,27 @@
#![allow(missing_docs)]
pub mod device {
pub use abi::io::{DeviceRequest, MountOptions, UnmountOptions};
}
pub mod terminal {
pub use abi::io::{
TerminalInputOptions, TerminalLineOptions, TerminalOptions, TerminalOutputOptions,
TerminalSize,
};
}
pub mod message_channel {
pub use abi::io::{
ChannelPublisherId, MessageDestination, ReceivedMessageMetadata, SentMessage,
};
}
pub mod poll {
pub use abi::io::PollControl;
}
pub use abi::io::{
DirectoryEntry, FileAttr, FileMetadataUpdate, FileMetadataUpdateMode, FileMode, FileType,
OpenOptions, RawFd, SeekFrom,
};

102
lib/runtime/src/lib.rs Normal file
View File

@ -0,0 +1,102 @@
//! Yggdrasil OS application runtime
#![feature(rustc_private, exposed_provenance)]
#![no_std]
#![deny(missing_docs)]
#![allow(nonstandard_style)]
#[cfg(not(feature = "rustc-dep-of-std"))]
extern crate compiler_builtins;
extern crate yggdrasil_abi as abi;
pub use abi::error::Error;
pub use abi::path;
pub mod debug;
pub mod io;
pub mod net;
pub mod process;
pub mod sys;
pub mod time;
pub mod mem {
//! Memory-related data structures
pub use abi::mem::MappingSource;
}
pub mod system {
//! System-related data structures
pub use abi::system::*;
}
#[cfg(feature = "rustc-dep-of-std")]
use core::ffi::{c_char, c_void};
#[cfg(feature = "rustc-dep-of-std")]
#[no_mangle]
unsafe extern "C" fn bcmp(p0: *const c_void, p1: *const c_void, len: usize) -> i32 {
memcmp(p0, p1, len)
}
#[cfg(feature = "rustc-dep-of-std")]
#[no_mangle]
unsafe extern "C" fn memcmp(p0: *const c_void, p1: *const c_void, len: usize) -> i32 {
let mut offset = 0;
if len == 0 {
return 0;
}
while offset < len {
let c0 = (p0 as *const u8).add(offset).read_volatile();
let c1 = (p1 as *const u8).add(offset).read_volatile();
if c0 > c1 {
return (c0 - c1) as i32;
} else if c0 < c1 {
return -((c1 - c0) as i32);
}
offset += 1;
}
0
}
/// XXX
#[cfg(feature = "rustc-dep-of-std")]
#[no_mangle]
pub unsafe extern "C" fn memcpy(p0: *mut c_void, p1: *const c_void, len: usize) -> *mut c_void {
compiler_builtins::mem::memcpy(p0 as _, p1 as _, len) as _
}
#[cfg(feature = "rustc-dep-of-std")]
#[no_mangle]
unsafe extern "C" fn memmove(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void {
compiler_builtins::mem::memmove(dst as _, src as _, n) as _
}
#[cfg(feature = "rustc-dep-of-std")]
#[no_mangle]
unsafe extern "C" fn memset(dst: *mut c_void, val: i32, len: usize) -> *mut c_void {
let mut offset = 0;
while offset < len {
(dst as *mut u8).add(offset).write_volatile(val as u8);
offset += 1;
}
dst
}
#[cfg(feature = "rustc-dep-of-std")]
#[no_mangle]
unsafe extern "C" fn strlen(mut s: *mut c_char) -> usize {
if s.is_null() {
return 0;
}
let mut len = 0;
while s.read() != 0 {
len += 1;
s = s.add(1);
}
len
}

54
lib/runtime/src/net.rs Normal file
View File

@ -0,0 +1,54 @@
//! Network-related functions and types
pub use abi::net::{MacAddress, SocketInterfaceQuery, SocketOption, SocketType};
#[cfg(feature = "alloc")]
pub mod dns {
//! DNS resolver module for `std`
use abi::net::dns::DnsSerialize;
pub use abi::net::dns::{
DnsClass, DnsMessage, DnsMethod, DnsRecordData, DnsReplyCode, DnsType,
};
/// Interface for performing UDP communication
pub trait UdpRequester {
/// Error returned by the requester
type Error;
/// Sends a message through the communication channel
fn send_message(&mut self, message: &[u8]) -> Result<(), Self::Error>;
/// Wait for a message, parses it and runs a function on it to determine whether to return
fn receive_message<F: Fn(&[u8]) -> Option<DnsMessage>>(
&mut self,
map: F,
) -> Result<DnsMessage, Self::Error>;
}
/// Performs a raw DNS query without analyzing the reply
pub fn perform_query<R: UdpRequester>(
requester: &mut R,
name: &str,
ty: DnsType,
xid: u16,
cookie: u64,
) -> Result<DnsMessage, R::Error> {
let mut packet = alloc::vec![];
let query = DnsMessage::query(name, ty, xid, cookie);
query.serialize(&mut packet);
requester.send_message(&packet)?;
let message = requester.receive_message(|data| {
let message = DnsMessage::parse(data)?;
if message.xid != xid || message.method != DnsMethod::REPLY {
return None;
}
Some(message)
})?;
Ok(message)
}
}

View File

@ -0,0 +1,6 @@
//! Process management data types
pub use abi::process::{
ExecveOptions, ExitCode, MutexOperation, ProcessId, ProcessInfoElement, ProgramArgumentInner,
Signal, SignalEntryData, SpawnOption, SpawnOptions, ThreadId, ThreadSpawnOptions,
};

View File

@ -0,0 +1,44 @@
/// AArch64 implementation of a syscall macro
#[macro_export]
macro_rules! syscall {
($num:expr $(,)?) => {{
let mut res: usize;
core::arch::asm!("svc #0", lateout("x0") res, in("x8") usize::from($num));
res
}};
($num:expr, $a0:expr $(,)?) => {{
let mut res: usize = $a0;
core::arch::asm!("svc #0",
inlateout("x0") res,
in("x8") usize::from($num));
res
}};
($num:expr, $a0:expr, $a1:expr $(,)?) => {{
let mut res: usize = $a0;
core::arch::asm!("svc #0",
inlateout("x0") res, in("x1") $a1,
in("x8") usize::from($num));
res
}};
($num:expr, $a0:expr, $a1:expr, $a2:expr $(,)?) => {{
let mut res: usize = $a0;
core::arch::asm!("svc #0",
inlateout("x0") res, in("x1") $a1, in("x2") $a2,
in("x8") usize::from($num));
res
}};
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr $(,)?) => {{
let mut res: usize = $a0;
core::arch::asm!("svc #0",
inlateout("x0") res, in("x1") $a1, in("x2") $a2,
in("x3") $a3, in("x8") usize::from($num));
res
}};
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr $(,)?) => {{
let mut res: usize = $a0;
core::arch::asm!("svc #0",
inlateout("x0") res, in("x1") $a1, in("x2") $a2,
in("x3") $a3, in("x4") $a4, in("x8") usize::from($num));
res
}};
}

View File

@ -0,0 +1,25 @@
//! System call implementations
#[cfg(target_arch = "aarch64")]
#[macro_use]
mod aarch64;
#[cfg(target_arch = "x86_64")]
#[macro_use]
mod x86_64;
#[allow(missing_docs)]
mod generated {
// Import all the necessary types from generated ABI
use abi::{
error::Error,
io::{ChannelPublisherId, FileMode, OpenOptions, PollControl, RawFd},
mem::MappingSource,
net::SocketType,
process::{ProcessId, Signal},
SyscallFunction,
};
include!(concat!(env!("OUT_DIR"), "/generated_calls.rs"));
}
pub use generated::*;

View File

@ -0,0 +1,106 @@
/// x86-64 implementation of a system call macro
#[macro_export]
macro_rules! syscall {
($num:expr $(,)?) => {{
let mut res = usize::from($num);
core::arch::asm!(
"syscall",
inlateout("rax") res,
out("rdi") _,
out("rsi") _,
out("rdx") _,
out("r10") _,
out("r8") _,
out("r9") _,
// Clobbered by syscall
out("rcx") _,
out("r11") _,
);
res
}};
($num:expr, $a0:expr $(,)?) => {{
let mut res = usize::from($num);
core::arch::asm!(
"syscall",
inlateout("rax") res,
in("rdi") $a0,
out("rsi") _,
out("rdx") _,
out("r10") _,
out("r8") _,
out("r9") _,
// Clobbered by syscall
out("rcx") _,
out("r11") _,
);
res
}};
($num:expr, $a0:expr, $a1:expr $(,)?) => {{
let mut res = usize::from($num);
core::arch::asm!(
"syscall",
inlateout("rax") res,
in("rdi") $a0,
in("rsi") $a1,
out("rdx") _,
out("r10") _,
out("r8") _,
out("r9") _,
// Clobbered by syscall
out("rcx") _,
out("r11") _,
);
res
}};
($num:expr, $a0:expr, $a1:expr, $a2:expr $(,)?) => {{
let mut res = usize::from($num);
core::arch::asm!(
"syscall",
inlateout("rax") res,
in("rdi") $a0,
in("rsi") $a1,
in("rdx") $a2,
out("r10") _,
out("r8") _,
out("r9") _,
// Clobbered by syscall
out("rcx") _,
out("r11") _,
);
res
}};
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr $(,)?) => {{
let mut res = usize::from($num);
core::arch::asm!(
"syscall",
inlateout("rax") res,
in("rdi") $a0,
in("rsi") $a1,
in("rdx") $a2,
in("r10") $a3,
out("r8") _,
out("r9") _,
// Clobbered by syscall
out("rcx") _,
out("r11") _,
);
res
}};
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr $(,)?) => {{
let mut res = usize::from($num);
core::arch::asm!(
"syscall",
inlateout("rax") res,
in("rdi") $a0,
in("rsi") $a1,
in("rdx") $a2,
in("r10") $a3,
in("r8") $a4,
out("r9") _,
// Clobbered by syscall
out("rcx") _,
out("r11") _,
);
res
}};
}

18
lib/runtime/src/time.rs Normal file
View File

@ -0,0 +1,18 @@
//! System time management
/// System time representation
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Timespec {
/// Seconds component
pub seconds: u64,
/// Nanoseconds component
pub nanoseconds: u64,
}
impl Timespec {
/// Constructs a [Timespec] with all components set to zero
pub const fn zero() -> Self {
Self { seconds: 0, nanoseconds: 0 }
}
}