Rewrite MPC106 emualation from scratch.

From now on, ppcmemory delegates physical address translation
to MPC106 on PowerMac Beige G3.
This commit is contained in:
Maxim Poliakovski 2019-08-21 08:33:01 +02:00
parent ac1f770f92
commit 2f06623c62
6 changed files with 364 additions and 986 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@
# Ignore compiled object files
*.o
*.d
# Ignore generated executables
dingusppc

View File

@ -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 <iostream>
#include <cstring>
#include <cinttypes>
#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;
}
}

View File

@ -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 <cinttypes>
#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

225
main.cpp
View File

@ -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<string,string> 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<string,string> 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);

View File

@ -10,6 +10,8 @@
#include <map>
#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;

View File

@ -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);
}