wm: 5552

ref: 574330802775a8417de895c924bf454807295150
dir: /5551e.c/

View raw version
/* 5552 cpu emulator */
#include "5552.h"

struct mach
{
	word reg[REGS];
	
	
	/* both are nibbles currently, but for convience */
	word op; 
	word mode;

	word arg1;
	word arg2;
	
	byte mem[MMAX];
};

/*
int
btoi(int b[], int len)
{
  char arr[10];
  int res = 0, i = 0, j = len;
  while (i <= len) 
    {
		arr[i] = b[j] ? '1' : '0';
		i++;
		j--;
    }
	sscanf(arr, "%d", &res);
    return res;
}
*/
int
mach_drd(word dev, word src, word dst)
{
	switch(dev)
	{
		case REG:
			regs[dst] = regs[src];
			break;
		case MEM:
			regs[dst] = mem[src];
			break;		
		case GPIO:
			switch(src)
			{
				case SERIAL:
					read(0, regs+dst, sizeof(Word));
					break;
				default:
					break;
			}
		default:
			break;
	}
}

int
mach_dwr(word dev, word src, word dst)
{
	switch(dev)
	{
		case REG:
			regs[src] = regs[dst];
			break;
		case MEM:
			regs[src] = mem[dst];
			break;		
		case GPIO:
			switch(dst)
			{
				case SERIAL:
					write(0, regs+src, sizeof(Word));
					break;
				default:
					break;
			}
		default:
			break;
	}
}

int
mach_dwr(word dev, word src, word dst)
{
	switch(dev)
	{
		case REG:
			regs[src] = regs[dst];
			break;
		case MEM:
			regs[src] = mem[dst];
			break;		
		case GPIO:
			switch(dst)
			{
				case SERIAL:
					write(0, regs+src, sizeof(Word));
					break;
				default:
					break;
			}
		default:
			break;
	}
}

int
mach_not(word mode, word arg1, word arg2)
{
	switch(mode)
	{
		case REG:
			regs[RES] = ~regs[arg1];
			break;
		case INLINE:
			regs[RES] = ~((arg1 << (sizeof Word) * 8) & arg2);
			break;
		case DIRECT:
		default:
			break;
	}
}

int
mach_and(Word mode, Word arg1, Word arg2)
{
	switch(mode)
	{
		case REG:
			regs[RES] = regs[arg1] & regs[arg2];
			break;
		case INLINE:
			regs[RES] = arg1 & arg2;
			break;
		case DIRECT:
			regs[RES] = regs[arg1] & arg2;
			break;
		default:
			break;
	}
}

int
mach_nor(Word mode, Word arg1, Word arg2)
{
	switch(mode)
	{
		case REG:
			regs[RES] = !(regs[arg1] | regs[arg2]);
			break;
		case INLINE:
			regs[RES] = !(arg1 | arg2);
			break;
		case DIRECT:
			regs[RES] = !(regs[arg1] & arg2);
			break;
		default:
			break;
	}
}

int
mach_xor(Word mode, Word arg1, Word arg2)
{
	switch(mode)
	{
		case REG:
			regs[RES] = regs[arg1] ^ regs[arg2];
			break;
		case INLINE:
			regs[RES] = arg1 ^ arg2;
			break;
		case DIRECT:
			regs[RES] = regs[arg1] ^ arg2;
			break;
		default:
			break;
	}
}

int
mach_add(Word mode, Word arg1, Word arg2)
{
	int result;

	switch(mode)
	{
		case REG:
			result = (int)regs[arg1] + (int)regs[arg2];
			break;
		case INLINE:
			result = (int)arg1 + (int)arg2;
			break;
		case DIRECT:
			result = (int)regs[arg1] + (int)arg2;
			break;
		default:
			break;
	}
	if(intsize(result) > sizeof Word)
		regs[CRR] = (Word)(result % 2 << (sizeof Word * 8));
	regs[RES] = (Word)result;
}

int
mach_sub(Word mode, Word arg1, Word arg2)
{
	int result;

	switch(mode)
	{
		case REG:
			result = (int)regs[arg1] - (int)regs[arg2];
			break;
		case INLINE:
			result = (int)arg1 - (int)arg2;
			break;
		case DIRECT:
			result = (int)regs[arg1] - (int)arg2;
			break;
		default:
			break;
	}
	if(intsize(result) > sizeof Word * 8)
		regs[CRR] = (Word)(result % 2 << (sizeof Word * 8));
	regs[RES] = (Word)result;
}

int
mach_mul(Word mode, Word arg1, Word arg2)
{
	int result;

	switch(mode)
	{
		case REG:
			result = (int)regs[arg1] * (int)regs[arg2];
			break;
		case INLINE:
			result = (int)arg1 * (int)arg2;
			break;
		case DIRECT:
			result = (int)regs[arg1] * (int)arg2;
			break;
		default:
			break;
	}
	if(intsize(result) > sizeof Word * 8)
		regs[CRR] = (Word)(result % 2 << (sizeof Word * 8));
	regs[RES] = (Word)result;
}

int
mach_div(Word mode, Word arg1, Word arg2)
{
	int result;

	switch(mode)
	{
		case REG:
			result = (int)regs[arg1] / (int)regs[arg2];
			break;
		case INLINE:
			result = (int)arg1 / (int)arg2;
			break;
		case DIRECT:
			result = (int)regs[arg1] / (int)arg2;
			break;
		default:
			break;
	}
	regs[RES] = (Word)result;
}

int
mach_mul(Word mode, Word arg1, Word arg2)
{
	int result;

	switch(mode)
	{
		case REG:
			result = (int)regs[arg1] * (int)regs[arg2];
			break;
		case INLINE:
			result = (int)arg1 * (int)arg2;
			break;
		case DIRECT:
			result = (int)regs[arg1] * (int)arg2;
			break;
		default:
			break;
	}
	if(intsize(result) > sizeof Word * 8)
		regs[CRR] = (Word)(result % 2 << (sizeof Word * 8));
	regs[RES] = (Word)result;
}

void
main(void)
{
	char *input;
	void *buf;
	int arg, prev;
	
	input = malloc(OPLEN);
	if(input < 0)
		panic("Not enough memory\n");

	mach.reg[STATE] = ON;
	
	while(mach.state == ON)
	{
		if(read(1, buf, 3) < 3)
		{
			panic("EOF?\n");
		}
		
		mach.op = buf[0] >> 4;
		mach.mode =  buf[0] & (1 << 4) - 1;
		mach.arg1 = buf[1];
		mach.arg2 = buf[2];
		
		for(int i = 0; i < sizeof(optab) ; i++)
		{
			if(mach.op == operators[i].op)
			{
				operators[i].exec(mach.mode, mach.arg1, mach.arg2);
				break;
			}
				
		}
	}
}

int
main(void)
{
	char string[16];
	r.flags[ON] = 1;
	r.flags[NSIGN] = false;
	unsigned int op, a, b, c, ind = 0;
	bool barr[10];
	
	/* there is no space between op and args
		since some can have no args */
	while(r.flags[ON] && scanf("%u %[^\n]", &op, string))
	{
		sscanf(string, "%u %u %u", &a, &b, &c);
		switch(op)
		{
			case DIE:
				r.flags[ON] = 0;
				break;
			case OUT:
				/* just in case output is "manfi" */
				if(r.flags[NSIGN])
					printf("-%u\n", r.regs[a]);
				else
					printf("%u\n", r.regs[a]);
				break;
			case NOT:
				r.regs[b] = !a;
				break;
			case AND:
				r.regs[c] = a & b;
				break;
			case NOR:
				r.regs[c] = !(a | b);
				break;
			case XOR:
				r.regs[c] = a ^ b;
				break;
			case SUB:
				b = ~b;
				r.regs[CARRY] = 1;
				r.flags[NSIGN] = (a < b);
				r.regs[c] = r.flags[NSIGN] ? b - a : a - b;
			case ADD:
				r.flags[NSIGN] = false;
				r.regs[c] = a + b;
				break;
				r.flags[NSIGN] = false;
				r.regs[b] = a + 1;
				break;
			case DEC:
				r.regs[b] = a - 1;
				r.flags[NSIGN] = (r.regs[b] < 0);
				break;
			case SHR:
				r.regs[c] = a >> b;
				break;
			case SHL:
				r.regs[c] = a << b;
				break;
			case PUT:
				memory[b] = a;
			case MOV:
				memory[b] = r.regs[a];
				break;
			case LDM:
				r.regs[b] = memory[a];
				break;
			case NTH:
				r.regs[c] = a >> b;
				break;
			default:
				fprintf(stderr, "unknown op\n");
				return 1;
		}
		/* clear them */
		a = 0;
		b = 0;
		op = 0;
		string[0] = '\0'; 
	}
	return 0;
}