diff src/cpu.c @ 43:6e7bfe83d2b0

Changed the design to vastly simplify the video hardware and support a 23-bit address space on the CPU
author Michael Pavone <pavone@retrodev.com>
date Sat, 27 Aug 2016 22:38:31 -0700
parents 5683d9ba9acc
children 51672bd41cdd
line wrap: on
line diff
--- a/src/cpu.c	Mon Apr 11 23:35:51 2016 -0700
+++ b/src/cpu.c	Sat Aug 27 22:38:31 2016 -0700
@@ -35,7 +35,7 @@
 	return context;
 }
 
-uint16_t cpu_read_16(cpu *context, uint16_t address)
+uint16_t cpu_read_16(cpu *context, uint32_t address)
 {
 	context->cycles += context->clock_inc;
 	if (address & 1) {
@@ -53,7 +53,7 @@
 	return 0xFFFF;
 }
 
-uint8_t cpu_read_8(cpu *context, uint16_t address)
+uint8_t cpu_read_8(cpu *context, uint32_t address)
 {
 	context->cycles += context->clock_inc;
 	memory_region *cur = context->mem_regions;
@@ -66,7 +66,7 @@
 	return 0xFF;
 }
 
-void cpu_write_16(cpu *context, uint16_t address, uint16_t value)
+void cpu_write_16(cpu *context, uint32_t address, uint16_t value)
 {
 	context->cycles += context->clock_inc;
 	if (address & 1) {
@@ -85,7 +85,7 @@
 	}
 }
 
-void cpu_write_8(cpu *context, uint16_t address, uint8_t value)
+void cpu_write_8(cpu *context, uint32_t address, uint8_t value)
 {
 	context->cycles += context->clock_inc;
 	memory_region *cur = context->mem_regions;
@@ -119,7 +119,7 @@
 
 void fetch_instruction(cpu *context)
 {
-	context->prefetch = cpu_read_16(context, context->regs[REG_PC]);
+	context->prefetch = cpu_read_16(context, context->pc_msb | context->regs[REG_PC]);
 	context->regs[REG_PC] += 2;
 	context->state = STATE_NORMAL;
 }
@@ -127,9 +127,11 @@
 void vector_fetch(cpu *context)
 {
 	context->exception_pc = context->regs[REG_PC] - 2;
+	context->exception_pch = context->pc_msb >> 16;
 	context->exception_sr = context->regs[REG_SR];
 	context->regs[REG_SR] &= ~(STATUS_INT0_ENABLE | STATUS_INT1_ENABLE);
 	context->regs[REG_PC] = cpu_read_16(context, context->vector_base + context->exception * 2);
+	context->pc_msb = 0;
 	context->state = STATE_NEED_FETCH;
 }
 
@@ -236,10 +238,6 @@
 		context->regs[REG_SR] = context->exception_sr;
 		context->state = STATE_NEED_FETCH;
 		return;
-	case TRAP:
-		context->state = STATE_EXCEPTION_START;
-		context->exception = context->regs[dst];
-		return;
 	case TRAPI:
 		context->state = STATE_EXCEPTION_START;
 		context->exception = dst;
@@ -274,6 +272,13 @@
 	case SETVBR:
 		context->vector_base = context->regs[dst];
 		break;
+	case GETDATABANKS:
+		context->regs[dst] = context->data_high_msb >> 7 | context->data_low_msb >> 15;
+		break;
+	case SETDATABANKS:
+		context->data_high_msb = (context->regs[dst] & 0xFF00) << 7;
+		context->data_low_msb = (context->regs[dst] & 0xFF) << 15;
+		break;
 	default:
 		context->state = STATE_EXCEPTION_START;
 		context->exception = EXCEPTION_INVALID_INSTRUCTION;
@@ -321,12 +326,11 @@
 			return;
 		}
 		break;
-	case IN:
-		context->regs[dst] = cpu_read_port(context, context->regs[a]);
+	case LONGJMP:
+		context->regs[REG_PC] = context->regs[a];
+		context->pc_msb = (context->regs[dst] & 0x7F) << 16;
+		context->state = STATE_NEED_FETCH;
 		break;
-	case OUT:
-		cpu_write_port(context, context->regs[a], context->regs[dst]);
-		return;
 	case INI:
 		context->regs[dst] = cpu_read_port(context, a);
 		break;
@@ -346,6 +350,10 @@
 		context->regs[dst] = context->regs[dst] | format_immediate(a);
 		update_flags_bitwise(context, context->regs[dst]);
 		break;
+	case XORI:
+		context->regs[dst] = context->regs[dst] ^ format_immediate(a);
+		update_flags_bitwise(context, context->regs[dst]);
+		break;
 	case LSI:
 		shift = a & 7;
 		if (!shift) {
@@ -377,6 +385,19 @@
 	}
 }
 
+uint32_t get_data_address(cpu *context, uint8_t a, uint8_t b)
+{
+	uint32_t address = context->regs[a] + context->regs[b];
+	if (a == REG_PC || b == REG_PC) {
+		address |= context->pc_msb;
+	} else if (address & 0x8000) {
+		address = (address & 0x7FFF) | context->data_high_msb;
+	} else {
+		address |= context->data_low_msb;
+	}
+	return address;
+}
+
 void run_instruction(cpu *context)
 {
 	uint16_t instruction = context->prefetch;
@@ -396,16 +417,16 @@
 		context->regs[dst] |= a << 12 | b << 8;
 		break;
 	case LD8:
-		context->regs[dst] = cpu_read_8(context, context->regs[a] + context->regs[b]);
+		context->regs[dst] = cpu_read_8(context, get_data_address(context, a, b));
 		break;
 	case LD16:
-		context->regs[dst] = cpu_read_16(context, context->regs[a] + context->regs[b]);
+		context->regs[dst] = cpu_read_16(context, get_data_address(context, a, b));
 		break;
 	case STR8:
-		cpu_write_8(context, context->regs[a] + context->regs[b], context->regs[dst]);
+		cpu_write_8(context, get_data_address(context, a, b), context->regs[dst]);
 		return;
 	case STR16:
-		cpu_write_16(context, context->regs[a] + context->regs[b], context->regs[dst]);
+		cpu_write_16(context,get_data_address(context, a, b), context->regs[dst]);
 		return;
 	case ADD:
 		tmp = context->regs[a] + context->regs[b];