1 Commits

Author SHA1 Message Date
meepingsnesroms
3e0fdfa53d Just a failed experiment 2018-12-29 11:13:06 -08:00
11 changed files with 45528 additions and 30 deletions

View File

@@ -27,6 +27,7 @@ UART1 USTCNT1
PLLFSR has a hack that makes busy wait loops finish faster by toggling the CLK32 bit on read, for power button issue
should also not transfer data to SD card when MOSI, MISO or SPICLK1 are disabled
port d data register INT* bits seem to have there data bits cleared when an edge triggered interrupt is cleared(according to MC68VZ328UM.pdf Page 10-15)
Cyclone will cause SIGSEGVs, don't know why yet(seems to have been caused by compressed jumptable)
Memory:
SD card can't be read or written to by Palm OS
@@ -57,13 +58,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

View File

@@ -7,6 +7,7 @@ INCFLAGS := -I$(LIBRETRO_COMM_DIR)/include
ifeq ($(DEBUG), 1)
COREDEFINES += -DEMU_DEBUG -DEMU_SANDBOX
else
EMU_FAST_CPU = 1
COREDEFINES += -DEMU_NO_SAFETY
endif

View File

@@ -50,7 +50,6 @@ 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{
@@ -63,7 +62,8 @@ ios{
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
# EMU_SANDBOX
CONFIG += emu_fast_cpu
macx|linux-g++{
# DEFINES += EMU_SANDBOX_OPCODE_LEVEL_DEBUG
# DEFINES += EMU_SANDBOX_LOG_APIS
@@ -75,6 +75,7 @@ CONFIG(debug, debug|release){
}
}else{
# release build, go fast
CONFIG += emu_fast_cpu
DEFINES += EMU_NO_SAFETY
}
@@ -82,10 +83,15 @@ 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
emu_fast_cpu{
DEFINES += EMU_FAST_CPU
optimize_for_arm32{
# only use with ARMv4<->7, ARMv8 is its own architecture
DEFINES += EMU_OPTIMIZE_FOR_ARM32
SOURCES += ../../src/m68k/cyclone/CycloneNew.S
}else{
SOURCES += ../../src/m68k/fame/famec.c
}
}else{
SOURCES += ../../src/m68k/musashi/m68kcpu.c \
../../src/m68k/musashi/m68kdasm.c \
@@ -147,7 +153,9 @@ HEADERS += \
../../src/specs/sed1376RegisterSpec.h \
../../src/specs/pdiUsbD12CommandSpec.h \
../../src/specs/emuFeatureRegisterSpec.h \
../../src/specs/sdCardCommandSpec.h
../../src/specs/sdCardCommandSpec.h \
../../src/m68k/fame/fame.h \
../../src/m68k/fame/famec_opcodes.h
FORMS += \
mainwindow.ui \

View File

@@ -17,7 +17,8 @@ extern "C" {
//DEFINE INFO!!!
//define EMU_MULTITHREADED to speed up long loops
//define EMU_OPTIMIZE_FOR_ARM32 to use ASM CPU core
//define EMU_FAST_CPU to use fast CPU cores
//define EMU_OPTIMIZE_FOR_ARM32 to use ASM CPU core, EMU_FAST_CPU must be on too
//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

View File

@@ -1,19 +1,24 @@
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "emulator.h"
#include "portability.h"
#include "hardwareRegisters.h"
#include "memoryAccess.h"
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
#include <stdlib.h>//for exit(1)
#include "m68k/cyclone/Cyclone.h"
#else
#include "m68k/fame/fame.h"
#endif
#else
#include "m68k/musashi/m68kcpu.h"
#endif
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
static struct Cyclone cycloneCpu;
@@ -25,7 +30,7 @@ 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);
unsigned int checkPc(unsigned int pc){
unsigned int flx68000CheckPc(unsigned int pc){
unsigned int dataBufferHost;
unsigned int dataBufferGuest;
unsigned int windowSize;
@@ -51,12 +56,31 @@ unsigned int checkPc(unsigned int pc){
return cycloneCpu.membase + pc;//new program counter
}
#else
static M68K_CONTEXT fameCpu;
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);
void flx68000InterruptAcknowledge(unsigned level){
int vector = interruptAcknowledge(level);
fameCpu.interrupts[0] = level;
}
#endif
#endif
void flx68000Init(void){
static bool inited = false;
if(!inited){
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
CycloneInit();
cycloneCpu.read8 = m68k_read_memory_8;
@@ -68,9 +92,20 @@ void flx68000Init(void){
cycloneCpu.write8 = m68k_write_memory_8;
cycloneCpu.write16 = m68k_write_memory_16;
cycloneCpu.write32 = m68k_write_memory_32;
cycloneCpu.checkpc = checkPc;
cycloneCpu.checkpc = flx68000CheckPc;
cycloneCpu.IrqCallback = interruptAcknowledge;
cycloneCpu.ResetCallback = emulatorSoftReset;
#else
fm68k_init();
fameCpu.read_byte = m68k_read_memory_8;
fameCpu.read_word = m68k_read_memory_16;
fameCpu.read_long = m68k_read_memory_32;
fameCpu.write_byte = m68k_write_memory_8;
fameCpu.write_word = m68k_write_memory_16;
fameCpu.write_long = m68k_write_memory_32;
fameCpu.iack_handler = flx68000InterruptAcknowledge;
fameCpu.reset_handler = emulatorSoftReset;
#endif
#else
m68k_init();
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
@@ -87,8 +122,12 @@ 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_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
CycloneReset(&cycloneCpu);
#else
fm68k_reset(&fameCpu);
#endif
#else
m68k_pulse_reset();
#endif
@@ -97,8 +136,12 @@ void flx68000Reset(void){
uint64_t flx68000StateSize(void){
uint64_t size = 0;
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
size += 0x80;//specified in Cyclone.h, line 82
#else
size += sizeof(fameCpu);
#endif
#else
size += sizeof(uint32_t) * 50;//m68ki_cpu
#endif
@@ -108,9 +151,14 @@ uint64_t flx68000StateSize(void){
void flx68000SaveState(uint8_t* data){
uint64_t offset = 0;
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
CyclonePack(&cycloneCpu, data + offset);
offset += 0x80;//specified in Cyclone.h, line 82
#else
memcpy(data + offset, &fameCpu, sizeof(fameCpu));
offset += sizeof(fameCpu);
#endif
#else
uint8_t index;
@@ -182,9 +230,14 @@ void flx68000SaveState(uint8_t* data){
void flx68000LoadState(uint8_t* data){
uint64_t offset = 0;
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
CycloneUnpack(&cycloneCpu, data + offset);
offset += 0x80;//specified in Cyclone.h, line 82
#else
memcpy(&fameCpu, data + offset, sizeof(fameCpu));
offset += sizeof(fameCpu);
#endif
#else
uint8_t index;
@@ -263,9 +316,13 @@ void flx68000Execute(void){
int32_t cpuCycles = sysclks * pctlrCpuClockDivider * palmClockMultiplier;
if(cpuCycles > 0){
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
cycloneCpu.cycles = cpuCycles;
CycloneRun(&cycloneCpu);
#else
fm68k_emulate(&fameCpu, cpuCycles, fm68k_reason_emulate);
#endif
#else
m68k_execute(cpuCycles);
#endif
@@ -279,32 +336,46 @@ void flx68000Execute(void){
}
void flx68000SetIrq(uint8_t irqLevel){
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
cycloneCpu.irq = irqLevel;
CycloneFlushIrq(&cycloneCpu);
#else
//fameCpu.interrupts[0] = irqLevel;
//fm68k_would_interrupt(&fameCpu);
#endif
#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
#if defined(EMU_FAST_CPU) && !defined(EMU_OPTIMIZE_FOR_ARM32)
uint32_t bank;
MULTITHREAD_LOOP(bank) for(bank = 0; bank < TOTAL_MEMORY_BANKS; bank++){
if(bankType[bank] == CHIP_A0_ROM)
fameCpu.Fetch[bank] = &palmRom + BANK_ADDRESS(bank) - chips[CHIP_A0_ROM].start;
else if(bankType[bank] == CHIP_DX_RAM)
fameCpu.Fetch[bank] = &palmRam + BANK_ADDRESS(bank) - chips[CHIP_DX_RAM].start;
}
#endif
}
bool flx68000IsSupervisor(void){
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
return CycloneGetSr(&cycloneCpu) & 0x2000;
return !!(CycloneGetSr(&cycloneCpu) & 0x2000);
#else
return !!(fameCpu.sr & 0x2000);
#endif
#else
return !!(m68k_get_reg(NULL, M68K_REG_SR) & 0x2000);
#endif
}
void flx68000BusError(uint32_t address, bool isWrite){
#if defined(EMU_OPTIMIZE_FOR_ARM32)
#if defined(EMU_FAST_CPU) || defined(EMU_NO_SAFETY)
//no bus error callback
#else
//never call outsize of a 68k opcode, behavior is undefined due to longjmp
@@ -334,7 +405,7 @@ uint32_t flx68000GetRegister(uint8_t reg){
M68K_REG_PC,
M68K_REG_SR
*/
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
if(reg < 8)
return cycloneCpu.d[reg];
@@ -346,22 +417,38 @@ uint32_t flx68000GetRegister(uint8_t reg){
return CycloneGetSr(&cycloneCpu);
return 0x00000000;
#else
if(reg < 8)
return fameCpu.dreg[reg].D;
else if(reg < 16)
return fameCpu.areg[reg - 8].D;
else if(reg == 16)
return fm68k_get_pc(&fameCpu);
else if(reg == 17)
return fameCpu.sr;
return 0x00000000;
#endif
#else
return m68k_get_reg(NULL, reg);
#endif
}
uint32_t flx68000GetPc(void){
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
return cycloneCpu.prev_pc;
return cycloneCpu.pc;
#else
return m68k_get_reg(NULL, M68K_REG_PPC);
return fm68k_get_pc(&fameCpu);
#endif
#else
return m68k_get_reg(NULL, M68K_REG_PC);
#endif
}
uint64_t flx68000ReadArbitraryMemory(uint32_t address, uint8_t size){
uint64_t data = UINT64_MAX;//invalid access
#if defined(EMU_FAST_CPU)
#if defined(EMU_OPTIMIZE_FOR_ARM32)
//reading from a hardware register FIFO will corrupt it!
if(bankType[START_BANK(address)] != CHIP_NONE){
@@ -382,6 +469,10 @@ uint64_t flx68000ReadArbitraryMemory(uint32_t address, uint8_t size){
}
CycloneSetSr(&cycloneCpu, m68kSr);
}
#else
//FAME here
#endif
#else
//reading from a hardware register FIFO will corrupt it!
if(bankType[START_BANK(address)] != CHIP_NONE){

180
src/m68k/fame/fame.h Normal file
View File

@@ -0,0 +1,180 @@
/*****************************************************************************/
/* FAME Fast and Accurate Motorola 68000 Emulation Core */
/* (c) 2005 Oscar Orallo Pelaez */
/* Version: 1.24 */
/* Date: 08-20-2005 */
/* See FAME.HTML for documentation and license information */
/*****************************************************************************/
#ifndef __FAME_H__
#define __FAME_H__
// uintptr_t
#include <stdlib.h>
#ifndef _MSC_VER
#include <stdint.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
// PicoDrive hacks
#define FAMEC_FETCHBITS (32 - 14)//BANK_SCOOT, was 8 for picodrive
#define M68K_FETCHBANK1 (1 << FAMEC_FETCHBITS)
//#define M68K_RUNNING 0x01
#define FM68K_HALTED 0x80
//#define M68K_WAITING 0x04
//#define M68K_DISABLE 0x20
//#define M68K_FAULTED 0x40
#define FM68K_EMULATE_GROUP_0 0x02
#define FM68K_EMULATE_TRACE 0x08
#define FM68K_DO_TRACE 0x10
/************************************/
/* General library defines */
/************************************/
#ifndef M68K_OK
#define M68K_OK 0
#endif
#ifndef M68K_RUNNING
#define M68K_RUNNING 1
#endif
#ifndef M68K_NO_SUP_ADDR_SPACE
#define M68K_NO_SUP_ADDR_SPACE 2
#endif
#ifndef M68K_DOUBLE_BUS_FAULT
#define M68K_DOUBLE_BUS_FAULT -1
#endif
#ifndef M68K_INV_REG
#define M68K_INV_REG -1
#endif
/* Hardware interrupt state */
#ifndef M68K_IRQ_LEVEL_ERROR
#define M68K_IRQ_LEVEL_ERROR -1
#endif
#ifndef M68K_IRQ_INV_PARAMS
#define M68K_IRQ_INV_PARAMS -2
#endif
/* Defines to specify hardware interrupt type */
#ifndef M68K_AUTOVECTORED_IRQ
#define M68K_AUTOVECTORED_IRQ -1
#endif
#ifndef M68K_SPURIOUS_IRQ
#define M68K_SPURIOUS_IRQ -2
#endif
#ifndef M68K_AUTO_LOWER_IRQ
#define M68K_AUTO_LOWER_IRQ 1
#endif
#ifndef M68K_MANUAL_LOWER_IRQ
#define M68K_MANUAL_LOWER_IRQ 0
#endif
/* Defines to specify address space */
#ifndef M68K_SUP_ADDR_SPACE
#define M68K_SUP_ADDR_SPACE 0
#endif
#ifndef M68K_USER_ADDR_SPACE
#define M68K_USER_ADDR_SPACE 2
#endif
#ifndef M68K_PROG_ADDR_SPACE
#define M68K_PROG_ADDR_SPACE 0
#endif
#ifndef M68K_DATA_ADDR_SPACE
#define M68K_DATA_ADDR_SPACE 1
#endif
/*******************/
/* Data definition */
/*******************/
typedef union
{
unsigned char B;
signed char SB;
unsigned short W;
signed short SW;
unsigned int D;
signed int SD;
} famec_union32;
/* M68K CPU CONTEXT */
typedef struct
{
unsigned int (*read_byte )(unsigned int a);
unsigned int (*read_word )(unsigned int a);
unsigned int (*read_long )(unsigned int a);
void (*write_byte)(unsigned int a,unsigned char d);
void (*write_word)(unsigned int a,unsigned short d);
void (*write_long)(unsigned int a,unsigned int d);
void (*reset_handler)(void);
void (*iack_handler)(unsigned level);
famec_union32 dreg[8];
famec_union32 areg[8];
unsigned asp;
unsigned pc;
unsigned char interrupts[8];
unsigned short sr;
unsigned short execinfo;
// PD extension
int io_cycle_counter; // cycles left
unsigned int Opcode;
signed int cycles_needed;
unsigned short *PC;
uintptr_t BasePC;
unsigned int flag_C;
unsigned int flag_V;
unsigned int flag_NotZ;
unsigned int flag_N;
unsigned int flag_X;
unsigned int flag_T;
unsigned int flag_S;
unsigned int flag_I;
unsigned char not_polling;
unsigned char pad[3];
uintptr_t Fetch[M68K_FETCHBANK1];
} M68K_CONTEXT;
typedef enum
{
fm68k_reason_emulate = 0,
fm68k_reason_init,
fm68k_reason_idle_install,
fm68k_reason_idle_remove,
} fm68k_call_reason;
/************************/
/* Function definition */
/************************/
/* General purpose functions */
void fm68k_init(void);
int fm68k_reset(M68K_CONTEXT *ctx);
int fm68k_emulate(M68K_CONTEXT *ctx, int n, fm68k_call_reason reason);
int fm68k_would_interrupt(M68K_CONTEXT *ctx); // to be called from fm68k_emulate()
unsigned int fm68k_get_pc(const M68K_CONTEXT *ctx);
// PICODRIVE_HACK
int fm68k_idle_install(void);
int fm68k_idle_remove(void);
#ifdef __cplusplus
}
#endif
#endif

5077
src/m68k/fame/famec.c Normal file

File diff suppressed because it is too large Load Diff

40136
src/m68k/fame/famec_opcodes.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -176,8 +176,8 @@ unsigned int m68k_read_disassembler_16 (unsigned int address);
unsigned int m68k_read_disassembler_32 (unsigned int address);
/* Write to anywhere */
void m68k_write_memory_8(unsigned int address, unsigned int value);
void m68k_write_memory_16(unsigned int address, unsigned int value);
void m68k_write_memory_8(unsigned int address, unsigned char value);
void m68k_write_memory_16(unsigned int address, unsigned short value);
void m68k_write_memory_32(unsigned int address, unsigned int value);
/* Special call to simulate undocumented 68k behavior when move.l with a

View File

@@ -13,12 +13,17 @@ EMU_SOURCES_C := $(EMU_PATH)/emulator.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
ifeq ($(EMU_FAST_CPU), 1)
EMU_DEFINES += -DEMU_FAST_CPU
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_ASM += $(EMU_PATH)/m68k/cyclone/CycloneOld.S
EMU_SOURCES_C += $(EMU_PATH)/m68k/fame/famec.c
endif
else
EMU_SOURCES_C += $(EMU_PATH)/m68k/musashi/m68kops.c \