From 2f06623c62eea8903467a9bda03c3eaf0fce9442 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Wed, 21 Aug 2019 08:33:01 +0200 Subject: [PATCH] Rewrite MPC106 emualation from scratch. From now on, ppcmemory delegates physical address translation to MPC106 on PowerMac Beige G3. --- .gitignore | 1 + devices/mpc106.cpp | 455 +++++++++-------------------------- devices/mpc106.h | 79 ++++-- main.cpp | 225 ++++++----------- ppcemumain.h | 6 +- ppcmemory.cpp | 584 +++++++++------------------------------------ 6 files changed, 364 insertions(+), 986 deletions(-) diff --git a/.gitignore b/.gitignore index 2d3b8c1..9c44707 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ # Ignore compiled object files *.o +*.d # Ignore generated executables dingusppc diff --git a/devices/mpc106.cpp b/devices/mpc106.cpp index 903ffc3..3607199 100644 --- a/devices/mpc106.cpp +++ b/devices/mpc106.cpp @@ -5,368 +5,151 @@ //if you want to distribute this. //(divingkatae#1017 on Discord) -//Functionality for the MPC106 +/** MPC106 (Grackle) emulation + + Author: Max Poliakovski +*/ #include #include #include + +#include "memctrlbase.h" +#include "mmiodevice.h" #include "../viacuda.h" #include "mpc106.h" #include "../ppcemumain.h" #include "../ppcmemory.h" -bool mpc106_membound_change; -bool mpc106_mem_approve; //Confirm memory transaction -uint32_t mpc106_address; // For fe000000 - fe00ffff -uint32_t mpc_config_addr; // Device No. and Reg No. included -uint32_t mpc_config_dat; // Value to write to the device -uint32_t cust_grab_size; // Custom bit size - -uint32_t mpc106_write_word; -uint32_t mpc106_read_word; -uint16_t mpc106_write_half; -uint16_t mpc106_read_half; -uint8_t mpc106_write_byte; -uint8_t mpc106_read_byte; - -uint8_t mpc106_word_custom_size; - -//The below array is used for ROM banks -//Top eight entries are for the starting addresses -//Bottom eight entries are for the ending addresses -uint32_t mpc106_memory_bounds[16] = +MPC106::MPC106() : MemCtrlBase("Grackle") { -0x00000, 0x00000, 0x00000, 0x00000, -0x00000, 0x00000, 0x00000, 0x00000, -0xFFFFF, 0xFFFFF, 0xFFFFF, 0xFFFFF, -0xFFFFF, 0xFFFFF, 0xFFFFF, 0xFFFFF, -}; - -//Entries are organized like so... - -//ROM Banks 0-3 (ext. starting address) (starting address) (0x00000) -//ROM Banks 4-7 (ext. starting address) (starting address) (0x00000) -//ROM Banks 0-3 (ext. ending address) ( ending address) (0x00000) -//ROM Banks 4-7 (ext. ending address) ( ending address) (0x00000) - -void mpc106_init(){ - mpc_config_addr = 0; - mpc_config_dat = 0; - - //Initialize Vendor & Device IDs - machine_fexxxx_mem[0x00] = 0x57; - machine_fexxxx_mem[0x01] = 0x10; - - machine_fexxxx_mem[0x02] = 0x02; - - //PCI command + status - machine_fexxxx_mem[0x04] = 0x06; - machine_fexxxx_mem[0x06] = 0x80; - - machine_fexxxx_mem[0x0B] = 0x06; - machine_fexxxx_mem[0x0C] = 0x08; - - machine_fexxxx_mem[0x73] = 0xCD; - - machine_fexxxx_mem[0xA8] = 0x10; - machine_fexxxx_mem[0xA9] = 0x00; - machine_fexxxx_mem[0xAA] = 0x00; - machine_fexxxx_mem[0xAB] = 0xFF; - - machine_fexxxx_mem[0xAC] = 0x0C; - machine_fexxxx_mem[0xAD] = 0x06; - machine_fexxxx_mem[0xAE] = 0x0C; - machine_fexxxx_mem[0xAF] = 0x00; - - machine_fexxxx_mem[0xBA] = 0x04; - machine_fexxxx_mem[0xC0] = 0x01; - - machine_fexxxx_mem[0xE0] = 0x42; - machine_fexxxx_mem[0xE1] = 0x00; - machine_fexxxx_mem[0xE2] = 0xFF; - machine_fexxxx_mem[0xE3] = 0x0F; - - machine_fexxxx_mem[0xF0] = 0x00; - machine_fexxxx_mem[0xF1] = 0x00; - machine_fexxxx_mem[0xF2] = 0x02; - machine_fexxxx_mem[0xF3] = 0xFF; - - machine_fexxxx_mem[0xF4] = 0x03; - machine_fexxxx_mem[0xF5] = 0x00; - machine_fexxxx_mem[0xF6] = 0x00; - machine_fexxxx_mem[0xF7] = 0x00; - - machine_fexxxx_mem[0xFC] = 0x00; - machine_fexxxx_mem[0xFD] = 0x00; - machine_fexxxx_mem[0xFE] = 0x10; - machine_fexxxx_mem[0xFF] = 0x00; - - mpc106_mem_approve = false; - mpc106_word_custom_size = 0; + /* add memory mapped I/O region for MPC106 registers */ + add_mmio_region(0xFEC00000, 0x300000, this); } -uint32_t mpc106_write_device(uint32_t device_addr, uint32_t insert_to_device, uint8_t bit_length){ - //Write to the specified device - Invoked when a write is made to 0xFEExxxxx. - //device_addr is what's stored in 0xFEC00CF8 (The MPG106/Grackle's CONFIG_ADDR Register). +MPC106::~MPC106() +{ +} - uint32_t reg_num = (device_addr & 0x07FC) >> 2; - uint32_t dev_num = (device_addr & 0xF800) >> 11; +uint32_t MPC106::read(uint32_t offset, int size) +{ + if (offset >= 0x200000) { + if (this->config_addr & 0x80) // process only if bit E (enable) is set + return pci_read(size); + } - switch(dev_num){ - case 0: - //Device 0 is reserved to the grackle by default - mpc106_address = reg_num; - mpc106_write(insert_to_device); - break; - case 16: - case 17: - via_cuda_address = (reg_num << 9) + (dev_num << 12) + 0x3000000; - via_write_byte = (uint8_t)insert_to_device; - via_cuda_write(); - break; + /* FIXME: reading from CONFIG_ADDR is ignored for now */ + + return 0; +} + +void MPC106::write(uint32_t offset, uint32_t value, int size) +{ + if (offset < 0x200000) { + this->config_addr = value; + } else { + if (this->config_addr & 0x80) // process only if bit E (enable) is set + return pci_write(value, size); + } +} + +uint32_t MPC106::pci_read(uint32_t size) +{ + int bus_num, dev_num, fun_num, reg_num; + + bus_num = (this->config_addr >> 8) & 0xFF; + if (bus_num) { + std::cout << this->name << " err: read attempt from non-local PCI bus, " + << "config_addr = " << std::hex << this->config_addr << std::endl; + return 0; + } + + dev_num = (this->config_addr >> 19) & 0x1F; + fun_num = (this->config_addr >> 16) & 0x07; + reg_num = (this->config_addr >> 24) & 0xFC; + + if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself + return myself_read(reg_num, size); + } else { + std::cout << this->name << " err: reading from device " << dev_num + << " not supported yet" << std::endl; + return 0; } return 0; } -uint32_t mpc106_read_device(uint32_t device_addr, uint8_t bit_length){ - //Read to the specified device - Invoked when a read is made to 0xFEExxxxx. - //device_addr is what's stored in 0xFEC00CF8 (The MPG106/Grackle's CONFIG_ADDR Register). +void MPC106::pci_write(uint32_t value, uint32_t size) +{ + int bus_num, dev_num, fun_num, reg_num; - uint32_t reg_num = (device_addr & 0x07FC) >> 2; - uint32_t dev_num = (device_addr & 0xF800) >> 11; + bus_num = (this->config_addr >> 8) & 0xFF; + if (bus_num) { + std::cout << this->name << " err: write attempt to non-local PCI bus, " + << "config_addr = " << std::hex << this->config_addr << std::endl; + return; + } - uint32_t grab_value = 0; + dev_num = (this->config_addr >> 19) & 0x1F; + fun_num = (this->config_addr >> 16) & 0x07; + reg_num = (this->config_addr >> 24) & 0xFC; - switch(dev_num){ - case 0: - //Device 0 is reserved to the grackle by default - mpc106_address = reg_num; - mpc106_read(); - grab_value = mpc106_read_word; + if (dev_num == 0 && fun_num == 0) { // dev_num 0 is assigned to myself + myself_write(reg_num, value, size); + } else { + std::cout << this->name << " err: writing to device " << dev_num + << " not supported yet" << std::endl; + } +} + +uint32_t MPC106::myself_read(int reg_num, uint32_t size) +{ +#ifdef MPC106_DEBUG + printf("read from Grackle register %08X\n", reg_num); +#endif + + switch(size) { + case 1: + return this->my_pci_cfg_hdr[reg_num]; break; - case 16: - case 17: - via_cuda_address = (reg_num << 8) + (dev_num << 12) + 0x3000000; - via_cuda_read(); - grab_value = (uint32_t)via_read_byte; + case 2: + return READ_WORD_BE(&this->my_pci_cfg_hdr[reg_num]); break; - } - - return grab_value; -} - -bool mpc106_check_membound(uint32_t attempted_address){ - uint32_t mem_address_begin; - uint32_t mem_address_end; - for (int get_rom_bank = 0; get_rom_bank < 8; get_rom_bank++){ - mem_address_begin = mpc106_memory_bounds[get_rom_bank]; - mem_address_end = mpc106_memory_bounds[get_rom_bank + 8]; - if ((attempted_address >= mem_address_begin) & (attempted_address <= mem_address_end)){ - uint8_t is_valid = (machine_fexxxx_mem[0xA0] >> get_rom_bank) & 0x01; - if (is_valid == 0){ - return true; - } - } - } - return false; -} - - -void mpc106_set_membound_begin(uint8_t bound_area){ - uint32_t bcheck_area = 0x80 + bound_area; - uint32_t newbound = machine_fexxxx_mem[bcheck_area]; - uint32_t bound_entry = bound_area % 8; - uint32_t change_entry = mpc106_memory_bounds[bound_entry]; - change_entry &= 0xfffff; - change_entry = newbound << 20; - mpc106_memory_bounds[bound_entry] = change_entry; -} - -void mpc106_set_membound_extbegin(uint8_t bound_area){ - uint32_t bcheck_area = 0x88 + bound_area; - uint32_t newbound = machine_fexxxx_mem[bcheck_area]; - uint32_t bound_entry = bound_area % 8; - uint32_t change_entry = mpc106_memory_bounds[bound_entry]; - change_entry &= 0x0fffffff; - change_entry = (newbound & 0x3) << 28; - mpc106_memory_bounds[bound_entry] = change_entry; -} - -void mpc106_set_membound_end(uint8_t bound_area){ - uint32_t bcheck_area = 0x90 + bound_area; - uint32_t newbound = machine_fexxxx_mem[bcheck_area]; - uint32_t bound_entry = (bound_area % 8) + 8; - uint32_t change_entry = mpc106_memory_bounds[bound_entry]; - change_entry &= 0xfffff; - change_entry = newbound << 20; - mpc106_memory_bounds[bound_entry] = change_entry; -} - -void mpc106_set_membound_extend(uint8_t bound_area){ - uint32_t bcheck_area = 0x98 + bound_area; - uint32_t newbound = machine_fexxxx_mem[bcheck_area]; - uint32_t bound_entry = (bound_area % 8) + 8; - uint32_t change_entry = mpc106_memory_bounds[bound_entry]; - change_entry &= 0x0fffffff; - change_entry = (newbound & 0x3) << 28; - mpc106_memory_bounds[bound_entry] = change_entry; -} - -void mpc106_read(){ - - uint8_t read_length = 4; - - - if ((mpc106_address >= 0x80) | (mpc106_address < 0xA0)){ - mpc106_membound_change = true; - read_length = mpc106_word_custom_size; - } - else{ - switch (mpc106_address){ - case 0x8: - case 0x9: - case 0xA: - case 0xB: - case 0xC: - case 0xD: - case 0xE: - case 0xF: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x72: - case 0x73: - case 0xA0: - case 0xA3: - read_length = 1; + case 4: + return READ_DWORD_BE(&this->my_pci_cfg_hdr[reg_num]); break; - case 0x0: - case 0x2: - case 0x4: - case 0x6: - case 0x70: - read_length = 2; + default: + std::cout << "MPC106 read error: invalid size parameter " << size + << std::endl; + } + + return 0; +} + +void MPC106::myself_write(int reg_num, uint32_t value, uint32_t size) +{ +#ifdef MPC106_DEBUG + printf("write %08X to Grackle register %08X\n", value, reg_num); +#endif + + // FIXME: implement write-protection for read-only registers + switch(size) { + case 1: + this->my_pci_cfg_hdr[reg_num] = value & 0xFF; break; - case 0xF0: - case 0xF4: - case 0xF8: - case 0xFC: - read_length = 4; - default: //Avoid writing into reserved areas - read_length = 0; - } - } - - switch(read_length){ - case 1: - mpc106_read_word |= (grab_macmem_ptr[mpc106_address]); - break; - case 2: - mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]); - mpc106_read_word |= (grab_macmem_ptr[mpc106_address]) << 8; - break; - case 4: - mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]); - mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]) << 8; - mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]) << 16; - mpc106_read_word |= (grab_macmem_ptr[mpc106_address]) << 24; - break; - } - -} - -void mpc106_write(uint32_t write_word){ - - uint8_t write_length = 4; - - if ((mpc106_address >= 0x80) | (mpc106_address < 0xA0)){ - mpc106_membound_change = true; - write_length = mpc106_word_custom_size; - } - else{ - switch (mpc106_address){ - case 0x70: - case 0x72: - case 0x73: - case 0xA0: - case 0xA3: - write_length = 1; - break; - case 0x4: - case 0x6: - write_length = 2; - break; - case 0xF0: - case 0xF4: - case 0xF8: - case 0xFC: - write_length = 4; - default: //Avoid writing into reserved areas - write_length = 0; - } - } - - if (mpc106_membound_change){ - switch(write_length){ - case 1: - change_membound_time(); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word) & 0xFF); - break; - case 2: - change_membound_time(); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF); - change_membound_time(); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF); - break; - case 4: - change_membound_time(); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF); - change_membound_time(); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF); - change_membound_time(); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 16) & 0xFF); - change_membound_time(); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 24) & 0xFF); - break; - } - } - else{ - switch(write_length){ - case 1: - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word) & 0xFF); - break; - case 2: - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF); - break; - case 4: - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF); - grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 16) & 0xFF); - grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 24) & 0xFF); - break; - } - } -} - -void change_membound_time(){ - if (mpc106_address < 0x88){ - mpc106_set_membound_begin(mpc106_address); - mpc106_membound_change = false; - } - else if (mpc106_address < 0x90){ - mpc106_set_membound_extbegin(mpc106_address); - mpc106_membound_change = false; - } - else if (mpc106_address < 0x98){ - mpc106_set_membound_end(mpc106_address); - mpc106_membound_change = false; - } - else if (mpc106_address < 0xA0){ - mpc106_set_membound_extend(mpc106_address); - mpc106_membound_change = false; + case 2: + this->my_pci_cfg_hdr[reg_num] = (value >> 8) & 0xFF; + this->my_pci_cfg_hdr[reg_num+1] = value & 0xFF; + break; + case 4: + this->my_pci_cfg_hdr[reg_num] = (value >> 24) & 0xFF; + this->my_pci_cfg_hdr[reg_num+1] = (value >> 16) & 0xFF; + this->my_pci_cfg_hdr[reg_num+2] = (value >> 8) & 0xFF; + this->my_pci_cfg_hdr[reg_num+3] = value & 0xFF; + break; + default: + std::cout << "MPC106 read error: invalid size parameter " << size + << std::endl; } } diff --git a/devices/mpc106.h b/devices/mpc106.h index 91c96f5..13f6b74 100644 --- a/devices/mpc106.h +++ b/devices/mpc106.h @@ -5,34 +5,71 @@ //if you want to distribute this. //(divingkatae#1017 on Discord) -//Functionality for the MPC106 +/** MPC106 (Grackle) emulation + + Author: Max Poliakovski + + Grackle IC is a combined memory and PCI controller manufactored by Motorola. + It's the central device in the Gossamer architecture. + Manual: https://www.nxp.com/docs/en/reference-manual/MPC106UM.pdf + + This code emulate as much functionality as needed to run PowerMac Beige G3. + This implies that + - we only support address map B + - our virtual device reports revision 4.0 as expected by machine firmware +*/ #ifndef MPC106_H_ #define MPC106_H_ -#define mpc106_addres_map_a 1 -#define mpc106_addres_map_b 0 +#include +#include "memctrlbase.h" +#include "mmiodevice.h" -extern uint32_t mpc106_address; -extern uint32_t mpc_config_addr; -extern uint32_t mpc_config_dat; -extern uint32_t mpc106_write_word; -extern uint32_t mpc106_read_word; -extern uint16_t mpc106_write_half; -extern uint16_t mpc106_read_half; -extern uint8_t mpc106_write_byte; -extern uint8_t mpc106_read_byte; -extern uint8_t mpc106_word_custom_size; +class MPC106 : public MemCtrlBase, public MMIODevice +{ +public: + using MemCtrlBase::name; -extern unsigned char* mpc106_regs; + MPC106(); + ~MPC106(); + uint32_t read(uint32_t offset, int size); + void write(uint32_t offset, uint32_t value, int size); -extern void change_membound_time(); -extern void mpc106_init(); -extern void mpc106_read(); -extern void mpc106_write(uint32_t write_word); -extern uint32_t mpc106_write_device(uint32_t device_addr, uint32_t insert_to_device, uint8_t bit_length); -extern uint32_t mpc106_read_device(uint32_t device_addr, uint8_t bit_length); -extern bool mpc106_check_membound(uint32_t attempted_address); +protected: + /* PCI access */ + uint32_t pci_read(uint32_t size); + void pci_write(uint32_t value, uint32_t size); + + /* my own registers access */ + uint32_t myself_read(int reg_num, uint32_t size); + void myself_write(int reg_num, uint32_t value, uint32_t size); + +private: + uint8_t my_pci_cfg_hdr[256] = { + 0x57, 0x10, // vendor ID: Motorola + 0x02, 0x00, // device ID: MPC106 + 0x06, 0x00, // PCI command + 0x80, 0x00, // PCI status + 0x40, // revision ID: 4.0 + 0x00, // standard programming + 0x00, // subclass code + 0x06, // class code + [0x73] = 0xCD, // default value for ODCR + [0xA8] = 0x10, 0x00, 0x00, 0xFF, // PICR1 + [0xAC] = 0x0C, 0x06, 0x0C, 0x00, // PICR2 + [0xBA] = 0x04, + [0xC0] = 0x01, + [0xE0] = 0x42, 0x00, 0xFF, 0x0F, + [0xE8] = 0x20, + [0xF0] = 0x00, 0x00, 0x02, 0xFF, + [0xF4] = 0x03, + [0xFC] = 0x00, 0x00, 0x10, 0x00 + }; + + uint32_t config_addr; + //uint32_t config_data; +}; #endif diff --git a/main.cpp b/main.cpp index bf0c7fd..99eb81d 100644 --- a/main.cpp +++ b/main.cpp @@ -38,6 +38,33 @@ using namespace std; +/** + Power Macintosh ROM identification string + + is located in the ConfigInfo structure starting at 0x30D064 (PCI Macs) + or 0x30C064 (Nubus Macs). This helps a lot to determine which + hardware is to be used. +*/ +static const map PPCMac_ROMIdentity = { //Codename Abbreviation for... + {"Alch", "Performa 6400"}, //Alchemy + {"Come", "PowerBook 2400"}, //Comet + {"Cord", "Power Mac 5200/6200 series"}, //Cordyceps + {"Gaze", "Power Mac 6500"}, //Gazelle + {"Goss", "Power Mac G3 Beige"}, //Gossamer + {"GRX ", "PowerBook G3 Wallstreet"}, //(Unknown) + {"Hoop", "PowerBook 3400"}, //Hooper + {"PBX ", "PowerBook Pre-G3"}, //(Unknown) + {"PDM ", "Nubus Power Mac or WGS"}, //Piltdown Man (6100/7100/8100) + {"Pip ", "Pippin... uh... yeah..."}, //Pippin + {"Powe", "Generic Power Mac"}, //PowerMac? + {"Spar", "20th Anniversay Mac, you lucky thing."}, //Spartacus + {"Tanz", "Power Mac 4400"}, //Tanzania + {"TNT ", "Power Mac 7xxxx/8xxx series"}, //Trinitrotoluene :-) + {"Zanz", "A complete engima."}, //Zanzibar (mentioned in Sheepshaver's code, but no match to any known ROM) + {"????", "A clone, perhaps?"} //N/A (Placeholder ID) +}; + + SetPRS ppc_state; bool power_on = 1; @@ -55,6 +82,7 @@ uint32_t ppc_next_instruction_address; //Used for branching, setting up the NIA uint32_t return_value; +MemCtrlBase *mem_ctrl_instance = 0; //A pointer to a pointer, used for quick movement to one of the following //memory areas. These are listed right below. @@ -90,7 +118,7 @@ bool msr_es_change; //Check Endian uint32_t rom_file_begin; //where to start storing ROM files in memory uint32_t pci_io_end; -uint32_t rom_file_setsize; +uint32_t rom_filesize; clock_t clock_test_begin; //Used to make sure the TBR does not increment so quickly. @@ -397,26 +425,14 @@ int main(int argc, char **argv) rom_file_begin = 0xFFF00000; //where to start storing ROM files in memory pci_io_end = 0x83FFFFFF; - rom_file_setsize = 0x400000; + rom_filesize = 0x400000; + //Init virtual CPU. reg_init(); - /** - uint16_t test_endianness = 0x1234; - - //Test for endianess before beginning - uint8_t grab_result = (uint8_t) (test_endianness >> 8); - endian_switch endis; - - //Special case for little-endian machines - switch(unsigned(grab_result)){ - case 18: - endis = little_end; - break; - default: - endis = big_end; - } - **/ + //0xFFF00100 is where the reset vector is. + //In other words, begin executing code here. + ppc_state.ppc_pc = 0xFFF00100; uint32_t opcode_entered = 0; //used for testing opcodes in playground @@ -431,38 +447,25 @@ int main(int argc, char **argv) romFile.open("rom.bin", ios::in|ios::binary); if (romFile.fail()){ - cerr << "rom.bin not present. Creating it right now. Please restart this program.\n"; - std::ofstream outfile ("rom.bin", ios::binary); - - outfile << "Testing!" << std::endl; - - outfile.close(); + cerr << "rom.bin not present. Please provide an appropriate ROM file" + << "and restart this program.\n"; + romFile.close(); return 1; } - //Allocate memory for ROM, RAM, and I/O. + //Calculate and validate ROM file size. romFile.seekg(0, romFile.end); - rom_file_setsize = romFile.tellg(); - printf("Rom SIZE: %d \n", rom_file_setsize); + rom_filesize = romFile.tellg(); + printf("Rom SIZE: %d \n", rom_filesize); romFile.seekg (0, romFile.beg); - /** - Allocate memory wisely. + if (rom_filesize != 0x400000){ + cerr << "Unsupported ROM File size. Expected size is 4 megabytes.\n"; + romFile.close(); + return 1; + } - Corresponds (mostly) to the follow memory patterns seen in - https://www.nxp.com/docs/en/reference-manual/MPC106UM.pdf - - machine_sysram_mem - 0x00000000 to 0x7FFFFFFF - machine_upperiocontrol_mem - 0x80000000 to 0x807FFFFF - machine_iocontrolcdma_mem - 0x80800000 to 0x80FFFFFF - machine_loweriocontrol_mem - 0x81000000 to 0xBF7FFFFF - machine_interruptack_mem - 0xBFFFFFF0 to 0xBFFFFFFF - machine_iocontrolmem_mem - 0xC0000000 to 0xFFBFFFFF - machine_sysrom_mem - 0xFFC00000 to 0xFFFFFFFF - **/ - - //grab_disk_buf = (unsigned char*) calloc (32768, 1); machine_sysram_mem = (unsigned char*) calloc (67108864, 1); machine_sysconfig_mem = (unsigned char*) calloc (2048, 1); machine_upperiocontrol_mem = (unsigned char*) calloc (8388608, 1); @@ -476,7 +479,7 @@ int main(int argc, char **argv) machine_feexxx_mem = (unsigned char*) calloc (4096, 1); machine_ff00xx_mem = (unsigned char*) calloc (4096, 1); machine_ff80xx_mem = (unsigned char*) calloc (1048576, 1); - machine_sysrom_mem = (unsigned char*) calloc (rom_file_setsize, 1); + machine_sysrom_mem = (unsigned char*) calloc (rom_filesize, 1); memset(machine_sysram_mem, 0x0, 67108864); memset(machine_sysconfig_mem, 0x0, 2048); @@ -492,19 +495,10 @@ int main(int argc, char **argv) memset(machine_ff80xx_mem, 0x0, 1048576); grab_sysram_size = sizeof(machine_sysram_mem); - grab_sysrom_size = rom_file_setsize; + grab_sysrom_size = rom_filesize; //Sanity checks - Prevent the input files being too small or too big. //Also prevent the ROM area from overflow. - if (grab_sysrom_size < 0x100000){ - cerr << "ROM File is too small. Must be at least 1 megabyte.\n"; - return 1; - } - else if (grab_sysrom_size > 0x400000){ - cerr << "ROM File is too big. Must be no more than 4 megabytes.\n"; - return 1; - } - if (ram_size_set < 0x800000){ cerr << "The RAM size must be at least 8 MB to function.\n"; return 1; @@ -516,41 +510,11 @@ int main(int argc, char **argv) rom_file_begin = 0xFFFFFFFF - grab_sysrom_size + 1; - /** - Test for PowerPC Mac ROMS - - Starting at 0x30D064 (0x30C064 in older ROMS), there is a boot - identifier string in the ROM. This helps a lot to determine which - setup is to by used. - **/ - char * memPPCBlock = new char[5]; - - map PPCMac_ROMIdentity = { //Codename Abbreviation for... - {"Alch", "Performa 6400"}, //Alchemy - {"Come", "PowerBook 2400"}, //Comet - {"Cord", "Power Mac 5200/6200 series"}, //Cordyceps - {"Gaze", "Power Mac 6500"}, //Gazelle - {"Goss", "Power Mac G3 Beige"}, //Gossamer - {"GRX ", "PowerBook G3 Wallstreet"}, //(Unknown) - {"Hoop", "PowerBook 3400"}, //Hooper - {"PBX ", "PowerBook Pre-G3"}, //(Unknown) - {"PDM ", "Power Mac G1 or WGS"}, //(Unknown) - {"Pip ", "Pippin... uh... yeah..."}, //Pippin - {"Powe", "Generic Power Mac"}, //PowerMac? - {"Spar", "20th Anniversay Mac, you lucky thing."}, //Spartacus - {"Tanz", "Power Mac 4400"}, //Tanzania - {"TNT ", "Power Mac 7xxxx/8xxx series"}, //Trinitrotoluene :-) - {"Zanz", "A complete engima."}, //Zanzibar (mentioned in Sheepshaver's code, but no match to any known ROM) - {"????", "A clone, perhaps?"} //N/A (Placeholder ID) - }; - char configGrab = 0; uint32_t configInfoOffset = 0; - if (grab_sysrom_size == 0x400000){ - romFile.seekg (0x300082, ios::beg); //This is where the place to get the offset is - romFile.get(configGrab); //just one byte to determine where the identifier string is + romFile.get(configGrab); //just one byte to determine ConfigInfo location configInfoOffset = (uint32_t)(configGrab & 0xff); if (configInfoOffset == 0xC0){ @@ -558,8 +522,11 @@ int main(int argc, char **argv) } uint32_t configInfoAddr = 0x300000 + (configInfoOffset << 8) + 0x69; //address to check the identifier string + char memPPCBlock[5]; //First four chars are enough to distinguish between codenames romFile.seekg (configInfoAddr, ios::beg); - romFile.read(memPPCBlock, sizeof(uint32_t)); //Only four chars needed to distinguish between codenames + romFile.read(memPPCBlock, 4); + memPPCBlock[4] = 0; + uint32_t rom_id = (memPPCBlock[0] << 24) | (memPPCBlock[1] << 16) | (memPPCBlock[2] << 8) | memPPCBlock[3]; std::string string_test = std::string(memPPCBlock); @@ -571,58 +538,35 @@ int main(int argc, char **argv) if (string_test.compare(redo_me) == 0){ cout << "The machine is identified as..." << iter->second << endl; romFile.seekg (0x0, ios::beg); - - //This is where the first real instruction is in the ROM - //0xFFF00000 - 0xFFF02FFF is for the exception table, - //which is stored in all PPC ROMs here, btw. - - //0xFFF00100 is where the reset vector is. - //In other words, begin executing code here. - - ppc_state.ppc_pc = 0xFFF00100;//Please don't move this from here. - //A strange bug will happen where this will prevent proper branching - mpc106_init(); - mac_serial_init(); - mac_swim3_init(); - via_cuda_init(); - openpic_init(); break; } else{ iter++; } } + + switch(rom_id) { + case 0x476F7373: + cout << "Initialize Gossamer hardware..."; + mem_ctrl_instance = new MPC106(); + if (!mem_ctrl_instance->add_rom_region(0xFFC00000, 0x400000) || + !mem_ctrl_instance->add_ram_region(0x00000000, 0x800000)) { + cout << "failure!\n" << endl; + delete(mem_ctrl_instance); + romFile.close(); + return 1; + } + cout << "done" << endl; + break; + default: + cout << "This machine not supported yet." << endl; + return 1; } - //Copy the contents of the IO data and the ROM to memory appropriate locations. + //Read ROM file content and transfer it to the dedicated ROM region romFile.read ((char *)machine_sysrom_mem,grab_sysrom_size); - - /* - //Open the Disk File. - uint64_t disk_file_setsize = 0; - ifstream diskFile; - - diskFile.open("disk.img", ios::in|ios::binary); - - if (diskFile){ - diskFile.seekg(0, romFile.end); - disk_file_setsize = romFile.tellg(); - diskFile.seekg(0, romFile.beg); - - if (disk_file_setsize % 32678 != 0){ - cout << "WARNING - Disk file has improper offsets. Make sure the disk image has even 32 KB sectors." << endl; - } - else{ - //Copy the contents of the IO data and the ROM to memory appropriate locations. - diskFile.read ((char *)machine_sysram_mem,(sizeof(uint8_t)*0x8000)); - disk_inserted = 1; - disk_offset = 0; - } - } - else{ - disk_inserted = 0; - } - */ + mem_ctrl_instance->set_data(0xFFC00000, machine_sysrom_mem, rom_filesize); + romFile.close(); clock_test_begin = clock(); @@ -641,29 +585,6 @@ int main(int argc, char **argv) } else if ((checker=="1")|(checker=="realtime")|(checker=="/realtime")|(checker=="-realtime")){ execute_interpreter(); - /* - if (disk_inserted){ - if (disk_word == 32768){ - if (disk_offset < disk_file_setsize){ - disk_offset += 32768; - diskFile.seekg(disk_offset, romFile.beg); - char *ptr = ((char*)machine_iocontrolmem_mem + (0xF3008000 % 0x4000000)); - diskFile.read (ptr,(sizeof(uint8_t)*0x8000)); - disk_word = 0; - } - else{ - disk_offset = 0; - diskFile.seekg(0, romFile.beg); - char *ptr = ((char*)machine_iocontrolmem_mem + (0xF3008000 % 0x4000000)); - diskFile.read (ptr,(sizeof(uint8_t)*0x8000)); - disk_word = 0; - } - } - else{ - disk_word += 4; - } - } - */ } else if ((checker=="e")|(checker=="loadelf")|(checker=="/loadelf")|(checker=="-loadelf")){ ifstream elfFile; @@ -864,7 +785,7 @@ int main(int argc, char **argv) std::cout << "playground - Mess around with and opcodes. " << endl; } - romFile.close(); + delete(mem_ctrl_instance); //Free memory after the emulation is completed. free(machine_sysram_mem); diff --git a/ppcemumain.h b/ppcemumain.h index be374e6..23fc13c 100644 --- a/ppcemumain.h +++ b/ppcemumain.h @@ -10,6 +10,8 @@ #include +#include "devices/memctrlbase.h" + //Uncomment this to help debug the emulator further //#define EXHAUSTIVE_DEBUG 1 @@ -96,7 +98,7 @@ extern uint32_t ram_size_set; extern uint32_t rom_file_begin; //where to start storing ROM files in memory extern uint32_t pci_io_end; -extern uint32_t rom_file_setsize; +extern uint32_t rom_filesize; //Additional steps to prevent overflow? extern int32_t add_result; @@ -220,6 +222,8 @@ void ppc_tbr_update(); void ppc_exception_handler(uint32_t exception_type, uint32_t handle_args); //MEMORY DECLARATIONS +extern MemCtrlBase *mem_ctrl_instance; + extern unsigned char * machine_sysram_mem; extern unsigned char * machine_sysconfig_mem; //Mapped to 0x68000000 - extern unsigned char * machine_68kemu_mem; diff --git a/ppcmemory.cpp b/ppcmemory.cpp index ce55785..add6376 100644 --- a/ppcmemory.cpp +++ b/ppcmemory.cpp @@ -20,6 +20,8 @@ #include "ppcemumain.h" #include "ppcmemory.h" #include "openpic.h" +#include "devices/memctrlbase.h" +#include "devices/mmiodevice.h" #include "devices/mpc106.h" #include "davbus.h" @@ -94,76 +96,70 @@ void msr_status_update(){ msr_dr_test = (ppc_state.ppc_msr >> 4) & 1; } -inline void ppc_set_cur_instruction(uint32_t mem_index) +static inline void ppc_set_cur_instruction(unsigned char *ptr, uint32_t offset) { - ppc_cur_instruction = (grab_macmem_ptr[mem_index] << 24) | - (grab_macmem_ptr[mem_index+1] << 16) | - (grab_macmem_ptr[mem_index+2] << 8) | - grab_macmem_ptr[mem_index+3]; + ppc_cur_instruction = (ptr[offset] << 24) | (ptr[offset+1] << 16) | + (ptr[offset+2] << 8) | ptr[offset+3]; } -void ppc_set_return_val(uint32_t mem_index, int num_size) +static inline void ppc_set_return_val(unsigned char *ptr, uint32_t offset, + int num_size) { //Put the final result in return_value here //This is what gets put back into the register if (ppc_state.ppc_msr & 1) { /* little-endian byte ordering */ if (num_size == 1) { // BYTE - return_value = grab_macmem_ptr[mem_index]; + return_value = ptr[offset]; } else if (num_size == 2) { // WORD - return_value = grab_macmem_ptr[mem_index] | - (grab_macmem_ptr[mem_index+1] << 8); + return_value = ptr[offset] | (ptr[offset+1] << 8); } else if (num_size == 4) { // DWORD - return_value = grab_macmem_ptr[mem_index] | - (grab_macmem_ptr[mem_index+1] << 8) | - (grab_macmem_ptr[mem_index+2] << 16) | - (grab_macmem_ptr[mem_index+3] << 24); + return_value = ptr[offset] | (ptr[offset+1] << 8) | + (ptr[offset+2] << 16) | (ptr[offset+3] << 24); } } else { /* big-endian byte ordering */ if (num_size == 1) { // BYTE - return_value = grab_macmem_ptr[mem_index]; + return_value = ptr[offset]; } else if (num_size == 2) { // WORD - return_value = (grab_macmem_ptr[mem_index] << 8) | - grab_macmem_ptr[mem_index+1]; + return_value = (ptr[offset] << 8) | ptr[offset+1]; } else if (num_size == 4) { // DWORD - return_value = (grab_macmem_ptr[mem_index] << 24) | - (grab_macmem_ptr[mem_index+1] << 16) | - (grab_macmem_ptr[mem_index+2] << 8) | - grab_macmem_ptr[mem_index+3]; + return_value = (ptr[offset] << 24) | (ptr[offset+1] << 16) | + (ptr[offset+2] << 8) | ptr[offset+3]; } } } -void ppc_memstore_value(uint32_t value_insert, uint32_t mem_index, int num_size) +static inline void ppc_memstore_value(unsigned char *ptr, uint32_t value, + uint32_t offset, int num_size) { if (ppc_state.ppc_msr & 1) { /* little-endian byte ordering */ if (num_size >= 1) { // BYTE - grab_macmem_ptr[mem_index] = value_insert & 0xFF; + ptr[offset] = value & 0xFF; } if (num_size >= 2) { // WORD - grab_macmem_ptr[mem_index+1] = (value_insert >> 8) & 0xFF; + ptr[offset+1] = (value >> 8) & 0xFF; } if (num_size == 4) { // DWORD - grab_macmem_ptr[mem_index+2] = (value_insert >> 16) & 0xFF; - grab_macmem_ptr[mem_index+3] = (value_insert >> 24) & 0xFF; + ptr[offset+2] = (value >> 16) & 0xFF; + ptr[offset+3] = (value >> 24) & 0xFF; } } else { /* big-endian byte ordering */ if (num_size == 1) { // BYTE - grab_macmem_ptr[mem_index] = value_insert & 0xFF; + ptr[offset] = value & 0xFF; } else if (num_size == 2) { // WORD - grab_macmem_ptr[mem_index] = (value_insert >> 8) & 0xFF; - grab_macmem_ptr[mem_index+1] = value_insert & 0xFF; + ptr[offset] = (value >> 8) & 0xFF; + ptr[offset+1] = value & 0xFF; } else if (num_size == 4) { // DWORD - grab_macmem_ptr[mem_index] = (value_insert >> 24) & 0xFF; - grab_macmem_ptr[mem_index+1] = (value_insert >> 16) & 0xFF; - grab_macmem_ptr[mem_index+2] = (value_insert >> 8) & 0xFF; - grab_macmem_ptr[mem_index+3] = value_insert & 0xFF; + ptr[offset] = (value >> 24) & 0xFF; + ptr[offset+1] = (value >> 16) & 0xFF; + ptr[offset+2] = (value >> 8) & 0xFF; + ptr[offset+3] = value & 0xFF; } } } @@ -282,7 +278,7 @@ void get_pointer_pteg1(uint32_t address_grab){ } } else{ - pte_word1 = address_grab % rom_file_setsize; + pte_word1 = address_grab % rom_filesize; grab_pteg1_ptr = machine_sysrom_mem; } } @@ -359,7 +355,7 @@ void get_pointer_pteg2(uint32_t address_grab){ } } else{ - pte_word2 = address_grab % rom_file_setsize; + pte_word2 = address_grab % rom_filesize; grab_pteg2_ptr = machine_sysrom_mem; } } @@ -561,465 +557,101 @@ uint32_t ppc_mmu_addr_translate(uint32_t la, uint32_t access_type) } -/** Insert a value into memory from a register. */ -void address_quickinsert_translate(uint32_t value_insert, uint32_t address_grab, - uint8_t num_bytes) +uint32_t write_last_pa_start = 0; +uint32_t write_last_pa_end = 0; +unsigned char *write_last_ptr = 0; + +void address_quickinsert_translate(uint32_t value, uint32_t addr, uint8_t num_bytes) { - uint32_t storage_area = 0; - - printf("Inserting into address %x with %x \n", address_grab, value_insert); - - // data address translation if enabled - if (ppc_state.ppc_msr & 0x10) { - printf("DATA RELOCATION GO! - INSERTING \n"); - - address_grab = ppc_mmu_addr_translate(address_grab, 0); - } - - //regular grabbing - if (address_grab < 0x80000000){ - if (mpc106_check_membound(address_grab)){ - if (address_grab > 0x03ffffff){ //for debug purposes - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; - } - else if ((address_grab >= 0x40000000) && (address_grab < 0x40400000)){ - if (is_nubus){ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_memstore_value(value_insert, storage_area, num_bytes); - return; - } - else{ - return; - } - } - else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){ - storage_area = address_grab % 0x2000; - grab_macmem_ptr = machine_sysconfig_mem; - } - else{ - storage_area = address_grab % 0x04000000; - grab_macmem_ptr = machine_sysram_mem; - printf("Uncharted territory: %x \n", address_grab); - } - } - else{ - return; - } - } - else if (address_grab < 0x80800000){ - storage_area = address_grab % 0x800000; - if (address_grab == 0x80000CF8){ - storage_area = 0x0CF8; //CONFIG_ADDR - value_insert = rev_endian32(value_insert); - grab_macmem_ptr = machine_fecxxx_mem; - uint32_t reg_num = (value_insert & 0x07FC) >> 2; - uint32_t dev_num = (value_insert & 0xF800) >> 11; - printf("ADDRESS SET FOR GRACKLE: "); - printf("Device Number: %d ", dev_num); - printf("Hex Register Number: %x \n", reg_num); - mpc106_address = value_insert; - } - else{ - grab_macmem_ptr = machine_upperiocontrol_mem; - } - - - if ((address_grab >= 0x80040000) && (address_grab < 0x80080000)){ - openpic_address = address_grab - 0x80000000; - openpic_read_word = value_insert; - openpic_read(); - return; - } - - printf("Uncharted territory: %x \n", address_grab); - } - else if (address_grab < 0x81000000){ - if (address_grab > 0x83FFFFFF){ - return; - } - storage_area = address_grab; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_iocontrolcdma_mem; - } - else if (address_grab < 0xBF800000){ - storage_area = address_grab % 33554432; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_loweriocontrol_mem; - } - else if (address_grab < 0xC0000000){ - storage_area = address_grab % 16; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_interruptack_mem; - } - else if (address_grab < 0xF0000000){ - printf("Invalid Memory Attempt: %x \n", address_grab); - return; - } - else if (address_grab < 0xF8000000){ - storage_area = address_grab % 67108864; - if ((address_grab >= 0xF3013000) && (address_grab < 0xF3013040)){ - mac_serial_address = storage_area; - serial_write_byte = (uint8_t)value_insert; - printf("Writing byte to Serial address %x ... %x \n", address_grab, via_write_byte); - mac_serial_write(); - return; - } - else if ((address_grab >= 0xF3014000) && (address_grab < 0xF3015000)){ - davbus_address = storage_area; - davbus_write_word = value_insert; - printf("\nWriting to DAVBus: %x \n", return_value); - davbus_write(); - return; - } - else if ((address_grab >= 0xF3015000) && (address_grab < 0xF3016000)){ - mac_swim3_address = storage_area; - swim3_write_byte = (uint8_t)value_insert; - printf("Writing byte to SWIM3 address %x ... %x \n", address_grab, swim3_write_byte); - mac_swim3_write(); - return; - } - else if ((address_grab >= 0xF3016000) && (address_grab < 0xF3018000)){ - via_cuda_address = storage_area; - via_write_byte = (uint8_t)value_insert; - printf("Writing byte to CUDA address %x ... %x \n", address_grab, via_write_byte); - via_cuda_write(); - return; - } - else if ((address_grab >= 0xF3040000) && (address_grab < 0xF3080000)){ - openpic_address = storage_area - 0x3000000; - openpic_write_word = value_insert; - printf("Writing byte to OpenPIC address %x ... %x \n", address_grab, openpic_write_word); - openpic_write(); - return; - } - else if (address_grab > 0xF3FFFFFF){ - printf("Uncharted territory: %x", address_grab); - return; - } - grab_macmem_ptr = machine_iocontrolmem_mem; - } - else if (address_grab < rom_file_begin){ - //Get back to this! (weeny1) - - if (address_grab < 0xFE000000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_f8xxxx_mem; - } - else if (address_grab < 0xFEC00000){ - mpc106_address = address_grab % 65536; - mpc106_write(value_insert); - return; - } - else if (address_grab < 0xFEE00000){ - storage_area = 0x0CF8; //CONFIG_ADDR - grab_macmem_ptr = machine_fecxxx_mem; - value_insert = rev_endian32(value_insert); - uint32_t reg_num = (value_insert & 0x07FC) >> 2; - uint32_t dev_num = (value_insert & 0xF800) >> 11; - printf("ADDRESS SET FOR GRACKLE \n"); - printf("Device Number: %d ", dev_num); - printf("Hex Register Number: %x \n", reg_num); - mpc_config_addr = value_insert; - } - else if (address_grab < 0xFF000000){ - storage_area = 0x0CFC; //CONFIG_DATA - mpc106_word_custom_size = num_bytes; - mpc106_write_device(mpc_config_addr, value_insert, num_bytes); - grab_macmem_ptr = machine_feexxx_mem; - } - else if (address_grab < 0xFF800000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_ff00xx_mem; - } - else{ - storage_area = (address_grab % 1048576) + 0x400000; - grab_macmem_ptr = machine_sysram_mem; - } - } - else{ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - } - - ppc_memstore_value(value_insert, storage_area, num_bytes); -} - -/** Grab a value from memory into a register */ -void address_quickgrab_translate(uint32_t address_grab, uint8_t num_bytes) -{ - uint32_t storage_area = 0; - - //printf("Grabbing from address %x \n", address_grab); - - return_value = 0; //reset this before going into the real fun. - /* data address translation if enabled */ if (ppc_state.ppc_msr & 0x10) { - printf("DATA RELOCATION GO! - GRABBING \n"); - - address_grab = ppc_mmu_addr_translate(address_grab, 0); + addr = ppc_mmu_addr_translate(addr, 0); } - if (address_grab >= 0xFFC00000){ - //printf("Charting ROM Area: %x \n", address_grab); - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_set_return_val(storage_area, num_bytes); - return; - } - - //regular grabbing - else if (address_grab < 0x80000000){ - if ((address_grab >= 0x40000000) && (address_grab < 0x40400000) && is_nubus){ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_set_return_val(storage_area, num_bytes); - return; - } - - if (mpc106_check_membound(address_grab)){ - if (address_grab > 0x03ffffff){ //for debug purposes - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; + if (addr >= write_last_pa_start && addr <= write_last_pa_end) { + ppc_memstore_value(write_last_ptr, value, addr - write_last_pa_start, num_bytes); + } else { + AddressMapEntry *entry = mem_ctrl_instance->find_range(addr); + if (entry) { + if (entry->type & RT_RAM) { + write_last_pa_start = entry->start; + write_last_pa_end = entry->end; + write_last_ptr = entry->mem_ptr; + ppc_memstore_value(write_last_ptr, value, addr - entry->start, num_bytes); + } else if (entry->type & RT_MMIO) { + entry->devobj->write(addr - entry->start, value, num_bytes); + } else { + printf("Please check your address map!\n"); } - else if ((address_grab >= 0x40000000) && (address_grab < 0x40400000)){ - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; - } - else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){ - storage_area = address_grab % 0x2000; - grab_macmem_ptr = machine_sysconfig_mem; - } - else{ - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; - } - } - else{ - //The address is not within the ROM banks - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; + } else { + printf("WARNING: write attempt to unmapped memory at 0x%08X!\n", addr); } } - else if (address_grab < 0x80800000){ - if ((address_grab >= 0x80040000) && (address_grab < 0x80080000)){ - openpic_address = address_grab - 0x80000000; - openpic_write(); - return_value = openpic_write_word; - return; - } - - storage_area = address_grab % 0x800000; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_upperiocontrol_mem; - } - else if (address_grab < 0x81000000){ - storage_area = address_grab; - if (address_grab > 0x83FFFFFF){ - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; - } - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_iocontrolcdma_mem; - } - else if (address_grab < 0xBF800000){ - storage_area = address_grab % 33554432; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_loweriocontrol_mem; - } - else if (address_grab < 0xC0000000){ - storage_area = address_grab % 16; - printf("Uncharted territory: %x \n", address_grab); - grab_macmem_ptr = machine_interruptack_mem; - } - else if (address_grab < 0xF0000000){ - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; - } - else if (address_grab < 0xF8000000){ - storage_area = address_grab % 67108864; - if ((address_grab >= 0xF3013000) && (address_grab < 0xF3013040)){ - mac_serial_address = storage_area; - mac_serial_read(); - return_value = serial_read_byte; - printf("\n Read from Serial: %x \n", return_value); - return; - } - else if ((address_grab >= 0xF3014000) && (address_grab < 0xF3015000)){ - davbus_address = storage_area; - davbus_read(); - return_value = davbus_read_word; - printf("\n Read from DAVBus: %x \n", return_value); - return; - } - else if ((address_grab >= 0xF3015000) && (address_grab < 0xF3016000)){ - mac_swim3_address = storage_area; - mac_swim3_read(); - return_value = swim3_read_byte; - printf("\n Read from Swim3: %x \n", return_value); - return; - } - else if ((address_grab >= 0xF3016000) && (address_grab < 0xF3018000)){ - via_cuda_address = storage_area; - via_cuda_read(); - return_value = via_read_byte; - printf("\n Read from CUDA: %x \n", return_value); - return; - } - else if ((address_grab >= 0xF3040000) && (address_grab < 0xF3080000)){ - openpic_address = storage_area - 0x3000000; - openpic_read(); - return_value = openpic_write_word; - return; - } - else if (address_grab > 0xF3FFFFFF){ - return_value = (num_bytes == 1)?0xFF:(num_bytes == 2)?0xFFFF:0xFFFFFFFF; - return; - } - grab_macmem_ptr = machine_iocontrolmem_mem; - } - else if (address_grab < rom_file_begin){ - //Get back to this! (weeny1) - if (address_grab < 0xFE000000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_f8xxxx_mem; - } - else if (address_grab < 0xFEC00000){ - mpc106_address = address_grab % 65536; - mpc106_read(); - return_value = mpc106_read_word; - return; - } - else if (address_grab < 0xFEE00000){ - return_value = (num_bytes == 1)? (mpc106_address & 0xFF):(num_bytes == 2)?(mpc106_address & 0xFFFF):mpc106_address; - return; - } - else if (address_grab < 0xFF000000){ - mpc106_word_custom_size = num_bytes; - return_value = mpc106_read_device(mpc_config_addr, num_bytes); - return_value = rev_endian32(return_value); - return; - } - else if (address_grab < 0xFF800000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_ff00xx_mem; - } - else{ - storage_area = (address_grab % 1048576) + 0x400000; - grab_macmem_ptr = machine_sysram_mem; - } - } - - ppc_set_return_val(storage_area, num_bytes); - } -void quickinstruction_translate(uint32_t address_grab) + +uint32_t read_last_pa_start = 0; +uint32_t read_last_pa_end = 0; +unsigned char *read_last_ptr = 0; + +/** Grab a value from memory into a register */ +void address_quickgrab_translate(uint32_t addr, uint8_t num_bytes) { - uint32_t storage_area = 0; + /* data address translation if enabled */ + if (ppc_state.ppc_msr & 0x10) { + //printf("DATA RELOCATION GO! - GRABBING \n"); - return_value = 0; //reset this before going into the real fun. + addr = ppc_mmu_addr_translate(addr, 0); + } + if (addr >= read_last_pa_start && addr <= read_last_pa_end) { + ppc_set_return_val(read_last_ptr, addr - read_last_pa_start, num_bytes); + } else { + AddressMapEntry *entry = mem_ctrl_instance->find_range(addr); + if (entry) { + if (entry->type & (RT_ROM | RT_RAM)) { + read_last_pa_start = entry->start; + read_last_pa_end = entry->end; + read_last_ptr = entry->mem_ptr; + ppc_set_return_val(read_last_ptr, addr - entry->start, num_bytes); + } else if (entry->type & RT_MMIO) { + return_value = entry->devobj->read(addr - entry->start, num_bytes); + } else { + printf("Please check your address map!\n"); + } + } else { + printf("WARNING: read attempt from unmapped memory at 0x%08X!\n", addr); + + /* reading from unmapped memory will return unmapped value */ + for (return_value = 0xFF; --num_bytes > 0;) + return_value = (return_value << 8) | 0xFF; + } + } +} + + +uint32_t exec_last_pa_start = 0; +uint32_t exec_last_pa_end = 0; +unsigned char *exec_last_ptr = 0; + +void quickinstruction_translate(uint32_t addr) +{ /* instruction address translation if enabled */ if (ppc_state.ppc_msr & 0x20) { - printf("INSTRUCTION RELOCATION GO! \n"); - - address_grab = ppc_mmu_instr_translate(address_grab); + addr = ppc_mmu_instr_translate(addr); } - //grab opcode from memory area - if (address_grab >= 0xFFC00000){ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_set_cur_instruction(storage_area); - return; - } - else if (address_grab < 0x80000000){ - if (address_grab < 0x040000000){ //for debug purposes - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; - } - else if ((address_grab >= 0x40000000) && (address_grab < 0x40400000)){ - if (is_nubus){ - storage_area = address_grab % rom_file_setsize; - grab_macmem_ptr = machine_sysrom_mem; - ppc_set_cur_instruction(storage_area); - return; - } - else{ - storage_area = address_grab; - grab_macmem_ptr = machine_sysram_mem; - } - } - else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){ - storage_area = address_grab % 0x2000; - grab_macmem_ptr = machine_sysconfig_mem; - } - else{ - storage_area = address_grab % 0x04000000; - grab_macmem_ptr = machine_sysram_mem; - printf("Uncharted territory: %x \n", address_grab); + if (addr >= exec_last_pa_start && addr <= exec_last_pa_end) { + ppc_set_cur_instruction(exec_last_ptr, addr - exec_last_pa_start); + } else { + AddressMapEntry *entry = mem_ctrl_instance->find_range(addr); + if (entry && entry->type & (RT_ROM | RT_RAM)) { + exec_last_pa_start = entry->start; + exec_last_pa_end = entry->end; + exec_last_ptr = entry->mem_ptr; + ppc_set_cur_instruction(exec_last_ptr, addr - exec_last_pa_start); + } else { + printf("WARNING: attempt to execute code at %08X!\n", addr); } } - else if (address_grab < 0x80800000){ - storage_area = address_grab % 0x800000; - grab_macmem_ptr = machine_upperiocontrol_mem; - - } - else if (address_grab < 0x81000000){ - storage_area = address_grab % 0x800000; - grab_macmem_ptr = machine_iocontrolcdma_mem; - - } - else if (address_grab < 0xBF80000){ - storage_area = address_grab % 33554432; - grab_macmem_ptr = machine_loweriocontrol_mem; - - } - else if (address_grab < 0xC0000000){ - storage_area = address_grab % 16; - grab_macmem_ptr = machine_interruptack_mem; - - } - else if (address_grab < 0xF0000000){ - printf("Invalid Memory Attempt: %x \n", address_grab); - return; - } - else if (address_grab < 0xF8000000){ - storage_area = address_grab % 67108864; - grab_macmem_ptr = machine_iocontrolmem_mem; - - } - else if (address_grab < rom_file_begin){ - //Get back to this! (weeny1) - - if (address_grab < 0xFE000000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_f8xxxx_mem; - } - else if (address_grab < 0xFEC00000){ - storage_area = address_grab % 65536; - grab_macmem_ptr = machine_fexxxx_mem; - } - else if (address_grab < 0xFEE00000){ - storage_area = 0x0CF8; //CONFIG_ADDR - grab_macmem_ptr = machine_fecxxx_mem; - } - else if (address_grab < 0xFF000000){ - storage_area = 0x0CFC; //CONFIG_DATA - grab_macmem_ptr = machine_feexxx_mem; - } - else if (address_grab < 0xFF800000){ - storage_area = address_grab % 4096; - grab_macmem_ptr = machine_ff00xx_mem; - } - else{ - storage_area = (address_grab % 1048576) + 0x400000; - grab_macmem_ptr = machine_sysram_mem; - } - } - - ppc_set_cur_instruction(storage_area); }