Mercurial > repos > simple16
comparison 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 |
comparison
equal
deleted
inserted
replaced
24:4c9dbfa30a66 | 25:fb14515266f4 |
---|---|
266 context->regs[dst] = context->exception; | 266 context->regs[dst] = context->exception; |
267 break; | 267 break; |
268 case SETENUM: | 268 case SETENUM: |
269 context->exception = context->regs[dst]; | 269 context->exception = context->regs[dst]; |
270 break; | 270 break; |
271 case GETVBR: | |
272 context->regs[dst] = context->vector_base; | |
273 break; | |
274 case SETVBR: | |
275 context->vector_base = context->regs[dst]; | |
276 break; | |
271 default: | 277 default: |
272 context->state = STATE_EXCEPTION_START; | 278 context->state = STATE_EXCEPTION_START; |
273 context->exception = EXCEPTION_INVALID_INSTRUCTION; | 279 context->exception = EXCEPTION_INVALID_INSTRUCTION; |
274 return; | 280 return; |
275 } | 281 } |
367 } | 373 } |
368 if (dst == REG_PC) { | 374 if (dst == REG_PC) { |
369 context->state = STATE_NEED_FETCH; | 375 context->state = STATE_NEED_FETCH; |
370 } | 376 } |
371 } | 377 } |
372 | |
373 char * mnemonics[] = { | |
374 "ldim", "ldimh", "ld8", "ld16", "str8", "str16", "add", "adc", "and", "or", "xor", "lsl", "lsr", "asr", "bcc", "single" | |
375 }; | |
376 | |
377 char * mnemonics_single_src[] = { | |
378 "mov", "neg", "not", "cmp", "call", "swap", "in", "out", "ini", "outi", "addi", "andi", "ori", "lsi", "cmpi", "single reg" | |
379 }; | |
380 | |
381 char * mnemonics_single_reg[] = { | |
382 "reti", "trap", "trapi", "getepc", "setepc", "getesr", "setesr", "getenum", "setenum", "setuer", "getuer" | |
383 }; | |
384 | 378 |
385 void run_instruction(cpu *context) | 379 void run_instruction(cpu *context) |
386 { | 380 { |
387 uint16_t instruction = context->prefetch; | 381 uint16_t instruction = context->prefetch; |
388 fetch_instruction(context); | 382 fetch_instruction(context); |
469 | 463 |
470 void run_cpu(cpu *context, uint32_t target_cycle) | 464 void run_cpu(cpu *context, uint32_t target_cycle) |
471 { | 465 { |
472 while (context->cycles < target_cycle) | 466 while (context->cycles < target_cycle) |
473 { | 467 { |
474 switch (context->state) | 468 context->current_target = target_cycle; |
469 context->pending_interrupts = get_current_interrupts(context); | |
470 uint32_t int_cycle = next_interrupt_cycle(context, (~context->pending_interrupts) & 0x3); | |
471 if (int_cycle < context->current_target) { | |
472 context->current_target = int_cycle; | |
473 } | |
474 while (context->cycles < context->current_target) | |
475 { | 475 { |
476 case STATE_NEED_FETCH: | 476 switch (context->state) |
477 fetch_instruction(context); | 477 { |
478 break; | 478 case STATE_NEED_FETCH: |
479 case STATE_NORMAL: | 479 fetch_instruction(context); |
480 run_instruction(context); | 480 break; |
481 break; | 481 case STATE_NORMAL: |
482 case STATE_EXCEPTION_START: | 482 if (context->regs[REG_SR] & context->pending_interrupts) { |
483 vector_fetch(context); | 483 context->state = STATE_EXCEPTION_START; |
484 break; | 484 context->exception = context->pending_interrupts & 1 ? EXCEPTION_INTERRUPT_0 : EXCEPTION_INTERRUPT_1; |
485 } | 485 context->pending_interrupts &= ~(1 << context->exception); |
486 } | 486 ack_interrupt(context, context->exception); |
487 } | 487 } else { |
488 run_instruction(context); | |
489 } | |
490 break; | |
491 case STATE_EXCEPTION_START: | |
492 vector_fetch(context); | |
493 break; | |
494 } | |
495 } | |
496 } | |
497 } |