wm: 5552

ref: b1698f6307812f32fe6d062908d52ac3350e5e8b
dir: /5551e.c/

View raw version
/* 5551 cpu emulator */

#include <stdbool.h>
#include <stdio.h>

#include "5551.h"

typedef struct
{
	bool flags[8];
	int regs[8];
}reg_t;

bool add_bit(bool a, bool b)
{
	bool out;
	out = ((a ^ b) ^ carry);
	carry = (((a ^ b) & carry) | (a & b));
	return out;
}

int btoi(bool 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 main()
{

	reg_t r;
	unsigned int memory[MMAX];
	memory[MMAX-1] = -1; 

	char string[16];
	r.flags[ON] = 1;
	r.flags[NSIGN] = 0;
	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;
				carry = 1;
			case ADD:
				while (a > 0 && b > 0) {
					int diga = a % 10;
					int digb = b % 10;
					barr[ind] = add_bit(diga, digb);
					a /= 10;
					b /= 10;
					ind++;
				}
				barr[ind] = carry;
				r.regs[c] = btoi(barr,ind);
				break;
				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'; 
        ind = 0;
        carry = 0;
	}
	return 0;
}