mirror of
https://github.com/libretro/Mu.git
synced 2026-09-22 22:56:12 +00:00
No more cyclone
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
0x9bdfeacc 0f 10 08 e2 and r1, r8, #15
|
||||
0x9bdfead0 <+0x0004> 01 11 d7 e7 ldrb r1, [r7, r1, lsl #2]
|
||||
0x9bdfead4 <+0x0008> 01 2c b0 e1 lsls r2, r1, #24
|
||||
0x9bdfead8 <+0x000c> 02 a1 02 e2 and r10, r2, #-2147483648 ; 0x80000000
|
||||
0x9bdfeadc <+0x0010> 01 a1 8a 03 orreq r10, r10, #1073741824 ; 0x40000000
|
||||
0x9bdfeae0 <+0x0014> 1e 2c 08 e2 and r2, r8, #7680 ; 0x1e00
|
||||
0x9bdfeae4 <+0x0018> a2 03 97 e7 ldr r0, [r7, r2, lsr #7]
|
||||
0x9bdfeae8 <+0x001c> 01 30 80 e2 add r3, r0, #1
|
||||
0x9bdfeaec <+0x0020> a2 33 87 e7 str r3, [r7, r2, lsr #7]
|
||||
0x9bdfeaf0 <+0x0024> 0f e0 a0 e1 mov lr, pc
|
||||
0x9bdfeaf4 <+0x0028> 74 f0 97 e5 ldr pc, [r7, #116] ; 0x74
|
||||
0x9bdfeaf8 <+0x002c> b2 80 d4 e0 ldrh r8, [r4], #2
|
||||
0x9bdfeafc <+0x0030> 08 50 55 e2 subs r5, r5, #8
|
||||
0x9bdfeb00 <+0x0034> 08 f1 96 c7 ldrgt pc, [r6, r8, lsl #2]
|
||||
0x9bdfeb04 <+0x0038> a3 fb ff ea b 0x9bdfd998 <CycloneEnd>
|
||||
|
||||
Crashed with SIGSEGV
|
||||
When compiled in release mode crashes with SIGILL
|
||||
@@ -1,5 +1,3 @@
|
||||
cyclone68k is crasing again when you turn the Palm off then turn it back on
|
||||
|
||||
Fixed:
|
||||
Endian compatibility is broken(the CPU state needs to be standardized)(fixed again with musashi and the other 68k core isn't used right now)
|
||||
Endian compatibility is broken(the CPU state needs to be standardized)
|
||||
RetroArch port crashes on exit(needed to check if environ_cb returned true, switched to libretro-common filestreams too)
|
||||
|
||||
@@ -57,13 +57,11 @@ edge triggered INT* don't clear on write to ISR when masked in IMR(I needed to u
|
||||
PDKBEN also has a hack for power on(its been removed)
|
||||
On hardware PDIRQEG seems not to actually work at all(CPUID:0x57000000)(it does)
|
||||
may need to trigger an interrupt if a IMR masked interrupt becomes unmasked and its bit is still set in IPR(already doing that)
|
||||
Cyclone will cause SIGSEGVs, don't know why yet(seems to have been caused by compressed jumptable)
|
||||
power button must be pushed twice to turn the CPU back on(when debugging it works the first time, then must be pushed twice to turn off instead of on)(this also occurs in the RetroArch build)
|
||||
the power button double press issue may be because the button map I am using was taken from POSE source, the power button may be mapped to other locations on the button matrix than expected
|
||||
if a sound interrupt is triggered while the button interrupt is disabled the button interrupt will still trigger(in galax game)(seems to be an issue with FIFOAV always = true hack and how INT_PWM1 needed to be cleared on read or write)
|
||||
SED1376 16 bpp mode is broken and crushed to the top of the screen
|
||||
audio can max out the resampler buffer, the max 1 FIFO sample can play is around 2.16 minutes(CLK32 / period(257) / clockDivider(16) / prescaler(128) / repeat(8))(257 * 16 * 128 * 8 / 32768=128.5 seconds)(safety check added, >= 1 second duty cycle is useless and will just make annoying cracks anyway)
|
||||
Cyclone CPU emulator is not working
|
||||
PWM1 output value is not a direct range cast of 0<->255 to 0<->32767, its additive, see properPwmSineWave.png
|
||||
inductor dosent properly drain when PWM1 gets disabled
|
||||
PWM1 FIFOAV is always set true
|
||||
|
||||
@@ -28,16 +28,6 @@ else ifeq ($(platform), osx)
|
||||
endif
|
||||
endif
|
||||
|
||||
# ifneq (,$(filter qnx vita ctr rpi2 classic_armv7_a7,$(platform)))
|
||||
# EMU_OPTIMIZE_FOR_ARM32 = 1
|
||||
# else ifneq (,$(findstring armv7,$(platform)))
|
||||
# EMU_OPTIMIZE_FOR_ARM32 = 1
|
||||
# else ifneq (,$(findstring armv6,$(platform)))
|
||||
# EMU_OPTIMIZE_FOR_ARM32 = 1
|
||||
# else ifneq (,$(findstring armhf,$(platform)))
|
||||
# EMU_OPTIMIZE_FOR_ARM32 = 1
|
||||
# endif
|
||||
|
||||
include $(EMU_PATH)/makefile.all
|
||||
|
||||
COREDEFINES += $(EMU_DEFINES)
|
||||
@@ -46,6 +36,8 @@ SOURCES_C := $(CORE_DIR)/libretro.c \
|
||||
$(CORE_DIR)/cursors.c \
|
||||
$(EMU_SOURCES_C)
|
||||
|
||||
SOURCES_ASM :=
|
||||
|
||||
ifneq ($(STATIC_LINKING), 1)
|
||||
SOURCES_C += $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \
|
||||
@@ -56,5 +48,3 @@ ifneq ($(STATIC_LINKING), 1)
|
||||
$(LIBRETRO_COMM_DIR)/string/stdstring.c \
|
||||
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c
|
||||
endif
|
||||
|
||||
SOURCES_ASM := $(EMU_SOURCES_ASM)
|
||||
|
||||
@@ -4,16 +4,6 @@ CORE_DIR := $(LOCAL_PATH)/..
|
||||
|
||||
GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)"
|
||||
|
||||
# prevent persisting in non ARM builds after the first ARM build
|
||||
EMU_OPTIMIZE_FOR_ARM32 := 0
|
||||
|
||||
# set ASM CPU core, only use with ARMv4<->7, ARMv8 is its own architecture
|
||||
# ifeq ($(TARGET_ARCH), arm)
|
||||
# ifneq ($(TARGET_ARCH_ABI), arm64-v8a)
|
||||
# EMU_OPTIMIZE_FOR_ARM32 := 1
|
||||
# endif
|
||||
# endif
|
||||
|
||||
include $(CORE_DIR)/build/Makefile.common
|
||||
|
||||
COREFLAGS := -ffast-math -funroll-loops -D__LIBRETRO__ -DINLINE=inline -DFRONTEND_SUPPORTS_RGB565 $(INCFLAGS) $(COREDEFINES)
|
||||
|
||||
@@ -50,20 +50,17 @@ android{
|
||||
QMAKE_CXXFLAGS += -fopenmp
|
||||
QMAKE_LFLAGS += -fopenmp
|
||||
DEFINES += EMU_MULTITHREADED
|
||||
# CONFIG += optimize_for_arm32 # for now, later this will check if building for ARMv4<->7
|
||||
}
|
||||
|
||||
ios{
|
||||
# QMAKE_INFO_PLIST = ios/Info.plist
|
||||
DEFINES += EMU_MULTITHREADED
|
||||
# iOS is now ARMv8 only, cyclone wont work
|
||||
}
|
||||
|
||||
|
||||
CONFIG(debug, debug|release){
|
||||
# debug build, be accurate, fail hard, and add logging
|
||||
DEFINES += EMU_DEBUG EMU_CUSTOM_DEBUG_LOG_HANDLER
|
||||
!optimize_for_arm32:DEFINES += EMU_SANDBOX
|
||||
DEFINES += EMU_DEBUG EMU_CUSTOM_DEBUG_LOG_HANDLER EMU_SANDBOX
|
||||
macx|linux-g++{
|
||||
# DEFINES += EMU_SANDBOX_OPCODE_LEVEL_DEBUG
|
||||
# DEFINES += EMU_SANDBOX_LOG_APIS
|
||||
@@ -82,19 +79,6 @@ CONFIG += c++11
|
||||
|
||||
INCLUDEPATH += $$PWD/qt-common/include
|
||||
|
||||
# only use with ARMv4<->7, ARMv8 is its own architecture
|
||||
optimize_for_arm32{
|
||||
DEFINES += EMU_OPTIMIZE_FOR_ARM32
|
||||
SOURCES += ../../src/m68k/cyclone/CycloneNew.S
|
||||
}else{
|
||||
SOURCES += ../../src/m68k/musashi/m68kcpu.c \
|
||||
../../src/m68k/musashi/m68kdasm.c \
|
||||
../../src/m68k/musashi/m68kopac.c \
|
||||
../../src/m68k/musashi/m68kopdm.c \
|
||||
../../src/m68k/musashi/m68kopnz.c \
|
||||
../../src/m68k/musashi/m68kops.c
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
debugviewer.cpp \
|
||||
emuwrapper.cpp \
|
||||
@@ -112,7 +96,13 @@ SOURCES += \
|
||||
../../src/pdiUsbD12.c \
|
||||
../../src/sdCard.c \
|
||||
../../src/sed1376.c \
|
||||
../../src/silkscreen.c
|
||||
../../src/silkscreen.c \
|
||||
../../src/m68k/m68kcpu.c \
|
||||
../../src/m68k/m68kdasm.c \
|
||||
../../src/m68k/m68kopac.c \
|
||||
../../src/m68k/m68kopdm.c \
|
||||
../../src/m68k/m68kopnz.c \
|
||||
../../src/m68k/m68kops.c
|
||||
|
||||
HEADERS += \
|
||||
debugviewer.h \
|
||||
@@ -124,11 +114,10 @@ HEADERS += \
|
||||
../../src/debug/sandbox.h \
|
||||
../../src/debug/sandboxTrapNumToName.c.h \
|
||||
../../src/debug/trapNames.h \
|
||||
../../src/m68k/cyclone/Cyclone.h \
|
||||
../../src/m68k/musashi/m68k.h \
|
||||
../../src/m68k/musashi/m68kconf.h \
|
||||
../../src/m68k/musashi/m68kcpu.h \
|
||||
../../src/m68k/musashi/m68kops.h \
|
||||
../../src/m68k/m68k.h \
|
||||
../../src/m68k/m68kconf.h \
|
||||
../../src/m68k/m68kcpu.h \
|
||||
../../src/m68k/m68kops.h \
|
||||
../../src/specs/dragonballVzRegisterSpec.h \
|
||||
../../src/ads7846.h \
|
||||
../../src/emulator.h \
|
||||
|
||||
@@ -48,7 +48,6 @@ The lack of ARM CPU will be fixed in my emulator see "OS improvements".
|
||||
|
||||
## Credits
|
||||
Musashi v3.4 (last version that builds outside of MAME)(68k Core)
|
||||
Cyclone 68000 (68k Core)
|
||||
blip_buf 1.1.0 (Audio Resampler)
|
||||
http://www.iconarchive.com/show/crystal-clear-icons-by-everaldo/App-palm-icon.html (Desktop Icon)
|
||||
http://tango.freedesktop.org/Tango_Icon_Library (Palm Action Buttons, All UI buttons)
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../m68k/musashi/m68k.h"
|
||||
#include "../m68k/musashi/m68kcpu.h"
|
||||
#include "../m68k/m68k.h"
|
||||
#include "../m68k/m68kcpu.h"
|
||||
#include "../emulator.h"
|
||||
#include "../ads7846.h"
|
||||
#include "../hardwareRegisters.h"
|
||||
|
||||
@@ -17,7 +17,6 @@ extern "C" {
|
||||
|
||||
//DEFINE INFO!!!
|
||||
//define EMU_MULTITHREADED to speed up long loops
|
||||
//define EMU_OPTIMIZE_FOR_ARM32 to use ASM CPU core
|
||||
//define EMU_NO_SAFETY to remove all safety checks
|
||||
//define EMU_BIG_ENDIAN on big endian systems
|
||||
//to enable degguging define EMU_DEBUG, all options below do nothing unless EMU_DEBUG is defined
|
||||
|
||||
148
src/flx68000.c
148
src/flx68000.c
@@ -5,26 +5,11 @@
|
||||
#include "portability.h"
|
||||
#include "hardwareRegisters.h"
|
||||
#include "memoryAccess.h"
|
||||
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
#include <stdlib.h>//for exit(1)
|
||||
#include "m68k/cyclone/Cyclone.h"
|
||||
#else
|
||||
#include "m68k/musashi/m68kcpu.h"
|
||||
#endif
|
||||
#include "m68k/m68kcpu.h"
|
||||
|
||||
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
static struct Cyclone cycloneCpu;
|
||||
|
||||
|
||||
extern unsigned int m68k_read_memory_8(unsigned int address);
|
||||
extern unsigned int m68k_read_memory_16(unsigned int address);
|
||||
extern unsigned int m68k_read_memory_32(unsigned int address);
|
||||
extern void m68k_write_memory_8(unsigned int address, unsigned char value);
|
||||
extern void m68k_write_memory_16(unsigned int address, unsigned short value);
|
||||
extern void m68k_write_memory_32(unsigned int address, unsigned int value);
|
||||
|
||||
/*
|
||||
//saving this little snippet to optimize musashi
|
||||
unsigned int checkPc(unsigned int pc){
|
||||
unsigned int dataBufferHost;
|
||||
unsigned int dataBufferGuest;
|
||||
@@ -51,27 +36,12 @@ unsigned int checkPc(unsigned int pc){
|
||||
|
||||
return cycloneCpu.membase + pc;//new program counter
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
void flx68000Init(void){
|
||||
static bool inited = false;
|
||||
|
||||
if(!inited){
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
CycloneInit();
|
||||
cycloneCpu.read8 = m68k_read_memory_8;
|
||||
cycloneCpu.read16 = m68k_read_memory_16;
|
||||
cycloneCpu.read32 = m68k_read_memory_32;
|
||||
cycloneCpu.fetch8 = m68k_read_memory_8;
|
||||
cycloneCpu.fetch16 = m68k_read_memory_16;
|
||||
cycloneCpu.fetch32 = m68k_read_memory_32;
|
||||
cycloneCpu.write8 = m68k_write_memory_8;
|
||||
cycloneCpu.write16 = m68k_write_memory_16;
|
||||
cycloneCpu.write32 = m68k_write_memory_32;
|
||||
cycloneCpu.checkpc = checkPc;
|
||||
cycloneCpu.IrqCallback = interruptAcknowledge;
|
||||
cycloneCpu.ResetCallback = emulatorSoftReset;
|
||||
#else
|
||||
m68k_init();
|
||||
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||
|
||||
@@ -79,7 +49,6 @@ void flx68000Init(void){
|
||||
|
||||
m68k_set_reset_instr_callback(emulatorSoftReset);
|
||||
m68k_set_int_ack_callback(interruptAcknowledge);
|
||||
#endif
|
||||
inited = true;
|
||||
}
|
||||
}
|
||||
@@ -87,31 +56,19 @@ void flx68000Init(void){
|
||||
void flx68000Reset(void){
|
||||
resetHwRegisters();
|
||||
resetAddressSpace();//address space must be reset after hardware registers because it is dependent on them
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
CycloneReset(&cycloneCpu);
|
||||
#else
|
||||
m68k_pulse_reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t flx68000StateSize(void){
|
||||
uint64_t size = 0;
|
||||
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
size += 0x80;//specified in Cyclone.h, line 82
|
||||
#else
|
||||
size += sizeof(uint32_t) * 50;//m68ki_cpu
|
||||
#endif
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void flx68000SaveState(uint8_t* data){
|
||||
uint64_t offset = 0;
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
CyclonePack(&cycloneCpu, data + offset);
|
||||
offset += 0x80;//specified in Cyclone.h, line 82
|
||||
#else
|
||||
uint8_t index;
|
||||
|
||||
for(index = 0; index < 16; index++){
|
||||
@@ -176,16 +133,10 @@ void flx68000SaveState(uint8_t* data){
|
||||
offset += sizeof(uint32_t);
|
||||
writeStateValue32(data + offset, m68ki_cpu.run_mode);
|
||||
offset += sizeof(uint32_t);
|
||||
#endif
|
||||
}
|
||||
|
||||
void flx68000LoadState(uint8_t* data){
|
||||
uint64_t offset = 0;
|
||||
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
CycloneUnpack(&cycloneCpu, data + offset);
|
||||
offset += 0x80;//specified in Cyclone.h, line 82
|
||||
#else
|
||||
uint8_t index;
|
||||
|
||||
for(index = 0; index < 16; index++){
|
||||
@@ -250,7 +201,6 @@ void flx68000LoadState(uint8_t* data){
|
||||
offset += sizeof(uint32_t);
|
||||
m68ki_cpu.run_mode = readStateValue32(data + offset);
|
||||
offset += sizeof(uint32_t);
|
||||
#endif
|
||||
}
|
||||
|
||||
void flx68000Execute(void){
|
||||
@@ -262,14 +212,8 @@ void flx68000Execute(void){
|
||||
double sysclks = dMin(cyclesRemaining, EMU_SYSCLK_PRECISION);
|
||||
int32_t cpuCycles = sysclks * pctlrCpuClockDivider * palmClockMultiplier;
|
||||
|
||||
if(cpuCycles > 0){
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
cycloneCpu.cycles = cpuCycles;
|
||||
CycloneRun(&cycloneCpu);
|
||||
#else
|
||||
if(cpuCycles > 0)
|
||||
m68k_execute(cpuCycles);
|
||||
#endif
|
||||
}
|
||||
addSysclks(sysclks);
|
||||
|
||||
cyclesRemaining -= sysclks;
|
||||
@@ -279,110 +223,31 @@ void flx68000Execute(void){
|
||||
}
|
||||
|
||||
void flx68000SetIrq(uint8_t irqLevel){
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
cycloneCpu.irq = irqLevel;
|
||||
CycloneFlushIrq(&cycloneCpu);
|
||||
#else
|
||||
m68k_set_irq(irqLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
void flx68000RefreshAddressing(void){
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
//cycloneCpu.pc = cycloneCpu.checkpc(cycloneCpu.pc);
|
||||
#else
|
||||
//C implementation doesnt cache address information
|
||||
#endif
|
||||
}
|
||||
|
||||
bool flx68000IsSupervisor(void){
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
return CycloneGetSr(&cycloneCpu) & 0x2000;
|
||||
#else
|
||||
return !!(m68k_get_reg(NULL, M68K_REG_SR) & 0x2000);
|
||||
#endif
|
||||
}
|
||||
|
||||
void flx68000BusError(uint32_t address, bool isWrite){
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
//no bus error callback
|
||||
#else
|
||||
#if !defined(EMU_NO_SAFETY)
|
||||
//never call outsize of a 68k opcode, behavior is undefined due to longjmp
|
||||
m68ki_trigger_bus_error(address, isWrite ? MODE_WRITE : MODE_READ, FLAG_S | m68ki_get_address_space());
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t flx68000GetRegister(uint8_t reg){
|
||||
//register standard, applys to all CPU cores
|
||||
/*
|
||||
M68K_REG_D0 = 0,
|
||||
M68K_REG_D1,
|
||||
M68K_REG_D2,
|
||||
M68K_REG_D3,
|
||||
M68K_REG_D4,
|
||||
M68K_REG_D5,
|
||||
M68K_REG_D6,
|
||||
M68K_REG_D7,
|
||||
M68K_REG_A0,
|
||||
M68K_REG_A1,
|
||||
M68K_REG_A2,
|
||||
M68K_REG_A3,
|
||||
M68K_REG_A4,
|
||||
M68K_REG_A5,
|
||||
M68K_REG_A6,
|
||||
M68K_REG_A7,
|
||||
M68K_REG_PC,
|
||||
M68K_REG_SR
|
||||
*/
|
||||
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
if(reg < 8)
|
||||
return cycloneCpu.d[reg];
|
||||
else if(reg < 16)
|
||||
return cycloneCpu.a[reg - 8];
|
||||
else if(reg == 16)
|
||||
return cycloneCpu.pc;
|
||||
else if(reg == 17)
|
||||
return CycloneGetSr(&cycloneCpu);
|
||||
|
||||
return 0x00000000;
|
||||
#else
|
||||
return m68k_get_reg(NULL, reg);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t flx68000GetPc(void){
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
return cycloneCpu.prev_pc;
|
||||
#else
|
||||
return m68k_get_reg(NULL, M68K_REG_PPC);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t flx68000ReadArbitraryMemory(uint32_t address, uint8_t size){
|
||||
uint64_t data = UINT64_MAX;//invalid access
|
||||
|
||||
#if defined(EMU_OPTIMIZE_FOR_ARM32)
|
||||
//reading from a hardware register FIFO will corrupt it!
|
||||
if(bankType[START_BANK(address)] != CHIP_NONE){
|
||||
uint16_t m68kSr = CycloneGetSr(&cycloneCpu);
|
||||
CycloneSetSr(&cycloneCpu, m68kSr | 0x2000);//prevent privilege violations
|
||||
switch(size){
|
||||
case 8:
|
||||
data = m68k_read_memory_8(address);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
data = m68k_read_memory_16(address);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
data = m68k_read_memory_32(address);
|
||||
break;
|
||||
}
|
||||
CycloneSetSr(&cycloneCpu, m68kSr);
|
||||
}
|
||||
#else
|
||||
//reading from a hardware register FIFO will corrupt it!
|
||||
if(bankType[START_BANK(address)] != CHIP_NONE){
|
||||
uint16_t m68kSr = m68k_get_reg(NULL, M68K_REG_SR);
|
||||
@@ -402,7 +267,6 @@ uint64_t flx68000ReadArbitraryMemory(uint32_t address, uint8_t size){
|
||||
}
|
||||
m68k_set_reg(M68K_REG_SR, m68kSr);
|
||||
}
|
||||
#endif
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
|
||||
// Cyclone 68000 Emulator - Header File
|
||||
|
||||
// Copyright (c) 2004,2011 FinalDave (emudave (at) gmail.com)
|
||||
// Copyright (c) 2005-2011 Gražvydas "notaz" Ignotas (notasas (at) gmail.com)
|
||||
|
||||
// This code is licensed under the GNU General Public License version 2.0 and the MAME License.
|
||||
// You can choose the license that has the most advantages for you.
|
||||
|
||||
// SVN repository can be found at http://code.google.com/p/cyclone68000/
|
||||
|
||||
|
||||
#ifndef __CYCLONE_H__
|
||||
#define __CYCLONE_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int CycloneVer; // Version number of library
|
||||
|
||||
extern long CycloneJumpTab[65536]; // default jump table
|
||||
|
||||
struct Cyclone
|
||||
{
|
||||
unsigned int d[8]; // [r7,#0x00]
|
||||
unsigned int a[8]; // [r7,#0x20]
|
||||
unsigned int pc; // [r7,#0x40] Memory Base (.membase) + 68k PC
|
||||
unsigned char srh; // [r7,#0x44] Status Register high (T_S__III)
|
||||
unsigned char not_pol;// [r7,#0x45] not polling
|
||||
unsigned char flags; // [r7,#0x46] Flags (ARM order: ____NZCV) [68k order is XNZVC]
|
||||
unsigned char irq; // [r7,#0x47] IRQ level
|
||||
unsigned int osp; // [r7,#0x48] Other Stack Pointer (USP/SSP)
|
||||
unsigned int xc; // [r7,#0x4c] Extend flag (bit29: ??X? _)
|
||||
unsigned int prev_pc; // [r7,#0x50] Set to start address of currently executed opcode + 2 (if enabled in config.h)
|
||||
unsigned int jumptab; // [r7,#0x54] Jump table pointer
|
||||
int state_flags; // [r7,#0x58] bit: 0: stopped state, 1: trace state, 2: activity bit, 3: addr error, 4: fatal halt
|
||||
int cycles; // [r7,#0x5c] Number of cycles to execute - 1. Updates to cycles left after CycloneRun()
|
||||
int membase; // [r7,#0x60] Memory Base (ARM address minus 68000 address)
|
||||
unsigned int (*checkpc)(unsigned int pc); // [r7,#0x64] called to recalc Memory Base+pc
|
||||
unsigned int (*read8 )(unsigned int a); // [r7,#0x68]
|
||||
unsigned int (*read16 )(unsigned int a); // [r7,#0x6c]
|
||||
unsigned int (*read32 )(unsigned int a); // [r7,#0x70]
|
||||
void (*write8 )(unsigned int a,unsigned char d); // [r7,#0x74]
|
||||
void (*write16)(unsigned int a,unsigned short d); // [r7,#0x78]
|
||||
void (*write32)(unsigned int a,unsigned int d); // [r7,#0x7c]
|
||||
unsigned int (*fetch8 )(unsigned int a); // [r7,#0x80]
|
||||
unsigned int (*fetch16)(unsigned int a); // [r7,#0x84]
|
||||
unsigned int (*fetch32)(unsigned int a); // [r7,#0x88]
|
||||
int (*IrqCallback)(int int_level); // [r7,#0x8c] optional irq callback function, see config.h
|
||||
void (*ResetCallback)(void); // [r7,#0x90] if enabled in config.h, calls this whenever RESET opcode is encountered.
|
||||
int (*UnrecognizedCallback)(void); // [r7,#0x94] if enabled in config.h, calls this whenever unrecognized opcode is encountered.
|
||||
void *internal_CycloneEnd; // [r7,#0x98] internal, do not modify
|
||||
int internal_s_cycles; // [r7,#0x9c] internal, do not modify
|
||||
void *internal_s_CycloneEnd; // [r7,#0xa0] internal, do not modify
|
||||
unsigned int internal[3]; // [r7,#0xa4] reserved for internal use, do not change.
|
||||
};
|
||||
|
||||
// Initialize. Used only if Cyclone was compiled with compressed jumptable, see config.h
|
||||
#define CycloneInit() \
|
||||
CycloneInitJT(CycloneJumpTab)
|
||||
void CycloneInitJT(void *jt);
|
||||
|
||||
// Reset
|
||||
#define CycloneReset(pcy) \
|
||||
CycloneResetJT(pcy, CycloneJumpTab)
|
||||
void CycloneResetJT(struct Cyclone *pcy, void *jt);
|
||||
|
||||
// Run cyclone. Cycles should be specified in context (pcy->cycles)
|
||||
void CycloneRun(struct Cyclone *pcy);
|
||||
|
||||
// Utility functions to get and set SR
|
||||
void CycloneSetSr(struct Cyclone *pcy, unsigned int sr);
|
||||
unsigned int CycloneGetSr(const struct Cyclone *pcy);
|
||||
|
||||
// Generates irq exception if needed (if pcy->irq > mask).
|
||||
// Returns cycles used for exception if it was generated, 0 otherwise.
|
||||
int CycloneFlushIrq(struct Cyclone *pcy);
|
||||
|
||||
// Functions for saving and restoring state.
|
||||
// CycloneUnpack() uses checkpc(), so it must be initialized.
|
||||
// save_buffer must point to buffer of 128 (0x80) bytes of size.
|
||||
void CyclonePack(const struct Cyclone *pcy, void *save_buffer);
|
||||
void CycloneUnpack(struct Cyclone *pcy, const void *save_buffer);
|
||||
|
||||
// genesis: if 1, switch to normal TAS handlers
|
||||
#define CycloneSetRealTAS(use_real) \
|
||||
CycloneSetRealTAS_JT(use_real, CycloneJumpTab)
|
||||
void CycloneSetRealTAS_JT(int use_real, void *jt);
|
||||
|
||||
|
||||
// These values are special return values for IrqCallback.
|
||||
|
||||
// Causes an interrupt autovector (0x18 + interrupt level) to be taken.
|
||||
// This happens in a real 68K if VPA or AVEC is asserted during an interrupt
|
||||
// acknowledge cycle instead of DTACK (the most common situation).
|
||||
#define CYCLONE_INT_ACK_AUTOVECTOR -1
|
||||
|
||||
// Causes the spurious interrupt vector (0x18) to be taken
|
||||
// This happens in a real 68K if BERR is asserted during the interrupt
|
||||
// acknowledge cycle (i.e. no devices responded to the acknowledge).
|
||||
#define CYCLONE_INT_ACK_SPURIOUS -2
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // End of extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __CYCLONE_H__
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,192 +0,0 @@
|
||||
|
||||
|
||||
/**
|
||||
* Cyclone 68000 configuration file
|
||||
**/
|
||||
|
||||
|
||||
/*
|
||||
* By default, only ARMv4 instructions are used.
|
||||
* If you want Cyclone to make use of newer ARM instructions, enable the
|
||||
* options(s) below. You can also override this using make argument:
|
||||
* make HAVE_ARMv6=1
|
||||
*/
|
||||
#ifndef HAVE_ARMv6
|
||||
#define HAVE_ARMv6 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If this option is enabled, Microsoft ARMASM compatible output is generated
|
||||
* (output file - Cyclone.asm). Otherwise GNU as syntax is used (Cyclone.s).
|
||||
*/
|
||||
#define USE_MS_SYNTAX 0
|
||||
|
||||
/*
|
||||
* Enable this option if you are going to use Cyclone to emulate Genesis /
|
||||
* Mega Drive system. As VDP chip in these systems had control of the bus,
|
||||
* several instructions were acting differently, for example TAS did'n have
|
||||
* the write-back phase. That will be emulated, if this option is enabled.
|
||||
*/
|
||||
#define CYCLONE_FOR_GENESIS 0
|
||||
|
||||
/*
|
||||
* This option compresses Cyclone's jumptable. Because of this the executable
|
||||
* will be smaller and load slightly faster and less relocations will be needed.
|
||||
* This also fixes the crash problem with 0xfffe and 0xffff opcodes.
|
||||
* Warning: if you enable this, you MUST call CycloneInit() before calling
|
||||
* CycloneRun(), or else it will crash, also seems to cause SIGSEGVs when enabled.
|
||||
*/
|
||||
#define COMPRESS_JUMPTABLE 0
|
||||
|
||||
/*
|
||||
* Address mask for memory hadlers. The bits set will be masked out of address
|
||||
* parameter, which is passed to r/w memory handlers.
|
||||
* Using 0xff000000 means that only 24 least significant bits should be used.
|
||||
* Set to 0 if you want to mask unused address bits in the memory handlers yourself.
|
||||
*/
|
||||
#define MEMHANDLERS_ADDR_MASK 0
|
||||
|
||||
/*
|
||||
* Cyclone keeps the 4 least significant bits of SR, PC+membase and it's cycle
|
||||
* counter in ARM registers instead of the context for performance reasons. If you for
|
||||
* any reason need to access them in your memory handlers, enable the options below,
|
||||
* otherwise disable them to improve performance.
|
||||
*
|
||||
* MEMHANDLERS_NEED_PC updates .pc context field with PC value effective at the time
|
||||
* when memhandler was called (opcode address + 2-10 bytes).
|
||||
* MEMHANDLERS_NEED_PREV_PC updates .prev_pc context field to currently executed
|
||||
* opcode address + 2.
|
||||
* Note that .pc and .prev_pc values are always real pointers to memory, so you must
|
||||
* subtract .membase to get M68k PC value.
|
||||
*
|
||||
* Warning: updating PC in memhandlers is dangerous, as Cyclone may internally
|
||||
* increment the PC before fetching the next instruction and continue executing
|
||||
* at wrong location. It's better to wait until Cyclone CycloneRun() finishes.
|
||||
*
|
||||
* Warning: if you enable MEMHANDLERS_CHANGE_CYCLES, you must also enable
|
||||
* MEMHANDLERS_NEED_CYCLES, or else Cyclone will keep reloading the same cycle
|
||||
* count and this will screw timing (if not cause a deadlock).
|
||||
*/
|
||||
#define MEMHANDLERS_NEED_PC 0
|
||||
#define MEMHANDLERS_NEED_PREV_PC 0
|
||||
#define MEMHANDLERS_NEED_FLAGS 0
|
||||
#define MEMHANDLERS_NEED_CYCLES 0
|
||||
#define MEMHANDLERS_CHANGE_PC 0
|
||||
#define MEMHANDLERS_CHANGE_FLAGS 0
|
||||
#define MEMHANDLERS_CHANGE_CYCLES 0
|
||||
|
||||
/*
|
||||
* If the following macro is defined, Cyclone no longer calls read*, write*,
|
||||
* fetch* and checkpc from it's context, it calls these functions directly
|
||||
* instead, prefixed with prefix selected below. For example, if
|
||||
* MEMHANDLERS_DIRECT_PREFIX is set to cyclone_, it will call cyclone_read8
|
||||
* on byte reads.
|
||||
* This is to avoid indirect jumps, which are slower. It also saves one ARM
|
||||
* instruction.
|
||||
*/
|
||||
/* MEMHANDLERS_DIRECT_PREFIX "cyclone_" */
|
||||
|
||||
/*
|
||||
* If enabled, Cyclone will call .IrqCallback routine from it's context whenever it
|
||||
* acknowledges an IRQ. IRQ level (.irq) is not cleared automatically, do this in your
|
||||
* handler if needed.
|
||||
* This function must either return vector number to use for interrupt exception,
|
||||
* CYCLONE_INT_ACK_AUTOVECTOR to use autovector (this is the most common case), or
|
||||
* CYCLONE_INT_ACK_SPURIOUS (least common case).
|
||||
* If disabled, it simply uses appropriate autovector, clears the IRQ level and
|
||||
* continues execution.
|
||||
*/
|
||||
#define USE_INT_ACK_CALLBACK 1
|
||||
|
||||
/*
|
||||
* Enable this if you need old PC, flags or cycles;
|
||||
* or you change cycles in your IrqCallback function.
|
||||
*/
|
||||
#define INT_ACK_NEEDS_STUFF 0
|
||||
#define INT_ACK_CHANGES_CYCLES 0
|
||||
|
||||
/*
|
||||
* If enabled, .ResetCallback is called from the context, whenever RESET opcode is
|
||||
* encountered. All context members are valid and can be changed.
|
||||
* If disabled, RESET opcode acts as an NOP.
|
||||
*/
|
||||
#define USE_RESET_CALLBACK 1
|
||||
|
||||
/*
|
||||
* If enabled, UnrecognizedCallback is called if an invalid opcode is
|
||||
* encountered. All context members are valid and can be changed. The handler
|
||||
* should return zero if you want Cyclone to gererate "Illegal Instruction"
|
||||
* exception after this, or nonzero if not. In the later case you should change
|
||||
* the PC by yourself, or else Cyclone will keep executing that opcode all over
|
||||
* again.
|
||||
* If disabled, "Illegal Instruction" exception is generated and execution is
|
||||
* continued.
|
||||
*/
|
||||
#define USE_UNRECOGNIZED_CALLBACK 0
|
||||
|
||||
/*
|
||||
* This option will also call UnrecognizedCallback for a-line and f-line
|
||||
* (0xa*** and 0xf***) opcodes the same way as described above, only appropriate
|
||||
* exceptions will be generated.
|
||||
*/
|
||||
#define USE_AFLINE_CALLBACK 0
|
||||
|
||||
/*
|
||||
* This makes Cyclone to call checkpc from it's context whenever it changes the PC
|
||||
* by a large value. It takes and should return the PC value in PC+membase form.
|
||||
* The flags and cycle counter are not valid in this function.
|
||||
*/
|
||||
#define USE_CHECKPC_CALLBACK 1
|
||||
|
||||
/*
|
||||
* This determines if checkpc() should be called after jumps when 8 and 16 bit
|
||||
* displacement values were used.
|
||||
*/
|
||||
#define USE_CHECKPC_OFFSETBITS_16 1
|
||||
#define USE_CHECKPC_OFFSETBITS_8 0
|
||||
|
||||
/*
|
||||
* Call checkpc() after DBcc jumps (which use 16bit displacement). Cyclone prior to
|
||||
* 0.0087 never did that.
|
||||
*/
|
||||
#define USE_CHECKPC_DBRA 1
|
||||
|
||||
/*
|
||||
* When this option is enabled Cyclone will do two word writes instead of one
|
||||
* long write when handling MOVE.L or MOVEM.L with pre-decrementing destination,
|
||||
* as described in Bart Trzynadlowski's doc (http://www.trzy.org/files/68knotes.txt).
|
||||
* Enable this if you are emulating a 16 bit system.
|
||||
*/
|
||||
#define SPLIT_MOVEL_PD 1
|
||||
|
||||
/*
|
||||
* Enable emulation of trace mode. Shouldn't cause any performance decrease, so it
|
||||
* should be safe to keep this ON.
|
||||
*/
|
||||
#define EMULATE_TRACE 1
|
||||
|
||||
/*
|
||||
* If enabled, address error exception will be generated if 68k code jumps to an
|
||||
* odd address. Causes very small performance hit (2 ARM instructions for every
|
||||
* emulated jump/return/exception in normal case).
|
||||
* Note: checkpc() must not clear least significant bit of rebased address
|
||||
* for this to work, as checks are performed after calling checkpc().
|
||||
*/
|
||||
#define EMULATE_ADDRESS_ERRORS_JUMP 1
|
||||
|
||||
/*
|
||||
* If enabled, address error exception will be generated if 68k code tries to
|
||||
* access a word or longword at an odd address. The performance cost is also 2 ARM
|
||||
* instructions per access (for address error checks).
|
||||
*/
|
||||
#define EMULATE_ADDRESS_ERRORS_IO 0
|
||||
|
||||
/*
|
||||
* If an address error happens during another address error processing,
|
||||
* the processor halts until it is reset (catastrophic system failure, as the manual
|
||||
* states). This option enables halt emulation.
|
||||
* Note that this might be not desired if it is known that emulated system should
|
||||
* never reach this state.
|
||||
*/
|
||||
#define EMULATE_HALT 1
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
EMU_DEFINES :=
|
||||
EMU_SOURCES_ASM :=
|
||||
EMU_SOURCES_C := $(EMU_PATH)/emulator.c \
|
||||
$(EMU_PATH)/memoryAccess.c \
|
||||
$(EMU_PATH)/hardwareRegisters.c \
|
||||
@@ -10,21 +9,10 @@ EMU_SOURCES_C := $(EMU_PATH)/emulator.c \
|
||||
$(EMU_PATH)/silkscreen.c \
|
||||
$(EMU_PATH)/flx68000.c \
|
||||
$(EMU_PATH)/audio/blip_buf.c \
|
||||
$(EMU_PATH)/m68k/m68kops.c \
|
||||
$(EMU_PATH)/m68k/m68kopnz.c \
|
||||
$(EMU_PATH)/m68k/m68kopdm.c \
|
||||
$(EMU_PATH)/m68k/m68kopac.c \
|
||||
$(EMU_PATH)/m68k/m68kdasm.c \
|
||||
$(EMU_PATH)/m68k/m68kcpu.c \
|
||||
$(EMU_PATH)/debug/sandbox.c
|
||||
|
||||
#only use with ARMv4<->7, ARMv8 is its own architecture
|
||||
ifeq ($(EMU_OPTIMIZE_FOR_ARM32), 1)
|
||||
EMU_DEFINES += -DEMU_OPTIMIZE_FOR_ARM32
|
||||
ifeq ($(EMU_NEW_ASM_SYNTAX), 1)
|
||||
EMU_SOURCES_ASM += $(EMU_PATH)/m68k/cyclone/CycloneNew.S
|
||||
else
|
||||
EMU_SOURCES_ASM += $(EMU_PATH)/m68k/cyclone/CycloneOld.S
|
||||
endif
|
||||
else
|
||||
EMU_SOURCES_C += $(EMU_PATH)/m68k/musashi/m68kops.c \
|
||||
$(EMU_PATH)/m68k/musashi/m68kopnz.c \
|
||||
$(EMU_PATH)/m68k/musashi/m68kopdm.c \
|
||||
$(EMU_PATH)/m68k/musashi/m68kopac.c \
|
||||
$(EMU_PATH)/m68k/musashi/m68kdasm.c \
|
||||
$(EMU_PATH)/m68k/musashi/m68kcpu.c
|
||||
endif
|
||||
|
||||
@@ -355,7 +355,7 @@ void m68k_write_memory_32(unsigned int address, unsigned int value){
|
||||
return;
|
||||
}
|
||||
|
||||
//memory access for the disassembler
|
||||
//memory access for the disassembler, unused but must be defined
|
||||
uint8_t m68k_read_disassembler_8(uint32_t address){return m68k_read_memory_8(address);}
|
||||
uint16_t m68k_read_disassembler_16(uint32_t address){return m68k_read_memory_16(address);}
|
||||
uint32_t m68k_read_disassembler_32(uint32_t address){return m68k_read_memory_32(address);}
|
||||
@@ -406,5 +406,4 @@ void resetAddressSpace(void){
|
||||
|
||||
MULTITHREAD_LOOP(bank) for(bank = 0; bank < TOTAL_MEMORY_BANKS; bank++)
|
||||
bankType[bank] = getProperBankType(bank);
|
||||
flx68000RefreshAddressing();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user