shithub: gpufs

ref: a66be92f63ec59c1811403eb7b95fa72588beee6
dir: /vm.c/

View raw version
#include <u.h>
#include <libc.h>
#include "vm.h"
#include "ops.h"
#include "objects.h"

extern int debug;

#define IDVALID(c) (c < numobjects)

Frame *stack = nil;

u32int
runinst(u32int *ptr)
{
	u32int len, opcode;
	void (*func)(Frame*,u32int);
	
	opcode = (*ptr) & 0x0000ffff;
	len = ((*ptr) & 0xffff0000) >> 16;
	
	if (oplookup(opcode, &func)) {
		func(stack, len);
		
		// if (func) changes pc, ignore it
		if (ptr == stack->pc) {
			stack->pc += len;
		}
		return len;
	}
	fprint(2, "error: %r\n");
	return 0;
}

void
runstack(u32int *ptr)
{
	Frame *n = malloc(sizeof(Frame));
	
	n->next = stack;
	stack = n;
	stack->pc = ptr;
	
	while (runinst(stack->pc)) {
		;
	}
}

void
retstack(void)
{
	Frame *p, *c;
	
	p = stack->next;
	c = stack;
	
	if (!p)
		goto fin;
	
	stack = p;

fin:
	free(c);
}

void
vmrun(u32int *ptr)
{
	stack = nil; // TODO clean stack
	runstack(ptr);
}

int compile = 0;

typedef struct Object Object;
struct Object {
	int id;
	char type;
	union {
		Shader s;
		Buffer b;
	};
};

Object objects[256];
int numobjects = 0;

vlong
genshader(void)
{
	vlong id;
	if (numobjects >= 256) {
		werrstr("not enough free objects!");
		return -1;
	}
	id = numobjects++;
	objects[id].id = id;
	objects[id].type = SHADER;
	objects[id].s.buffer = nil;
	objects[id].s.len = -1;
	return id;
}

vlong
genbuffer(long size)
{
	vlong id;
	if (numobjects >= 256) {
		werrstr("not enough free objects!");
		return -1;
	}
	id = numobjects;
	objects[id].id = id;
	objects[id].type = BUFFER;
	objects[id].b.len = size;
	objects[id].b.buffer = malloc(size);
	if (!objects[id].b.buffer) {
		werrstr("cannot allocate memory: %r");
		return -1;
	}
	numobjects++;
	return id;
}

vlong
getnumobjects()
{
	return numobjects;
}

long
getbufferlength(vlong id)
{
	if (objects[id].type != BUFFER) {
		werrstr("invalid object type!");
		return -1;
	}
	return objects[id].b.len;
}

long
getshaderlength(vlong id)
{
	long len;
	if (objects[id].type != SHADER) {
		werrstr("invalid object type!");
		return -1;
	}
	len = objects[id].s.len;
	return len < 0 ? 0 : len;
}

int
getobjecttype(vlong id)
{
	return objects[id].type;
}

vlong
getobjectid(vlong num)
{
	if (num >= numobjects) {
		werrstr("invalid object number: %lld", num);
		return -1;
	}
	return objects[num].id;
}

int
writeshader(vlong id, void *data, long n, long offset)
{
	char *buf;
	
	if (!IDVALID(id)) {
		werrstr("invalid object id %lld", id);
		return 0;
	}
	
	if (objects[id].type != SHADER) {
		werrstr("invalid object type: %lld != SHADER", id);
		return 0;
	}
	
	buf = (char*)objects[id].s.buffer;
	if (!buf) {
		objects[id].s.len = n+offset;
		objects[id].s.buffer = malloc(objects[id].s.len);
		buf = (char*)objects[id].s.buffer;
	}
	if (!buf) {
		sysfatal("out of memory");
		return 0;
	}
	if (offset+n > objects[id].s.len) {
		objects[id].s.len = n+offset;
		objects[id].s.buffer = realloc(objects[id].s.buffer, objects[id].s.len);
		buf = (char*)objects[id].s.buffer;
	}
	if (!buf) {
		sysfatal("out of memory!");
		return 0;
	}
	buf += offset;
	memcpy(buf, data, n);
	return n;
}

int
writebuffer(vlong id, void *data, long n, long offset)
{
	char *buf;
	
	if (!IDVALID(id)) {
		werrstr("invalid object id %lld", id);
		return 0;
	}
	
	if (objects[id].type != BUFFER) {
		werrstr("invalid object type: %lld != BUFFER", id);
		return 0;
	}
	
	if (offset+n > objects[id].b.len) {
		return -1;
	}
	
	buf = &objects[id].b.buffer[offset];
	memcpy(buf, data, n);
	return n;
}

int
compileshader(vlong id)
{
	werrstr("not implemented!");
	return 0;
}

int
readshader(vlong id, void *data, long n, long offset)
{
	char *buf;
	
	if (!IDVALID(id)) {
		werrstr("invalid id %lld", id);
		return 0;
	}
	
	if (objects[id].type != SHADER) {
		werrstr("invalid object type: %lld != SHADER", id);
		return 0;
	}
	
	buf = (char*)objects[id].s.buffer;
	
	if (!buf) {
		werrstr("shader is empty");
		return 0;
	}
	
	if (offset+n > objects[id].b.len) {
		n = objects[id].s.len - offset;
	}
	if (n <= 0)
		return 0;
	
	buf = &buf[offset];
	memcpy(data, buf, n);
	return n;
}

int readbuffer(vlong id, void *data, long n, long offset)
{
	char *buf;
	
	if (!IDVALID(id)) {
		werrstr("invalid id %lld", id);
		return 0;
	}
	
	if (objects[id].type != BUFFER) {
		werrstr("invalid object type: %lld != BUFFER", id);
		return 0;
	}
	
	if (offset+n > objects[id].b.len) {
		n = objects[id].b.len - offset;
	}
	if (n <= 0)
		return 0;
	
	buf = &objects[id].b.buffer[offset];
	memcpy(data, buf, n);
	return n;
}