diff src/cpu.c @ 25:fb14515266f4

Implemented timer and timer interrupts. Added get/setvbr instructions. Fixed assembler bug. Moved mnemonics into a separate source file
author Michael Pavone <pavone@retrodev.com>
date Thu, 31 Mar 2016 23:25:52 -0700
parents a9364f5ee81a
children 083347ccd508
line wrap: on
line diff
--- a/src/cpu.c	Thu Mar 31 00:07:37 2016 -0700
+++ b/src/cpu.c	Thu Mar 31 23:25:52 2016 -0700
@@ -268,6 +268,12 @@
 	case SETENUM:
 		context->exception = context->regs[dst];
 		break;
+	case GETVBR:
+		context->regs[dst] = context->vector_base;
+		break;
+	case SETVBR:
+		context->vector_base = context->regs[dst];
+		break;
 	default:
 		context->state = STATE_EXCEPTION_START;
 		context->exception = EXCEPTION_INVALID_INSTRUCTION;
@@ -370,18 +376,6 @@
 	}
 }
 
-char * mnemonics[] = {
-	"ldim", "ldimh", "ld8", "ld16", "str8", "str16", "add", "adc", "and", "or", "xor", "lsl", "lsr", "asr", "bcc", "single"
-};
-
-char * mnemonics_single_src[] = {
-	"mov", "neg", "not", "cmp", "call", "swap", "in", "out", "ini", "outi", "addi", "andi", "ori", "lsi", "cmpi", "single reg"
-};
-
-char * mnemonics_single_reg[] = {
-	"reti", "trap", "trapi", "getepc", "setepc", "getesr", "setesr", "getenum", "setenum", "setuer", "getuer"
-};
-
 void run_instruction(cpu *context)
 {
 	uint16_t instruction = context->prefetch;
@@ -471,17 +465,33 @@
 {
 	while (context->cycles < target_cycle)
 	{
-		switch (context->state)
+		context->current_target = target_cycle;
+		context->pending_interrupts = get_current_interrupts(context);
+		uint32_t int_cycle = next_interrupt_cycle(context, (~context->pending_interrupts) & 0x3);
+		if (int_cycle < context->current_target) {
+			context->current_target = int_cycle;
+		}
+		while (context->cycles < context->current_target)
 		{
-		case STATE_NEED_FETCH:
-			fetch_instruction(context);
-			break;
-		case STATE_NORMAL:
-			run_instruction(context);
-			break;
-		case STATE_EXCEPTION_START:
-			vector_fetch(context);
-			break;
+			switch (context->state)
+			{
+			case STATE_NEED_FETCH:
+				fetch_instruction(context);
+				break;
+			case STATE_NORMAL:
+				if (context->regs[REG_SR] & context->pending_interrupts) {
+					context->state = STATE_EXCEPTION_START;
+					context->exception = context->pending_interrupts & 1 ? EXCEPTION_INTERRUPT_0 : EXCEPTION_INTERRUPT_1;
+					context->pending_interrupts &= ~(1 << context->exception);
+					ack_interrupt(context, context->exception);
+				} else {
+					run_instruction(context);
+				}
+				break;
+			case STATE_EXCEPTION_START:
+				vector_fetch(context);
+				break;
+			}
 		}
 	}
 }
\ No newline at end of file