diff options
| author | mrb0nk500 <b0nk@b0nk.xyz> | 2019-11-17 23:04:31 -0500 | 
|---|---|---|
| committer | mrb0nk500 <b0nk@b0nk.xyz> | 2019-11-17 23:04:31 -0500 | 
| commit | c42888e7e09b0a45c6b02534829eac06506834a6 (patch) | |
| tree | fd720f5aca4e603efd4e549d798ab318e38c17fd | |
| parent | f070b984f4d1af513d215bd24e6b1951e3ee86cb (diff) | |
The emulator is working!!!
| -rw-r--r-- | opcode.h | 92 | ||||
| -rw-r--r-- | sux.c | 268 | 
2 files changed, 333 insertions, 27 deletions
| @@ -1,4 +1,4 @@ -#define OPNAME(opcode) #opcode /* Get name of Opcode, for dissambly. */ +#define OPNAME(opcode) [opcode] = #opcode /* Get name of Opcode, for dissambly. */  #define CPS 0x00 /* Clear Processor Status. */  #define ADC 0x01 /* ADd with Carry. */  #define PHP 0x08 /* PusH Processor status to stack. */ @@ -84,3 +84,93 @@  #define STX 0xF4 /* STore X register. */  #define SAX 0xF5 /* Store Accumulator, and X register. */  #define BRK 0xF8 /* BReaK. */ +#define STP 0xFF /* SToP. */ + +static const char *opname[0x100] = { +	OPNAME(CPS), +	OPNAME(ADC), +	OPNAME(PHP), +	OPNAME(PHA), +	OPNAME(PHY), +	OPNAME(PAY), +	OPNAME(PHX), +	OPNAME(PAX), +	OPNAME(JMP), +	OPNAME(SBC), +	OPNAME(PLP), +	OPNAME(PLA), +	OPNAME(PLY), +	OPNAME(PYA), +	OPNAME(PLX), +	OPNAME(PXA), +	OPNAME(JSR), +	OPNAME(AND), +	OPNAME(ANY), +	OPNAME(AAY), +	OPNAME(ANX), +	OPNAME(AAX), +	OPNAME(STT), +	OPNAME(BPO), +	OPNAME(ORA), +	OPNAME(ORY), +	OPNAME(OAY), +	OPNAME(ORX), +	OPNAME(OAX), +	OPNAME(SEI), +	OPNAME(BNG), +	OPNAME(XOR), +	OPNAME(XRY), +	OPNAME(XAY), +	OPNAME(XRX), +	OPNAME(XAX), +	OPNAME(CLI), +	OPNAME(BCS), +	OPNAME(SLA), +	OPNAME(SEC), +	OPNAME(BCC), +	OPNAME(SRA), +	OPNAME(CLC), +	OPNAME(BEQ), +	OPNAME(ROL), +	OPNAME(SSP), +	OPNAME(BNE), +	OPNAME(ROR), +	OPNAME(CSP), +	OPNAME(BVS), +	OPNAME(MUL), +	OPNAME(SEV), +	OPNAME(BVC), +	OPNAME(DIV), +	OPNAME(CLV), +	OPNAME(RTS), +	OPNAME(CMP), +	OPNAME(CPY), +	OPNAME(CAY), +	OPNAME(CPX), +	OPNAME(CAX), +	OPNAME(ENT), +	OPNAME(RTI), +	OPNAME(INC), +	OPNAME(INY), +	OPNAME(IAY), +	OPNAME(INX), +	OPNAME(IAX), +	OPNAME(DEC), +	OPNAME(DEY), +	OPNAME(DAY), +	OPNAME(DEX), +	OPNAME(DAX), +	OPNAME(LDA), +	OPNAME(LDY), +	OPNAME(LAY), +	OPNAME(LDX), +	OPNAME(LAX), +	OPNAME(NOP), +	OPNAME(STA), +	OPNAME(STY), +	OPNAME(SAY), +	OPNAME(STX), +	OPNAME(SAX), +	OPNAME(BRK), +	OPNAME(STP), +}; @@ -1,7 +1,18 @@  #include "opcode.h"  #include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#define C (1 << 0) +#define Z (1 << 1) +#define I (1 << 2) +#define S (1 << 3) +#define V (1 << 6) +#define N (1 << 7) +  #define STK_STADDR 0x010000 /* Starting address of the stack. */  uint8_t *addr; /* Address Space. */ +uint8_t update_pc = 1; /* Update the program counter. */  uint16_t sp; /* Stack pointer. */  uint64_t a[8]; /* Accumulator. */  uint64_t y[8]; /* Y index. */ @@ -126,19 +137,14 @@ int alu(uint8_t opcode, uint64_t value, uint8_t thread) {  			break;  		/* Shift accumulator left. */  		case SLA: -			c = (ps & (1 << thread)) >> thread; -			if (value > 1) -				c = ((a << value-1) & 0x8000000000000000) >> 63;  			sum = (value < 64) ? a[thread] << value : 0; +			c = a[thread] >> 63;  			a[thread] = sum;  			break;  		/* Shift accumulator right. */  		case SRA: -			c = (ps & (1 << thread)) >> thread; -			if (value > 1) -				c = (a >> value-1) & 1; -			sum = (value < 64) ? a << value : 0; -			c = sum & 1; +			sum = (value < 64) ? a[thread] >> value : 0; +			c = a[thread] & 1;  			a[thread] = sum;  			break;  		/* Rotate accumulator left. */ @@ -156,7 +162,7 @@ int alu(uint8_t opcode, uint64_t value, uint8_t thread) {  			a[thread]++;  			if (opcode == IAY)  				y[thread]++; -			if[opcode == IAX] +			if (opcode == IAX)  				x[thread]++;  			break;  		/* Increment y register. */ @@ -174,7 +180,7 @@ int alu(uint8_t opcode, uint64_t value, uint8_t thread) {  			a[thread]--;  			if (opcode == DAY)  				y[thread]--; -			if[opcode == DAX] +			if (opcode == DAX)  				x[thread]--;  			break;  		/* Decrement y register. */ @@ -186,17 +192,17 @@ int alu(uint8_t opcode, uint64_t value, uint8_t thread) {  			x[thread]--;  			break;  		default: -			printf("Cool, you inputed a non existent opcode, which means\n" +			/*printf("Cool, you inputed a non existent opcode, which means\n"  				"that you have now wasted clock cycles.\n" -				"Good job! *clap*\n"); +				"Good job! *clap*\n");*/  			break;  	}  	z = (a[thread] == 0);  	n = (a[thread] >> 63); -	ps = (n) ? (ps | 1 << 7+thread) : (ps & ~(1 << 7+thread)); -	ps = (v) ? (ps | 1 << 6+thread) : (ps & ~(1 << 6+thread)); -	ps = (z) ? (ps | 1 << 1+thread) : (ps & ~(1 << 1+thread)); -	ps = (c) ? (ps | 1 << thread) : (ps & ~(1 << thread)); +	ps = (n) ? (ps | (uint64_t)N << 8*thread) : (ps & ~((uint64_t)N << 8*thread)); +	ps = (v) ? (ps | (uint64_t)V << 8*thread) : (ps & ~((uint64_t)V << 8*thread)); +	ps = (z) ? (ps | (uint64_t)Z << 8*thread) : (ps & ~((uint64_t)Z << 8*thread)); +	ps = (c) ? (ps | (uint64_t)C << 8*thread) : (ps & ~((uint64_t)C << 8*thread));  	return 1;  } @@ -222,6 +228,7 @@ int threads(uint8_t opcode, uint64_t value) {  }  int branch(uint8_t opcode, uint64_t value, uint8_t thread) { +	uint64_t dif;  	switch (opcode) {  		/* Jump. */  		case JMP: @@ -236,6 +243,132 @@ int branch(uint8_t opcode, uint64_t value, uint8_t thread) {  		case RTS:  			pc[thread] = pull(8);  			break; +		/* Branch if positive. */ +		case BPO: +			if (!(ps & ((uint64_t)N << 8*thread))) +				pc[thread] = value; +			else +				pc[thread]+=0; +			break; +		/* Branch if negative. */ +		case BNG: +			if (ps & ((uint64_t)N << 8*thread)) +				pc[thread] = value; +			else +				pc[thread]+=0; +			break; +		/* Branch if equal. */ +		case BEQ: +			if (ps & ((uint64_t)Z << 8*thread)) +				pc[thread] = value; +			else +				pc[thread]+=0; +			break; +		/* Branch if not equal. */ +		case BNE: +			if (!(ps & ((uint64_t)Z << 8*thread))) +				pc[thread] = value; +			else +				pc[thread]+=0; +			break; +		/* Branch if carry set. */ +		case BCS: +			if (ps & ((uint64_t)C << 8*thread)) +				pc[thread] = value; +			else +				pc[thread]+=0; +			break; +		/* Branch if carry clear. */ +		case BCC: +			if (!(ps & ((uint64_t)C << 8*thread))) +				pc[thread] = value; +			else +				pc[thread]+=0; +			break; +		/* Branch if overflow set. */ +		case BVS: +			if (ps & ((uint64_t)V << 8*thread)) +				pc[thread] = value; +			else +				pc[thread]+=0; +			break; +		/* Branch if overflow clear. */ +		case BVC: +			if (!(ps & ((uint64_t)V << 8*thread))) +				pc[thread] = value; +			else +				pc[thread]+=0; +			break; +		/* Compare accumulator. */ +		case CMP: +		case CAY: +		case CAX: +			if (opcode == CAY || opcode == CAX) { +				dif = (opcode == CAY) ? a[thread]-y[thread] : a[thread]-x[thread]; +				value = a[thread]; +			} else { +				dif = value-a[thread]; +			} +			ps = (dif & 0x8000000000000000) ? (ps | (uint64_t)N << 8*thread) : (ps & ~((uint64_t)N << 8*thread)); +			ps = (dif == 0) ? (ps | (uint64_t)Z << 8*thread) : (ps & ~((uint64_t)Z << 8*thread)); +			ps = (dif > value) ? (ps | (uint64_t)C << 8*thread) : (ps & ~((uint64_t)C << 8*thread)); +			break; +		/* Compare y register. */ +		case CPY: +			dif = value-y[thread]; +			ps = (dif & 0x8000000000000000) ? (ps | (uint64_t)N << 8*thread) : (ps & ~((uint64_t)N << 8*thread)); +			ps = (dif == 0) ? (ps | (uint64_t)Z << 8*thread) : (ps & ~((uint64_t)Z << 8*thread)); +			ps = (dif > value) ? (ps | (uint64_t)C << 8*thread) : (ps & ~((uint64_t)C << 8*thread)); +			break; +		/* Compare x register. */ +		case CPX: +			dif = value-x[thread]; +			ps = (dif & 0x8000000000000000) ? (ps | (uint64_t)N << 8*thread) : (ps & ~((uint64_t)N << 8*thread)); +			ps = (dif == 0) ? (ps | (uint64_t)Z << 8*thread) : (ps & ~((uint64_t)Z << 8*thread)); +			ps = (dif > value) ? (ps | (uint64_t)C << 8*thread) : (ps & ~((uint64_t)C << 8*thread)); +			break; +	} +	return 1; +} + +int setflags(uint8_t opcode, uint8_t thread) { +	switch (opcode) { +		/* Clear processor status. */ +		case CPS: +			ps &= 0; +			break; +		/* Set interupt flag. */ +		case SEI: +			ps |= ((uint64_t)I << 8*thread); +			break; +		/* Clear interupt flag. */ +		case CLI: +			ps &= ~((uint64_t)I << 8*thread); +			break; +		/* Set carry flag. */ +		case SEC: +			ps |= ((uint64_t)C << 8*thread); +			break; +		/* Clear carry flag. */ +		case CLC: +			ps &= ~((uint64_t)C << 8*thread); +			break; +		/* Set stack protection flag. */ +		case SSP: +			ps |= ((uint64_t)S << 8*thread); +			break; +		/* Clear stack protection flag. */ +		case CSP: +			ps &= ~((uint64_t)S << 8*thread); +			break; +		/* Set overflow flag. */ +		case SEV: +			ps |= ((uint64_t)V << 8*thread); +			break; +		/* Clear overflow flag. */ +		case CLV: +			ps &= ~((uint64_t)V << 8*thread); +			break;  	}  	return 1;  } @@ -289,17 +422,17 @@ int memory(uint8_t opcode, uint64_t value, uint8_t thread) {  		case PHA:  		case PAY:  		case PAX: -			push(a, value); +			push(a[thread], value);  			if (opcode == PAY) -				push(y, value); +				push(y[thread], value);  			if (opcode == PAX) -				push(x, value); +				push(x[thread], value);  			break;  		case PHY: -			push(y, value); +			push(y[thread], value);  			break;  		case PHX: -			push(x, value); +			push(x[thread], value);  			break;  		/* Pull processor status. */  		case PLP: @@ -309,20 +442,103 @@ int memory(uint8_t opcode, uint64_t value, uint8_t thread) {  		case PLA:  		case PYA:  		case PXA: -			a = pull(value); +			a[thread] = pull(value);  			if (opcode == PAY) -				y = pull(value); +				y[thread] = pull(value);  			if (opcode == PAX) -				x = pull(value); +				x[thread] = pull(value);  			break;  		/* Pull y register. */  		case PLY: -			y = pull(value); +			y[thread] = pull(value);  			break;  		/* Pull x register. */  		case PLX: -			x = pull(value); +			x[thread] = pull(value);  			break;  	}  	return 1;  } + +int misc(uint8_t opcode, uint8_t thread) { +	switch (opcode) { +		/* No operation. */ +		case NOP: +			break; +		/* TODO: Implement interupts. */ +		case BRK: +			break; +	} +	return 1; +} + +int main(int argc, char **argv) { +	a[0] = 0; +	x[0] = 0; +	y[0] = 0; +	addr = malloc(8*0x04000000); +	int v = 0; +	addr[0x8000] = 0x00;	/* CPS */ +	addr[0x8001] = 0xE1;	/* LDA #$E1 */ +	addr[0x8002] = 0x01; +	addr[0x8003] = 0x51;	/* SLA #$01 */ +	addr[0x8004] = 0x01; +	addr[0x8005] = 0xF1;	/* STA $4000*/ +	addr[0x8006] = 0x00; +	addr[0x8007] = 0x40; +	addr[0x8008] = 0x50;	/* BCS $8001 */ +	addr[0x8009] = 0x01; +	addr[0x800A] = 0x80; +	addr[0x800B] = 0x10;	/* JMP $1003 */ +	addr[0x800C] = 0x03; +	addr[0x800D] = 0x80; +	addr[0x8010] = 0xFF;	/* STP */ +	addr[0xFFFC] = 0x00; +	addr[0xFFFD] = 0x80; +	pc[0] = addr[0xFFFC] | (addr[0xFFFD] << 8); +	uint64_t value = 0; +	uint8_t end = 0; +	uint8_t opcode = 0; +	uint8_t size; +	printf("\033[2J"); +	while (!end) { +	printf("pc: 0x%04llx, a: 0x%016llx, carry: %u, inst: %s, value: 0x%04llx, $%04llx: %02x\n", pc[0], a[0], ps & 1, opname[opcode], value, value, addr[value]); +	opcode = addr[pc[0]]; +	if (opcode == STA || opcode == JMP || opcode == BCS) +		size = 2; +	else if (opcode == CPS || opcode == NOP) +		size = 0; +	else if (opcode == STP) +		end = 1, size = 0; +	else +		size = 1; +	if(update_pc) +		pc[0]++; +	else +		update_pc = 1; +	if (size) { +		int i = 0; +		while (i < size) { +			if (!i) +				value = (addr[pc[0]]); +			else +				value |= (addr[pc[0]] << (8*i)); +			printf("pc: 0x%04llx, a: 0x%016llx, carry: %u, inst: %s, value: 0x%04llx, $%04llx: %02x\n", pc[0], a[0], ps & 1, opname[opcode], value, value, addr[value]); +			if (update_pc) +				pc[0]++; +			else +				update_pc = 1; +			i++; +		} +	} +	if (opcode == SLA || opcode == ADC) +		alu(opcode, value, 0); +	if (opcode == JMP || opcode == BCS) +		branch(opcode, value, 0); +	memory(opcode, value, 0); +	printf("pc: 0x%04llx, a: 0x%016llx, carry: %u, inst: %s, value: 0x%04llx, $%04llx: %02x\n", pc[0], a[0], ps & 1, opname[opcode], value, value, addr[value]); +	} +	free(addr); +	return 0; + +} | 
