Skip to content

Commit

Permalink
Merge pull request #766 from frangarcj/cyclone
Browse files Browse the repository at this point in the history
Cyclone and DrZ80 support
  • Loading branch information
arcadez2003 committed Jan 3, 2020
2 parents 2c23c6b + b308c3f commit 225812f
Show file tree
Hide file tree
Showing 20 changed files with 79,543 additions and 5 deletions.
13 changes: 9 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,8 @@ else ifeq ($(platform), vita)
TARGET = $(TARGET_NAME)_libretro_$(platform).a
CC = arm-vita-eabi-gcc$(EXE_EXT)
AR = arm-vita-eabi-ar$(EXE_EXT)
PLATCFLAGS += -DVITA
CFLAGS += -mthumb -mfloat-abi=hard -fsingle-precision-constant
PLATCFLAGS += -DVITA -marm
CFLAGS += -mfloat-abi=hard -fsingle-precision-constant
CFLAGS += -Wall -mword-relocations
CFLAGS += -fomit-frame-pointer -ffast-math
CFLAGS += -fno-unwind-tables -fno-asynchronous-unwind-tables
Expand All @@ -341,7 +341,9 @@ else ifeq ($(platform), vita)
HAVE_RZLIB := 1
ARM = 1
STATIC_LINKING := 1

USE_CYCLONE := 1
USE_DRZ80 := 1

else ifneq (,$(findstring armv,$(platform)))
TARGET = $(TARGET_NAME)_libretro.so
CFLAGS += -fPIC
Expand Down Expand Up @@ -627,7 +629,7 @@ CFLAGS += $(INCFLAGS) $(INCFLAGS_PLATFORM)
# combine the various definitions to one
CDEFS = $(DEFS) $(COREDEFS) $(CPUDEFS) $(SOUNDDEFS) $(ASMDEFS) $(DBGDEFS)

OBJECTS := $(SOURCES_C:.c=.o)
OBJECTS := $(SOURCES_C:.c=.o) $(SOURCES_ASM:.s=.o)

OBJOUT = -o
LINKOUT = -o
Expand Down Expand Up @@ -678,6 +680,9 @@ CFLAGS += $(PLATCFLAGS) $(CDEFS)
@echo Compiling $<...
$(HIDE)$(CC) -c $(OBJOUT)$@ $< $(CFLAGS)

%.o: %.s
$(CC) -c $(OBJOUT)$@ $< $(CFLAGS)

$(OBJ)/%.a:
@echo Archiving $@...
@$(RM) $@
Expand Down
12 changes: 12 additions & 0 deletions Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -2702,3 +2702,15 @@ SOURCES_C += \
$(CORE_DIR)/lib/zlib/unzip.c \
$(CORE_DIR)/lib/zlib/zutil.c
endif

ifeq ($(USE_CYCLONE), 1)
CPUDEFS += -DHAS_CYCLONE=1
SOURCES_ASM += $(CORE_DIR)/cpu/m68000_cyclone/cyclone.s
SOURCES_C += $(CORE_DIR)/cpu/m68000_cyclone/c68000.c
endif

ifeq ($(USE_DRZ80), 1)
CPUDEFS += -DHAS_DRZ80=1
SOURCES_ASM += $(CORE_DIR)/cpu/z80_drz80/drz80.s
SOURCES_C += $(CORE_DIR)/cpu/z80_drz80/drz80_z80.c
endif
282 changes: 282 additions & 0 deletions src/cpu/m68000_cyclone/c68000.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
#include "c68000.h"
#include "driver.h"
#include "cpuintrf.h"
#include "cyclone.h"
#include "memory.h"


typedef struct
{
struct Cyclone regs;
int pending_interrupts;
int (*MAMEIrqCallback)(int int_level);
} Cyclone_Regs;

static Cyclone_Regs cyclone;
int cyclone_ICount;

static unsigned int MyCheckPc(unsigned int pc)
{
pc = (pc-cyclone.regs.membase) & 0xffffff; /* Get the real program counter */
change_pc24bew(pc);
cyclone.regs.membase=(unsigned int)OP_ROM;
return cyclone.regs.membase+pc; /* New program counter */
}

static void update_irq_line(void)
{
if (cyclone.pending_interrupts & 0xff000000)
{
int level, mask = 0x80000000;
for (level = 7; level; level--, mask >>= 1)
if (cyclone.pending_interrupts & mask)
break;
cyclone.regs.irq = level;
}
else
{
cyclone.regs.irq = 0;
}
}

static int MyIrqCallback(int irq)
{
cyclone.pending_interrupts &= ~(1 << (24 + irq));
if (cyclone.MAMEIrqCallback)
cyclone.MAMEIrqCallback(irq);
update_irq_line();
return CYCLONE_INT_ACK_AUTOVECTOR;
}

static void cyclone_Cause_Interrupt(int level)
{
if (level >= 1 && level <= 7)
cyclone.pending_interrupts |= 1 << (24 + level);
update_irq_line();
}

static void cyclone_Clear_Interrupt (int level)
{
if (level >= 1 && level <= 7)
cyclone.pending_interrupts &= ~(1 << (24 + level));
update_irq_line();
}

static data32_t cpu_readmem24bew_dword(offs_t address)
{
data32_t result = cpu_readmem24bew_word(address) << 16;
return result | cpu_readmem24bew_word(address + 2);
}

static void cpu_writemem24bew_dword(offs_t address, data32_t data)
{
cpu_writemem24bew_word(address, data >> 16);
cpu_writemem24bew_word(address + 2, data);
}

void cyclone_init(void)
{
CycloneInit();
}

void cyclone_reset(void *param)
{
memset(&cyclone, 0,sizeof(Cyclone_Regs));
cyclone.regs.checkpc=MyCheckPc;
cyclone.regs.read8 = (unsigned int (*)(unsigned int)) cpu_readmem24bew;
cyclone.regs.read16 = (unsigned int (*)(unsigned int)) cpu_readmem24bew_word;
cyclone.regs.read32 = (unsigned int (*)(unsigned int)) cpu_readmem24bew_dword;
cyclone.regs.write8 = (void (*)(unsigned int, unsigned char)) cpu_writemem24bew;
cyclone.regs.write16= (void (*)(unsigned int, unsigned short)) cpu_writemem24bew_word;
cyclone.regs.write32= (void (*)(unsigned int, unsigned int)) cpu_writemem24bew_dword;
cyclone.regs.fetch8 = (unsigned int (*)(unsigned int)) cpu_readmem24bew;
cyclone.regs.fetch16 = (unsigned int (*)(unsigned int)) cpu_readmem24bew_word;
cyclone.regs.fetch32 = (unsigned int (*)(unsigned int)) cpu_readmem24bew_dword;
cyclone.regs.IrqCallback=MyIrqCallback; /* 0 */
cyclone.regs.srh=0x27; /* Set supervisor mode */
cyclone.regs.a[7]=cyclone.regs.read32(0); /* Get Stack Pointer */
cyclone.regs.membase=0;
cyclone.regs.pc=cyclone.regs.checkpc(cyclone.regs.read32(4)); /* Get Program Counter */
cyclone.regs.state_flags = 0; /* not stopped or tracing */
cyclone.pending_interrupts = 0;
CycloneReset(&cyclone.regs);
}

unsigned int cyclone_get_pc(void)
{
return (cyclone.regs.pc - cyclone.regs.membase) & 0xffffff;
}

void cyclone_set_context(void *src)
{
if (src)
{
memcpy(&cyclone,src,sizeof(Cyclone_Regs));
}
update_irq_line();
}

unsigned cyclone_get_context(void *dst)
{
if (dst)
{
memcpy(dst,&cyclone,sizeof(Cyclone_Regs));
}
return sizeof(Cyclone_Regs);

}

int cyclone_execute(int cycles)
{
cyclone.regs.cycles = cycles;
cyclone_ICount = cyclone.regs.cycles;
CycloneRun(&cyclone.regs);
cyclone_ICount = cyclone.regs.cycles;
return (cycles - cyclone.regs.cycles);
}

void cyclone_exit(void)
{
}

void cyclone_set_pc(unsigned val)
{
cyclone.regs.pc=MyCheckPc(val);
}
unsigned cyclone_get_sp(void)
{
return cyclone.regs.a[7];
}

void cyclone_set_sp(unsigned val)
{
cyclone.regs.a[7] = val;
}

enum
{
/* NOTE: M68K_SP fetches the current SP, be it USP, ISP, or MSP */
M68K_PC=1, M68K_SP, M68K_ISP, M68K_USP, M68K_MSP, M68K_SR, M68K_VBR,
M68K_SFC, M68K_DFC, M68K_CACR, M68K_CAAR, M68K_PREF_ADDR, M68K_PREF_DATA,
M68K_D0, M68K_D1, M68K_D2, M68K_D3, M68K_D4, M68K_D5, M68K_D6, M68K_D7,
M68K_A0, M68K_A1, M68K_A2, M68K_A3, M68K_A4, M68K_A5, M68K_A6, M68K_A7
};

unsigned cyclone_get_reg(int regnum)
{
switch( regnum )
{
case REG_PC:
case M68K_PC: return cyclone_get_pc();
case REG_SP:
case M68K_SP: return cyclone_get_sp();
case M68K_ISP: return cyclone.regs.osp;
case M68K_USP: return cyclone.regs.osp;
case M68K_SR: return CycloneGetSr(&cyclone.regs);
case M68K_D0: return cyclone.regs.d[0];
case M68K_D1: return cyclone.regs.d[1];
case M68K_D2: return cyclone.regs.d[2];
case M68K_D3: return cyclone.regs.d[3];
case M68K_D4: return cyclone.regs.d[4];
case M68K_D5: return cyclone.regs.d[5];
case M68K_D6: return cyclone.regs.d[6];
case M68K_D7: return cyclone.regs.d[7];
case M68K_A0: return cyclone.regs.a[0];
case M68K_A1: return cyclone.regs.a[1];
case M68K_A2: return cyclone.regs.a[2];
case M68K_A3: return cyclone.regs.a[3];
case M68K_A4: return cyclone.regs.a[4];
case M68K_A5: return cyclone.regs.a[5];
case M68K_A6: return cyclone.regs.a[6];
case M68K_A7: return cyclone.regs.a[7];
case REG_PREVIOUSPC: return (cyclone.regs.prev_pc - cyclone.regs.membase - 2) & 0xffffff;
default:
if( regnum < REG_SP_CONTENTS )
{
unsigned offset = cyclone_get_sp() + 4 * (REG_SP_CONTENTS - regnum);
if( offset < 0xfffffd )
return cpu_readmem24bew_dword( offset );
}
}
return 0;
}

void cyclone_set_reg(int regnum, unsigned val)
{
switch( regnum )
{
case REG_PC:
case M68K_PC: cyclone_set_pc(val); break;
case REG_SP:
case M68K_SP: cyclone_set_sp(val); break;
case M68K_ISP: cyclone.regs.osp = val; break;
case M68K_USP: cyclone.regs.osp = val; break;
case M68K_SR: CycloneSetSr (&cyclone.regs,val); break;
case M68K_D0: cyclone.regs.d[0] = val; break;
case M68K_D1: cyclone.regs.d[1] = val; break;
case M68K_D2: cyclone.regs.d[2] = val; break;
case M68K_D3: cyclone.regs.d[3] = val; break;
case M68K_D4: cyclone.regs.d[4] = val; break;
case M68K_D5: cyclone.regs.d[5] = val; break;
case M68K_D6: cyclone.regs.d[6] = val; break;
case M68K_D7: cyclone.regs.d[7] = val; break;
case M68K_A0: cyclone.regs.a[0] = val; break;
case M68K_A1: cyclone.regs.a[1] = val; break;
case M68K_A2: cyclone.regs.a[2] = val; break;
case M68K_A3: cyclone.regs.a[3] = val; break;
case M68K_A4: cyclone.regs.a[4] = val; break;
case M68K_A5: cyclone.regs.a[5] = val; break;
case M68K_A6: cyclone.regs.a[6] = val; break;
case M68K_A7: cyclone.regs.a[7] = val; break;
default:
if( regnum < REG_SP_CONTENTS )
{
unsigned offset = cyclone_get_sp() + 4 * (REG_SP_CONTENTS - regnum);
if( offset < 0xfffffd )
cpu_writemem24bew_word( offset, val );
}
}
}

void cyclone_set_irq_line(int irqline, int state)
{
if (irqline == IRQ_LINE_NMI)
irqline = 7;
switch(state)
{
case CLEAR_LINE:
cyclone_Clear_Interrupt(irqline);
return;
case ASSERT_LINE:
cyclone_Cause_Interrupt(irqline);
return;
default:
cyclone_Cause_Interrupt(irqline);
return;
}
}

void cyclone_set_irq_callback(int (*callback)(int irqline))
{
cyclone.MAMEIrqCallback = callback;
}

const char *cyclone_info(void *context, int regnum)
{
switch( regnum )
{
case CPU_INFO_NAME: return "Cyclone 68000";
case CPU_INFO_FAMILY: return "Motorola 68K";
case CPU_INFO_VERSION: return "v0.0088";
case CPU_INFO_FILE: return __FILE__;
case CPU_INFO_CREDITS: return "Copyright Copyright 2004-2007 Dave, Reesy and Notaz. All rights reserved";
}
return "";
}

unsigned cyclone_dasm(char *buffer, unsigned pc)
{
change_pc24(pc);
sprintf(buffer, "$%04X", cpu_readop16(pc) );
return 2;
}
30 changes: 30 additions & 0 deletions src/cpu/m68000_cyclone/c68000.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef C68000_H
#define C68000_H

extern int cyclone_ICount;

#define cyclone_INT_NONE 0
#define cyclone_IRQ_1 1
#define cyclone_IRQ_2 2
#define cyclone_IRQ_3 3
#define cyclone_IRQ_4 4
#define cyclone_IRQ_5 5
#define cyclone_IRQ_6 6
#define cyclone_IRQ_7 7
#define cyclone_INT_ACK_AUTOVECTOR -1
#define cyclone_STOP 0x10

extern void cyclone_init(void);
extern void cyclone_reset(void *param);
extern void cyclone_exit(void);
extern int cyclone_execute(int cycles);
extern unsigned cyclone_get_context(void *dst);
extern void cyclone_set_context(void *src);
extern unsigned cyclone_get_reg(int regnum);
extern void cyclone_set_reg(int regnum, unsigned val);
extern void cyclone_set_irq_line(int irqline, int state);
extern void cyclone_set_irq_callback(int (*callback)(int irqline));
extern const char *cyclone_info(void *context, int regnum);
extern unsigned cyclone_dasm(char *buffer, unsigned pc);

#endif
Loading

0 comments on commit 225812f

Please sign in to comment.