uvmac/lib/M68K/m68khooks.c
InvisibleUp 30ded064a5 Remove floppy disk hack
I don't want it and I have more pressing concerns at the moment
2023-04-01 17:44:25 -07:00

292 lines
7.5 KiB
C

#include "m68k.h"
//#include "m68kcpu.h"
#include "GLOBGLUE.h"
#include <stddef.h>
#include <stdbool.h>
#include <assert.h>
#include <stdio.h>
/* --- extra global variables --- */
bool m68k_on_breakpoint = false;
bool m68k_need_singlestep = false;
/* ======================================================================== */
/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */
/* ======================================================================== */
/* You will have to implement these functions */
/* read/write functions called by the CPU to access memory.
* while values used are 32 bits, only the appropriate number
* of bits are relevant (i.e. in write_memory_8, only the lower 8 bits
* of value should be written to memory).
*
* NOTE: I have separated the immediate and PC-relative memory fetches
* from the other memory fetches because some systems require
* differentiation between PROGRAM and DATA fetches (usually
* for security setups such as encryption).
* This separation can either be achieved by setting
* M68K_SEPARATE_READS in m68kconf.h and defining
* the read functions, or by setting M68K_EMULATE_FC and
* making a function code callback function.
* Using the callback offers better emulation coverage
* because you can also monitor whether the CPU is in SYSTEM or
* USER mode, but it is also slower.
*/
/* Read from anywhere */
unsigned int m68k_read_memory_8(unsigned int address)
{
ATTer *r = get_address_realblock1(false, address);
// check for bus error
//assert(r != NULL);
if (r == NULL) {
//m68k_pulse_bus_error(); // might cause issues on Mac
return 0;
}
address &= r->usemask;
// Check if memory-mapped IO
if (r->Access == kATTA_mmdvmask) {
return MMDV_Access(r, 0, false, true, address);
}
// Return raw data
uint8_t result = *(uint8_t *)(r->usebase + address);
//fprintf(stderr, "read8 %X -> %X\n", address, result);
return result;
}
unsigned int m68k_read_memory_16(unsigned int address)
{
ATTer *r = get_address_realblock1(false, address);
// check for bus error
//assert(r != NULL);
if (r == NULL) {
//m68k_pulse_bus_error(); // might cause issues on Mac
return 0;
}
address &= r->usemask;
// Check if memory-mapped IO
if (r->Access == kATTA_mmdvmask) {
return MMDV_Access(r, 0, false, false, address);
}
// Return raw data
uint16_t result;
#ifdef _MSC_VER
result = _byteswap_ushort(*(uint16_t *)(r->usebase + address));
#else
// gcc-likes
result = __builtin_bswap16(*(uint16_t *)(r->usebase + address));
#endif
//fprintf(stderr, "read16 %X -> %X\n", address, result);
return result;
}
unsigned int m68k_read_memory_32(unsigned int address)
{
ATTer *r = get_address_realblock1(false, address);
// check for bus error
//assert(r != NULL);
if (r == NULL) {
//m68k_pulse_bus_error(); // might cause issues on Mac
return 0;
}
address &= r->usemask;
// Check if memory-mapped IO
// TODO: check that this is the correct endianess
if (r->Access == kATTA_mmdvmask) {
return (MMDV_Access(r, 0, false, false, address) << 16) \
+ MMDV_Access(r, 0, false, false, address+2);
}
// Return raw data
uint32_t result;
#ifdef _MSC_VER
result = _byteswap_ulong(*(uint32_t *)(r->usebase + address));
#else
result = __builtin_bswap32(*(uint32_t *)(r->usebase + address));
#endif
//fprintf(stderr, "read32 %X -> %X\n", address, result);
return result;
}
#if 0
/* Read data immediately following the PC */
unsigned int m68k_read_immediate_16(unsigned int address) {
return m68k_read_memory_16(address);
}
unsigned int m68k_read_immediate_32(unsigned int address) {
return m68k_read_memory_32(address);
}
/* Read data relative to the PC */
unsigned int m68k_read_pcrelative_8(unsigned int address) {
return m68k_read_memory_8(address);
}
unsigned int m68k_read_pcrelative_16(unsigned int address) {
return m68k_read_memory_16(address);
}
unsigned int m68k_read_pcrelative_32(unsigned int address) {
return m68k_read_memory_32(address);
}
#endif
/* Memory access for the disassembler */
unsigned int m68k_read_disassembler_8 (unsigned int address) {
return m68k_read_memory_8(address);
}
unsigned int m68k_read_disassembler_16 (unsigned int address) {
return m68k_read_memory_16(address);
}
unsigned int m68k_read_disassembler_32 (unsigned int address) {
return m68k_read_memory_32(address);
}
/* Write to anywhere */
void m68k_write_memory_8(unsigned int address, unsigned int value)
{
ATTer *r = get_address_realblock1(true, address);
// check for bus error
assert(r != NULL);
if (r == NULL) {
//m68k_pulse_bus_error(); // might cause issues on Mac
return;
}
address &= r->usemask;
// Check if memory-mapped IO
if (r->Access == kATTA_mmdvmask) {
MMDV_Access(r, value, true, true, address);
return;
}
// Return raw data
*(uint8_t *)(r->usebase + address) = (uint8_t) value;
}
void m68k_write_memory_16(unsigned int address, unsigned int value)
{
ATTer *r = get_address_realblock1(true, address);
#ifdef _MSC_VER
value = _byteswap_ushort(value);
#else
value = __builtin_bswap16(value);
#endif
// check for bus error
//assert (r != NULL);
if (r == NULL) {
//m68k_pulse_bus_error(); // might cause issues on Mac
return;
}
address &= r->usemask;
// Check if memory-mapped IO
if (r->Access == kATTA_mmdvmask) {
MMDV_Access(r, value, true, false, address);
return;
}
// Return raw data
*(uint16_t *)(r->usebase + address) = (uint16_t) value;
}
void m68k_write_memory_32(unsigned int address, unsigned int value)
{
ATTer *r = get_address_realblock1(true, address);
#ifdef _MSC_VER
value = _byteswap_ulong(value);
#else
value = __builtin_bswap32(value);
#endif
// check for bus error
//assert(r != NULL);
if (r == NULL) {
//m68k_pulse_bus_error(); // might cause issues on Mac
return;
}
address &= r->usemask;
// Check if memory-mapped IO
// TODO: check if proper endianess
if (r->Access == kATTA_mmdvmask) {
MMDV_Access(r, value & 0xFFFF0000, true, false, address);
MMDV_Access(r, value & 0x0000FFFF, true, false, address+2);
return;
}
// Return raw data
*(uint32_t *)(r->usebase + address) = (uint32_t) value;
}
/* Special call to simulate undocumented 68k behavior when move.l with a
* predecrement destination mode is executed.
* To simulate real 68k behavior, first write the high word to
* [address+2], and then write the low word to [address].
*
* Enable this functionality with M68K_SIMULATE_PD_WRITES in m68kconf.h.
*/
void m68k_write_memory_32_pd(unsigned int address, unsigned int value)
{
m68k_write_memory_16(address+2, value & 0xFFFF0000);
m68k_write_memory_16(address, value & 0x0000FFFF);
}
// Initialize M68K with the proper options for the system
bool m68k_init_mac()
{
// TODO: this, but better
if (Use68020) {
m68k_set_cpu_type(M68K_CPU_TYPE_68020);
} else {
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
}
m68k_init();
//gdbstub_init();
return true;
}
// Thunks for old M68K emulator
uint8_t get_vm_byte(uint32_t addr) {
return m68k_read_memory_8(addr);
}
uint16_t get_vm_word(uint32_t addr) {
return m68k_read_memory_16(addr);
}
uint32_t get_vm_long(uint32_t addr) {
return m68k_read_memory_32(addr);
}
void put_vm_byte(uint32_t addr, uint8_t b) {
m68k_write_memory_8(addr, b);
}
void put_vm_word(uint32_t addr, uint16_t w) {
m68k_write_memory_16(addr, w);
}
void put_vm_long(uint32_t addr, uint32_t l) {
m68k_write_memory_32(addr, l);
}
// purely for debugging purposes
void m68k_instruction_hook(uint32_t pc)
{
if (pc == 0x4006E4) {
fprintf(stderr, "PC: %X\n", pc);
}
}