Add files via upload

The first attempt at uploading new files.
This commit is contained in:
dingusdev 2019-07-01 19:15:33 -07:00 committed by GitHub
parent d31fdb37bd
commit eaa517b63b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 7309 additions and 0 deletions

71
dingusppc.cbp Normal file
View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="dingusppc" />
<Option makefile="makefile" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/dingusppc" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-std=c++14" />
<Add option="-m32" />
<Add option="-g" />
</Compiler>
<Linker>
<Add option="-m32" />
</Linker>
</Target>
<Target title="Release">
<Option output="bin/Release/dingusppc" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-std=c++14" />
<Add option="-m32" />
</Compiler>
<Linker>
<Add option="-O3" />
<Add option="-m32" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wall" />
<Add option="-std=c++11" />
<Add option="-fexceptions" />
</Compiler>
<Unit filename="macioserial.cpp" />
<Unit filename="macioserial.h" />
<Unit filename="macscsi.cpp" />
<Unit filename="macscsi.h" />
<Unit filename="macswim3.cpp" />
<Unit filename="macswim3.h" />
<Unit filename="main.cpp" />
<Unit filename="mpc106.cpp" />
<Unit filename="mpc106.h" />
<Unit filename="openpic.cpp" />
<Unit filename="openpic.h" />
<Unit filename="poweropcodes.cpp" />
<Unit filename="ppcemumain.h" />
<Unit filename="ppcfpopcodes.cpp" />
<Unit filename="ppcgekkoopcodes.cpp" />
<Unit filename="ppcmemory.cpp" />
<Unit filename="ppcmemory.h" />
<Unit filename="ppcopcodes.cpp" />
<Unit filename="viacuda.cpp" />
<Unit filename="viacuda.h" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>

41
macioserial.cpp Normal file
View File

@ -0,0 +1,41 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the Serial Ports
// Based on the Zilog Z8530 SCC chip
#include <iostream>
#include <cinttypes>
#include "macioserial.h"
#include "ppcemumain.h"
uint32_t mac_serial_address;
uint8_t serial_write_byte;
uint8_t serial_read_byte;
void mac_serial_init(){
machine_iocontrolmem_mem[0x3013004] = 0x04;
machine_iocontrolmem_mem[0x3013009] = 0xC0;
machine_iocontrolmem_mem[0x301300B] = 0x08;
machine_iocontrolmem_mem[0x301300E] = 0x30;
machine_iocontrolmem_mem[0x301300F] = 0xF8;
machine_iocontrolmem_mem[0x3013010] = 0x44;
machine_iocontrolmem_mem[0x3013011] = 0x06;
}
void mac_serial_read(){
if (mac_serial_address >=0x3013020){
mac_serial_address -= 0x20;
}
machine_iocontrolmem_mem[mac_serial_address] = serial_read_byte;
}
void mac_serial_write(){
if (mac_serial_address >=0x3013020){
mac_serial_address -= 0x20;
}
serial_write_byte = machine_iocontrolmem_mem[mac_serial_address];
}

22
macioserial.h Normal file
View File

@ -0,0 +1,22 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the Serial Ports
// Based on the Zilog Z8530 SCC chip
#ifndef MAC_IO_SERIAL_H
#define MAC_IO_SERIAL_H
extern uint32_t mac_serial_address;
extern uint8_t serial_write_byte;
extern uint8_t serial_read_byte;
extern void mac_serial_init();
extern void mac_serial_read();
extern void mac_serial_write();
#endif

1
macscsi.c Normal file
View File

@ -0,0 +1 @@

31
macscsi.cpp Normal file
View File

@ -0,0 +1,31 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the SCSI
#include <iostream>
#include <cstring>
#include <cinttypes>
#include "ppcemumain.h"
#include "macscsi.h"
uint32_t macscsi_address;
uint8_t macscsi_write_byte;
uint8_t macscsi_read_byte;
void macscsi_init(){
}
void macscsi_read(){
}
void macscsi_write(){
}

21
macscsi.h Normal file
View File

@ -0,0 +1,21 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the SCSI
#ifndef MACSCSI_H_
#define MACSCSI_H_
extern uint32_t macscsi_address;
extern uint8_t macscsi_write_byte;
extern uint8_t macscsi_read_byte;
extern void macscsi_init();
extern void macscsi_read();
extern void macscsi_write();
#endif

29
macswim3.cpp Normal file
View File

@ -0,0 +1,29 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the Swim 3 Floppy Drive
#include <iostream>
#include <cinttypes>
#include "macswim3.h"
#include "ppcemumain.h"
uint32_t mac_swim3_address;
uint8_t swim3_write_byte;
uint8_t swim3_read_byte;
void mac_swim3_init(){
machine_iocontrolmem_mem[0x3015C00] = 0xF0;
}
void mac_swim3_read(){
swim3_read_byte = machine_iocontrolmem_mem[mac_swim3_address];
}
void mac_swim3_write(){
machine_iocontrolmem_mem[mac_swim3_address] = swim3_write_byte;
}

19
macswim3.h Normal file
View File

@ -0,0 +1,19 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
#ifndef MAC_SWIM3_H
#define MAC_SWIM3_H
extern uint32_t mac_swim3_address;
extern uint8_t swim3_write_byte;
extern uint8_t swim3_read_byte;
extern void mac_swim3_init();
extern void mac_swim3_read();
extern void mac_swim3_write();
#endif // MAC_IO_SERIAL_H

859
main.cpp Normal file
View File

@ -0,0 +1,859 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//The main runfile - main.cpp
//This is where the magic begins
#include <iostream>
#include <map>
#include <cstring>
#include <cinttypes>
#include <array>
#include <stdio.h>
#include <fstream>
#include <chrono>
#include <ctime>
#include <stdexcept>
#include "ppcemumain.h"
#include "macioserial.h"
#include "macswim3.h"
#include "ppcmemory.h"
#include "viacuda.h"
#include "mpc106.h"
#include "openpic.h"
//#include <vector>
#define max_16b_int 65535
#define max_32b_int 4294967295
#define ENDIAN_REVERSE16(x) (x >> 8) | (((x) & 0x00FF) << 8)
#define ENDIAN_REVERSE32(x) (x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24)
#define ENDIAN_REVERSE64(x) (x >> 56) | ((x & 0x00FF000000000000) >> 48) | ((x & 0x0000FF0000000000) >> 40) | ((x & 0x000000FF00000000) >> 32) | \
((x & 0x00000000FF000000) << 32) | ((x & 0x0000000000FF0000) << 40) | ((x & 0x000000000000FF00) << 48) | ((x & 0x00000000000000FF) << 56)
using namespace std;
SetPRS ppc_state;
bool grab_branch;
bool grab_exception;
bool grab_return;
uint32_t ppc_cur_instruction;
uint32_t ppc_effective_address;
uint32_t ppc_real_address;
uint32_t ppc_next_instruction_address;
uint32_t temp_address; //used for determining where memory ends up.
uint32_t return_value;
uint32_t pc_return_value;
//A pointer to a pointer, used for quick movement to one of the following
//memory areas. These are listed right below.
unsigned char * grab_array_ptr;
unsigned char * machine_sysram_mem;
unsigned char * machine_sysconfig_mem;
unsigned char * machine_upperiocontrol_mem;
unsigned char * machine_iocontrolcdma_mem;
unsigned char * machine_loweriocontrol_mem;
unsigned char * machine_interruptack_mem;
unsigned char * machine_iocontrolmem_mem;
unsigned char * machine_f8xxxx_mem;
unsigned char * machine_fexxxx_mem;
unsigned char * machine_fecxxx_mem;
unsigned char * machine_feexxx_mem;
unsigned char * machine_ff00xx_mem;
unsigned char * machine_ff80xx_mem;
unsigned char * machine_sysrom_mem;
uint32_t grab_sysram_size;
uint32_t grab_iocont_size;
uint32_t grab_sysrom_size;
uint32_t ram_size_set;
uint32_t prev_msr_state = 0;
uint32_t cur_msr_state = 0;
//MSR Flags
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;
clock_t clock_test_begin; //Used to make sure the TBR does not increment so quickly.
uint32_t write_opcode;
uint8_t write_char;
/*
//DISK VARIABLES
unsigned char * grab_disk_buf;
bool disk_inserted;
uint64_t disk_offset = 0;
uint32_t disk_word = 0;
*/
uint16_t rev_endian16(uint16_t insert_int){
return ENDIAN_REVERSE16(insert_int);
}
uint32_t rev_endian32(uint32_t insert_int){
return ENDIAN_REVERSE32(insert_int);
}
uint64_t rev_endian64(uint64_t insert_int){
return ENDIAN_REVERSE64(insert_int);
}
//Time Base Register Update Code
//TODO - Make this a bit less hacky somehow.
void ppc_tbr_update()
{
clock_t clock_test_current = clock();
uint32_t test_clock = ((uint32_t) (clock_test_current - clock_test_begin)) / CLOCKS_PER_SEC;
if (test_clock){
if (ppc_state.ppc_tbr[0] != 0xFFFFFFFF){
ppc_state.ppc_tbr[0]++;
}
else{
ppc_state.ppc_tbr[0] = 0;
if (ppc_state.ppc_tbr[1] !=0xFFFFFFFF){
ppc_state.ppc_tbr[1]++;
}
else{
ppc_state.ppc_tbr[1] = 0;
}
}
clock_test_begin = clock();
//Placeholder Decrementing Code
if(ppc_state.ppc_spr[22] > 0){
ppc_state.ppc_spr[22]--;
}
}
}
void ppc_expection_handler(uint32_t exception_type, uint32_t handle_args){
ppc_next_instruction_address = 0x0; //used to construct a new address
grab_exception = true;
printf("MSR VALUE: %x \n Exception Type: %x", ppc_state.ppc_msr, exception_type);
//Check ROM Exception Prefix
if (ppc_state.ppc_msr && 0x40){
ppc_next_instruction_address |= 0xFFF00000;
}
else{
ppc_next_instruction_address &= 0x0000FFFF;
}
switch(exception_type){
case 0x0100: //System Reset
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = ppc_state.ppc_msr;
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += 0x0100;
break;
/**
case 0x0200: //Machine Check
break;
case 0x0300: //DSI
break;
case 0x0400: //ISI
break;
**/
case 0x0500: //External Interrupt
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += 0x0500;
break;
case 0x0600: //Alignment Exception
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_state.ppc_spr[19] = ppc_cur_instruction;
ppc_next_instruction_address += 0x0600;
case 0x0700: //Program;
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
handle_args += 0x10000;
ppc_state.ppc_spr[27] = handle_args + (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += 0x0700;
break;
case 0x0C00: //Sys Call
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += 0x0C00;
break;
/**
case 0x0d: //Trace
break
**/
default:
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += exception_type;
}
}
//Initialize the PPC's registers.
void reg_init(){
for (uint32_t i = 0; i < 32; i++){
ppc_state.ppc_fpr[i] = 0;
}
ppc_state.ppc_pc = 0;
for (uint32_t i = 0; i < 32; i++){
ppc_state.ppc_gpr[i] = 0;
}
ppc_state.ppc_cr = 0;
ppc_state.ppc_fpscr = 0;
ppc_state.ppc_tbr[0] = 0;
ppc_state.ppc_tbr[1] = 0;
for (uint32_t i = 0; i < 1024; i++){
switch(i){
case 287:
//Identify as a G3
//Processor IDS
// 601 v1 - 00010001
// 603 v1 - 00030001
// 604 v1 - 00040001
// 603e v1 - 00060101
// 750 v1 - 00080200
ppc_state.ppc_spr[i] = 0x00080200;
break;
/**
case 528:
case 536:
ppc_state.ppc_spr[i] = 0x00001FFE;
break;
case 530:
case 538:
ppc_state.ppc_spr[i] = 0xC0001FFE;
break;
case 532:
case 540:
ppc_state.ppc_spr[i] = 0xE0001FFE;
break;
case 534:
case 542:
ppc_state.ppc_spr[i] = 0xF0001FFE;
break;
case 529:
case 531:
case 537:
case 539:
ppc_state.ppc_spr[i] = 0x00000002;
break;
case 533:
case 541:
ppc_state.ppc_spr[i] = 0xE0000002;
break;
case 535:
ppc_state.ppc_spr[i] = 0xF0000002;
break;
case 543:
ppc_state.ppc_spr[i] = 0x00000002;
break;
**/
default:
ppc_state.ppc_spr[i] = 0;
}
}
//Only bit 25 of the MSR is initially set on bootup.
ppc_state.ppc_msr = 0x40;
for (uint32_t i = 0; i < 16; i++){
ppc_state.ppc_sr[i] = 0;
}
}
//Debugging Functions
uint32_t reg_print(){
for (uint32_t i = 0; i < 32; i++){
printf("FPR %d : %I64u", i, ppc_state.ppc_fpr[i]);
}
ppc_state.ppc_pc = 0;
for (uint32_t i = 0; i < 32; i++){
printf("GPR %d : %d", i, ppc_state.ppc_gpr[i]);
}
printf("CR : %d", ppc_state.ppc_cr);
printf("FPSCR : %d", ppc_state.ppc_fpscr);
printf("TBR 0 : %d", ppc_state.ppc_tbr[0]);
printf("TBR 1 : %d", ppc_state.ppc_tbr[1]);
for (uint32_t i = 0; i < 1024; i++){
printf("SPR %d : %d", i, ppc_state.ppc_spr[i]);
}
printf("CR : %d", ppc_state.ppc_cr);
printf("MSR : %d", ppc_state.ppc_msr);
for (uint32_t i = 0; i < 16; i++){
printf("SR %d : %d", i, ppc_state.ppc_sr[i]);
}
return 0;
}
uint32_t reg_read(){
uint32_t grab_me = 0;
std::cout << hex << "TODO: Decide which register to read from; for now, which GPR?" << endl;
//printf("Which register to read from? 0 - GPR, 1 = FPR, 2 = CR, 3 = FPSCR");
std::cin >> hex >> grab_me;
if (grab_me < 32){
printf("GPR value: %d", ppc_state.ppc_gpr[grab_me]);
}
return 0;
}
uint32_t reg_write(){
uint32_t grab_me = 0;
std::cout << hex << "TODO: Decide which register to write to; for now, which GPR?" << endl;
//printf("Which register to write to? 0 - GPR, 1 = FPR, 2 = CR, 3 = FPSCR");
std::cin >> hex >> grab_me;
if (grab_me < 32){
printf("GPR value: %d", ppc_state.ppc_gpr[grab_me]);
}
return 0;
}
int main(int argc, char **argv)
{
ram_size_set = 0x4000000; //64 MB of RAM for the Mac
rom_file_begin = 0xFFF00000; //where to start storing ROM files in memory
pci_io_end = 0x83FFFFFF;
rom_file_setsize = 0x400000;
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;
}
**/
bool power_on = 1;
uint32_t opcode_entered = 0; //used for testing opcodes in playground
std::cout << "DingusPPC - Prototype 5bf3 (6/9/2019) " << endl;
std::cout << "Written by divingkatae, (c) 2019. " << endl;
std::cout << "This is not intended for general use. " << endl;
std::cout << "Use at your own discretion. " << endl;
//Open the ROM File.
ifstream romFile;
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();
return 1;
}
//Allocate memory for ROM, RAM, and I/O.
romFile.seekg(0, romFile.end);
rom_file_setsize = romFile.tellg();
printf("Rom SIZE: %d \n", rom_file_setsize);
romFile.seekg (0, romFile.beg);
/**
Allocate memory wisely.
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);
machine_iocontrolcdma_mem = (unsigned char*) calloc (8388608, 1);
machine_loweriocontrol_mem = (unsigned char*) calloc (33554432, 1);
machine_interruptack_mem = (unsigned char*) calloc (16, 1);
machine_iocontrolmem_mem = (unsigned char*) calloc (67108864, 1);
machine_f8xxxx_mem = (unsigned char*) calloc (4096, 1);
machine_fexxxx_mem = (unsigned char*) calloc (262144, 1);
machine_fecxxx_mem = (unsigned char*) calloc (4096, 1);
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);
memset(machine_sysram_mem, 0x0, 67108864);
memset(machine_sysconfig_mem, 0x0, 2048);
memset(machine_upperiocontrol_mem, 0x0, 8388607);
memset(machine_iocontrolcdma_mem, 0x0, 8388607);
memset(machine_interruptack_mem, 0x0, 16);
memset(machine_iocontrolmem_mem, 0x0, 67108864);
memset(machine_f8xxxx_mem, 0x0, 4096);
memset(machine_fexxxx_mem, 0x0, 262144);
memset(machine_fecxxx_mem, 0x0, 4096);
memset(machine_feexxx_mem, 0x0, 4096);
memset(machine_ff00xx_mem, 0x0, 4096);
memset(machine_ff80xx_mem, 0x0, 1048576);
grab_sysram_size = sizeof(machine_sysram_mem);
grab_sysrom_size = rom_file_setsize;
//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;
}
else if (ram_size_set > 0x20000000){
cerr << "RAM too big. Must be no more than 2 GB.\n";
return 1;
}
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)
};
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.read(configInfoOffset, 1);
uint32_t configInfoAddr = 0x300000 + (configInfoOffset << 8);
romFile.seekg (configInfoAddr, ios::beg);
romFile.read(memPPCBlock, sizeof(uint32_t)); //Only four chars needed to distinguish between codenames
std::string string_test = std::string(memPPCBlock);
//Just auto-iterate through the list
for (auto iter = PPCMac_ROMIdentity.begin(); iter != PPCMac_ROMIdentity.end(); ){
string redo_me = iter->first;
if (!string_test.compare(redo_me)){
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;
}
}
}
//Copy the contents of the IO data and the ROM to memory appropriate locations.
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;
}
*/
clock_test_begin = clock();
if (argc > 1){
string checker = argv[1];
cout << checker << endl;
if (checker == "fuzzer"){
//Brute force every instruction that the PPC can interpret.
//TODO: Change this so that this goes through user-specified instructions.
ppc_cur_instruction = 0xFFFFFFFF;
std::cout << "Testing Opcode: " << ppc_cur_instruction << endl;
while (ppc_cur_instruction > 0x00000000){
ppc_main_opcode();
ppc_cur_instruction--;
}
}
else if ((checker=="1")|(checker=="realtime")|(checker=="/realtime")|(checker=="-realtime")){
while (power_on){
cout << "PowerPC PC Address: " << hex << ppc_state.ppc_pc << endl;
quickinstruction_translate(ppc_state.ppc_pc);
ppc_main_opcode();
if (grab_branch & !grab_exception){
ppc_state.ppc_pc = ppc_next_instruction_address;
grab_branch = 0;
ppc_tbr_update();
}
else if (grab_return | grab_exception){
ppc_state.ppc_pc = ppc_next_instruction_address;
grab_exception = 0;
grab_return = 0;
ppc_tbr_update();
}
else{
ppc_state.ppc_pc += 4;
ppc_tbr_update();
}
ppc_cur_instruction = 0;
/*
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;
uint32_t elf_file_setsize = 0;
char elf_headerchk [4];
char elf_bformat [1];
char elf_machine [2];
char elf_memoffset [4];
elfFile.seekg(0, elfFile.end);
elf_file_setsize = elfFile.tellg();
elfFile.seekg (0, elfFile.beg);
if (elf_file_setsize < 45){
cerr << "Elf File TOO SMALL. Please make sure it's a legitimate file.";
return 1;
}
else if (elf_file_setsize > ram_size_set){
cerr << "Elf File TOO BIG. Please make sure it fits within memory.";
return 1;
}
//There's got to be a better way to get fields of info from an ELF file.
elfFile.seekg(0x0, ios::beg); //ELF file begins here
elfFile.read(elf_headerchk, 4);
elfFile.seekg(0x4, ios::cur);
elfFile.read(elf_bformat, 1);
elfFile.seekg(0x8, ios::cur);
elfFile.read(elf_machine, 2);
elfFile.seekg(0x6, ios::cur);
elfFile.read(elf_memoffset, 4);
elfFile.seekg (0, elfFile.beg);
bool elf_valid_check = (atoi(elf_headerchk) == 0x7F454C46) && (atoi(elf_bformat) == 1) &&\
((atoi(elf_machine) == 0) | (atoi(elf_machine) == 20));
if (!elf_valid_check){
cerr << "The ELF file inserted was not legitimate. Please try again." << endl;
return 1;
}
elfFile.read ((char *)machine_sysram_mem,ram_size_set);
if (argc > 2){
string elfname = string(argv[1]);
elfname = elfname + ".elf";
elfFile.open(elfname, ios::in|ios::binary);
}
else{
elfFile.open("test.elf", ios::in|ios::binary);
}
if (elfFile.fail()){
cerr << "Please insert the elf file before continuing.\n";
return 1;
}
ppc_state.ppc_pc = atoi(elf_memoffset);
while (power_on){
quickinstruction_translate(ppc_state.ppc_pc);
ppc_main_opcode();
if (grab_branch & !grab_exception){
ppc_state.ppc_pc = ppc_effective_address;
grab_branch = 0;
ppc_tbr_update();
}
else if (grab_return | grab_exception){
ppc_state.ppc_pc = ppc_next_instruction_address;
grab_exception = 0;
grab_return = 0;
ppc_tbr_update();
}
else if (ppc_cur_instruction == 0){
cout << "Opcode 0 executed. Shutting off the power before the flood even starts. \n" << endl;
power_on = 0; //Hack - Prevent flooding the log.
}
else{
ppc_state.ppc_pc += 4;
ppc_tbr_update();
}
ppc_cur_instruction = 0;
}
}
else if (checker=="assemble"){
if (argc > 2){
checker = argv[1];
}
else{
checker = "\\compile.txt";
}
ifstream inFile (checker, ios::binary | ios::ate);
if (!inFile) {
cerr << "Unable to open file for assembling.";
exit(1);
}
cout << "Insert Assembler Here! - TODO" << endl;
}
else if ((checker=="eso")|(checker=="/eso")|(checker=="-eso")){
std::cout << hex << "Ready to execute an opcode?" << endl;
string check_q;
cin >> check_q;
getline (cin, check_q);
if (check_q != "No"){
quickinstruction_translate(ppc_state.ppc_pc);
ppc_main_opcode();
if (grab_branch & !grab_exception){
ppc_state.ppc_pc = ppc_effective_address;
grab_branch = 0;
ppc_tbr_update();
}
else if (grab_return | grab_exception){
ppc_state.ppc_pc = ppc_next_instruction_address;
grab_exception = 0;
grab_return = 0;
ppc_tbr_update();
}
else{
ppc_state.ppc_pc += 4;
ppc_tbr_update();
}
ppc_cur_instruction = 0;
}
}
else if ((checker=="epo")|(checker=="/epo")|(checker=="-epo")){
std::cout << hex << "Ready to execute a page of opcodes?" << endl;
string check_q;
cin >> check_q;
getline (cin, check_q);
if (check_q != "No"){
for (int instructions_to_do = 0; instructions_to_do < 256; instructions_to_do++){
quickinstruction_translate(ppc_state.ppc_pc);
ppc_main_opcode();
if (grab_branch & !grab_exception){
ppc_state.ppc_pc = ppc_effective_address;
grab_branch = 0;
ppc_tbr_update();
}
else if (grab_return | grab_exception){
ppc_state.ppc_pc = ppc_next_instruction_address;
grab_exception = 0;
grab_return = 0;
ppc_tbr_update();
}
else{
ppc_state.ppc_pc += 4;
ppc_tbr_update();
}
ppc_cur_instruction = 0;
}
}
}
else if ((checker=="play")|(checker=="playground")|(checker=="/playground")|(checker=="-playground")){
std::cout << hex << "Enter any opcodes for the PPC you want here." << endl;
while (power_on){
cin >> hex >> opcode_entered;
//power off the PPC
if (opcode_entered == 0x00000000){
power_on = 0;
}
//print registers
else if (opcode_entered == 0x00000001){
reg_print();
}
else if (opcode_entered == 0x00000002){
reg_read();
}
else if (opcode_entered == 0x00000003){
reg_write();
}
//test another opcode
else{
ppc_cur_instruction = opcode_entered;
quickinstruction_translate(ppc_state.ppc_pc);
ppc_main_opcode();
if (grab_branch & !grab_exception){
ppc_state.ppc_pc = ppc_effective_address;
grab_branch = 0;
ppc_tbr_update();
}
else if (grab_return | grab_exception){
ppc_state.ppc_pc = ppc_next_instruction_address;
grab_exception = 0;
grab_return = 0;
ppc_tbr_update();
}
else{
ppc_state.ppc_pc += 4;
ppc_tbr_update();
}
ppc_cur_instruction = 0;
}
}
}
}
else{
std::cout << " " << endl;
std::cout << "Please enter one of the following commands when" << endl;
std::cout << "booting up DingusPPC... " << endl;
std::cout << " " << endl;
std::cout << " " << endl;
std::cout << "realtime - Run the emulator in real-time. " << endl;
std::cout << "loadelf - Load an ELF file to run from RAM. " << endl;
std::cout << "fuzzer - Test every single PPC opcode. " << endl;
std::cout << "eso - Execute a single opcode per key press. " << endl;
std::cout << "epo - Execute a page of opcodes per key press. " << endl;
std::cout << "playground - Mess around with and opcodes. " << endl;
//std::cout << "assembler - NOT YET IMPLEMENTED " << endl;
}
romFile.close();
//Free memory after the emulation is completed.
free(machine_sysram_mem);
free(machine_upperiocontrol_mem);
free(machine_iocontrolcdma_mem);
free(machine_loweriocontrol_mem);
free(machine_interruptack_mem);
free(machine_iocontrolmem_mem);
free(machine_f8xxxx_mem);
free(machine_fexxxx_mem);
free(machine_fecxxx_mem);
free(machine_feexxx_mem);
free(machine_ff00xx_mem);
free(machine_ff80xx_mem);
free(machine_sysrom_mem);
return 0;
}

50
makefile Normal file
View File

@ -0,0 +1,50 @@
OBJS = main.o macioserial.o macscsi.o macswim3.o mpc106.o openpic.o poweropcodes.o ppcfpopcodes.o ppcgekkoopcodes.o ppcmemory.o ppcopcodes.o viacuda.o
SOURCE = main.c macioserial.cpp macscsi.cpp macswim3.cpp mpc106.cpp openpic.cpp poweropcodes.cpp ppcfpopcodes.cpp ppcgekkoopcodes.cpp ppcmemory.cpp ppcopcodes.cpp viacuda.cpp
HEADER = macioserial.h macscsi.h macswim3.h mpc106.h openpic.h ppcemumain.h ppcmemory.h viacuda.h
OUT = dingusppc
CC = g++
FLAGS = -g -c -Wall
LFLAGS =
all: $(OBJS)
$(CC) -g $(OBJS) -o $(OUT) $(LFLAGS)
main.o: main.c
$(CC) $(FLAGS) main.c
macioserial.o: macioserial.cpp
$(CC) $(FLAGS) macioserial.cpp
macscsi.o: macscsi.cpp
$(CC) $(FLAGS) macscsi.cpp
macswim3.o: macswim3.cpp
$(CC) $(FLAGS) macswim3.cpp
mpc106.o: mpc106.cpp
$(CC) $(FLAGS) mpc106.cpp
openpic.o: openpic.cpp
$(CC) $(FLAGS) openpic.cpp
poweropcodes.o: poweropcodes.cpp
$(CC) $(FLAGS) poweropcodes.cpp
ppcfpopcodes.o: ppcfpopcodes.cpp
$(CC) $(FLAGS) ppcfpopcodes.cpp
ppcgekkoopcodes.o: ppcgekkoopcodes.cpp
$(CC) $(FLAGS) ppcgekkoopcodes.cpp
ppcmemory.o: ppcmemory.cpp
$(CC) $(FLAGS) ppcmemory.cpp
ppcopcodes.o: ppcopcodes.cpp
$(CC) $(FLAGS) ppcopcodes.cpp
viacuda.o: viacuda.cpp
$(CC) $(FLAGS) viacuda.cpp
clean:
rm -f $(OBJS) $(OUT)

1
mpc106.c Normal file
View File

@ -0,0 +1 @@

164
mpc106.cpp Normal file
View File

@ -0,0 +1,164 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the MPC106
#include <iostream>
#include <cstring>
#include <cinttypes>
#include "mpc106.h"
#include "ppcemumain.h"
#include "ppcmemory.h"
bool mpc106_address_map;
uint32_t mpc106_address;
uint32_t mpc_config_addr;
uint32_t mpc_config_dat;
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;
unsigned char* mpc106_regs;
void mpc106_init(){
mpc106_regs = (unsigned char*) calloc (256, 1);
memset(mpc106_regs, 0x0, 256);
//Initialize Vendor & Device IDs
mpc106_regs[0] = 0x57;
mpc106_regs[1] = 0x10;
mpc106_regs[2] = 0x02;
//PCI command + status
mpc106_regs[4] = 0x06;
mpc106_regs[6] = 0x80;
mpc106_regs[115] = 0xCD;
mpc106_regs[168] = 0x10;
mpc106_regs[169] = 0x00;
mpc106_regs[170] = 0x00;
mpc106_regs[171] = 0xFF;
mpc106_regs[172] = 0x0C;
mpc106_regs[173] = 0x06;
mpc106_regs[174] = 0x0C;
mpc106_regs[175] = 0x00;
}
void mpc106_write_device(uint32_t value){
}
void mpc106_read_device(uint32_t value, uint8_t bit_length){
}
void mpc106_read(){
uint8_t read_length = 4;
switch (mpc106_address){
case 0x8:
case 0x72:
case 0x73:
case 0xA0:
case 0xA3:
read_length = 1;
break;
case 0x0:
case 0x2:
case 0x4:
case 0x6:
case 0x70:
read_length = 2;
break;
case 0x80:
case 0x84:
case 0x88:
case 0x8C:
case 0x90:
case 0x94:
case 0x98:
case 0x9C:
case 0xF0:
case 0xF4:
case 0xF8:
case 0xFC:
read_length = 4;
}
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;
switch (mpc106_address){
case 0x8:
case 0x70:
case 0x72:
case 0x73:
case 0xA0:
write_length = 1;
break;
case 0x0:
case 0x2:
case 0x4:
case 0x6:
write_length = 2;
break;
case 0x80:
case 0x84:
case 0x88:
case 0x8C:
case 0x90:
case 0x94:
case 0x98:
case 0x9C:
case 0xF0:
case 0xF4:
case 0xF8:
case 0xFC:
write_length = 4;
}
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;
}
}

32
mpc106.h Normal file
View File

@ -0,0 +1,32 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the MPC106
#ifndef MPC106_H_
#define MPC106_H_
#define mpc106_addres_map_a 1
#define mpc106_addres_map_b 0
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 unsigned char* mpc106_regs;
extern void mpc106_init();
extern void mpc106_read();
extern void mpc106_write(uint32_t write_word);
#endif

34
openpic.cpp Normal file
View File

@ -0,0 +1,34 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the OPENPIC
#include <iostream>
#include <cstring>
#include <cinttypes>
#include "ppcemumain.h"
uint32_t openpic_address;
uint32_t openpic_write_word;
uint32_t openpic_read_word;
void openpic_init(){
for (int i = 0x40004; i < 0x7FFFF; i++){
if (i % 16 == 0){
i += 4;
}
machine_upperiocontrol_mem[i] = 0xFF;
}
}
void openpic_read(){
machine_upperiocontrol_mem[openpic_address] = openpic_read_word;
}
void openpic_write(){
openpic_write_word = machine_upperiocontrol_mem[openpic_address];
}

21
openpic.h Normal file
View File

@ -0,0 +1,21 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the OPENPIC
#ifndef OPENPIC_H_
#define OPENPIC_H_
extern uint32_t openpic_address;
extern uint32_t openpic_write_word;
extern uint32_t openpic_read_word;
extern void openpic_init();
extern void openpic_read();
extern void openpic_write();
#endif

795
poweropcodes.cpp Normal file
View File

@ -0,0 +1,795 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
// The Power-specific opcodes for the processor - ppcopcodes.cpp
// Any shared opcodes are in ppcopcodes.cpp
#include <iostream>
#include <array>
#include <stdio.h>
#include <stdexcept>
#include "ppcemumain.h"
#include "ppcmemory.h"
#include <cmath>
#include <limits>
void power_abs(){
ppc_grab_regsda();
if (ppc_result_a == 0x80000000){
ppc_result_d = ppc_result_a;
}
else{
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_store_result_regd();
}
void power_absdot(){
ppc_grab_regsda();
if (ppc_result_a == 0x80000000){
ppc_result_d = ppc_result_a;
}
else{
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_changecrf0(ppc_result_d);
ppc_store_result_regd();
}
void power_abso(){
ppc_grab_regsda();
if (ppc_result_a == 0x80000000){
ppc_result_d = ppc_result_a;
ppc_state.ppc_spr[1] |= 0x40000000;
}
else{
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_store_result_regd();
}
void power_absodot(){
ppc_grab_regsda();
if (ppc_result_a == 0x80000000){
ppc_result_d = ppc_result_a;
ppc_state.ppc_spr[1] |= 0x40000000;
}
else{
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_changecrf0(ppc_result_d);
ppc_store_result_regd();
}
void power_clcs(){
ppc_grab_regsda();
switch(reg_a){
case 12:
case 13:
case 14:
case 15:
ppc_result_d = 65535;
break;
default:
ppc_result_d = 0;
}
ppc_store_result_regd();
}
void power_clcsdot(){
switch(reg_a){
case 12:
case 13:
case 14:
case 15:
ppc_result_d = 65535;
break;
default:
ppc_result_d = 0;
}
ppc_changecrf0(ppc_result_d);
printf("Does RC do anything here? (TODO) \n");
ppc_store_result_regd();
}
void power_div(){
ppc_grab_regsdab();
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
ppc_store_result_regd();
}
void power_divdot(){
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
}
void power_divo(){
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
}
void power_divodot(){
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
}
void power_divs(){
ppc_grab_regsdab();
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
ppc_store_result_regd();
}
void power_divsdot(){
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
}
void power_divso(){
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
}
void power_divsodot(){
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
}
void power_doz(){
ppc_grab_regsdab();
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
ppc_result_d = 0;
}
else{
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
}
ppc_store_result_rega();
}
void power_dozdot(){
ppc_grab_regsdab();
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
ppc_result_d = 0;
}
else{
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
}
ppc_changecrf0(ppc_result_d);
ppc_store_result_rega();
}
void power_dozo(){
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
ppc_result_d = 0;
}
else{
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
}
}
void power_dozodot(){
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
ppc_result_d = 0;
}
else{
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
}
}
void power_dozi(){
ppc_grab_regsdab();
if (((int32_t)ppc_result_a) > simm){
ppc_result_d = 0;
}
else{
ppc_result_d = ~ppc_result_a + simm + 1;
}
ppc_store_result_rega();
}
void power_lscbx(){
ppc_grab_regsdab();
uint32_t bytes_copied = 0;
bool match_found = false;
uint32_t shift_amount = 0;
uint8_t byte_compared = (uint8_t)((ppc_state.ppc_spr[1] & 0xFF00) >> 8);
if ((ppc_state.ppc_spr[1] & 0x7f) == 0){
return;
}
uint32_t bytes_to_load = (ppc_state.ppc_spr[1] & 0x7f) + 1;
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
do{
ppc_effective_address++;
bytes_to_load--;
if (match_found == false){
switch(shift_amount){
case 0:
address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1);
ppc_result_d = (ppc_result_d & 0x00FFFFFF) | (return_value << 24);
ppc_store_result_regd();
break;
case 1:
address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1);
ppc_result_d = (ppc_result_d & 0xFF00FFFF) | (return_value << 16);
ppc_store_result_regd();
break;
case 2:
address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1);
ppc_result_d = (ppc_result_d & 0xFFFF00FF) | (return_value << 8);
ppc_store_result_regd();
break;
case 3:
address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1);
ppc_result_d = (ppc_result_d & 0xFFFFFF00) | return_value;
ppc_store_result_regd();
break;
}
bytes_copied++;
}
if (((uint8_t)return_value) == byte_compared){
break;
}
return_value = 0;
if (shift_amount == 3){
shift_amount = 0;
reg_d = (reg_d + 1) & 0x1F;
}
else{
shift_amount++;
}
}while (bytes_to_load > 0);
ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xFFFFFF80) | bytes_copied;
ppc_store_result_regd();
}
void power_lscbxdot(){
printf("OOPS! Placeholder!!! \n");
}
void power_maskg(){
ppc_grab_regssab();
uint32_t mask_start = ppc_result_d & 31;
uint32_t mask_end = ppc_result_b & 31;
uint32_t insert_mask = 0;
if (mask_start < (mask_end + 1)){
for (uint32_t i = mask_start; i < mask_end; i++){
insert_mask |= (0x80000000 >> i);
}
}
else if (mask_start == (mask_end + 1)){
insert_mask = 0xFFFFFFFF;
}
else{
insert_mask = 0xFFFFFFFF;
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++){
insert_mask &= (~(0x80000000 >> i));
}
}
ppc_result_a = insert_mask;
ppc_store_result_rega();
}
void power_maskgdot(){
ppc_grab_regssab();
uint32_t mask_start = ppc_result_d & 31;
uint32_t mask_end = ppc_result_b & 31;
uint32_t insert_mask = 0;
if (mask_start < (mask_end + 1)){
for (uint32_t i = mask_start; i < mask_end; i++){
insert_mask |= (0x80000000 >> i);
}
}
else if (mask_start == (mask_end + 1)){
insert_mask = 0xFFFFFFFF;
}
else{
insert_mask = 0xFFFFFFFF;
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++){
insert_mask &= (~(0x80000000 >> i));
}
}
ppc_result_a = insert_mask;
ppc_store_result_rega();
}
void power_maskir(){
ppc_grab_regssab();
uint32_t mask_insert = ppc_result_a;
uint32_t insert_rot = 0x80000000;
do{
if (ppc_result_b & insert_rot){
mask_insert &= ~insert_rot;
mask_insert |= (ppc_result_d & insert_rot);
}
insert_rot = insert_rot>> 1;
}while(insert_rot > 0);
ppc_result_a = (ppc_result_d & ppc_result_b);
ppc_store_result_rega();
}
void power_maskirdot(){
ppc_grab_regssab();
uint32_t mask_insert = ppc_result_a;
uint32_t insert_rot = 0x80000000;
do{
if (ppc_result_b & insert_rot){
mask_insert &= ~insert_rot;
mask_insert |= (ppc_result_d & insert_rot);
}
insert_rot = insert_rot>> 1;
}while(insert_rot > 0);
ppc_result_a = (ppc_result_d & ppc_result_b);
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_mul(){
ppc_grab_regsdab();
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
ppc_result_d = ((uint32_t)(product >> 32));
ppc_state.ppc_spr[0] = ((uint32_t)(product));
ppc_store_result_regd();
}
void power_muldot(){
ppc_grab_regsdab();
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
ppc_result_d = ((uint32_t)(product >> 32));
ppc_state.ppc_spr[0] = ((uint32_t)(product));
ppc_changecrf0(ppc_result_d);
ppc_store_result_regd();
}
void power_mulo(){
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
ppc_result_d = ((uint32_t)(product >> 32));
ppc_state.ppc_spr[0] = ((uint32_t)(product));
}
void power_mulodot(){
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
ppc_result_d = ((uint32_t)(product >> 32));
ppc_state.ppc_spr[0] = ((uint32_t)(product));
}
void power_nabs(){
ppc_grab_regsda();
ppc_result_d = (0x80000000 | ppc_result_a);
ppc_store_result_regd();
}
void power_nabsdot(){
ppc_result_d = (0x80000000 | ppc_result_a);
}
void power_nabso(){
ppc_result_d = (0x80000000 | ppc_result_a);
}
void power_nabsodot(){
ppc_result_d = (0x80000000 | ppc_result_a);
}
void power_rlmi(){
ppc_grab_regssab();
rot_mb = (ppc_cur_instruction >> 6) & 31;
rot_me = (ppc_cur_instruction >> 1) & 31;
uint32_t rot_amt = ppc_result_b & 31;
uint32_t insert_mask = 0;
if (rot_mb < (rot_me + 1)){
for (uint32_t i = rot_mb; i < rot_me; i++){
insert_mask |= (0x80000000 >> i);
}
}
else if (rot_mb == (rot_me + 1)){
insert_mask = 0xFFFFFFFF;
}
else{
insert_mask = 0xFFFFFFFF;
for (uint32_t i = (rot_me + 1); i < (rot_mb - 1); i++){
insert_mask &= (~(0x80000000 >> i));
}
}
uint32_t step2 = (ppc_result_d << rot_amt) | (ppc_result_d >> rot_amt);
ppc_result_a = step2 & insert_mask;
ppc_store_result_rega();
}
void power_rrib(){
ppc_grab_regssab();
if (ppc_result_d & 0x80000000){
ppc_result_a |= (0x80000000 >> ppc_result_b);
}
else{
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
}
ppc_store_result_rega();
}
void power_rribdot(){
ppc_grab_regssab();
if (ppc_result_d & 0x80000000){
ppc_result_a |= (0x80000000 >> ppc_result_b);
}
else{
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
}
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_sle(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
ppc_state.ppc_spr[0] = insert_final & insert_mask;
ppc_result_a = insert_final & insert_mask;
ppc_store_result_rega();
}
void power_sledot(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
ppc_state.ppc_spr[0] = insert_final & insert_mask;
ppc_result_a = insert_final & insert_mask;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_sleq(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end;
ppc_state.ppc_spr[0] = insert_start;
ppc_store_result_rega();
}
void power_sleqdot(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end;
ppc_state.ppc_spr[0] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_sliq(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end & insert_mask;
ppc_state.ppc_spr[0] = insert_start;
ppc_store_result_rega();
}
void power_sliqdot(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end & insert_mask;
ppc_state.ppc_spr[0] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_slliq(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end;
ppc_state.ppc_spr[0] = insert_start;
ppc_store_result_rega();
}
void power_slliqdot(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end;
ppc_state.ppc_spr[0] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_sllq(){
printf("OOPS! Placeholder!!! \n");
}
void power_sllqdot(){
printf("OOPS! Placeholder!!! \n");
}
void power_slq(){
printf("OOPS! Placeholder!!! \n");
}
void power_slqdot(){
printf("OOPS! Placeholder!!! \n");
}
void power_sraiq(){
printf("OOPS! Placeholder!!! \n");
}
void power_sraiqdot(){
printf("OOPS! Placeholder!!! \n");
}
void power_sraq(){
printf("OOPS! Placeholder!!! \n");
}
void power_sraqdot(){
printf("OOPS! Placeholder!!! \n");
}
void power_sre(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
ppc_state.ppc_spr[0] = insert_final & insert_mask;
ppc_result_a = insert_final;
ppc_store_result_rega();
}
void power_sredot(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
ppc_state.ppc_spr[0] = insert_final & insert_mask;
ppc_result_a = insert_final;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_srea(){
printf("OOPS! Placeholder!!! \n");
}
void power_sreadot(){
printf("OOPS! Placeholder!!! \n");
}
void power_sreq(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
rot_sh = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_sh; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end;
ppc_state.ppc_spr[0] = insert_start;
ppc_store_result_rega();
}
void power_sreqdot(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
rot_sh = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_sh; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end;
ppc_state.ppc_spr[0] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_sriq(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end;
ppc_state.ppc_spr[0] = insert_start;
ppc_store_result_rega();
}
void power_sriqdot(){
ppc_grab_regssa();
uint32_t insert_mask = 0;
rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
}
ppc_result_a = insert_end;
ppc_state.ppc_spr[0] = insert_start;
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_srliq(){
printf("OOPS! Placeholder!!! \n");
}
void power_srliqdot(){
printf("OOPS! Placeholder!!! \n");
}
void power_srlq(){
printf("OOPS! Placeholder!!! \n");
}
void power_srlqdot(){
printf("OOPS! Placeholder!!! \n");
}
void power_srq(){
printf("OOPS! Placeholder!!! \n");
}
void power_srqdot(){
printf("OOPS! Placeholder!!! \n");
}

762
ppcemumain.h Normal file
View File

@ -0,0 +1,762 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
#ifndef PPCEMUMAIN_H_
#define PPCEMUMAIN_H_
#include <map>
enum endian_switch {big_end = 0, little_end = 1};
typedef void (*PPCOpcode)(void);
/**
Except for the floating-point registers, all registers require
32 bits for representation. Floating-point registers need 64 bits.
gpr = General Purpose Register
fpr = Floating Point (FP) Register
cr = Condition Register
tbr = Time Base Register
fpscr = FP Status and Condition Register
spr = Special Register
msr = Machine State Register
sr = Segment Register
**/
typedef struct struct_ppc_state {
uint64_t ppc_fpr [32];
uint32_t ppc_pc; //Referred as the CIA in the PPC manual
uint32_t ppc_gpr [32];
uint32_t ppc_cr;
uint32_t ppc_fpscr;
uint32_t ppc_tbr [2];
uint32_t ppc_spr [1024];
uint32_t ppc_msr;
uint32_t ppc_sr [16];
bool ppc_reserve; //reserve bit used for lwarx and stcwx
} SetPRS;
extern SetPRS ppc_state;
/**
typedef struct struct_ppc64_state {
uint64_t ppc_fpr [32];
uint64_t ppc_pc; //Referred as the CIA in the PPC manual
uint64_t ppc_gpr [32];
uint32_t ppc_cr;
uint32_t ppc_fpscr;
uint32_t ppc_tbr [2];
uint64_t ppc_spr [1024];
uint32_t ppc_msr;
uint32_t ppc_sr [16];
bool ppc_reserve; //reserve bit used for lwarx and stcwx
} SetPRS64;
extern SetPRS64 ppc_state64;
**/
/**
Specific SPRS to be weary of:
USER MODEL
SPR 1 - XER
SPR 8 - Link Register / Branch
b0 - Summary Overflow
b1 - Overflow
b2 - Carry
b25-31 - Number of bytes to transfer
SPR 9 - Count
SUPERVISOR MODEL
19 is the Data Address Register
22 is the Decrementer
26, 27 are the Save and Restore Registers (SRR0, SRR1)
272 - 275 are the SPRGs
284 - 285 for writing to the TBR's.
528 - 535 are the Instruction BAT registers
536 - 543 are the Data BAT registers
**/
extern uint32_t return_value; //used for loading from memory
extern uint32_t pc_return_value; //used for getting instructions
extern uint32_t opcode_value; //used for interpreting opcodes
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;
//Additional steps to prevent overflow?
extern int32_t add_result;
extern int32_t sidiv_result;
extern int32_t simult_result;
extern uint32_t uiadd_result;
extern uint32_t uidiv_result;
extern uint32_t uimult_result;
extern uint64_t uiproduct;
extern int64_t siproduct;
extern int32_t word_copy_location;
extern uint32_t strwrd_replace_value;
extern uint32_t crf_d;
extern uint32_t crf_s;
extern uint32_t reg_s;
extern uint32_t reg_d;
extern uint32_t reg_a;
extern uint32_t reg_b;
extern uint32_t reg_c;
extern uint32_t xercon;
extern uint32_t cmp_c;
extern uint32_t crm;
extern uint32_t br_bo;
extern uint32_t br_bi;
extern uint32_t rot_sh;
extern uint32_t rot_mb;
extern uint32_t rot_me;
extern uint32_t uimm;
extern uint32_t not_this;
extern uint32_t grab_sr;
extern uint32_t grab_inb; //This is for grabbing the number of immediate bytes for loading and storing
extern uint32_t grab_d; //This is for grabbing d from Store and Load instructions
extern uint32_t ppc_to;
extern int32_t simm;
extern int32_t adr_li;
extern int32_t br_bd;
//Used for GP calcs
extern uint32_t ppc_result_a;
extern uint32_t ppc_result_b;
extern uint32_t ppc_result_c;
extern uint32_t ppc_result_d;
//Used for FP calcs
extern uint64_t ppc_result64_a;
extern uint64_t ppc_result64_b;
extern uint64_t ppc_result64_c;
extern uint64_t ppc_result64_d;
extern uint16_t rev_endian16(uint16_t insert_int);
extern uint32_t uimm_rev_endian16(uint32_t insert_int);
extern int32_t simm_rev_endian16(int32_t insert_int);
extern uint32_t rev_endian32(uint32_t insert_int);
extern uint64_t rev_endian64(uint64_t insert_int);
extern bool grab_branch;
extern bool grab_exception;
extern bool grab_return;
extern bool is_601; //For PowerPC 601 Emulation
extern bool is_gekko; //For GameCube Emulation
extern bool is_altivec; //For Altivec Emulation
extern bool is_64bit; //For PowerPC G5 Emulation
//uint64_t virtual_address;
//Important Addressing Integers
extern uint64_t ppc_virtual_address; //It's 52 bits
extern uint32_t ppc_cur_instruction;
extern uint32_t ppc_effective_address;
extern uint32_t ppc_real_address;
extern uint32_t ppc_next_instruction_address;
extern uint32_t temp_address; //used for determining where memory ends up.
//Function prototypes
void reg_init();
uint32_t reg_print();
uint32_t reg_read();
uint32_t reg_write();
void ppc_illegalop();
void ppc_opcode4();
void ppc_opcode16();
void ppc_opcode18();
void ppc_opcode19();
void ppc_opcode31();
void ppc_opcode59();
void ppc_opcode63();
extern void ppc_grab_regsda();
extern void ppc_grab_regsdb();
extern void ppc_grab_regssa();
extern void ppc_grab_regssb();
extern void ppc_grab_regsdab();
extern void ppc_grab_regssab();
extern void ppc_grab_regsdasimm();
extern void ppc_grab_regsdauimm();
extern void ppc_grab_regssasimm();
extern void ppc_grab_regssauimm();
extern void ppc_grab_regsfpdb();
extern void ppc_grab_regsfpdab();
extern void ppc_grab_regsfpdia();
extern void ppc_grab_regsfpdiab();
extern void ppc_grab_regsfpsia();
extern void ppc_grab_regsfpsiab();
extern void ppc_store_result_regd();
extern void ppc_store_result_rega();
extern void ppc_store_sfpresult();
extern void ppc_store_dfpresult();
void ppc_carry(uint32_t a, uint32_t b);
void ppc_setsoov(uint32_t a, uint32_t b);
void ppc_changecrf0(uint32_t set_result);
void ppc_tbr_update();
void ppc_expection_handler(uint32_t exception_type, uint32_t handle_args);
//MEMORY DECLARATIONS
extern unsigned char * machine_sysram_mem;
extern unsigned char * machine_sysconfig_mem;
//Mapped to 0x68000000 - extern unsigned char * machine_68kemu_mem;
extern unsigned char * machine_upperiocontrol_mem;
extern unsigned char * machine_iocontrolcdma_mem;
extern unsigned char * machine_loweriocontrol_mem;
extern unsigned char * machine_interruptack_mem;
extern unsigned char * machine_iocontrolmem_mem;
extern unsigned char * machine_f8xxxx_mem;
extern unsigned char * machine_fexxxx_mem;
extern unsigned char * machine_fecxxx_mem;
extern unsigned char * machine_feexxx_mem;
extern unsigned char * machine_ff00xx_mem;
extern unsigned char * machine_ff80xx_mem;
extern unsigned char * machine_sysrom_mem;
//The functions used by the PowerPC processor
extern void ppc_bcctr();
extern void ppc_bcctrl();
extern void ppc_bclr();
extern void ppc_bclrl();
extern void ppc_crand();
extern void ppc_crandc();
extern void ppc_creqv();
extern void ppc_crnand();
extern void ppc_crnor();
extern void ppc_cror();
extern void ppc_crorc();
extern void ppc_crxor();
extern void ppc_isync();
extern void ppc_add();
extern void ppc_adddot();
extern void ppc_addo();
extern void ppc_addodot();
extern void ppc_addc();
extern void ppc_addcdot();
extern void ppc_addco();
extern void ppc_addcodot();
extern void ppc_adde();
extern void ppc_addedot();
extern void ppc_addeo();
extern void ppc_addeodot();
extern void ppc_addme();
extern void ppc_addmedot();
extern void ppc_addmeo();
extern void ppc_addmeodot();
extern void ppc_addze();
extern void ppc_addzedot();
extern void ppc_addzeo();
extern void ppc_addzeodot();
extern void ppc_and();
extern void ppc_anddot();
extern void ppc_andc();
extern void ppc_andcdot();
extern void ppc_cmp();
extern void ppc_cmpl();
extern void ppc_cntlzw();
extern void ppc_cntlzwdot();
extern void ppc_dcbf();
extern void ppc_dcbi();
extern void ppc_dcbst();
extern void ppc_dcbt();
extern void ppc_dcbtst();
extern void ppc_dcbz();
extern void ppc_divw();
extern void ppc_divwdot();
extern void ppc_divwo();
extern void ppc_divwodot();
extern void ppc_divwu();
extern void ppc_divwudot();
extern void ppc_divwuo();
extern void ppc_divwuodot();
extern void ppc_eieio();
extern void ppc_eqv();
extern void ppc_eqvdot();
extern void ppc_extsb();
extern void ppc_extsbdot();
extern void ppc_extsh();
extern void ppc_extshdot();
extern void ppc_icbi();
extern void ppc_mftb();
extern void ppc_lhzux();
extern void ppc_lhzx();
extern void ppc_lhaux();
extern void ppc_lhax();
extern void ppc_lhbrx();
extern void ppc_lwarx();
extern void ppc_lbzux();
extern void ppc_lbzx();
extern void ppc_lwbrx();
extern void ppc_lwzux();
extern void ppc_lwzx();
extern void ppc_mcrxr();
extern void ppc_mfcr();
extern void ppc_mulhwu();
extern void ppc_mulhwudot();
extern void ppc_mulhw();
extern void ppc_mulhwdot();
extern void ppc_mullw();
extern void ppc_mullwdot();
extern void ppc_mullwo();
extern void ppc_mullwodot();
extern void ppc_nand();
extern void ppc_nanddot();
extern void ppc_neg();
extern void ppc_negdot();
extern void ppc_nego();
extern void ppc_negodot();
extern void ppc_nor();
extern void ppc_nordot();
extern void ppc_or();
extern void ppc_ordot();
extern void ppc_orc();
extern void ppc_orcdot();
extern void ppc_slw();
extern void ppc_slwdot();
extern void ppc_srw();
extern void ppc_srwdot();
extern void ppc_sraw();
extern void ppc_srawdot();
extern void ppc_srawi();
extern void ppc_srawidot();
extern void ppc_stbx();
extern void ppc_stbux();
extern void ppc_stfiwx();
extern void ppc_sthx();
extern void ppc_sthux();
extern void ppc_sthbrx();
extern void ppc_stwx();
extern void ppc_stwcx();
extern void ppc_stwux();
extern void ppc_stwbrx();
extern void ppc_subf();
extern void ppc_subfdot();
extern void ppc_subfo();
extern void ppc_subfodot();
extern void ppc_subfc();
extern void ppc_subfcdot();
extern void ppc_subfco();
extern void ppc_subfcodot();
extern void ppc_subfe();
extern void ppc_subfedot();
extern void ppc_subfme();
extern void ppc_subfmedot();
extern void ppc_subfze();
extern void ppc_subfzedot();
extern void ppc_sync();
extern void ppc_tlbia();
extern void ppc_tlbie();
extern void ppc_tlbli();
extern void ppc_tlbld();
extern void ppc_tlbsync();
extern void ppc_tw();
extern void ppc_xor();
extern void ppc_xordot();
extern void ppc_lswi();
extern void ppc_lswx();
extern void ppc_stswi();
extern void ppc_stswx();
extern void ppc_mfsr();
extern void ppc_mfsrin();
extern void ppc_mtsr();
extern void ppc_mtsrin();
extern void ppc_mtcrf();
extern void ppc_mfmsr();
extern void ppc_mfspr();
extern void ppc_mtmsr();
extern void ppc_mtspr();
extern void ppc_mtfsb0();
extern void ppc_mtfsb1();
extern void ppc_mcrfs();
extern void ppc_mtfsb0dot();
extern void ppc_mtfsb1dot();
extern void ppc_fmr();
extern void ppc_mffs();
extern void ppc_mtfsf();
extern void ppc_addi();
extern void ppc_addic();
extern void ppc_addicdot();
extern void ppc_addis();
extern void ppc_andidot();
extern void ppc_andisdot();
extern void ppc_b();
extern void ppc_ba();
extern void ppc_bl();
extern void ppc_bla();
extern void ppc_bc();
extern void ppc_bca();
extern void ppc_bcl();
extern void ppc_bcla();
extern void ppc_cmpi();
extern void ppc_cmpli();
extern void ppc_lbz();
extern void ppc_lbzu();
extern void ppc_lha();
extern void ppc_lhau();
extern void ppc_lhz();
extern void ppc_lhzu();
extern void ppc_lwz();
extern void ppc_lwzu();
extern void ppc_lmw();
extern void ppc_mulli();
extern void ppc_ori();
extern void ppc_oris();
extern void ppc_rfi();
extern void ppc_rlwimi();
extern void ppc_rlwinm();
extern void ppc_rlwnm();
extern void ppc_sc();
extern void ppc_stb();
extern void ppc_stbu();
extern void ppc_sth();
extern void ppc_sthu();
extern void ppc_stw();
extern void ppc_stwu();
extern void ppc_stmw();
extern void ppc_subfic();
extern void ppc_twi();
extern void ppc_xori();
extern void ppc_xoris();
extern void ppc_lfs();
extern void ppc_lfsu();
extern void ppc_lfsux();
extern void ppc_lfsx();
extern void ppc_lfd();
extern void ppc_lfdu();
extern void ppc_stfs();
extern void ppc_stfsu();
extern void ppc_stfsux();
extern void ppc_stfd();
extern void ppc_stfdu();
extern void ppc_stfdx();
extern void ppc_stfdux();
extern void ppc_fadd();
extern void ppc_fsub();
extern void ppc_fmult();
extern void ppc_fdiv();
extern void ppc_fadds();
extern void ppc_fsubs();
extern void ppc_fmults();
extern void ppc_fdivs();
extern void ppc_fmadd();
extern void ppc_fmsub();
extern void ppc_fnmadd();
extern void ppc_fnmsub();
extern void ppc_fmadds();
extern void ppc_fmsubs();
extern void ppc_fnmadds();
extern void ppc_fnmsubs();
extern void ppc_fabs();
extern void ppc_fneg();
extern void ppc_fsel();
extern void ppc_fres();
extern void ppc_fsqrts();
extern void ppc_fsqrt();
extern void ppc_frsqrte();
extern void ppc_frsp();
extern void ppc_fctiw();
extern void ppc_fctiwz();
extern void ppc_fcmpo();
extern void ppc_fcmpu();
//Power-specific instructions
extern void power_abs();
extern void power_absdot();
extern void power_abso();
extern void power_absodot();
extern void power_clcs();
extern void power_clcsdot();
extern void power_div();
extern void power_divdot();
extern void power_divo();
extern void power_divodot();
extern void power_divs();
extern void power_divsdot();
extern void power_divso();
extern void power_divsodot();
extern void power_doz();
extern void power_dozdot();
extern void power_dozo();
extern void power_dozodot();
extern void power_dozi();
extern void power_lscbx();
extern void power_lscbxdot();
extern void power_maskg();
extern void power_maskgdot();
extern void power_maskir();
extern void power_maskirdot();
extern void power_mul();
extern void power_muldot();
extern void power_mulo();
extern void power_mulodot();
extern void power_nabs();
extern void power_nabsdot();
extern void power_nabso();
extern void power_nabsodot();
extern void power_rlmi();
extern void power_rrib();
extern void power_rribdot();
extern void power_sle();
extern void power_sledot();
extern void power_sleq();
extern void power_sleqdot();
extern void power_sliq();
extern void power_sliqdot();
extern void power_slliq();
extern void power_slliqdot();
extern void power_sllq();
extern void power_sllqdot();
extern void power_slq();
extern void power_slqdot();
extern void power_sraiq();
extern void power_sraiqdot();
extern void power_sraq();
extern void power_sraqdot();
extern void power_sre();
extern void power_sredot();
extern void power_srea();
extern void power_sreadot();
extern void power_sreq();
extern void power_sreqdot();
extern void power_sriq();
extern void power_sriqdot();
extern void power_srliq();
extern void power_srliqdot();
extern void power_srlq();
extern void power_srlqdot();
extern void power_srq();
extern void power_srqdot();
//Gekko instructions
extern void ppc_psq_l();
extern void ppc_psq_lu();
extern void ppc_psq_st();
extern void ppc_psq_stu();
//AltiVec instructions
//64-bit instructions
//G5+ instructions
extern void ppc_main_opcode();
//A listing of all of the available opcodes on the PPC.
static std::map<uint8_t, PPCOpcode> OpcodeGrabber =
{{0, &ppc_illegalop}, {1, &ppc_illegalop}, {2, &ppc_illegalop}, {3, &ppc_twi},
{4, &ppc_opcode4}, {5, &ppc_illegalop}, {6, &ppc_illegalop}, {7, &ppc_mulli},
{8, &ppc_subfic}, {9, &power_dozi}, {10, &ppc_cmpli}, {11, &ppc_cmpi},
{12, &ppc_addic}, {13, &ppc_addicdot}, {14, &ppc_addi}, {15, &ppc_addis},
{16, &ppc_opcode16}, {17, &ppc_sc}, {18, &ppc_opcode18}, {19, &ppc_opcode19},
{20, &ppc_rlwimi}, {21, &ppc_rlwinm}, {22, &power_rlmi}, {23, &ppc_rlwnm},
{24, &ppc_ori}, {25, &ppc_oris}, {26, &ppc_xori}, {27, &ppc_xoris},
{28, &ppc_andidot}, {29, &ppc_andisdot}, {30, &ppc_illegalop}, {31, &ppc_opcode31},
{32, &ppc_lwz}, {33, &ppc_lwzu}, {34, &ppc_lbz}, {35, &ppc_lbzu},
{36, &ppc_stw}, {37, &ppc_stwu}, {38, &ppc_stb}, {39, &ppc_stbu},
{40, &ppc_lhz}, {41, &ppc_lhzu}, {42, &ppc_lha}, {42, &ppc_lhau},
{44, &ppc_sth}, {45, &ppc_sthu}, {46, &ppc_lmw}, {47, &ppc_stmw},
{48, &ppc_lfs}, {49, &ppc_lfsu}, {50, &ppc_lfd}, {51, &ppc_lfdu},
{52, &ppc_stfs}, {53, &ppc_stfsu}, {54, &ppc_stfd}, {55, &ppc_stfdu},
{56, &ppc_psq_l}, {57, &ppc_psq_lu}, {58, &ppc_illegalop}, {59, &ppc_illegalop},
{60, &ppc_psq_st}, {61, &ppc_psq_stu}, {62, &ppc_illegalop}, {63, &ppc_opcode63}};
//All of the opcodes possible are generated from the first 6 bits
//of each instruction given by the processor.
/**These next few tables combine the last 11 bits of an instruction
to generate an opcode. These means different opcodes for up to
four different forms of a function.
There are four big families of opcodes
Opcode 19 - General Conditional Register Functions
Opcode 31 - General Integer Functions
Opcode 59 - Single-Precision Floating-Point Functions
Opcode 63 - Double-Precision Floating-Point Functions
The last two have instructions that don't neatly feat into one
table, partially due to instructions that use either 6 or 11 bits
for the instruction.
**/
static std::map<uint8_t, PPCOpcode> SubOpcode16Grabber=
{{0, &ppc_bc}, {1, &ppc_bcl}, {2, &ppc_bca}, {3, &ppc_bcla}
};
static std::map<uint8_t, PPCOpcode> SubOpcode18Grabber=
{{0, &ppc_b}, {1, &ppc_bl}, {2, &ppc_ba}, {3, &ppc_bla}
};
static std::map<uint16_t, PPCOpcode> SubOpcode19Grabber=
{{32, &ppc_bclr}, {33, &ppc_bclrl}, {66, &ppc_crnor}, {100, &ppc_rfi},
{258, &ppc_crandc}, {300, &ppc_isync}, {386, &ppc_crxor}, {450, &ppc_crnand},
{514, &ppc_crand}, {578, &ppc_creqv}, {834, &ppc_crorc}, {898, &ppc_cror},
{1056, &ppc_bcctr}, {1057, &ppc_bcctrl}
};
static std::map<uint16_t, PPCOpcode> SubOpcode31Grabber=
{{0, &ppc_cmp}, {8, &ppc_tw}, {16, &ppc_subfc}, {17, &ppc_subfcdot},
{20, &ppc_addc}, {21, &ppc_addcdot}, {22, &ppc_mulhwu}, {23, &ppc_mulhwudot},
{38, &ppc_mfcr}, {40, &ppc_lwarx}, {46, &ppc_lwzx}, {48, &ppc_slw},
{49, &ppc_slwdot}, {52, &ppc_cntlzw}, {53, &ppc_cntlzwdot}, {56, &ppc_and},
{57, &ppc_anddot}, {58, &power_maskg}, {59, &power_maskgdot},
{64, &ppc_cmpl}, {80, &ppc_subf}, {81, &ppc_subfdot},
{108, &ppc_dcbst}, {110, &ppc_lwzux}, {120, &ppc_andc}, {121, &ppc_andcdot},
{150, &ppc_mulhw}, {151, &ppc_mulhwdot}, {166, &ppc_mfmsr}, {172, &ppc_dcbf},
{174, &ppc_lbzx}, {208, &ppc_neg}, {209, &ppc_negdot},
{214, &power_mul}, {215, &power_mulo}, {238, &ppc_lbzux},
{248, &ppc_nor}, {249, &ppc_nordot}, {272, &ppc_subfe}, {273, &ppc_subfedot},
{276, &ppc_adde}, {277, &ppc_addedot}, {288, &ppc_mtcrf}, {292, &ppc_mtmsr},
{301, &ppc_stwcx}, {302, &ppc_stwx}, {304, &power_slq}, {305, &power_slqdot},
{306, &power_sle}, {307, &power_sledot}, {366, &ppc_stwux},
{368, &power_sliq}, {400, &ppc_subfze},
{401, &ppc_subfzedot}, {404, &ppc_addze}, {405, &ppc_addzedot}, {420, &ppc_mtsr},
{430, &ppc_stbx}, {432, &power_sllq}, {433, &power_sllqdot}, {434, &power_sleq},
{436, &power_sleqdot}, {464, &ppc_subfme}, {465, &ppc_subfmedot}, {468, &ppc_addme},
{469, &ppc_addmedot}, {470, &ppc_mullw}, {471, &ppc_mullwdot}, {484, &ppc_mtsrin},
{492, &ppc_dcbtst}, {494, &ppc_stbux}, {496, &power_slliq}, {497, &power_slliqdot},
{528, &power_doz}, {529, &power_dozdot}, {532, &ppc_add}, {533, &ppc_adddot},
{554, &power_lscbx}, {555, &power_lscbxdot}, {556, &ppc_dcbt},
{558, &ppc_lhzx}, {568, &ppc_eqv}, {569, &ppc_eqvdot}, {612, &ppc_tlbie},
{622, &ppc_lhzux}, {632, &ppc_xor}, {633, &ppc_xordot}, {662, &power_div},
{663, &power_divdot}, {678, &ppc_mfspr}, {686, &ppc_lhax},
{720, &power_abs}, {721, &power_absdot}, {726, &power_divs}, {727, &power_divsdot},
{740, &ppc_tlbia}, {742, &ppc_mftb}, {750, &ppc_lhaux}, {814, &ppc_sthx},
{824, &ppc_orc}, {825, &ppc_orcdot}, {878, &ppc_sthx},
{888, &ppc_or}, {889, &ppc_ordot}, {918, &ppc_divwu}, {919, &ppc_divwudot},
{934, &ppc_mtspr}, {940, &ppc_dcbi}, {952, &ppc_nand}, {953, &ppc_nanddot},
{976, &power_nabs}, {977, &power_nabsdot}, {982, &ppc_divw}, {983, &ppc_divwdot},
{1024, &ppc_mcrxr}, {1040, &ppc_subfco}, {1041, &ppc_subfcodot}, {1044, &ppc_addco},
{1045, &ppc_addcodot}, {1062, &power_clcs}, {1063, &power_clcsdot}, {1066, &ppc_lswx},
{1068, &ppc_lwbrx}, {1070, &ppc_lfsx}, {1072, &ppc_srw}, {1073, &ppc_srwdot},
{1074, &power_rrib}, {1075, &power_rribdot}, {1082, &power_maskir}, {1083, &power_maskirdot},
{1104, &ppc_subfo}, {1105, &ppc_subfodot}, {1134, &ppc_lfsux}, {1190, &ppc_mfsr},
{1194, &ppc_lswi}, {1196, &ppc_isync}, {1232, &ppc_nego}, {1233, &ppc_negodot},
{1238, &power_mulo}, {1239, &power_mulodot},
{1300, &ppc_addeo}, {1301, &ppc_addeodot}, {1318, &ppc_mfsrin}, {1322, &ppc_stswx},
{1324, &ppc_stwbrx}, {1328, &power_srq}, {1329, &power_srqdot}, {1330, &power_sre},
{1331, &power_sredot}, {1390, &ppc_stfsux}, {1392, &power_sriq}, {1393, &power_sriqdot},
{1428, &ppc_addzeo}, {1429, &ppc_addzeodot}, {1450, &ppc_stswi}, {1454, &ppc_stfdx},
{1456, &power_srlq}, {1457, &power_srlqdot}, {1458, &power_sreq}, {1459, &power_sreqdot},
{1492, &ppc_addmeo}, {1493, &ppc_addmeodot},
{1494, &ppc_mullwo}, {1495, &ppc_mullwodot}, {1518, &ppc_stfdux}, {1520, &power_srliq},
{1521, &power_srliqdot},{1552, &power_dozo}, {1553, &power_dozodot}, {1556, &ppc_addo},
{1557, &ppc_addodot}, {1580, &ppc_lhbrx}, {1584, &ppc_sraw}, {1585, &ppc_srawdot},
{1648, &ppc_srawi}, {1649, &ppc_srawidot}, {1686, &power_divo}, {1687, &power_divodot},
{1708, &ppc_eieio}, {1744, &power_abso}, {1745, &power_absodot},
{1750, &power_divso}, {1751, &power_divsodot}, {1836, &ppc_sthbrx},
{1840, &power_sraq}, {1841, &power_sraqdot}, {1842, &power_srea}, {1843, &power_sreadot},
{1844, &ppc_extsh}, {1845, &ppc_extshdot}, {1904, &power_sraiq}, {1905, &power_sraiqdot},
{1908, &ppc_extsb}, {1909, &ppc_extsbdot}, {1942, &ppc_divwuo},
{1943, &ppc_divwuodot}, {1956, &ppc_tlbld}, {1964, &ppc_icbi}, {1966, &ppc_stfiwx},
{2000, &power_nabso}, {2001, &power_nabsodot}, {2006, &ppc_divwo}, {2007, &ppc_divwodot},
{2020, &ppc_tlbli}, {2028, &ppc_dcbz}
};
static std::map<uint16_t, PPCOpcode> SubOpcode59Grabber=
{{36, &ppc_fdivs}, {40, &ppc_fsubs}, {42, &ppc_fadds}, {44, &ppc_fsqrts}, {48, &ppc_frsp},
{50, &ppc_fmults}, {56, &ppc_fmsubs}, {58, &ppc_fmadds}, {60, &ppc_fnmsubs}, {62, &ppc_fnmadds},
{114, &ppc_fmults}, {120, &ppc_fmsubs}, {122, &ppc_fmadds}, {124, &ppc_fnmsubs}, {126, &ppc_fnmadds},
{178, &ppc_fmults}, {184, &ppc_fmsubs}, {186, &ppc_fmadds}, {188, &ppc_fnmsubs}, {190, &ppc_fnmadds},
{242, &ppc_fmults}, {248, &ppc_fmsubs}, {250, &ppc_fmadds}, {252, &ppc_fnmsubs}, {254, &ppc_fnmadds},
{306, &ppc_fmults}, {312, &ppc_fmsubs}, {314, &ppc_fmadds}, {316, &ppc_fnmsubs}, {318, &ppc_fnmadds},
{370, &ppc_fmults}, {376, &ppc_fmsubs}, {378, &ppc_fmadds}, {380, &ppc_fnmsubs}, {382, &ppc_fnmadds},
{434, &ppc_fmults}, {440, &ppc_fmsubs}, {442, &ppc_fmadds}, {444, &ppc_fnmsubs}, {446, &ppc_fnmadds},
{498, &ppc_fmults}, {504, &ppc_fmsubs}, {506, &ppc_fmadds}, {508, &ppc_fnmsubs}, {510, &ppc_fnmadds},
{562, &ppc_fmults}, {568, &ppc_fmsubs}, {570, &ppc_fmadds}, {572, &ppc_fnmsubs}, {574, &ppc_fnmadds},
{626, &ppc_fmults}, {632, &ppc_fmsubs}, {634, &ppc_fmadds}, {636, &ppc_fnmsubs}, {638, &ppc_fnmadds},
{690, &ppc_fmults}, {696, &ppc_fmsubs}, {698, &ppc_fmadds}, {700, &ppc_fnmsubs}, {702, &ppc_fnmadds},
{754, &ppc_fmults}, {752, &ppc_fmsubs}, {754, &ppc_fmadds}, {764, &ppc_fnmsubs}, {766, &ppc_fnmadds},
{818, &ppc_fmults}, {824, &ppc_fmsubs}, {826, &ppc_fmadds}, {828, &ppc_fnmsubs}, {830, &ppc_fnmadds},
{882, &ppc_fmults}, {888, &ppc_fmsubs}, {890, &ppc_fmadds}, {892, &ppc_fnmsubs}, {894, &ppc_fnmadds},
{946, &ppc_fmults}, {952, &ppc_fmsubs}, {954, &ppc_fmadds}, {956, &ppc_fnmsubs}, {958, &ppc_fnmadds},
{1010, &ppc_fmults}, {1016, &ppc_fmsubs}, {1018, &ppc_fmadds}, {1020, &ppc_fnmsubs}, {1022, &ppc_fnmadds},
{1074, &ppc_fmults}, {1080, &ppc_fmsubs}, {1082, &ppc_fmadds}, {1084, &ppc_fnmsubs}, {1086, &ppc_fnmadds},
{1138, &ppc_fmults}, {1144, &ppc_fmsubs}, {1146, &ppc_fmadds}, {1148, &ppc_fnmsubs}, {1150, &ppc_fnmadds},
{1202, &ppc_fmults}, {1208, &ppc_fmsubs}, {1210, &ppc_fmadds}, {1212, &ppc_fnmsubs}, {1214, &ppc_fnmadds},
{1266, &ppc_fmults}, {1272, &ppc_fmsubs}, {1274, &ppc_fmadds}, {1276, &ppc_fnmsubs}, {1278, &ppc_fnmadds},
{1330, &ppc_fmults}, {1336, &ppc_fmsubs}, {1338, &ppc_fmadds}, {1340, &ppc_fnmsubs}, {1342, &ppc_fnmadds},
{1394, &ppc_fmults}, {1400, &ppc_fmsubs}, {1402, &ppc_fmadds}, {1404, &ppc_fnmsubs}, {1406, &ppc_fnmadds},
{1458, &ppc_fmults}, {1464, &ppc_fmsubs}, {1466, &ppc_fmadds}, {1468, &ppc_fnmsubs}, {1470, &ppc_fnmadds},
{1522, &ppc_fmults}, {1528, &ppc_fmsubs}, {1530, &ppc_fmadds}, {1532, &ppc_fnmsubs}, {1534, &ppc_fnmadds},
{1586, &ppc_fmults}, {1592, &ppc_fmsubs}, {1594, &ppc_fmadds}, {1596, &ppc_fnmsubs}, {1598, &ppc_fnmadds},
{1650, &ppc_fmults}, {1656, &ppc_fmsubs}, {1658, &ppc_fmadds}, {1660, &ppc_fnmsubs}, {1662, &ppc_fnmadds},
{1714, &ppc_fmults}, {1720, &ppc_fmsubs}, {1722, &ppc_fmadds}, {1724, &ppc_fnmsubs}, {1726, &ppc_fnmadds},
{1778, &ppc_fmults}, {1784, &ppc_fmsubs}, {1786, &ppc_fmadds}, {1788, &ppc_fnmsubs}, {1790, &ppc_fnmadds},
{1842, &ppc_fmults}, {1848, &ppc_fmsubs}, {1850, &ppc_fmadds}, {1852, &ppc_fnmsubs}, {1854, &ppc_fnmadds},
{1906, &ppc_fmults}, {1912, &ppc_fmsubs}, {1914, &ppc_fmadds}, {1916, &ppc_fnmsubs}, {1918, &ppc_fnmadds},
{1970, &ppc_fmults}, {1976, &ppc_fmsubs}, {1978, &ppc_fmadds}, {1980, &ppc_fnmsubs}, {1982, &ppc_fnmadds},
{2034, &ppc_fmults}, {2040, &ppc_fmsubs}, {2042, &ppc_fmadds}, {2044, &ppc_fnmsubs}, {2046, &ppc_fnmadds}
};
static std::map<uint16_t, PPCOpcode> SubOpcode63Grabber=
{{0, &ppc_fcmpu}, {24, &ppc_frsp}, {28, &ppc_fctiw}, {30, &ppc_fctiwz}, {36, &ppc_fdiv},
{40, &ppc_fsub}, {42, &ppc_fadd}, {44, &ppc_fsqrt}, {50, &ppc_fmult},
{52, &ppc_frsqrte}, {56, &ppc_fmsub}, {58, &ppc_fmadd}, {60, &ppc_fnmsub},
{62, &ppc_fnmadd}, {64, &ppc_fcmpo}, {76, &ppc_mtfsb1}, {77, &ppc_mtfsb1dot}, {80, &ppc_fneg},
{114, &ppc_fmult}, {120, &ppc_fmsub}, {122, &ppc_fmadd}, {124, &ppc_fnmsub}, {126, &ppc_fnmadd},
{128, &ppc_mcrfs}, {140, &ppc_mtfsb0}, {141, &ppc_mtfsb0dot},{144, &ppc_fmr},
{178, &ppc_fmult}, {184, &ppc_fmsub}, {186, &ppc_fmadd}, {188, &ppc_fnmsub}, {190, &ppc_fnmadd},
{242, &ppc_fmult}, {248, &ppc_fmsub}, {250, &ppc_fmadd}, {252, &ppc_fnmsub}, {254, &ppc_fnmadd},
{306, &ppc_fmult}, {312, &ppc_fmsub}, {314, &ppc_fmadd}, {316, &ppc_fnmsub}, {318, &ppc_fnmadd},
{370, &ppc_fmult}, {376, &ppc_fmsub}, {378, &ppc_fmadd}, {380, &ppc_fnmsub}, {382, &ppc_fnmadd},
{434, &ppc_fmult}, {440, &ppc_fmsub}, {442, &ppc_fmadd}, {444, &ppc_fnmsub}, {446, &ppc_fnmadd},
{498, &ppc_fmult}, {504, &ppc_fmsub}, {506, &ppc_fmadd}, {508, &ppc_fnmsub}, {510, &ppc_fnmadd},
{528, &ppc_fabs},
{562, &ppc_fmult}, {568, &ppc_fmsub}, {570, &ppc_fmadd}, {572, &ppc_fnmsub}, {574, &ppc_fnmadd},
{626, &ppc_fmult}, {632, &ppc_fmsub}, {634, &ppc_fmadd}, {636, &ppc_fnmsub}, {638, &ppc_fnmadd},
{690, &ppc_fmult}, {696, &ppc_fmsub}, {698, &ppc_fmadd}, {700, &ppc_fnmsub}, {702, &ppc_fnmadd},
{754, &ppc_fmult}, {752, &ppc_fmsub}, {754, &ppc_fmadd}, {764, &ppc_fnmsub}, {766, &ppc_fnmadd},
{818, &ppc_fmult}, {824, &ppc_fmsub}, {826, &ppc_fmadd}, {828, &ppc_fnmsub}, {830, &ppc_fnmadd},
{882, &ppc_fmult}, {888, &ppc_fmsub}, {890, &ppc_fmadd}, {892, &ppc_fnmsub}, {894, &ppc_fnmadd},
{946, &ppc_fmult}, {952, &ppc_fmsub}, {954, &ppc_fmadd}, {956, &ppc_fnmsub}, {958, &ppc_fnmadd},
{1010, &ppc_fmult}, {1016, &ppc_fmsub}, {1018, &ppc_fmadd}, {1020, &ppc_fnmsub}, {1022, &ppc_fnmadd},
{1074, &ppc_fmult}, {1080, &ppc_fmsub}, {1082, &ppc_fmadd}, {1084, &ppc_fnmsub}, {1086, &ppc_fnmadd},
{1138, &ppc_fmult}, {1144, &ppc_fmsub}, {1146, &ppc_fmadd}, {1148, &ppc_fnmsub}, {1150, &ppc_fnmadd},
{1166, &ppc_mffs},
{1202, &ppc_fmult}, {1208, &ppc_fmsub}, {1210, &ppc_fmadd}, {1212, &ppc_fnmsub}, {1214, &ppc_fnmadd},
{1266, &ppc_fmult}, {1272, &ppc_fmsub}, {1274, &ppc_fmadd}, {1276, &ppc_fnmsub}, {1278, &ppc_fnmadd},
{1330, &ppc_fmult}, {1336, &ppc_fmsub}, {1338, &ppc_fmadd}, {1340, &ppc_fnmsub}, {1342, &ppc_fnmadd},
{1394, &ppc_fmult}, {1400, &ppc_fmsub}, {1402, &ppc_fmadd}, {1404, &ppc_fnmsub}, {1406, &ppc_fnmadd},
{1422, &ppc_mffs},
{1458, &ppc_fmult}, {1464, &ppc_fmsub}, {1466, &ppc_fmadd}, {1468, &ppc_fnmsub}, {1470, &ppc_fnmadd},
{1522, &ppc_fmult}, {1528, &ppc_fmsub}, {1530, &ppc_fmadd}, {1532, &ppc_fnmsub}, {1534, &ppc_fnmadd},
{1586, &ppc_fmult}, {1592, &ppc_fmsub}, {1594, &ppc_fmadd}, {1596, &ppc_fnmsub}, {1598, &ppc_fnmadd},
{1650, &ppc_fmult}, {1656, &ppc_fmsub}, {1658, &ppc_fmadd}, {1660, &ppc_fnmsub}, {1662, &ppc_fnmadd},
{1714, &ppc_fmult}, {1720, &ppc_fmsub}, {1722, &ppc_fmadd}, {1724, &ppc_fnmsub}, {1726, &ppc_fnmadd},
{1778, &ppc_fmult}, {1784, &ppc_fmsub}, {1786, &ppc_fmadd}, {1788, &ppc_fnmsub}, {1790, &ppc_fnmadd},
{1842, &ppc_fmult}, {1848, &ppc_fmsub}, {1850, &ppc_fmadd}, {1852, &ppc_fnmsub}, {1854, &ppc_fnmadd},
{1906, &ppc_fmult}, {1912, &ppc_fmsub}, {1914, &ppc_fmadd}, {1916, &ppc_fnmsub}, {1918, &ppc_fnmadd},
{1970, &ppc_fmult}, {1976, &ppc_fmsub}, {1978, &ppc_fmadd}, {1980, &ppc_fnmsub}, {1982, &ppc_fnmadd},
{2034, &ppc_fmult}, {2040, &ppc_fmsub}, {2042, &ppc_fmadd}, {2044, &ppc_fnmsub}, {2046, &ppc_fnmadd}
};
#endif // PPCEMUMAIN_H

679
ppcfpopcodes.cpp Normal file
View File

@ -0,0 +1,679 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
// The opcodes for the processor - ppcopcodes.cpp
#include <iostream>
#include <map>
#include <unordered_map>
#include <cinttypes>
#include <array>
#include <stdio.h>
#include <stdexcept>
#include "ppcemumain.h"
#include "ppcmemory.h"
#include <cmath>
#include <limits>
//Used for FP calcs
uint64_t ppc_result64_a;
uint64_t ppc_result64_b;
uint64_t ppc_result64_c;
uint64_t ppc_result64_d;
double snan = std::numeric_limits<double>::signaling_NaN();
double qnan = std::numeric_limits<double>::quiet_NaN();
//Storage and register retrieval functions for the floating point functions.
void ppc_store_sfpresult(){
ppc_state.ppc_fpr[reg_d] = (uint64_t)ppc_result_d;
}
void ppc_store_dfpresult(){
ppc_state.ppc_fpr[reg_d] = ppc_result64_d;
}
void ppc_grab_regsfpdb(){
reg_d = (ppc_cur_instruction >> 21) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
ppc_result64_b = ppc_state.ppc_fpr[reg_b];
}
void ppc_grab_regsfpdiab(){
reg_d = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
ppc_result_a = ppc_state.ppc_gpr[reg_a];
ppc_result_b = ppc_state.ppc_gpr[reg_b];
}
void ppc_grab_regsfpdia(){
reg_d = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
ppc_result_a = ppc_state.ppc_gpr[reg_a];
}
void ppc_grab_regsfpsia(){
reg_s = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
ppc_result_d = ppc_state.ppc_gpr[reg_s];
ppc_result_a = ppc_state.ppc_gpr[reg_a];
}
void ppc_grab_regsfpsiab(){
reg_s = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
ppc_result64_d = ppc_state.ppc_fpr[reg_s];
ppc_result_a = ppc_state.ppc_gpr[reg_a];
ppc_result_b = ppc_state.ppc_gpr[reg_b];
}
void ppc_grab_regsfpsab(){
reg_s = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
ppc_result64_d = ppc_state.ppc_fpr[reg_s];
ppc_result64_a = ppc_state.ppc_fpr[reg_a];
ppc_result64_b = ppc_state.ppc_fpr[reg_b];
}
void ppc_grab_regsfpdab(){
reg_d = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
ppc_result64_a = ppc_state.ppc_fpr[reg_a];
ppc_result64_b = ppc_state.ppc_fpr[reg_b];
}
void ppc_grab_regsfpdac(){
reg_d = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_c = (ppc_cur_instruction >> 6) & 31;
ppc_result64_a = ppc_state.ppc_fpr[reg_a];
ppc_result64_c = ppc_state.ppc_fpr[reg_c];
}
void ppc_grab_regsfpdabc(){
reg_d = (ppc_cur_instruction >> 21) & 31;
reg_a = (ppc_cur_instruction >> 16) & 31;
reg_b = (ppc_cur_instruction >> 11) & 31;
reg_c = (ppc_cur_instruction >> 6) & 31;
ppc_result64_a = ppc_state.ppc_fpr[reg_a];
ppc_result64_b = ppc_state.ppc_fpr[reg_b];
ppc_result64_c = ppc_state.ppc_fpr[reg_c];
}
//Floating Point Arithmetic
void ppc_fadd(){
ppc_grab_regsfpdab();
double testd1 = (double)ppc_result64_a;
double testd2 = (double)ppc_result64_b;
double testd3 = testd1 + testd2;
ppc_result64_d = (uint64_t)testd3;
ppc_store_dfpresult();
}
void ppc_fsub(){
ppc_grab_regsfpdab();
double testd1 = (double)ppc_result64_a;
double testd2 = (double)ppc_result64_b;
double testd3 = testd1 - testd2;
ppc_result64_d = (uint64_t)testd3;
ppc_store_dfpresult();
}
void ppc_fmult(){
ppc_grab_regsfpdac();
double testd1 = (double)ppc_result64_a;
double testd2 = (double)ppc_result64_c;
double testd3 = testd1 * testd2;
ppc_result64_d = (uint64_t)testd3;
ppc_store_dfpresult();
}
void ppc_fdiv(){
ppc_grab_regsfpdab();
double testd1 = (double)ppc_result64_a;
double testd2 = (double)ppc_result64_b;
double testd3 = testd1 / testd2;
ppc_result64_d = (uint64_t)testd3;
ppc_store_dfpresult();
}
void ppc_fmadd(){
ppc_grab_regsfpdabc();
double testd1 = (double)ppc_result64_a;
double testd2 = (double)ppc_result64_b;
double testd3 = (double)ppc_result64_c;
double testd4 = (testd1 * testd3) + testd2;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
}
void ppc_fmsub(){
ppc_grab_regsfpdabc();
double testd1 = (double)ppc_result64_a;
double testd2 = (double)ppc_result64_b;
double testd3 = (double)ppc_result64_c;
double testd4 = (testd1 * testd3) - testd2;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
}
void ppc_fnmadd(){
ppc_grab_regsfpdabc();
double testd1 = (double)ppc_result64_a;
double testd2 = (double)ppc_result64_b;
double testd3 = (double)ppc_result64_c;
double testd4 = -((testd1 * testd3) + testd2);
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
}
void ppc_fnmsub(){
ppc_grab_regsfpdabc();
double testd1 = (double)ppc_result64_a;
double testd2 = (double)ppc_result64_b;
double testd3 = (double)ppc_result64_c;
double testd4 = -((testd1 * testd3) - testd2);
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
}
void ppc_fadds(){
ppc_grab_regsfpdab();
float testd1 = (float)ppc_result64_a;
float testd2 = (float)ppc_result64_b;
float testd3 = testd1 + testd2;
ppc_result64_d = (uint64_t)testd3;
ppc_store_dfpresult();
}
void ppc_fsubs(){
ppc_grab_regsfpdab();
float testd1 = (float)ppc_result64_a;
float testd2 = (float)ppc_result64_b;
float testd3 = testd1 - testd2;
ppc_result64_d = (uint64_t)testd3;
ppc_store_dfpresult();
}
void ppc_fmults(){
ppc_grab_regsfpdac();
float testf1 = (float)ppc_result64_a;
float testf2 = (float)ppc_result64_c;
float testf3 = testf1 * testf2;
ppc_result64_d = (uint64_t)testf3;
ppc_store_dfpresult();
}
void ppc_fdivs(){
ppc_grab_regsfpdab();
float testf1 = (float)ppc_result64_a;
float testf2 = (float)ppc_result64_b;
float testf3 = testf1 / testf2;
ppc_result64_d = (uint64_t)testf3;
ppc_store_dfpresult();
}
void ppc_fmadds(){
ppc_grab_regsfpdabc();
float testf1 = (float)ppc_result64_a;
float testf2 = (float)ppc_result64_b;
float testf3 = (float)ppc_result64_c;
float testf4 = (testf1 * testf3) + testf2;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
}
void ppc_fmsubs(){
ppc_grab_regsfpdabc();
float testf1 = (float)ppc_result64_a;
float testf2 = (float)ppc_result64_b;
float testf3 = (float)ppc_result64_c;
float testf4 = (testf1 * testf3) - testf2;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
}
void ppc_fnmadds(){
ppc_grab_regsfpdabc();
float testf1 = (float)ppc_result64_a;
float testf2 = (float)ppc_result64_b;
float testf3 = (float)ppc_result64_c;
float testf4 = -((testf1 * testf3) + testf2);
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
}
void ppc_fnmsubs(){
ppc_grab_regsfpdabc();
float testf1 = (float)ppc_result64_a;
float testf2 = (float)ppc_result64_b;
float testf3 = (float)ppc_result64_c;
float testf4 = -((testf1 * testf3) - testf2);
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
}
void ppc_fabs(){
ppc_grab_regsfpdb();
double testd1 = (double)ppc_result64_b;
ppc_result64_d = (uint64_t)(abs(testd1));
ppc_store_dfpresult();
}
void ppc_fneg(){
ppc_grab_regsfpdb();
double testd1 = (double)ppc_result64_a;
double testd3 = -testd1;
ppc_result64_d = (double)testd3;
ppc_store_dfpresult();
}
void ppc_fsel(){
ppc_grab_regsfpdabc();
double testd1 = (double)ppc_result64_a;
double testd2 = (double)ppc_result64_b;
double testd3 = (double)ppc_result64_c;
if (testd1 >= 0.0){
ppc_result64_d = (uint64_t)testd3;
}
else{
ppc_result64_d = (uint64_t)testd2;
}
ppc_store_dfpresult();
}
void ppc_fsqrt(){
ppc_grab_regsfpdb();
double test = (double)ppc_result64_b;
std::sqrt(test);
ppc_result64_d = (uint64_t)test;
ppc_store_dfpresult();
}
void ppc_fsqrts(){
ppc_grab_regsfpdb();
uint32_t test = (uint32_t)ppc_result64_b;
test += 127 << 23;
test >>= 1;
ppc_result64_d = (uint64_t)test;
ppc_store_dfpresult();
}
void ppc_frsqrte(){
ppc_grab_regsfpdb();
double testd2 = (double)ppc_result64_b;
for (int i = 0; i < 10; i++){
testd2 = testd2 * (1.5 - (testd2 * .5) * testd2 * testd2);
}
ppc_result64_d = (uint64_t) testd2;
ppc_store_dfpresult();
}
void ppc_frsp(){
ppc_grab_regsfpdb();
double testd2 = (double)ppc_result64_b;
float testf2 = (float) testd2;
ppc_result64_d = (uint64_t) testf2;
ppc_store_dfpresult();
}
void ppc_fres(){
ppc_grab_regsfpdb();
float testf2 = (float)ppc_result64_b;
testf2 = 1/testf2;
ppc_result64_d = (uint64_t) testf2;
ppc_store_dfpresult();
}
void ppc_fctiw(){
//PLACEHOLDER!
ppc_grab_regsfpdiab();
double testd1 = (double)ppc_result64_b;
ppc_result_d = (uint32_t)(testd1);
ppc_store_result_regd();
}
void ppc_fctiwz(){
//PLACEHOLDER!
ppc_grab_regsfpdiab();
double testd1 = (double)ppc_result64_a;
ppc_result_d = (uint32_t)(testd1);
ppc_store_result_regd();
}
//Floating Point Store and Load
void ppc_lfs(){
ppc_grab_regsfpdia();
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
ppc_result64_d = (uint64_t)return_value;
ppc_store_dfpresult();
}
void ppc_lfsu(){
ppc_grab_regsfpdia();
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
ppc_result64_d = (uint64_t)return_value;
ppc_result_a = ppc_effective_address;
ppc_store_dfpresult();
ppc_store_result_rega();
}
void ppc_lfsx(){
ppc_grab_regsfpdiab();
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
ppc_result64_d = (uint64_t)return_value;
ppc_store_dfpresult();
}
void ppc_lfsux(){
ppc_grab_regsfpdiab();
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
ppc_result64_d = (uint64_t)return_value;
ppc_result_a = ppc_effective_address;
ppc_store_dfpresult();
ppc_store_result_rega();
}
void ppc_lfd(){
ppc_grab_regsfpdia();
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
uint64_t combine_result1 = (uint64_t)(return_value);
address_quickgrab_translate((ppc_effective_address + 4), ppc_state.ppc_fpr[reg_d], 4);
uint64_t combine_result2 = (uint64_t)(return_value);
ppc_result64_d = (combine_result1 << 32) | combine_result2;
ppc_store_dfpresult();
}
void ppc_lfdu(){
ppc_grab_regsfpdia();
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
uint64_t combine_result1 = (uint64_t)(return_value);
address_quickgrab_translate((ppc_effective_address + 4), ppc_state.ppc_fpr[reg_d], 4);
uint64_t combine_result2 = (uint64_t)(return_value);
ppc_result64_d = (combine_result1 << 32) | combine_result2;
ppc_store_dfpresult();
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
void ppc_stfs(){
ppc_grab_regsfpsia();
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
address_quickinsert_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_s], 4);
}
void ppc_stfsu(){
ppc_grab_regsfpsia();
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
uint32_t split_result1 = (uint32_t)((float)(ppc_state.ppc_fpr[reg_s]));
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
void ppc_stfsux(){
ppc_grab_regsfpsiab();
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
uint32_t split_result1 = (uint32_t)((float)(ppc_state.ppc_fpr[reg_s]));
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
void ppc_stfd(){
ppc_grab_regsfpsia();
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] >> 32);
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s]);
address_quickinsert_translate(ppc_effective_address, split_result2, 4);
}
void ppc_stfdu(){
ppc_grab_regsfpsia();
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] >> 32);
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s]);
address_quickinsert_translate(ppc_effective_address, split_result2, 4);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
void ppc_stfdx(){
ppc_grab_regsfpsiab();
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] >> 32);
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s]);
address_quickinsert_translate(ppc_effective_address, split_result2, 4);
}
void ppc_stfdux(){
ppc_grab_regsfpsiab();
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] >> 32);
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s]);
address_quickinsert_translate(ppc_effective_address, split_result2, 4);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
void ppc_stfiwx(){
ppc_grab_regsfpsiab();
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] & 0xFFFFFFFF);
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
}
//Floating Point Register Transfer
void ppc_fmr(){
ppc_grab_regsfpdb();
ppc_state.ppc_fpr[reg_d] = ppc_state.ppc_fpr[reg_b];
ppc_store_dfpresult();
}
void ppc_mffs(){
ppc_grab_regsda();
uint64_t fpstore1 = ppc_state.ppc_fpr[reg_d] & 0xFFFFFFFF00000000;
uint64_t fpstore2 = ppc_state.ppc_fpscr & 0x00000000FFFFFFFF;
fpstore1 |= fpstore2;
ppc_state.ppc_fpr[reg_d] = fpstore1;
ppc_store_sfpresult();
}
void ppc_mtfsf(){
reg_b = (ppc_cur_instruction >> 11) & 31;
uint32_t fm_mask = (ppc_cur_instruction >> 17) & 255;
crm += ((fm_mask & 1) == 1)? 0xF0000000 : 0x00000000;
crm += ((fm_mask & 2) == 1)? 0x0F000000 : 0x00000000;
crm += ((fm_mask & 4) == 1)? 0x00F00000 : 0x00000000;
crm += ((fm_mask & 8) == 1)? 0x000F0000 : 0x00000000;
crm += ((fm_mask & 16) == 1)? 0x0000F000 : 0x00000000;
crm += ((fm_mask & 32) == 1)? 0x00000F00 : 0x00000000;
crm += ((fm_mask & 64) == 1)? 0x000000F0 : 0x00000000;
crm += ((fm_mask & 128) == 1)? 0x0000000F : 0x00000000;
uint32_t quickfprval = (uint32_t)ppc_state.ppc_fpr[reg_b];
ppc_state.ppc_fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
}
void ppc_mtfsb0(){
crf_d = (ppc_cur_instruction >> 21) & 0x31;
if ((crf_d == 0) || (crf_d > 2)){
ppc_state.ppc_fpscr &= ~(1 << (31 - crf_d));
}
}
void ppc_mtfsb0dot(){
//PLACEHOLDER
crf_d = (ppc_cur_instruction >> 21) & 0x31;
if ((crf_d == 0) || (crf_d > 2)){
ppc_state.ppc_fpscr &= ~(1 << crf_d);
}
}
void ppc_mtfsb1(){
crf_d = (ppc_cur_instruction >> 21) & 0x31;
if ((crf_d == 0) || (crf_d > 2)){
ppc_state.ppc_fpscr |= (1 << crf_d);
}
}
void ppc_mtfsb1dot(){
//PLACEHOLDER
crf_d = ~(ppc_cur_instruction >> 21) & 0x31;
if ((crf_d == 0) || (crf_d > 2)){
ppc_state.ppc_fpscr |= (1 << crf_d);
}
}
void ppc_mcrfs(){
crf_d = (ppc_cur_instruction >> 23) & 7;
crf_d = crf_d << 2;
crf_s = (ppc_cur_instruction >> 18) & 7;
crf_s = crf_d << 2;
ppc_state.ppc_cr = ~(ppc_state.ppc_cr & ((15 << (28- crf_d)))) & (ppc_state.ppc_fpscr & (15 << (28- crf_s)));
}
//Floating Point Comparisons
void ppc_fcmpo(){
ppc_grab_regsfpsab();
crf_d = (ppc_cur_instruction >> 23) & 7;
crf_d = crf_d << 2;
double db_test_a = (double)ppc_result64_a;
double db_test_b = (double)ppc_result64_b;
ppc_state.ppc_fpscr &= 0xFFFF0FFF;
if (std::isnan(db_test_a) || std::isnan(db_test_b)){
cmp_c |= 0x01;
}
else if (db_test_a < db_test_b){
cmp_c |= 0x08;
}
else if (db_test_a > db_test_b){
cmp_c |= 0x04;
}
else{
cmp_c |= 0x02;
}
ppc_state.ppc_fpscr |= (cmp_c << 12);
ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
if ((db_test_a == snan) || (db_test_b == snan)){
ppc_state.ppc_fpscr |= 0x1000000;
if (ppc_state.ppc_fpscr && 0x80){
ppc_state.ppc_fpscr |= 0x80000;
}
}
else if ((db_test_a == qnan) || (db_test_b == qnan)){
ppc_state.ppc_fpscr |= 0x80000;
}
}
void ppc_fcmpu(){
ppc_grab_regsfpsab();
crf_d = (ppc_cur_instruction >> 23) & 7;
crf_d = crf_d << 2;
double db_test_a = (double)ppc_result64_a;
double db_test_b = (double)ppc_result64_b;
ppc_state.ppc_fpscr &= 0xFFFF0FFF;
if (std::isnan(db_test_a) || std::isnan(db_test_b)){
cmp_c |= 0x01;
}
else if (db_test_a < db_test_b){
cmp_c |= 0x08;
}
else if (db_test_a > db_test_b){
cmp_c |= 0x04;
}
else{
cmp_c |= 0x02;
}
ppc_state.ppc_fpscr |= (cmp_c << 12);
ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
if ((db_test_a == snan) || (db_test_b == snan)){
ppc_state.ppc_fpscr |= 0x1000000;
}
}

32
ppcgekkoopcodes.cpp Normal file
View File

@ -0,0 +1,32 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
// The uniquely Gekko opcodes for the processor - ppcgekkoopcodes.cpp
#include <iostream>
#include <stdio.h>
#include "ppcemumain.h"
void ppc_psq_l(){
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
exit(0);
}
void ppc_psq_lu(){
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
exit(0);
}
void ppc_psq_st(){
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
exit(0);
}
void ppc_psq_stu(){
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
exit(0);
}

991
ppcmemory.cpp Normal file
View File

@ -0,0 +1,991 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
// The memory operations - ppcmemory.cpp
#include <iostream>
#include <cstdint>
#include <cinttypes>
#include <string>
#include <array>
#include <thread>
#include <atomic>
#include "viacuda.h"
#include "macioserial.h"
#include "macswim3.h"
#include "ppcemumain.h"
#include "ppcmemory.h"
#include "openpic.h"
#include "mpc106.h"
std::vector<uint32_t> pte_storage;
uint64_t ppc_virtual_address; //It's 52 bits, but 64 bits more than covers the range needed.
uint32_t bat_srch;
uint32_t bepi_chk;
uint32_t pte_word1;
uint32_t pte_word2;
uint32_t msr_ir_test;
uint32_t msr_dr_test;
uint32_t msr_ip_test;
uint32_t choose_sr;
uint32_t pteg_hash1;
uint32_t pteg_hash2;
uint32_t pteg_answer;
uint32_t pteg_address1;
uint32_t pteg_temp1;
uint32_t pteg_address2;
uint32_t pteg_temp2;
uint32_t pteg_check1;
uint32_t rev_pteg_check1;
uint32_t pteg_check2;
uint32_t rev_pteg_check2;
unsigned char * grab_tempmem_ptr1;
unsigned char * grab_tempmem_ptr2;
unsigned char * grab_tempmem_ptr3;
unsigned char * grab_tempmem_ptr4;
unsigned char * grab_macmem_ptr;
unsigned char * grab_pteg1_ptr;
unsigned char * grab_pteg2_ptr;
std::atomic<bool> hash_found (false);
uint32_t dbat_array_map [4][3]={
//flg ea begin ea end
{0x00,0x00000000,0x00000000},
{0x00,0x00000000,0x00000000},
{0x00,0x00000000,0x00000000},
{0x00,0x00000000,0x00000000}
};
uint32_t ibat_array_map [4][3]={
//flg ea begin ea end
{0x00,0x00000000,0x00000000},
{0x00,0x00000000,0x00000000},
{0x00,0x00000000,0x00000000},
{0x00,0x00000000,0x00000000}
};
/**
Quickly map to memory - sort of.
0x00000000 - 0x7FFFFFFF - Macintosh system memory
(Because this emulator is trying to emulate a Mac with a Grackle motherboard,
the most memory that can ever be allocated to the system is 2 Gigs.)
0x80000000 - 0xFF7FFFFF - PCI memory
This memory is allocated to things like the memory controller, video, and audio.
0xF3000000 - Mac OS I/O Device area
0xF3013000 - Serial Printer Port (0x20 bytes)
0xF3013020 - Serial Modem Port (0x20 bytes)
0xF3011000 - BMAC Ethernet (0x1000 bytes)
0xF3014000 - DAVAudio Sound Bus (0x1000 bytes)
0xF3015000 - Swim 3 Floppy Disk Drive (0x1000 bytes)
0xF3016000 - Cuda (0x2000 bytes)
0xF3020000 - Heathrow ATA (Hard Drive Interface)
0xFF800000 - 0xFFFFFFFF - ROM memory
This memory is for storing the ROM needed to boot up the computer.
This could definitely be refactored better - TODO
**/
void msr_status_update(){
msr_ip_test = (ppc_state.ppc_msr >> 6) & 1;
msr_ir_test = (ppc_state.ppc_msr >> 5) & 1;
msr_dr_test = (ppc_state.ppc_msr >> 4) & 1;
}
void ibat_update(){
uint8_t tlb_place = 0;
uint32_t ref_area = 0;
bool msr_pr = ppc_state.ppc_msr && 4000; //This is for problem mode; make sure that supervisor mode does not touch this!
for (int bat_srch = 528; bat_srch < 535; bat_srch += 2){
ref_area = ((ppc_state.ppc_spr[bat_srch] & 0x1FFC) > 0) ? ((ppc_state.ppc_spr[bat_srch] & 0x1FFC) << 16): 131072;
bepi_chk|= (ppc_effective_address & 0xFFFE0000) & ~ref_area;
bool supervisor_on = (ppc_state.ppc_spr[bat_srch] & 0x00000002);
bool problem_on = (ppc_state.ppc_spr[bat_srch] & 0x00000001);
if (((ppc_state.ppc_spr[bat_srch] & 0xFFFE0000) == bepi_chk) &&
((problem_on && msr_pr) || (supervisor_on && !msr_pr))){
//Set write/read flags, beginning of transfer area, and end of transfer area
ibat_array_map[tlb_place][0] = (ppc_state.ppc_spr[bat_srch] & 0x3);
ibat_array_map[tlb_place][1] = (ppc_state.ppc_spr[bat_srch] & 0xFFFE0000);
ibat_array_map[tlb_place][2] = ((ppc_state.ppc_spr[bat_srch] & 0xFFFE0000) + ref_area) - 1;
break;
}
tlb_place++;
}
}
void dbat_update(){
uint8_t tlb_place = 0;
uint32_t ref_area = 0;
bool msr_pr = ppc_state.ppc_msr && 4000; //This is for problem mode; make sure that supervisor mode does not touch this!
for (int bat_srch = 536; bat_srch < 543; bat_srch += 2){
ref_area = (ppc_state.ppc_spr[bat_srch] & 0x1FFC) > 0? ((ppc_state.ppc_spr[bat_srch] & 0x1FFC) << 16): 131072;
bepi_chk|= (ppc_effective_address & 0xFFFE0000) & ~ref_area;
bool supervisor_on = (ppc_state.ppc_spr[bat_srch] & 0x00000002);
bool problem_on = (ppc_state.ppc_spr[bat_srch] & 0x00000001);
if (((ppc_state.ppc_spr[bat_srch] & 0xFFFE0000) == bepi_chk) &&
((problem_on && (msr_pr != 0)) || (supervisor_on && (msr_pr == 0)))){
//Set write/read flags, beginning of transfer area, and end of transfer area
dbat_array_map[tlb_place][0] = (ppc_state.ppc_spr[bat_srch] & 0x3);
dbat_array_map[tlb_place][1] = (ppc_state.ppc_spr[bat_srch] & 0xFFFE0000);
dbat_array_map[tlb_place][2] = ((ppc_state.ppc_spr[bat_srch] & 0xFFFE0000) + ref_area) - 1;
break;
}
tlb_place++;
}
}
void get_pointer_pteg1(uint32_t address_grab){
//Grab the array pointer for the PTEG
if (address_grab < 0x80000000){
pte_word1 = address_grab % ram_size_set;
if (address_grab < 0x040000000){ //for debug purposes
grab_pteg1_ptr = machine_sysram_mem;
}
else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){
pte_word1 = address_grab % 0x2000;
grab_pteg1_ptr = machine_sysconfig_mem;
}
else{
printf("Uncharted territory: %x", address_grab);
}
}
else if (address_grab < 0x80800000){
pte_word1 = address_grab % 0x800000;
grab_pteg1_ptr = machine_upperiocontrol_mem;
}
else if (address_grab < 0x81000000){
pte_word1 = address_grab % 0x800000;
grab_pteg1_ptr = machine_iocontrolcdma_mem;
}
else if (address_grab < 0xBF80000){
pte_word1 = address_grab % 33554432;
grab_pteg1_ptr = machine_loweriocontrol_mem;
}
else if (address_grab < 0xC0000000){
pte_word1 = address_grab % 16;
grab_pteg1_ptr = machine_interruptack_mem;
}
else if (address_grab < 0xF0000000){
printf("Invalid Memory Attempt: %x \n", address_grab);
return;
}
else if (address_grab < 0xF8000000){
pte_word1 = address_grab % 67108864;
grab_pteg1_ptr = machine_iocontrolmem_mem;
}
else if (address_grab < rom_file_begin){
//Get back to this! (weeny1)
if (address_grab < 0xFE000000){
pte_word1 = address_grab % 4096;
grab_pteg1_ptr = machine_f8xxxx_mem;
}
else if (address_grab < 0xFEC00000){
pte_word1 = address_grab % 65536;
grab_pteg1_ptr = machine_fexxxx_mem;
}
else if (address_grab < 0xFEE00000){
pte_word1 = 0x0CF8; //CONFIG_ADDR
grab_pteg1_ptr = machine_fecxxx_mem;
}
else if (address_grab < 0xFF000000){
pte_word1 = 0x0CFC; //CONFIG_DATA
grab_pteg1_ptr = machine_feexxx_mem;
}
else if (address_grab < 0xFF800000){
pte_word1 = address_grab % 4096;
grab_pteg1_ptr = machine_ff00xx_mem;
}
else{
pte_word1 = (address_grab % 1048576) + 0x400000;
grab_pteg1_ptr = machine_sysram_mem;
}
}
else{
pte_word1 = address_grab % rom_file_setsize;
grab_pteg1_ptr = machine_sysrom_mem;
}
}
void get_pointer_pteg2(uint32_t address_grab){
//Grab the array pointer for the PTEG
if (address_grab < 0x80000000){
pte_word2 = address_grab % ram_size_set;
if (address_grab < 0x040000000){ //for debug purposes
grab_pteg2_ptr = machine_sysram_mem;
}
else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){
pte_word2 = address_grab % 0x2000;
grab_pteg2_ptr = machine_sysconfig_mem;
}
else{
printf("Uncharted territory: %x", address_grab);
}
}
else if (address_grab < 0x80800000){
pte_word2 = address_grab % 0x800000;
grab_pteg2_ptr = machine_upperiocontrol_mem;
}
else if (address_grab < 0x81000000){
pte_word2 = address_grab % 0x800000;
grab_pteg2_ptr = machine_iocontrolcdma_mem;
}
else if (address_grab < 0xBF80000){
pte_word2 = address_grab % 33554432;
grab_pteg2_ptr = machine_loweriocontrol_mem;
}
else if (address_grab < 0xC0000000){
pte_word2 = address_grab % 16;
grab_pteg2_ptr = machine_interruptack_mem;
}
else if (address_grab < 0xF0000000){
printf("Invalid Memory Attempt: %x \n", address_grab);
return;
}
else if (address_grab < 0xF8000000){
pte_word2 = address_grab % 67108864;
grab_pteg2_ptr = machine_iocontrolmem_mem;
}
else if (address_grab < rom_file_begin){
//Get back to this! (weeny1)
if (address_grab < 0xFE000000){
pte_word2 = address_grab % 4096;
grab_pteg2_ptr = machine_f8xxxx_mem;
}
else if (address_grab < 0xFEC00000){
pte_word2 = address_grab % 65536;
grab_pteg2_ptr = machine_fexxxx_mem;
}
else if (address_grab < 0xFEE00000){
pte_word2 = 0x0CF8; //CONFIG_ADDR
grab_pteg2_ptr = machine_fecxxx_mem;
}
else if (address_grab < 0xFF000000){
pte_word2 = 0x0CFC; //CONFIG_DATA
grab_pteg2_ptr = machine_feexxx_mem;
}
else if (address_grab < 0xFF800000){
pte_word2 = address_grab % 4096;
grab_pteg2_ptr = machine_ff00xx_mem;
}
else{
pte_word2 = (address_grab % 1048576) + 0x400000;
grab_pteg2_ptr = machine_sysram_mem;
}
}
else{
pte_word2 = address_grab % rom_file_setsize;
grab_pteg2_ptr = machine_sysrom_mem;
}
}
void primary_generate_pa(){
pteg_address1 |= ppc_state.ppc_spr[25] & 0xFE000000;
pteg_temp1 = (((ppc_state.ppc_spr[25] & 0x1FF) << 10) & (pteg_hash1 & 0x7FC00));
pteg_address1 |= ((ppc_state.ppc_spr[25] & 0x1FF0000) | pteg_temp1);
pteg_address1 |= (pteg_hash1 & 0x3FF) << 6;
}
void secondary_generate_pa(){
pteg_address2 |= ppc_state.ppc_spr[25] & 0xFE000000;
pteg_temp2 = (((ppc_state.ppc_spr[25] & 0x1FF) << 10) & (pteg_hash2 & 0x7FC00));
pteg_address2 |= ((ppc_state.ppc_spr[25] & 0x1FF0000) | pteg_temp2);
pteg_address2 |= (pteg_hash2 & 0x3FF) << 6;
}
void primary_hash_check(uint32_t vpid_known){
uint32_t entries_size = ((ppc_state.ppc_spr[25] & 0x1FF) > 0)? ((ppc_state.ppc_spr[25] & 0x1FF) << 9): 65536;
uint32_t entries_area = pte_word1 + entries_size;
uint32_t check_vpid = 0;
do{
if (!hash_found){
check_vpid |= grab_pteg1_ptr[pte_word1++] << 24;
check_vpid |= grab_pteg1_ptr[pte_word1++] << 16;
check_vpid |= grab_pteg1_ptr[pte_word1++] << 8;
check_vpid |= grab_pteg1_ptr[pte_word1++];
check_vpid = (check_vpid >> 7) & 0xFFFFFF;
if ((check_vpid >> 31) && 0x01){
if (vpid_known == check_vpid){
hash_found = true;
pteg_answer |= grab_pteg1_ptr[pte_word1++] << 24;
pteg_answer |= grab_pteg1_ptr[pte_word1++] << 16;
pteg_answer |= grab_pteg1_ptr[pte_word1++] << 8;
pteg_answer |= grab_pteg1_ptr[pte_word1++];
break;
}
else{
pte_word1 += 4;
check_vpid = 0;
}
}
else{
pte_word1 += 4;
check_vpid = 0;
}
}
else{
pte_word1 = entries_area;
}
}while (pte_word1 < entries_area);
}
void secondary_hash_check(uint32_t vpid_known){
uint32_t entries_size = ((ppc_state.ppc_spr[25] & 0x1FF) > 0)? ((ppc_state.ppc_spr[25] & 0x1FF) << 9): 65536;
uint32_t entries_area = pte_word1 + entries_size;
uint32_t check_vpid = 0;
do{
if (!hash_found){
check_vpid |= grab_pteg2_ptr[pte_word2++] << 24;
check_vpid |= grab_pteg2_ptr[pte_word2++] << 16;
check_vpid |= grab_pteg2_ptr[pte_word2++] << 8;
check_vpid |= grab_pteg2_ptr[pte_word2++];
check_vpid = (check_vpid >> 7) & 0xFFFFFF;
if ((check_vpid >> 31) && 0x01){
if (vpid_known == check_vpid){
hash_found = true;
pteg_answer |= grab_pteg2_ptr[pte_word2++] << 24;
pteg_answer |= grab_pteg2_ptr[pte_word2++] << 16;
pteg_answer |= grab_pteg2_ptr[pte_word2++] << 8;
pteg_answer |= grab_pteg2_ptr[pte_word2++];
break;
}
else{
pte_word2 += 4;
check_vpid = 0;
}
}
else{
pte_word2 += 4;
check_vpid = 0;
}
}
else{
pte_word2 = entries_area;
}
}while (pte_word2 < entries_area);
}
void pteg_translate(uint32_t address_grab){
uint32_t choose_sr = (ppc_effective_address >> 28) & 0x0F;
pteg_hash1 = ppc_state.ppc_sr[choose_sr] & 0x7FFFF;
uint32_t page_index = (ppc_effective_address & 0xFFFF000) >> 12;
pteg_hash1 = (pteg_hash1 ^ page_index);
pteg_hash2 = ~pteg_hash1;
std::thread primary_pa_check(&primary_generate_pa);
std::thread secondary_pa_check(&secondary_generate_pa);
primary_pa_check.join();
secondary_pa_check.join();
uint32_t grab_val = ppc_state.ppc_sr[choose_sr] & 0xFFFFFF;
std::thread primary_pteg_check(&primary_hash_check, std::ref(grab_val));
std::thread secondary_pteg_check(&secondary_hash_check, std::ref(grab_val));
primary_pteg_check.join();
secondary_pteg_check.join();
}
void address_quickinsert_translate(uint32_t address_grab, uint32_t value_insert, uint8_t bit_num){
//Insert a value into memory from a register
printf("Inserting into address %x with %x", address_grab, value_insert);
uint32_t storage_area = 0;
uint32_t grab_batl = 537;
uint32_t blocklen = 0;
bool bat_to_go=0;
bool pteg_to_go=0;
//data bat
if ((ppc_state.ppc_msr >> 4) & 0x1){
printf("DATA RELOCATION GO! - INSERTING \n");
uint32_t min_val;
uint32_t max_val;
pteg_to_go = 1;
for (uint32_t grab_loop = 0; grab_loop < 4; grab_loop++){
if ((dbat_array_map[grab_loop][0] >> 1) && 0x1){
min_val = dbat_array_map[grab_loop][1];
max_val = dbat_array_map[grab_loop][2];
if ((address_grab >= min_val) && (address_grab < max_val) && (max_val != 0)){
blocklen = max_val - min_val;
bat_to_go = 1;
pteg_to_go = 0;
break;
}
}
grab_batl += 2;
}
}
if (bat_to_go){
uint32_t final_grab = 0;
final_grab |= (((address_grab & 0x0FFE0000) & blocklen) | (ppc_state.ppc_spr[grab_batl] & 0xFFFE0000));
final_grab |= (address_grab & 0x1FFFF);
//Check the PP Tags in the batl
//if (!(ppc_state.ppc_spr[grab_batl] == 0x2)){
// ppc_expection_handler(0x0300, 0x0);
// }
address_grab = final_grab;
}
else if (pteg_to_go){
pteg_translate(address_grab);
if (hash_found == true){
address_grab &= 0xFFF;
address_grab |= (pteg_answer & 0xFFFFF000);
}
}
//regular grabbing
if (address_grab < 0x80000000){
if (address_grab > 0x03ffffff){ //for debug purposes
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);
}
}
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 \n");
printf("Device Number: %d ", dev_num);
printf("Register Number: %d \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 >= 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 > 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){
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;
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("Register Number: %d \n", reg_num);
mpc106_address = value_insert;
}
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;
}
}
else{
storage_area = address_grab % rom_file_setsize;
grab_macmem_ptr = machine_sysrom_mem;
}
switch (ppc_state.ppc_msr & 0x1){
case 0:
if (bit_num == 1){
grab_macmem_ptr[storage_area] = (uint8_t)value_insert;
}
else if (bit_num == 2){
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 8);
grab_macmem_ptr[storage_area] = (uint8_t)value_insert;
}
else if (bit_num == 4){
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 24);
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 16);
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 8);
grab_macmem_ptr[storage_area] = (uint8_t)value_insert;
}
break;
case 1:
if (bit_num == 1){
grab_macmem_ptr[storage_area] = (uint8_t)value_insert;
}
else if (bit_num == 2){
grab_macmem_ptr[storage_area++] = (uint8_t)value_insert;
grab_macmem_ptr[storage_area] = (uint8_t)(value_insert >> 8);
}
else if (bit_num == 4){
grab_macmem_ptr[storage_area++] = (uint8_t)value_insert;
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 8);
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 16);
grab_macmem_ptr[storage_area] = (uint8_t)(value_insert >> 24);
}
break;
}
}
void address_quickgrab_translate(uint32_t address_grab, uint32_t value_extract, uint8_t bit_num){
//Grab a value from memory into a register
printf("Grabbing from address %x", address_grab);
uint32_t storage_area = 0;
uint32_t grab_batl = 537;
uint32_t blocklen = 0;
bool bat_to_go=0;
bool pteg_to_go=0;
return_value = 0; //reset this before going into the real fun.
//data bat
if ((ppc_state.ppc_msr >> 4) & 0x1){
printf("DATA RELOCATION GO! - GRABBING \n");
uint32_t min_val;
uint32_t max_val;
pteg_to_go = 1;
for (uint32_t grab_loop = 0; grab_loop < 4; grab_loop++){
if (dbat_array_map[grab_loop][0] && 0x1){
min_val = dbat_array_map[grab_loop][1];
max_val = dbat_array_map[grab_loop][2];
if ((address_grab >= min_val) && (address_grab <= max_val) && (max_val != 0)){
blocklen = max_val - min_val;
bat_to_go = 1;
pteg_to_go = 0;
break;
}
}
grab_batl += 2;
}
}
if (bat_to_go){
uint32_t final_grab = 0;
final_grab |= (((address_grab & 0x0FFE0000) & blocklen) | (ppc_state.ppc_spr[grab_batl] & 0xFFFE0000));
final_grab |= (address_grab & 0x1FFFF);
//Check the PP Tags in the batl
//if ((ppc_state.ppc_spr[grab_batl] & 0x3) == 0x0){
// ppc_expection_handler(0x0300, 0x0);
//}
address_grab = final_grab;
}
else if (pteg_to_go){
pteg_translate(address_grab);
if (hash_found == true){
address_grab &= 0xFFF;
address_grab |= (pteg_answer & 0xFFFFF000);
}
}
//regular grabbing
if (address_grab < 0x80000000){
if (address_grab > 0x03ffffff){ //for debug purposes
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 = (bit_num == 1)?0xFF:(bit_num == 2)?0xFFFF:0xFFFFFFFF;
return;
}
}
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 = (bit_num == 1)?0xFF:(bit_num == 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 = (bit_num == 1)?0xFF:(bit_num == 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 >= 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;
}
if ((address_grab >= 0xF3040000) && (address_grab < 0xF3080000)){
openpic_address = address_grab - 0x80000000;
openpic_write();
return_value = openpic_write_word;
return;
}
else if (address_grab > 0xF3FFFFFF){
return_value = (bit_num == 1)?0xFF:(bit_num == 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){
storage_area = address_grab % 65536;
grab_macmem_ptr = machine_fexxxx_mem;
}
else if (address_grab < 0xFEE00000){
return_value = (bit_num == 1)? (mpc106_address & 0xFF):(bit_num == 2)?(mpc106_address & 0xFFFF):mpc106_address;
return;
}
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;
}
}
else{
printf("Charting ROM Area: %x \n", address_grab);
storage_area = address_grab % rom_file_setsize;
grab_macmem_ptr = machine_sysrom_mem;
}
//Put the final result in return_value here
//This is what gets put back into the register
switch (ppc_state.ppc_msr & 0x1){
case 0:
if (bit_num == 1){
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area]));
}
else if (bit_num == 2){
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 8;
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area]));
}
else if (bit_num == 4){
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 24;
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 16;
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 8;
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area]));
}
break;
case 1:
if (bit_num == 1){
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area]));
}
else if (bit_num == 2){
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) ;
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area])) << 8;
}
else if (bit_num == 4){
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) ;
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 8;
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 16;
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area])) << 24;
}
}
}
void quickinstruction_translate(uint32_t address_grab){
uint32_t storage_area = 0;
uint32_t grab_batl = 537;
uint32_t blocklen = 0;
bool bat_to_go=0;
bool pteg_to_go=0;
return_value = 0; //reset this before going into the real fun.
//instruction bat
if ((ppc_state.ppc_msr >> 5) & 0x1) {
printf("INSTRUCTION RELOCATION GO! \n");
uint32_t min_val;
uint32_t max_val;
pteg_to_go = 1;
for (uint32_t grab_loop = 0; grab_loop < 4; grab_loop++){
if (ibat_array_map[grab_loop][0] && 0x1){
min_val = ibat_array_map[grab_loop][1];
max_val = ibat_array_map[grab_loop][2];
if ((address_grab >= min_val) && (address_grab <= max_val) && (max_val != 0)){
blocklen = max_val - min_val;
bat_to_go = 1;
pteg_to_go = 0;
break;
}
}
grab_batl += 2;
}
}
if (bat_to_go){
uint32_t final_grab = 0;
final_grab |= (((address_grab & 0x0FFE0000) & blocklen) | (ppc_state.ppc_spr[grab_batl] & 0xFFFE0000));
final_grab |= (address_grab & 0x1FFFF);
//if ((ppc_state.ppc_spr[grab_batl] & 0x3) == 0x0){
// ppc_expection_handler(0x0400, 0x0);
//}
address_grab = final_grab;
}
else if (pteg_to_go){
pteg_translate(address_grab);
if (hash_found == true){
address_grab &= 0xFFF;
address_grab |= (pteg_answer & 0xFFFFF000);
}
}
if ((address_grab < 0x100000) && ((ppc_state.ppc_msr >> 6) & 1)){
address_grab |= 0xFFF00000;
}
//grab opcode from memory area
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 >= 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", address_grab);
}
}
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;
}
}
else{
storage_area = address_grab % rom_file_setsize;
grab_macmem_ptr = machine_sysrom_mem;
}
ppc_cur_instruction += (grab_macmem_ptr[(storage_area++)]) << 24;
ppc_cur_instruction += (grab_macmem_ptr[(storage_area++)]) << 16;
ppc_cur_instruction += (grab_macmem_ptr[(storage_area++)]) << 8;
ppc_cur_instruction += (grab_macmem_ptr[(storage_area)]);
}

42
ppcmemory.h Normal file
View File

@ -0,0 +1,42 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
// The opcodes for the processor - ppcopcodes.cpp
#ifndef PPCMEMORY_H
#define PPCMEMORY_H
#include <vector>
#include <array>
extern uint32_t bat_srch;
extern uint32_t bepi_chk;
extern uint32_t msr_ir_test;
extern uint32_t msr_dr_test;
extern uint32_t msr_ip_test;
extern unsigned char * grab_macmem_ptr;
/**
struct pte {
uint32_t page_index_no;
uint32_t entry[];
pte *next;
} PTE;
**/
extern void ibat_update();
extern void dbat_update();
extern void msr_status_update();
extern void address_quickinsert_translate(uint32_t address_grab, uint32_t value_insert, uint8_t bit_num);
extern void address_quickgrab_translate(uint32_t address_grab, uint32_t value_extract, uint8_t bit_num);
extern void quickinstruction_translate(uint32_t address_grab);
#endif // PPCMEMORY_H

2411
ppcopcodes.cpp Normal file

File diff suppressed because it is too large Load Diff

153
viacuda.cpp Normal file
View File

@ -0,0 +1,153 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
//Functionality for the VIA CUDA
#include <iostream>
#include <cinttypes>
#include "viacuda.h"
#include "ppcemumain.h"
uint32_t via_cuda_address;
uint32_t via_set_mode;
uint8_t via_opcode_store_bit;
uint8_t via_write_byte;
uint8_t via_read_byte;
unsigned char porta_ca1, porta_ca2 = 0;
unsigned char porta_cb1, porta_cb2 = 0;
bool via_cuda_confirm;
bool via_cuda_signal_read;
bool via_cuda_signal_write;
void via_ifr_update(){
if ((machine_iocontrolmem_mem[VIACUDA_IFR] && 127) && (machine_iocontrolmem_mem[VIACUDA_IER] && 127)){
machine_iocontrolmem_mem[VIACUDA_IFR] |= 128;
}
else{
machine_iocontrolmem_mem[VIACUDA_IFR] &= 127;
}
}
void via_t1_update(){
if (machine_iocontrolmem_mem[VIACUDA_T1CH] > 0){
machine_iocontrolmem_mem[VIACUDA_T1CH]--;
}
else{
machine_iocontrolmem_mem[VIACUDA_T1CH] = machine_iocontrolmem_mem[VIACUDA_T1LH];
}
if (machine_iocontrolmem_mem[VIACUDA_T1CL] > 0){
machine_iocontrolmem_mem[VIACUDA_T1CL]--;
}
else{
machine_iocontrolmem_mem[VIACUDA_T1CL] = machine_iocontrolmem_mem[VIACUDA_T1LL];
}
}
void via_cuda_init(){
machine_iocontrolmem_mem[VIACUDA_A] = 0x80;
machine_iocontrolmem_mem[VIACUDA_DIRB] = 0xFF;
machine_iocontrolmem_mem[VIACUDA_DIRA] = 0xFF;
machine_iocontrolmem_mem[VIACUDA_T1LL] = 0xFF;
machine_iocontrolmem_mem[VIACUDA_T1LH] = 0xFF;
machine_iocontrolmem_mem[VIACUDA_IER] = 0x7F;
}
void via_cuda_read(){
switch(via_cuda_address){
case VIACUDA_B:
if (machine_iocontrolmem_mem[VIACUDA_DIRB] != 0){
via_read_byte = (via_write_byte & ~machine_iocontrolmem_mem[VIACUDA_DIRB]) | (machine_iocontrolmem_mem[VIACUDA_B] & machine_iocontrolmem_mem[VIACUDA_DIRB]);
break;
}
case VIACUDA_A:
machine_iocontrolmem_mem[VIACUDA_IFR] = ~porta_ca1;
via_read_byte = (machine_iocontrolmem_mem[VIACUDA_A] & ~machine_iocontrolmem_mem[VIACUDA_DIRA]) | (machine_iocontrolmem_mem[VIACUDA_A] & machine_iocontrolmem_mem[VIACUDA_DIRA]);
break;
case VIACUDA_IER:
via_read_byte = machine_iocontrolmem_mem[VIACUDA_IER] | 0x80;
break;
case VIACUDA_ANH:
via_read_byte = machine_iocontrolmem_mem[VIACUDA_A] & ~machine_iocontrolmem_mem[VIACUDA_DIRA];
break;
default:
via_read_byte = machine_iocontrolmem_mem[via_cuda_address];
}
via_read_byte = machine_iocontrolmem_mem[via_cuda_address];
}
void via_cuda_write(){
switch(via_cuda_address){
case VIACUDA_B:
machine_iocontrolmem_mem[VIACUDA_B] = via_write_byte & machine_iocontrolmem_mem[VIACUDA_DIRB];
break;
case VIACUDA_A:
machine_iocontrolmem_mem[VIACUDA_IFR] = ~porta_ca1;
if ((machine_iocontrolmem_mem[VIACUDA_PCR] & 0x0A) != 0x02){
machine_iocontrolmem_mem[VIACUDA_IFR] = ~porta_ca2;
}
via_ifr_update();
machine_iocontrolmem_mem[VIACUDA_A] = (via_write_byte & machine_iocontrolmem_mem[VIACUDA_DIRA]) | (~machine_iocontrolmem_mem[VIACUDA_DIRA]);
break;
case VIACUDA_DIRB:
machine_iocontrolmem_mem[VIACUDA_DIRB] = via_write_byte;
break;
case VIACUDA_DIRA:
machine_iocontrolmem_mem[VIACUDA_DIRA] = via_write_byte;
break;
case VIACUDA_T1LL:
case VIACUDA_T1LH:
via_t1_update();
machine_iocontrolmem_mem[via_cuda_address] = via_write_byte;
break;
case VIACUDA_T2CH:
via_t1_update();
machine_iocontrolmem_mem[VIACUDA_T2CH] = via_write_byte;
break;
case VIACUDA_PCR:
machine_iocontrolmem_mem[VIACUDA_PCR] = via_write_byte;
if ((via_write_byte & 0x0E) == 0x0C){
porta_ca2 = 0;
}
else if ((via_write_byte & 0x08)){
porta_ca2 = 1;
}
if ((via_write_byte & 0xE0) == 0xC0){
porta_cb2 = 0;
}
if ((via_write_byte & 0x80)){
porta_cb2 = 1;
}
break;
case VIACUDA_IFR:
if (via_write_byte & 0x80){
machine_iocontrolmem_mem[VIACUDA_IFR] &= (via_write_byte & 0x7F);
}
else{
machine_iocontrolmem_mem[VIACUDA_IFR] &= ~(via_write_byte & 0x7F);
}
via_ifr_update();
break;
case VIACUDA_IER:
machine_iocontrolmem_mem[VIACUDA_IER] &= ~(via_write_byte & 0x7F);
via_ifr_update();
break;
case VIACUDA_ANH:
machine_iocontrolmem_mem[VIACUDA_A] = (via_write_byte & machine_iocontrolmem_mem[VIACUDA_DIRA]) | (~machine_iocontrolmem_mem[VIACUDA_DIRA]);
break;
default:
machine_iocontrolmem_mem[via_cuda_address] = via_write_byte;
}
machine_iocontrolmem_mem[via_cuda_address] = via_write_byte;
}

48
viacuda.h Normal file
View File

@ -0,0 +1,48 @@
//DingusPPC - Prototype 5bf2
//Written by divingkatae
//(c)2018-20 (theweirdo)
//Please ask for permission
//if you want to distribute this.
//(divingkatae#1017 on Discord)
#ifndef VIACUDA_H_
#define VIACUDA_H_
#define VIACUDA_B 0x3016000 /* B-side data */
#define VIACUDA_A 0x3016200 /* A-side data */
#define VIACUDA_DIRB 0x3016400 /* B-side direction (1=output) */
#define VIACUDA_DIRA 0x3016600 /* A-side direction (1=output) */
#define VIACUDA_T1CL 0x3016800 /* Timer 1 ctr/latch (low 8 bits) */
#define VIACUDA_T1CH 0x3016A00 /* Timer 1 counter (high 8 bits) */
#define VIACUDA_T1LL 0x3016C00 /* Timer 1 latch (low 8 bits) */
#define VIACUDA_T1LH 0x3016E00 /* Timer 1 latch (high 8 bits) */
#define VIACUDA_T2CL 0x3017000 /* Timer 2 ctr/latch (low 8 bits) */
#define VIACUDA_T2CH 0x3017200 /* Timer 2 counter (high 8 bits) */
#define VIACUDA_SR 0x3017400 /* Shift register */
#define VIACUDA_ACR 0x3017600 /* Auxiliary control register */
#define VIACUDA_PCR 0x3017800 /* Peripheral control register */
#define VIACUDA_IFR 0x3017A00 /* Interrupt flag register */
#define VIACUDA_IER 0x3017C00 /* Interrupt enable register */
#define VIACUDA_ANH 0x3017E00 /* A-side data, no handshake */
extern uint32_t via_cuda_address;
extern uint8_t via_opcode_store_bit;
extern uint8_t via_write_byte;
extern uint8_t via_read_byte;
extern bool via_cuda_confirm;
extern bool via_cuda_signal_read;
extern bool via_cuda_signal_write;
extern unsigned char porta_ca1, porta_ca2;
extern unsigned char porta_cb1, porta_cb2;
extern uint32_t via_set_mode;
extern void via_ifr_update();
extern void via_t1_update();
extern void via_cuda_init();
extern void via_cuda_read();
extern void via_cuda_write();
#endif // VIACUDA_H