Source to jet/memory.c


Enter a symbol's name here to quickly find it.

#include <Memory.h>
#include <OSUtils.h>
#include <SegLoad.h>

#include "jet.h"

typedef struct memblk {
	unsigned long size;
	struct memblk *next;
} memblk;

static void relocate(char *txt, char *relo);

static memblk *free_blocks;

void init_memory(char *m_begin, char *m_end)
{
	free_blocks = (memblk *)(((unsigned long)m_begin + 0x03) & ~0x03);
	free_blocks->size = (unsigned long)(m_end - m_begin - sizeof(memblk)) & ~0x03;
	free_blocks->next = 0;
}

void *m_alloc(long number)
{
	unsigned long size;
	memblk *b;
	
	if (number == -1) {
		if (free_blocks == NULL)
			return 0;
		else
			return (void *)free_blocks->size;
	}
	size = ((unsigned long)number + 0x03) & ~0x03;
	if ((free_blocks == NULL) || (free_blocks->size < size))
		return 0;
	b = free_blocks;
	if (free_blocks->size > size + sizeof(memblk)) {
		free_blocks = (memblk *)((char *)free_blocks + sizeof(memblk) + size);
		free_blocks->size = b->size - sizeof(memblk) - size;
		free_blocks->next = b->next;
	} else {
		size = free_blocks->size;
		free_blocks = NULL;
	}
	b->size = size;
	b->next = 0;
	return (void *)(b + 1);
}

long m_free(void *block)
{
	memblk *b;
	
	b = (memblk *)((char *)block - sizeof(memblk));
	b->next = free_blocks;
	free_blocks = b;
	return 0;
}

long m_shrink(short zero, void *ptr, long size)
{
	memblk *b1, *b2;
	unsigned long s;

	s = ((unsigned long)size + 0x03) & ~0x03;
	b1 = (memblk *)((char *)ptr - sizeof(memblk));
	b2 = (memblk *)((char *)b1 + sizeof(memblk) + s);
	b2->size = b1->size - sizeof(memblk) - s;
	b2->next = free_blocks;
	free_blocks = b2;
	b1->size = size;
	return 0;
}

long m_xalloc(long number, short mode)
{
	return -EINVAL;
}

/* this is no where near correct for the general case */
/* I just want it to work for mint right now */
long p_exec(short mode, void *ptr1, void *ptr2, void *ptr3)
{
	long size;
	short f;
	struct aexec hdr;
	_DTA dta;
	char *prog, *cmd, *env;
	
	if (mode != 0) {
		c_conws("p_exec only supports mode 0\r\n");
		p_term(0);
	}
	prog = ptr1;
	cmd = ptr2;
	env = ptr3;
	f_setdta(&dta);
	if (f_sfirst(prog, 0) < 0) {
		c_conws("can't find ");
		c_conws(prog);
		c_conws("\r\n");
		p_term(0);
	}
	size = curbp->p_hitpa - (curbp->p_lowtpa + sizeof(*curbp));
	if (dta.dta_size > size) {
		c_conws("not enough memory to load ");
		c_conws(prog);
		c_conws("\r\n");
		p_term(0);
	}
	f = f_open(prog, O_RDONLY);
	if (f < 0) {
		c_conws("can't open ");
		c_conws(prog);
		c_conws("\r\n");
		p_term(0);
	}
	f_read(f, sizeof(hdr), &hdr);
	if (A_BADMAG(hdr)) {
		c_conws(prog);
		c_conws(" is not executable\r\n");
		p_term(0);
	}
	curbp->p_env = env;
	curbp->p_cmdlin[0] = strlen(cmd);
	strcpy(curbp->p_cmdlin + 1, cmd);
	curbp->p_tbase = (char *)(curbp + 1);
	curbp->p_dbase = curbp->p_tbase + hdr.a_text;
	curbp->p_bbase = curbp->p_dbase + hdr.a_data;
	curbp->p_tlen = hdr.a_text;
	curbp->p_dlen = hdr.a_data;
	curbp->p_blen = hdr.a_bss;
	f_read(f, dta.dta_size - sizeof(hdr), curbp->p_tbase);
	f_close(f);
	relocate(curbp->p_tbase, curbp->p_bbase + hdr.a_syms);
	FlushInstructionCache();
	memset(curbp->p_bbase, 0, curbp->p_blen);
	call_sr = 0;
	call_regs[0] = 0;
	call_pc = (long)curbp->p_tbase;
	call_sp = (long)curbp->p_hitpa - (2 *sizeof(long));
	((long *)call_sp)[0] = 0xffffffff;
	((long *)call_sp)[1] = (long)curbp;
	if (vm) {
		swap = 0;
		mintssp = jet_stack;
		if (HoldMemory(ApplicZone(), (long)(jet_stack)-(long)ApplicZone() +
			dta.dta_size - sizeof(hdr) + 1) != 0) {
			c_conws("Unable to Hold memory\r\n");
			p_term(0);
		}
		asm(".word	0x7008,0xa08d	/* enter supervisor mode */
		movel	sp,_macssp		/* save the mac ssp */
		movel	_mintssp,sp ");		/* restore the mint ssp */
	}
	out();
	/* not reached */
	return 0;
}

void p_term(short retcode)
{
	c_conws("Press a key to quit program\r\n");
	b_conin(2);
	ExitToShell();
}

void p_term0(void)
{
	p_term(0);
}

static void relocate(char *txt, char *relo)
{
	char *text, *p;
	int c;
	long off, adr;
	
	text = txt;
	p = relo;
	if (*((long *)p) == 0)
		return;
	off = (long)text;
	adr = off + (*(long *)p);
	p += sizeof(long);
	
	for (;;) {
		*((long *)adr) += (long)off;
		for (;;) {
			c = *p++ & 0xFF;
			if (c != 1)
				break;
			adr += 254;
		}
		if (c == 0)
			break;
		if (c & 1) {
			c_conws("relocation error\r\n");
			p_term(0);
		}
		adr += c;
	}
}