From eaa517b63be6b13244bc3e4cff44be73f98cb90b Mon Sep 17 00:00:00 2001 From: dingusdev <52434309+dingusdev@users.noreply.github.com> Date: Mon, 1 Jul 2019 19:15:33 -0700 Subject: [PATCH] Add files via upload The first attempt at uploading new files. --- dingusppc.cbp | 71 ++ macioserial.cpp | 41 + macioserial.h | 22 + macscsi.c | 1 + macscsi.cpp | 31 + macscsi.h | 21 + macswim3.cpp | 29 + macswim3.h | 19 + main.cpp | 859 +++++++++++++++ makefile | 50 + mpc106.c | 1 + mpc106.cpp | 164 +++ mpc106.h | 32 + openpic.cpp | 34 + openpic.h | 21 + poweropcodes.cpp | 795 ++++++++++++++ ppcemumain.h | 762 ++++++++++++++ ppcfpopcodes.cpp | 679 ++++++++++++ ppcgekkoopcodes.cpp | 32 + ppcmemory.cpp | 991 ++++++++++++++++++ ppcmemory.h | 42 + ppcopcodes.cpp | 2411 +++++++++++++++++++++++++++++++++++++++++++ viacuda.cpp | 153 +++ viacuda.h | 48 + 24 files changed, 7309 insertions(+) create mode 100644 dingusppc.cbp create mode 100644 macioserial.cpp create mode 100644 macioserial.h create mode 100644 macscsi.c create mode 100644 macscsi.cpp create mode 100644 macscsi.h create mode 100644 macswim3.cpp create mode 100644 macswim3.h create mode 100644 main.cpp create mode 100644 makefile create mode 100644 mpc106.c create mode 100644 mpc106.cpp create mode 100644 mpc106.h create mode 100644 openpic.cpp create mode 100644 openpic.h create mode 100644 poweropcodes.cpp create mode 100644 ppcemumain.h create mode 100644 ppcfpopcodes.cpp create mode 100644 ppcgekkoopcodes.cpp create mode 100644 ppcmemory.cpp create mode 100644 ppcmemory.h create mode 100644 ppcopcodes.cpp create mode 100644 viacuda.cpp create mode 100644 viacuda.h diff --git a/dingusppc.cbp b/dingusppc.cbp new file mode 100644 index 0000000..f4bdcc7 --- /dev/null +++ b/dingusppc.cbp @@ -0,0 +1,71 @@ + + + + + + diff --git a/macioserial.cpp b/macioserial.cpp new file mode 100644 index 0000000..a3c7f1c --- /dev/null +++ b/macioserial.cpp @@ -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 +#include +#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]; +} diff --git a/macioserial.h b/macioserial.h new file mode 100644 index 0000000..3ac8a4e --- /dev/null +++ b/macioserial.h @@ -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 diff --git a/macscsi.c b/macscsi.c new file mode 100644 index 0000000..d3f5a12 --- /dev/null +++ b/macscsi.c @@ -0,0 +1 @@ + diff --git a/macscsi.cpp b/macscsi.cpp new file mode 100644 index 0000000..725f1dd --- /dev/null +++ b/macscsi.cpp @@ -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 +#include +#include +#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(){ + +} + diff --git a/macscsi.h b/macscsi.h new file mode 100644 index 0000000..1293dfc --- /dev/null +++ b/macscsi.h @@ -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 diff --git a/macswim3.cpp b/macswim3.cpp new file mode 100644 index 0000000..3c20060 --- /dev/null +++ b/macswim3.cpp @@ -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 +#include +#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; +} diff --git a/macswim3.h b/macswim3.h new file mode 100644 index 0000000..68763de --- /dev/null +++ b/macswim3.h @@ -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 diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..58dd2ff --- /dev/null +++ b/main.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ppcemumain.h" +#include "macioserial.h" +#include "macswim3.h" +#include "ppcmemory.h" +#include "viacuda.h" +#include "mpc106.h" +#include "openpic.h" +//#include + +#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 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; +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..46653d2 --- /dev/null +++ b/makefile @@ -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) diff --git a/mpc106.c b/mpc106.c new file mode 100644 index 0000000..d3f5a12 --- /dev/null +++ b/mpc106.c @@ -0,0 +1 @@ + diff --git a/mpc106.cpp b/mpc106.cpp new file mode 100644 index 0000000..4bdf04e --- /dev/null +++ b/mpc106.cpp @@ -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 +#include +#include +#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; + } +} diff --git a/mpc106.h b/mpc106.h new file mode 100644 index 0000000..5f16073 --- /dev/null +++ b/mpc106.h @@ -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 diff --git a/openpic.cpp b/openpic.cpp new file mode 100644 index 0000000..1ffd8ec --- /dev/null +++ b/openpic.cpp @@ -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 +#include +#include +#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]; +} diff --git a/openpic.h b/openpic.h new file mode 100644 index 0000000..064e978 --- /dev/null +++ b/openpic.h @@ -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 diff --git a/poweropcodes.cpp b/poweropcodes.cpp new file mode 100644 index 0000000..b68b780 --- /dev/null +++ b/poweropcodes.cpp @@ -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 +#include +#include +#include +#include "ppcemumain.h" +#include "ppcmemory.h" +#include +#include + +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"); +} diff --git a/ppcemumain.h b/ppcemumain.h new file mode 100644 index 0000000..6a23bbd --- /dev/null +++ b/ppcemumain.h @@ -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 + +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 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 SubOpcode16Grabber= + {{0, &ppc_bc}, {1, &ppc_bcl}, {2, &ppc_bca}, {3, &ppc_bcla} + }; +static std::map SubOpcode18Grabber= + {{0, &ppc_b}, {1, &ppc_bl}, {2, &ppc_ba}, {3, &ppc_bla} + }; +static std::map 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 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 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 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 diff --git a/ppcfpopcodes.cpp b/ppcfpopcodes.cpp new file mode 100644 index 0000000..66c4f96 --- /dev/null +++ b/ppcfpopcodes.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include "ppcemumain.h" +#include "ppcmemory.h" +#include +#include + +//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::signaling_NaN(); + double qnan = std::numeric_limits::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; + } +} diff --git a/ppcgekkoopcodes.cpp b/ppcgekkoopcodes.cpp new file mode 100644 index 0000000..b3444af --- /dev/null +++ b/ppcgekkoopcodes.cpp @@ -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 +#include +#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); +} diff --git a/ppcmemory.cpp b/ppcmemory.cpp new file mode 100644 index 0000000..b94f6b3 --- /dev/null +++ b/ppcmemory.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include "viacuda.h" +#include "macioserial.h" +#include "macswim3.h" +#include "ppcemumain.h" +#include "ppcmemory.h" +#include "openpic.h" +#include "mpc106.h" + +std::vector 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 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)]); +} diff --git a/ppcmemory.h b/ppcmemory.h new file mode 100644 index 0000000..3810392 --- /dev/null +++ b/ppcmemory.h @@ -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 +#include + +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 diff --git a/ppcopcodes.cpp b/ppcopcodes.cpp new file mode 100644 index 0000000..d1fb3d3 --- /dev/null +++ b/ppcopcodes.cpp @@ -0,0 +1,2411 @@ +//DingusPPC - Prototype 5bf2 +//Written by divingkatae +//(c)2018-20 (theweirdo) +//Please ask for permission +//if you want to distribute this. +//(divingkatae#1017 on Discord) + +// General opcodes for the processor - ppcopcodes.cpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ppcemumain.h" +#include "ppcmemory.h" + + uint32_t crf_d; + uint32_t crf_s; + uint32_t reg_s; + uint32_t reg_d; + uint32_t reg_a; + uint32_t reg_b; + uint32_t reg_c; //used only for floating point multiplication operations + uint32_t xercon; + uint32_t cmp_c; + uint32_t crm; + uint32_t br_bo; + uint32_t br_bi; + uint32_t rot_sh; + uint32_t rot_mb; + uint32_t rot_me; + uint32_t uimm; + uint32_t not_this; + uint32_t grab_sr; + uint32_t grab_inb; //This is for grabbing the number of immediate bytes for loading and storing + uint32_t grab_d; //This is for grabbing d from Store and Load instructions + uint32_t ppc_to; + int32_t simm; + int32_t adr_li; + int32_t br_bd; + +//Used for GP calcs + uint32_t ppc_result_a = 0; + uint32_t ppc_result_b = 0; + uint32_t ppc_result_c = 0; + uint32_t ppc_result_d = 0; + + int32_t sidiv_result; + uint32_t uidiv_result; + uint64_t uiproduct; + int64_t siproduct; + + uint32_t strwrd_replace_value; + +/** +Extract the registers desired and the values of the registers +This also takes the MSR into account, mainly to determine +what endian the numbers are to be stored in. +**/ + +//Storage and register retrieval functions for the integer functions. +void ppc_store_result_regd(){ + ppc_state.ppc_gpr[reg_d] = ppc_result_d; +} + +void ppc_store_result_rega(){ + ppc_state.ppc_gpr[reg_a] = ppc_result_a; +} + +void ppc_grab_regsdasimm(){ + reg_d = (ppc_cur_instruction >> 21) & 31; + reg_a = (ppc_cur_instruction >> 16) & 31; + simm = (int32_t)((int16_t)((ppc_cur_instruction) & 65535)); + ppc_result_a = ppc_state.ppc_gpr[reg_a]; +} + +void ppc_grab_regsdauimm(){ + reg_d = (ppc_cur_instruction >> 21) & 31; + reg_a = (ppc_cur_instruction >> 16) & 31; + uimm = (uint32_t)((uint16_t)((ppc_cur_instruction) & 65535)); + ppc_result_a = ppc_state.ppc_gpr[reg_a]; +} + +void ppc_grab_regssasimm(){ + reg_s = (ppc_cur_instruction >> 21) & 31; + reg_a = (ppc_cur_instruction >> 16) & 31; + simm = (int32_t)((int16_t)((ppc_cur_instruction) & 65535)); + ppc_result_a = ppc_state.ppc_gpr[reg_a]; + ppc_result_d = ppc_state.ppc_gpr[reg_s]; +} + +void ppc_grab_regssauimm(){ + reg_s = (ppc_cur_instruction >> 21) & 31; + reg_a = (ppc_cur_instruction >> 16) & 31; + uimm = (uint32_t)((uint16_t)((ppc_cur_instruction) & 65535)); + ppc_result_d = ppc_state.ppc_gpr[reg_s]; + ppc_result_a = ppc_state.ppc_gpr[reg_a]; +} + +void ppc_grab_regsdab(){ + 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_regssab(){ + reg_s = (ppc_cur_instruction >> 21) & 31; + reg_a = (ppc_cur_instruction >> 16) & 31; + reg_b = (ppc_cur_instruction >> 11) & 31; + ppc_result_d = ppc_state.ppc_gpr[reg_s]; + ppc_result_a = ppc_state.ppc_gpr[reg_a]; + ppc_result_b = ppc_state.ppc_gpr[reg_b]; +} + +void ppc_grab_regssa(){ + 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_regssb(){ + reg_s = (ppc_cur_instruction >> 21) & 31; + reg_b = (ppc_cur_instruction >> 16) & 31; + ppc_result_d = ppc_state.ppc_gpr[reg_s]; + ppc_result_b = ppc_state.ppc_gpr[reg_b]; +} + +void ppc_grab_regsda(){ + 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_regsdb(){ + reg_d = (ppc_cur_instruction >> 21) & 31; + reg_b = (ppc_cur_instruction >> 11) & 31; + ppc_result_b = ppc_state.ppc_gpr[reg_b]; +} + + +//Affects CR Field 0 - For integer operations +void ppc_changecrf0(uint32_t set_result){ + ppc_state.ppc_cr &= 0x0FFFFFFF; + + if (set_result == 0){ + ppc_state.ppc_cr |= 0x20000000; + } + else if (set_result & 0x80000000){ + ppc_state.ppc_cr |= 0x80000000; + } + else{ + ppc_state.ppc_cr |= 0x40000000; + } + + if (ppc_state.ppc_spr[1] & 0x80000000){ + ppc_state.ppc_cr |= 0x10000000; + } +} + +//Affects the XER register's Carry Bit +void ppc_carry(uint32_t a, uint32_t b){ + if (b > ~a){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } +} + +//Affects the XER register's SO and OV Bits +void ppc_setsoov(uint32_t a, uint32_t b){ + uint64_t a64b = (uint64_t)a; + uint64_t b64b = (uint64_t)b; + + if ((a64b + b64b) > 0xFFFFFFFF){ + ppc_state.ppc_spr[1] |= 0x40000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xBFFFFFFF; + } + + if (((a64b + b64b) < 0x80000000) || (ppc_state.ppc_spr[1] && 0x40000000)){ + ppc_state.ppc_spr[1] |= 0x80000000; + } + else{ + ppc_state.ppc_spr[1] &= 0x7FFFFFFF; + } +} + +/** +Avoid some tedious steps to breaking down the opcodes, +allowing for some nice maps to cleanly organize each opcode. +**/ + +void ppc_illegalop(){ + uint8_t illegal_code = ppc_cur_instruction >> 26; + uint32_t grab_it = (uint32_t) illegal_code; + printf("Illegal opcode reported: %d Report this! \n", grab_it); + exit(-1); + //ppc_expection_handler(0x0700, 0x80000); +} + +void ppc_illegalsubop31(){ + uint16_t illegal_subcode = ppc_cur_instruction & 2047; + uint32_t grab_it = (uint32_t) illegal_subcode; + printf("Illegal subopcode for 31 reported: %d Report this! \n", grab_it); +} + +void ppc_opcode4(){ + printf("Reading from Opcode 4 table \n"); + uint8_t subop_grab = ppc_cur_instruction & 3; + uint32_t regrab = (uint32_t)subop_grab; + printf("Executing subopcode entry %d \n .. or would if I bothered to implement it. SORRY!", regrab); + exit(0); +} + +void ppc_opcode16(){ + //printf("Reading from Opcode 16 table \n"); + uint8_t subop_grab = ppc_cur_instruction & 3; + //uint32_t regrab = (uint32_t)subop_grab; + //printf("Executing subopcode entry %d \n", regrab); + SubOpcode16Grabber[subop_grab](); +} + +void ppc_opcode18(){ + //printf("Reading from Opcode 18 table \n"); + uint8_t subop_grab = ppc_cur_instruction & 3; + //uint32_t regrab = (uint32_t)subop_grab; + //printf("Executing subopcode entry %d \n", regrab); + SubOpcode18Grabber[subop_grab](); +} + +void ppc_opcode19(){ + //printf("Reading from Opcode 19 table \n"); + uint16_t subop_grab = ppc_cur_instruction & 2047; + //uint32_t regrab = (uint32_t)subop_grab; + //printf("Executing subopcode entry %d \n", regrab); + if (SubOpcode19Grabber.count(subop_grab) == 1){ + SubOpcode19Grabber[subop_grab](); + } + else{ + std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl; + ppc_expection_handler(0x0700, 0x80000); + } +} + +void ppc_opcode31(){ + //printf("Reading from Opcode 31 table \n"); + uint16_t subop_grab = ppc_cur_instruction & 2047; + //uint32_t regrab = (uint32_t)subop_grab; + //printf("Executing subopcode entry %d \n", regrab); + if (SubOpcode31Grabber.count(subop_grab) == 1){ + SubOpcode31Grabber[subop_grab](); + } + else{ + std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl; + ppc_expection_handler(0x0700, 0x80000); + } +} + +void ppc_opcode63(){ + //printf("Reading from Opcode 63 table \n"); + uint16_t subop_grab = ppc_cur_instruction & 2047; + //uint32_t regrab = (uint32_t)subop_grab; + //std::cout << "Executing subopcode entry " << regrab << std::endl; + if (SubOpcode63Grabber.count(subop_grab) == 1){ + SubOpcode63Grabber[subop_grab](); + } + else{ + //std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl; + ppc_expection_handler(0x0700, 0x80000); + } +} + +void ppc_main_opcode(){ + //Grab the main opcode + uint8_t ppc_mainop = (ppc_cur_instruction >> 26) & 63; + //printf("Main Opcode: %d \n", ppc_mainop); + OpcodeGrabber[ppc_mainop](); +} + +/** +The core functionality of this PPC emulation is within all of these void functions. +This is where the opcode tables in the ppcemumain.h come into play - reducing the number of comparisons needed. +This means loads of functions, but less CPU cycles needed to determine the function (theoretically). +**/ + +void ppc_addi(){ + ppc_grab_regsdasimm(); + ppc_result_d = (reg_a == 0)?simm:(ppc_result_a + simm); + ppc_store_result_regd(); +} + +void ppc_addic(){ + ppc_grab_regsdasimm(); + ppc_result_d = (ppc_result_a + simm); + ppc_carry(ppc_result_a, ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_addicdot(){ + ppc_grab_regsdasimm(); + ppc_result_d = (ppc_result_a + simm); + ppc_changecrf0(ppc_result_d); + ppc_carry(ppc_result_a, ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_addis(){ + ppc_grab_regsdasimm(); + ppc_result_d = (reg_a == 0)?(simm << 16):(ppc_result_a + (simm << 16)); + ppc_store_result_regd(); +} + +void ppc_add(){ + ppc_grab_regsdab(); + ppc_result_d = ppc_result_a + ppc_result_b; + ppc_store_result_regd(); +} + +void ppc_adddot(){ + ppc_grab_regsdab(); + ppc_result_d = ppc_result_a + ppc_result_b; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +//addo + addodot +void ppc_addo(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + ppc_result_d = ppc_result_a + ppc_result_b; + ppc_store_result_regd(); +} + +void ppc_addodot(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + ppc_result_d = ppc_result_a + ppc_result_b; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_addc(){ + ppc_grab_regsdab(); + ppc_result_d = ppc_result_a + ppc_result_b; + ppc_carry(ppc_result_a, ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_addcdot(){ + ppc_grab_regsdab(); + ppc_result_d = ppc_result_a + ppc_result_b; + ppc_carry(ppc_result_a, ppc_result_d); + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_addco(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + ppc_result_d = ppc_result_a + ppc_result_b; + ppc_carry(ppc_result_a, ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_addcodot(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + ppc_result_d = ppc_result_a + ppc_result_b; + ppc_carry(ppc_result_a, ppc_result_d); + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_adde(){ + ppc_grab_regsdab(); + uint32_t grab_xer = ppc_state.ppc_spr[1] && 0x20000000; + ppc_result_d = ppc_result_a + ppc_result_b + grab_xer; + if (((grab_xer != 0) && (grab_xer > (~(ppc_result_b + ppc_result_a)))) || (ppc_result_d > ~ppc_result_a)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_store_result_regd(); +} + +void ppc_addedot(){ + ppc_grab_regsdab(); + uint32_t grab_xer = ppc_state.ppc_spr[1] && 0x20000000; + ppc_result_d = ppc_result_a + ppc_result_b + grab_xer; + ppc_changecrf0(ppc_result_d); + if (((ppc_result_b + grab_xer) < ppc_result_b) || (ppc_result_d < ppc_result_a)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_store_result_regd(); +} + +void ppc_addeo(){ + ppc_grab_regsdab(); + uint32_t grab_xer = ppc_state.ppc_spr[1] && 0x20000000; + ppc_setsoov(ppc_result_a, ppc_result_b + grab_xer); + ppc_result_d = ppc_result_a + ppc_result_b + grab_xer; + if (((ppc_result_b + grab_xer) < ppc_result_b) || (ppc_result_d < ppc_result_a)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_store_result_regd(); +} + +void ppc_addeodot(){ + ppc_grab_regsdab(); + uint32_t grab_xer = ppc_state.ppc_spr[1] && 0x20000000; + ppc_setsoov(ppc_result_a, ppc_result_b + grab_xer); + ppc_result_d = ppc_result_a + ppc_result_b + grab_xer; + if (((ppc_result_b + grab_xer) < ppc_result_b) || (ppc_result_d < ppc_result_a)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_addme(){ + ppc_grab_regsda(); + uint32_t grab_xer = ppc_state.ppc_spr[1] && 0x20000000; + ppc_result_d = ppc_result_a + grab_xer - 1; + if ((grab_xer - 1) > ~ppc_result_a){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_store_result_regd(); +} + +void ppc_addmedot(){ + ppc_grab_regsda(); + uint32_t grab_xer = ppc_state.ppc_spr[1] && 0x20000000; + ppc_result_d = ppc_result_a + grab_xer - 1; + if ((grab_xer - 1) > ~ppc_result_a){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_addmeo(){ + ppc_grab_regsda(); + uint32_t grab_xer = ppc_state.ppc_spr[1] && 0x20000000; + ppc_setsoov(ppc_result_a, grab_xer); + ppc_result_d = ppc_result_a + grab_xer - 1; + if ((grab_xer - 1) > ~ppc_result_a){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_store_result_regd(); +} + +void ppc_addmeodot(){ + ppc_grab_regsda(); + uint32_t grab_xer = (ppc_state.ppc_spr[1] && 0x20000000); + ppc_setsoov(ppc_result_a, grab_xer); + ppc_result_d = ppc_result_a + grab_xer - 1; + ppc_changecrf0(ppc_result_d); + if ((grab_xer - 1) > ~ppc_result_a){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_store_result_regd(); +} + +void ppc_addze(){ + ppc_grab_regsda(); + uint32_t grab_xer = (ppc_state.ppc_spr[1] && 0x20000000); + ppc_result_d = ppc_result_a + grab_xer; + if (grab_xer > ~ppc_result_a){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_store_result_regd(); +} + +void ppc_addzedot(){ + ppc_grab_regsda(); + uint32_t grab_xer = (ppc_state.ppc_spr[1] && 0x20000000); + ppc_result_d = ppc_result_a + grab_xer; + if (grab_xer > ~ppc_result_a){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_addzeo(){ + ppc_grab_regsda(); + uint32_t grab_xer = (ppc_state.ppc_spr[1] && 0x20000000); + ppc_setsoov(ppc_result_a, grab_xer); + ppc_result_d = ppc_result_a + grab_xer; + if (grab_xer > ~ppc_result_a){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_store_result_regd(); +} + +void ppc_addzeodot(){ + ppc_grab_regsda(); + uint32_t grab_xer = (ppc_state.ppc_spr[1] && 0x20000000); + ppc_setsoov(ppc_result_a, grab_xer); + ppc_result_d = ppc_result_a + grab_xer; + if (grab_xer > ~ppc_result_a){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subf(){ + ppc_grab_regsdab(); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + 1; + ppc_store_result_regd(); +} + +void ppc_subfdot(){ + ppc_grab_regsdab(); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + 1; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subfo(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + 1; + ppc_store_result_regd(); +} + +void ppc_subfodot(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + 1; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subfc(){ + ppc_grab_regsdab(); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + 1; + if (ppc_result_d < (not_this + 1)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subfcdot(){ + ppc_grab_regsdab(); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + 1; + if (ppc_result_d < (not_this + 1)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, ppc_result_d); + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subfco(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + 1; + if (ppc_result_d < (not_this + 1)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subfcodot(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + 1; + if (ppc_result_d < (not_this + 1)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, ppc_result_d); + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subfic(){ + ppc_grab_regsdasimm(); + not_this = ~ppc_result_a; + ppc_result_d = not_this + simm + 1; + if (ppc_result_d < (not_this + 1)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_store_result_regd(); +} + +void ppc_subfe(){ + ppc_grab_regsdab(); + uint32_t grab_xer = (ppc_state.ppc_spr[1] && 0x20000000); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + (ppc_state.ppc_spr[1] && 0x20000000); + if (ppc_result_d < (not_this + grab_xer)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subfedot(){ + ppc_grab_regsdab(); + uint32_t grab_xer = (ppc_state.ppc_spr[1] && 0x20000000); + not_this = ~ppc_result_a; + ppc_result_d = not_this + ppc_result_b + grab_xer; + if (ppc_result_d < (not_this + grab_xer)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, ppc_result_d); + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subfme(){ + ppc_grab_regsda(); + not_this = ~ppc_result_a; + uint32_t grab_xer = (ppc_state.ppc_spr[1] && 0x20000000); + ppc_result_d = not_this + grab_xer - 1; + if (ppc_result_a || grab_xer){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, grab_xer); + ppc_store_result_regd(); +} + +void ppc_subfmedot(){ + ppc_grab_regsda(); + not_this = ~ppc_result_a; + uint32_t grab_xer = (ppc_state.ppc_spr[1] && 0x20000000); + ppc_result_d = not_this + grab_xer - 1; + if (ppc_result_d < (not_this + grab_xer)){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, grab_xer); + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_subfze(){ + ppc_grab_regsda(); + not_this = ~ppc_result_a; + ppc_result_d = not_this + (ppc_state.ppc_spr[1] && 0x20000000); + if (ppc_result_d < not_this){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, (ppc_state.ppc_spr[1] && 0x20000000)); + ppc_store_result_regd(); +} + +void ppc_subfzedot(){ + ppc_grab_regsda(); + not_this = ~ppc_result_a; + ppc_result_d = not_this + (ppc_state.ppc_spr[1] && 0x20000000); + if (ppc_result_d < not_this){ + ppc_state.ppc_spr[1] |= 0x20000000; + } + else{ + ppc_state.ppc_spr[1] &= 0xDFFFFFFF; + } + ppc_carry(ppc_result_a, (ppc_state.ppc_spr[1] && 0x20000000)); + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_and(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d & ppc_result_b; + ppc_store_result_rega(); +} + +void ppc_anddot(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d & ppc_result_b; + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_andc(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d & ~(ppc_result_b); + ppc_store_result_rega(); +} + +void ppc_andcdot(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d & ~(ppc_result_b); + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_andidot(){ + ppc_grab_regssauimm(); + ppc_result_a = ppc_result_d & uimm; + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_andisdot(){ + ppc_grab_regssauimm(); + ppc_result_a = ppc_result_d & (uimm << 16); + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_nand(){ + ppc_grab_regssab(); + ppc_result_a = ~(ppc_result_d & ppc_result_b); + ppc_store_result_rega(); +} + +void ppc_nanddot(){ + ppc_grab_regssab(); + ppc_result_a = ~(ppc_result_d & ppc_result_b); + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_or(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d | ppc_result_b; + printf("OR Result: %x in Reg %d from Regs %d and %d \n", ppc_result_a, reg_a, reg_s, reg_b); + ppc_store_result_rega(); +} + +void ppc_ordot(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d | ppc_result_b; + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_orc(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d | ~(ppc_result_b); + ppc_store_result_rega(); +} + +void ppc_orcdot(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d | ~(ppc_result_b); + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_ori(){ + ppc_grab_regssauimm(); + ppc_result_a = ppc_result_d | uimm; + ppc_store_result_rega(); +} + +void ppc_oris(){ + ppc_grab_regssauimm(); + ppc_result_a = ppc_result_d | (uimm << 16); + ppc_store_result_rega(); +} + +void ppc_eqv(){ + ppc_grab_regssab(); + ppc_result_a = ~(ppc_result_d ^ ppc_result_b); + ppc_store_result_rega(); +} + +void ppc_eqvdot(){ + ppc_grab_regssab(); + ppc_result_a = ~(ppc_result_d ^ ppc_result_b); + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_nor(){ + ppc_grab_regssab(); + ppc_result_a = ~(ppc_result_d | ppc_result_b); + ppc_store_result_rega(); +} + +void ppc_nordot(){ + ppc_grab_regssab(); + ppc_result_a = ~(ppc_result_d | ppc_result_b); + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_xor(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d ^ ppc_result_b; + ppc_store_result_rega(); +} + +void ppc_xordot(){ + ppc_grab_regssab(); + ppc_result_a = ppc_result_d ^ ppc_result_b; + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_xori(){ + ppc_grab_regssauimm(); + ppc_result_a = ppc_result_d ^ uimm; + ppc_store_result_rega(); +} + +void ppc_xoris(){ + ppc_grab_regssauimm(); + ppc_result_a = ppc_result_d ^ (uimm << 16); + ppc_store_result_rega(); +} + +void ppc_neg(){ + ppc_grab_regsda(); + ppc_result_d = ~(ppc_result_a) + 1; + ppc_store_result_regd(); +} + +void ppc_negdot(){ + ppc_grab_regsda(); + ppc_result_d = ~(ppc_result_a) + 1; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_nego(){ + ppc_grab_regsda(); + ppc_result_d = ~(ppc_result_a) + 1; + ppc_state.ppc_spr[1] |= 0x40000000; + ppc_setsoov(ppc_result_d, 1); + ppc_store_result_regd(); +} + +void ppc_negodot(){ + ppc_grab_regsda(); + ppc_result_d = ~(ppc_result_a) + 1; + ppc_changecrf0(ppc_result_d); + ppc_state.ppc_spr[1] |= 0x40000000; + ppc_setsoov(ppc_result_d, 1); + ppc_store_result_regd(); +} + +void ppc_cntlzw(){ + ppc_grab_regssa(); + uint32_t trail = 0; + uint32_t bit_set = 0x80000000; + do{ + if ((ppc_result_d && bit_set) == 1){ + break; + } + bit_set = bit_set >> 1; + trail++; + } while (trail < 32); + ppc_result_a = trail; + ppc_store_result_rega(); +} + +void ppc_cntlzwdot(){ + ppc_grab_regssa(); + uint32_t trail = 0; + uint32_t bit_set = 0xF0000000; + do{ + if ((ppc_result_d && bit_set) == 1){ + break; + } + bit_set = bit_set >> 1; + trail++; + } while (trail < 32); + ppc_result_a = trail; + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_mulhwu(){ + ppc_grab_regsdab(); + uiproduct = (uint64_t) ppc_result_a * (uint64_t) ppc_result_b; + uiproduct = uiproduct >> 32; + ppc_result_d = uiproduct; + ppc_store_result_regd(); +} + +void ppc_mulhwudot(){ + ppc_grab_regsdab(); + uiproduct = (uint64_t) ppc_result_a * (uint64_t) ppc_result_b; + uiproduct = uiproduct >> 32; + ppc_result_d = uiproduct; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_mulhw(){ + ppc_grab_regsdab(); + siproduct = (int64_t) ppc_result_a * (int64_t) ppc_result_b; + siproduct = siproduct >> 32; + ppc_result_d = (uint32_t) siproduct; + ppc_store_result_regd(); +} + +void ppc_mulhwdot(){ + ppc_grab_regsdab(); + siproduct = (int64_t) ppc_result_a * (int64_t) ppc_result_b; + siproduct = siproduct >> 32; + ppc_result_d = (uint32_t) siproduct; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_mullw(){ + ppc_grab_regsdab(); + siproduct = (int64_t) ppc_result_a * (int64_t) ppc_result_b; + siproduct &= 4294967295; + ppc_result_d = (uint32_t) siproduct; + ppc_store_result_regd(); +} + +void ppc_mullwdot(){ + ppc_grab_regsdab(); + siproduct = ppc_result_a * ppc_result_b; + siproduct &= 4294967295; + ppc_result_d = (uint32_t) siproduct; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_mullwo(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + siproduct = ppc_result_a * ppc_result_b; + siproduct &= 4294967295; + ppc_result_d = (uint32_t) siproduct; + ppc_store_result_regd(); +} + +void ppc_mullwodot(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + siproduct = ppc_result_a * ppc_result_b; + siproduct &= 4294967295; + ppc_result_d = (uint32_t) siproduct; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_mulli(){ + ppc_grab_regsdasimm(); + int64_t siproduct = (int64_t)((ppc_result_a) * ((int64_t)simm)); + siproduct &= 4294967295; + ppc_result_d = (uint32_t) siproduct; + ppc_store_result_regd(); +} + +void ppc_divw(){ + ppc_grab_regsdab(); + sidiv_result = (int32_t) ppc_result_a / (int32_t) ppc_result_b; + ppc_result_d = (uint32_t) sidiv_result; + ppc_store_result_regd(); +} + +void ppc_divwdot(){ + ppc_grab_regsdab(); + sidiv_result = (int32_t) ppc_result_a / (int32_t) ppc_result_b; + ppc_result_d = (uint32_t) sidiv_result; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_divwo(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + sidiv_result = (int32_t) ppc_result_a / (int32_t) ppc_result_b; + ppc_result_d = (uint32_t) sidiv_result; + ppc_store_result_regd(); +} + +void ppc_divwodot(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + sidiv_result = (int32_t) ppc_result_a / (int32_t) ppc_result_b; + ppc_result_d = (uint32_t) sidiv_result; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_divwu(){ + ppc_grab_regsdab(); + uidiv_result = ppc_result_a / ppc_result_b; + ppc_result_d = uidiv_result; + ppc_store_result_regd(); +} + +void ppc_divwudot(){ + ppc_grab_regsdab(); + uidiv_result = ppc_result_a / ppc_result_b; + ppc_result_d = uidiv_result; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +void ppc_divwuo(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + uidiv_result = ppc_result_a / ppc_result_b; + ppc_result_d = uidiv_result; + ppc_store_result_regd(); +} + +void ppc_divwuodot(){ + ppc_grab_regsdab(); + ppc_setsoov(ppc_result_a, ppc_result_b); + uidiv_result = ppc_result_a / ppc_result_b; + ppc_result_d = uidiv_result; + ppc_changecrf0(ppc_result_d); + ppc_store_result_regd(); +} + +//Value shifting + +void ppc_slw(){ + ppc_grab_regssab(); + ppc_result_a = (ppc_result_b < 32)?(ppc_result_d << ppc_result_b):0; + ppc_store_result_rega(); +} + +void ppc_slwdot(){ + ppc_grab_regssab(); + ppc_result_a = (ppc_result_b < 32)?(ppc_result_d << ppc_result_b):0; + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_srw(){ + ppc_grab_regssab(); + ppc_result_a = (ppc_result_b < 32)?(ppc_result_d >> ppc_result_b):0; + ppc_store_result_rega(); +} + +void ppc_srwdot(){ + ppc_grab_regssab(); + ppc_result_a = (ppc_result_b < 32)?(ppc_result_d >> ppc_result_b):0; + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_sraw(){ + ppc_grab_regssab(); + + if (ppc_result_b > 32){ + ppc_result_a = ((ppc_result_d) > 0x7FFFFFFF)?0xFFFFFFFF:0x0; + ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0); + } + else{ + ppc_result_a = (uint32_t)((int32_t)ppc_result_d >> ppc_result_b); + ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0); + } + ppc_store_result_rega(); +} + +void ppc_srawdot(){ + ppc_grab_regssab(); + if (ppc_result_b > 32){ + ppc_result_a = ((ppc_result_d) > 0x7FFFFFFF)?0xFFFFFFFF:0x0; + ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0); + } + else{ + ppc_result_a = (uint32_t)((int32_t)ppc_result_d >> ppc_result_b); + ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0); + } + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_srawi(){ + ppc_grab_regssa(); + rot_sh = (ppc_cur_instruction >> 11) & 31; + + ppc_result_a = (uint32_t)((int32_t)ppc_result_d >> rot_sh); + ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0); + + ppc_store_result_rega(); +} + +void ppc_srawidot(){ + ppc_grab_regssa(); + rot_sh = (ppc_cur_instruction >> 11) & 31; + + ppc_result_a = (uint32_t)((int32_t)ppc_result_d >> rot_sh); + ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0); + + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_rlwimi(){ + ppc_grab_regssa(); + rot_sh = (ppc_cur_instruction >> 11) & 31; + rot_mb = (ppc_cur_instruction >> 6) & 31; + rot_me = (ppc_cur_instruction >> 1) & 31; + uint32_t step1 = (0xFFFFFFFF >> (rot_me + 1)) ^ (0xFFFFFFFF >> rot_mb); + uint32_t step2 = (rot_me < rot_mb)? ~step1 : step1; + uint32_t step3 = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32-rot_sh))); + ppc_result_a = (ppc_result_a & ~step2) | (step3 & step2); + if ((ppc_cur_instruction & 0x01) == 1){ + ppc_changecrf0(ppc_result_a); + } + ppc_store_result_rega(); +} + +void ppc_rlwinm(){ + ppc_grab_regssa(); + rot_sh = (ppc_cur_instruction >> 11) & 31; + rot_mb = (ppc_cur_instruction >> 6) & 31; + rot_me = (ppc_cur_instruction >> 1) & 31; + uint32_t step1 = (0xFFFFFFFF >> (rot_me + 1)) ^ (0xFFFFFFFF >> rot_mb); + uint32_t step2 = (rot_me < rot_mb)? ~step1 : step1; + uint32_t step3 = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32-rot_sh))); + ppc_result_a = step2 & step3; + if ((ppc_cur_instruction & 0x01) == 1){ + ppc_changecrf0(ppc_result_a); + } + ppc_store_result_rega(); +} + +void ppc_rlwnm(){ + ppc_grab_regssab(); + rot_mb = (ppc_cur_instruction >> 6) & 31; + rot_me = (ppc_cur_instruction >> 1) & 31; + uint32_t step1 = (0xFFFFFFFF >> (rot_me + 1)) ^ (0xFFFFFFFF >> rot_mb); + uint32_t step2 = (rot_me < rot_mb)? ~step1 : step1; + uint32_t step3 = ((ppc_result_d << ppc_result_b) | (ppc_result_d >> (32-ppc_result_b))); + ppc_result_a = step2 & step3; + if ((ppc_cur_instruction & 0x01) == 1){ + ppc_changecrf0(ppc_result_a); + } + ppc_store_result_rega(); +} + +void ppc_mfcr(){ + reg_d = (ppc_cur_instruction >> 21) & 31; + printf("CR: %x \n", ppc_state.ppc_cr); + ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_cr; +} + +void ppc_mtsr(){ + if ((ppc_state.ppc_msr && 0x4000) == 0){ + reg_s = (ppc_cur_instruction >> 21) & 31; + grab_sr = (ppc_cur_instruction >> 16) & 15; + ppc_state.ppc_sr[grab_sr] = ppc_state.ppc_gpr[reg_s]; + } +} + +void ppc_mtsrin(){ + if ((ppc_state.ppc_msr && 0x4000) == 0){ + ppc_grab_regssb(); + grab_sr = ppc_result_b & 15; + ppc_state.ppc_sr[grab_sr] = ppc_result_d; + } +} + +void ppc_mfsr(){ + if ((ppc_state.ppc_msr && 0x4000) == 0){ + reg_d = (ppc_cur_instruction >> 21) & 31; + grab_sr = (ppc_cur_instruction >> 16) & 15; + ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_sr[grab_sr]; + ppc_store_result_regd(); + } +} + +void ppc_mfsrin(){ + if ((ppc_state.ppc_msr && 0x4000) == 0){ + ppc_grab_regssb(); + grab_sr = ppc_result_b & 15; + ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_sr[grab_sr]; + ppc_store_result_regd(); + } +} + +void ppc_mfmsr(){ + if ((ppc_state.ppc_msr && 0x4000) == 0){ + reg_d = (ppc_cur_instruction >> 21) & 31; + ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_msr; + ppc_store_result_regd(); + } +} + +void ppc_mtmsr(){ + //if ((ppc_state.ppc_msr && 0x4000) == 0){ + reg_s = (ppc_cur_instruction >> 21) & 31; + ppc_state.ppc_msr = ppc_state.ppc_spr[reg_s]; + msr_status_update(); + //} +} + +void ppc_mfspr(){ + uint32_t ref_spr = (((ppc_cur_instruction >> 11) & 31) << 5) | ((ppc_cur_instruction >> 16) & 31); + printf("MFSPR SPR REF: %d \n", ref_spr); + reg_d = (ppc_cur_instruction >> 21) & 31; + ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_spr[ref_spr]; + printf("Contained inside Reg %d: %x \n", reg_d, ppc_state.ppc_gpr[reg_d]); +} + +void ppc_mtspr(){ + uint32_t ref_spr = (((ppc_cur_instruction >> 11) & 31) << 5) | ((ppc_cur_instruction >> 16) & 31); + printf("MTSPR SPR REF: %d \n", ref_spr); + reg_s = (ppc_cur_instruction >> 21) & 31; + printf("Contained inside Reg %d: %x \n", reg_s, ppc_state.ppc_gpr[reg_s]); + + if (ref_spr != 287){ + ppc_state.ppc_spr[ref_spr] = ppc_state.ppc_gpr[reg_s]; + } + + switch(ref_spr){ + //Mirror the TBRs in the SPR range to the user-mode TBRs. + case 268: + ppc_state.ppc_tbr[0] = ppc_state.ppc_gpr[reg_s]; + break; + case 269: + ppc_state.ppc_tbr[1] = ppc_state.ppc_gpr[reg_s]; + break; + case 528: + case 529: + case 530: + case 531: + case 532: + case 533: + case 534: + case 535: + ibat_update(); + std::cout << "IBAT CHANGED!" <> 11) & 31) << 5) | ((ppc_cur_instruction >> 16) & 31); + reg_d = (ppc_cur_instruction >> 21) & 31; + switch(ref_spr){ + case 268: + ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_tbr[0]; + break; + case 269: + ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_tbr[1]; + break; + default: + std::cout << "Invalid TBR access attempted!" << std::endl; + } +} + +void ppc_mtcrf(){ + uint32_t cr_mask = 0; + ppc_grab_regssa(); + crm = ((ppc_cur_instruction >> 12) & 255); + //check this + cr_mask += ((crm && 128))? 0xF0000000 : 0x00000000; + cr_mask += ((crm && 64))? 0x0F000000 : 0x00000000; + cr_mask += ((crm && 32))? 0x00F00000 : 0x00000000; + cr_mask += ((crm && 16))? 0x000F0000 : 0x00000000; + cr_mask += ((crm && 8))? 0x0000F000 : 0x00000000; + cr_mask += ((crm && 4))? 0x00000F00 : 0x00000000; + cr_mask += ((crm && 2))? 0x000000F0 : 0x00000000; + cr_mask += ((crm && 1))? 0x0000000F : 0x00000000; + ppc_state.ppc_cr = (ppc_result_d & cr_mask) | (ppc_state.ppc_cr & ~(cr_mask)); +} + +void ppc_mcrxr(){ + crf_d = (ppc_cur_instruction >> 23) & 7; + crf_d = crf_d << 2; + ppc_state.ppc_cr = (ppc_state.ppc_cr & ~(0xF0000000 >> crf_d)) | ((ppc_state.ppc_spr[1] & 0xF0000000) >> crf_d); + ppc_state.ppc_spr[1] &= 0x0FFFFFFF; +} + +void ppc_extsb(){ + ppc_grab_regssa(); + ppc_result_a = (ppc_result_d < 0x80)?(ppc_result_d & 0x000000FF):(0xFFFFFF00 | (ppc_result_d & 0x000000FF)); + ppc_store_result_rega(); +} + +void ppc_extsbdot(){ + ppc_grab_regssa(); + ppc_result_a = (ppc_result_d < 0x80)?(ppc_result_d & 0x000000FF):(0xFFFFFF00 | (ppc_result_d & 0x000000FF)); + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +void ppc_extsh(){ + ppc_grab_regssa(); + ppc_result_a = (ppc_result_d < 0x8000)?(ppc_result_d & 0x0000FFFF):(0xFFFF0000 | (ppc_result_d & 0x0000FFFF)); + ppc_store_result_rega(); +} + +void ppc_extshdot(){ + ppc_grab_regssa(); + ppc_result_a = (ppc_result_d < 0x8000)?(ppc_result_d & 0x0000FFFF):(0xFFFF0000 | (ppc_result_d & 0x0000FFFF)); + ppc_changecrf0(ppc_result_a); + ppc_store_result_rega(); +} + +//Branching Instructions + +//The last two bytes of the instruction are used for determining how the branch happens. +//The middle 24 bytes are the 24-bit address to use for branching to. + + +void ppc_b(){ + uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC); + adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000 + quick_test); + ppc_next_instruction_address = (uint32_t)(ppc_state.ppc_pc + adr_li); + grab_branch = 1; +} + +void ppc_bl(){ + uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC); + adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000 + quick_test); + ppc_next_instruction_address = (uint32_t)(ppc_state.ppc_pc + adr_li); + ppc_state.ppc_spr[8] = (uint32_t)(ppc_state.ppc_pc + 4); + grab_branch = 1; +} + +void ppc_ba(){ + uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC); + adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000 + quick_test); + ppc_next_instruction_address = adr_li; + grab_branch = 1; +} + +void ppc_bla(){ + uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC); + adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000 + quick_test); + ppc_next_instruction_address = adr_li; + ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4; + grab_branch = 1; +} + +void ppc_bc(){ + br_bo = (ppc_cur_instruction >> 21) & 31; + br_bi = (ppc_cur_instruction >> 16) & 31; + br_bd = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFC)); + uint32_t ctr_ok = 1; + uint32_t cnd_ok = 1; + + if (!(br_bo & 0x04)){ + (ppc_state.ppc_spr[9])--; + } + ctr_ok = ((br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) ^ (br_bo & 0x02))); + cnd_ok = ((br_bo & 0x10) || !((ppc_state.ppc_cr & (0x80000000 >> br_bi)) ^ (br_bo & 0x08))); + + if (ctr_ok && cnd_ok){ + ppc_next_instruction_address = (ppc_state.ppc_pc + br_bd); + grab_branch = 1; + } + else{ + printf("BRANCH FAILED: %d %d", ctr_ok, cnd_ok); + } +} + +void ppc_bca(){ + br_bo = (ppc_cur_instruction >> 21) & 31; + br_bi = (ppc_cur_instruction >> 16) & 31; + br_bd = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFC)); + uint32_t ctr_ok = 1; + uint32_t cnd_ok = 1; + + if (!(br_bo & 0x04)){ + (ppc_state.ppc_spr[9])--; + } + ctr_ok = ((br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) ^ (br_bo & 0x02))); + cnd_ok = ((br_bo & 0x10) || !((ppc_state.ppc_cr & (0x80000000 >> br_bi)) ^ (br_bo & 0x08))); + + if (ctr_ok && cnd_ok){ + ppc_next_instruction_address = br_bd; + grab_branch = 1; + } +} + +void ppc_bcl(){ + + br_bo = (ppc_cur_instruction >> 21) & 31; + br_bi = (ppc_cur_instruction >> 16) & 31; + br_bd = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFC)); + uint32_t ctr_ok = 1; + uint32_t cnd_ok = 1; + + if (!(br_bo & 0x04)){ + (ppc_state.ppc_spr[9])--; + } + ctr_ok = ((br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) ^ (br_bo & 0x02))); + cnd_ok = ((br_bo & 0x10) || !((ppc_state.ppc_cr & (0x80000000 >> br_bi)) ^ (br_bo & 0x08))); + + if (ctr_ok && cnd_ok){ + ppc_next_instruction_address = (ppc_state.ppc_pc + br_bd); + grab_branch = 1; + } + ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4; +} + +void ppc_bcla(){ + + br_bo = (ppc_cur_instruction >> 21) & 31; + br_bi = (ppc_cur_instruction >> 16) & 31; + br_bd = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFC)); + uint32_t ctr_ok = 1; + uint32_t cnd_ok = 1; + + if (!(br_bo & 0x04)){ + (ppc_state.ppc_spr[9])--; + } + ctr_ok = ((br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) ^ (br_bo & 0x02))); + cnd_ok = ((br_bo & 0x10) || !((ppc_state.ppc_cr & (0x80000000 >> br_bi)) ^ (br_bo & 0x08))); + + if (ctr_ok && cnd_ok){ + ppc_next_instruction_address = br_bd; + grab_branch = 1; + } + ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4; +} + +void ppc_bcctr(){ + br_bo = (ppc_cur_instruction >> 21) & 31; + br_bi = (ppc_cur_instruction >> 16) & 31; + + uint32_t cnd_ok = 1; + cnd_ok = ((br_bo & 0x10) || !((ppc_state.ppc_cr & (0x80000000 >> br_bi)) ^ (br_bo & 0x08))); + + if (cnd_ok){ + adr_li = (ppc_state.ppc_spr[9] & 0xFFFFFFFC); + ppc_next_instruction_address = adr_li; + grab_branch = 1; + } +} + +void ppc_bcctrl(){ + br_bo = (ppc_cur_instruction >> 21) & 31; + br_bi = (ppc_cur_instruction >> 16) & 31; + + uint32_t cnd_ok = 1; + cnd_ok = ((br_bo & 0x10) || !((ppc_state.ppc_cr & (0x80000000 >> br_bi)) ^ (br_bo & 0x08))); + + if (cnd_ok){ + adr_li = (ppc_state.ppc_spr[9] & 0xFFFFFFFC); + ppc_next_instruction_address = adr_li; + grab_branch = 1; + } + ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4; +} + +void ppc_bclr(){ + br_bo = (ppc_cur_instruction >> 21) & 31; + br_bi = (ppc_cur_instruction >> 16) & 31; + uint32_t ctr_ok = 1; + uint32_t cnd_ok = 1; + + if (!(br_bo & 0x04)){ + (ppc_state.ppc_spr[9])--; + } + ctr_ok = ((br_bo & 0x04) | ((ppc_state.ppc_spr[9] != 0) ^ (br_bo & 0x02))); + cnd_ok = ((br_bo & 0x10) || !((ppc_state.ppc_cr & (0x80000000 >> br_bi)) ^ (br_bo & 0x08))); + + if (ctr_ok && cnd_ok){ + ppc_next_instruction_address = (ppc_state.ppc_spr[8] & 0xFFFFFFFC); + grab_branch = 1; + } + else{ + printf("Branch failed. \n"); + } +} + +void ppc_bclrl(){ + br_bo = (ppc_cur_instruction >> 21) & 31; + br_bi = (ppc_cur_instruction >> 16) & 31; + uint32_t ctr_ok = 1; + uint32_t cnd_ok = 1; + if (!(br_bo & 0x04)){ + (ppc_state.ppc_spr[9])--; + } + ctr_ok = ((br_bo & 0x04) | ((ppc_state.ppc_spr[9] != 0) ^ (br_bo & 0x02))); + cnd_ok = ((br_bo & 0x10) || !((ppc_state.ppc_cr & (0x80000000 >> br_bi)) ^ (br_bo & 0x08))); + + if (ctr_ok && cnd_ok){ + ppc_next_instruction_address = (ppc_state.ppc_spr[8] & 0xFFFFFFFC); + grab_branch = 1; + } + ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4; +} +//Compare Instructions + +void ppc_cmp(){ + //if (!((ppc_cur_instruction >> 21) && 0x1)){ + crf_d = (ppc_cur_instruction >> 23) & 7; + crf_d = crf_d << 2; + ppc_grab_regssab(); + xercon = (ppc_state.ppc_spr[1] & 0x80000000) >> 3; + cmp_c = (((int32_t)ppc_result_a) == ((int32_t)ppc_result_b)) ? 0x20000000 : (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) ? 0x40000000 : 0x80000000; + ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d)); + //} + //else{ + // printf("Warning: Invalid CMP Instruction."); + //} +} + +void ppc_cmpi(){ + //if (!((ppc_cur_instruction >> 21) && 0x1)){ + crf_d = (ppc_cur_instruction >> 23) & 7; + crf_d = crf_d << 2; + ppc_grab_regssasimm(); + xercon = (ppc_state.ppc_spr[1] & 0x80000000) >> 3; + cmp_c = (((int32_t)ppc_result_a) == simm) ? 0x20000000 : (((int32_t)ppc_result_a) > simm) ? 0x40000000 : 0x80000000; + ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d)); + // } + //else{ + // printf("Warning: Invalid CMP Instruction."); + //} +} + +void ppc_cmpl(){ + //if (!((ppc_cur_instruction >> 21) && 0x1)){ + crf_d = (ppc_cur_instruction >> 23) & 7; + crf_d = crf_d << 2; + ppc_grab_regssab(); + xercon = (ppc_state.ppc_spr[1] & 0x80000000) >> 3; + cmp_c = (ppc_result_a == ppc_result_b) ? 0x20000000 : (ppc_result_a > ppc_result_b) ? 0x40000000 : 0x80000000; + ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d)); + //} + //else{ + // printf("Warning: Invalid CMP Instruction."); + //} +} + +void ppc_cmpli(){ + // if (!((ppc_cur_instruction >> 21) && 0x1)){ + crf_d = (ppc_cur_instruction >> 23) & 7; + crf_d = crf_d << 2; + ppc_grab_regssauimm(); + xercon = (ppc_state.ppc_spr[1] & 0x80000000) >> 3; + cmp_c = (ppc_result_a == uimm) ? 0x20000000 : (ppc_result_a > uimm) ? 0x40000000 : 0x80000000; + ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d)); + // } + //else{ + // printf("Warning: Invalid CMP Instruction."); + // } +} + +//Condition Register Changes + +void ppc_crand(){ + ppc_grab_regsdab(); + if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) & (ppc_state.ppc_cr && (0x80000000 >> reg_b))){ + ppc_state.ppc_cr |= (0x80000000 >> reg_d); + } + else{ + ppc_state.ppc_cr &= ~(0x80000000 >> reg_d); + } +} +void ppc_crandc(){ + ppc_grab_regsdab(); + if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) & ~(ppc_state.ppc_cr && (0x80000000 >> reg_b))){ + ppc_state.ppc_cr |= (0x80000000 >> reg_d); + } + else{ + ppc_state.ppc_cr &= ~(0x80000000 >> reg_d); + } +} +void ppc_creqv(){ + ppc_grab_regsdab(); + if (!((ppc_state.ppc_cr && (0x80000000 >> reg_a)) ^ !(ppc_state.ppc_cr && (0x80000000 >> reg_b)))){ + ppc_state.ppc_cr |= (0x80000000 >> reg_d); + } + else{ + ppc_state.ppc_cr &= ~(0x80000000 >> reg_d); + } +} +void ppc_crnand(){ + ppc_grab_regsdab(); + if (!((ppc_state.ppc_cr && (0x80000000 >> reg_a)) & (ppc_state.ppc_cr && (0x80000000 >> reg_b)))){ + ppc_state.ppc_cr |= (0x80000000 >> reg_d); + } + else{ + ppc_state.ppc_cr &= ~(0x80000000 >> reg_d); + } +} +void ppc_crnor(){ + ppc_grab_regsdab(); + if (!((ppc_state.ppc_cr && (0x80000000 >> reg_a)) | ~(ppc_state.ppc_cr && (0x80000000 >> reg_b)))){ + ppc_state.ppc_cr |= (0x80000000 >> reg_d); + } + else{ + ppc_state.ppc_cr &= ~(0x80000000 >> reg_d); + } +} + +void ppc_cror(){ + ppc_grab_regsdab(); + if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) | (ppc_state.ppc_cr && (0x80000000 >> reg_b))){ + ppc_state.ppc_cr |= (0x80000000 >> reg_d); + } + else{ + ppc_state.ppc_cr &= ~(0x80000000 >> reg_d); + } +} +void ppc_crorc(){ + ppc_grab_regsdab(); + if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) | ~(ppc_state.ppc_cr && (0x80000000 >> reg_b))){ + ppc_state.ppc_cr |= (0x80000000 >> reg_d); + } + else{ + ppc_state.ppc_cr &= ~(0x80000000 >> reg_d); + } +} +void ppc_crxor(){ + ppc_grab_regsdab(); + if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) ^ (ppc_state.ppc_cr && (0x80000000 >> reg_b))){ + ppc_state.ppc_cr |= (0x80000000 >> reg_d); + } + else{ + ppc_state.ppc_cr &= ~(0x80000000 >> reg_d); + } +} + +//Processor MGMT Fns. + +void ppc_rfi(){ + uint32_t new_srr1_val = (ppc_state.ppc_spr[27] & 0x87C0FF73); + uint32_t new_msr_val = (ppc_state.ppc_msr & ~(0x87C0FF73)); + ppc_state.ppc_msr = (new_msr_val | new_srr1_val) & 0xFFFBFFFF; + ppc_next_instruction_address = ppc_state.ppc_spr[26] & 0xFFFFFFFC; + + grab_return = true; +} + +void ppc_sc(){ + ppc_expection_handler(0x0C00, 0x20000); +} + +void ppc_tw(){ + reg_a = (ppc_cur_instruction >> 11) & 31; + reg_b = (ppc_cur_instruction >> 16) & 31; + ppc_to = (ppc_cur_instruction >> 21) & 31; + if ((((int32_t)ppc_state.ppc_gpr[reg_a] < (int32_t)ppc_state.ppc_gpr[reg_b]) & (ppc_to && 0x10)) || \ + (((int32_t)ppc_state.ppc_gpr[reg_a] > (int32_t)ppc_state.ppc_gpr[reg_b]) & (ppc_to && 0x08)) || \ + (((int32_t)ppc_state.ppc_gpr[reg_a] == (int32_t)ppc_state.ppc_gpr[reg_b]) & (ppc_to && 0x04)) || \ + ((ppc_state.ppc_gpr[reg_a] < ppc_state.ppc_gpr[reg_b]) & (ppc_to && 0x02)) || \ + ((ppc_state.ppc_gpr[reg_a] > ppc_state.ppc_gpr[reg_b]) & (ppc_to && 0x01))){ + ppc_expection_handler(0x0700, 0x20000); + } +} + +void ppc_twi(){ + simm = (int32_t)((int16_t)((ppc_cur_instruction) & 65535)); + reg_b = (ppc_cur_instruction >> 16) & 31; + ppc_to = (ppc_cur_instruction >> 21) & 31; + if ((((int32_t)ppc_state.ppc_gpr[reg_a] < simm) & (ppc_to && 0x10)) || \ + (((int32_t)ppc_state.ppc_gpr[reg_a] > simm) & (ppc_to && 0x08)) || \ + (((int32_t)ppc_state.ppc_gpr[reg_a] == simm) & (ppc_to && 0x04)) || \ + ((ppc_state.ppc_gpr[reg_a] < (uint32_t)simm) & (ppc_to && 0x02)) || \ + ((ppc_state.ppc_gpr[reg_a] > (uint32_t)simm) & (ppc_to && 0x01))){ + ppc_expection_handler(0x0700, 0x20000); + } +} + +void ppc_eieio(){ + std::cout << "Oops. Placeholder for eieio." << std::endl; +} + +void ppc_isync(){ + std::cout << "Oops. Placeholder for isync." << std::endl; +} + +void ppc_sync(){ + std::cout << "Oops. Placeholder for sync." << std::endl; +} + +void ppc_icbi(){ + std::cout << "Oops. Placeholder for icbi." << std::endl; +} + +void ppc_dcbf(){ + std::cout << "Oops. Placeholder for dcbf." << std::endl; +} + +void ppc_dcbi(){ + std::cout << "Oops. Placeholder for dcbi." << std::endl; +} + +void ppc_dcbst(){ + std::cout << "Oops. Placeholder for dcbst." << std::endl; +} + +void ppc_dcbt(){ + //Not needed, the HDI reg is touched to no-op this instruction. + return; +} + +void ppc_dcbtst(){ + //Not needed, the HDI reg is touched to no-op this instruction. + return; +} + +void ppc_dcbz(){ + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + if (!(ppc_state.ppc_pc % 32) && (ppc_state.ppc_pc < 0xFFFFFFE0)){ + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickinsert_translate(ppc_effective_address, 0, 4); + address_quickinsert_translate((ppc_effective_address + 4), 0, 4); + address_quickinsert_translate((ppc_effective_address + 8), 0, 4); + address_quickinsert_translate((ppc_effective_address + 12), 0, 4); + address_quickinsert_translate((ppc_effective_address + 16), 0, 4); + address_quickinsert_translate((ppc_effective_address + 20), 0, 4); + address_quickinsert_translate((ppc_effective_address + 24), 0, 4); + address_quickinsert_translate((ppc_effective_address + 28), 0, 4); + } + else{ + ppc_expection_handler(0x0600, 0x00000); + } +} + +//Integer Load and Store Functions + +void ppc_stb(){ + ppc_grab_regssa(); + grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF))); + ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d); + printf("STB Storage Area: %x \n",ppc_effective_address); + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 1); +} + +void ppc_stbx(){ + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 1); +} + +void ppc_stbu(){ + ppc_grab_regssa(); + grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF))); + if (reg_a != 0){ + ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d); + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 1); + } +} + +void ppc_stbux(){ + ppc_grab_regssab(); + if (reg_a != 0){ + ppc_effective_address = ppc_result_a + reg_b; + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 1); + } + else{ + ppc_expection_handler(0x07000, 0x20000); + } + ppc_result_a = ppc_effective_address; + ppc_store_result_rega(); +} + +void ppc_sth(){ + ppc_grab_regssa(); + grab_d = (uint32_t)((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_result_d, 2); +} + +void ppc_sthu(){ + ppc_grab_regssa(); + grab_d = (uint32_t)((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_result_d, 2); +} + +void ppc_sthux(){ + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 2); + ppc_result_a = ppc_effective_address; + ppc_store_result_rega(); +} + +void ppc_sthx(){ + ppc_grab_regssab(); + if (reg_a != 0){ + ppc_effective_address = ppc_result_a + ppc_result_b; + } + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 2); +} + +void ppc_sthbrx(){ + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + ppc_result_d = (uint32_t)(rev_endian16((uint16_t)ppc_result_d)); + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 2); +} + +void ppc_stw(){ + ppc_grab_regssa(); + grab_d = (uint32_t)((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_result_d, 4); +} + +void ppc_stwx(){ + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 4); +} + +void ppc_stwcx(){ + //PLACEHOLDER CODE FOR STWCX - We need to check for reserve memory + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + if (ppc_state.ppc_reserve){ + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 4); + ppc_state.ppc_cr |= (ppc_state.ppc_spr[1] && 0x80000000)?0x30000000:0x20000000; + ppc_state.ppc_reserve = false; + } + else{ + ppc_state.ppc_cr |= (ppc_state.ppc_spr[1] && 0x80000000)?0x10000000:0; + } +} + +void ppc_stwu(){ + ppc_grab_regssa(); + grab_d = (uint32_t)((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_result_d, 4); + ppc_result_a = ppc_effective_address; + ppc_store_result_rega(); +} + +void ppc_stwux(){ + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 4); + ppc_result_a = ppc_effective_address; + ppc_store_result_rega(); +} + +void ppc_stwbrx(){ + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + printf("STWBRX Storage Area: %x \n",ppc_effective_address); + ppc_result_d = rev_endian32(ppc_result_d); + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 4); +} + +void ppc_stmw(){ + ppc_grab_regssa(); + grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF))); + ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d); + //How many words to store in memory - using a do-while for this + do{ + address_quickinsert_translate(ppc_effective_address, ppc_result_d, 4); + ppc_effective_address +=4; + reg_d++; + }while (reg_d < 32); +} + +void ppc_lbz(){ + ppc_grab_regsda(); + grab_d = (uint32_t)((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_result_d, 1); + printf("LBZ Storage Area: %x \n",ppc_effective_address); + ppc_result_d = return_value; + return_value = 0; + ppc_store_result_regd(); +} + +void ppc_lbzu(){ + ppc_grab_regsda(); + grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF))); + if ((reg_a != reg_d) || reg_a != 0){ + ppc_effective_address = ppc_result_a + grab_d; + } + else{ + ppc_expection_handler(0x0700, 0x20000); + } + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1); + ppc_result_d = return_value; + return_value = 0; + ppc_result_a = ppc_effective_address; + ppc_store_result_regd(); + ppc_store_result_rega(); +} + +void ppc_lbzx(){ + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickgrab_translate((ppc_effective_address), ppc_result_d, 1); + ppc_result_d = return_value; + return_value = 0; + ppc_store_result_regd(); +} + +void ppc_lbzux(){ + ppc_grab_regsdab(); + if ((reg_a != reg_d) || reg_a != 0){ + ppc_effective_address = ppc_result_a + ppc_result_b; + } + else{ + ppc_expection_handler(0x0700, 0x20000); + } + address_quickgrab_translate((ppc_effective_address), ppc_result_d, 1); + ppc_result_d = return_value; + return_value = 0; + ppc_result_a = ppc_effective_address; + ppc_store_result_regd(); + ppc_store_result_rega(); +} + + +void ppc_lhz(){ + ppc_grab_regsda(); + grab_d = (uint32_t)((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_result_d, 2); + ppc_result_d = return_value; + return_value = 0; + ppc_store_result_regd(); +} + +void ppc_lhzu(){ + ppc_grab_regsda(); + grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF))); + ppc_effective_address = ppc_result_a + grab_d; + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 2); + ppc_result_d = return_value; + return_value = 0; + ppc_result_a = ppc_effective_address; + ppc_store_result_regd(); + ppc_store_result_rega(); +} + +void ppc_lhzx(){ + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickgrab_translate((ppc_effective_address), ppc_result_d, 2); + ppc_result_d = return_value; + return_value = 0; + ppc_store_result_regd(); +} + +void ppc_lhzux(){ + ppc_grab_regsdab(); + ppc_effective_address = ppc_result_a + ppc_result_b; + address_quickgrab_translate((ppc_effective_address), ppc_result_d, 2); + ppc_result_d = return_value; + return_value = 0; + ppc_result_a = ppc_effective_address; + ppc_store_result_regd(); + ppc_store_result_rega(); +} + +void ppc_lha(){ + ppc_grab_regsda(); + grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF))); + ppc_effective_address = (reg_a == 0)?grab_d:(uint32_t)(ppc_result_a + grab_d); + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 2); + uint16_t go_this = (uint16_t)return_value; + if (go_this && 0x8000){ + ppc_result_d = 0xFFFF0000 | (uint32_t)return_value; + ppc_store_result_regd(); + } + else{ + ppc_result_d = (uint32_t)return_value; + ppc_store_result_regd(); + } + return_value = 0; +} + +void ppc_lhau(){ + ppc_grab_regsda(); + grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF))); + ppc_effective_address = (reg_a == 0)?grab_d:(uint32_t)(ppc_result_a + grab_d); + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 2); + uint16_t go_this = (uint16_t)return_value; + if (go_this && 0x8000){ + ppc_result_d = 0xFFFF0000 | (uint32_t)return_value; + ppc_store_result_regd(); + } + else{ + ppc_result_d = (uint32_t)return_value; + ppc_store_result_regd(); + } + return_value = 0; + ppc_result_a = ppc_effective_address; + ppc_store_result_rega(); +} + +void ppc_lhaux(){ + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 2); + uint16_t go_this = (uint16_t)return_value; + if (go_this && 0x8000){ + ppc_result_d = 0xFFFF0000 | (uint32_t)return_value; + ppc_store_result_regd(); + } + else{ + ppc_result_d = (uint32_t)return_value; + ppc_store_result_regd(); + } + return_value = 0; + ppc_result_a = ppc_effective_address; + ppc_store_result_rega(); +} + +void ppc_lhax(){ + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 2); + uint16_t go_this = (uint16_t)return_value; + if (go_this && 0x8000){ + ppc_result_d = 0xFFFF0000 | (uint32_t)return_value; + ppc_store_result_regd(); + } + else{ + ppc_result_d = (uint32_t)return_value; + ppc_store_result_regd(); + } + return_value = 0; +} + +void ppc_lhbrx(){ + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 2); + ppc_result_d = (uint32_t)(rev_endian16((uint16_t)ppc_result_d)); + return_value = 0; + ppc_store_result_regd(); +} + +void ppc_lwz(){ + ppc_grab_regsda(); + grab_d = (uint32_t)((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_result_d, 4); + ppc_result_d = return_value; + return_value = 0; + ppc_store_result_regd(); +} + +void ppc_lwbrx(){ + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + printf("LWBRX Storage Area: %x \n",ppc_effective_address); + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 4); + ppc_result_d = rev_endian32(return_value); + return_value = 0; + ppc_store_result_regd(); +} + +void ppc_lwzu(){ + ppc_grab_regsda(); + grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF))); + if ((reg_a != reg_d) || reg_a != 0){ + ppc_effective_address = ppc_result_a + grab_d; + } + else{ + ppc_expection_handler(0x0700, 0x20000); + } + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 4); + ppc_result_d = return_value; + return_value = 0; + ppc_store_result_regd(); + ppc_result_a = ppc_effective_address; + ppc_store_result_rega(); +} + +void ppc_lwzx(){ + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 4); + ppc_result_d = return_value; + return_value = 0; + ppc_store_result_regd(); +} + +void ppc_lwzux(){ + ppc_grab_regsdab(); + if ((reg_a != reg_d) || reg_a != 0){ + ppc_effective_address = ppc_result_a + ppc_result_b; + } + else{ + ppc_expection_handler(0x0700, 0x20000); + } + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 4); + ppc_result_d = return_value; + return_value = 0; + ppc_result_a = ppc_effective_address; + ppc_store_result_regd(); + ppc_store_result_rega(); +} + +void ppc_lwarx(){ + //Placeholder - Get the reservation of memory implemented! + ppc_grab_regsdab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + ppc_state.ppc_reserve = true; + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 4); + ppc_result_d = return_value; + return_value = 0; + ppc_store_result_regd(); +} + +void ppc_lmw(){ + ppc_grab_regsda(); + grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF))); + ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d); + //How many words to load in memory - using a do-while for this + do{ + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 4); + ppc_state.ppc_gpr[reg_d] = return_value; + return_value = 0; + ppc_effective_address +=4; + reg_d++; + }while (reg_d < 32); +} + +void ppc_lswi(){ + ppc_grab_regsda(); + ppc_effective_address = ppc_result_a; + grab_inb = (ppc_cur_instruction >> 11) & 31; + grab_inb = grab_inb % 32 == 0 ? 32 : grab_inb; + + uint32_t shift_times = 0; + + while (grab_inb > 0){ + switch(shift_times){ + case 0: + address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1); + ppc_state.ppc_gpr[reg_d] = (ppc_result_d & 0x00FFFFFF) | (return_value << 24); + ppc_store_result_regd(); + return_value = 0; + 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(); + return_value = 0; + 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(); + return_value = 0; + 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(); + return_value = 0; + break; + default: + printf("Something really horrible happened with lswi."); + } + if (shift_times == 3){ + shift_times = 0; + reg_d = (reg_d + 1) & 0x1F; + } + else{ + shift_times++; + } + return_value = 0; + ppc_effective_address++; + grab_inb--; + } +} + +void ppc_lswx(){ + ppc_grab_regsdab(); + //Invalid instruction forms + if ((ppc_result_d == 0) && (ppc_result_a == 0)){ + ppc_expection_handler(0x0700, 0x100000); + } + if ((ppc_result_d == ppc_result_a) || (ppc_result_a == ppc_result_b)){ + ppc_expection_handler(0x0700, 0x100000); + } + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + grab_inb = ppc_state.ppc_spr[1] & 127; + uint32_t shift_times = 0; + while (grab_inb > 0){ + switch(shift_times){ + 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(); + return_value = 0; + 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(); + return_value = 0; + 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(); + return_value = 0; + 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(); + return_value = 0; + break; + default: + printf("Something really horrible happened with lswx."); + } + if (shift_times == 3){ + shift_times = 0; + reg_d = (reg_d + 1) & 0x1F; + } + else{ + shift_times++; + } + return_value = 0; + ppc_effective_address++; + grab_inb--; + } + +} + +void ppc_stswi(){ + ppc_grab_regssa(); + ppc_effective_address = (reg_a == 0)?0:ppc_result_a; + grab_inb = (ppc_cur_instruction >> 11) & 31; + grab_inb = grab_inb % 32 == 0 ? 32 : grab_inb; + uint32_t shift_times = 0; + while (grab_inb > 0){ + switch(shift_times){ + case 0: + strwrd_replace_value = (ppc_result_d >> 24); + address_quickinsert_translate(ppc_effective_address, strwrd_replace_value, 1); + break; + case 1: + strwrd_replace_value = (ppc_result_d >> 16); + address_quickinsert_translate(ppc_effective_address, strwrd_replace_value, 1); + break; + case 2: + strwrd_replace_value = (ppc_result_d >> 8); + address_quickinsert_translate(ppc_effective_address, strwrd_replace_value, 1); + break; + case 3: + strwrd_replace_value = (ppc_result_d); + address_quickinsert_translate(ppc_effective_address, strwrd_replace_value, 1); + break; + default: + printf("Something really horrible happened with stswi."); + } + if (shift_times == 3){ + shift_times = 0; + reg_s = (reg_s + 1) & 0x1F; + } + else{ + shift_times++; + } + return_value = 0; + ppc_effective_address++; + grab_inb--; + } +} + +void ppc_stswx(){ + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b); + grab_inb = ppc_state.ppc_spr[1] & 127; + uint32_t shift_times = 0; + while (grab_inb > 0){ + switch(shift_times){ + case 0: + strwrd_replace_value = (ppc_result_d >> 24); + address_quickinsert_translate(ppc_effective_address, strwrd_replace_value, 1); + break; + case 1: + strwrd_replace_value = (ppc_result_d >> 16); + address_quickinsert_translate(ppc_effective_address, strwrd_replace_value, 1); + break; + case 2: + strwrd_replace_value = (ppc_result_d >> 8); + address_quickinsert_translate(ppc_effective_address, strwrd_replace_value, 1); + break; + case 3: + strwrd_replace_value = (ppc_result_d); + address_quickinsert_translate(ppc_effective_address, strwrd_replace_value, 1); + break; + default: + printf("Something really horrible happened with stswx."); + } + if (shift_times == 3){ + shift_times = 0; + reg_s = (reg_s + 1) & 0x1F; + } + else{ + shift_times++; + } + return_value = 0; + ppc_effective_address++; + grab_inb--; + } +} + +//TLB Instructions + +void ppc_tlbie(){ + /** + reg_b = (ppc_cur_instruction >> 11) & 31; + uint32_t vps = ppc_state.ppc_gpr[reg_b] & 0xFFFF000; + **/ + printf("Placeholder for tlbie \n"); +} + +void ppc_tlbia(){ + printf("Placeholder for tlbia \n"); +} + +void ppc_tlbld(){ + printf("Placeholder for tlbld - 603 only \n"); +} + +void ppc_tlbli(){ + printf("Placeholder for tlbli - 603 only \n"); +} diff --git a/viacuda.cpp b/viacuda.cpp new file mode 100644 index 0000000..74ea9d1 --- /dev/null +++ b/viacuda.cpp @@ -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 +#include +#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; +} diff --git a/viacuda.h b/viacuda.h new file mode 100644 index 0000000..b54ad64 --- /dev/null +++ b/viacuda.h @@ -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