front
aiju 2020-01-22 13:09:09 +00:00
parent 1ecdf09aee
commit 6f80913ac7
10 changed files with 3230 additions and 0 deletions

View File

@ -48,6 +48,7 @@ DIRS=\
sokoban\
sudoku\
timmy\
v8e\
4s.$O 5s.$O xs.$O: xs.h
$O.4s $O.5s: xs.$O

1166
sys/src/games/v8e/cpu.c Normal file

File diff suppressed because it is too large Load Diff

516
sys/src/games/v8e/cpubcd.c Normal file
View File

@ -0,0 +1,516 @@
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
static s8int
getsign(u16int l, u32int a)
{
u8int c;
if(l == 0) return 1;
c = readm(a + l/2, 0);
c &= 0xf;
if(c == 11 || c == 13) return -1;
return 1;
}
static int
getdig(u16int l, u32int a, int i)
{
u8int c;
if(i >= l) return 0;
i = l - 1 - i;
if((l & 1) == 0) i++;
a += i/2;
c = readm(a, 0);
if((i & 1) == 0) return c >> 4;
return c & 0xf;
}
static void
putdig(u16int l, u32int a, int i, int v)
{
u8int c;
if(i >= l){
if(v != 0)
ps |= FLAGV;
return;
}
i = l - 1 - i;
if((l & 1) == 0) i++;
a += i/2;
if((l & 1) == 0 && i == 1)
c = 0;
else
c = readm(a, 0);
if((i & 1) == 0) c = c & 0x0f | v << 4;
else c = c & 0xf0 | v;
writem(a, c, 0);
}
static void
putsign(u16int l, u32int a, s8int s)
{
u8int c;
a += l/2;
c = readm(a, 0);
c = c & 0xf0 | 12 | s < 0;
writem(a, c, 0);
}
static u32int
sigdig(u16int l, u32int a)
{
u32int e;
e = a + l/2 + 1;
for(; a < e; a++)
if(readm(a, 0) != 0)
return a;
return a;
}
void
cvtlp(void)
{
s32int x;
u16int l;
u32int a;
u8int v;
int i;
x = readm(amode(2), 2);
l = readm(amode(1), 1);
a = addrof(amode(0));
ps = ps & ~15 | FLAGZ;
if(x < 0){
x = -x;
ps |= FLAGN;
}
for(i = 0; i < l; i++){
v = x % 10;
x /= 10;
putdig(l, a, i, v);
if(v != 0) ps &= ~FLAGZ;
}
if(x != 0) ps |= FLAGV;
if((ps & (FLAGN|FLAGZ)) == 0)
ps &= ~FLAGN;
putsign(l, a, -((ps & FLAGN) != 0));
r[0] = 0;
r[1] = 0;
r[2] = 0;
r[3] = sigdig(l, a);
}
static uchar
editread(void)
{
u8int rc;
if((s32int) r[0] <= 0){
if(r[0] == 0)
sysfatal("editread");
r[0] += 0x10000;
return 0;
}else{
rc = readm(r[1], 0);
if((r[0] & 1) != 0)
rc >>= 4;
else
rc &= 0xf;
r[0]--;
if((r[0] & 1) != 0)
r[1]++;
return rc;
}
}
void
editpc(void)
{
u8int p, c;
int i;
r[0] = readm(amode(1), 1);
r[1] = addrof(amode(0));
r[2] = 0x2020;
r[3] = addrof(amode(0));
r[5] = addrof(amode(0));
ps = ps & ~15 | FLAGZ;
c = readm(r[1] + r[0]/2, 0) & 0xf;
if(c == 11 || c == 13){
ps |= FLAGN;
r[2] |= 0xd00;
}
for(;;){
p = readm(r[3]++, 0);
switch(p){
case 0x00:
if(r[0] != 0) sysfatal("editpc");
if((ps & FLAGZ) != 0)
ps &= ~FLAGN;
return;
case 0x01:
if((ps & FLAGC) == 0){
writem(r[5]++, r[2] >> 8, 0);
ps |= FLAGC;
}
break;
case 0x02: ps &= ~FLAGC; break;
case 0x03: ps |= FLAGC; break;
case 0x04: writem(r[5]++, r[2] >> 8, 0); break;
case 0x40: r[2] = r[2] & ~0xff | (u8int)readm(r[3]++, 0); break;
case 0x41: r[2] = r[2] & ~0xff00 | (u8int)readm(r[3]++, 0) << 8; break;
case 0x42:
p = readm(r[3]++, 0);
if((ps & FLAGN) == 0)
r[2] = r[2] & ~0xff00 | p << 8;
break;
case 0x43:
p = readm(r[3]++, 0);
if((ps & FLAGN) != 0)
r[2] = r[2] & ~0xff00 | p << 8;
break;
case 0x44:
p = readm(r[3]++, 0);
if((ps & FLAGC) != 0)
writem(r[5]++, p, 0);
else
writem(r[5]++, r[2], 0);
break;
case 0x45:
p = readm(r[3]++, 0);
if((ps & FLAGZ) != 0){
r[5] -= p;
while(p-- != 0)
writem(r[5]++, r[2], 0);
}
break;
case 0x46:
p = readm(r[3]++, 0);
if((ps & (FLAGN|FLAGZ)) == (FLAGN|FLAGZ))
writem(r[5] - p, r[2], 0);
break;
case 0x47:
p = readm(r[3]++, 0);
if((u16int)r[0] > p){
r[0] = (u16int) r[0];
i = r[0] - p;
while(i-- > 0)
if(editread() != 0)
ps = ps & ~FLAGZ | FLAGV;
}else
r[0] = (u16int) r[0] | r[0] - p << 16;
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
for(; p > 0x80; p--)
writem(r[5]++, r[2], 0);
break;
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97:
case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
for(; p > 0x90; p--){
c = editread();
if(c != 0) ps = ps & ~FLAGZ | FLAGC;
if((ps & FLAGC) == 0)
writem(r[5]++, r[2], 0);
else
writem(r[5]++, '0' + c, 0);
}
break;
case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7:
case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
for(; p > 0xa0; p--){
c = editread();
if(c != 0){
if((ps & FLAGC) == 0)
writem(r[5]++, r[2] >> 8, 0);
ps = ps & ~FLAGZ | FLAGC;
}
if((ps & FLAGC) == 0)
writem(r[5]++, r[2], 0);
else
writem(r[5]++, '0' + c, 0);
}
break;
default: sysfatal("editpc: unknown pattern %.2x (pc=%.8ux)", p, curpc);
}
}
}
void
movp(void)
{
u16int l;
u32int sa, da;
u8int c, d;
int i, n;
l = readm(amode(1), 1);
sa = addrof(amode(0));
da = addrof(amode(1));
n = l/2 + 1;
ps = ps & ~(FLAGN|FLAGV) | FLAGZ;
for(i = 0; i < n-1; i++){
c = readm(sa++, 0);
writem(da++, c, 0);
if(c != 0) ps &= ~FLAGZ;
}
c = readm(sa, 0);
if((c & 0xf0) != 0) ps &= ~FLAGZ;
d = c & 0xf0;
c &= 0xf;
if(c == 11 || c == 13) ps |= FLAGN;
if((ps & (FLAGN|FLAGZ)) == (FLAGN|FLAGZ)) ps &= ~FLAGN;
if((ps & FLAGN) != 0) d |= 13;
else d |= 12;
writem(da, d, 0);
}
static int
cmpmag(u16int l1, u32int a1, u16int l2, u32int a2)
{
int i;
u8int c1, c2;
for(i = l1 > l2 ? l1 : l2; --i >= 0; ){
c1 = getdig(l1, a1, i);
c2 = getdig(l2, a2, i);
if(c1 > c2) return 1;
if(c1 < c2) return -1;
}
return 0;
}
void
addp(int rn, int sub)
{
u16int l1, l2, l3;
u32int a1, a2, a3;
s8int s1, s2;
int c, i, l, t;
l1 = readm(amode(1), 1);
a1 = addrof(amode(0));
l2 = readm(amode(1), 1);
a2 = addrof(amode(0));
if(rn == 6){
l3 = readm(amode(1), 1);
a3 = addrof(amode(0));
}else{
l3 = l2;
a3 = a2;
}
s1 = getsign(l1, a1);
s2 = getsign(l2, a2);
r[0] = 0;
r[1] = sigdig(l1, a1);
r[2] = 0;
r[3] = sigdig(l2, a2);
r[4] = 0;
if(sub) s1 ^= -2;
if(s1 == s2){
c = 0;
l = l1;
if(l2 > l) l = l2;
if(l3 > l) l = l3;
for(i = 0; i < l; i++){
t = c + getdig(l1, a1, i) + getdig(l2, a2, i);
for(c = 0; t >= 10; c++) t -= 10;
putdig(l3, a3, i, t);
}
}else{
if(cmpmag(l1, a1, l2, a2) < 0){
t = l1; l1 = l2; l2 = t;
t = a1; a1 = a2; a2 = t;
s1 = s2;
}
c = 0;
l = l3 > l1 ? l3 : l1;
for(i = 0; i < l; i++){
t = getdig(l1, a1, i) - getdig(l2, a2, i);
for(c = 0; t < 0; c++) t += 10;
putdig(l3, a3, i, t);
}
}
if(c != 0) ps |= FLAGV;
putsign(l3, a3, s1);
r[5] = sigdig(l3, a3);
}
void
cmpp(int rn)
{
u16int l1, l2;
u32int a1, a2;
s8int s1, s2;
int rc;
l1 = readm(amode(1), 1);
a1 = addrof(amode(0));
if(rn == 4)
l2 = readm(amode(1), 1);
else
l2 = l1;
a2 = addrof(amode(0));
s1 = getsign(l1, a1);
s2 = getsign(l2, a2);
r[0] = 0;
r[1] = sigdig(l1, a1);
r[2] = 0;
r[3] = sigdig(l2, a2);
ps &= ~15;
if(s1 != s2){
if(s1 < s2) ps |= FLAGN;
return;
}
rc = cmpmag(l1, a1, l2, a2);
if(rc == 0) ps |= FLAGZ;
else if(rc > 0) ps |= FLAGN;
}
void
ashp(void)
{
s8int cnt, rnd;
s16int sl, dl;
u32int sa, da;
int i, c, x;
cnt = readm(amode(0), 0);
sl = readm(amode(1), 1);
sa = addrof(amode(2));
rnd = readm(amode(0), 0);
dl = readm(amode(1), 1);
da = addrof(amode(2));
ps = ps & ~15 | FLAGZ;
x = getsign(sl, sa);
if(x < 0) ps |= FLAGN;
putsign(dl, da, x);
for(i = 0; i < cnt; i++)
putdig(dl, da, i, 0);
c = cnt < 0 && getdig(sl, sa, -1-cnt) >= rnd;
for(i = cnt >= 0 ? 0 : -cnt; i < sl; i++){
x = getdig(sl, sa, i) + c;
for(c = 0; x >= 10; c++) x -= 10;
putdig(dl, da, i + cnt, x);
if(x != 0) ps &= ~FLAGZ;
}
putdig(dl, da, i + cnt, c);
r[0] = 0;
r[1] = sigdig(sl, sa);
r[2] = 0;
r[3] = sigdig(dl, da);
}
void
locc(int inv)
{
u8int chr;
u16int len;
u32int addr;
chr = readm(amode(0), 0);
len = readm(amode(1), 1);
addr = addrof(amode(0));
ps &= ~15;
for(; len != 0; addr++, len--)
if(inv ^ (readm(addr, 0) == chr))
break;
if(len == 0) ps |= FLAGZ;
r[0] = len;
r[1] = addr;
}
void
cmpc(int op5)
{
u16int l1, l2;
u32int a1, a2;
u8int a, b, f;
if(op5){
l1 = readm(amode(1), 1);
a1 = addrof(amode(2));
f = readm(amode(0), 0);
l2 = readm(amode(1), 1);
a2 = addrof(amode(2));
}else{
l1 = l2 = readm(amode(1), 1);
a1 = addrof(amode(2));
a2 = addrof(amode(2));
f = 0;
}
a = b = f;
for(; l1 > 0 && l2 > 0; l1--, l2--, a1++, a2++){
a = readm(a1, 0);
b = readm(a2, 0);
if(a != b) goto ineq;
}
for(; l1 > 0; l1--, a1++){
a = readm(a1, 0);
b = f;
if(a != b) goto ineq;
}
for(; l2 > 0; l2--, a2++){
a = f;
b = readm(a2, 0);
if(a != b) goto ineq;
}
ineq:
ps = ps & ~15;
if((s8int)a < (s8int)b) ps |= FLAGN;
if(a == b) ps |= FLAGZ;
if(a < b) ps |= FLAGC;
r[0] = l1;
r[1] = a1;
r[2] = l2;
r[3] = a2;
}
void
movc(int op5)
{
u16int sl, dl, l;
u32int sa, da;
int i;
u8int f;
sl = readm(amode(1), 1);
sa = addrof(amode(0));
if(op5){
f = readm(amode(0), 0);
dl = readm(amode(1), 1);
}else{
f = 0;
dl = sl;
}
da = addrof(amode(0));
l = sl < dl ? sl : dl;
if(sa < da)
for(i = l; --i >= 0; )
writem(da + i, readm(sa + i, 0), 0);
else
for(i = 0; i < l; i++)
writem(da + i, readm(sa + i, 0), 0);
for(i = l; i < dl; i++)
writem(da + i, f, 0);
r[0] = sl - l;
r[1] = sa + sl;
r[2] = 0;
r[3] = da + dl;
r[4] = 0;
r[5] = 0;
ps &= ~15;
if((s16int) sl < (s16int) dl) ps |= FLAGN;
else if(sl == dl) ps |= FLAGZ;
if(sl < dl) ps |= FLAGC;
}

521
sys/src/games/v8e/cpufp.c Normal file
View File

@ -0,0 +1,521 @@
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
/* BUGS: Not bit accurate. */
enum {
ADD,
SUB,
MUL,
DIV,
CMP,
};
enum {
EBIAS = 129
};
#define zero(x) (((x) & 0xff80) == 0)
#define inval(x) (((x) & 0xff80) == 0x8000)
#define expo(x) ((x) >> 7 & 0xff)
#define mantf(x) (1<<23 | ((x) & 0x7f) << 16 | (x) >> 16)
#define mantd(x) (1ULL<<55|((x)&0x7f)<<48|((x)&0xffff0000)<<16| \
(x)>>16&0xffff0000|(u16int)((x)>>48))
#define sign(x) ((int)x << 16 >> 30 | 1)
#define makef(s, e, m) ((s)&0x8000|(e)<<7|(m)<<16|(m)>>16&0x7f)
#define maked(s, e, m) (s&0x8000|(e)<<7|(uvlong)(m)<<48|(uvlong)((m)&0xffff0000)<<16| \
(m)>>16&0xffff0000|(m)>>48&0x7f)
static double
vfc(u32int a)
{
union { u32int a; float b; } u;
if(zero(a)) return 0;
a -= 0x100;
u.a = a >> 16 | a << 16;
return u.b;
}
static double
vdc(u64int a)
{
union { u64int a; double b; } u;
if(zero(a)) return 0;
u.a = mantd(a) >> 3 & (1ULL<<52)-1 | expo(a) + 894 << 52 | sign(a) & 1ULL<<63;
return u.b;
}
static int
clz32(u32int a)
{
int n;
static uchar c[16] = {4, 3, 2, 2, 1, 1, 1, 1};
n = 0;
if((a >> 16) == 0){n += 16; a <<= 16;}
if((a >> 24) == 0){n += 8; a <<= 8;}
if((a >> 28) == 0){n += 4; a <<= 4;}
return n + c[a >> 28];
}
static int
clz64(uvlong a)
{
int n;
static uchar c[16] = {4, 3, 2, 2, 1, 1, 1, 1};
n = 0;
if((a >> 32) == 0){n += 32; a <<= 32;}
if((a >> 48) == 0){n += 16; a <<= 16;}
if((a >> 56) == 0){n += 8; a <<= 8;}
if((a >> 60) == 0){n += 4; a <<= 4;}
return n + c[a >> 60];
}
static int
magcmpd(u64int a, u64int b)
{
int e;
s64int m;
e = expo(a) - expo(b);
if(e > 0) return 1;
if(e < 0) return -1;
m = mantd(a) - mantd(b);
if(m > 0) return 1;
if(m < 0) return -1;
return 0;
}
static int
cmpd(u64int a, u64int b)
{
int s;
if(zero(a)){
if(zero(b)) return 0;
return -sign(b);
}
if(zero(b)) return sign(a);
s = sign(a) - sign(b);
if(s > 0) return 1;
if(s < 0) return -1;
return magcmpd(a, b);
}
static u32int
addf(u32int a, u32int b, int sub)
{
int e1, e2, m1, m2, s1, s2;
int n;
u32int c;
if(inval(a) || inval(b)) return 0x8000;
if(zero(b)) return a;
if(sub) b ^= 0x8000;
if(zero(a)) return b;
if(magcmpd(a, b) < 0){
c = a;
a = b;
b = c;
}
e1 = expo(a); m1 = mantf(a); s1 = sign(a);
e2 = expo(b); m2 = mantf(b); s2 = sign(b);
if(e1 - e2 >= 24) return a;
m2 >>= e1 - e2;
if(s1 == s2)
m1 += m2;
else
m1 -= m2;
if(m1 == 0) return 0;
n = 8 - clz32(m1);
e1 += n;
if(n > 0) m1 >>= n;
else m1 <<= -n;
return makef(s1, e1, m1);
}
static u32int
mulf(u32int a, u32int b)
{
int e1, e2, m1, m2, s1, s2, l;
if(zero(a) || zero(b)) return 0;
e1 = expo(a); m1 = mantf(a); s1 = sign(a);
e2 = expo(b); m2 = mantf(b); s2 = sign(b);
s1 ^= s2 & -2;
e1 += e2 - EBIAS;
if(e1 <= 0) return 0;
l = (uvlong)m1 * m2 + (1<<22) >> 23;
if((l & 1<<24) != 0){
l >>= 1;
e1++;
}
if(e1 >= 256) return 0x8000;
return makef(s1, e1, l);
}
static u32int
divf(u32int a, u32int b)
{
int e1, e2, m1, m2, s1, s2;
uvlong l;
if(zero(a)) return 0;
if(zero(b)) return 0x8000;
e1 = expo(a); m1 = mantf(a); s1 = sign(a);
e2 = expo(b); m2 = mantf(b); s2 = sign(b);
s1 ^= s2 & -2;
e1 -= e2 - EBIAS;
l = (uvlong) m1 << 40;
l /= m2;
l >>= 17;
if(l == 0) return 0;
while((l & 1<<23) == 0){
l <<= 1;
e1--;
}
if(e1 <= 0) return 0;
if(e1 >= 256) return 0x8000;
return makef(s1, e1, l);
}
static u64int
addd(u64int a, u64int b, int sub)
{
int e1, e2, s1, s2;
u64int m1, m2;
int n;
u64int c;
if(inval(a) || inval(b)) return 0x8000;
if(zero(b)) return a;
if(sub) b ^= 0x8000;
if(zero(a)) return b;
if(magcmpd(a, b) < 0){
c = a;
a = b;
b = c;
}
e1 = expo(a); m1 = mantd(a); s1 = sign(a);
e2 = expo(b); m2 = mantd(b); s2 = sign(b);
if(e1 - e2 >= 56) return a;
m2 >>= e1 - e2;
if(s1 == s2)
m1 += m2;
else
m1 -= m2;
if(m1 == 0) return 0;
n = 8 - clz64(m1);
e1 += n;
if(n > 0) m1 >>= n;
else m1 <<= -n;
return maked(s1, e1, m1);
}
static u64int
mul55(u64int a, u64int b)
{
u64int l;
l = (uvlong)(u32int)a * (u32int)b >> 32;
l += (a >> 32) * (u32int)b;
l += (u32int)a * (b >> 32);
l = l + (1<<21) >> 22;
l += (a >> 32) * (b >> 32) << 10;
l = l + 1 >> 1;
return l;
}
static u64int
mul62(u64int a, u64int b)
{
u64int l;
l = (uvlong)(u32int)a * (u32int)b >> 32;
l += (a >> 32) * (u32int)b;
l += (u32int)a * (b >> 32);
l = l + (1<<28) >> 29;
l += (a >> 32) * (b >> 32) << 3;
l = l + 1 >> 1;
return l;
}
static u64int
muld(u64int a, u64int b)
{
int e1, e2, s1, s2;
uvlong m1, m2;
uvlong l;
if(zero(a) || zero(b)) return 0;
e1 = expo(a); m1 = mantd(a); s1 = sign(a);
e2 = expo(b); m2 = mantd(b); s2 = sign(b);
s1 ^= s2 & -2;
e1 += e2 - EBIAS;
if(e1 <= 0) return 0;
l = mul55(m1, m2);
if((l & 1ULL<<56) != 0){
l >>= 1;
e1++;
}
if(e1 >= 256) return 0x8000;
return maked(s1, e1, l);
}
static u64int
divd(u64int a, u64int b)
{
int e1, e2, s1, s2;
uvlong m1, m2, l;
if(zero(a)) return 0;
if(zero(b)) return 0x8000;
e1 = expo(a); m1 = mantd(a); s1 = sign(a);
e2 = expo(b); m2 = mantd(b); s2 = sign(b);
s1 ^= s2 & -2;
e1 -= e2 - EBIAS;
l = (1ULL<<63) / (m2 >> 28) << 26;
m2 <<= 7;
l = mul62(l, (1ULL<<63) - mul62(l, m2));
l = mul62(l, (1ULL<<63) - mul62(l, m2));
l = mul62(l, (1ULL<<63) - mul62(l, m2));
l = mul62(l, m1 << 7);
l += 1<<6;
l >>= 7;
if(l == 0) return 0;
while((l & 1ULL<<55) == 0){
l <<= 1;
e1--;
}
if(e1 <= 0) return 0;
if(e1 >= 256) return 0x8000;
return maked(s1, e1, l);
}
void
alufp(int o, int r, int s)
{
u64int a, b, v;
vlong c;
int i;
switch(r){
case 2:
b = readm64(amode(s), s);
c = amode(s);
a = readm64(c, s);
break;
case 3:
b = readm64(amode(s), s);
a = readm64(amode(s), s);
c = amode(s);
break;
default: sysfatal("alufp: r==%d", r);
}
switch(o){
case ADD:
if(s == 0x13) v = addd(a, b, 0);
else v = addf(a, b, 0);
break;
case SUB:
if(s == 0x13) v = addd(a, b, 1);
else v = addf(a, b, 1);
break;
case MUL:
if(s == 0x13) v = muld(a, b);
else v = mulf(a, b);
break;
case DIV:
if(s == 0x13) v = divd(a, b);
else v = divf(a, b);
break;
case CMP:
ps &= ~15;
i = cmpd(b, a);
if(i < 0) ps |= FLAGN;
if(i == 0) ps |= FLAGZ;
return;
default:
sysfatal("alufp: unimplemented op=%d", o);
}
// print("%.8ux %d %20.16g %20.16g %20.16g\n", curpc, o, vdc(a), vdc(b), vdc(v));
ps &= ~15;
if(zero(v)) ps |= FLAGZ;
if((v & 0x8000) != 0) ps |= FLAGN;
writem64(c, v, s);
}
static u64int
itof(s32int i)
{
int n;
u64int l;
l = 0;
if(i < 0){
l |= 0x8000;
i = -i;
}else if(i == 0)
return 0;
n = clz32(i);
l |= maked(0, 160 - n, (uvlong)i << 24 + n);
return l;
}
static s64int
ftoi(u64int l)
{
int s, e;
s = sign(l);
e = expo(l);
l = mantd(l);
if(e >= EBIAS + 64) return 1LL<<63;
if(e < EBIAS) return 0;
l >>= EBIAS + 55 - e;
if(s < 0) return -l;
else return l;
}
void
cvtfp(int s, int t, int r)
{
u64int l;
int si, e;
switch(s){
case 0: l = itof((s8int) readm(amode(0), 0)); break;
case 1: l = itof((s16int) readm(amode(1), 1)); break;
case 2: l = itof(readm(amode(2), 2)); break;
case 0x12: l = readm(amode(2), 2); break;
case 0x13: l = readm64(amode(3), 3); break;
default: sysfatal("cvtfp: s==%d", s);
}
if(r) l = addd(l, maked(sign(l), 128, 0), 0);
if(t < 0x10) l = ftoi(l);
ps &= ~15;
switch(t){
case 0:
if((s64int)l != (s8int)l) ps |= FLAGV;
l = (s8int) l;
break;
case 1:
if((s64int)l != (s16int)l) ps |= FLAGV;
l = (s16int) l;
break;
case 2:
if((s64int)l != (s32int)l) ps |= FLAGV;
l = (s32int) l;
break;
case 0x12:
si = sign(l);
e = expo(l);
l = mantd(l);
l += 1ULL<<31;
if((l & 1ULL<<56) != 0){
l >>= 1;
e++;
}
l = maked(si, e, l);
break;
}
writem64(amode(t), l, t);
if(t >= 0x10){
if(zero(l)) ps |= FLAGZ;
if((l & 0x8000) != 0) ps |= FLAGN;
}else{
if(l == 0) ps |= FLAGZ;
if((s64int)l < 0) ps |= FLAGN;
}
}
void
movefp(int t, int n)
{
u64int x;
x = readm64(amode(t), t);
if(inval(x)) sysfatal("invalid float");
ps &= ~(FLAGN|FLAGZ|FLAGV);
if(zero(x))
ps |= FLAGZ;
else{
if(n) x ^= 0x8000;
if((x & 0x8000) != 0) ps |= FLAGN;
}
writem64(amode(t), x, t);
}
void
emod(int s)
{
u64int a, b, m1, m2, l;
u8int a8;
vlong ai, af;
int e1, e2, s1, s2, n;
a = readm64(amode(s), s);
a8 = readm(amode(0), 0);
b = readm64(amode(s), s);
ai = amode(2);
af = amode(s);
if(zero(a) || zero(b)){
ps = ps & ~15 | FLAGZ;
writem(ai, 0, 2);
writem64(af, 0, s);
return;
}
e1 = expo(a); m1 = mantd(a) << 8 | a8; s1 = sign(a);
e2 = expo(b); m2 = mantd(b); s2 = sign(b);
s1 ^= s2 & -2;
e1 += e2 - EBIAS;
if(e1 <= 0){
ps = ps & ~15 | FLAGZ;
writem(ai, 0, 2);
writem64(af, 0, s);
return;
}
l = (uvlong)(u32int)m1 * (u32int)m2 >> 32;
l += (m1 >> 32) * (u32int)m2;
l += (u32int)m1 * (m2 >> 32);
l = l + (1<<29) >> 30;
l += (m1 >> 32) * (m2 >> 32) << 2;
l = l + 1 >> 1;
while((l & 1ULL<<56) != 0){
l = l + 1 >> 1;
e1++;
}
if(e1 >= 256){
ps |= FLAGV;
return;
}
if(e1 < EBIAS){
writem(ai, 0, 2);
writem64(af, maked(s1, e1, l), s);
if(s1 < 0) ps |= FLAGN;
return;
}
writem(ai, l >> 55+EBIAS-e1, 2);
l &= (1ULL<<55+EBIAS-e1) - 1;
if(l == 0){
writem64(af, 0, s);
ps |= FLAGZ;
return;
}
n = clz64(l)-8;
l <<= n;
e1 -= n;
writem64(af, maked(s1, e1, l), s);
if(s1 < 0) ps |= FLAGN;
}
void
fptest(void)
{
}

57
sys/src/games/v8e/dat.h Normal file
View File

@ -0,0 +1,57 @@
typedef char s8int;
typedef short s16int;
typedef int s32int;
typedef vlong s64int;
extern u32int r[16];
extern u32int ps;
extern u32int curpc;
extern int trace;
#define U32(x) ((x)[0] | (x)[1] << 8 | (x)[2] << 16 | (x)[3] << 24)
typedef struct Segment Segment;
typedef struct Chan Chan;
struct Segment {
enum {
SEGRO = 1,
} flags;
u32int start, size;
u32int *data;
};
extern Segment segs[3];
enum {
STACKSIZE = 16*1024*1024
};
enum {
EPERM = 1,
ENOENT = 2,
EIO = 5,
EBADF = 9,
EINVAL = 22,
EMFILE = 24,
ENOTTY = 25,
};
struct Chan {
int fd;
enum {
DONTCLOSE = 1,
DIR = 2,
FAKETTY = 4,
} flags;
char *buf, *bufp, *bufe;
};
enum { NCHANS = 128 };
enum {
FLAGN = 8,
FLAGZ = 4,
FLAGV = 2,
FLAGC = 1,
};

16
sys/src/games/v8e/fns.h Normal file
View File

@ -0,0 +1,16 @@
void step(void);
u8int memread8(u32int);
u16int memread16(u32int);
u32int memread32(u32int);
void memwrite(u32int, u32int, u32int);
void syscall(u16int);
void writem(vlong, u32int, int);
void *emalloc(ulong);
void sysinit(void);
u32int readm(vlong, int);
u64int readm64(vlong, int);
u32int addrof(vlong);
void writem(vlong, u32int, int);
void writem64(vlong, u64int, int);
vlong amode(int);
int load(char *, char **, char **);

74
sys/src/games/v8e/mem.c Normal file
View File

@ -0,0 +1,74 @@
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
static Segment *
seglook(u32int a, int n, u32int **lp)
{
Segment *s;
for(s = segs; s < segs + nelem(segs); s++)
if(a >= s->start && a < s->start + s->size)
break;
if(s == segs + nelem(segs)) return nil;
if(a + n > s->start + s->size) return nil;
if(lp != nil) *lp = s->data + (a - s->start >> 2);
return s;
}
u8int
memread8(u32int a)
{
u32int *p;
if(seglook(a, 1, &p) == nil) sysfatal("invalid read from %.8ux (pc=%.8ux)", a, curpc);
switch(a & 3){
case 0: return *p;
case 1: return *p >> 8;
case 2: return *p >> 16;
case 3: return *p >> 24;
}
return 0;
}
u16int
memread16(u32int a)
{
u32int *p;
if(seglook(a, 2, &p) == nil) sysfatal("invalid read from %.8ux (pc=%.8ux)", a, curpc);
switch(a & 3){
case 0: return *p;
case 1: return *p >> 8;
case 2: return *p >> 16;
case 3: return *p >> 24 | p[1] << 8;
}
return 0;
}
u32int
memread32(u32int a)
{
u32int *p;
if(seglook(a, 4, &p) == nil) sysfatal("invalid read from %.8ux (pc=%.8ux)", a, curpc);
switch(a & 3){
case 0: return *p;
case 1: return *p >> 8 | p[1] << 24;
case 2: return *p >> 16 | p[1] << 16;
case 3: return *p >> 24 | p[1] << 8;
}
return *p;
}
void
memwrite(u32int a, u32int v, u32int m)
{
u32int *p;
Segment *s;
s = seglook(a, 4, &p);
if(s == nil || (s->flags & SEGRO) != 0) sysfatal("invalid write to %.8ux=%.8ux (mask=%.8ux, pc=%.8ux)", a, v, m, curpc);
*p = *p & ~m | v & m;
}

14
sys/src/games/v8e/mkfile Normal file
View File

@ -0,0 +1,14 @@
</$objtype/mkfile
BIN=/$objtype/bin
TARG=v8e
HFILES=dat.h fns.h
OFILES=\
v8e.$O \
cpu.$O \
cpubcd.$O \
cpufp.$O \
mem.$O \
sys.$O \
</sys/src/cmd/mkone

660
sys/src/games/v8e/sys.c Normal file
View File

@ -0,0 +1,660 @@
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
Chan chans[NCHANS];
int systrace=1;
#define dprint print
static u32int
arg(int n)
{
return memread32(r[12] + (n + 1) * 4);
}
static char *
strget(u32int addr)
{
int n;
char *s;
for(n = 0; memread8(addr + n) != 0; n++)
;
s = emalloc(n + 1);
for(n = 0; n == 0 || s[n-1] != 0; n++)
s[n] = memread8(addr + n);
return s;
}
static char **
vecget(u32int addr)
{
int n;
u32int u;
char **s;
for(n = 0; readm(addr + n, 2) != 0; n += 4)
;
s = emalloc((n + 1) * sizeof(char *));
for(n = 0; u = readm(addr + n * 4, 2), u != 0; n++)
s[n] = strget(u);
return s;
}
static Chan *
getfd(int n)
{
if((unsigned)n >= NCHANS || chans[n].fd < 0)
return nil;
return &chans[n];
}
static Chan *
newfd(void)
{
Chan *c;
for(c = chans; c < chans + nelem(chans); c++)
if(c->fd < 0)
return c;
return nil;
}
static int
toerrno(void)
{
char buf[ERRMAX];
rerrstr(buf, sizeof(buf));
if(strstr(buf, "not found")) return -ENOENT;
print("couldn't translate %s\n", buf);
return -EIO;
}
static int
toerrnoi(int rc)
{
if(rc >= 0)
return rc;
return toerrno();
}
static int
dostat(u32int buf, Dir *d)
{
int m;
if(d == nil) return toerrno();
writem(buf, 0, 1); /* dev */
writem(buf + 2, d->qid.path, 1); /* ino */
m = d->mode & 0777;
if((d->mode & DMDIR) != 0) m |= 040000;
else m |= 010000;
writem(buf + 4, m, 1); /* mode */
writem(buf + 6, 1, 1); /* nlink */
writem(buf + 8, 0, 1); /* uid */
writem(buf + 10, 0, 1); /* gid */
writem(buf + 12, d->dev, 1); /* dev */
writem(buf + 16, d->length, 2); /* size */
writem(buf + 20, d->atime, 2); /* atime */
writem(buf + 24, d->mtime, 2); /* mtime */
writem(buf + 28, d->mtime, 2); /* ctime */
free(d);
return 0;
}
static int
sysexit(void)
{
int no;
no = arg(0);
if(no == 0) exits(nil);
exits(smprint("%d", no));
return 0;
}
static int
dodirread(Chan *c)
{
Dir *d, *dp;
int rc;
free(c->buf);
c->buf = c->bufp = c->bufe = nil;
rc = dirread(c->fd, &d);
if(rc <= 0) return rc;
c->bufp = c->bufe = c->buf = emalloc(16 * rc);
for(dp = d; --rc >= 0; dp++){
*c->bufe++ = dp->qid.path;
*c->bufe++ = dp->qid.path >> 8;
strncpy(c->bufe, dp->name, 14);
c->bufe += 14;
}
free(d);
return 0;
}
static int
sysread(void)
{
int fd, sz, rc, i;
u32int addr;
char *buf;
Chan *c;
fd = arg(0);
addr = arg(1);
sz = arg(2);
if(systrace) dprint("read(%d, %#ux, %d)\n", fd, addr, sz);
c = getfd(fd);
if(sz < 0) return -EINVAL;
if(c == nil) return -EBADF;
if((c->flags & DIR) != 0){
if(c->bufp >= c->bufe)
if(dodirread(c) < 0)
return toerrno();
for(rc = 0; sz > 0 && c->bufp < c->bufe; rc++, sz--)
writem(addr++, *c->bufp++, 0);
return rc;
}else{
buf = emalloc(sz);
rc = read(c->fd, buf, sz);
for(i = 0; i < rc; i++)
writem(addr + i, buf[i], 0);
free(buf);
if(rc < 0) return toerrno();
}
return rc;
}
static int
syswrite(void)
{
int fd, sz, rc, i;
u32int addr;
Chan *c;
char *buf;
fd = arg(0);
addr = arg(1);
sz = arg(2);
if(systrace) dprint("write(%d, %#ux, %d)\n", fd, addr, sz);
c = getfd(fd);
if(sz < 0) return -EINVAL;
if(c == nil) return -EBADF;
buf = emalloc(sz);
for(i = 0; i < sz; i++)
buf[i] = memread8(addr + i);
rc = write(c->fd, buf, sz);
free(buf);
return toerrnoi(rc);
}
static int
sysopen(void)
{
char *s;
Chan *c;
int m;
Dir *d;
s = strget(arg(0));
m = arg(1);
if(systrace) dprint("open(\"%s\", %#uo)\n", s, m);
switch(m){
case 0: m = OREAD; break;
case 1: m = OWRITE; break;
case 2: m = ORDWR; break;
default: free(s); return -EINVAL;
}
c = newfd();
if(c == nil){
free(s);
return -EMFILE;
}
c->fd = open(s, m);
free(s);
if(c->fd < 0) return toerrno();
d = dirfstat(c->fd);
if(d == nil){
close(c->fd);
return toerrno();
}
if((d->mode & DMDIR) != 0)
c->flags |= DIR;
free(d);
return c - chans;
}
static int
sysclose(void)
{
int fd;
Chan *c;
fd = arg(0);
if(systrace) dprint("close(%d)\n", fd);
c = getfd(fd);
if(c == nil) return -EBADF;
if((c->flags & DONTCLOSE) == 0)
close(c->fd);
c->fd = -1;
return 0;
}
static int
sysfstat(void)
{
int fd, buf;
Chan *c;
Dir *d;
fd = arg(0);
buf = arg(1);
if(systrace) dprint("fstat(%d, %#ux)\n", fd, buf);
c = getfd(fd);
if(c == nil) return -EBADF;
d = dirfstat(c->fd);
return dostat(buf, d);
}
static int
syslstat(void)
{
char *s;
int buf;
Dir *d;
s = strget(arg(0));
buf = arg(1);
if(systrace) dprint("lstat(\"%s\", %#ux)\n", s, buf);
d = dirstat(s);
free(s);
return dostat(buf, d);
}
static int
sysioctl(void)
{
int fd, ctl;
u32int addr;
Chan *c;
fd = arg(0);
ctl = arg(1);
addr = arg(2);
if(systrace) dprint("lstat(%d, %#ux, %#ux)\n", fd, ctl, addr);
c = getfd(fd);
if(c == nil) return -EBADF;
switch(ctl){
case 't'<<8|8:
if((c->flags & FAKETTY) != 0){
writem(addr, 13 | 13<<8 | '#'<<16 | '@'<<24, 2);
writem(addr + 4, 06010, 2);
return 0;
}
return -ENOTTY;
case 'j'<<8|3: return -EINVAL;
default:
fprint(2, "unknown ioctl %c%d\n", ctl >> 8, (u8int)ctl);
return -EINVAL;
}
}
static int
systime(void)
{
u32int addr;
int t;
addr = arg(0);
if(systrace) dprint("time(%#ux)\n", addr);
t = time(0);
if(addr != 0) writem(addr, t, 2);
return t;
}
static int
sysbreak(void)
{
u32int a;
int ns;
a = arg(0);
if(systrace) dprint("break(%#ux)\n", a);
a = -(-a & -1024);
ns = a - segs[1].start;
if(ns > segs[1].size){
segs[1].data = realloc(segs[1].data, ns);
memset((uchar *) segs[1].data + segs[1].size, 0, ns - segs[1].size);
segs[1].size = ns;
}
return 0;
}
static int
sysftime(void)
{
u32int p;
vlong n;
Tm *t;
p = arg(0);
if(systrace) dprint("ftime(%#ux)\n", p);
n = nsec();
n /= 1000000;
writem(p + 4, n % 1000, 1);
n /= 1000;
writem(p, n, 2);
t = localtime(n);
writem(p + 6, -t->tzoff / 60, 1);
writem(p + 8, 0, 1);
return 0;
}
static int
syssignal(void)
{
return 0;
}
static int
sysgetpid(void)
{
if(systrace) dprint("getpid()\n");
return getpid() & 0xffff;
}
static int
sysaccess(void)
{
char *s;
int m, rc;
s = strget(arg(0));
m = arg(1);
if(systrace) dprint("access(\"%s\", %#ux)\n", s, m);
rc = access(s, m & 7);
free(s);
return toerrnoi(rc);
}
static int
syscreat(void)
{
char *s;
Chan *c;
int m;
s = strget(arg(0));
m = arg(1);
if(systrace) dprint("creat(\"%s\", %#uo)\n", s, m);
c = newfd();
if(c == nil){
free(s);
return -EMFILE;
}
c->fd = create(s, OWRITE, m & 0777);
free(s);
if(c->fd < 0) return toerrno();
return c - chans;
}
static int
sysseek(void)
{
int fd, off, wh;
Chan *c;
fd = arg(0);
off = arg(1);
wh = arg(2);
if(systrace) dprint("seek(%d, %d, %d)\n", fd, off, wh);
c = getfd(fd);
if(c == nil || off < 0 || (uint)wh > 2) return -EBADF;
return toerrnoi(seek(c->fd, off, wh));
}
static int
sysunlink(void)
{
char *s;
int rc;
s = strget(arg(0));
if(systrace) dprint("unlink(\"%s\")\n", s);
rc = remove(s);
free(s);
return toerrnoi(rc);
}
static int
syschdir(void)
{
char *s;
int rc;
s = strget(arg(0));
if(systrace) dprint("chdir(\"%s\")\n", s);
rc = chdir(s);
free(s);
return toerrnoi(rc);
}
static int
sysgetuid(void)
{
return 0;
}
static int
sysfork(void)
{
int rc;
if(systrace) dprint("fork()\n");
rc = fork();
if(rc < 0) return toerrno();
if(rc == 0){
r[1] = 1;
return getppid();
}
r[1] = 0;
return rc;
}
static int
sysexece(void)
{
char *file, **argv, **env, **p;
int rc;
file = strget(arg(0));
argv = vecget(arg(1));
env = vecget(arg(2));
if(systrace) dprint("exece(\"%s\", ..., ...)\n", file);
rc = load(file, argv, env);
for(p = argv; *p != nil; p++)
free(*p);
for(p = env; *p != nil; p++)
free(*p);
free(file);
free(argv);
free(env);
return toerrnoi(rc);
}
static int
syswait(void)
{
Waitmsg *w;
int rc, st;
u32int addr;
char *p;
addr = arg(0);
if(systrace) dprint("wait(%#ux)\n", addr);
w = wait();
if(w == nil) return toerrno();
rc = w->pid;
if(addr != 0){
st = strtol(w->msg, &p, 10) & 255 << 8;
if(*p == 0) st = 127 << 8;
writem(addr, st, 2);
}
free(w);
return rc;
}
int mask = 022;
static int
sysumask(void)
{
int rc;
rc = mask;
mask = arg(0);
if(systrace) dprint("umask(%#uo)\n", mask);
return rc;
}
static int
syslink(void)
{
char *a, *b;
int f0, f1, rc, n;
char buf[8192];
a = strget(arg(0));
b = strget(arg(1));
if(systrace) dprint("link(\"%s\", \"%s\")\n", a, b);
f0 = open(a, OREAD);
f1 = create(b, OWRITE | OEXCL, 0777 ^ mask);
if(f0 < 0 || f1 < 0) {
err:
rc = toerrno();
goto out;
}
for(;;){
n = read(f0, buf, sizeof(buf));
if(n < 0) goto err;
if(n == 0) break;
if(write(f1, buf, n) < n) goto err;
}
rc = 0;
out:
if(f0 >= 0) close(f0);
if(f1 >= 0) close(f1);
free(a);
free(b);
return rc;
}
static int
syschmod(void)
{
char *a;
int mode;
Dir d;
Dir *e;
a = strget(arg(0));
mode = arg(1);
if(systrace) dprint("chmod(\"%s\", %#uo)\n", a, mode);
e = dirstat(a);
if(e == nil){
free(a);
return toerrno();
}
nulldir(&d);
d.mode = e->mode & ~0777 | mode & 0777;
free(e);
if(dirwstat(a, &d) < 0){
free(a);
return toerrno();
}
free(a);
return 0;
}
static int
sysdup(void)
{
int fd;
Chan *c, *d;
fd = arg(0);
if(systrace) dprint("dup(%d)\n", fd);
c = getfd(fd);
if(c == nil) return -EBADF;
d = newfd();
if(d == nil) return -EMFILE;
d->fd = c->fd;
d->flags = c->flags;
return d - chans;
}
void
syscall(u16int c)
{
int rc;
static int (*calls[])(void) = {
[1] sysexit,
[2] sysfork,
[3] sysread,
[4] syswrite,
[5] sysopen,
[6] sysclose,
[7] syswait,
[8] syscreat,
[9] syslink,
[10] sysunlink,
[12] syschdir,
[13] systime,
[15] syschmod,
[17] sysbreak,
[18] syslstat,
[19] sysseek,
[20] sysgetpid,
[24] sysgetuid,
[28] sysfstat,
[33] sysaccess,
[35] sysftime,
[40] syslstat,
[41] sysdup,
[48] syssignal,
[54] sysioctl,
[59] sysexece,
[60] sysumask,
[66] sysfork,
};
if(c >= nelem(calls) || calls[c] == nil) sysfatal("unknown syscall %d", c);
rc = calls[c]();
if(rc < 0){
r[0] = -rc;
ps |= 1;
}else{
r[0] = rc;
ps &= ~1;
}
}
void
sysinit(void)
{
int i;
for(i = 0; i < NCHANS; i++)
chans[i].fd = -1;
chans[0].fd = 0;
chans[0].flags = DONTCLOSE|FAKETTY;
chans[1].fd = 1;
chans[1].flags = DONTCLOSE|FAKETTY;
chans[2].fd = 2;
chans[2].flags = DONTCLOSE|FAKETTY;
}

205
sys/src/games/v8e/v8e.c Normal file
View File

@ -0,0 +1,205 @@
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <ctype.h>
#include "dat.h"
#include "fns.h"
Segment segs[3];
void *
emalloc(ulong n)
{
void *v;
v = malloc(n);
if(v == nil) sysfatal("malloc: %r");
memset(v, 0, n);
setmalloctag(v, getcallerpc(&n));
return v;
}
enum {
OMAGIC = 0407,
NMAGIC = 0410,
ZMAGIC = 0413,
};
static int
readn32(int fd, u32int *l, int sz)
{
static uchar buf[8192];
uchar *p;
int n, rc;
while(sz > 0){
n = 8192;
if(n > sz) n = sz;
rc = readn(fd, buf, n);
if(rc < 0) return -1;
if(rc < n){
werrstr("unexpected eof");
return -1;
}
sz -= n;
p = buf;
for(; n >= 4; n -= 4){
*l++ = U32(p);
p += 4;
}
switch(n){
case 1: *l = p[0]; break;
case 2: *l = p[0] | p[1] << 8; break;
case 3: *l = p[0] | p[1] << 8 | p[2] << 16; break;
}
}
return 0;
}
static void
setupstack(char **argv)
{
u32int *nargv;
int i, j;
int argc;
r[14] = 0x7ffff400;
#define push32(x) { r[14] -= 4; memwrite(r[14], x, -1); }
for(argc = 0; argv[argc] != nil; argc++)
;
nargv = emalloc(sizeof(u32int) * argc);
for(i = argc; --i >= 0; ){
r[14] -= strlen(argv[i]) + 1;
nargv[i] = r[14];
for(j = 0; argv[i][j] != 0; j++)
writem(r[14] + j, argv[i][j], 0);
}
r[14] &= -4;
push32(0);
push32(0);
push32(0);
for(i = argc; --i >= 0; )
push32(nargv[i]);
push32(argc);
free(nargv);
}
static int
shload(int fd, char *file, char **argv, char **envp)
{
char buf[256];
char *s, *a;
char *p;
int rc;
char **nargv, **pp;
int n;
rc = read(fd, buf, sizeof(buf) - 1);
if(rc <= 0){
werrstr("invalid magic");
return -1;
}
close(fd);
buf[rc] = 0;
p = strchr(buf, '\n');
if(p == nil) *p = 0;
p = buf;
while(isspace(*p)) p++;
s = p;
while(*p != 0 && !isspace(*p)) p++;
if(*p != 0){
*p = 0;
while(isspace(*p)) p++;
if(*p != 0){
a = p;
while(*p != 0 && !isspace(*p)) p++;
}else a = nil;
}else a = nil;
for(n = 0; argv[n] != nil; n++)
;
nargv = emalloc((n + 3) * sizeof(char *));
pp = nargv;
*pp++ = s;
if(a != nil) *pp++ = a;
while(n--)
*pp++ = *argv++;
load(s, nargv, envp);
free(nargv);
return 0;
}
int
load(char *file, char **argv, char **envp)
{
uchar hdr[32];
int fd;
u32int hmagic, htext, hdata, hbss, hentry;
fd = open(file, OREAD);
if(fd < 0) return -1;
if(readn(fd, hdr, 2) < 2) return -1;
if(hdr[0] == '#' && hdr[1] == '!')
return shload(fd, file, argv, envp);
if(readn(fd, hdr + 2, 30) < 30) return -1;
hmagic = U32(&hdr[0]);
htext = U32(&hdr[4]);
hdata = U32(&hdr[8]);
hbss = U32(&hdr[12]);
hentry = U32(&hdr[20]);
switch(hmagic){
case ZMAGIC: case OMAGIC: case NMAGIC: break;
default:
werrstr("invalid magic %.6o", hmagic);
return -1;
}
free(segs[0].data);
free(segs[1].data);
free(segs[2].data);
segs[0].start = 0;
segs[0].size = htext;
segs[0].data = emalloc(-(-htext & -4));
segs[1].start = -(-htext & -1024);
segs[1].size = hdata + hbss;
segs[1].data = emalloc(-(-(hdata + hbss) & -4));
segs[2].start = 0x7ffff400 - STACKSIZE;
segs[2].size = STACKSIZE;
segs[2].data = emalloc(STACKSIZE);
if(hmagic != OMAGIC)
segs[0].flags = SEGRO;
if(hmagic == ZMAGIC)
seek(fd, 1024, 0);
if(readn32(fd, segs[0].data, htext) < 0) exits(smprint("%r"));
if(readn32(fd, segs[1].data, hdata) < 0) exits(smprint("%r"));
close(fd);
memset(r, 0, sizeof(r));
r[15] = hentry + 2;
setupstack(argv);
return 0;
}
static void
usage(void)
{
sysfatal("usage");
}
void
main(int argc, char **argv)
{
extern void fptest(void);
rfork(RFNAMEG);
fptest();
ARGBEGIN{
case 'N':
if(addns(nil, EARGF(usage())) < 0)
sysfatal("addns: %r");
break;
default: usage();
}ARGEND;
if(argc < 1) usage();
sysinit();
if(load(argv[0], argv, nil) < 0) sysfatal("load: %r");
for(;;) step();
}