shithub: drawcpu

Download patch

ref: 8d93ccdbb2a2dee8d2eb1387da1b316fdf84b208
parent: fed44bd6dee3c21a0b5ac0c11c13b4271e20f6f3
author: halfwit <michaelmisch1985@gmail.com>
date: Wed Jul 16 10:49:21 EDT 2025

Modifications and updates as part of a rework around emulating using an embedded 5e

--- a/include/lib.h
+++ b/include/lib.h
@@ -314,10 +314,7 @@
 extern	int	getfields(char*, char**, int, int, char*);
 extern	char*	utfecpy(char*, char*, char*);
 extern	int	tas(int*);
-extern  void trampoline(void*);
-extern void start(uintptr_t entry, Tos *, int, char *[]);
-extern  long sysintercept(void*, void*, void*, void*, void*, void*, void*);
-extern  int patch(void*, int);
+extern  int cas(int *, int, int);
 extern	void	quotefmtinstall(void);
 extern	int	dec64(uchar*, int, char*, int);
 extern	int	enc64(char*, int, uchar*, int);
--- /dev/null
+++ b/include/proc.h
@@ -1,0 +1,2 @@
+extern void step(void);
+int loadtext(char *, int, char **);
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -5,6 +5,7 @@
 OFILES=\
 	alloc.$O\
 	allocb.$O\
+	arm.$O\
 	await.$O\
 	chan.$O\
 	data.$O\
@@ -29,7 +30,10 @@
 	postnote.$O\
 	procinit.$O\
 	notify.$O\
+	rendez.$O\
 	rwlock.$O\
+	seg.$O\
+	sema.$O\
 	sleep.$O\
 	stub.$O\
 	syscall.$O\
--- /dev/null
+++ b/kern/arm.c
@@ -1,0 +1,580 @@
+#include <u.h>
+#include <lib.h>
+#include "dat.h"
+#include "fns.h"
+#include "proc.h"
+
+enum {
+	fI = 1<<25,
+	fP = 1<<24,
+	fLi = 1<<24,
+	fU = 1<<23,
+	fB = 1<<22,
+	fW = 1<<21,
+	fL = 1<<20,
+	fS = 1<<20,
+	fSg = 1<<6,
+	fH = 1<<5,
+};
+
+void
+invalid(u32int instr)
+{
+	fprint(2, "undefined instruction %8ux @ %8ux", instr, up->R[15] - 4);
+}
+
+u32int
+evenaddr(u32int addr, u32int mask)
+{
+	if((addr & mask) == 0)
+		return addr;
+	return addr & ~mask;
+}
+
+static u32int
+doshift(u32int instr, uint *carry)
+{
+	ulong amount, val;
+
+	val = up->R[instr & 15];
+	if(instr & (1<<4)) {
+		if(instr & (1<<7))
+			invalid(instr);
+		amount = up->R[(instr >> 8) & 15] & 0xFF;
+		if(amount == 0)
+			return val;
+	} else {
+		amount = (instr >> 7) & 31;
+		if(amount == 0 && (instr & (3<<5)) != 0)
+			amount = 32;
+	}
+	switch((instr >> 5) & 3) {
+	default:
+		if(amount == 0)
+			return val;
+		if(amount < 32) {
+			*carry = (val >> (32 - amount)) & 1;
+			return val << amount;
+		}
+		*carry = val & 1;
+		return 0;
+	case 1:
+		if(amount < 32){
+			*carry = (val >> (amount - 1)) & 1;
+			return val >> amount;
+		}
+		*carry = val >> 31;
+		return 0;
+	case 2:
+		if(amount < 32){
+			*carry = (val >> (amount - 1)) & 1;
+			return ((long) val) >> amount;
+		}
+		if((long)val < 0){
+			*carry = 1;
+			return -1;
+		}
+		*carry = 0;
+		return 0;
+	case 3:
+		amount &= 31;
+		if(amount){
+			*carry = (val >> (amount - 1)) & 1;
+			return (val >> amount) | (val << (32 - amount));
+		}
+		amount = *carry & 1;
+		*carry = val & 1;
+		return (val>>1) | (amount<<31);
+	}
+}
+
+static void
+single(u32int instr)
+{
+	long offset;
+	u32int addr;
+	u32int *Rn, *Rd;
+	void *targ;
+	Segment *seg;
+	
+	if(instr & fI) {
+		uint carry = 0;
+		if(instr & (1<<4))
+			invalid(instr);
+		offset = doshift(instr, &carry);
+	} else
+		offset = instr & ((1<<12) - 1);
+	if(!(instr & fU))
+		offset = - offset;
+	Rn = up->R + ((instr >> 16) & 15);
+	Rd = up->R + ((instr >> 12) & 15);
+	if((instr & (fW | fP)) == fW)
+		invalid(instr);
+	if(Rn == up->R + 15) {
+		if(instr & fW)
+			invalid(instr);
+		addr = up->R[15] + 4;
+	}
+	else
+		addr = *Rn;
+	if(instr & fP)
+		addr += offset;
+	if((instr & fB) == 0)
+		addr = evenaddr(addr, 3);
+	targ = vaddr(addr, (instr & fB) == 0 ? 4 : 1, &seg);
+	switch(instr & (fB | fL)) {
+	case 0:
+		*(u32int*) targ = *Rd;
+		break;
+	case fB:
+		*(uint*) targ = *Rd;
+		break;
+	case fL:
+		*Rd = *(u32int*) targ;
+		break;
+	case fB | fL:
+		*Rd = *(uint*) targ;
+		break;
+	}
+	if(Rd == up->R + 15 && !(instr & fL)) {
+		if(instr & fB)
+			*(uint*) targ += 8;
+		else
+			*(u32int*) targ += 8;
+	}
+	segunlock(seg);
+	if(!(instr & fP))
+		addr += offset;
+	if((instr & fW) || !(instr & fP))
+		*Rn = addr;
+}
+
+static void
+swap(u32int instr)
+{
+	u32int *Rm, *Rn, *Rd, *targ, addr, old, new;
+	Segment *seg;
+	
+	Rm = up->R + (instr & 15);
+	Rd = up->R + ((instr >> 12) & 15);
+	Rn = up->R + ((instr >> 16) & 15);
+	if(Rm == up->R + 15 || Rd == up->R + 15 || Rn == up->R + 15)
+		invalid(instr);
+	addr = *Rn;
+	if((instr & fB) == 0)
+		addr = evenaddr(addr, 3);
+	targ = (u32int *) vaddr(addr & ~3, 4, &seg);
+	do {
+		old = *targ;
+		new = *Rm;
+		if(instr & fB){
+			new &= 0xFF;
+			new <<= 8*(addr&3);
+			new |= old & ~(0xFF << 8*(addr&3));
+		}
+	} while(!cas((int*)targ, old, new));
+	if(instr & fB) {
+		old >>= 8*(addr&3);
+		old &= 0xFF;
+	}
+	*Rd = old;
+	segunlock(seg);
+}
+
+static u32int
+add(u32int a, u32int b, uint type, uint *carry, uint *overflow)
+{
+	u32int res1;
+	u64int res2;
+
+	if(type) {
+		res2 = (u64int)a - b + *carry - 1;
+		res1 = res2;
+		if(((a ^ b) & (1<<31)) && !((b ^ res1) & (1<<31))) *overflow = 1;
+		else *overflow = 0;
+		if(res2 & 0x100000000LL) *carry = 0;
+		else *carry = 1;	
+	} else {
+		res2 = (u64int)a + b + *carry;
+		res1 = res2;
+		if(!((a ^ b) & (1<<31)) && ((b ^ res1) & (1<<31))) *overflow = 1;
+		else *overflow = 0;
+		if(res2 & 0x100000000LL) *carry = 1;
+		else *carry = 0;
+	}
+	return res1;
+}
+
+static void
+alu(u32int instr)
+{
+	u32int Rn, *Rd, operand, shift, result, op;
+	uint carry, overflow;
+	
+	Rn = up->R[(instr >> 16) & 15];
+	Rd = up->R + ((instr >> 12) & 15);
+	if(((instr >> 16) & 15) == 15) {
+		Rn += 4;
+		if(!(instr & fI) && (instr & (1<<4)))
+			Rn += 4;
+	}
+	if(Rd == up->R + 15 && (instr & fS))
+		invalid(instr);
+
+	carry = (up->CPSR & flC) != 0;
+	overflow = (up->CPSR & flV) != 0;
+
+	if(instr & fI) {
+		operand = instr & 0xFF;
+		shift = ((instr >> 8) & 15) << 1;
+		if(shift){
+			operand = (operand >> shift) | (operand << (32 - shift));
+			carry = operand >> 31;
+		}
+	} else
+		operand = doshift(instr, &carry);
+
+	op = (instr >> 21) & 15;
+	if(op >= 8 && op <= 11 && !(instr & fS)){
+		fprint(2, "no PSR transfers plz");
+		return;
+	}
+	if(op >= 5 && op < 8)
+		carry = (up->CPSR & flC) != 0;
+	switch(op) {
+	case 0: case 8: result = Rn & operand; break;
+	case 1: case 9: result = Rn ^ operand; break;
+	case 2: case 10: carry = 1; case 6: result = add(Rn, operand, 1, &carry, &overflow); break;
+	case 3:          carry = 1; case 7: result = add(operand, Rn, 1, &carry, &overflow); break;
+	case 4: case 11: carry = 0; case 5: result = add(operand, Rn, 0, &carry, &overflow); break;
+	case 12: result = Rn | operand; break;
+	case 13: result = operand; break;
+	case 14: result = Rn & ~operand; break;
+	case 15: result = ~operand; break;
+	default: result = 0; /* never happens */
+	}
+	if(instr & fS) {
+		up->CPSR &= ~FLAGS;
+		if(result == 0)
+			up->CPSR |= flZ;
+		if(result & (1<<31))
+			up->CPSR |= flN;
+		if(carry)
+			up->CPSR |= flC;
+		if(overflow)
+			up->CPSR |= flV;
+	}
+	if(op < 8 || op >= 12)
+		*Rd = result;
+}
+
+static void
+branch(u32int instr)
+{
+	long offset;
+	
+	offset = instr & ((1<<24) - 1);
+	if(offset & (1<<23))
+		offset |= ~((1 << 24) - 1);
+	offset *= 4;
+	if(instr & fLi)
+		up->R[14] = up->R[15];
+	up->R[15] += offset + 4;
+}
+
+static void
+halfword(u32int instr)
+{
+	u32int offset, target, *Rn, *Rd;
+	Segment *seg;
+	
+	if(instr & (1<<22)) {
+		offset = (instr & 15) | ((instr >> 4) & 0xF0);
+	} else {
+		if((instr & 15) == 15)
+			invalid(instr);
+		offset = up->R[instr & 15];
+	}
+	if(!(instr & fU))
+		offset = - offset;
+	if(!(instr & fP) && (instr & fW))
+		invalid(instr);
+	Rn = up->R + ((instr >> 16) & 15);
+	Rd = up->R + ((instr >> 12) & 15);
+	if(Rn == up->R + 15 || Rd == up->R + 15)
+		fprint(2, "R15 in halfword");
+	target = *Rn;
+	if(instr & fP)
+		target += offset;
+	if(instr & fH)
+		target = evenaddr(target, 1);
+	switch(instr & (fSg | fH | fL)) {
+	case fSg: *(uint*) vaddr(target, 1, &seg) = *Rd; break;
+	case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break;
+	case fH: case fSg | fH: *(uint16_t*) vaddr(target, 2, &seg) = *Rd; break;
+	case fH | fL: *Rd = *(uint16_t*) vaddr(target, 2, &seg); break;
+	case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, 2, &seg); break;
+	}
+	segunlock(seg);
+	if(!(instr & fP))
+		target += offset;
+	if(!(instr & fP) || (instr & fW))
+		*Rn = target;
+}
+
+static void
+block(u32int instr)
+{
+	int i;
+	u32int targ, *Rn;
+	Segment *seg;
+
+	print("Checking invalid\n");
+	if(instr & (1<<22))
+		invalid(instr);
+	
+	Rn = up->R +((instr >> 16) & 15);
+	if(Rn == up->R + 15 || instr & (1<<15))
+		print("R15 in block");
+	targ = evenaddr(*Rn, 3);
+	if(instr & fU) {
+		for(i = 0; i < 16; i++) {
+			if(!(instr & (1<<i)))
+				continue;
+			if(instr & fP)
+				targ += 4;
+			if(instr & fL)
+				up->R[i] = *(u32int*) vaddr(targ, 4, &seg);
+			else
+				*(u32int*) vaddr(targ, 4, &seg) = up->R[i];
+			segunlock(seg);
+			if(!(instr & fP))
+				targ += 4;
+		}
+	} else {
+		for(i = 15; i >= 0; i--) {
+			if(!(instr & (1<<i)))
+				continue;
+			if(instr & fP)
+				targ -= 4;
+			if(instr & fL)
+				up->R[i] = *(u32int*) vaddr(targ, 4, &seg);
+			else
+				*(u32int*) vaddr(targ, 4, &seg) = up->R[i];
+			segunlock(seg);
+			if(!(instr & fP))
+				targ -= 4;
+		}
+	}
+	if(instr & fW)
+		*Rn = targ;
+	print("Farnished\n");
+}
+
+static void
+multiply(u32int instr)
+{
+	u32int *Rd, *Rn, *Rs, *Rm, res;
+	
+	Rm = up->R + (instr & 15);
+	Rs = up->R + ((instr >> 8) & 15);
+	Rn = up->R + ((instr >> 12) & 15);
+	Rd = up->R + ((instr >> 16) & 15);
+	if(Rd == Rm || Rm == up->R + 15 || Rs == up->R + 15 || Rn == up->R + 15 || Rd == up->R + 15)
+		invalid(instr);
+	res = *Rm * *Rs;
+	if(instr & (1<<21))
+		res += *Rn;
+	*Rd = res;
+	if(instr & (1<<20)) {
+		up->CPSR &= ~(flN | flZ);
+		if(res & (1<<31))
+			up->CPSR |= flN;
+		if(res == 0)
+			up->CPSR |= flZ;
+	}
+}
+
+static void
+multiplylong(u32int instr)
+{
+	u32int *RdH, *RdL, *Rs, *Rm;
+	u64int res;
+	
+	Rm = up->R + (instr & 15);
+	Rs = up->R + ((instr >> 8) & 15);
+	RdL = up->R + ((instr >> 12) & 15);
+	RdH = up->R + ((instr >> 16) & 15);
+	if(RdL == RdH || RdH == Rm || RdL == Rm || Rm == up->R + 15 || Rs == up->R + 15 || RdL == up->R + 15 || RdH == up->R + 15)
+		invalid(instr);
+	if(instr & (1<<22))
+		res = ((vlong)*(int*)Rs) * *(int*)Rm;
+	else {
+		res = *Rs;
+		res *= *Rm;
+	}
+	if(instr & (1<<21)) {
+		res += *RdL;
+		res += ((uvlong)*RdH) << 32;
+	}
+	*RdL = res;
+	*RdH = res >> 32;
+	if(instr & (1<<20)) {
+		up->CPSR &= ~FLAGS;
+		if(res == 0)
+			up->CPSR |= flN;
+		if(res & (1LL<<63))
+			up->CPSR |= flV;
+	}
+}
+
+static void
+singleex(u32int instr)
+{
+	u32int *Rn, *Rd, *Rm, *targ, addr;
+	Segment *seg;
+	
+	Rd = up->R + ((instr >> 12) & 15);
+	Rn = up->R + ((instr >> 16) & 15);
+	if(Rd == up->R + 15 || Rn == up->R + 15)
+		invalid(instr);
+	addr = evenaddr(*Rn, 3);
+	if(instr & fS) {
+		targ = vaddr(addr, 4, &seg);
+		*Rd = *targ;
+		up->lladdr = addr;
+		up->llval = *Rd;
+		segunlock(seg);
+	} else {
+		Rm = up->R + (instr & 15);
+		if(Rm == up->R + 15)
+			invalid(instr);
+		targ = vaddr(addr, 4, &seg);
+
+		/*
+		 * this is not quite correct as we will succeed even
+		 * if the value was modified and then restored to its
+		 * original value but good enough approximation for
+		 * libc's _tas(), _cas() and _xinc()/_xdec().
+		 */
+		*Rd = addr != up->lladdr || !cas((int*)targ, up->llval, *Rm);
+		segunlock(seg);
+		clrex();
+	}
+}
+
+void
+clrex(void)
+{
+	up->lladdr = 0;
+	up->llval = 0;
+}
+
+static void
+barrier(void)
+{
+	static Lock l;
+
+	lock(&l);
+	unlock(&l);
+}
+
+int
+step(void)
+{
+	u32int instr;
+	Segment *seg;
+print("Grabbing instruction\n");
+	instr = *(u32int*) vaddr(up->R[15], 4, &seg);
+print("Grabbed instruction\n");
+	segunlock(seg);
+
+	up->R[15] += 4;
+	switch(instr >> 28) {
+	case 0x0: if(!(up->CPSR & flZ)) return 1; break;
+	case 0x1: if(up->CPSR & flZ) return 1; break;
+	case 0x2: if(!(up->CPSR & flC)) return 1; break;
+	case 0x3: if(up->CPSR & flC) return 1; break;
+	case 0x4: if(!(up->CPSR & flN)) return 1; break;
+	case 0x5: if(up->CPSR & flN) return 1; break;
+	case 0x6: if(!(up->CPSR & flV)) return 1; break;
+	case 0x7: if(up->CPSR & flV) return 1; break;
+	case 0x8: if(!(up->CPSR & flC) || (up->CPSR & flZ)) return 1; break;
+	case 0x9: if((up->CPSR & flC) && !(up->CPSR & flZ)) return 1; break;
+	case 0xA: if(!(up->CPSR & flN) != !(up->CPSR & flV)) return 1; break;
+	case 0xB: if(!(up->CPSR & flN) == !(up->CPSR & flV)) return 1; break;
+	case 0xC: if((up->CPSR & flZ) || !(up->CPSR & flN) != !(up->CPSR & flV)) return 1; break;
+	case 0xD: if(!(up->CPSR & flZ) && !(up->CPSR & flN) == !(up->CPSR & flV)) return 1; break;
+	case 0xE: break;
+	case 0xF:
+		switch(instr & 0xFFF000F0){
+		case 0xF5700010:	/* CLREX */
+		print("clrex\n");
+			//clrex();
+			return 1;
+		case 0xF5700040:	/* DSB */
+		case 0xF5700050:	/* DMB */
+		case 0xF5700060:	/* ISB */
+		print("barrier\n");
+			//barrier();
+			return 1;
+		}
+	default: 
+		fprint(2, "condition code %x not implemented (instr %ux, ps %ux)", instr >> 28, instr, up->R[15]);
+		return 0;
+	}
+	if((instr & 0x0FB00FF0) == 0x01000090)
+	print("Swap\n");
+		//swap(instr);
+	else if((instr & 0x0FE000F0) == 0x01800090)
+	print("Singleex\n");
+		//singleex(instr);
+	else if((instr & 0x0FC000F0) == 0x90)
+	print("Multiply\n");
+		//multiply(instr);
+	else if((instr & 0x0F8000F0) == 0x800090)
+	print("Multiplylong\n");
+		//multiplylong(instr);
+	else if((instr & ((1<<26) | (1<<27))) == (1 << 26))
+	print("Single\n");
+		//single(instr);
+	else if((instr & 0x0E000090) == 0x90 && (instr & 0x60))
+	print("Halfword\n");
+		//halfword(instr);
+	else if((instr & ((1<<26) | (1<<27))) == 0)
+	print("Alu\n");
+		//alu(instr);
+	else if((instr & (7<<25)) == (5 << 25))
+	print("Branch\n");
+		//branch(instr);
+	else if((instr & (15<<24)) == (15 << 24))
+	print("Syscall\n");
+		//_syscall();
+	else if((instr & (7<<25)) == (4 << 25))
+	print("Block\n");
+		//block(instr);
+	else if((instr & 0x0E000F00) == 0x0C000100)
+	print("Fpatransfer\n");
+		//fpatransfer(instr);
+	else if((instr & 0x0E000F10) == 0x0E000100)
+	print("Fpaoperation\n");
+		//fpaoperation(instr);
+	else if((instr & 0x0E000F10) == 0x0E000110)
+	print("Fparegtransfer\n");
+		//fparegtransfer(instr);
+	else if((instr & 0x0F000A10) == 0x0E000A00)
+	print("Vfpoperation\n");
+		//vfpoperation(instr);
+	else if((instr & 0x0F000F10) == 0x0E000A10)
+	print("Vfpregtransfer\n");
+		//vfpregtransfer(instr);
+	else if((instr & 0x0F000A00) == 0x0D000A00)
+	print("Vfprmtransfer\n");
+		//vfprmtransfer(instr);
+	else {
+		print("Invalid\n");
+		invalid(instr);
+		return 0;
+	}
+	return 1;
+}
\ No newline at end of file
--- a/kern/dat.h
+++ b/kern/dat.h
@@ -1,7 +1,6 @@
 #define	KNAMELEN		28	/* max length of name held in kernel */
 
 //#define	BLOCKALIGN		8
-typedef struct Binary	Binary;
 typedef struct Block	Block;
 typedef struct Chan	Chan;
 typedef struct Cmdbuf	Cmdbuf;
@@ -120,16 +119,21 @@
 	Bpktck	=	(1<<5),		/* packet checksum */
 };
 
-/* Not using segments, so this is our holder */
-struct Binary
-{
-	uintptr entry;
-	uintptr text;
-	uintptr data;
-	uintptr bss;
-	uintptr bs;
-	uintptr ts;
-	uintptr ds;
+enum {
+	STACKSIZE = 0x100000,
+	NAMEMAX = 27,
+	NSMAX	=	1000,
+	NNOTE = 5,
+	NSLOG = 7,
+	SEGNUM = 8,
+	Nfpregs = 16,
+	NSCACHE	=	(1<<NSLOG),
+
+	flN = 1<<31,
+	flZ = 1<<30,
+	flC = 1<<29,
+	flV = 1<<28,
+	FLAGS = flN | flZ | flC | flV,
 };
 
 struct Block
@@ -232,14 +236,6 @@
 	Qid	qid[1];
 };
 
-enum
-{
-	NSMAX	=	1000,
-	NSLOG	=	7,
-	NSCACHE	=	(1<<NSLOG),
-	NNOTE   =   5,
-};
-
 struct Mntwalk				/* state for /proc/#/ns */
 {
 	int		cddone;
@@ -359,7 +355,7 @@
 	SEGDATA,
 	SEGBSS,
 	SEGSTACK,
-	SEGNUM = 8,
+	SEGFLLOCK = 1,
 };
 
 
@@ -383,7 +379,7 @@
 
 	Lock	rlock;		/* sync sleep/wakeup with postnote */
 	Rendez	*r;		/* rendezvous point slept on */
-	Rendez	sleep;		/* place for syssleep/debug */
+	Rendez	rsleep;		/* place for syssleep/debug */
 	int	notepending;	/* note issued but not acted on */
 	int	kp;		/* true if a kernel process */
 
@@ -401,10 +397,16 @@
 	char	genbuf[128];	/* buffer used e.g. for last name element from namec */
 	char	text[KNAMELEN];
 
+
 	u32int lladdr;		/* LL/SC emulation */
 	u32int llval;
 
+	u32int CPSR;		/* status register */
 
+	u32int FPSR;
+	double F[Nfpregs];
+	int		fd; 		/* fd for syscall emulation */
+
 	/* Notes */
 	u32int notehandler;
 	int innote;
@@ -415,19 +417,16 @@
 	Chan	*dot;
 
 	Proc	*qnext;
-	Binary  *bin;
-
+	
 	void	(*fn)(void*);
 	void	*arg;
 
 	char oproc[1024];	/* reserved for os */
-	u32int CPSR;		/* status register for step */
-	/* TODO: Multiarch */
+
 	u32int R[16];		/* general purpose registers / PC (R15) */
 	Segment *S[SEGNUM];
 };
 
-
 struct Segment {
 	Ref ref;
 	int flags;
@@ -529,3 +528,4 @@
 };
 
 extern Kmesg kmesg;
+
--- a/kern/devmnt.c
+++ b/kern/devmnt.c
@@ -744,7 +744,7 @@
 	}
 
 	lock(&m->lk);
-	r->z = &up->sleep;
+	r->z = &up->rsleep;
 	r->m = m;
 	r->list = m->queue;
 	m->queue = r;
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -2,13 +2,14 @@
 
 Block*		adjustblock(Block*, int);
 Block*		allocb(int);
-int		blocklen(Block*);
+int		    blocklen(Block*);
+void        *bufifnec(u32int, int, int *);
 char*		chanpath(Chan*);
-int		cangetc(void*);
-int		canlock(Lock*);
-int		canputc(void*);
-int		canqlock(QLock*);
-int		canrlock(RWlock*);
+int	    	cangetc(void*);
+int 		canlock(Lock*);
+int		    canputc(void*);
+int	    	canqlock(QLock*);
+int 		canrlock(RWlock*);
 void		chandevinit(void);
 void		chandevreset(void);
 void		chandevshutdown(void);
@@ -17,8 +18,9 @@
 void		checkb(Block*, char*);
 Chan*		cclone(Chan*);
 void		cclose(Chan*);
-char*	clipread(void);
-int		clipwrite(char*);
+char*	    clipread(void);
+int		    clipwrite(char*);
+void        clrex(void);
 void		closeegrp(Egrp*);
 void		closefgrp(Fgrp*);
 void		closemount(Mount*);
@@ -25,22 +27,24 @@
 void		closepgrp(Pgrp*);
 void		closergrp(Rgrp*);
 void		cmderror(Cmdbuf*, char*);
-int		cmount(Chan*, Chan*, int, char*);
+int		    cmount(Chan*, Chan*, int, char*);
 Block*		concatblock(Block*);
+void        copyback(u32int, int, void *);
 Block*		copyblock(Block*, int);
+void        *copyifnec(u32int, int, int *);
 void		cunmount(Chan*, Chan*);
-int		decref(Ref*);
+int		    decref(Ref*);
 Chan*		devattach(int, char*);
 Block*		devbread(Chan*, long, ulong);
 long		devbwrite(Chan*, Block*, ulong);
 Chan*		devclone(Chan*);
-int		devconfig(int, char *, DevConf *);
+int		    devconfig(int, char *, DevConf *);
 Chan*		devcreate(Chan*, char*, int, ulong);
 void		devdir(Chan*, Qid, char*, vlong, char*, long, Dir*);
 long		devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
 Devgen		devgen;
 void		devinit(void);
-int		devno(int, int);
+int		    devno(int, int);
 Chan*		devopen(Chan*, int, Dirtab*, int, Devgen*);
 void		devpermcheck(char*, ulong, int);
 void		devpower(int);
@@ -47,24 +51,30 @@
 void		devremove(Chan*);
 void		devreset(void);
 void		devshutdown(void);
-int		devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
+int		    devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
 Walkqid*	devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
-int		devwstat(Chan*, uchar*, int);
+int	    	devwstat(Chan*, uchar*, int);
 Dir*		dirchanstat(Chan*);
 void		drawcmap(void);
+void        donote(char *, ulong);
 Fgrp*		dupfgrp(Fgrp*);
-int		emptystr(char*);
+int		    emptystr(char*);
 void		envcpy(Egrp*, Egrp*);
-int		eqchan(Chan*, Chan*, int);
-int		eqqid(Qid, Qid);
+int	    	eqchan(Chan*, Chan*, int);
+int 		eqqid(Qid, Qid);
 void		error(char*);
+u32int      evenaddr(u32int,u32int);
 void		exhausted(char*);
 void		exit(int);
 void        fdclose(int, int);
 Chan*		fdtochan(int, int, int, int);
+void        fpatransfer(u32int);
+void        fpaoperation(u32int);
+void        fparegtransfer(u32int);
 void		free(void*);
 void		freeb(Block*);
 void		freeblist(Block*);
+void        freesegs(void);
 uintptr		getmalloctag(void*);
 uintptr		getrealloctag(void*);
 void		gotolabel(Label*);
@@ -74,14 +84,15 @@
 Block*		iallocb(int);
 void		ilock(Lock*);
 void		iunlock(Lock*);
-int		incref(Ref*);
-int		iprint(char*, ...);
+int 		incref(Ref*);
+void        invalid(u32int);
+int	    	iprint(char*, ...);
 void		isdir(Chan*);
-int		iseve(void);
+int		    iseve(void);
 #define	islo()	(0)
-int		kbdputc(Queue*, int);
+int	    	kbdputc(Queue*, int);
 void		kbdkey(Rune, int);
-int		kproc(char*, void(*)(void*), void*);
+int		    kproc(char*, void(*)(void*), void*);
 void		ksetenv(char*, char*, int);
 void		kstrcpy(char*, char*, int);
 void		kstrdup(char**, char*);
@@ -108,7 +119,8 @@
 void		muxclose(Mnt*);
 Chan*		namec(char*, int, int, ulong);
 Chan*		newchan(void);
-int		newfd(Chan*);
+Segment     *newseg(u32int, u32int, int);
+int		    newfd(Chan*);
 Mhead*		newmhead(Chan*);
 Mount*		newmount(Chan*, int, char*);
 Path*		newpath(char*);
@@ -117,10 +129,10 @@
 Proc*		newproc(void);
 char*		nextelem(char*, char*);
 void		nexterror(void);
-int		openmode(ulong);
+int 		openmode(ulong);
 void*		oscmd(char**, int, char*, Chan**);
-int		oscmdwait(void*, char*, int);
-int		oscmdkill(void*);
+int	    	oscmdwait(void*, char*, int);
+int		    oscmdkill(void*);
 void		oscmdfree(void*);
 void		oserrstr(void);
 void		oserror(void);
@@ -132,48 +144,48 @@
 void		pathclose(Path*);
 void		pexit(char*, int);
 void		printinit(void);
-int		procindex(ulong);
+int	    	procindex(ulong);
 void		pgrpcpy(Pgrp*, Pgrp*);
 void		pgrpnote(ulong, char*, long, int);
 Pgrp*		pgrptab(int);
 #define		poperror()		up->nerrlab--
-int		postnote(Proc*, int, char*, int);
-int		pprint(char*, ...);
-int		procfdprint(Chan*, int, int, char*, int);
+int		    postnote(Proc*, int, char*, int);
+int	        pprint(char*, ...);
+int		    procfdprint(Chan*, int, int, char*, int);
 void		procinit0(void);
 Proc*		proctab(int);
 void		procwired(Proc*, int);
-int		pullblock(Block**, int);
+int		    pullblock(Block**, int);
 Block*		pullupblock(Block*, int);
 Block*		pullupqueue(Queue*, int);
 void		putmhead(Mhead*);
 void		putstr(char*);
 void		putstrn(char*, int);
-Label*	pwaserror(void);
+Label*	    pwaserror(void);
 long		readblist(Block*, uchar*, long, ulong);
-int		qaddlist(Queue*, Block*);
+int		    qaddlist(Queue*, Block*);
 Block*		qbread(Queue*, int);
 long		qbwrite(Queue*, Block*);
 Queue*		qbypass(void (*)(void*, Block*), void*);
-int		qcanread(Queue*);
+int 		qcanread(Queue*);
 void		qclose(Queue*);
-int		qconsume(Queue*, void*, int);
+int	    	qconsume(Queue*, void*, int);
 Block*		qcopy(Queue*, int, ulong);
-int		qdiscard(Queue*, int);
+int		    qdiscard(Queue*, int);
 void		qflush(Queue*);
 void		qfree(Queue*);
-int		qfull(Queue*);
+int 		qfull(Queue*);
 Block*		qget(Queue*);
-void		qhangup(Queue*, char*);
-int		qisclosed(Queue*);
+void   		qhangup(Queue*, char*);
+int		    qisclosed(Queue*);
 void		qinit(void);
-int		qiwrite(Queue*, void*, int);
-int		qlen(Queue*);
+int		    qiwrite(Queue*, void*, int);
+int		    qlen(Queue*);
 void		qlock(QLock*);
 Queue*		qopen(int, int, void (*)(void*), void*);
-int		qpass(Queue*, Block*);
-int		qpassnolim(Queue*, Block*);
-int		qproduce(Queue*, void*, int);
+int 		qpass(Queue*, Block*);
+int	    	qpassnolim(Queue*, Block*);
+int		    qproduce(Queue*, void*, int);
 void		qputback(Queue*, Block*);
 long		qread(Queue*, void*, int);
 Block*		qremove(Queue*);
@@ -180,21 +192,24 @@
 void		qreopen(Queue*);
 void		qsetlimit(Queue*, int);
 void		qunlock(QLock*);
-int		qwindow(Queue*);
-int		qwrite(Queue*, void*, int);
+int 		qwindow(Queue*);
+int	    	qwrite(Queue*, void*, int);
 void		qnoblock(Queue*, int);
 void		randominit(void);
 ulong		randomread(void*, ulong);
-int		readnum(ulong, char*, ulong, ulong, int);
-int		readstr(ulong, char*, ulong, char*);
-int		return0(void*);
+int		    readnum(ulong, char*, ulong, ulong, int);
+int 		readstr(ulong, char*, ulong, char*);
+int	    	return0(void*);
 void		rlock(RWlock*);
 void		runlock(RWlock*);
-extern void		(*screenputs)(char*, int);
+extern void	(*screenputs)(char*, int);
 void*		secalloc(ulong);
 void		secfree(void*);
 long		seconds(void);
-int		setlabel(Label*);
+void        segunlock(Segment*);
+int         semacquire(long*, int);
+int         semrelease(long*, long);
+int 		setlabel(Label*);
 void		setmalloctag(void*, uintptr);
 void		setrealloctag(void*, uintptr);
 long		showfilewrite(char*, int);
@@ -201,33 +216,37 @@
 char*		skipslash(char*);
 void		sleep(Rendez*, int(*)(void*), void*);
 void*		smalloc(ulong);
-int		splhi(void);
-int		spllo(void);
+int	    	splhi(void);
+int		    spllo(void);
 void		splx(int);
+int         step(void);
+void        _syscall(void);
 Block*		trimblock(Block*, int, int);
 long		unionread(Chan*, void*, long);
 void		unlock(Lock*);
+void        *vaddr(u32int, u32int, Segment **);
+void        *vaddrnol(u32int, u32int);
 #define	    validaddr(one, two, three);
 void		validname(char*, int);
 char*		validnamedup(char*, int);
 void		validstat(uchar*, int);
+void        vfpregtransfer(u32int);
+void        vfprmtransfer(u32int);
+void        vfpoperation(u32int);
 void*		vmemchr(void*, int, ulong);
 Proc*		wakeup(Rendez*);
-int		walk(Chan**, char**, int, int, int*);
-#define	waserror()	(setjmp(pwaserror()->buf))
+int		    walk(Chan**, char**, int, int, int*);
+#define	    waserror()	(setjmp(pwaserror()->buf))
 void		wlock(RWlock*);
 void		wunlock(RWlock*);
 void		osyield(void);
 void		osmsleep(int);
-ulong	ticks(void);
-void	osproc(Proc*);
-void    *osbuildmem(Chan *, uintptr, uintptr, uintptr, int, uintptr);
-void    osprepmem(void*, uintptr, uintptr, uintptr, uintptr);
-void	osnewproc(Proc*);
-void    osclrmem(uintptr, uintptr);
-void	procsleep(void);
-void	procwakeup(Proc*);
-void	osinit(void);
-void	screeninit(void);
+ulong   	ticks(void);
+void	    osproc(Proc*);
+void	    osnewproc(Proc*);
+void	    procsleep(void);
+void	    procwakeup(Proc*);
+void	    osinit(void);
+void	    screeninit(void);
 extern	void	terminit(void);
 extern	void	setterm(int);
--- a/kern/posix.c
+++ b/kern/posix.c
@@ -266,88 +266,6 @@
 	return snprint(status, nstatus, "%d 0 0 0 'odd status: 0x%x'", pid, s);
 }
 
-void
-osclrmem(uintptr mem, uintptr ms)
-{
-
-	if(mem)
-#if defined __APPLE__
-		mach_vm_deallocate(task, (mach_vm_address_t)mem, (mach_vm_size_t)ms);
-#else
-		munmap((void*)mem, ms);
-#endif
-}
-
-void *
-osbuildmem(Chan *tc, uintptr ts, uintptr ds, uintptr bss, int offset, uintptr align)
-{
-    int n;
-    void *exec, *binary;
-    size_t total_size;
-
-    /* Read in initial datum */
-    exec = mallocz(ts+ds, 1);
-    n = devtab[tc->type]->read(tc, exec, ts+ds, offset);
-    if(!exec || n < (ts+ds) || n < 0)
-        error("read error: %r");
-
-#if defined __APPLE__
-    kern_return_t kr;
-    mach_vm_address_t base = 0;
-    mach_vm_size_t size = (mach_vm_size_t)(n + bss + align);
-
-    kr = mach_vm_allocate(task, &base, size, VM_FLAGS_ANYWHERE);
-    if(kr != KERN_SUCCESS) 
-		error("unable to allocate: %r");
-    
-    binary = (void*)base;
-#else
-    /* Contiguous memory block - start with RW for setup */
-    binary = mmap(nil, n+bss+align, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
-    if(binary == MAP_FAILED)
-        error("Failed: %r");
-#endif
-    /* Copy the binary data (text + data sections) */
-    memcpy(binary, exec, n);
-    free(exec);
-    return binary;
-}
-
-void
-osprepmem(void *base, uintptr b, uintptr text, uintptr data, uintptr bss)
-{
-	uintptr *ptr, end, offset;
-
-	end = (uintptr)b+text+data;
-	offset = (uintptr)b;
-
-	/* If we needed to align, copy the data to the aligned location */
-	if(b != (uintptr)base)
-		memmove((void*)b, base, text+data);
-
-	/* Zero out BSS section at aligned location */
-	memset((void*)b + text + data, 0, bss);
-
-	/* Patch the text + data sections to meet our new base */
-    for(ptr = (uintptr*)b; (uintptr)ptr < end; ptr++) {
-        uintptr val = *ptr;
-        if(val >= UTZERO && val <= (UTZERO + text + data)) {
-            *ptr = val + offset;
-        }
-    }
-
-#if defined __APPLE__
-    kern_return_t kr;
-    kr = mach_vm_protect(task, (mach_vm_address_t)b, (mach_vm_size_t)text, FALSE, VM_PROT_READ|VM_PROT_EXECUTE);
-    if(kr != KERN_SUCCESS)
-        print("Unable to vm_protect aligned text section: %s\n", mach_error_string(kr));
-#else
-	/* Set proper memory permissions for aligned sections */
-	if(mprotect((void*)b, text, PROT_READ|PROT_EXEC) != 0)
-		print("Unable to mprotect aligned text section: %r\n");
-#endif
-}
-
 int
 oscmdkill(void *c)
 {
--- /dev/null
+++ b/kern/seg.c
@@ -1,0 +1,136 @@
+#include <u.h>
+#include <lib.h>
+#include "dat.h"
+#include "fns.h"
+
+// TODO: Update to 64 bit
+Segment *
+newseg(u32int start, u32int size, int idx)
+{
+	Segment *s;
+	
+	s = mallocz(sizeof *s, 1);
+	incref(&s->ref);
+	s->start = start;
+	s->size = size;
+	s->dref = malloc(size + sizeof(Ref));
+	memset(s->dref, 0, sizeof(Ref));
+	incref(s->dref);
+	s->data = s->dref + 1;
+	if(idx == SEGBSS)
+		s->flags = SEGFLLOCK;
+	up->S[idx] = s;
+	return s;
+}
+
+void
+freesegs(void)
+{
+	Segment **s, *ss;
+	
+	for(s = up->S; s < up->S + SEGNUM; s++) {
+		if(*s == nil)
+			continue;
+		ss = *s;
+		if(decref((*s)->dref) == 0)
+			free((*s)->dref);
+		if(decref(&ss->ref) == 0)
+			free(*s);
+		*s = nil;
+	}
+}
+
+void *
+vaddr(u32int addr, u32int len, Segment **seg)
+{
+	Segment **ss, *s;
+	for(ss = up->S; ss < up->S + SEGNUM; ss++) {
+		if(*ss == nil)
+			continue;
+		s = *ss;
+		if(addr >= s->start && addr < s->start + s->size) {
+			if(addr + len > s->start + s->size)
+				break;
+			if(s->flags & SEGFLLOCK)
+				rlock(&s->rw);
+			*seg = s;
+			return (char *)s->data + (addr - s->start);
+		}
+	}
+	fprint(2, "fault %.8ux (%d) @ %.8ux", addr, len, up->R[15]);
+	return nil;
+}
+
+void *
+vaddrnol(u32int addr, u32int len)
+{
+	Segment *seg;
+	void *ret;
+	
+	ret = vaddr(addr, len, &seg);
+	segunlock(seg);
+	return ret;
+}
+
+/* might be made a macro for hurr durr performance */
+void
+segunlock(Segment *s)
+{
+	if(s->flags & SEGFLLOCK)
+		runlock(&s->rw);
+}
+
+void *
+copyifnec(u32int addr, int len, int *copied)
+{
+	void *targ, *ret;
+	Segment *seg;
+	
+	targ = vaddr(addr, len > 0 ? len : 0, &seg);
+	if((seg->flags & SEGFLLOCK) == 0) {
+		*copied = 0;
+		return targ;
+	}
+	if(len < 0)
+		len = strlen(targ) + 1;
+	ret = malloc(len);
+	setmalloctag(ret, getcallerpc(&addr));
+	memcpy(ret, targ, len);
+	segunlock(seg);
+	*copied = 1;
+	return ret;
+}
+
+void *
+bufifnec(u32int addr, int len, int *buffered)
+{
+	void *targ, *v;
+	Segment *seg;
+	
+	targ = vaddr(addr, len, &seg);
+	if((seg->flags & SEGFLLOCK) == 0) {
+		*buffered = 0;
+		return targ;
+	}
+	segunlock(seg);
+	*buffered = 1;
+	v = malloc(len);
+	setmalloctag(v, getcallerpc(&addr));
+	return v;
+}
+
+void
+copyback(u32int addr, int len, void *data)
+{
+	void *targ;
+	Segment *seg;
+
+	if(len <= 0) {
+		free(data);
+		return;
+	}
+	targ = vaddr(addr, len, &seg);
+	memmove(targ, data, len);
+	segunlock(seg);
+	free(data);
+}
\ No newline at end of file
--- /dev/null
+++ b/kern/sema.c
@@ -1,0 +1,188 @@
+/* Semaphore implementation for Plan 9 emulator */
+
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "user.h"
+
+/* Semaphore wait queue entry */
+typedef struct Semwait Semwait;
+struct Semwait {
+    Semwait *next;
+    Proc *proc;
+    long *addr;
+};
+
+static Lock semlock;
+static Semwait *semwait;
+
+
+/*
+ * Semaphore sleep condition function
+ * Called by sleep() to check if we should continue sleeping
+ */
+int
+semwakeup(void *arg)
+{
+    long *addr = (long*)arg;
+    
+    /* Return 0 to continue sleeping, 1 to wake up */
+    return *addr > 0;
+}
+
+/*
+ * semacquire - acquire semaphore
+ * addr: pointer to semaphore counter
+ * block: 1 to block if unavailable, 0 to return immediately
+ * 
+ * Returns: 0 on success, -1 on error
+ */
+int
+semacquire(long *addr, int block)
+{
+    Semwait *w, **l;
+    
+    if(addr == nil) {
+        werrstr("semacquire: nil address");
+        return -1;
+    }
+    
+    lock(&semlock);
+    
+    /* Try to decrement the semaphore */
+    if(*addr > 0) {
+        (*addr)--;
+        unlock(&semlock);
+        return 0;
+    }
+    
+    /* Semaphore is 0, can't acquire */
+    if(!block) {
+        unlock(&semlock);
+        werrstr("semacquire: would block");
+        return -1;
+    }
+    
+    /* Block until semaphore is available */
+    w = malloc(sizeof(Semwait));
+    if(w == nil) {
+        unlock(&semlock);
+        werrstr("semacquire: out of memory");
+        return -1;
+    }
+    
+    w->addr = addr;
+    w->proc = up;
+    w->next = semwait;
+    semwait = w;
+    
+    /* Use the existing sleep rendezvous mechanism */
+    up->state = Wakeme;
+    unlock(&semlock);
+    
+    /* Sleep on the semaphore address as rendezvous point */
+    if(waserror()) {
+        /* Interrupted - remove from wait queue */
+        lock(&semlock);
+        for(l = &semwait; *l; l = &(*l)->next) {
+            if(*l == w) {
+                *l = w->next;
+                break;
+            }
+        }
+        unlock(&semlock);
+        free(w);
+        nexterror();
+    }
+    
+    ksleep(&up->rsleep, semwakeup, addr);
+    poperror();
+    
+    return 0;
+}
+
+/*
+ * semrelease - release semaphore
+ * addr: pointer to semaphore counter  
+ * count: number of times to increment semaphore
+ *
+ * Returns: 0 on success, -1 on error
+ */
+int
+semrelease(long *addr, long count)
+{
+    Semwait *w, **l;
+    Proc *p;
+    
+    if(addr == nil) {
+        werrstr("semrelease: nil address");
+        return -1;
+    }
+    
+    if(count <= 0) {
+        werrstr("semrelease: bad count");
+        return -1;
+    }
+    
+    lock(&semlock);
+    
+    /* Increment the semaphore counter */
+    *addr += count;
+    
+    /* Wake up waiting processes */
+    l = &semwait;
+    while(*l && count > 0) {
+        w = *l;
+        if(w->addr == addr) {
+            /* Remove from wait list */
+            *l = w->next;
+            
+            /* Wake up the process */
+            p = w->proc;
+            wakeup(&p->rsleep);
+            
+            free(w);
+            count--;
+            (*addr)--; /* Process will consume one count */
+        } else {
+            l = &w->next;
+        }
+    }
+    
+    unlock(&semlock);
+    return 0;
+}
+
+/*
+ * Helper function to clean up semaphore waiters when process exits
+ * Call this from your process cleanup code
+ */
+void
+cleansemwait(Proc *p)
+{
+    Semwait *w, **l;
+    
+    lock(&semlock);
+    l = &semwait;
+    while(*l) {
+        w = *l;
+        if(w->proc == p) {
+            *l = w->next;
+            free(w);
+        } else {
+            l = &w->next;
+        }
+    }
+    unlock(&semlock);
+}
+
+/*
+ * Initialize semaphore system - call during startup
+ */
+void
+seminit(void)
+{
+    semwait = nil;
+}
\ No newline at end of file
--- /dev/null
+++ b/kern/sys.h
@@ -1,0 +1,52 @@
+#define	SYSR1		0
+#define	_ERRSTR		1
+#define	BIND		2
+#define	CHDIR		3
+#define	CLOSE		4
+#define	DUP		5
+#define	ALARM		6
+#define	EXEC		7
+#define	EXITS		8
+#define	_FSESSION	9
+#define	FAUTH		10
+#define	_FSTAT		11
+#define	SEGBRK		12
+#define	_MOUNT		13
+#define	OPEN		14
+#define	_READ		15
+#define	OSEEK		16
+#define	SLEEP		17
+#define	_STAT		18
+#define	RFORK		19
+#define	_WRITE		20
+#define	PIPE		21
+#define	CREATE		22
+#define	FD2PATH		23
+#define	BRK_		24
+#define	REMOVE		25
+#define	_WSTAT		26
+#define	_FWSTAT		27
+#define	NOTIFY		28
+#define	NOTED		29
+#define	SEGATTACH	30
+#define	SEGDETACH	31
+#define	SEGFREE		32
+#define	SEGFLUSH	33
+#define	RENDEZVOUS	34
+#define	UNMOUNT		35
+#define	_WAIT		36
+#define	SEMACQUIRE	37
+#define	SEMRELEASE	38
+#define	SEEK		39
+#define	FVERSION	40
+#define	ERRSTR		41
+#define	STAT		42
+#define	FSTAT		43
+#define	WSTAT		44
+#define	FWSTAT		45
+#define	MOUNT		46
+#define	AWAIT		47
+#define	PREAD		50
+#define	PWRITE		51
+#define	TSEMACQUIRE	52
+#define _NSEC		53
\ No newline at end of file
--- a/kern/syscall.c
+++ b/kern/syscall.c
@@ -4,92 +4,650 @@
 #include "fns.h"
 #include "error.h"
 #include "user.h"
+#include "sys.h"
 
-long
-sysintercept(void* r0, void* r1, void* r2, void* r3, void* r4, void* r5, void* r6)
+static u32int
+arg(int n)
 {
-    print("Interception %d\n", r0);
-    long ret = -1;
-    switch((int)r0){
-        case 0: /* SYSR1 */
-            ret = 0;
-            break;
-        case 1: /* _ERRSTR */
-            ret = errstr((char*)r1, 64);
-            break;
-        case 2: /* BIND */
-            ret = bind((char*) r1, (char*)r2, (int) r3);
-            break;
-        case 3: /* CHDIR */
-            ret = chdir((char *)r1);
-            break;
-        case 4: /* CLOSE */
-            ret = close((int)r1);
-            break;
-        case 5: /* DUP */
-            ret = dup((int)r1, (int)r2);
-            break;
-    	case 6: /* ALARM */
-            ret = alarm((int) r1);
-            break;
-        case 7: /* EXEC */
-            ret = exec((int) r1, (char**)r2);
-            break;
-        case 8: /* EXITS */
-            exits((char*)r1);
-            ret = 0;
-            break;
-        case 9: /* _FSESSION */
-            //ret = fsession();
-            break;
-        case 10: /* FAUTH */
-            // ret = fauth();
-            break;
-        case 11: /* _FSTAT */
-            ret = fstat((int) r1, (char*) r2, (int)r3);
-            break;  
-        case 12: /* SEGBRK */
-        case 13: /* _MOUNT */
-        case 14: /* OPEN */
-        case 15: /* _READ */
-        case 16: /* OSEEK */
-        case 17: /* SLEEP */
-        case 18: /* _STAT */
-        case 19: /* RFORK */
-        case 20: /* _WRITE */
-        case 21: /* PIPE */
-        case 22: /* CREATE */
-        case 23: /* FD2PATH */
-        case 24: /* BRK_ */
-        case 25: /* REMOVE */
-        case 26: /* _WSTAT */
-        case 27: /* _FWSAT */
-        case 28: /* NOTIFY */
-        case 29: /* NOTED */
-        case 30: /* SEGATTACH */
-        case 31: /* SEGDETACH */
-        case 32: /* SEGFREE */
-        case 33: /* SEGFLUSH */
-        case 34: /* RENDEZVOUS */
-        case 35: /* UNMOUNT */
-        case 36: /* _WAIT */
-        case 37: /* SEMACQUIRE */
-        case 38: /* SEMRELEASE */
-        case 39: /* SEEK */
-        case 40: /* FVERSION */
-        case 41: /* ERRSTR */
-        case 42: /* STAT */
-        case 43: /* FSTAT */
-        case 44: /* WSTAT */
-        case 45: /* FWSTAT */
-        case 46: /* MOUNT */
-        case 47: /* AWAIT */
-        case 50: /* PREAD */
-        case 51: /* PWRITE */
-        case 52: /* TSEMACQUIRE */
-        case 53: /* _NSEC */
-            break;
-    }
+	/* no locking necessary, since we're on the stack */
+	return *(u32int*) vaddrnol(up->R[13] + 4 + 4 * n, 4);
+}
 
-    return ret;
+static u64int
+argv(int n)
+{
+	return arg(n) | ((u64int)arg(n+1) << 32);
 }
+
+u32int
+noteerr(u32int x, u32int y)
+{
+	if(((int)x) >= ((int)y))
+		return x;
+	rerrstr(up->errstr, ERRMAX);
+	return x;
+}
+
+void
+cherrstr(char *str, ...)
+{
+	va_list va;
+	
+	va_start(va, str);
+	vsnprint(up->errstr, ERRMAX, str, va);
+	va_end(va);
+}
+
+static void
+_sysopen(void)
+{
+	u32int name, flags;
+	char *namet;
+	int fd, copied;
+	
+	name = arg(0);
+	flags = arg(1);
+	namet = copyifnec(name, -1, &copied);
+	fd = open(namet, flags);
+	if(copied)
+		free(namet);
+	if(fd < 0) {
+		noteerr(0, 1);
+		up->R[0] = fd;
+		return;
+	}
+	up->R[0] = fd;
+}
+
+static void
+_syscreate(void)
+{
+	u32int name, flags, perm;
+	char *namet;
+	int fd, copied;
+	
+	name = arg(0);
+	flags = arg(1);
+	perm = arg(2);
+	namet = copyifnec(name, -1, &copied);
+	fd = create(namet, flags, perm);
+	if(copied)
+		free(namet);
+	if(fd < 0) {
+		noteerr(0, 1);
+		up->R[0] = fd;
+		return;
+	}
+	up->R[0] = fd;
+}
+
+static void
+_sysclose(void)
+{
+	u32int fd;
+	
+	fd = arg(0);
+	up->R[0] = noteerr(close(fd), 0);
+}
+
+static void
+_syspread(void)
+{
+	int buffered;
+	u32int fd, size, buf;
+	u64int off;
+	void *targ;
+	
+	fd = arg(0);
+	buf = arg(1);
+	size = arg(2);
+	off = argv(3);
+	targ = bufifnec(buf, size, &buffered);
+	up->R[0] = noteerr(pread(fd, targ, size, off), size);
+	if(buffered)
+		copyback(buf, up->R[0], targ);
+}
+
+static void
+_syspwrite(void)
+{
+	u32int fd, size, buf;
+	u64int off;
+	int copied;
+	void *buft;
+	
+	fd = arg(0);
+	buf = arg(1);
+	size = arg(2);
+	off = argv(3);
+	buft = copyifnec(buf, size, &copied);
+	up->R[0] = noteerr(pwrite(fd, buft, size, off), size);
+	if(copied)
+		free(buft);
+}
+
+static void
+_sysseek(void)
+{
+	u32int fd, type;
+	vlong n, *ret;
+	Segment *seg;
+	
+	ret = vaddr(arg(0), 8, &seg);
+	fd = arg(1);
+	n = argv(2);
+	type = arg(4);
+	*ret = seek(fd, n, type);
+	if(*ret < 0) noteerr(0, 1);
+	segunlock(seg);
+}
+
+static void
+_sysfd2path(void)
+{
+	u32int fd, buf, nbuf;
+	void *buft;
+	int buffered;
+	
+	fd = arg(0);
+	buf = arg(1);
+	nbuf = arg(2);
+	buft = bufifnec(buf, nbuf, &buffered);
+	up->R[0] = noteerr(fd2path(fd, buft, nbuf), 0);
+	if(buffered)
+		copyback(buf, nbuf, buft);
+}
+
+static void
+_sysstat(void)
+{
+	u32int name, edir, nedir;
+	char *namet;
+	void *edirt;
+	int copied, buffered;
+	
+	name = arg(0);
+	namet = copyifnec(name, -1, &copied);
+	edir = arg(1);
+	nedir = arg(2);
+	edirt = bufifnec(edir, nedir, &buffered);
+	up->R[0] = noteerr(sysstat(namet, edirt, nedir), nedir);
+	if(copied)
+		free(namet);
+	if(buffered)
+		copyback(edir, up->R[0], edirt);
+}
+
+static void
+_sysfstat(void)
+{
+	u32int fd, edir, nedir;
+	void *edirt;
+	int buffered;
+	
+	fd = arg(0);
+	edir = arg(1);
+	nedir = arg(2);
+	edirt = bufifnec(edir, nedir, &buffered);
+	up->R[0] = noteerr(sysfstat(fd, edirt, nedir), nedir);
+	if(buffered)
+		copyback(edir, up->R[0], edirt);
+}
+
+static void
+_syswstat(void)
+{
+	u32int name, edir, nedir;
+	char *namet;
+	void *edirt;
+	int copied, copied2;
+	
+	name = arg(0);
+	namet = copyifnec(name, -1, &copied);
+	edir = arg(1);
+	nedir = arg(2);
+	edirt = copyifnec(edir, nedir, &copied2);
+	up->R[0] = noteerr(syswstat(namet, edirt, nedir), nedir);
+	if(copied)
+		free(namet);
+	if(copied2)
+		free(edirt);
+}
+
+static void
+_sysfwstat(void)
+{
+	u32int fd, edir, nedir;
+	void *edirt;
+	int copied;
+	
+	fd = arg(0);
+	edir = arg(1);
+	nedir = arg(2);
+	edirt = copyifnec(edir, nedir, &copied);
+	up->R[0] = noteerr(sysfwstat(fd, edirt, nedir), nedir);
+	if(copied)
+		free(edirt);
+}
+
+// TODO: This may be better done as a longjmp back
+static void
+_sysexits(void)
+{
+	if(arg(0) == 0)
+		exits(nil);
+	else
+		exits(vaddrnol(arg(0), 0));
+}
+
+static void
+_sysbrk(void)
+{
+	ulong v;
+	Segment *s;
+	
+	v = arg(0);
+	v = v + 7 & -8;
+	if(v >= up->S[SEGSTACK]->start)
+		fprint(2, "bss > stack, wtf?");
+	if(v < up->S[SEGBSS]->start)
+		fprint(2, "bss length < 0, wtf?");
+	s = up->S[SEGBSS];
+	wlock(&s->rw);
+	s->dref = realloc(s->dref, v - s->start + sizeof(Ref));
+	if(s->dref == nil)
+		fprint(2, "error reallocating");
+	s->data = s->dref + 1;
+	if(s->size < v - s->start)
+		memset((char*)s->data + s->size, 0, v - s->start - s->size);
+	s->size = v - s->start;
+	up->R[0] = 0;
+	wunlock(&s->rw);
+}
+
+static void
+_syserrstr(void)
+{
+	char buf[ERRMAX], *srct;
+	u32int src, len;
+	int copied;
+	
+	src = arg(0);
+	len = arg(1);
+	srct = copyifnec(src, len, &copied);
+	strcpy(buf, up->errstr);
+	utfecpy(up->errstr, up->errstr + ERRMAX, srct);
+	utfecpy(srct, srct + len, buf);
+	if(copied)
+		copyback(src, len, srct);
+	up->R[0] = 0;
+}
+
+static void
+_syschdir(void)
+{
+	u32int dir;
+	char *dirt;
+	int copied;
+	
+	dir = arg(0);
+	dirt = copyifnec(dir, -1, &copied);
+	up->R[0] = noteerr(syschdir(dirt), 0);
+	if(copied)
+		free(dirt);
+}
+
+static void
+_sysnotify(void)
+{
+	u32int handler;
+	
+	handler = arg(0);
+	up->notehandler = handler;
+	up->R[0] = 0;
+}
+
+static void
+_sysnoted(void)
+{
+	u32int v;
+	
+	v = arg(0);
+	if(up->innote)
+		longjmp(up->notejmp, v + 1);
+	cherrstr("the front fell off");
+	up->R[0] = -1;
+}
+
+
+static void
+_sysrfork(void)
+{
+	u32int flags;
+	int rc, i;
+	Segment *s, *t;
+	Proc *p;
+	int old;
+	
+	flags = arg(0);
+
+	if((flags & (RFFDG | RFCFDG)) == (RFFDG | RFCFDG) ||
+	   (flags & (RFNAMEG | RFCNAMEG)) == (RFNAMEG | RFCNAMEG) ||
+	   (flags & (RFENVG | RFCENVG)) == (RFENVG | RFCENVG)) {
+		up->R[0] = -1;
+		cherrstr("bad arg in syscall");
+		return;
+	}
+	if((flags & RFPROC) == 0) {
+		if(flags & RFFDG) {
+			old = up->fd;
+			up->fd = copyfd(up->fd);
+			fddecref(old);
+		}
+		if(flags & RFCFDG) {
+			old = up->fd;
+			//up->fd = newfd();
+			fddecref(old);
+		}
+		up->R[0] = noteerr(rfork(flags), 0);
+		return;
+	}
+	//incref(&nproc);
+	p = emallocz(sizeof(Proc));
+	memcpy(p, up, sizeof(Proc));
+	for(i = 0; i < SEGNUM; i++) {
+		s = p->S[i];
+		if(s == nil)
+			continue;
+		if((flags & RFMEM) == 0 && i != SEGTEXT || i == SEGSTACK) {
+			t = emallocz(sizeof(Segment));
+			incref(t);
+			t->size = s->size;
+			t->start = s->start;
+			t->dref = emalloc(sizeof(Ref) + s->size);
+			memset(t->dref, 0, sizeof(Ref));
+			incref(t->dref);
+			t->data = t->dref + 1;
+			memcpy(t->data, s->data, s->size);
+			p->S[i] = t;
+		} else {
+			incref(s->dref);
+			incref(s);
+		}
+	}
+	
+	if(flags & RFFDG)
+		p->fd = copyfd(up->fd);
+	//else if(flags & RFCFDG)
+	//	p->fd = newfd();
+	//else
+	//	incref(up->fd);
+
+	//incref(up->path);
+	rc = rfork(RFMEM | flags);
+	if(rc < 0) /* this should NEVER happen */
+		sysfatal("rfork failed wtf: %r");
+	if(rc == 0) {
+	//	up = p;
+		//atexit(cleanup);
+		up->pid = getpid();
+		inittos();
+	//	addproc(P);
+	}
+	up->R[0] = rc;
+}
+   
+
+static void
+_sysexec(void)
+{
+	u32int name, argv, *argvt;
+	char *namet, **argvv;
+	int i, argc, rc;
+	Segment *seg1, *seg2;
+	
+	name = arg(0);
+	argv = arg(1);
+	namet = strdup(vaddr(name, 0, &seg1));
+	segunlock(seg1);
+	argvt = vaddr(argv, 0, &seg1);
+	for(argc = 0; argvt[argc]; argc++)
+		;
+	argvv = emalloc(sizeof(char *) * argc);
+	for(i = 0; i < argc; i++) {
+		argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
+		segunlock(seg2);
+	}
+	segunlock(seg1);
+	rc = loadtext(namet, argc, argvv);
+	for(i = 0; i < argc; i++)
+		free(argvv[i]);
+	free(argvv);
+	if(rc < 0)
+		up->R[0] = noteerr(rc, 0);
+	free(namet);
+}
+
+static void
+_sysawait(void)
+{
+	u32int s, n;
+	void *st;
+	int buffered;
+	
+	s = arg(0);
+	n = arg(1);
+	st = bufifnec(s, n, &buffered);
+	up->R[0] = noteerr(await(st, n), 0);
+	if(buffered)
+		copyback(s, up->R[0], st);
+}
+
+static void
+_syspipe(void)
+{
+	u32int fd, *fdt;
+	int buffered;
+	
+	fd = arg(0);
+	fdt = bufifnec(fd, 8, &buffered);
+	up->R[0] = noteerr(syspipe((int *) fdt), 0);
+	if(buffered)
+		copyback(fd, 8, fdt);
+}
+
+static void
+_sysdup(void)
+{
+	u32int oldfd, newfd;
+	
+	oldfd = arg(0);
+	newfd = arg(1);
+	up->R[0] = noteerr(dup2(oldfd, newfd), 0);
+}
+
+static void
+_syssleep(void)
+{
+	u32int n;
+	
+	n = arg(0);
+	osmsleep(n);
+	up->R[0] = 0;
+}
+
+static void
+_sysrendezvous(void)
+{
+	u32int tag, value;
+	
+	tag = arg(0);
+	value = arg(1);
+	up->R[0] = (u32int) (uintptr)sysrendezvous((void *)tag, (void *)value);
+	if(up->R[0] == ~0)
+		noteerr(0, 1);
+}
+
+static void
+_sysmount(void)
+{
+	u32int fd, afd, old, flag, aname;
+	char *oldt, *anamet;
+	int copiedold, copiedaname;
+	
+	fd = arg(0);
+	afd = arg(1);
+	old = arg(2);
+	flag = arg(3);
+	aname = arg(4);
+	oldt = copyifnec(old, -1, &copiedold);
+	if(aname) {
+		anamet = copyifnec(aname, -1, &copiedaname);
+	} else {
+		anamet = nil;
+		copiedaname = 0;
+	}
+	up->R[0] = noteerr(sysmount(fd, afd, oldt, flag, anamet), 0);
+	if(copiedold)
+		free(oldt);
+	if(copiedaname)
+		free(anamet);
+}
+
+static void
+_sysbind(void)
+{
+	u32int name, old, flags;
+	char *namet, *oldt;
+	int copiedname, copiedold;
+	
+	name = arg(0);
+	old = arg(1);
+	flags = arg(2);
+	namet = copyifnec(name, -1, &copiedname);
+	oldt = copyifnec(old, -1, &copiedold);
+	up->R[0] = noteerr(sysbind(namet, oldt, flags), 0);
+	if(copiedname)
+		free(namet);
+	if(copiedold)
+		free(oldt);
+}
+
+static void
+_sysunmount(void)
+{
+	u32int name, old;
+	char *namet, *oldt;
+	int copiedname, copiedold;
+	
+	name = arg(0);
+	old = arg(1);
+	oldt = copyifnec(old, -1, &copiedold);
+	if(name == 0) {
+		namet = nil;
+		copiedname = 0;
+		up->R[0] = noteerr(sysunmount(nil, oldt), 0);
+	} else {
+		namet = copyifnec(name, -1, &copiedname);
+		up->R[0] = noteerr(sysunmount(namet, oldt), 0);
+	}
+	if(copiedold)
+		free(oldt);
+	if(copiedname)
+		free(namet);
+}
+
+static void
+_sysremove(void)
+{
+	u32int file;
+	char *filet;
+	int copied;
+	
+	file = arg(0);
+	filet = copyifnec(file, -1, &copied);
+	up->R[0] = noteerr(sysremove(filet), 0);
+	if(copied)
+		free(filet);
+}
+
+static void
+_sysalarm(void)
+{
+	u32int msec;
+	
+	msec = arg(0);
+	up->R[0] = alarm(msec);
+}
+
+static void
+_syssemacquire(void)
+{
+	u32int addr, block;
+	long *addrt;
+
+	addr = arg(0);
+	block = arg(1);
+	addrt = vaddrnol(addr, 4);
+	// Still need semaphores
+	up->R[0] = noteerr(semacquire(addrt, block), 0);
+}
+
+static void
+_syssemrelease(void)
+{
+	u32int addr, count;
+	long *addrt;
+	Segment *seg;
+
+	addr = arg(0);
+	count = arg(1);
+	addrt = vaddr(addr, 4, &seg);
+	// Still need semaphores
+	up->R[0] = noteerr(semrelease(addrt, count), 0);
+	segunlock(seg);
+}
+
+void
+_syscall(void)
+{
+	u32int n;
+	static void (*calls[])(void) = {
+		[EXITS] 		= _sysexits,
+		[CLOSE] 		= _sysclose,
+		[OPEN] 			= _sysopen,
+		[CREATE] 		= _syscreate,
+		[PREAD] 		= _syspread,
+		[PWRITE] 		= _syspwrite,
+		[BRK_] 			= _sysbrk,
+		[ERRSTR] 		= _syserrstr,
+		[STAT] 			= _sysstat,
+		[FSTAT] 		= _sysfstat,
+		[WSTAT] 		= _syswstat,
+		[FWSTAT] 		= _sysfwstat,
+		[SEEK] 			= _sysseek,
+		[CHDIR]		 	= _syschdir,
+		[FD2PATH] 		= _sysfd2path,
+		[NOTIFY] 		= _sysnotify,
+		[NOTED] 		= _sysnoted,
+		[RFORK] 		= _sysrfork,
+		[EXEC]	 		= _sysexec,
+		[AWAIT] 		= _sysawait,
+		[PIPE] 			= _syspipe,
+		[SLEEP] 		= _syssleep,
+		[RENDEZVOUS] 	= _sysrendezvous,
+		[BIND] 			= _sysbind,
+		[UNMOUNT] 		= _sysunmount,
+		[DUP] 			= _sysdup,
+		[MOUNT] 		= _sysmount,
+		[REMOVE] 		= _sysremove,
+		[ALARM] 		= _sysalarm,
+		[SEMACQUIRE] 	= _syssemacquire,
+		[SEMRELEASE] 	= _syssemrelease,
+	};
+	
+	n = up->R[0];
+	if(n >= nelem(calls) || calls[n] == nil)
+		fprint(2, "no such syscall %d @ %#ux", n, up->R[15] - 4);
+	calls[n]();
+}
\ No newline at end of file
--- a/kern/sysproc.c
+++ b/kern/sysproc.c
@@ -5,6 +5,7 @@
 #include "error.h"
 #include "user.h"
 #include "mem.h"
+#include "sys.h"
 #include <a.out.h>
 #include <signal.h>
 #include <sys/mman.h>
@@ -20,33 +21,13 @@
     USED(x);
 }
 
-static void
-sigsegv(int sig)
+static u32int
+arg(int n)
 {
-    print("Segfault: %d: %r\n", sig);
-    longjmp(exec_jmp, 2);
+	/* no locking necessary, since we're on the stack */
+	return *(u32int*) vaddrnol(up->R[13] + 4 + 4 * n, 4);
 }
 
-static void
-sigquit(int sig)
-{
-    print("Sigquittin': %r\n");
-    longjmp(exec_jmp, 1);
-}
-
-static void
-sigbus(int sig)
-{
-    print("Bussin': %r\n");
-    longjmp(exec_jmp, 2);
-}
-
-static void
-sigsys(int sig)
-{
-    print("We here!!! sig %d\n", sig);
-}
-
 int
 sysrfork(int flags)
 {
@@ -188,15 +169,6 @@
            | (uvlong)p[7];
 }
 
-void
-evenaddr(uintptr addr)
-{
-    if(addr & 3){
-        postnote(up, 1, "sys: odd address", NDebug);
-        error(Ebadarg);
-    }
-}
-
 void*
 vmemchr(void *s, int c, ulong n)
 {
@@ -222,125 +194,196 @@
 }
 
 #undef read
-int
-sysexec(int argc, char **argv)
+/* Load text and data segments into memory */
+
+
+/* the following code is not for the weak of heart */
+void
+donote(char *msg, ulong type)
 {
-    union {
-        struct {
-            Exec ex;
-            uvlong hdr[1];
-        } ehdr;
-        char buf[256];
-    } u;
-    void (*_main)(int, char*[]);
-    char line[256];
-    char *progarg[32+1];
-    char *file, *elem;
-    void *base;
-    Chan *tc;
-    ulong magic;
-    uintptr t, b, entry, text, data, bss, align;
-    int n, indir;
+	int rc;
+	u32int *ureg, *sp, uregp, msgp;
+	char *msgb;
 
-    elem = nil;
-    align = BY2PG-1;
-    indir = 0;
-    file = argv[0];
+        print("In donote\n");
+	if(up->notehandler == 0)
+		exits(msg);
 
-    for(;;){
-        tc = namec(file, Aopen, OEXEC, 0);
-        if(waserror()){
-            cclose(tc);
-            nexterror();
-        }
-        if(!indir)
-            kstrdup(&elem, up->genbuf);
-        n = devtab[tc->type]->read(tc, u.buf, sizeof(u.buf), 0);
-        if (n >= sizeof(Exec)){
-            magic = beswal(u.ehdr.ex.magic);
-            if(magic & AOUT_MAGIC) {
-				if(magic & HDR_MAGIC){
-                    if(n < sizeof(u.ehdr))
-                        error(Ebadexec);
-                    entry = beswav(u.ehdr.hdr[0]);
-                    text = UTZERO+sizeof(u.ehdr);
-                } else {
-                    entry = beswal(u.ehdr.ex.entry);
-                    text = UTZERO+sizeof(u.ehdr);
-                }
-                if(entry < text)
-                    error(Ebadexec);
-                text += beswal(u.ehdr.ex.text);
-                if(text <= entry || text >= (USTKTOP-USTKSIZE))
-					error(Ebadexec);
-                switch(magic){
-                case S_MAGIC:
-                    align = 0x1fffff;
-                    break;
-                case P_MAGIC:
-                case V_MAGIC:
-                    align = 0x3fff;
-                    break;
-                case R_MAGIC:
-                    align = 0xffff;
-                    break;
-                }
-                break;
-            }
-        }
-        if(indir++)
-            error(Ebadexec);
+	clrex();
+	uregp = up->R[13] - 18 * 4;
+	ureg = vaddrnol(uregp, 18 * 4);
+	memcpy(ureg, up->R, 15 * 4);
+	ureg[15] = type;
+	ureg[16] = up->CPSR;
+	ureg[17] = up->R[15];
+	up->R[13] = uregp;
+	msgp = up->R[13] -= ERRMAX;
+	msgb = vaddrnol(msgp, ERRMAX);
+	strncpy(msgb, msg, ERRMAX);
+	up->R[13] -= 3 * 4;
+	sp = vaddrnol(up->R[13], 3 * 4);
+	sp[0] = 0;
+	sp[2] = msgp;
+	up->R[0] = uregp;
+	up->R[15] = up->notehandler;
+	up->innote = 1;
+	switch(rc = setjmp(up->notejmp) - 1) {
+	case -1:
+		for(;;) {
+			step();
+		}
+	case NDFLT:
+		exits(msg);
+	case NCONT:
+		break;
+	default:
+		sysfatal("unhandled noted argument %d", rc);
+	}
+	up->innote = 0;
+	ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */
+	memcpy(up->R, ureg, 15 * 4);
+	up->CPSR = ureg[16];
+	up->R[15] = ureg[17];
+}
 
-        memmove(line, u.buf, sizeof(u.buf));
-        n = shargs(line, n, progarg, nelem(progarg));
-        if(n < 1)
-            error(Ebadexec);
-        progarg[n++] = file;
-        progarg[n] = nil;
-        file = progarg[0];
-        progarg[0] = elem;
-        poperror();
-        cclose(tc);
-    }
 
-    text -= UTZERO;
-    entry -= UTZERO;
-	data = beswal(u.ehdr.ex.data);
-	bss = beswal(u.ehdr.ex.bss);
+static void
+initstack(int argc, char **argv)
+{
+	ulong tos, sp, ap, size, i, len;
+	
+	tos = USTKTOP - sizeof(Tos) * 2;
+	sp = tos;
+	
+	size = 8;
+	for(i = 0; i < argc; i++)
+		size += strlen(argv[i]) + 5;
+	
+	sp -= size;
+	sp &= ~7;
+	up->R[0] = tos;
+	up->R[1] = USTKTOP - 4;
+	up->R[13] = sp;
+	
+	*(ulong *) vaddrnol(sp, 4) = argc;
+	sp += 4;
+	ap = sp + (argc + 1) * 4;
+	for(i = 0; i < argc; i++) {
+		*(ulong *) vaddrnol(sp, 4) = ap;
+		sp += 4;
+		len = strlen(argv[i]) + 1;
+		memcpy(vaddrnol(ap, len), argv[i], len);
+		ap += len;
+	}
+	*(ulong *) vaddrnol(sp, 4) = 0;
+	inittos();
+}
 
-    /* Set up text, data, and bss. OS dependent. */
-    base = osbuildmem(tc, text, data, bss, sizeof(u.ehdr), align);
-    b = ((uintptr)base + align) & ~align;
 
-    /* Handle alignment, BSS setup, and memory protection. OS dependent. */
-    osprepmem(base, b, text, data, bss);
+void
+inittos(void)
+{
+	ulong tos;
 
-    poperror();
-    cclose(tc);
+	tos = USTKTOP - sizeof(Tos) * 2;
+	((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = up->pid;
+}
 
-    /* Meaningful signals to us */
-    signal(SIGSEGV, sigsegv);
-    signal(SIGQUIT, sigquit);
-    signal(SIGINT, sigquit);
-    signal(SIGSYS, sigsys);
-    signal(SIGBUS, sigbus);
+// TODO: fd has to go away here.
+static int
+loadscript(int fd, char *file, int argc, char **argv)
+{
+	char buf[513], *p, **q, **nargv;
+	int rc, nargc, i;
+	
+	seek(fd, 0, 0);
+	rc = readn(fd, buf, 512);
+	if(rc <= 0)
+		goto invalid;
+	close(fd);
+	buf[rc] = 0;
+	p = strchr(buf, '\n');
+	if(p == nil)
+		goto invalid;
+	*p = 0;
+	while(isspace(*--p))
+		*p = 0;
+	nargc = 0;
+	p = buf + 2;
+	while(*p) {
+		while(*p && isspace(*p))
+			p++;
+		nargc++;
+		while(*p && !isspace(*p))
+			p++;
+	}
+	if(nargc == 0)
+		goto invalid;
+	nargv = emallocz(sizeof(char *) * (nargc + argc));
+	q = nargv;
+	p = buf + 2;
+	while(*p) {
+		while(*p && isspace(*p))
+			p++;
+		*(p-1) = 0;
+		*q++ = p;
+		while(*p && !isspace(*p))
+			p++;
+	}
+	*q++ = file;
+	for(i = 1; i < argc; i++)
+		*q++ = argv[i];
+	rc = loadtext(*nargv, argc + nargc, nargv);
+	free(nargv);
+	return rc;
 
-    switch(setjmp(exec_jmp)) {
-    case 0:
-        print("Base %p, Aligned base %p, Entry offset %lx, Text %lx\n", base, (void*)b, entry, text);
+invalid:
+	werrstr("exec header invalid");
+	return -1;
+}
 
-        _main = (void (*)(int, char*[]))(b+entry);
-        _main(argc, argv);
+int
+loadtext(char *file, int argc, char **argv)
+{
+	Segment *text, *data, *bss;
+	char buf[2];
+    Chan *tc;
+    int n;
+	    union {
+        struct {
+            Exec ex;
+            uvlong hdr[1];
+        } ehdr;
+        char buf[256];
+    } u;
 
-        longjmp(exec_jmp, 1);
-        break;
-    case 1:
-        osclrmem((uintptr)b, text+data+bss);
-        break;
-    case 2:
-        //error("Signal: %r");
-        return -1;
-    }
+    tc = namec(file, Aopen, OEXEC, 0);
+    n = devtab[tc->type]->read(tc, u.buf, sizeof(u.buf), 0);
 
-    return 0;
-}
\ No newline at end of file
+	copyname(file);
+	up->notehandler = up->innote = up->notein = up->noteout = 0;
+	freesegs();
+	memset(up->R, 0, sizeof(up->R));
+	up->CPSR = 0;
+    // Read instead with beswav(whatever) 
+	//text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
+	//data = newseg(fp.dataddr, fp.datsz, SEGDATA);
+	//bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);
+	//newseg(USTKTOP - STACKSIZE, STACKSIZE, SEGSTACK);
+    // This also doesn't work, we want to read in the devtab way
+	//seek(fd, fp.txtoff - fp.hdrsz, 0);
+	//if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
+	//	sysfatal("%r");
+	//seek(fd, fp.datoff, 0);
+	//if(readn(fd, data->data, fp.datsz) < fp.datsz)
+	//	sysfatal("%r");
+	//memset(bss->data, 0, bss->size);
+	//up->R[15] = fp.entry;
+	//if(havesymbols && syminit(fd, &fp) < 0)
+	//	fprint(2, "initializing symbol table: %r\n");
+	//close(fd);
+	fdclear(up->fd);
+	initstack(argc, argv);
+	resetfpa();
+	return 0;
+}
--- a/main.c
+++ b/main.c
@@ -5,9 +5,9 @@
 #include "user.h"
 #include "drawcpu.h"
 #include "arg.h"
+#include "proc.h"
 
 char *argv0;
-char *dbgfile = "./debug.log";
 int debug;
 
 void
@@ -48,12 +48,24 @@
 	exit(1);
 }
 
+int
+notehandler(void *, char *note)
+{
+	if(strncmp(note, "sys:", 4) == 0)
+		return 0;
+	
+	if(strncmp(note, "emu:", 4) == 0)
+		exits(note);
 
+	addnote(note);
+	return 1;
+}
+
 int
 main(int argc, char **argv)
 {
 	extern ulong kerndate;
-	char *path;
+	char *path, *file;
 
 	path = nil;
 	kerndate = seconds();
@@ -98,14 +110,25 @@
 	if(path != nil)
 		bind(path, "/bin", MAFTER);
 
-	char *cmd[] = {
-		// Substitute the real path to a useful binary here
-		// It should be a 9front binary for the architecture 
-		// of the host machine (the one you're compiling on)
-		"./Users/halfwit/Downloads/drawcpu/bin/echo",
-		"hi"
-	};
+	if(**argv == '/' || **argv == '.' || **argv == '#') {
+		// TODO: Export loadtext from the kernel
+		if(loadtext(*argv, argc, argv) < 0)
+			sysfatal("loadtext: %r");
+		return;
+	}
+	file = smprint("/bin/%s", *argv);
+	if(loadtext(file, argc, argv) < 0)
+		sysfatal("loadtext: %r");
+	free(file);
 
-	exec(2, cmd);
-	_exit(0);
+	// TODO: Export step() from the kernel
+	atnotify(notehandler, 1);
+	for(;;) {
+		// Kernel step, while this greys kernelspace/userspace this is the cleaner approach
+		step();
+		while((up->notein - up->noteout) % NNOTE) {
+			donote(up->notes[up->noteout % NNOTE], 0);
+			ainc(&up->noteout);
+		}
+	}
 }
--- a/posix-amd64/Makefile
+++ b/posix-amd64/Makefile
@@ -7,7 +7,7 @@
 OFILES=\
 	getcallerpc.$O\
 	tas.$O\
-	trampoline.$O\
+	cas.$O\
 
 default: $(LIB)
 $(LIB): $(OFILES)
--- a/posix-amd64/trampoline.c
+++ /dev/null
@@ -1,79 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "../kern/fns.h"
-#include "mem.h"
-
-/* TODO: This is not arm64 code, this is amd64 code */
-extern void asm_syscall_hook(void);
-void ____asm_syscall_hook(void)
-{
-	/*
-	 * asm_syscall_hook is the address where the
-	 * trampoline code first jumps to.
-	 *
-	 * the procedure below calls the C function
-	 * namded syscall_hook.
-	 *
-	 * at the entry point of this,
-	 * the register values follow the calling convention
-	 * of the system calls. the following transforms
-	 * to the calling convention of the C functions.
-	 *
-	 * we do this just for writing the hook in C.
-	 * so, this part would not be performance optimal.
-	 */
-	asm volatile (
-	".globl asm_syscall_hook \n\t"
-	"asm_syscall_hook: \n\t"
-	"movq (%rsp), %rcx \n\t"
-	"pushq %rbp \n\t"
-	"movq %rsp, %rbp \n\t"
-	"subq $16,%rsp \n\t"
-	"movq %rcx,8(%rsp) \n\t"
-	"movq %r9,(%rsp) \n\t"
-	"movq %r8, %r9 \n\t"
-	"movq %r10, %r8 \n\t"
-	"movq %rdx, %rcx \n\t"
-	"movq %rsi, %rdx \n\t"
-	"movq %rdi, %rsi \n\t"
-	"movq %rax, %rdi \n\t"
-	"call syscall \n\t"
-	"leaveq \n\t"
-	"retq \n\t"
-	);
-}
-
-int
-trampoline(void *text)
-{
-    int i;
-    for(i = 0; i < _NSYS; i++)
-        ((uint8_t *)text)[i] = 0x90;
-
-    /* Preserve redzone */
-    ((uint8_t*)text)[_NSYS + 0x00] = 0x48;
-    ((uint8_t *) text)[_NSYS + 0x01] = 0x81;
-	((uint8_t *) text)[_NSYS + 0x02] = 0xec;
-	((uint8_t *) text)[_NSYS + 0x03] = 0x80;
-	((uint8_t *) text)[_NSYS + 0x04] = 0x00;
-	((uint8_t *) text)[_NSYS + 0x05] = 0x00;
-	((uint8_t *) text)[_NSYS + 0x06] = 0x00;
-
-    /* 49 bb [64-bit addr (8-byte)] movabs [64-bit addr (8-byte)],%r11 */
-	((uint8_t *) text)[_NSYS + 0x07] = 0x49;
-	((uint8_t *) text)[_NSYS + 0x08] = 0xbb;
-	((uint8_t *) text)[_NSYS + 0x09] = ((uint64_t) asm_syscall_hook >> (8 * 0)) & 0xff;
-	((uint8_t *) text)[_NSYS + 0x0a] = ((uint64_t) asm_syscall_hook >> (8 * 1)) & 0xff;
-	((uint8_t *) text)[_NSYS + 0x0b] = ((uint64_t) asm_syscall_hook >> (8 * 2)) & 0xff;
-	((uint8_t *) text)[_NSYS + 0x0c] = ((uint64_t) asm_syscall_hook >> (8 * 3)) & 0xff;
-	((uint8_t *) text)[_NSYS + 0x0d] = ((uint64_t) asm_syscall_hook >> (8 * 4)) & 0xff;
-	((uint8_t *) text)[_NSYS + 0x0e] = ((uint64_t) asm_syscall_hook >> (8 * 5)) & 0xff;
-	((uint8_t *) text)[_NSYS + 0x0f] = ((uint64_t) asm_syscall_hook >> (8 * 6)) & 0xff;
-	((uint8_t *) text)[_NSYS + 0x10] = ((uint64_t) asm_syscall_hook >> (8 * 7)) & 0xff;
-
-	// 41 ff e3                jmp    *%r11
-	((uint8_t *) text)[_NSYS + 0x11] = 0x41;
-	((uint8_t *) text)[_NSYS + 0x12] = 0xff;
-	((uint8_t *) text)[_NSYS + 0x13] = 0xe3;
-	return i + 0x13;
-}
--- a/posix-arm/Makefile
+++ b/posix-arm/Makefile
@@ -7,6 +7,7 @@
 OFILES=\
 	getcallerpc.$O\
 	tas.$O\
+	cas.$O\
 
 default: $(LIB)
 $(LIB): $(OFILES)
--- /dev/null
+++ b/posix-arm/cas.c
@@ -1,0 +1,36 @@
+#include "u.h"
+#include "libc.h"
+
+int
+cas(int *x, int old, int new)
+{
+	int     v, t;
+
+#if ARMv5
+	__asm__(
+		"1:	ldr	%0, [%2]\n"
+		"	cmp	%0, %3\n"
+		"	bne	2f\n"
+		"	swp	%1, %4, [%2]\n"
+		"	cmp	%1, %3\n"
+		"	bne	1b\n"
+		"2:"
+		: "=&r" (v), "=&r" (t)
+		: "r" (x), "r" (old), "r" (new)
+		: "cc", "memory"
+	);
+#else
+	__asm__ (
+		"1:	ldrex	%0, [%2]\n"
+		"	cmp	%0, %3\n"
+		"	bne	2f\n"
+		"	strex	%1, %4, [%2]\n"
+		"	teq	%1, #0\n"
+		"	bne	1b\n"
+		"2:"
+		: "=&r" (v), "=&r" (t)
+		: "r" (x), "r" (old), "r" (new)
+		: "cc");
+#endif
+	return (v == old);
+}
\ No newline at end of file
--- a/posix-arm64/Makefile
+++ b/posix-arm64/Makefile
@@ -7,9 +7,7 @@
 OFILES=\
 	getcallerpc.$O\
 	tas.$O\
-	trampoline.$O\
-	patch.$O\
-	start.$O\
+	cas.$O\
 
 default: $(LIB)
 $(LIB): $(OFILES)
--- /dev/null
+++ b/posix-arm64/cas.c
@@ -1,0 +1,30 @@
+#include "u.h"
+#include "libc.h"
+
+#ifndef __has_builtin
+#define __has_builtin(x) 0
+#endif
+
+int
+cas(int *x, int old, int new)
+{
+#if __has_builtin(__atomic_compare_exchange_n) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)))
+	return __atomic_compare_exchange_n(x, &old, new, 0, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
+#else
+	int     v, t;
+
+	__asm__ (
+		"1:	ldxr	%0, [%3]\n"
+		"	cmp	%0, %4\n"
+		"	bne	2f\n"
+		"	stxr	%w1, %5, [%3]\n"
+		"	cmp	%1, #0\n"
+		"	bne	1b\n"
+		"2:"
+		: "=&r" (v), "=&r" (t)
+		: "m" (*x), "r" (x), "r" (old), "r" (new)
+		: "cc");
+
+	return (v == old);
+#endif
+}
\ No newline at end of file
--- a/posix-arm64/mem.h
+++ b/posix-arm64/mem.h
@@ -1,4 +1,3 @@
-#define AOUT_MAGIC  (R_MAGIC)
 /*
  * Memory and machine-specific definitions.  Used in C and assembler.
  */
--- a/posix-arm64/patch.c
+++ /dev/null
@@ -1,23 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "mem.h"
-
-int
-patch(void* text, int size)
-{
-    ulong i;
-    int ret = -1;
-    for(i = 0; i < size - BY2WD; i++){
-        // MOV X0, #immediate (could be D2800000 | syscall_number)
-        // BL X0 (could be D4000010 | offset)
-        // 0xD63F0000 is our BLR X0
-        // This sets up our jmp to the trampoline code
-        if ((*(ulong*)&text[i] & 0xFFFF0000) == 0xD2800000 && (*(ulong*)&text[i+BY2SE] & 0xFFFF0000) == 0xD4000000) {
-            ulong *ptr = (ulong*)&text[i+BY2SE];
-            *ptr &= 0xFFFF0000;
-            *ptr |= 0xD63F0000;
-            ret++;
-        }
-    }
-    return ret;
-}
--- a/posix-arm64/start.c
+++ /dev/null
@@ -1,42 +1,0 @@
-#include "u.h"
-#include "libc.h"
-void start(uintptr_t entry, Tos *_tos, int argc, char *argv[])
-{
-    register uintptr_t r0 asm("x0") = entry;
-    register Tos *r1 asm("x1") = _tos;
-    register int r2 asm("w2") = argc;
-    register char **r3 asm("x3") = argv;
-
-    __asm__ __volatile__ (
-                // Load values into registers
-                "mov x0, %0\n\t"
-                "mov x1, %1\n\t"
-                "mov w2, %w2\n\t"
-                "mov x3, %3\n\t"
-
-                // push argv onto stack
-                "mov x4, x2\n\t"
-                "add x4, x4, #1\n\t"
-                "lsl x4, x4, #3\n\t"
-                "sub sp, sp, x4\n\t"
-                "mov x5, sp\n\t"
-                "mov x6, x3\n\t"
-
-                // copy argv in at a time
-                "copy_argv_loop:\n\t"
-                "ldr x7, [x6], #8\n\t"
-                "str x7, [x5], #8\n\t"
-                "subs x4, x4, #1\n\t"
-                "bne copy_argv_loop\n\t"
-        
-                // push argc onto stack
-                "sub sp, sp, #4\n\t"
-                "str w2, [sp]\n\t"
-
-                // jump to entry point
-                "br x0\n\t"
-                "ret\n\t"
-                :
-                : "r"(r0), "r"(r1), "r"(r2), "r"(r3)
-                : "x4", "x5", "x6", "x7");
-}
\ No newline at end of file
--- a/posix-arm64/trampoline.c
+++ /dev/null
@@ -1,75 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include "mem.h"
-
-void asm_syscall_hook(void)
-{
-	print("In hook somehow\n");
-	__asm__ __volatile__ (
-		"asm_syscall_hook:\r\n"
-    	"stp x29, x30, [sp, #-16]!\r\n"  // Save frame pointer and link register
-    	"mov x29, sp\r\n"                // Set up frame pointer
-    	"sub sp, sp, #32\r\n"            // Allocate 32 bytes on stack
-    	"stp x8, x0, [sp, #16]\r\n"      // Save x8 (syscall number) and x0
-    	"stp x1, x2, [sp]\r\n"           // Save x1 and x2
-    	"mov x1, x0\r\n"                 // Shift arguments: x0 -> x1
-    	"mov x2, x1\r\n"                 // x1 -> x2
-    	"mov x3, x2\r\n"                 // x2 -> x3
-    	"mov x4, x3\r\n"                 // x3 -> x4
-    	"mov x5, x4\r\n"                 // x4 -> x5
-    	"mov x6, x5\r\n"                 // x5 -> x6
-    	"mov x0, x8\r\n"                 // Move syscall number to x0
-    	"bl _sysintercept\r\n"           // Call syscall function
-    	"ldp x1, x2, [sp]\r\n"           // Restore original x1 and x2
-    	"ldp x8, x3, [sp, #16]\r\n"      // Restore original x8 and load original x0 into x3
-    	"mov x1, x3\r\n"                 // Restore original x0 to x1 (new x0 is return value)
-    	"ldp x29, x30, [sp], #48\r\n"    // Restore frame pointer and link register, and deallocate stack
-    	"ret\r\n"
-	);
-}
-
-/**
- * based on https://github.com/yasukata/zpoline/blob/master/main.c
- * This will add NOP into the first 53 sections of text
- * When a syscall is patched, it will instead jump here
- * From the NOP slide, it then calls into asm_syscall_hook which in turn calls sysintercept
- */
-void
-trampoline(void *text)
-{
-	void *hook_address = (void*)&asm_syscall_hook;
-    uint8_t code[] = {
-        // 53 nop instructions to catch the 9 syscalls (0xd503201f each)
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5, 0x1f, 0x20, 0x03, 0xd5,
-        0x1f, 0x20, 0x03, 0xd5,
-        // Main code
-        0xff, 0x43, 0x00, 0xd1,  // sub sp, sp, #0x80
-        0x00, 0x00, 0x00, 0x90,  // adrp x11, 0 (placeholder)
-        0x0b, 0x00, 0x00, 0x91,  // add x11, x11, :lo12:0 (placeholder)
-        0x60, 0x01, 0x3f, 0xd6   // br x11
-    };
-
-    // Calculate the relative address for adrp
-    uintptr_t adrp_offset = ((uintptr_t)hook_address >> 12) & 0x7FFFF;
-    code[216] |= (adrp_offset & 0xFF);
-    code[217] |= ((adrp_offset >> 8) & 0x7F) << 1;
-
-    // Set the low 12 bits for add
-    uintptr_t add_offset = (uintptr_t)hook_address & 0xFFF;
-    code[220] |= (add_offset & 0xFF);
-    code[221] |= (add_offset >> 8) << 2;
-
-	memcpy(text, code, sizeof(code));
-}
--