#include "../h/param.h"
#include "../h/systm.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/proc.h"
#include "../h/text.h"
#include "../h/seg.h"

/*
 * Load the user hardware segmentation
 * registers from the software prototype.
 * The software registers must have
 * been setup prior by estabur.
 */
sureg()
{
	register *up;
	register struct seg *rp;
	register a, t;
	register struct text *tp;

	t = a = (u.u_procp->p_addr) << SEGASL;
	if ((tp=u.u_procp->p_textp) != NULL)
		t = (tp->x_caddr)<<SEGASL;
	up = &u.u_uisa[16];
	rp = &uisa0[16];
	while (--up >= &u.u_uisa[0])
		(--rp)->seg_hste = (*up + (*up&TX? t: (*up&ABS? 0: a))) & ~(TX|ABS);
}

/*
 * Set up software prototype segmentation
 * registers to implement the 3 pseudo
 * text,data,stack segment sizes passed
 * as arguments.
 * The argument sep specifies if the
 * text and data+stack segments are to
 * be separated (meaningless on Interdata).
 * The last argument determines whether the text
 * segment is read-write or read-only.
 */
estabur(nt, nd, ns, sep, xrw)
unsigned nt, nd, ns;
{
	register a, *ap, *dp;

	if(sep) 
		goto err;
	else
		if(ctos(nt)+ctos(nd)+ctos(ns) > (NSEGS-1))
			goto err;
	if(nt+nd+ns+USIZE > maxmem)
		goto err;
	a = 0;
	ap = &u.u_uisa[0];
	while(nt >= SEGFULL) {
		*ap++ = (a<<SEGASL) | ((SEGFULL-1)<<SEGLSL) | xrw|TX;
		a += SEGFULL;
		nt -= SEGFULL;
	}
	if(nt) {
		*ap++ = (a<<SEGASL) | ((nt-1)<<SEGLSL) | xrw|TX;
	}
	a = USIZE;
	while(nd >= SEGFULL) {
		*ap++ = (a<<SEGASL) | ((SEGFULL-1)<<SEGLSL) | RW;
		a += SEGFULL;
		nd -= SEGFULL;
	}
	if(nd) {
		*ap++ = (a<<SEGASL) | ((nd-1)<<SEGLSL) | RW;
		a += nd;
	}
	u.u_sseg = (NSEGS-1)-ctos(ns);
	dp = &u.u_uisa[u.u_sseg];
	while(ap < dp) {
		*ap++ = 0;
	}
	while(ns >= SEGFULL) {
		*ap++ = (a<<SEGASL) | ((SEGFULL-1)<<SEGLSL) | RW;
		a += SEGFULL;
		ns -= SEGFULL;
	}
	if(ns) {
		*ap++ = (a<<SEGASL) | ((ns-1)<<SEGLSL) | RW;
	}
	sureg();
	return(0);

err:
	u.u_error = ENOMEM;
	return(-1);
}
