File:  [Generator SEGA Genesis emulator] / generator / src / reg68k.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Wed Mar 4 04:46:32 2020 UTC (6 years, 4 months ago) by root
Branches: MAIN, JamesPonder
CVS tags: v0_31, HEAD
0.31

/* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */

#include "generator.h"
#include "registers.h"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>

#include "reg68k.h"
#include "mem68k.h"
#include "cpu68k.h"
#include "cpuz80.h"
#include "vdp.h"
#include "ui.h"
#include "compile.h"
#include "gensound.h"

/*** externed variables ***/

#if (!(defined(PROCESSOR_ARM) || defined(PROCESSOR_SPARC) \
       || defined(PROCESSOR_INTEL)))
  uint32 reg68k_pc;
  uint32 *reg68k_regs;
  t_sr reg68k_sr;
#endif

/*** forward references ***/


/*** reg68k_external_step - execute one instruction ***/

unsigned int reg68k_external_step(void)
{
  static t_ipc ipc;
  static t_iib *piib;
  jmp_buf jb;
  static unsigned int clks;

  if (!(piib = cpu68k_iibtable[fetchword(regs.pc)]))
    ui_err("Invalid instruction @ %08X\n", regs.pc);

  /* !!! entering global register usage area !!! */

  if (!setjmp(jb)) {
    /* move PC and register block into global processor register variables */
    reg68k_pc = regs.pc;
    reg68k_regs = regs.regs;
    reg68k_sr = regs.sr;

    if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending)
      reg68k_internal_autovector(regs.pending);

    cpu68k_ipc(reg68k_pc,
	       mem68k_memptr[(reg68k_pc>>12) & 0xfff](reg68k_pc & 0xFFFFFF),
	       piib, &ipc);
    cpu68k_functable[fetchword(reg68k_pc)*2+1](&ipc);
    cpu68k_clocks+= piib->clocks;
    clks = cpu68k_clocks;
    /* restore global registers back to permanent storage */
    regs.pc = reg68k_pc;
    regs.sr = reg68k_sr;
    longjmp(jb, 1);
  }
  return clks; /* number of clocks done */
}

/*** reg68k_external_execute - execute at least given number of clocks,
     and return number of clocks executed too much (-ve) ***/

unsigned int reg68k_external_execute(unsigned int clocks)
{
  unsigned int index, i;
  t_ipclist *list;
  t_ipc *ipc;
  uint32 pc24;
  jmp_buf jb;
  static t_ipc step_ipc;
  static t_iib *step_piib;
  static int clks;

  clks = clocks;

  if (!setjmp(jb)) {
    /* move PC and register block into global variables */
    reg68k_pc = regs.pc;
    reg68k_regs = regs.regs;
    reg68k_sr = regs.sr;

    if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending)
      reg68k_internal_autovector(regs.pending);

    do {
      pc24 = reg68k_pc & 0xffffff;
      if ((pc24 & 0xff0000) == 0xff0000) {
	/* executing code from RAM, do not use compiled information */
	do {
	  step_piib = cpu68k_iibtable[fetchword(reg68k_pc)];
	  cpu68k_ipc(reg68k_pc,
		     mem68k_memptr[(reg68k_pc>>12) &
				  0xfff](reg68k_pc & 0xFFFFFF),
		     step_piib, &step_ipc);
	  cpu68k_functable[fetchword(reg68k_pc)*2+1](&step_ipc);
	  clks-= step_piib->clocks;
	  cpu68k_clocks+= step_piib->clocks;
	} while (!step_piib->flags.endblk);
	list = NULL; /* stop compiler warning ;(  */
      } else {
	index = (pc24>>1) & (LEN_IPCLISTTABLE-1);
	list = ipclist[index];
	while(list && (list->pc != pc24)) {
	  list = list->next;
	}
#ifdef PROCESSOR_ARM
	if (!list) {
	  list = cpu68k_makeipclist(pc24);
	  list->next = ipclist[index];
	  ipclist[index] = list;
	  list->compiled = compile_make(list);
	}
	list->compiled((t_ipc *)(list+1));
#else
	if (!list) {
	  /* LOG_USER(("Making IPC list @ %08x", pc24)); */
	  list = cpu68k_makeipclist(pc24);
	  list->next = ipclist[index];
	  ipclist[index] = list;
	}
	ipc = (t_ipc *)(list+1);
	do {
	  ipc->function(ipc);
	  ipc++;
	} while (*(int *)ipc);
#endif
	clks-= list->clocks;
	cpu68k_clocks+= list->clocks;
      }
    } while (clks > 0);
    /* restore global registers back to permanent storage */
    regs.pc = reg68k_pc;
    regs.sr = reg68k_sr;
    longjmp(jb, 1);
  }
  return -clks; /* i.e. number of clocks done too much */
}

/*** reg68k_external_autovector - for external use ***/

void reg68k_external_autovector(int avno)
{
  jmp_buf jb;

  if (!setjmp(jb)) {
    /* move PC and register block into global processor register variables */
    reg68k_pc = regs.pc;
    reg68k_regs = regs.regs;
    reg68k_sr = regs.sr;

    reg68k_internal_autovector(avno);

    /* restore global registers back to permanent storage */
    regs.pc = reg68k_pc;
    regs.sr = reg68k_sr;
    longjmp(jb, 1);
  }
}

/*** reg68k_internal_autovector - go to autovector - this call assumes global
     registers are already setup ***/

void reg68k_internal_autovector(int avno)
{
  int curlevel = (reg68k_sr.sr_int>>8) & 7;
  uint32 tmpaddr;

  LOG_DEBUG1(("autovector %d", avno));
  if (curlevel < avno || avno == 7) {
    if (regs.stop) {
      LOG_DEBUG1(("stop finished"));
      /* autovector whilst in a STOP instruction */
      reg68k_pc+= 4;
      regs.stop = 0;
    }
    if (!reg68k_sr.sr_struct.s) {
      regs.regs[15]^= regs.sp;   /* swap A7 and SP */
      regs.sp^= regs.regs[15];
      regs.regs[15]^= regs.sp;
      reg68k_sr.sr_struct.s = 1;
    }
    regs.regs[15]-=4;
    storelong(regs.regs[15], reg68k_pc);
    regs.regs[15]-=2;
    storeword(regs.regs[15], reg68k_sr.sr_int);
    reg68k_sr.sr_struct.t = 0;
    reg68k_sr.sr_int&= ~0x0700;
    reg68k_sr.sr_int|= avno << 8;
    tmpaddr = reg68k_pc;
    reg68k_pc = fetchlong((V_AUTO+avno-1)*4);
    LOG_DEBUG1(("AUTOVECTOR %d: %X -> %X", avno, tmpaddr, reg68k_pc));
    regs.pending = 0;
  } else {
    LOG_DEBUG1(("%08X autovector %d pending", reg68k_pc, avno));
    regs.pending = avno;
  }
}

/*** reg68k_internal_vector - go to vector - this call assumes global
     registers are already setup ***/

void reg68k_internal_vector(int vno, uint32 oldpc)
{
  LOG_DEBUG1(("Vector %d called from %8x!", vno, regs.pc));
  if (!reg68k_sr.sr_struct.s) {
    regs.regs[15]^= regs.sp;   /* swap A7 and SP */
    regs.sp^= regs.regs[15];
    regs.regs[15]^= regs.sp;
    reg68k_sr.sr_struct.s = 1;
  }
  regs.regs[15]-=4;
  storelong(regs.regs[15], oldpc);
  regs.regs[15]-=2;
  storeword(regs.regs[15], reg68k_sr.sr_int);
  reg68k_pc = fetchlong(vno*4);
  LOG_DEBUG1(("VECTOR %d: %X -> %X\n", vno, oldpc, reg68k_pc));
}   

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.