mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-02-22 13:29:49 +00:00
Add files via upload
The first attempt at uploading new files.
This commit is contained in:
parent
d31fdb37bd
commit
eaa517b63b
71
dingusppc.cbp
Normal file
71
dingusppc.cbp
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="dingusppc" />
|
||||
<Option makefile="makefile" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Debug">
|
||||
<Option output="bin/Debug/dingusppc" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Debug/" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-std=c++14" />
|
||||
<Add option="-m32" />
|
||||
<Add option="-g" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Release">
|
||||
<Option output="bin/Release/dingusppc" prefix_auto="1" extension_auto="1" />
|
||||
<Option object_output="obj/Release/" />
|
||||
<Option type="1" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-std=c++14" />
|
||||
<Add option="-m32" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-O3" />
|
||||
<Add option="-m32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wall" />
|
||||
<Add option="-std=c++11" />
|
||||
<Add option="-fexceptions" />
|
||||
</Compiler>
|
||||
<Unit filename="macioserial.cpp" />
|
||||
<Unit filename="macioserial.h" />
|
||||
<Unit filename="macscsi.cpp" />
|
||||
<Unit filename="macscsi.h" />
|
||||
<Unit filename="macswim3.cpp" />
|
||||
<Unit filename="macswim3.h" />
|
||||
<Unit filename="main.cpp" />
|
||||
<Unit filename="mpc106.cpp" />
|
||||
<Unit filename="mpc106.h" />
|
||||
<Unit filename="openpic.cpp" />
|
||||
<Unit filename="openpic.h" />
|
||||
<Unit filename="poweropcodes.cpp" />
|
||||
<Unit filename="ppcemumain.h" />
|
||||
<Unit filename="ppcfpopcodes.cpp" />
|
||||
<Unit filename="ppcgekkoopcodes.cpp" />
|
||||
<Unit filename="ppcmemory.cpp" />
|
||||
<Unit filename="ppcmemory.h" />
|
||||
<Unit filename="ppcopcodes.cpp" />
|
||||
<Unit filename="viacuda.cpp" />
|
||||
<Unit filename="viacuda.h" />
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<envvars />
|
||||
<debugger />
|
||||
<lib_finder disable_auto="1" />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
41
macioserial.cpp
Normal file
41
macioserial.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the Serial Ports
|
||||
// Based on the Zilog Z8530 SCC chip
|
||||
|
||||
#include <iostream>
|
||||
#include <cinttypes>
|
||||
#include "macioserial.h"
|
||||
#include "ppcemumain.h"
|
||||
|
||||
uint32_t mac_serial_address;
|
||||
uint8_t serial_write_byte;
|
||||
uint8_t serial_read_byte;
|
||||
|
||||
void mac_serial_init(){
|
||||
machine_iocontrolmem_mem[0x3013004] = 0x04;
|
||||
machine_iocontrolmem_mem[0x3013009] = 0xC0;
|
||||
machine_iocontrolmem_mem[0x301300B] = 0x08;
|
||||
machine_iocontrolmem_mem[0x301300E] = 0x30;
|
||||
machine_iocontrolmem_mem[0x301300F] = 0xF8;
|
||||
machine_iocontrolmem_mem[0x3013010] = 0x44;
|
||||
machine_iocontrolmem_mem[0x3013011] = 0x06;
|
||||
}
|
||||
|
||||
void mac_serial_read(){
|
||||
if (mac_serial_address >=0x3013020){
|
||||
mac_serial_address -= 0x20;
|
||||
}
|
||||
machine_iocontrolmem_mem[mac_serial_address] = serial_read_byte;
|
||||
}
|
||||
void mac_serial_write(){
|
||||
if (mac_serial_address >=0x3013020){
|
||||
mac_serial_address -= 0x20;
|
||||
}
|
||||
serial_write_byte = machine_iocontrolmem_mem[mac_serial_address];
|
||||
}
|
22
macioserial.h
Normal file
22
macioserial.h
Normal file
@ -0,0 +1,22 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the Serial Ports
|
||||
// Based on the Zilog Z8530 SCC chip
|
||||
|
||||
#ifndef MAC_IO_SERIAL_H
|
||||
#define MAC_IO_SERIAL_H
|
||||
|
||||
extern uint32_t mac_serial_address;
|
||||
extern uint8_t serial_write_byte;
|
||||
extern uint8_t serial_read_byte;
|
||||
|
||||
extern void mac_serial_init();
|
||||
extern void mac_serial_read();
|
||||
extern void mac_serial_write();
|
||||
|
||||
#endif
|
31
macscsi.cpp
Normal file
31
macscsi.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the SCSI
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cinttypes>
|
||||
#include "ppcemumain.h"
|
||||
#include "macscsi.h"
|
||||
|
||||
uint32_t macscsi_address;
|
||||
uint8_t macscsi_write_byte;
|
||||
uint8_t macscsi_read_byte;
|
||||
|
||||
void macscsi_init(){
|
||||
|
||||
}
|
||||
|
||||
void macscsi_read(){
|
||||
|
||||
}
|
||||
|
||||
void macscsi_write(){
|
||||
|
||||
}
|
||||
|
21
macscsi.h
Normal file
21
macscsi.h
Normal file
@ -0,0 +1,21 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the SCSI
|
||||
|
||||
#ifndef MACSCSI_H_
|
||||
#define MACSCSI_H_
|
||||
|
||||
extern uint32_t macscsi_address;
|
||||
extern uint8_t macscsi_write_byte;
|
||||
extern uint8_t macscsi_read_byte;
|
||||
|
||||
extern void macscsi_init();
|
||||
extern void macscsi_read();
|
||||
extern void macscsi_write();
|
||||
|
||||
#endif
|
29
macswim3.cpp
Normal file
29
macswim3.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the Swim 3 Floppy Drive
|
||||
|
||||
#include <iostream>
|
||||
#include <cinttypes>
|
||||
#include "macswim3.h"
|
||||
#include "ppcemumain.h"
|
||||
|
||||
uint32_t mac_swim3_address;
|
||||
uint8_t swim3_write_byte;
|
||||
uint8_t swim3_read_byte;
|
||||
|
||||
void mac_swim3_init(){
|
||||
machine_iocontrolmem_mem[0x3015C00] = 0xF0;
|
||||
}
|
||||
|
||||
void mac_swim3_read(){
|
||||
swim3_read_byte = machine_iocontrolmem_mem[mac_swim3_address];
|
||||
}
|
||||
|
||||
void mac_swim3_write(){
|
||||
machine_iocontrolmem_mem[mac_swim3_address] = swim3_write_byte;
|
||||
}
|
19
macswim3.h
Normal file
19
macswim3.h
Normal file
@ -0,0 +1,19 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
#ifndef MAC_SWIM3_H
|
||||
#define MAC_SWIM3_H
|
||||
|
||||
extern uint32_t mac_swim3_address;
|
||||
extern uint8_t swim3_write_byte;
|
||||
extern uint8_t swim3_read_byte;
|
||||
|
||||
extern void mac_swim3_init();
|
||||
extern void mac_swim3_read();
|
||||
extern void mac_swim3_write();
|
||||
|
||||
#endif // MAC_IO_SERIAL_H
|
859
main.cpp
Normal file
859
main.cpp
Normal file
@ -0,0 +1,859 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//The main runfile - main.cpp
|
||||
//This is where the magic begins
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
#include <cinttypes>
|
||||
#include <array>
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <stdexcept>
|
||||
#include "ppcemumain.h"
|
||||
#include "macioserial.h"
|
||||
#include "macswim3.h"
|
||||
#include "ppcmemory.h"
|
||||
#include "viacuda.h"
|
||||
#include "mpc106.h"
|
||||
#include "openpic.h"
|
||||
//#include <vector>
|
||||
|
||||
#define max_16b_int 65535
|
||||
#define max_32b_int 4294967295
|
||||
#define ENDIAN_REVERSE16(x) (x >> 8) | (((x) & 0x00FF) << 8)
|
||||
#define ENDIAN_REVERSE32(x) (x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24)
|
||||
#define ENDIAN_REVERSE64(x) (x >> 56) | ((x & 0x00FF000000000000) >> 48) | ((x & 0x0000FF0000000000) >> 40) | ((x & 0x000000FF00000000) >> 32) | \
|
||||
((x & 0x00000000FF000000) << 32) | ((x & 0x0000000000FF0000) << 40) | ((x & 0x000000000000FF00) << 48) | ((x & 0x00000000000000FF) << 56)
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
SetPRS ppc_state;
|
||||
|
||||
bool grab_branch;
|
||||
bool grab_exception;
|
||||
bool grab_return;
|
||||
|
||||
uint32_t ppc_cur_instruction;
|
||||
uint32_t ppc_effective_address;
|
||||
uint32_t ppc_real_address;
|
||||
uint32_t ppc_next_instruction_address;
|
||||
uint32_t temp_address; //used for determining where memory ends up.
|
||||
|
||||
uint32_t return_value;
|
||||
|
||||
uint32_t pc_return_value;
|
||||
|
||||
|
||||
//A pointer to a pointer, used for quick movement to one of the following
|
||||
//memory areas. These are listed right below.
|
||||
unsigned char * grab_array_ptr;
|
||||
|
||||
unsigned char * machine_sysram_mem;
|
||||
unsigned char * machine_sysconfig_mem;
|
||||
unsigned char * machine_upperiocontrol_mem;
|
||||
unsigned char * machine_iocontrolcdma_mem;
|
||||
unsigned char * machine_loweriocontrol_mem;
|
||||
unsigned char * machine_interruptack_mem;
|
||||
unsigned char * machine_iocontrolmem_mem;
|
||||
unsigned char * machine_f8xxxx_mem;
|
||||
unsigned char * machine_fexxxx_mem;
|
||||
unsigned char * machine_fecxxx_mem;
|
||||
unsigned char * machine_feexxx_mem;
|
||||
unsigned char * machine_ff00xx_mem;
|
||||
unsigned char * machine_ff80xx_mem;
|
||||
unsigned char * machine_sysrom_mem;
|
||||
|
||||
uint32_t grab_sysram_size;
|
||||
uint32_t grab_iocont_size;
|
||||
uint32_t grab_sysrom_size;
|
||||
|
||||
uint32_t ram_size_set;
|
||||
|
||||
uint32_t prev_msr_state = 0;
|
||||
uint32_t cur_msr_state = 0;
|
||||
|
||||
//MSR Flags
|
||||
bool msr_es_change; //Check Endian
|
||||
|
||||
uint32_t rom_file_begin; //where to start storing ROM files in memory
|
||||
uint32_t pci_io_end;
|
||||
|
||||
uint32_t rom_file_setsize;
|
||||
|
||||
clock_t clock_test_begin; //Used to make sure the TBR does not increment so quickly.
|
||||
|
||||
uint32_t write_opcode;
|
||||
uint8_t write_char;
|
||||
|
||||
/*
|
||||
//DISK VARIABLES
|
||||
unsigned char * grab_disk_buf;
|
||||
bool disk_inserted;
|
||||
uint64_t disk_offset = 0;
|
||||
uint32_t disk_word = 0;
|
||||
*/
|
||||
|
||||
|
||||
uint16_t rev_endian16(uint16_t insert_int){
|
||||
return ENDIAN_REVERSE16(insert_int);
|
||||
}
|
||||
|
||||
uint32_t rev_endian32(uint32_t insert_int){
|
||||
return ENDIAN_REVERSE32(insert_int);
|
||||
}
|
||||
|
||||
uint64_t rev_endian64(uint64_t insert_int){
|
||||
return ENDIAN_REVERSE64(insert_int);
|
||||
}
|
||||
|
||||
//Time Base Register Update Code
|
||||
//TODO - Make this a bit less hacky somehow.
|
||||
void ppc_tbr_update()
|
||||
{
|
||||
clock_t clock_test_current = clock();
|
||||
uint32_t test_clock = ((uint32_t) (clock_test_current - clock_test_begin)) / CLOCKS_PER_SEC;
|
||||
if (test_clock){
|
||||
if (ppc_state.ppc_tbr[0] != 0xFFFFFFFF){
|
||||
ppc_state.ppc_tbr[0]++;
|
||||
}
|
||||
else{
|
||||
ppc_state.ppc_tbr[0] = 0;
|
||||
if (ppc_state.ppc_tbr[1] !=0xFFFFFFFF){
|
||||
ppc_state.ppc_tbr[1]++;
|
||||
}
|
||||
else{
|
||||
ppc_state.ppc_tbr[1] = 0;
|
||||
}
|
||||
}
|
||||
clock_test_begin = clock();
|
||||
//Placeholder Decrementing Code
|
||||
if(ppc_state.ppc_spr[22] > 0){
|
||||
ppc_state.ppc_spr[22]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_expection_handler(uint32_t exception_type, uint32_t handle_args){
|
||||
ppc_next_instruction_address = 0x0; //used to construct a new address
|
||||
grab_exception = true;
|
||||
|
||||
printf("MSR VALUE: %x \n Exception Type: %x", ppc_state.ppc_msr, exception_type);
|
||||
|
||||
//Check ROM Exception Prefix
|
||||
if (ppc_state.ppc_msr && 0x40){
|
||||
ppc_next_instruction_address |= 0xFFF00000;
|
||||
}
|
||||
else{
|
||||
ppc_next_instruction_address &= 0x0000FFFF;
|
||||
}
|
||||
|
||||
switch(exception_type){
|
||||
case 0x0100: //System Reset
|
||||
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
|
||||
ppc_state.ppc_spr[27] = ppc_state.ppc_msr;
|
||||
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
|
||||
ppc_next_instruction_address += 0x0100;
|
||||
break;
|
||||
/**
|
||||
case 0x0200: //Machine Check
|
||||
break;
|
||||
case 0x0300: //DSI
|
||||
break;
|
||||
case 0x0400: //ISI
|
||||
break;
|
||||
**/
|
||||
case 0x0500: //External Interrupt
|
||||
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
|
||||
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
|
||||
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
|
||||
ppc_next_instruction_address += 0x0500;
|
||||
break;
|
||||
case 0x0600: //Alignment Exception
|
||||
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
|
||||
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
|
||||
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
|
||||
ppc_state.ppc_spr[19] = ppc_cur_instruction;
|
||||
ppc_next_instruction_address += 0x0600;
|
||||
case 0x0700: //Program;
|
||||
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
|
||||
handle_args += 0x10000;
|
||||
ppc_state.ppc_spr[27] = handle_args + (ppc_state.ppc_msr & 0xFFFF);
|
||||
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
|
||||
ppc_next_instruction_address += 0x0700;
|
||||
break;
|
||||
case 0x0C00: //Sys Call
|
||||
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
|
||||
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
|
||||
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
|
||||
ppc_next_instruction_address += 0x0C00;
|
||||
break;
|
||||
/**
|
||||
case 0x0d: //Trace
|
||||
break
|
||||
**/
|
||||
default:
|
||||
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
|
||||
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
|
||||
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
|
||||
ppc_next_instruction_address += exception_type;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Initialize the PPC's registers.
|
||||
void reg_init(){
|
||||
for (uint32_t i = 0; i < 32; i++){
|
||||
ppc_state.ppc_fpr[i] = 0;
|
||||
}
|
||||
ppc_state.ppc_pc = 0;
|
||||
for (uint32_t i = 0; i < 32; i++){
|
||||
ppc_state.ppc_gpr[i] = 0;
|
||||
}
|
||||
ppc_state.ppc_cr = 0;
|
||||
ppc_state.ppc_fpscr = 0;
|
||||
ppc_state.ppc_tbr[0] = 0;
|
||||
ppc_state.ppc_tbr[1] = 0;
|
||||
|
||||
for (uint32_t i = 0; i < 1024; i++){
|
||||
switch(i){
|
||||
case 287:
|
||||
//Identify as a G3
|
||||
//Processor IDS
|
||||
// 601 v1 - 00010001
|
||||
// 603 v1 - 00030001
|
||||
// 604 v1 - 00040001
|
||||
// 603e v1 - 00060101
|
||||
// 750 v1 - 00080200
|
||||
ppc_state.ppc_spr[i] = 0x00080200;
|
||||
break;
|
||||
/**
|
||||
case 528:
|
||||
case 536:
|
||||
ppc_state.ppc_spr[i] = 0x00001FFE;
|
||||
break;
|
||||
case 530:
|
||||
case 538:
|
||||
ppc_state.ppc_spr[i] = 0xC0001FFE;
|
||||
break;
|
||||
case 532:
|
||||
case 540:
|
||||
ppc_state.ppc_spr[i] = 0xE0001FFE;
|
||||
break;
|
||||
case 534:
|
||||
case 542:
|
||||
ppc_state.ppc_spr[i] = 0xF0001FFE;
|
||||
break;
|
||||
case 529:
|
||||
case 531:
|
||||
case 537:
|
||||
case 539:
|
||||
ppc_state.ppc_spr[i] = 0x00000002;
|
||||
break;
|
||||
case 533:
|
||||
case 541:
|
||||
ppc_state.ppc_spr[i] = 0xE0000002;
|
||||
break;
|
||||
case 535:
|
||||
ppc_state.ppc_spr[i] = 0xF0000002;
|
||||
break;
|
||||
case 543:
|
||||
ppc_state.ppc_spr[i] = 0x00000002;
|
||||
break;
|
||||
**/
|
||||
default:
|
||||
ppc_state.ppc_spr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Only bit 25 of the MSR is initially set on bootup.
|
||||
ppc_state.ppc_msr = 0x40;
|
||||
for (uint32_t i = 0; i < 16; i++){
|
||||
ppc_state.ppc_sr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//Debugging Functions
|
||||
uint32_t reg_print(){
|
||||
for (uint32_t i = 0; i < 32; i++){
|
||||
printf("FPR %d : %I64u", i, ppc_state.ppc_fpr[i]);
|
||||
}
|
||||
ppc_state.ppc_pc = 0;
|
||||
for (uint32_t i = 0; i < 32; i++){
|
||||
printf("GPR %d : %d", i, ppc_state.ppc_gpr[i]);
|
||||
}
|
||||
printf("CR : %d", ppc_state.ppc_cr);
|
||||
printf("FPSCR : %d", ppc_state.ppc_fpscr);
|
||||
printf("TBR 0 : %d", ppc_state.ppc_tbr[0]);
|
||||
printf("TBR 1 : %d", ppc_state.ppc_tbr[1]);
|
||||
|
||||
for (uint32_t i = 0; i < 1024; i++){
|
||||
printf("SPR %d : %d", i, ppc_state.ppc_spr[i]);
|
||||
}
|
||||
|
||||
printf("CR : %d", ppc_state.ppc_cr);
|
||||
|
||||
printf("MSR : %d", ppc_state.ppc_msr);
|
||||
|
||||
for (uint32_t i = 0; i < 16; i++){
|
||||
printf("SR %d : %d", i, ppc_state.ppc_sr[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t reg_read(){
|
||||
uint32_t grab_me = 0;
|
||||
std::cout << hex << "TODO: Decide which register to read from; for now, which GPR?" << endl;
|
||||
//printf("Which register to read from? 0 - GPR, 1 = FPR, 2 = CR, 3 = FPSCR");
|
||||
std::cin >> hex >> grab_me;
|
||||
if (grab_me < 32){
|
||||
printf("GPR value: %d", ppc_state.ppc_gpr[grab_me]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t reg_write(){
|
||||
uint32_t grab_me = 0;
|
||||
std::cout << hex << "TODO: Decide which register to write to; for now, which GPR?" << endl;
|
||||
//printf("Which register to write to? 0 - GPR, 1 = FPR, 2 = CR, 3 = FPSCR");
|
||||
std::cin >> hex >> grab_me;
|
||||
if (grab_me < 32){
|
||||
printf("GPR value: %d", ppc_state.ppc_gpr[grab_me]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ram_size_set = 0x4000000; //64 MB of RAM for the Mac
|
||||
|
||||
rom_file_begin = 0xFFF00000; //where to start storing ROM files in memory
|
||||
pci_io_end = 0x83FFFFFF;
|
||||
rom_file_setsize = 0x400000;
|
||||
|
||||
reg_init();
|
||||
|
||||
/**
|
||||
uint16_t test_endianness = 0x1234;
|
||||
|
||||
//Test for endianess before beginning
|
||||
uint8_t grab_result = (uint8_t) (test_endianness >> 8);
|
||||
endian_switch endis;
|
||||
|
||||
//Special case for little-endian machines
|
||||
switch(unsigned(grab_result)){
|
||||
case 18:
|
||||
endis = little_end;
|
||||
break;
|
||||
default:
|
||||
endis = big_end;
|
||||
}
|
||||
**/
|
||||
|
||||
bool power_on = 1;
|
||||
uint32_t opcode_entered = 0; //used for testing opcodes in playground
|
||||
|
||||
std::cout << "DingusPPC - Prototype 5bf3 (6/9/2019) " << endl;
|
||||
std::cout << "Written by divingkatae, (c) 2019. " << endl;
|
||||
std::cout << "This is not intended for general use. " << endl;
|
||||
std::cout << "Use at your own discretion. " << endl;
|
||||
|
||||
//Open the ROM File.
|
||||
ifstream romFile;
|
||||
|
||||
romFile.open("rom.bin", ios::in|ios::binary);
|
||||
|
||||
if (romFile.fail()){
|
||||
cerr << "rom.bin not present. Creating it right now. Please restart this program.\n";
|
||||
std::ofstream outfile ("rom.bin", ios::binary);
|
||||
|
||||
outfile << "Testing!" << std::endl;
|
||||
|
||||
outfile.close();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//Allocate memory for ROM, RAM, and I/O.
|
||||
romFile.seekg(0, romFile.end);
|
||||
rom_file_setsize = romFile.tellg();
|
||||
printf("Rom SIZE: %d \n", rom_file_setsize);
|
||||
romFile.seekg (0, romFile.beg);
|
||||
|
||||
/**
|
||||
Allocate memory wisely.
|
||||
|
||||
Corresponds (mostly) to the follow memory patterns seen in
|
||||
https://www.nxp.com/docs/en/reference-manual/MPC106UM.pdf
|
||||
|
||||
machine_sysram_mem - 0x00000000 to 0x7FFFFFFF
|
||||
machine_upperiocontrol_mem - 0x80000000 to 0x807FFFFF
|
||||
machine_iocontrolcdma_mem - 0x80800000 to 0x80FFFFFF
|
||||
machine_loweriocontrol_mem - 0x81000000 to 0xBF7FFFFF
|
||||
machine_interruptack_mem - 0xBFFFFFF0 to 0xBFFFFFFF
|
||||
machine_iocontrolmem_mem - 0xC0000000 to 0xFFBFFFFF
|
||||
machine_sysrom_mem - 0xFFC00000 to 0xFFFFFFFF
|
||||
**/
|
||||
|
||||
//grab_disk_buf = (unsigned char*) calloc (32768, 1);
|
||||
machine_sysram_mem = (unsigned char*) calloc (67108864, 1);
|
||||
machine_sysconfig_mem = (unsigned char*) calloc (2048, 1);
|
||||
machine_upperiocontrol_mem = (unsigned char*) calloc (8388608, 1);
|
||||
machine_iocontrolcdma_mem = (unsigned char*) calloc (8388608, 1);
|
||||
machine_loweriocontrol_mem = (unsigned char*) calloc (33554432, 1);
|
||||
machine_interruptack_mem = (unsigned char*) calloc (16, 1);
|
||||
machine_iocontrolmem_mem = (unsigned char*) calloc (67108864, 1);
|
||||
machine_f8xxxx_mem = (unsigned char*) calloc (4096, 1);
|
||||
machine_fexxxx_mem = (unsigned char*) calloc (262144, 1);
|
||||
machine_fecxxx_mem = (unsigned char*) calloc (4096, 1);
|
||||
machine_feexxx_mem = (unsigned char*) calloc (4096, 1);
|
||||
machine_ff00xx_mem = (unsigned char*) calloc (4096, 1);
|
||||
machine_ff80xx_mem = (unsigned char*) calloc (1048576, 1);
|
||||
machine_sysrom_mem = (unsigned char*) calloc (rom_file_setsize, 1);
|
||||
|
||||
memset(machine_sysram_mem, 0x0, 67108864);
|
||||
memset(machine_sysconfig_mem, 0x0, 2048);
|
||||
memset(machine_upperiocontrol_mem, 0x0, 8388607);
|
||||
memset(machine_iocontrolcdma_mem, 0x0, 8388607);
|
||||
memset(machine_interruptack_mem, 0x0, 16);
|
||||
memset(machine_iocontrolmem_mem, 0x0, 67108864);
|
||||
memset(machine_f8xxxx_mem, 0x0, 4096);
|
||||
memset(machine_fexxxx_mem, 0x0, 262144);
|
||||
memset(machine_fecxxx_mem, 0x0, 4096);
|
||||
memset(machine_feexxx_mem, 0x0, 4096);
|
||||
memset(machine_ff00xx_mem, 0x0, 4096);
|
||||
memset(machine_ff80xx_mem, 0x0, 1048576);
|
||||
|
||||
grab_sysram_size = sizeof(machine_sysram_mem);
|
||||
grab_sysrom_size = rom_file_setsize;
|
||||
|
||||
//Sanity checks - Prevent the input files being too small or too big.
|
||||
//Also prevent the ROM area from overflow.
|
||||
if (grab_sysrom_size < 0x100000){
|
||||
cerr << "ROM File is too small. Must be at least 1 megabyte.\n";
|
||||
return 1;
|
||||
}
|
||||
else if (grab_sysrom_size > 0x400000){
|
||||
cerr << "ROM File is too big. Must be no more than 4 megabytes.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ram_size_set < 0x800000){
|
||||
cerr << "The RAM size must be at least 8 MB to function.\n";
|
||||
return 1;
|
||||
}
|
||||
else if (ram_size_set > 0x20000000){
|
||||
cerr << "RAM too big. Must be no more than 2 GB.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
rom_file_begin = 0xFFFFFFFF - grab_sysrom_size + 1;
|
||||
|
||||
/**
|
||||
Test for PowerPC Mac ROMS
|
||||
|
||||
Starting at 0x30D064 (0x30C064 in older ROMS), there is a boot
|
||||
identifier string in the ROM. This helps a lot to determine which
|
||||
setup is to by used.
|
||||
**/
|
||||
char * memPPCBlock = new char[5];
|
||||
|
||||
map<string,string> PPCMac_ROMIdentity = { //Codename Abbreviation for...
|
||||
{"Alch", "Performa 6400"}, //Alchemy
|
||||
{"Come", "PowerBook 2400"}, //Comet
|
||||
{"Cord", "Power Mac 5200/6200 series"}, //Cordyceps
|
||||
{"Gaze", "Power Mac 6500"}, //Gazelle
|
||||
{"Goss", "Power Mac G3 Beige"}, //Gossamer
|
||||
{"GRX ", "PowerBook G3 Wallstreet"}, //(Unknown)
|
||||
{"Hoop", "PowerBook 3400"}, //Hooper
|
||||
{"PBX ", "PowerBook Pre-G3"}, //(Unknown)
|
||||
{"PDM ", "Power Mac G1 or WGS"}, //(Unknown)
|
||||
{"Pip ", "Pippin... uh... yeah..."}, //Pippin
|
||||
{"Powe", "Generic Power Mac"}, //PowerMac?
|
||||
{"Spar", "20th Anniversay Mac, you lucky thing."}, //Spartacus
|
||||
{"Tanz", "Power Mac 4400"}, //Tanzania
|
||||
{"TNT ", "Power Mac 7xxxx/8xxx series"}, //Trinitrotoluene :-)
|
||||
{"Zanz", "A complete engima."} //Zanzibar (mentioned in Sheepshaver's code, but no match to any known ROM)
|
||||
};
|
||||
|
||||
uint32_t configInfoOffset = 0;
|
||||
|
||||
if (grab_sysrom_size == 0x400000){
|
||||
|
||||
romFile.seekg (0x300082, ios::beg); //This is where the place to get the offset is
|
||||
romFile.read(configInfoOffset, 1);
|
||||
uint32_t configInfoAddr = 0x300000 + (configInfoOffset << 8);
|
||||
romFile.seekg (configInfoAddr, ios::beg);
|
||||
romFile.read(memPPCBlock, sizeof(uint32_t)); //Only four chars needed to distinguish between codenames
|
||||
|
||||
std::string string_test = std::string(memPPCBlock);
|
||||
|
||||
//Just auto-iterate through the list
|
||||
for (auto iter = PPCMac_ROMIdentity.begin(); iter != PPCMac_ROMIdentity.end(); ){
|
||||
|
||||
string redo_me = iter->first;
|
||||
|
||||
if (!string_test.compare(redo_me)){
|
||||
cout << "The machine is identified as..." << iter->second << endl;
|
||||
romFile.seekg (0x0, ios::beg);
|
||||
|
||||
//This is where the first real instruction is in the ROM
|
||||
//0xFFF00000 - 0xFFF02FFF is for the exception table,
|
||||
//which is stored in all PPC ROMs here, btw.
|
||||
|
||||
//0xFFF00100 is where the reset vector is.
|
||||
//In other words, begin executing code here.
|
||||
|
||||
ppc_state.ppc_pc = 0xFFF00100;//Please don't move this from here.
|
||||
//A strange bug will happen where this will prevent proper branching
|
||||
mpc106_init();
|
||||
mac_serial_init();
|
||||
mac_swim3_init();
|
||||
via_cuda_init();
|
||||
openpic_init();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Copy the contents of the IO data and the ROM to memory appropriate locations.
|
||||
romFile.read ((char *)machine_sysrom_mem,grab_sysrom_size);
|
||||
|
||||
/*
|
||||
//Open the Disk File.
|
||||
uint64_t disk_file_setsize = 0;
|
||||
ifstream diskFile;
|
||||
|
||||
diskFile.open("disk.img", ios::in|ios::binary);
|
||||
|
||||
if (diskFile){
|
||||
diskFile.seekg(0, romFile.end);
|
||||
disk_file_setsize = romFile.tellg();
|
||||
diskFile.seekg(0, romFile.beg);
|
||||
|
||||
if (disk_file_setsize % 32678 != 0){
|
||||
cout << "WARNING - Disk file has improper offsets. Make sure the disk image has even 32 KB sectors." << endl;
|
||||
}
|
||||
else{
|
||||
//Copy the contents of the IO data and the ROM to memory appropriate locations.
|
||||
diskFile.read ((char *)machine_sysram_mem,(sizeof(uint8_t)*0x8000));
|
||||
disk_inserted = 1;
|
||||
disk_offset = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
disk_inserted = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
clock_test_begin = clock();
|
||||
|
||||
if (argc > 1){
|
||||
string checker = argv[1];
|
||||
cout << checker << endl;
|
||||
if (checker == "fuzzer"){
|
||||
//Brute force every instruction that the PPC can interpret.
|
||||
//TODO: Change this so that this goes through user-specified instructions.
|
||||
ppc_cur_instruction = 0xFFFFFFFF;
|
||||
std::cout << "Testing Opcode: " << ppc_cur_instruction << endl;
|
||||
while (ppc_cur_instruction > 0x00000000){
|
||||
ppc_main_opcode();
|
||||
ppc_cur_instruction--;
|
||||
}
|
||||
}
|
||||
else if ((checker=="1")|(checker=="realtime")|(checker=="/realtime")|(checker=="-realtime")){
|
||||
while (power_on){
|
||||
cout << "PowerPC PC Address: " << hex << ppc_state.ppc_pc << endl;
|
||||
quickinstruction_translate(ppc_state.ppc_pc);
|
||||
ppc_main_opcode();
|
||||
if (grab_branch & !grab_exception){
|
||||
ppc_state.ppc_pc = ppc_next_instruction_address;
|
||||
grab_branch = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else if (grab_return | grab_exception){
|
||||
ppc_state.ppc_pc = ppc_next_instruction_address;
|
||||
grab_exception = 0;
|
||||
grab_return = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else{
|
||||
ppc_state.ppc_pc += 4;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
ppc_cur_instruction = 0;
|
||||
/*
|
||||
if (disk_inserted){
|
||||
if (disk_word == 32768){
|
||||
if (disk_offset < disk_file_setsize){
|
||||
disk_offset += 32768;
|
||||
diskFile.seekg(disk_offset, romFile.beg);
|
||||
char *ptr = ((char*)machine_iocontrolmem_mem + (0xF3008000 % 0x4000000));
|
||||
diskFile.read (ptr,(sizeof(uint8_t)*0x8000));
|
||||
disk_word = 0;
|
||||
}
|
||||
else{
|
||||
disk_offset = 0;
|
||||
diskFile.seekg(0, romFile.beg);
|
||||
char *ptr = ((char*)machine_iocontrolmem_mem + (0xF3008000 % 0x4000000));
|
||||
diskFile.read (ptr,(sizeof(uint8_t)*0x8000));
|
||||
disk_word = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
disk_word += 4;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
else if ((checker=="e")|(checker=="loadelf")|(checker=="/loadelf")|(checker=="-loadelf")){
|
||||
ifstream elfFile;
|
||||
uint32_t elf_file_setsize = 0;
|
||||
|
||||
char elf_headerchk [4];
|
||||
char elf_bformat [1];
|
||||
char elf_machine [2];
|
||||
char elf_memoffset [4];
|
||||
|
||||
elfFile.seekg(0, elfFile.end);
|
||||
elf_file_setsize = elfFile.tellg();
|
||||
elfFile.seekg (0, elfFile.beg);
|
||||
|
||||
if (elf_file_setsize < 45){
|
||||
cerr << "Elf File TOO SMALL. Please make sure it's a legitimate file.";
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (elf_file_setsize > ram_size_set){
|
||||
cerr << "Elf File TOO BIG. Please make sure it fits within memory.";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//There's got to be a better way to get fields of info from an ELF file.
|
||||
elfFile.seekg(0x0, ios::beg); //ELF file begins here
|
||||
elfFile.read(elf_headerchk, 4);
|
||||
elfFile.seekg(0x4, ios::cur);
|
||||
elfFile.read(elf_bformat, 1);
|
||||
elfFile.seekg(0x8, ios::cur);
|
||||
elfFile.read(elf_machine, 2);
|
||||
elfFile.seekg(0x6, ios::cur);
|
||||
elfFile.read(elf_memoffset, 4);
|
||||
elfFile.seekg (0, elfFile.beg);
|
||||
|
||||
bool elf_valid_check = (atoi(elf_headerchk) == 0x7F454C46) && (atoi(elf_bformat) == 1) &&\
|
||||
((atoi(elf_machine) == 0) | (atoi(elf_machine) == 20));
|
||||
|
||||
if (!elf_valid_check){
|
||||
cerr << "The ELF file inserted was not legitimate. Please try again." << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
elfFile.read ((char *)machine_sysram_mem,ram_size_set);
|
||||
|
||||
if (argc > 2){
|
||||
string elfname = string(argv[1]);
|
||||
elfname = elfname + ".elf";
|
||||
elfFile.open(elfname, ios::in|ios::binary);
|
||||
}
|
||||
else{
|
||||
elfFile.open("test.elf", ios::in|ios::binary);
|
||||
}
|
||||
if (elfFile.fail()){
|
||||
cerr << "Please insert the elf file before continuing.\n";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ppc_state.ppc_pc = atoi(elf_memoffset);
|
||||
|
||||
while (power_on){
|
||||
quickinstruction_translate(ppc_state.ppc_pc);
|
||||
ppc_main_opcode();
|
||||
if (grab_branch & !grab_exception){
|
||||
ppc_state.ppc_pc = ppc_effective_address;
|
||||
grab_branch = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else if (grab_return | grab_exception){
|
||||
ppc_state.ppc_pc = ppc_next_instruction_address;
|
||||
grab_exception = 0;
|
||||
grab_return = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else if (ppc_cur_instruction == 0){
|
||||
cout << "Opcode 0 executed. Shutting off the power before the flood even starts. \n" << endl;
|
||||
power_on = 0; //Hack - Prevent flooding the log.
|
||||
}
|
||||
else{
|
||||
ppc_state.ppc_pc += 4;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
ppc_cur_instruction = 0;
|
||||
}
|
||||
}
|
||||
else if (checker=="assemble"){
|
||||
if (argc > 2){
|
||||
checker = argv[1];
|
||||
}
|
||||
else{
|
||||
checker = "\\compile.txt";
|
||||
}
|
||||
ifstream inFile (checker, ios::binary | ios::ate);
|
||||
if (!inFile) {
|
||||
cerr << "Unable to open file for assembling.";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cout << "Insert Assembler Here! - TODO" << endl;
|
||||
|
||||
}
|
||||
else if ((checker=="eso")|(checker=="/eso")|(checker=="-eso")){
|
||||
std::cout << hex << "Ready to execute an opcode?" << endl;
|
||||
|
||||
string check_q;
|
||||
cin >> check_q;
|
||||
getline (cin, check_q);
|
||||
|
||||
if (check_q != "No"){
|
||||
quickinstruction_translate(ppc_state.ppc_pc);
|
||||
ppc_main_opcode();
|
||||
if (grab_branch & !grab_exception){
|
||||
ppc_state.ppc_pc = ppc_effective_address;
|
||||
grab_branch = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else if (grab_return | grab_exception){
|
||||
ppc_state.ppc_pc = ppc_next_instruction_address;
|
||||
grab_exception = 0;
|
||||
grab_return = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else{
|
||||
ppc_state.ppc_pc += 4;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
ppc_cur_instruction = 0;
|
||||
}
|
||||
}
|
||||
else if ((checker=="epo")|(checker=="/epo")|(checker=="-epo")){
|
||||
std::cout << hex << "Ready to execute a page of opcodes?" << endl;
|
||||
|
||||
string check_q;
|
||||
cin >> check_q;
|
||||
getline (cin, check_q);
|
||||
|
||||
if (check_q != "No"){
|
||||
for (int instructions_to_do = 0; instructions_to_do < 256; instructions_to_do++){
|
||||
quickinstruction_translate(ppc_state.ppc_pc);
|
||||
ppc_main_opcode();
|
||||
if (grab_branch & !grab_exception){
|
||||
ppc_state.ppc_pc = ppc_effective_address;
|
||||
grab_branch = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else if (grab_return | grab_exception){
|
||||
ppc_state.ppc_pc = ppc_next_instruction_address;
|
||||
grab_exception = 0;
|
||||
grab_return = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else{
|
||||
ppc_state.ppc_pc += 4;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
ppc_cur_instruction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((checker=="play")|(checker=="playground")|(checker=="/playground")|(checker=="-playground")){
|
||||
std::cout << hex << "Enter any opcodes for the PPC you want here." << endl;
|
||||
|
||||
while (power_on){
|
||||
cin >> hex >> opcode_entered;
|
||||
//power off the PPC
|
||||
if (opcode_entered == 0x00000000){
|
||||
power_on = 0;
|
||||
}
|
||||
//print registers
|
||||
else if (opcode_entered == 0x00000001){
|
||||
reg_print();
|
||||
}
|
||||
else if (opcode_entered == 0x00000002){
|
||||
reg_read();
|
||||
}
|
||||
else if (opcode_entered == 0x00000003){
|
||||
reg_write();
|
||||
}
|
||||
//test another opcode
|
||||
else{
|
||||
ppc_cur_instruction = opcode_entered;
|
||||
quickinstruction_translate(ppc_state.ppc_pc);
|
||||
ppc_main_opcode();
|
||||
if (grab_branch & !grab_exception){
|
||||
ppc_state.ppc_pc = ppc_effective_address;
|
||||
grab_branch = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else if (grab_return | grab_exception){
|
||||
ppc_state.ppc_pc = ppc_next_instruction_address;
|
||||
grab_exception = 0;
|
||||
grab_return = 0;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
else{
|
||||
ppc_state.ppc_pc += 4;
|
||||
ppc_tbr_update();
|
||||
}
|
||||
ppc_cur_instruction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
std::cout << " " << endl;
|
||||
std::cout << "Please enter one of the following commands when" << endl;
|
||||
std::cout << "booting up DingusPPC... " << endl;
|
||||
std::cout << " " << endl;
|
||||
std::cout << " " << endl;
|
||||
std::cout << "realtime - Run the emulator in real-time. " << endl;
|
||||
std::cout << "loadelf - Load an ELF file to run from RAM. " << endl;
|
||||
std::cout << "fuzzer - Test every single PPC opcode. " << endl;
|
||||
std::cout << "eso - Execute a single opcode per key press. " << endl;
|
||||
std::cout << "epo - Execute a page of opcodes per key press. " << endl;
|
||||
std::cout << "playground - Mess around with and opcodes. " << endl;
|
||||
//std::cout << "assembler - NOT YET IMPLEMENTED " << endl;
|
||||
}
|
||||
|
||||
romFile.close();
|
||||
|
||||
//Free memory after the emulation is completed.
|
||||
free(machine_sysram_mem);
|
||||
free(machine_upperiocontrol_mem);
|
||||
free(machine_iocontrolcdma_mem);
|
||||
free(machine_loweriocontrol_mem);
|
||||
free(machine_interruptack_mem);
|
||||
free(machine_iocontrolmem_mem);
|
||||
free(machine_f8xxxx_mem);
|
||||
free(machine_fexxxx_mem);
|
||||
free(machine_fecxxx_mem);
|
||||
free(machine_feexxx_mem);
|
||||
free(machine_ff00xx_mem);
|
||||
free(machine_ff80xx_mem);
|
||||
free(machine_sysrom_mem);
|
||||
|
||||
return 0;
|
||||
}
|
50
makefile
Normal file
50
makefile
Normal file
@ -0,0 +1,50 @@
|
||||
OBJS = main.o macioserial.o macscsi.o macswim3.o mpc106.o openpic.o poweropcodes.o ppcfpopcodes.o ppcgekkoopcodes.o ppcmemory.o ppcopcodes.o viacuda.o
|
||||
SOURCE = main.c macioserial.cpp macscsi.cpp macswim3.cpp mpc106.cpp openpic.cpp poweropcodes.cpp ppcfpopcodes.cpp ppcgekkoopcodes.cpp ppcmemory.cpp ppcopcodes.cpp viacuda.cpp
|
||||
HEADER = macioserial.h macscsi.h macswim3.h mpc106.h openpic.h ppcemumain.h ppcmemory.h viacuda.h
|
||||
OUT = dingusppc
|
||||
CC = g++
|
||||
FLAGS = -g -c -Wall
|
||||
LFLAGS =
|
||||
|
||||
all: $(OBJS)
|
||||
$(CC) -g $(OBJS) -o $(OUT) $(LFLAGS)
|
||||
|
||||
main.o: main.c
|
||||
$(CC) $(FLAGS) main.c
|
||||
|
||||
macioserial.o: macioserial.cpp
|
||||
$(CC) $(FLAGS) macioserial.cpp
|
||||
|
||||
macscsi.o: macscsi.cpp
|
||||
$(CC) $(FLAGS) macscsi.cpp
|
||||
|
||||
macswim3.o: macswim3.cpp
|
||||
$(CC) $(FLAGS) macswim3.cpp
|
||||
|
||||
mpc106.o: mpc106.cpp
|
||||
$(CC) $(FLAGS) mpc106.cpp
|
||||
|
||||
openpic.o: openpic.cpp
|
||||
$(CC) $(FLAGS) openpic.cpp
|
||||
|
||||
poweropcodes.o: poweropcodes.cpp
|
||||
$(CC) $(FLAGS) poweropcodes.cpp
|
||||
|
||||
ppcfpopcodes.o: ppcfpopcodes.cpp
|
||||
$(CC) $(FLAGS) ppcfpopcodes.cpp
|
||||
|
||||
ppcgekkoopcodes.o: ppcgekkoopcodes.cpp
|
||||
$(CC) $(FLAGS) ppcgekkoopcodes.cpp
|
||||
|
||||
ppcmemory.o: ppcmemory.cpp
|
||||
$(CC) $(FLAGS) ppcmemory.cpp
|
||||
|
||||
ppcopcodes.o: ppcopcodes.cpp
|
||||
$(CC) $(FLAGS) ppcopcodes.cpp
|
||||
|
||||
viacuda.o: viacuda.cpp
|
||||
$(CC) $(FLAGS) viacuda.cpp
|
||||
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(OUT)
|
164
mpc106.cpp
Normal file
164
mpc106.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the MPC106
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cinttypes>
|
||||
#include "mpc106.h"
|
||||
#include "ppcemumain.h"
|
||||
#include "ppcmemory.h"
|
||||
|
||||
bool mpc106_address_map;
|
||||
|
||||
uint32_t mpc106_address;
|
||||
uint32_t mpc_config_addr;
|
||||
uint32_t mpc_config_dat;
|
||||
|
||||
uint32_t mpc106_write_word;
|
||||
uint32_t mpc106_read_word;
|
||||
uint16_t mpc106_write_half;
|
||||
uint16_t mpc106_read_half;
|
||||
uint8_t mpc106_write_byte;
|
||||
uint8_t mpc106_read_byte;
|
||||
unsigned char* mpc106_regs;
|
||||
|
||||
void mpc106_init(){
|
||||
mpc106_regs = (unsigned char*) calloc (256, 1);
|
||||
memset(mpc106_regs, 0x0, 256);
|
||||
|
||||
//Initialize Vendor & Device IDs
|
||||
mpc106_regs[0] = 0x57;
|
||||
mpc106_regs[1] = 0x10;
|
||||
|
||||
mpc106_regs[2] = 0x02;
|
||||
|
||||
//PCI command + status
|
||||
mpc106_regs[4] = 0x06;
|
||||
mpc106_regs[6] = 0x80;
|
||||
|
||||
mpc106_regs[115] = 0xCD;
|
||||
|
||||
mpc106_regs[168] = 0x10;
|
||||
mpc106_regs[169] = 0x00;
|
||||
mpc106_regs[170] = 0x00;
|
||||
mpc106_regs[171] = 0xFF;
|
||||
|
||||
mpc106_regs[172] = 0x0C;
|
||||
mpc106_regs[173] = 0x06;
|
||||
mpc106_regs[174] = 0x0C;
|
||||
mpc106_regs[175] = 0x00;
|
||||
}
|
||||
|
||||
void mpc106_write_device(uint32_t value){
|
||||
}
|
||||
|
||||
void mpc106_read_device(uint32_t value, uint8_t bit_length){
|
||||
}
|
||||
|
||||
void mpc106_read(){
|
||||
|
||||
uint8_t read_length = 4;
|
||||
|
||||
switch (mpc106_address){
|
||||
case 0x8:
|
||||
case 0x72:
|
||||
case 0x73:
|
||||
case 0xA0:
|
||||
case 0xA3:
|
||||
read_length = 1;
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x2:
|
||||
case 0x4:
|
||||
case 0x6:
|
||||
case 0x70:
|
||||
read_length = 2;
|
||||
break;
|
||||
case 0x80:
|
||||
case 0x84:
|
||||
case 0x88:
|
||||
case 0x8C:
|
||||
case 0x90:
|
||||
case 0x94:
|
||||
case 0x98:
|
||||
case 0x9C:
|
||||
case 0xF0:
|
||||
case 0xF4:
|
||||
case 0xF8:
|
||||
case 0xFC:
|
||||
read_length = 4;
|
||||
}
|
||||
|
||||
switch(read_length){
|
||||
case 1:
|
||||
mpc106_read_word |= (grab_macmem_ptr[mpc106_address]);
|
||||
break;
|
||||
case 2:
|
||||
mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]);
|
||||
mpc106_read_word |= (grab_macmem_ptr[mpc106_address]) << 8;
|
||||
break;
|
||||
case 4:
|
||||
mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]);
|
||||
mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]) << 8;
|
||||
mpc106_read_word |= (grab_macmem_ptr[mpc106_address++]) << 16;
|
||||
mpc106_read_word |= (grab_macmem_ptr[mpc106_address]) << 24;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mpc106_write(uint32_t write_word){
|
||||
|
||||
uint8_t write_length = 4;
|
||||
|
||||
switch (mpc106_address){
|
||||
case 0x8:
|
||||
case 0x70:
|
||||
case 0x72:
|
||||
case 0x73:
|
||||
case 0xA0:
|
||||
write_length = 1;
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x2:
|
||||
case 0x4:
|
||||
case 0x6:
|
||||
write_length = 2;
|
||||
break;
|
||||
case 0x80:
|
||||
case 0x84:
|
||||
case 0x88:
|
||||
case 0x8C:
|
||||
case 0x90:
|
||||
case 0x94:
|
||||
case 0x98:
|
||||
case 0x9C:
|
||||
case 0xF0:
|
||||
case 0xF4:
|
||||
case 0xF8:
|
||||
case 0xFC:
|
||||
write_length = 4;
|
||||
}
|
||||
|
||||
switch(write_length){
|
||||
case 1:
|
||||
grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word) & 0xFF);
|
||||
break;
|
||||
case 2:
|
||||
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF);
|
||||
grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF);
|
||||
break;
|
||||
case 4:
|
||||
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word) & 0xFF);
|
||||
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 8) & 0xFF);
|
||||
grab_macmem_ptr[mpc106_address++] |= (uint8_t)((mpc106_read_word >> 16) & 0xFF);
|
||||
grab_macmem_ptr[mpc106_address] |= (uint8_t)((mpc106_read_word >> 24) & 0xFF);
|
||||
break;
|
||||
}
|
||||
}
|
32
mpc106.h
Normal file
32
mpc106.h
Normal file
@ -0,0 +1,32 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the MPC106
|
||||
|
||||
#ifndef MPC106_H_
|
||||
#define MPC106_H_
|
||||
|
||||
#define mpc106_addres_map_a 1
|
||||
#define mpc106_addres_map_b 0
|
||||
|
||||
extern uint32_t mpc106_address;
|
||||
extern uint32_t mpc_config_addr;
|
||||
extern uint32_t mpc_config_dat;
|
||||
|
||||
extern uint32_t mpc106_write_word;
|
||||
extern uint32_t mpc106_read_word;
|
||||
extern uint16_t mpc106_write_half;
|
||||
extern uint16_t mpc106_read_half;
|
||||
extern uint8_t mpc106_write_byte;
|
||||
extern uint8_t mpc106_read_byte;
|
||||
extern unsigned char* mpc106_regs;
|
||||
|
||||
extern void mpc106_init();
|
||||
extern void mpc106_read();
|
||||
extern void mpc106_write(uint32_t write_word);
|
||||
|
||||
#endif
|
34
openpic.cpp
Normal file
34
openpic.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the OPENPIC
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <cinttypes>
|
||||
#include "ppcemumain.h"
|
||||
|
||||
uint32_t openpic_address;
|
||||
uint32_t openpic_write_word;
|
||||
uint32_t openpic_read_word;
|
||||
|
||||
void openpic_init(){
|
||||
for (int i = 0x40004; i < 0x7FFFF; i++){
|
||||
if (i % 16 == 0){
|
||||
i += 4;
|
||||
}
|
||||
machine_upperiocontrol_mem[i] = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void openpic_read(){
|
||||
machine_upperiocontrol_mem[openpic_address] = openpic_read_word;
|
||||
}
|
||||
|
||||
void openpic_write(){
|
||||
openpic_write_word = machine_upperiocontrol_mem[openpic_address];
|
||||
}
|
21
openpic.h
Normal file
21
openpic.h
Normal file
@ -0,0 +1,21 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the OPENPIC
|
||||
|
||||
#ifndef OPENPIC_H_
|
||||
#define OPENPIC_H_
|
||||
|
||||
extern uint32_t openpic_address;
|
||||
extern uint32_t openpic_write_word;
|
||||
extern uint32_t openpic_read_word;
|
||||
|
||||
extern void openpic_init();
|
||||
extern void openpic_read();
|
||||
extern void openpic_write();
|
||||
|
||||
#endif
|
795
poweropcodes.cpp
Normal file
795
poweropcodes.cpp
Normal file
@ -0,0 +1,795 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
// The Power-specific opcodes for the processor - ppcopcodes.cpp
|
||||
// Any shared opcodes are in ppcopcodes.cpp
|
||||
|
||||
#include <iostream>
|
||||
#include <array>
|
||||
#include <stdio.h>
|
||||
#include <stdexcept>
|
||||
#include "ppcemumain.h"
|
||||
#include "ppcmemory.h"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
void power_abs(){
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000){
|
||||
ppc_result_d = ppc_result_a;
|
||||
|
||||
}
|
||||
else{
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
|
||||
void power_absdot(){
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000){
|
||||
ppc_result_d = ppc_result_a;
|
||||
|
||||
}
|
||||
else{
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_abso(){
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000){
|
||||
ppc_result_d = ppc_result_a;
|
||||
ppc_state.ppc_spr[1] |= 0x40000000;
|
||||
|
||||
}
|
||||
else{
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_absodot(){
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000){
|
||||
ppc_result_d = ppc_result_a;
|
||||
ppc_state.ppc_spr[1] |= 0x40000000;
|
||||
|
||||
}
|
||||
else{
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_clcs(){
|
||||
ppc_grab_regsda();
|
||||
switch(reg_a){
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
ppc_result_d = 65535;
|
||||
break;
|
||||
default:
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_clcsdot(){
|
||||
switch(reg_a){
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
ppc_result_d = 65535;
|
||||
break;
|
||||
default:
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
printf("Does RC do anything here? (TODO) \n");
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_div(){
|
||||
ppc_grab_regsdab();
|
||||
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
|
||||
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_divdot(){
|
||||
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
|
||||
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
|
||||
}
|
||||
|
||||
void power_divo(){
|
||||
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
|
||||
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
|
||||
}
|
||||
|
||||
void power_divodot(){
|
||||
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
|
||||
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
|
||||
}
|
||||
|
||||
void power_divs(){
|
||||
ppc_grab_regsdab();
|
||||
ppc_result_d = ppc_result_a / ppc_result_b;
|
||||
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_divsdot(){
|
||||
ppc_result_d = ppc_result_a / ppc_result_b;
|
||||
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
|
||||
}
|
||||
|
||||
void power_divso(){
|
||||
ppc_result_d = ppc_result_a / ppc_result_b;
|
||||
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
|
||||
}
|
||||
|
||||
void power_divsodot(){
|
||||
ppc_result_d = ppc_result_a / ppc_result_b;
|
||||
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
|
||||
}
|
||||
|
||||
void power_doz(){
|
||||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else{
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_dozdot(){
|
||||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else{
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_dozo(){
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else{
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void power_dozodot(){
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else{
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void power_dozi(){
|
||||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > simm){
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
else{
|
||||
ppc_result_d = ~ppc_result_a + simm + 1;
|
||||
}
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_lscbx(){
|
||||
ppc_grab_regsdab();
|
||||
uint32_t bytes_copied = 0;
|
||||
bool match_found = false;
|
||||
uint32_t shift_amount = 0;
|
||||
uint8_t byte_compared = (uint8_t)((ppc_state.ppc_spr[1] & 0xFF00) >> 8);
|
||||
if ((ppc_state.ppc_spr[1] & 0x7f) == 0){
|
||||
return;
|
||||
}
|
||||
uint32_t bytes_to_load = (ppc_state.ppc_spr[1] & 0x7f) + 1;
|
||||
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
|
||||
do{
|
||||
ppc_effective_address++;
|
||||
bytes_to_load--;
|
||||
if (match_found == false){
|
||||
switch(shift_amount){
|
||||
case 0:
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1);
|
||||
ppc_result_d = (ppc_result_d & 0x00FFFFFF) | (return_value << 24);
|
||||
ppc_store_result_regd();
|
||||
break;
|
||||
case 1:
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1);
|
||||
ppc_result_d = (ppc_result_d & 0xFF00FFFF) | (return_value << 16);
|
||||
ppc_store_result_regd();
|
||||
break;
|
||||
case 2:
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1);
|
||||
ppc_result_d = (ppc_result_d & 0xFFFF00FF) | (return_value << 8);
|
||||
ppc_store_result_regd();
|
||||
break;
|
||||
case 3:
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_result_d, 1);
|
||||
ppc_result_d = (ppc_result_d & 0xFFFFFF00) | return_value;
|
||||
ppc_store_result_regd();
|
||||
break;
|
||||
}
|
||||
|
||||
bytes_copied++;
|
||||
}
|
||||
if (((uint8_t)return_value) == byte_compared){
|
||||
break;
|
||||
}
|
||||
|
||||
return_value = 0;
|
||||
|
||||
if (shift_amount == 3){
|
||||
shift_amount = 0;
|
||||
reg_d = (reg_d + 1) & 0x1F;
|
||||
}
|
||||
else{
|
||||
shift_amount++;
|
||||
}
|
||||
}while (bytes_to_load > 0);
|
||||
ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xFFFFFF80) | bytes_copied;
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_lscbxdot(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_maskg(){
|
||||
ppc_grab_regssab();
|
||||
uint32_t mask_start = ppc_result_d & 31;
|
||||
uint32_t mask_end = ppc_result_b & 31;
|
||||
uint32_t insert_mask = 0;
|
||||
|
||||
if (mask_start < (mask_end + 1)){
|
||||
for (uint32_t i = mask_start; i < mask_end; i++){
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
}
|
||||
else if (mask_start == (mask_end + 1)){
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
}
|
||||
else{
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++){
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_mask;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_maskgdot(){
|
||||
ppc_grab_regssab();
|
||||
uint32_t mask_start = ppc_result_d & 31;
|
||||
uint32_t mask_end = ppc_result_b & 31;
|
||||
uint32_t insert_mask = 0;
|
||||
|
||||
if (mask_start < (mask_end + 1)){
|
||||
for (uint32_t i = mask_start; i < mask_end; i++){
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
}
|
||||
else if (mask_start == (mask_end + 1)){
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
}
|
||||
else{
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++){
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_mask;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_maskir(){
|
||||
ppc_grab_regssab();
|
||||
uint32_t mask_insert = ppc_result_a;
|
||||
uint32_t insert_rot = 0x80000000;
|
||||
do{
|
||||
if (ppc_result_b & insert_rot){
|
||||
mask_insert &= ~insert_rot;
|
||||
mask_insert |= (ppc_result_d & insert_rot);
|
||||
}
|
||||
insert_rot = insert_rot>> 1;
|
||||
}while(insert_rot > 0);
|
||||
|
||||
ppc_result_a = (ppc_result_d & ppc_result_b);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_maskirdot(){
|
||||
ppc_grab_regssab();
|
||||
uint32_t mask_insert = ppc_result_a;
|
||||
uint32_t insert_rot = 0x80000000;
|
||||
do{
|
||||
if (ppc_result_b & insert_rot){
|
||||
mask_insert &= ~insert_rot;
|
||||
mask_insert |= (ppc_result_d & insert_rot);
|
||||
}
|
||||
insert_rot = insert_rot>> 1;
|
||||
}while(insert_rot > 0);
|
||||
|
||||
ppc_result_a = (ppc_result_d & ppc_result_b);
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_mul(){
|
||||
ppc_grab_regsdab();
|
||||
uint64_t product;
|
||||
|
||||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.ppc_spr[0] = ((uint32_t)(product));
|
||||
ppc_store_result_regd();
|
||||
|
||||
}
|
||||
|
||||
void power_muldot(){
|
||||
ppc_grab_regsdab();
|
||||
uint64_t product;
|
||||
|
||||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.ppc_spr[0] = ((uint32_t)(product));
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_regd();
|
||||
|
||||
}
|
||||
|
||||
void power_mulo(){
|
||||
uint64_t product;
|
||||
|
||||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.ppc_spr[0] = ((uint32_t)(product));
|
||||
|
||||
}
|
||||
|
||||
void power_mulodot(){
|
||||
uint64_t product;
|
||||
|
||||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.ppc_spr[0] = ((uint32_t)(product));
|
||||
|
||||
}
|
||||
|
||||
void power_nabs(){
|
||||
ppc_grab_regsda();
|
||||
ppc_result_d = (0x80000000 | ppc_result_a);
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_nabsdot(){
|
||||
ppc_result_d = (0x80000000 | ppc_result_a);
|
||||
}
|
||||
|
||||
void power_nabso(){
|
||||
ppc_result_d = (0x80000000 | ppc_result_a);
|
||||
}
|
||||
|
||||
void power_nabsodot(){
|
||||
ppc_result_d = (0x80000000 | ppc_result_a);
|
||||
}
|
||||
|
||||
void power_rlmi(){
|
||||
ppc_grab_regssab();
|
||||
rot_mb = (ppc_cur_instruction >> 6) & 31;
|
||||
rot_me = (ppc_cur_instruction >> 1) & 31;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
uint32_t insert_mask = 0;
|
||||
|
||||
if (rot_mb < (rot_me + 1)){
|
||||
for (uint32_t i = rot_mb; i < rot_me; i++){
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
}
|
||||
else if (rot_mb == (rot_me + 1)){
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
}
|
||||
else{
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (rot_me + 1); i < (rot_mb - 1); i++){
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t step2 = (ppc_result_d << rot_amt) | (ppc_result_d >> rot_amt);
|
||||
ppc_result_a = step2 & insert_mask;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_rrib(){
|
||||
ppc_grab_regssab();
|
||||
if (ppc_result_d & 0x80000000){
|
||||
ppc_result_a |= (0x80000000 >> ppc_result_b);
|
||||
}
|
||||
else{
|
||||
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
|
||||
}
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_rribdot(){
|
||||
ppc_grab_regssab();
|
||||
if (ppc_result_d & 0x80000000){
|
||||
ppc_result_a |= (0x80000000 >> ppc_result_b);
|
||||
}
|
||||
else{
|
||||
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
|
||||
}
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sle(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_amt; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
|
||||
ppc_state.ppc_spr[0] = insert_final & insert_mask;
|
||||
ppc_result_a = insert_final & insert_mask;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sledot(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_amt; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
|
||||
ppc_state.ppc_spr[0] = insert_final & insert_mask;
|
||||
ppc_result_a = insert_final & insert_mask;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sleq(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_amt; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sleqdot(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_amt; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sliq(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end & insert_mask;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sliqdot(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end & insert_mask;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_slliq(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_slliqdot(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sllq(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_sllqdot(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_slq(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_slqdot(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_sraiq(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_sraiqdot(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_sraq(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_sraqdot(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_sre(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_amt; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
|
||||
ppc_state.ppc_spr[0] = insert_final & insert_mask;
|
||||
ppc_result_a = insert_final;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sredot(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_amt; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
|
||||
ppc_state.ppc_spr[0] = insert_final & insert_mask;
|
||||
ppc_result_a = insert_final;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_srea(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_sreadot(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_sreq(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
rot_sh = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sreqdot(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
rot_sh = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sriq(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sriqdot(){
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--){
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
|
||||
uint32_t insert_end = ppc_state.ppc_spr[0];
|
||||
|
||||
for (int i = 0; i < 32; i++){
|
||||
if (insert_mask & (1 << i)){
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.ppc_spr[0] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_srliq(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_srliqdot(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_srlq(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_srlqdot(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_srq(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_srqdot(){
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
762
ppcemumain.h
Normal file
762
ppcemumain.h
Normal file
@ -0,0 +1,762 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
#ifndef PPCEMUMAIN_H_
|
||||
#define PPCEMUMAIN_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
enum endian_switch {big_end = 0, little_end = 1};
|
||||
|
||||
typedef void (*PPCOpcode)(void);
|
||||
|
||||
/**
|
||||
Except for the floating-point registers, all registers require
|
||||
32 bits for representation. Floating-point registers need 64 bits.
|
||||
|
||||
gpr = General Purpose Register
|
||||
fpr = Floating Point (FP) Register
|
||||
cr = Condition Register
|
||||
tbr = Time Base Register
|
||||
fpscr = FP Status and Condition Register
|
||||
spr = Special Register
|
||||
msr = Machine State Register
|
||||
sr = Segment Register
|
||||
**/
|
||||
|
||||
typedef struct struct_ppc_state {
|
||||
uint64_t ppc_fpr [32];
|
||||
uint32_t ppc_pc; //Referred as the CIA in the PPC manual
|
||||
uint32_t ppc_gpr [32];
|
||||
uint32_t ppc_cr;
|
||||
uint32_t ppc_fpscr;
|
||||
uint32_t ppc_tbr [2];
|
||||
uint32_t ppc_spr [1024];
|
||||
uint32_t ppc_msr;
|
||||
uint32_t ppc_sr [16];
|
||||
bool ppc_reserve; //reserve bit used for lwarx and stcwx
|
||||
} SetPRS;
|
||||
|
||||
extern SetPRS ppc_state;
|
||||
|
||||
/**
|
||||
typedef struct struct_ppc64_state {
|
||||
uint64_t ppc_fpr [32];
|
||||
uint64_t ppc_pc; //Referred as the CIA in the PPC manual
|
||||
uint64_t ppc_gpr [32];
|
||||
uint32_t ppc_cr;
|
||||
uint32_t ppc_fpscr;
|
||||
uint32_t ppc_tbr [2];
|
||||
uint64_t ppc_spr [1024];
|
||||
uint32_t ppc_msr;
|
||||
uint32_t ppc_sr [16];
|
||||
bool ppc_reserve; //reserve bit used for lwarx and stcwx
|
||||
} SetPRS64;
|
||||
|
||||
extern SetPRS64 ppc_state64;
|
||||
**/
|
||||
|
||||
/**
|
||||
Specific SPRS to be weary of:
|
||||
|
||||
USER MODEL
|
||||
SPR 1 - XER
|
||||
SPR 8 - Link Register / Branch
|
||||
b0 - Summary Overflow
|
||||
b1 - Overflow
|
||||
b2 - Carry
|
||||
b25-31 - Number of bytes to transfer
|
||||
SPR 9 - Count
|
||||
|
||||
SUPERVISOR MODEL
|
||||
19 is the Data Address Register
|
||||
22 is the Decrementer
|
||||
26, 27 are the Save and Restore Registers (SRR0, SRR1)
|
||||
272 - 275 are the SPRGs
|
||||
284 - 285 for writing to the TBR's.
|
||||
528 - 535 are the Instruction BAT registers
|
||||
536 - 543 are the Data BAT registers
|
||||
**/
|
||||
|
||||
extern uint32_t return_value; //used for loading from memory
|
||||
|
||||
extern uint32_t pc_return_value; //used for getting instructions
|
||||
|
||||
extern uint32_t opcode_value; //used for interpreting opcodes
|
||||
extern uint32_t ram_size_set;
|
||||
|
||||
extern uint32_t rom_file_begin; //where to start storing ROM files in memory
|
||||
extern uint32_t pci_io_end;
|
||||
|
||||
extern uint32_t rom_file_setsize;
|
||||
|
||||
//Additional steps to prevent overflow?
|
||||
extern int32_t add_result;
|
||||
extern int32_t sidiv_result;
|
||||
extern int32_t simult_result;
|
||||
extern uint32_t uiadd_result;
|
||||
extern uint32_t uidiv_result;
|
||||
extern uint32_t uimult_result;
|
||||
extern uint64_t uiproduct;
|
||||
extern int64_t siproduct;
|
||||
|
||||
extern int32_t word_copy_location;
|
||||
extern uint32_t strwrd_replace_value;
|
||||
|
||||
extern uint32_t crf_d;
|
||||
extern uint32_t crf_s;
|
||||
extern uint32_t reg_s;
|
||||
extern uint32_t reg_d;
|
||||
extern uint32_t reg_a;
|
||||
extern uint32_t reg_b;
|
||||
extern uint32_t reg_c;
|
||||
extern uint32_t xercon;
|
||||
extern uint32_t cmp_c;
|
||||
extern uint32_t crm;
|
||||
extern uint32_t br_bo;
|
||||
extern uint32_t br_bi;
|
||||
extern uint32_t rot_sh;
|
||||
extern uint32_t rot_mb;
|
||||
extern uint32_t rot_me;
|
||||
extern uint32_t uimm;
|
||||
extern uint32_t not_this;
|
||||
extern uint32_t grab_sr;
|
||||
extern uint32_t grab_inb; //This is for grabbing the number of immediate bytes for loading and storing
|
||||
extern uint32_t grab_d; //This is for grabbing d from Store and Load instructions
|
||||
extern uint32_t ppc_to;
|
||||
extern int32_t simm;
|
||||
extern int32_t adr_li;
|
||||
extern int32_t br_bd;
|
||||
|
||||
//Used for GP calcs
|
||||
extern uint32_t ppc_result_a;
|
||||
extern uint32_t ppc_result_b;
|
||||
extern uint32_t ppc_result_c;
|
||||
extern uint32_t ppc_result_d;
|
||||
|
||||
//Used for FP calcs
|
||||
extern uint64_t ppc_result64_a;
|
||||
extern uint64_t ppc_result64_b;
|
||||
extern uint64_t ppc_result64_c;
|
||||
extern uint64_t ppc_result64_d;
|
||||
|
||||
extern uint16_t rev_endian16(uint16_t insert_int);
|
||||
extern uint32_t uimm_rev_endian16(uint32_t insert_int);
|
||||
extern int32_t simm_rev_endian16(int32_t insert_int);
|
||||
extern uint32_t rev_endian32(uint32_t insert_int);
|
||||
extern uint64_t rev_endian64(uint64_t insert_int);
|
||||
|
||||
extern bool grab_branch;
|
||||
extern bool grab_exception;
|
||||
extern bool grab_return;
|
||||
|
||||
extern bool is_601; //For PowerPC 601 Emulation
|
||||
extern bool is_gekko; //For GameCube Emulation
|
||||
extern bool is_altivec; //For Altivec Emulation
|
||||
extern bool is_64bit; //For PowerPC G5 Emulation
|
||||
|
||||
//uint64_t virtual_address;
|
||||
|
||||
//Important Addressing Integers
|
||||
extern uint64_t ppc_virtual_address; //It's 52 bits
|
||||
extern uint32_t ppc_cur_instruction;
|
||||
extern uint32_t ppc_effective_address;
|
||||
extern uint32_t ppc_real_address;
|
||||
extern uint32_t ppc_next_instruction_address;
|
||||
extern uint32_t temp_address; //used for determining where memory ends up.
|
||||
|
||||
//Function prototypes
|
||||
void reg_init();
|
||||
uint32_t reg_print();
|
||||
uint32_t reg_read();
|
||||
uint32_t reg_write();
|
||||
|
||||
void ppc_illegalop();
|
||||
void ppc_opcode4();
|
||||
void ppc_opcode16();
|
||||
void ppc_opcode18();
|
||||
void ppc_opcode19();
|
||||
void ppc_opcode31();
|
||||
void ppc_opcode59();
|
||||
void ppc_opcode63();
|
||||
|
||||
extern void ppc_grab_regsda();
|
||||
extern void ppc_grab_regsdb();
|
||||
|
||||
extern void ppc_grab_regssa();
|
||||
extern void ppc_grab_regssb();
|
||||
|
||||
extern void ppc_grab_regsdab();
|
||||
extern void ppc_grab_regssab();
|
||||
|
||||
extern void ppc_grab_regsdasimm();
|
||||
extern void ppc_grab_regsdauimm();
|
||||
extern void ppc_grab_regssasimm();
|
||||
extern void ppc_grab_regssauimm();
|
||||
|
||||
extern void ppc_grab_regsfpdb();
|
||||
extern void ppc_grab_regsfpdab();
|
||||
extern void ppc_grab_regsfpdia();
|
||||
extern void ppc_grab_regsfpdiab();
|
||||
extern void ppc_grab_regsfpsia();
|
||||
extern void ppc_grab_regsfpsiab();
|
||||
|
||||
extern void ppc_store_result_regd();
|
||||
extern void ppc_store_result_rega();
|
||||
extern void ppc_store_sfpresult();
|
||||
extern void ppc_store_dfpresult();
|
||||
|
||||
void ppc_carry(uint32_t a, uint32_t b);
|
||||
void ppc_setsoov(uint32_t a, uint32_t b);
|
||||
void ppc_changecrf0(uint32_t set_result);
|
||||
|
||||
void ppc_tbr_update();
|
||||
void ppc_expection_handler(uint32_t exception_type, uint32_t handle_args);
|
||||
|
||||
//MEMORY DECLARATIONS
|
||||
extern unsigned char * machine_sysram_mem;
|
||||
extern unsigned char * machine_sysconfig_mem;
|
||||
//Mapped to 0x68000000 - extern unsigned char * machine_68kemu_mem;
|
||||
extern unsigned char * machine_upperiocontrol_mem;
|
||||
extern unsigned char * machine_iocontrolcdma_mem;
|
||||
extern unsigned char * machine_loweriocontrol_mem;
|
||||
extern unsigned char * machine_interruptack_mem;
|
||||
extern unsigned char * machine_iocontrolmem_mem;
|
||||
extern unsigned char * machine_f8xxxx_mem;
|
||||
extern unsigned char * machine_fexxxx_mem;
|
||||
extern unsigned char * machine_fecxxx_mem;
|
||||
extern unsigned char * machine_feexxx_mem;
|
||||
extern unsigned char * machine_ff00xx_mem;
|
||||
extern unsigned char * machine_ff80xx_mem;
|
||||
extern unsigned char * machine_sysrom_mem;
|
||||
|
||||
//The functions used by the PowerPC processor
|
||||
extern void ppc_bcctr();
|
||||
extern void ppc_bcctrl();
|
||||
extern void ppc_bclr();
|
||||
extern void ppc_bclrl();
|
||||
extern void ppc_crand();
|
||||
extern void ppc_crandc();
|
||||
extern void ppc_creqv();
|
||||
extern void ppc_crnand();
|
||||
extern void ppc_crnor();
|
||||
extern void ppc_cror();
|
||||
extern void ppc_crorc();
|
||||
extern void ppc_crxor();
|
||||
extern void ppc_isync();
|
||||
|
||||
extern void ppc_add();
|
||||
extern void ppc_adddot();
|
||||
extern void ppc_addo();
|
||||
extern void ppc_addodot();
|
||||
extern void ppc_addc();
|
||||
extern void ppc_addcdot();
|
||||
extern void ppc_addco();
|
||||
extern void ppc_addcodot();
|
||||
extern void ppc_adde();
|
||||
extern void ppc_addedot();
|
||||
extern void ppc_addeo();
|
||||
extern void ppc_addeodot();
|
||||
extern void ppc_addme();
|
||||
extern void ppc_addmedot();
|
||||
extern void ppc_addmeo();
|
||||
extern void ppc_addmeodot();
|
||||
extern void ppc_addze();
|
||||
extern void ppc_addzedot();
|
||||
extern void ppc_addzeo();
|
||||
extern void ppc_addzeodot();
|
||||
extern void ppc_and();
|
||||
extern void ppc_anddot();
|
||||
extern void ppc_andc();
|
||||
extern void ppc_andcdot();
|
||||
extern void ppc_cmp();
|
||||
extern void ppc_cmpl();
|
||||
extern void ppc_cntlzw();
|
||||
extern void ppc_cntlzwdot();
|
||||
extern void ppc_dcbf();
|
||||
extern void ppc_dcbi();
|
||||
extern void ppc_dcbst();
|
||||
extern void ppc_dcbt();
|
||||
extern void ppc_dcbtst();
|
||||
extern void ppc_dcbz();
|
||||
extern void ppc_divw();
|
||||
extern void ppc_divwdot();
|
||||
extern void ppc_divwo();
|
||||
extern void ppc_divwodot();
|
||||
extern void ppc_divwu();
|
||||
extern void ppc_divwudot();
|
||||
extern void ppc_divwuo();
|
||||
extern void ppc_divwuodot();
|
||||
extern void ppc_eieio();
|
||||
extern void ppc_eqv();
|
||||
extern void ppc_eqvdot();
|
||||
extern void ppc_extsb();
|
||||
extern void ppc_extsbdot();
|
||||
extern void ppc_extsh();
|
||||
extern void ppc_extshdot();
|
||||
extern void ppc_icbi();
|
||||
extern void ppc_mftb();
|
||||
extern void ppc_lhzux();
|
||||
extern void ppc_lhzx();
|
||||
extern void ppc_lhaux();
|
||||
extern void ppc_lhax();
|
||||
extern void ppc_lhbrx();
|
||||
extern void ppc_lwarx();
|
||||
extern void ppc_lbzux();
|
||||
extern void ppc_lbzx();
|
||||
extern void ppc_lwbrx();
|
||||
extern void ppc_lwzux();
|
||||
extern void ppc_lwzx();
|
||||
extern void ppc_mcrxr();
|
||||
extern void ppc_mfcr();
|
||||
extern void ppc_mulhwu();
|
||||
extern void ppc_mulhwudot();
|
||||
extern void ppc_mulhw();
|
||||
extern void ppc_mulhwdot();
|
||||
extern void ppc_mullw();
|
||||
extern void ppc_mullwdot();
|
||||
extern void ppc_mullwo();
|
||||
extern void ppc_mullwodot();
|
||||
extern void ppc_nand();
|
||||
extern void ppc_nanddot();
|
||||
extern void ppc_neg();
|
||||
extern void ppc_negdot();
|
||||
extern void ppc_nego();
|
||||
extern void ppc_negodot();
|
||||
extern void ppc_nor();
|
||||
extern void ppc_nordot();
|
||||
extern void ppc_or();
|
||||
extern void ppc_ordot();
|
||||
extern void ppc_orc();
|
||||
extern void ppc_orcdot();
|
||||
extern void ppc_slw();
|
||||
extern void ppc_slwdot();
|
||||
extern void ppc_srw();
|
||||
extern void ppc_srwdot();
|
||||
extern void ppc_sraw();
|
||||
extern void ppc_srawdot();
|
||||
extern void ppc_srawi();
|
||||
extern void ppc_srawidot();
|
||||
extern void ppc_stbx();
|
||||
extern void ppc_stbux();
|
||||
extern void ppc_stfiwx();
|
||||
extern void ppc_sthx();
|
||||
extern void ppc_sthux();
|
||||
extern void ppc_sthbrx();
|
||||
extern void ppc_stwx();
|
||||
extern void ppc_stwcx();
|
||||
extern void ppc_stwux();
|
||||
extern void ppc_stwbrx();
|
||||
extern void ppc_subf();
|
||||
extern void ppc_subfdot();
|
||||
extern void ppc_subfo();
|
||||
extern void ppc_subfodot();
|
||||
extern void ppc_subfc();
|
||||
extern void ppc_subfcdot();
|
||||
extern void ppc_subfco();
|
||||
extern void ppc_subfcodot();
|
||||
extern void ppc_subfe();
|
||||
extern void ppc_subfedot();
|
||||
extern void ppc_subfme();
|
||||
extern void ppc_subfmedot();
|
||||
extern void ppc_subfze();
|
||||
extern void ppc_subfzedot();
|
||||
extern void ppc_sync();
|
||||
extern void ppc_tlbia();
|
||||
extern void ppc_tlbie();
|
||||
extern void ppc_tlbli();
|
||||
extern void ppc_tlbld();
|
||||
extern void ppc_tlbsync();
|
||||
extern void ppc_tw();
|
||||
extern void ppc_xor();
|
||||
extern void ppc_xordot();
|
||||
|
||||
extern void ppc_lswi();
|
||||
extern void ppc_lswx();
|
||||
extern void ppc_stswi();
|
||||
extern void ppc_stswx();
|
||||
|
||||
extern void ppc_mfsr();
|
||||
extern void ppc_mfsrin();
|
||||
extern void ppc_mtsr();
|
||||
extern void ppc_mtsrin();
|
||||
|
||||
extern void ppc_mtcrf();
|
||||
extern void ppc_mfmsr();
|
||||
extern void ppc_mfspr();
|
||||
extern void ppc_mtmsr();
|
||||
extern void ppc_mtspr();
|
||||
|
||||
extern void ppc_mtfsb0();
|
||||
extern void ppc_mtfsb1();
|
||||
extern void ppc_mcrfs();
|
||||
extern void ppc_mtfsb0dot();
|
||||
extern void ppc_mtfsb1dot();
|
||||
extern void ppc_fmr();
|
||||
extern void ppc_mffs();
|
||||
extern void ppc_mtfsf();
|
||||
|
||||
extern void ppc_addi();
|
||||
extern void ppc_addic();
|
||||
extern void ppc_addicdot();
|
||||
extern void ppc_addis();
|
||||
extern void ppc_andidot();
|
||||
extern void ppc_andisdot();
|
||||
extern void ppc_b();
|
||||
extern void ppc_ba();
|
||||
extern void ppc_bl();
|
||||
extern void ppc_bla();
|
||||
extern void ppc_bc();
|
||||
extern void ppc_bca();
|
||||
extern void ppc_bcl();
|
||||
extern void ppc_bcla();
|
||||
extern void ppc_cmpi();
|
||||
extern void ppc_cmpli();
|
||||
extern void ppc_lbz();
|
||||
extern void ppc_lbzu();
|
||||
extern void ppc_lha();
|
||||
extern void ppc_lhau();
|
||||
extern void ppc_lhz();
|
||||
extern void ppc_lhzu();
|
||||
extern void ppc_lwz();
|
||||
extern void ppc_lwzu();
|
||||
extern void ppc_lmw();
|
||||
extern void ppc_mulli();
|
||||
extern void ppc_ori();
|
||||
extern void ppc_oris();
|
||||
extern void ppc_rfi();
|
||||
extern void ppc_rlwimi();
|
||||
extern void ppc_rlwinm();
|
||||
extern void ppc_rlwnm();
|
||||
extern void ppc_sc();
|
||||
extern void ppc_stb();
|
||||
extern void ppc_stbu();
|
||||
extern void ppc_sth();
|
||||
extern void ppc_sthu();
|
||||
extern void ppc_stw();
|
||||
extern void ppc_stwu();
|
||||
extern void ppc_stmw();
|
||||
extern void ppc_subfic();
|
||||
extern void ppc_twi();
|
||||
extern void ppc_xori();
|
||||
extern void ppc_xoris();
|
||||
|
||||
extern void ppc_lfs();
|
||||
extern void ppc_lfsu();
|
||||
extern void ppc_lfsux();
|
||||
extern void ppc_lfsx();
|
||||
extern void ppc_lfd();
|
||||
extern void ppc_lfdu();
|
||||
extern void ppc_stfs();
|
||||
extern void ppc_stfsu();
|
||||
extern void ppc_stfsux();
|
||||
extern void ppc_stfd();
|
||||
extern void ppc_stfdu();
|
||||
extern void ppc_stfdx();
|
||||
extern void ppc_stfdux();
|
||||
|
||||
extern void ppc_fadd();
|
||||
extern void ppc_fsub();
|
||||
extern void ppc_fmult();
|
||||
extern void ppc_fdiv();
|
||||
extern void ppc_fadds();
|
||||
extern void ppc_fsubs();
|
||||
extern void ppc_fmults();
|
||||
extern void ppc_fdivs();
|
||||
extern void ppc_fmadd();
|
||||
extern void ppc_fmsub();
|
||||
extern void ppc_fnmadd();
|
||||
extern void ppc_fnmsub();
|
||||
extern void ppc_fmadds();
|
||||
extern void ppc_fmsubs();
|
||||
extern void ppc_fnmadds();
|
||||
extern void ppc_fnmsubs();
|
||||
extern void ppc_fabs();
|
||||
extern void ppc_fneg();
|
||||
extern void ppc_fsel();
|
||||
extern void ppc_fres();
|
||||
extern void ppc_fsqrts();
|
||||
extern void ppc_fsqrt();
|
||||
extern void ppc_frsqrte();
|
||||
extern void ppc_frsp();
|
||||
extern void ppc_fctiw();
|
||||
extern void ppc_fctiwz();
|
||||
|
||||
extern void ppc_fcmpo();
|
||||
extern void ppc_fcmpu();
|
||||
|
||||
//Power-specific instructions
|
||||
extern void power_abs();
|
||||
extern void power_absdot();
|
||||
extern void power_abso();
|
||||
extern void power_absodot();
|
||||
extern void power_clcs();
|
||||
extern void power_clcsdot();
|
||||
extern void power_div();
|
||||
extern void power_divdot();
|
||||
extern void power_divo();
|
||||
extern void power_divodot();
|
||||
extern void power_divs();
|
||||
extern void power_divsdot();
|
||||
extern void power_divso();
|
||||
extern void power_divsodot();
|
||||
extern void power_doz();
|
||||
extern void power_dozdot();
|
||||
extern void power_dozo();
|
||||
extern void power_dozodot();
|
||||
extern void power_dozi();
|
||||
extern void power_lscbx();
|
||||
extern void power_lscbxdot();
|
||||
extern void power_maskg();
|
||||
extern void power_maskgdot();
|
||||
extern void power_maskir();
|
||||
extern void power_maskirdot();
|
||||
extern void power_mul();
|
||||
extern void power_muldot();
|
||||
extern void power_mulo();
|
||||
extern void power_mulodot();
|
||||
extern void power_nabs();
|
||||
extern void power_nabsdot();
|
||||
extern void power_nabso();
|
||||
extern void power_nabsodot();
|
||||
extern void power_rlmi();
|
||||
extern void power_rrib();
|
||||
extern void power_rribdot();
|
||||
extern void power_sle();
|
||||
extern void power_sledot();
|
||||
extern void power_sleq();
|
||||
extern void power_sleqdot();
|
||||
extern void power_sliq();
|
||||
extern void power_sliqdot();
|
||||
extern void power_slliq();
|
||||
extern void power_slliqdot();
|
||||
extern void power_sllq();
|
||||
extern void power_sllqdot();
|
||||
extern void power_slq();
|
||||
extern void power_slqdot();
|
||||
extern void power_sraiq();
|
||||
extern void power_sraiqdot();
|
||||
extern void power_sraq();
|
||||
extern void power_sraqdot();
|
||||
extern void power_sre();
|
||||
extern void power_sredot();
|
||||
extern void power_srea();
|
||||
extern void power_sreadot();
|
||||
extern void power_sreq();
|
||||
extern void power_sreqdot();
|
||||
extern void power_sriq();
|
||||
extern void power_sriqdot();
|
||||
extern void power_srliq();
|
||||
extern void power_srliqdot();
|
||||
extern void power_srlq();
|
||||
extern void power_srlqdot();
|
||||
extern void power_srq();
|
||||
extern void power_srqdot();
|
||||
|
||||
//Gekko instructions
|
||||
extern void ppc_psq_l();
|
||||
extern void ppc_psq_lu();
|
||||
extern void ppc_psq_st();
|
||||
extern void ppc_psq_stu();
|
||||
|
||||
//AltiVec instructions
|
||||
|
||||
//64-bit instructions
|
||||
|
||||
//G5+ instructions
|
||||
|
||||
extern void ppc_main_opcode();
|
||||
|
||||
//A listing of all of the available opcodes on the PPC.
|
||||
|
||||
static std::map<uint8_t, PPCOpcode> OpcodeGrabber =
|
||||
{{0, &ppc_illegalop}, {1, &ppc_illegalop}, {2, &ppc_illegalop}, {3, &ppc_twi},
|
||||
{4, &ppc_opcode4}, {5, &ppc_illegalop}, {6, &ppc_illegalop}, {7, &ppc_mulli},
|
||||
{8, &ppc_subfic}, {9, &power_dozi}, {10, &ppc_cmpli}, {11, &ppc_cmpi},
|
||||
{12, &ppc_addic}, {13, &ppc_addicdot}, {14, &ppc_addi}, {15, &ppc_addis},
|
||||
{16, &ppc_opcode16}, {17, &ppc_sc}, {18, &ppc_opcode18}, {19, &ppc_opcode19},
|
||||
{20, &ppc_rlwimi}, {21, &ppc_rlwinm}, {22, &power_rlmi}, {23, &ppc_rlwnm},
|
||||
{24, &ppc_ori}, {25, &ppc_oris}, {26, &ppc_xori}, {27, &ppc_xoris},
|
||||
{28, &ppc_andidot}, {29, &ppc_andisdot}, {30, &ppc_illegalop}, {31, &ppc_opcode31},
|
||||
{32, &ppc_lwz}, {33, &ppc_lwzu}, {34, &ppc_lbz}, {35, &ppc_lbzu},
|
||||
{36, &ppc_stw}, {37, &ppc_stwu}, {38, &ppc_stb}, {39, &ppc_stbu},
|
||||
{40, &ppc_lhz}, {41, &ppc_lhzu}, {42, &ppc_lha}, {42, &ppc_lhau},
|
||||
{44, &ppc_sth}, {45, &ppc_sthu}, {46, &ppc_lmw}, {47, &ppc_stmw},
|
||||
{48, &ppc_lfs}, {49, &ppc_lfsu}, {50, &ppc_lfd}, {51, &ppc_lfdu},
|
||||
{52, &ppc_stfs}, {53, &ppc_stfsu}, {54, &ppc_stfd}, {55, &ppc_stfdu},
|
||||
{56, &ppc_psq_l}, {57, &ppc_psq_lu}, {58, &ppc_illegalop}, {59, &ppc_illegalop},
|
||||
{60, &ppc_psq_st}, {61, &ppc_psq_stu}, {62, &ppc_illegalop}, {63, &ppc_opcode63}};
|
||||
|
||||
//All of the opcodes possible are generated from the first 6 bits
|
||||
//of each instruction given by the processor.
|
||||
|
||||
|
||||
/**These next few tables combine the last 11 bits of an instruction
|
||||
to generate an opcode. These means different opcodes for up to
|
||||
four different forms of a function.
|
||||
|
||||
There are four big families of opcodes
|
||||
|
||||
Opcode 19 - General Conditional Register Functions
|
||||
Opcode 31 - General Integer Functions
|
||||
Opcode 59 - Single-Precision Floating-Point Functions
|
||||
Opcode 63 - Double-Precision Floating-Point Functions
|
||||
|
||||
The last two have instructions that don't neatly feat into one
|
||||
table, partially due to instructions that use either 6 or 11 bits
|
||||
for the instruction.
|
||||
**/
|
||||
static std::map<uint8_t, PPCOpcode> SubOpcode16Grabber=
|
||||
{{0, &ppc_bc}, {1, &ppc_bcl}, {2, &ppc_bca}, {3, &ppc_bcla}
|
||||
};
|
||||
static std::map<uint8_t, PPCOpcode> SubOpcode18Grabber=
|
||||
{{0, &ppc_b}, {1, &ppc_bl}, {2, &ppc_ba}, {3, &ppc_bla}
|
||||
};
|
||||
static std::map<uint16_t, PPCOpcode> SubOpcode19Grabber=
|
||||
{{32, &ppc_bclr}, {33, &ppc_bclrl}, {66, &ppc_crnor}, {100, &ppc_rfi},
|
||||
{258, &ppc_crandc}, {300, &ppc_isync}, {386, &ppc_crxor}, {450, &ppc_crnand},
|
||||
{514, &ppc_crand}, {578, &ppc_creqv}, {834, &ppc_crorc}, {898, &ppc_cror},
|
||||
{1056, &ppc_bcctr}, {1057, &ppc_bcctrl}
|
||||
};
|
||||
static std::map<uint16_t, PPCOpcode> SubOpcode31Grabber=
|
||||
{{0, &ppc_cmp}, {8, &ppc_tw}, {16, &ppc_subfc}, {17, &ppc_subfcdot},
|
||||
{20, &ppc_addc}, {21, &ppc_addcdot}, {22, &ppc_mulhwu}, {23, &ppc_mulhwudot},
|
||||
{38, &ppc_mfcr}, {40, &ppc_lwarx}, {46, &ppc_lwzx}, {48, &ppc_slw},
|
||||
{49, &ppc_slwdot}, {52, &ppc_cntlzw}, {53, &ppc_cntlzwdot}, {56, &ppc_and},
|
||||
{57, &ppc_anddot}, {58, &power_maskg}, {59, &power_maskgdot},
|
||||
{64, &ppc_cmpl}, {80, &ppc_subf}, {81, &ppc_subfdot},
|
||||
{108, &ppc_dcbst}, {110, &ppc_lwzux}, {120, &ppc_andc}, {121, &ppc_andcdot},
|
||||
{150, &ppc_mulhw}, {151, &ppc_mulhwdot}, {166, &ppc_mfmsr}, {172, &ppc_dcbf},
|
||||
{174, &ppc_lbzx}, {208, &ppc_neg}, {209, &ppc_negdot},
|
||||
{214, &power_mul}, {215, &power_mulo}, {238, &ppc_lbzux},
|
||||
{248, &ppc_nor}, {249, &ppc_nordot}, {272, &ppc_subfe}, {273, &ppc_subfedot},
|
||||
{276, &ppc_adde}, {277, &ppc_addedot}, {288, &ppc_mtcrf}, {292, &ppc_mtmsr},
|
||||
{301, &ppc_stwcx}, {302, &ppc_stwx}, {304, &power_slq}, {305, &power_slqdot},
|
||||
{306, &power_sle}, {307, &power_sledot}, {366, &ppc_stwux},
|
||||
{368, &power_sliq}, {400, &ppc_subfze},
|
||||
{401, &ppc_subfzedot}, {404, &ppc_addze}, {405, &ppc_addzedot}, {420, &ppc_mtsr},
|
||||
{430, &ppc_stbx}, {432, &power_sllq}, {433, &power_sllqdot}, {434, &power_sleq},
|
||||
{436, &power_sleqdot}, {464, &ppc_subfme}, {465, &ppc_subfmedot}, {468, &ppc_addme},
|
||||
{469, &ppc_addmedot}, {470, &ppc_mullw}, {471, &ppc_mullwdot}, {484, &ppc_mtsrin},
|
||||
{492, &ppc_dcbtst}, {494, &ppc_stbux}, {496, &power_slliq}, {497, &power_slliqdot},
|
||||
{528, &power_doz}, {529, &power_dozdot}, {532, &ppc_add}, {533, &ppc_adddot},
|
||||
{554, &power_lscbx}, {555, &power_lscbxdot}, {556, &ppc_dcbt},
|
||||
{558, &ppc_lhzx}, {568, &ppc_eqv}, {569, &ppc_eqvdot}, {612, &ppc_tlbie},
|
||||
{622, &ppc_lhzux}, {632, &ppc_xor}, {633, &ppc_xordot}, {662, &power_div},
|
||||
{663, &power_divdot}, {678, &ppc_mfspr}, {686, &ppc_lhax},
|
||||
{720, &power_abs}, {721, &power_absdot}, {726, &power_divs}, {727, &power_divsdot},
|
||||
{740, &ppc_tlbia}, {742, &ppc_mftb}, {750, &ppc_lhaux}, {814, &ppc_sthx},
|
||||
{824, &ppc_orc}, {825, &ppc_orcdot}, {878, &ppc_sthx},
|
||||
{888, &ppc_or}, {889, &ppc_ordot}, {918, &ppc_divwu}, {919, &ppc_divwudot},
|
||||
{934, &ppc_mtspr}, {940, &ppc_dcbi}, {952, &ppc_nand}, {953, &ppc_nanddot},
|
||||
{976, &power_nabs}, {977, &power_nabsdot}, {982, &ppc_divw}, {983, &ppc_divwdot},
|
||||
{1024, &ppc_mcrxr}, {1040, &ppc_subfco}, {1041, &ppc_subfcodot}, {1044, &ppc_addco},
|
||||
{1045, &ppc_addcodot}, {1062, &power_clcs}, {1063, &power_clcsdot}, {1066, &ppc_lswx},
|
||||
{1068, &ppc_lwbrx}, {1070, &ppc_lfsx}, {1072, &ppc_srw}, {1073, &ppc_srwdot},
|
||||
{1074, &power_rrib}, {1075, &power_rribdot}, {1082, &power_maskir}, {1083, &power_maskirdot},
|
||||
{1104, &ppc_subfo}, {1105, &ppc_subfodot}, {1134, &ppc_lfsux}, {1190, &ppc_mfsr},
|
||||
{1194, &ppc_lswi}, {1196, &ppc_isync}, {1232, &ppc_nego}, {1233, &ppc_negodot},
|
||||
{1238, &power_mulo}, {1239, &power_mulodot},
|
||||
{1300, &ppc_addeo}, {1301, &ppc_addeodot}, {1318, &ppc_mfsrin}, {1322, &ppc_stswx},
|
||||
{1324, &ppc_stwbrx}, {1328, &power_srq}, {1329, &power_srqdot}, {1330, &power_sre},
|
||||
{1331, &power_sredot}, {1390, &ppc_stfsux}, {1392, &power_sriq}, {1393, &power_sriqdot},
|
||||
{1428, &ppc_addzeo}, {1429, &ppc_addzeodot}, {1450, &ppc_stswi}, {1454, &ppc_stfdx},
|
||||
{1456, &power_srlq}, {1457, &power_srlqdot}, {1458, &power_sreq}, {1459, &power_sreqdot},
|
||||
{1492, &ppc_addmeo}, {1493, &ppc_addmeodot},
|
||||
{1494, &ppc_mullwo}, {1495, &ppc_mullwodot}, {1518, &ppc_stfdux}, {1520, &power_srliq},
|
||||
{1521, &power_srliqdot},{1552, &power_dozo}, {1553, &power_dozodot}, {1556, &ppc_addo},
|
||||
{1557, &ppc_addodot}, {1580, &ppc_lhbrx}, {1584, &ppc_sraw}, {1585, &ppc_srawdot},
|
||||
{1648, &ppc_srawi}, {1649, &ppc_srawidot}, {1686, &power_divo}, {1687, &power_divodot},
|
||||
{1708, &ppc_eieio}, {1744, &power_abso}, {1745, &power_absodot},
|
||||
{1750, &power_divso}, {1751, &power_divsodot}, {1836, &ppc_sthbrx},
|
||||
{1840, &power_sraq}, {1841, &power_sraqdot}, {1842, &power_srea}, {1843, &power_sreadot},
|
||||
{1844, &ppc_extsh}, {1845, &ppc_extshdot}, {1904, &power_sraiq}, {1905, &power_sraiqdot},
|
||||
{1908, &ppc_extsb}, {1909, &ppc_extsbdot}, {1942, &ppc_divwuo},
|
||||
{1943, &ppc_divwuodot}, {1956, &ppc_tlbld}, {1964, &ppc_icbi}, {1966, &ppc_stfiwx},
|
||||
{2000, &power_nabso}, {2001, &power_nabsodot}, {2006, &ppc_divwo}, {2007, &ppc_divwodot},
|
||||
{2020, &ppc_tlbli}, {2028, &ppc_dcbz}
|
||||
};
|
||||
|
||||
static std::map<uint16_t, PPCOpcode> SubOpcode59Grabber=
|
||||
{{36, &ppc_fdivs}, {40, &ppc_fsubs}, {42, &ppc_fadds}, {44, &ppc_fsqrts}, {48, &ppc_frsp},
|
||||
{50, &ppc_fmults}, {56, &ppc_fmsubs}, {58, &ppc_fmadds}, {60, &ppc_fnmsubs}, {62, &ppc_fnmadds},
|
||||
{114, &ppc_fmults}, {120, &ppc_fmsubs}, {122, &ppc_fmadds}, {124, &ppc_fnmsubs}, {126, &ppc_fnmadds},
|
||||
{178, &ppc_fmults}, {184, &ppc_fmsubs}, {186, &ppc_fmadds}, {188, &ppc_fnmsubs}, {190, &ppc_fnmadds},
|
||||
{242, &ppc_fmults}, {248, &ppc_fmsubs}, {250, &ppc_fmadds}, {252, &ppc_fnmsubs}, {254, &ppc_fnmadds},
|
||||
{306, &ppc_fmults}, {312, &ppc_fmsubs}, {314, &ppc_fmadds}, {316, &ppc_fnmsubs}, {318, &ppc_fnmadds},
|
||||
{370, &ppc_fmults}, {376, &ppc_fmsubs}, {378, &ppc_fmadds}, {380, &ppc_fnmsubs}, {382, &ppc_fnmadds},
|
||||
{434, &ppc_fmults}, {440, &ppc_fmsubs}, {442, &ppc_fmadds}, {444, &ppc_fnmsubs}, {446, &ppc_fnmadds},
|
||||
{498, &ppc_fmults}, {504, &ppc_fmsubs}, {506, &ppc_fmadds}, {508, &ppc_fnmsubs}, {510, &ppc_fnmadds},
|
||||
{562, &ppc_fmults}, {568, &ppc_fmsubs}, {570, &ppc_fmadds}, {572, &ppc_fnmsubs}, {574, &ppc_fnmadds},
|
||||
{626, &ppc_fmults}, {632, &ppc_fmsubs}, {634, &ppc_fmadds}, {636, &ppc_fnmsubs}, {638, &ppc_fnmadds},
|
||||
{690, &ppc_fmults}, {696, &ppc_fmsubs}, {698, &ppc_fmadds}, {700, &ppc_fnmsubs}, {702, &ppc_fnmadds},
|
||||
{754, &ppc_fmults}, {752, &ppc_fmsubs}, {754, &ppc_fmadds}, {764, &ppc_fnmsubs}, {766, &ppc_fnmadds},
|
||||
{818, &ppc_fmults}, {824, &ppc_fmsubs}, {826, &ppc_fmadds}, {828, &ppc_fnmsubs}, {830, &ppc_fnmadds},
|
||||
{882, &ppc_fmults}, {888, &ppc_fmsubs}, {890, &ppc_fmadds}, {892, &ppc_fnmsubs}, {894, &ppc_fnmadds},
|
||||
{946, &ppc_fmults}, {952, &ppc_fmsubs}, {954, &ppc_fmadds}, {956, &ppc_fnmsubs}, {958, &ppc_fnmadds},
|
||||
{1010, &ppc_fmults}, {1016, &ppc_fmsubs}, {1018, &ppc_fmadds}, {1020, &ppc_fnmsubs}, {1022, &ppc_fnmadds},
|
||||
{1074, &ppc_fmults}, {1080, &ppc_fmsubs}, {1082, &ppc_fmadds}, {1084, &ppc_fnmsubs}, {1086, &ppc_fnmadds},
|
||||
{1138, &ppc_fmults}, {1144, &ppc_fmsubs}, {1146, &ppc_fmadds}, {1148, &ppc_fnmsubs}, {1150, &ppc_fnmadds},
|
||||
{1202, &ppc_fmults}, {1208, &ppc_fmsubs}, {1210, &ppc_fmadds}, {1212, &ppc_fnmsubs}, {1214, &ppc_fnmadds},
|
||||
{1266, &ppc_fmults}, {1272, &ppc_fmsubs}, {1274, &ppc_fmadds}, {1276, &ppc_fnmsubs}, {1278, &ppc_fnmadds},
|
||||
{1330, &ppc_fmults}, {1336, &ppc_fmsubs}, {1338, &ppc_fmadds}, {1340, &ppc_fnmsubs}, {1342, &ppc_fnmadds},
|
||||
{1394, &ppc_fmults}, {1400, &ppc_fmsubs}, {1402, &ppc_fmadds}, {1404, &ppc_fnmsubs}, {1406, &ppc_fnmadds},
|
||||
{1458, &ppc_fmults}, {1464, &ppc_fmsubs}, {1466, &ppc_fmadds}, {1468, &ppc_fnmsubs}, {1470, &ppc_fnmadds},
|
||||
{1522, &ppc_fmults}, {1528, &ppc_fmsubs}, {1530, &ppc_fmadds}, {1532, &ppc_fnmsubs}, {1534, &ppc_fnmadds},
|
||||
{1586, &ppc_fmults}, {1592, &ppc_fmsubs}, {1594, &ppc_fmadds}, {1596, &ppc_fnmsubs}, {1598, &ppc_fnmadds},
|
||||
{1650, &ppc_fmults}, {1656, &ppc_fmsubs}, {1658, &ppc_fmadds}, {1660, &ppc_fnmsubs}, {1662, &ppc_fnmadds},
|
||||
{1714, &ppc_fmults}, {1720, &ppc_fmsubs}, {1722, &ppc_fmadds}, {1724, &ppc_fnmsubs}, {1726, &ppc_fnmadds},
|
||||
{1778, &ppc_fmults}, {1784, &ppc_fmsubs}, {1786, &ppc_fmadds}, {1788, &ppc_fnmsubs}, {1790, &ppc_fnmadds},
|
||||
{1842, &ppc_fmults}, {1848, &ppc_fmsubs}, {1850, &ppc_fmadds}, {1852, &ppc_fnmsubs}, {1854, &ppc_fnmadds},
|
||||
{1906, &ppc_fmults}, {1912, &ppc_fmsubs}, {1914, &ppc_fmadds}, {1916, &ppc_fnmsubs}, {1918, &ppc_fnmadds},
|
||||
{1970, &ppc_fmults}, {1976, &ppc_fmsubs}, {1978, &ppc_fmadds}, {1980, &ppc_fnmsubs}, {1982, &ppc_fnmadds},
|
||||
{2034, &ppc_fmults}, {2040, &ppc_fmsubs}, {2042, &ppc_fmadds}, {2044, &ppc_fnmsubs}, {2046, &ppc_fnmadds}
|
||||
};
|
||||
static std::map<uint16_t, PPCOpcode> SubOpcode63Grabber=
|
||||
{{0, &ppc_fcmpu}, {24, &ppc_frsp}, {28, &ppc_fctiw}, {30, &ppc_fctiwz}, {36, &ppc_fdiv},
|
||||
{40, &ppc_fsub}, {42, &ppc_fadd}, {44, &ppc_fsqrt}, {50, &ppc_fmult},
|
||||
{52, &ppc_frsqrte}, {56, &ppc_fmsub}, {58, &ppc_fmadd}, {60, &ppc_fnmsub},
|
||||
{62, &ppc_fnmadd}, {64, &ppc_fcmpo}, {76, &ppc_mtfsb1}, {77, &ppc_mtfsb1dot}, {80, &ppc_fneg},
|
||||
{114, &ppc_fmult}, {120, &ppc_fmsub}, {122, &ppc_fmadd}, {124, &ppc_fnmsub}, {126, &ppc_fnmadd},
|
||||
{128, &ppc_mcrfs}, {140, &ppc_mtfsb0}, {141, &ppc_mtfsb0dot},{144, &ppc_fmr},
|
||||
{178, &ppc_fmult}, {184, &ppc_fmsub}, {186, &ppc_fmadd}, {188, &ppc_fnmsub}, {190, &ppc_fnmadd},
|
||||
{242, &ppc_fmult}, {248, &ppc_fmsub}, {250, &ppc_fmadd}, {252, &ppc_fnmsub}, {254, &ppc_fnmadd},
|
||||
{306, &ppc_fmult}, {312, &ppc_fmsub}, {314, &ppc_fmadd}, {316, &ppc_fnmsub}, {318, &ppc_fnmadd},
|
||||
{370, &ppc_fmult}, {376, &ppc_fmsub}, {378, &ppc_fmadd}, {380, &ppc_fnmsub}, {382, &ppc_fnmadd},
|
||||
{434, &ppc_fmult}, {440, &ppc_fmsub}, {442, &ppc_fmadd}, {444, &ppc_fnmsub}, {446, &ppc_fnmadd},
|
||||
{498, &ppc_fmult}, {504, &ppc_fmsub}, {506, &ppc_fmadd}, {508, &ppc_fnmsub}, {510, &ppc_fnmadd},
|
||||
{528, &ppc_fabs},
|
||||
{562, &ppc_fmult}, {568, &ppc_fmsub}, {570, &ppc_fmadd}, {572, &ppc_fnmsub}, {574, &ppc_fnmadd},
|
||||
{626, &ppc_fmult}, {632, &ppc_fmsub}, {634, &ppc_fmadd}, {636, &ppc_fnmsub}, {638, &ppc_fnmadd},
|
||||
{690, &ppc_fmult}, {696, &ppc_fmsub}, {698, &ppc_fmadd}, {700, &ppc_fnmsub}, {702, &ppc_fnmadd},
|
||||
{754, &ppc_fmult}, {752, &ppc_fmsub}, {754, &ppc_fmadd}, {764, &ppc_fnmsub}, {766, &ppc_fnmadd},
|
||||
{818, &ppc_fmult}, {824, &ppc_fmsub}, {826, &ppc_fmadd}, {828, &ppc_fnmsub}, {830, &ppc_fnmadd},
|
||||
{882, &ppc_fmult}, {888, &ppc_fmsub}, {890, &ppc_fmadd}, {892, &ppc_fnmsub}, {894, &ppc_fnmadd},
|
||||
{946, &ppc_fmult}, {952, &ppc_fmsub}, {954, &ppc_fmadd}, {956, &ppc_fnmsub}, {958, &ppc_fnmadd},
|
||||
{1010, &ppc_fmult}, {1016, &ppc_fmsub}, {1018, &ppc_fmadd}, {1020, &ppc_fnmsub}, {1022, &ppc_fnmadd},
|
||||
{1074, &ppc_fmult}, {1080, &ppc_fmsub}, {1082, &ppc_fmadd}, {1084, &ppc_fnmsub}, {1086, &ppc_fnmadd},
|
||||
{1138, &ppc_fmult}, {1144, &ppc_fmsub}, {1146, &ppc_fmadd}, {1148, &ppc_fnmsub}, {1150, &ppc_fnmadd},
|
||||
{1166, &ppc_mffs},
|
||||
{1202, &ppc_fmult}, {1208, &ppc_fmsub}, {1210, &ppc_fmadd}, {1212, &ppc_fnmsub}, {1214, &ppc_fnmadd},
|
||||
{1266, &ppc_fmult}, {1272, &ppc_fmsub}, {1274, &ppc_fmadd}, {1276, &ppc_fnmsub}, {1278, &ppc_fnmadd},
|
||||
{1330, &ppc_fmult}, {1336, &ppc_fmsub}, {1338, &ppc_fmadd}, {1340, &ppc_fnmsub}, {1342, &ppc_fnmadd},
|
||||
{1394, &ppc_fmult}, {1400, &ppc_fmsub}, {1402, &ppc_fmadd}, {1404, &ppc_fnmsub}, {1406, &ppc_fnmadd},
|
||||
{1422, &ppc_mffs},
|
||||
{1458, &ppc_fmult}, {1464, &ppc_fmsub}, {1466, &ppc_fmadd}, {1468, &ppc_fnmsub}, {1470, &ppc_fnmadd},
|
||||
{1522, &ppc_fmult}, {1528, &ppc_fmsub}, {1530, &ppc_fmadd}, {1532, &ppc_fnmsub}, {1534, &ppc_fnmadd},
|
||||
{1586, &ppc_fmult}, {1592, &ppc_fmsub}, {1594, &ppc_fmadd}, {1596, &ppc_fnmsub}, {1598, &ppc_fnmadd},
|
||||
{1650, &ppc_fmult}, {1656, &ppc_fmsub}, {1658, &ppc_fmadd}, {1660, &ppc_fnmsub}, {1662, &ppc_fnmadd},
|
||||
{1714, &ppc_fmult}, {1720, &ppc_fmsub}, {1722, &ppc_fmadd}, {1724, &ppc_fnmsub}, {1726, &ppc_fnmadd},
|
||||
{1778, &ppc_fmult}, {1784, &ppc_fmsub}, {1786, &ppc_fmadd}, {1788, &ppc_fnmsub}, {1790, &ppc_fnmadd},
|
||||
{1842, &ppc_fmult}, {1848, &ppc_fmsub}, {1850, &ppc_fmadd}, {1852, &ppc_fnmsub}, {1854, &ppc_fnmadd},
|
||||
{1906, &ppc_fmult}, {1912, &ppc_fmsub}, {1914, &ppc_fmadd}, {1916, &ppc_fnmsub}, {1918, &ppc_fnmadd},
|
||||
{1970, &ppc_fmult}, {1976, &ppc_fmsub}, {1978, &ppc_fmadd}, {1980, &ppc_fnmsub}, {1982, &ppc_fnmadd},
|
||||
{2034, &ppc_fmult}, {2040, &ppc_fmsub}, {2042, &ppc_fmadd}, {2044, &ppc_fnmsub}, {2046, &ppc_fnmadd}
|
||||
};
|
||||
|
||||
|
||||
#endif // PPCEMUMAIN_H
|
679
ppcfpopcodes.cpp
Normal file
679
ppcfpopcodes.cpp
Normal file
@ -0,0 +1,679 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
// The opcodes for the processor - ppcopcodes.cpp
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <cinttypes>
|
||||
#include <array>
|
||||
#include <stdio.h>
|
||||
#include <stdexcept>
|
||||
#include "ppcemumain.h"
|
||||
#include "ppcmemory.h"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
//Used for FP calcs
|
||||
uint64_t ppc_result64_a;
|
||||
uint64_t ppc_result64_b;
|
||||
uint64_t ppc_result64_c;
|
||||
uint64_t ppc_result64_d;
|
||||
|
||||
double snan = std::numeric_limits<double>::signaling_NaN();
|
||||
double qnan = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
//Storage and register retrieval functions for the floating point functions.
|
||||
|
||||
void ppc_store_sfpresult(){
|
||||
ppc_state.ppc_fpr[reg_d] = (uint64_t)ppc_result_d;
|
||||
}
|
||||
|
||||
void ppc_store_dfpresult(){
|
||||
ppc_state.ppc_fpr[reg_d] = ppc_result64_d;
|
||||
}
|
||||
|
||||
void ppc_grab_regsfpdb(){
|
||||
reg_d = (ppc_cur_instruction >> 21) & 31;
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
ppc_result64_b = ppc_state.ppc_fpr[reg_b];
|
||||
}
|
||||
|
||||
void ppc_grab_regsfpdiab(){
|
||||
reg_d = (ppc_cur_instruction >> 21) & 31;
|
||||
reg_a = (ppc_cur_instruction >> 16) & 31;
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
||||
ppc_result_b = ppc_state.ppc_gpr[reg_b];
|
||||
}
|
||||
|
||||
void ppc_grab_regsfpdia(){
|
||||
reg_d = (ppc_cur_instruction >> 21) & 31;
|
||||
reg_a = (ppc_cur_instruction >> 16) & 31;
|
||||
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
||||
}
|
||||
|
||||
void ppc_grab_regsfpsia(){
|
||||
reg_s = (ppc_cur_instruction >> 21) & 31;
|
||||
reg_a = (ppc_cur_instruction >> 16) & 31;
|
||||
ppc_result_d = ppc_state.ppc_gpr[reg_s];
|
||||
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
||||
}
|
||||
|
||||
void ppc_grab_regsfpsiab(){
|
||||
reg_s = (ppc_cur_instruction >> 21) & 31;
|
||||
reg_a = (ppc_cur_instruction >> 16) & 31;
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
ppc_result64_d = ppc_state.ppc_fpr[reg_s];
|
||||
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
||||
ppc_result_b = ppc_state.ppc_gpr[reg_b];
|
||||
}
|
||||
|
||||
void ppc_grab_regsfpsab(){
|
||||
reg_s = (ppc_cur_instruction >> 21) & 31;
|
||||
reg_a = (ppc_cur_instruction >> 16) & 31;
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
ppc_result64_d = ppc_state.ppc_fpr[reg_s];
|
||||
ppc_result64_a = ppc_state.ppc_fpr[reg_a];
|
||||
ppc_result64_b = ppc_state.ppc_fpr[reg_b];
|
||||
}
|
||||
|
||||
void ppc_grab_regsfpdab(){
|
||||
reg_d = (ppc_cur_instruction >> 21) & 31;
|
||||
reg_a = (ppc_cur_instruction >> 16) & 31;
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
ppc_result64_a = ppc_state.ppc_fpr[reg_a];
|
||||
ppc_result64_b = ppc_state.ppc_fpr[reg_b];
|
||||
}
|
||||
|
||||
void ppc_grab_regsfpdac(){
|
||||
reg_d = (ppc_cur_instruction >> 21) & 31;
|
||||
reg_a = (ppc_cur_instruction >> 16) & 31;
|
||||
reg_c = (ppc_cur_instruction >> 6) & 31;
|
||||
ppc_result64_a = ppc_state.ppc_fpr[reg_a];
|
||||
ppc_result64_c = ppc_state.ppc_fpr[reg_c];
|
||||
}
|
||||
|
||||
void ppc_grab_regsfpdabc(){
|
||||
reg_d = (ppc_cur_instruction >> 21) & 31;
|
||||
reg_a = (ppc_cur_instruction >> 16) & 31;
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
reg_c = (ppc_cur_instruction >> 6) & 31;
|
||||
ppc_result64_a = ppc_state.ppc_fpr[reg_a];
|
||||
ppc_result64_b = ppc_state.ppc_fpr[reg_b];
|
||||
ppc_result64_c = ppc_state.ppc_fpr[reg_c];
|
||||
}
|
||||
|
||||
//Floating Point Arithmetic
|
||||
void ppc_fadd(){
|
||||
ppc_grab_regsfpdab();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
|
||||
double testd3 = testd1 + testd2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testd3;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fsub(){
|
||||
ppc_grab_regsfpdab();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
|
||||
double testd3 = testd1 - testd2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testd3;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fmult(){
|
||||
ppc_grab_regsfpdac();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
double testd2 = (double)ppc_result64_c;
|
||||
|
||||
double testd3 = testd1 * testd2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testd3;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fdiv(){
|
||||
ppc_grab_regsfpdab();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
|
||||
double testd3 = testd1 / testd2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testd3;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fmadd(){
|
||||
ppc_grab_regsfpdabc();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
double testd3 = (double)ppc_result64_c;
|
||||
|
||||
double testd4 = (testd1 * testd3) + testd2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testd4;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fmsub(){
|
||||
ppc_grab_regsfpdabc();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
double testd3 = (double)ppc_result64_c;
|
||||
|
||||
double testd4 = (testd1 * testd3) - testd2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testd4;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fnmadd(){
|
||||
ppc_grab_regsfpdabc();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
double testd3 = (double)ppc_result64_c;
|
||||
|
||||
double testd4 = -((testd1 * testd3) + testd2);
|
||||
|
||||
ppc_result64_d = (uint64_t)testd4;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fnmsub(){
|
||||
ppc_grab_regsfpdabc();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
double testd3 = (double)ppc_result64_c;
|
||||
|
||||
double testd4 = -((testd1 * testd3) - testd2);
|
||||
|
||||
ppc_result64_d = (uint64_t)testd4;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fadds(){
|
||||
ppc_grab_regsfpdab();
|
||||
float testd1 = (float)ppc_result64_a;
|
||||
float testd2 = (float)ppc_result64_b;
|
||||
|
||||
float testd3 = testd1 + testd2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testd3;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fsubs(){
|
||||
ppc_grab_regsfpdab();
|
||||
float testd1 = (float)ppc_result64_a;
|
||||
float testd2 = (float)ppc_result64_b;
|
||||
|
||||
float testd3 = testd1 - testd2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testd3;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fmults(){
|
||||
ppc_grab_regsfpdac();
|
||||
float testf1 = (float)ppc_result64_a;
|
||||
float testf2 = (float)ppc_result64_c;
|
||||
|
||||
float testf3 = testf1 * testf2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testf3;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fdivs(){
|
||||
ppc_grab_regsfpdab();
|
||||
float testf1 = (float)ppc_result64_a;
|
||||
float testf2 = (float)ppc_result64_b;
|
||||
|
||||
float testf3 = testf1 / testf2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testf3;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
|
||||
void ppc_fmadds(){
|
||||
ppc_grab_regsfpdabc();
|
||||
float testf1 = (float)ppc_result64_a;
|
||||
float testf2 = (float)ppc_result64_b;
|
||||
float testf3 = (float)ppc_result64_c;
|
||||
|
||||
float testf4 = (testf1 * testf3) + testf2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testf4;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fmsubs(){
|
||||
ppc_grab_regsfpdabc();
|
||||
float testf1 = (float)ppc_result64_a;
|
||||
float testf2 = (float)ppc_result64_b;
|
||||
float testf3 = (float)ppc_result64_c;
|
||||
|
||||
float testf4 = (testf1 * testf3) - testf2;
|
||||
|
||||
ppc_result64_d = (uint64_t)testf4;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fnmadds(){
|
||||
ppc_grab_regsfpdabc();
|
||||
float testf1 = (float)ppc_result64_a;
|
||||
float testf2 = (float)ppc_result64_b;
|
||||
float testf3 = (float)ppc_result64_c;
|
||||
|
||||
float testf4 = -((testf1 * testf3) + testf2);
|
||||
|
||||
ppc_result64_d = (uint64_t)testf4;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fnmsubs(){
|
||||
ppc_grab_regsfpdabc();
|
||||
float testf1 = (float)ppc_result64_a;
|
||||
float testf2 = (float)ppc_result64_b;
|
||||
float testf3 = (float)ppc_result64_c;
|
||||
|
||||
float testf4 = -((testf1 * testf3) - testf2);
|
||||
|
||||
ppc_result64_d = (uint64_t)testf4;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fabs(){
|
||||
ppc_grab_regsfpdb();
|
||||
double testd1 = (double)ppc_result64_b;
|
||||
|
||||
ppc_result64_d = (uint64_t)(abs(testd1));
|
||||
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fneg(){
|
||||
ppc_grab_regsfpdb();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
|
||||
double testd3 = -testd1;
|
||||
|
||||
ppc_result64_d = (double)testd3;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fsel(){
|
||||
ppc_grab_regsfpdabc();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
double testd3 = (double)ppc_result64_c;
|
||||
|
||||
if (testd1 >= 0.0){
|
||||
ppc_result64_d = (uint64_t)testd3;
|
||||
}
|
||||
else{
|
||||
ppc_result64_d = (uint64_t)testd2;
|
||||
}
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fsqrt(){
|
||||
ppc_grab_regsfpdb();
|
||||
double test = (double)ppc_result64_b;
|
||||
std::sqrt(test);
|
||||
ppc_result64_d = (uint64_t)test;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fsqrts(){
|
||||
ppc_grab_regsfpdb();
|
||||
uint32_t test = (uint32_t)ppc_result64_b;
|
||||
test += 127 << 23;
|
||||
test >>= 1;
|
||||
ppc_result64_d = (uint64_t)test;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_frsqrte(){
|
||||
ppc_grab_regsfpdb();
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
for (int i = 0; i < 10; i++){
|
||||
testd2 = testd2 * (1.5 - (testd2 * .5) * testd2 * testd2);
|
||||
}
|
||||
ppc_result64_d = (uint64_t) testd2;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_frsp(){
|
||||
ppc_grab_regsfpdb();
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
float testf2 = (float) testd2;
|
||||
ppc_result64_d = (uint64_t) testf2;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fres(){
|
||||
ppc_grab_regsfpdb();
|
||||
float testf2 = (float)ppc_result64_b;
|
||||
testf2 = 1/testf2;
|
||||
ppc_result64_d = (uint64_t) testf2;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_fctiw(){
|
||||
//PLACEHOLDER!
|
||||
ppc_grab_regsfpdiab();
|
||||
double testd1 = (double)ppc_result64_b;
|
||||
|
||||
ppc_result_d = (uint32_t)(testd1);
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void ppc_fctiwz(){
|
||||
//PLACEHOLDER!
|
||||
ppc_grab_regsfpdiab();
|
||||
double testd1 = (double)ppc_result64_a;
|
||||
|
||||
ppc_result_d = (uint32_t)(testd1);
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
//Floating Point Store and Load
|
||||
|
||||
void ppc_lfs(){
|
||||
ppc_grab_regsfpdia();
|
||||
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
|
||||
ppc_result64_d = (uint64_t)return_value;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
|
||||
void ppc_lfsu(){
|
||||
ppc_grab_regsfpdia();
|
||||
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
|
||||
ppc_result64_d = (uint64_t)return_value;
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_dfpresult();
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void ppc_lfsx(){
|
||||
ppc_grab_regsfpdiab();
|
||||
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
|
||||
ppc_result64_d = (uint64_t)return_value;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
|
||||
void ppc_lfsux(){
|
||||
ppc_grab_regsfpdiab();
|
||||
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
|
||||
ppc_result64_d = (uint64_t)return_value;
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_dfpresult();
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void ppc_lfd(){
|
||||
ppc_grab_regsfpdia();
|
||||
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
|
||||
uint64_t combine_result1 = (uint64_t)(return_value);
|
||||
address_quickgrab_translate((ppc_effective_address + 4), ppc_state.ppc_fpr[reg_d], 4);
|
||||
uint64_t combine_result2 = (uint64_t)(return_value);
|
||||
ppc_result64_d = (combine_result1 << 32) | combine_result2;
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
|
||||
void ppc_lfdu(){
|
||||
ppc_grab_regsfpdia();
|
||||
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
|
||||
address_quickgrab_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_d], 4);
|
||||
uint64_t combine_result1 = (uint64_t)(return_value);
|
||||
address_quickgrab_translate((ppc_effective_address + 4), ppc_state.ppc_fpr[reg_d], 4);
|
||||
uint64_t combine_result2 = (uint64_t)(return_value);
|
||||
ppc_result64_d = (combine_result1 << 32) | combine_result2;
|
||||
ppc_store_dfpresult();
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
|
||||
void ppc_stfs(){
|
||||
ppc_grab_regsfpsia();
|
||||
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
|
||||
address_quickinsert_translate(ppc_effective_address, ppc_state.ppc_fpr[reg_s], 4);
|
||||
}
|
||||
|
||||
void ppc_stfsu(){
|
||||
ppc_grab_regsfpsia();
|
||||
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
|
||||
uint32_t split_result1 = (uint32_t)((float)(ppc_state.ppc_fpr[reg_s]));
|
||||
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void ppc_stfsux(){
|
||||
ppc_grab_regsfpsiab();
|
||||
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
|
||||
uint32_t split_result1 = (uint32_t)((float)(ppc_state.ppc_fpr[reg_s]));
|
||||
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void ppc_stfd(){
|
||||
ppc_grab_regsfpsia();
|
||||
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
|
||||
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] >> 32);
|
||||
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
|
||||
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s]);
|
||||
address_quickinsert_translate(ppc_effective_address, split_result2, 4);
|
||||
}
|
||||
|
||||
void ppc_stfdu(){
|
||||
ppc_grab_regsfpsia();
|
||||
grab_d = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address = (reg_a == 0)?grab_d:ppc_result_a + grab_d;
|
||||
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] >> 32);
|
||||
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
|
||||
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s]);
|
||||
address_quickinsert_translate(ppc_effective_address, split_result2, 4);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void ppc_stfdx(){
|
||||
ppc_grab_regsfpsiab();
|
||||
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
|
||||
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] >> 32);
|
||||
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
|
||||
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s]);
|
||||
address_quickinsert_translate(ppc_effective_address, split_result2, 4);
|
||||
}
|
||||
|
||||
void ppc_stfdux(){
|
||||
ppc_grab_regsfpsiab();
|
||||
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
|
||||
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] >> 32);
|
||||
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
|
||||
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s]);
|
||||
address_quickinsert_translate(ppc_effective_address, split_result2, 4);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void ppc_stfiwx(){
|
||||
ppc_grab_regsfpsiab();
|
||||
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
|
||||
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s] & 0xFFFFFFFF);
|
||||
address_quickinsert_translate(ppc_effective_address, split_result1, 4);
|
||||
}
|
||||
//Floating Point Register Transfer
|
||||
|
||||
void ppc_fmr(){
|
||||
ppc_grab_regsfpdb();
|
||||
ppc_state.ppc_fpr[reg_d] = ppc_state.ppc_fpr[reg_b];
|
||||
ppc_store_dfpresult();
|
||||
}
|
||||
|
||||
void ppc_mffs(){
|
||||
ppc_grab_regsda();
|
||||
uint64_t fpstore1 = ppc_state.ppc_fpr[reg_d] & 0xFFFFFFFF00000000;
|
||||
uint64_t fpstore2 = ppc_state.ppc_fpscr & 0x00000000FFFFFFFF;
|
||||
fpstore1 |= fpstore2;
|
||||
ppc_state.ppc_fpr[reg_d] = fpstore1;
|
||||
ppc_store_sfpresult();
|
||||
}
|
||||
|
||||
void ppc_mtfsf(){
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
uint32_t fm_mask = (ppc_cur_instruction >> 17) & 255;
|
||||
crm += ((fm_mask & 1) == 1)? 0xF0000000 : 0x00000000;
|
||||
crm += ((fm_mask & 2) == 1)? 0x0F000000 : 0x00000000;
|
||||
crm += ((fm_mask & 4) == 1)? 0x00F00000 : 0x00000000;
|
||||
crm += ((fm_mask & 8) == 1)? 0x000F0000 : 0x00000000;
|
||||
crm += ((fm_mask & 16) == 1)? 0x0000F000 : 0x00000000;
|
||||
crm += ((fm_mask & 32) == 1)? 0x00000F00 : 0x00000000;
|
||||
crm += ((fm_mask & 64) == 1)? 0x000000F0 : 0x00000000;
|
||||
crm += ((fm_mask & 128) == 1)? 0x0000000F : 0x00000000;
|
||||
uint32_t quickfprval = (uint32_t)ppc_state.ppc_fpr[reg_b];
|
||||
ppc_state.ppc_fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
|
||||
}
|
||||
|
||||
void ppc_mtfsb0(){
|
||||
crf_d = (ppc_cur_instruction >> 21) & 0x31;
|
||||
if ((crf_d == 0) || (crf_d > 2)){
|
||||
ppc_state.ppc_fpscr &= ~(1 << (31 - crf_d));
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_mtfsb0dot(){
|
||||
//PLACEHOLDER
|
||||
crf_d = (ppc_cur_instruction >> 21) & 0x31;
|
||||
if ((crf_d == 0) || (crf_d > 2)){
|
||||
ppc_state.ppc_fpscr &= ~(1 << crf_d);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_mtfsb1(){
|
||||
crf_d = (ppc_cur_instruction >> 21) & 0x31;
|
||||
if ((crf_d == 0) || (crf_d > 2)){
|
||||
ppc_state.ppc_fpscr |= (1 << crf_d);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_mtfsb1dot(){
|
||||
//PLACEHOLDER
|
||||
crf_d = ~(ppc_cur_instruction >> 21) & 0x31;
|
||||
if ((crf_d == 0) || (crf_d > 2)){
|
||||
ppc_state.ppc_fpscr |= (1 << crf_d);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ppc_mcrfs(){
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
crf_d = crf_d << 2;
|
||||
crf_s = (ppc_cur_instruction >> 18) & 7;
|
||||
crf_s = crf_d << 2;
|
||||
ppc_state.ppc_cr = ~(ppc_state.ppc_cr & ((15 << (28- crf_d)))) & (ppc_state.ppc_fpscr & (15 << (28- crf_s)));
|
||||
}
|
||||
|
||||
//Floating Point Comparisons
|
||||
|
||||
void ppc_fcmpo(){
|
||||
ppc_grab_regsfpsab();
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
crf_d = crf_d << 2;
|
||||
|
||||
double db_test_a = (double)ppc_result64_a;
|
||||
double db_test_b = (double)ppc_result64_b;
|
||||
|
||||
ppc_state.ppc_fpscr &= 0xFFFF0FFF;
|
||||
|
||||
if (std::isnan(db_test_a) || std::isnan(db_test_b)){
|
||||
cmp_c |= 0x01;
|
||||
}
|
||||
else if (db_test_a < db_test_b){
|
||||
cmp_c |= 0x08;
|
||||
}
|
||||
else if (db_test_a > db_test_b){
|
||||
cmp_c |= 0x04;
|
||||
}
|
||||
else{
|
||||
cmp_c |= 0x02;
|
||||
}
|
||||
|
||||
ppc_state.ppc_fpscr |= (cmp_c << 12);
|
||||
ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
|
||||
|
||||
if ((db_test_a == snan) || (db_test_b == snan)){
|
||||
ppc_state.ppc_fpscr |= 0x1000000;
|
||||
if (ppc_state.ppc_fpscr && 0x80){
|
||||
ppc_state.ppc_fpscr |= 0x80000;
|
||||
}
|
||||
}
|
||||
else if ((db_test_a == qnan) || (db_test_b == qnan)){
|
||||
ppc_state.ppc_fpscr |= 0x80000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ppc_fcmpu(){
|
||||
ppc_grab_regsfpsab();
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
crf_d = crf_d << 2;
|
||||
|
||||
double db_test_a = (double)ppc_result64_a;
|
||||
double db_test_b = (double)ppc_result64_b;
|
||||
|
||||
ppc_state.ppc_fpscr &= 0xFFFF0FFF;
|
||||
|
||||
if (std::isnan(db_test_a) || std::isnan(db_test_b)){
|
||||
cmp_c |= 0x01;
|
||||
}
|
||||
else if (db_test_a < db_test_b){
|
||||
cmp_c |= 0x08;
|
||||
}
|
||||
else if (db_test_a > db_test_b){
|
||||
cmp_c |= 0x04;
|
||||
}
|
||||
else{
|
||||
cmp_c |= 0x02;
|
||||
}
|
||||
|
||||
ppc_state.ppc_fpscr |= (cmp_c << 12);
|
||||
ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
|
||||
|
||||
if ((db_test_a == snan) || (db_test_b == snan)){
|
||||
ppc_state.ppc_fpscr |= 0x1000000;
|
||||
}
|
||||
}
|
32
ppcgekkoopcodes.cpp
Normal file
32
ppcgekkoopcodes.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
// The uniquely Gekko opcodes for the processor - ppcgekkoopcodes.cpp
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include "ppcemumain.h"
|
||||
|
||||
void ppc_psq_l(){
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ppc_psq_lu(){
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ppc_psq_st(){
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ppc_psq_stu(){
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
991
ppcmemory.cpp
Normal file
991
ppcmemory.cpp
Normal file
@ -0,0 +1,991 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
// The memory operations - ppcmemory.cpp
|
||||
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <cinttypes>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include "viacuda.h"
|
||||
#include "macioserial.h"
|
||||
#include "macswim3.h"
|
||||
#include "ppcemumain.h"
|
||||
#include "ppcmemory.h"
|
||||
#include "openpic.h"
|
||||
#include "mpc106.h"
|
||||
|
||||
std::vector<uint32_t> pte_storage;
|
||||
uint64_t ppc_virtual_address; //It's 52 bits, but 64 bits more than covers the range needed.
|
||||
|
||||
uint32_t bat_srch;
|
||||
uint32_t bepi_chk;
|
||||
|
||||
uint32_t pte_word1;
|
||||
uint32_t pte_word2;
|
||||
|
||||
uint32_t msr_ir_test;
|
||||
uint32_t msr_dr_test;
|
||||
uint32_t msr_ip_test;
|
||||
|
||||
uint32_t choose_sr;
|
||||
uint32_t pteg_hash1;
|
||||
uint32_t pteg_hash2;
|
||||
uint32_t pteg_answer;
|
||||
|
||||
uint32_t pteg_address1;
|
||||
uint32_t pteg_temp1;
|
||||
uint32_t pteg_address2;
|
||||
uint32_t pteg_temp2;
|
||||
|
||||
uint32_t pteg_check1;
|
||||
uint32_t rev_pteg_check1;
|
||||
uint32_t pteg_check2;
|
||||
uint32_t rev_pteg_check2;
|
||||
|
||||
unsigned char * grab_tempmem_ptr1;
|
||||
unsigned char * grab_tempmem_ptr2;
|
||||
unsigned char * grab_tempmem_ptr3;
|
||||
unsigned char * grab_tempmem_ptr4;
|
||||
|
||||
unsigned char * grab_macmem_ptr;
|
||||
unsigned char * grab_pteg1_ptr;
|
||||
unsigned char * grab_pteg2_ptr;
|
||||
|
||||
std::atomic<bool> hash_found (false);
|
||||
|
||||
uint32_t dbat_array_map [4][3]={
|
||||
//flg ea begin ea end
|
||||
{0x00,0x00000000,0x00000000},
|
||||
{0x00,0x00000000,0x00000000},
|
||||
{0x00,0x00000000,0x00000000},
|
||||
{0x00,0x00000000,0x00000000}
|
||||
};
|
||||
|
||||
uint32_t ibat_array_map [4][3]={
|
||||
//flg ea begin ea end
|
||||
{0x00,0x00000000,0x00000000},
|
||||
{0x00,0x00000000,0x00000000},
|
||||
{0x00,0x00000000,0x00000000},
|
||||
{0x00,0x00000000,0x00000000}
|
||||
};
|
||||
|
||||
/**
|
||||
Quickly map to memory - sort of.
|
||||
|
||||
0x00000000 - 0x7FFFFFFF - Macintosh system memory
|
||||
(Because this emulator is trying to emulate a Mac with a Grackle motherboard,
|
||||
the most memory that can ever be allocated to the system is 2 Gigs.)
|
||||
|
||||
0x80000000 - 0xFF7FFFFF - PCI memory
|
||||
This memory is allocated to things like the memory controller, video, and audio.
|
||||
|
||||
0xF3000000 - Mac OS I/O Device area
|
||||
0xF3013000 - Serial Printer Port (0x20 bytes)
|
||||
0xF3013020 - Serial Modem Port (0x20 bytes)
|
||||
0xF3011000 - BMAC Ethernet (0x1000 bytes)
|
||||
0xF3014000 - DAVAudio Sound Bus (0x1000 bytes)
|
||||
0xF3015000 - Swim 3 Floppy Disk Drive (0x1000 bytes)
|
||||
0xF3016000 - Cuda (0x2000 bytes)
|
||||
0xF3020000 - Heathrow ATA (Hard Drive Interface)
|
||||
|
||||
0xFF800000 - 0xFFFFFFFF - ROM memory
|
||||
This memory is for storing the ROM needed to boot up the computer.
|
||||
|
||||
This could definitely be refactored better - TODO
|
||||
**/
|
||||
|
||||
void msr_status_update(){
|
||||
msr_ip_test = (ppc_state.ppc_msr >> 6) & 1;
|
||||
msr_ir_test = (ppc_state.ppc_msr >> 5) & 1;
|
||||
msr_dr_test = (ppc_state.ppc_msr >> 4) & 1;
|
||||
}
|
||||
|
||||
void ibat_update(){
|
||||
uint8_t tlb_place = 0;
|
||||
uint32_t ref_area = 0;
|
||||
bool msr_pr = ppc_state.ppc_msr && 4000; //This is for problem mode; make sure that supervisor mode does not touch this!
|
||||
for (int bat_srch = 528; bat_srch < 535; bat_srch += 2){
|
||||
ref_area = ((ppc_state.ppc_spr[bat_srch] & 0x1FFC) > 0) ? ((ppc_state.ppc_spr[bat_srch] & 0x1FFC) << 16): 131072;
|
||||
bepi_chk|= (ppc_effective_address & 0xFFFE0000) & ~ref_area;
|
||||
bool supervisor_on = (ppc_state.ppc_spr[bat_srch] & 0x00000002);
|
||||
bool problem_on = (ppc_state.ppc_spr[bat_srch] & 0x00000001);
|
||||
if (((ppc_state.ppc_spr[bat_srch] & 0xFFFE0000) == bepi_chk) &&
|
||||
((problem_on && msr_pr) || (supervisor_on && !msr_pr))){
|
||||
//Set write/read flags, beginning of transfer area, and end of transfer area
|
||||
ibat_array_map[tlb_place][0] = (ppc_state.ppc_spr[bat_srch] & 0x3);
|
||||
ibat_array_map[tlb_place][1] = (ppc_state.ppc_spr[bat_srch] & 0xFFFE0000);
|
||||
ibat_array_map[tlb_place][2] = ((ppc_state.ppc_spr[bat_srch] & 0xFFFE0000) + ref_area) - 1;
|
||||
break;
|
||||
}
|
||||
tlb_place++;
|
||||
}
|
||||
}
|
||||
|
||||
void dbat_update(){
|
||||
uint8_t tlb_place = 0;
|
||||
uint32_t ref_area = 0;
|
||||
bool msr_pr = ppc_state.ppc_msr && 4000; //This is for problem mode; make sure that supervisor mode does not touch this!
|
||||
for (int bat_srch = 536; bat_srch < 543; bat_srch += 2){
|
||||
ref_area = (ppc_state.ppc_spr[bat_srch] & 0x1FFC) > 0? ((ppc_state.ppc_spr[bat_srch] & 0x1FFC) << 16): 131072;
|
||||
bepi_chk|= (ppc_effective_address & 0xFFFE0000) & ~ref_area;
|
||||
bool supervisor_on = (ppc_state.ppc_spr[bat_srch] & 0x00000002);
|
||||
bool problem_on = (ppc_state.ppc_spr[bat_srch] & 0x00000001);
|
||||
if (((ppc_state.ppc_spr[bat_srch] & 0xFFFE0000) == bepi_chk) &&
|
||||
((problem_on && (msr_pr != 0)) || (supervisor_on && (msr_pr == 0)))){
|
||||
//Set write/read flags, beginning of transfer area, and end of transfer area
|
||||
dbat_array_map[tlb_place][0] = (ppc_state.ppc_spr[bat_srch] & 0x3);
|
||||
dbat_array_map[tlb_place][1] = (ppc_state.ppc_spr[bat_srch] & 0xFFFE0000);
|
||||
dbat_array_map[tlb_place][2] = ((ppc_state.ppc_spr[bat_srch] & 0xFFFE0000) + ref_area) - 1;
|
||||
break;
|
||||
}
|
||||
tlb_place++;
|
||||
}
|
||||
}
|
||||
|
||||
void get_pointer_pteg1(uint32_t address_grab){
|
||||
//Grab the array pointer for the PTEG
|
||||
if (address_grab < 0x80000000){
|
||||
pte_word1 = address_grab % ram_size_set;
|
||||
if (address_grab < 0x040000000){ //for debug purposes
|
||||
grab_pteg1_ptr = machine_sysram_mem;
|
||||
}
|
||||
else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){
|
||||
pte_word1 = address_grab % 0x2000;
|
||||
grab_pteg1_ptr = machine_sysconfig_mem;
|
||||
}
|
||||
else{
|
||||
printf("Uncharted territory: %x", address_grab);
|
||||
}
|
||||
}
|
||||
else if (address_grab < 0x80800000){
|
||||
pte_word1 = address_grab % 0x800000;
|
||||
grab_pteg1_ptr = machine_upperiocontrol_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0x81000000){
|
||||
pte_word1 = address_grab % 0x800000;
|
||||
grab_pteg1_ptr = machine_iocontrolcdma_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0xBF80000){
|
||||
pte_word1 = address_grab % 33554432;
|
||||
grab_pteg1_ptr = machine_loweriocontrol_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0xC0000000){
|
||||
pte_word1 = address_grab % 16;
|
||||
grab_pteg1_ptr = machine_interruptack_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0xF0000000){
|
||||
printf("Invalid Memory Attempt: %x \n", address_grab);
|
||||
return;
|
||||
}
|
||||
else if (address_grab < 0xF8000000){
|
||||
pte_word1 = address_grab % 67108864;
|
||||
grab_pteg1_ptr = machine_iocontrolmem_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < rom_file_begin){
|
||||
//Get back to this! (weeny1)
|
||||
if (address_grab < 0xFE000000){
|
||||
pte_word1 = address_grab % 4096;
|
||||
grab_pteg1_ptr = machine_f8xxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEC00000){
|
||||
pte_word1 = address_grab % 65536;
|
||||
grab_pteg1_ptr = machine_fexxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEE00000){
|
||||
pte_word1 = 0x0CF8; //CONFIG_ADDR
|
||||
grab_pteg1_ptr = machine_fecxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFF000000){
|
||||
pte_word1 = 0x0CFC; //CONFIG_DATA
|
||||
grab_pteg1_ptr = machine_feexxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFF800000){
|
||||
pte_word1 = address_grab % 4096;
|
||||
grab_pteg1_ptr = machine_ff00xx_mem;
|
||||
}
|
||||
else{
|
||||
pte_word1 = (address_grab % 1048576) + 0x400000;
|
||||
grab_pteg1_ptr = machine_sysram_mem;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pte_word1 = address_grab % rom_file_setsize;
|
||||
grab_pteg1_ptr = machine_sysrom_mem;
|
||||
}
|
||||
}
|
||||
|
||||
void get_pointer_pteg2(uint32_t address_grab){
|
||||
//Grab the array pointer for the PTEG
|
||||
if (address_grab < 0x80000000){
|
||||
pte_word2 = address_grab % ram_size_set;
|
||||
if (address_grab < 0x040000000){ //for debug purposes
|
||||
grab_pteg2_ptr = machine_sysram_mem;
|
||||
}
|
||||
else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){
|
||||
pte_word2 = address_grab % 0x2000;
|
||||
grab_pteg2_ptr = machine_sysconfig_mem;
|
||||
}
|
||||
else{
|
||||
printf("Uncharted territory: %x", address_grab);
|
||||
}
|
||||
}
|
||||
else if (address_grab < 0x80800000){
|
||||
pte_word2 = address_grab % 0x800000;
|
||||
grab_pteg2_ptr = machine_upperiocontrol_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0x81000000){
|
||||
pte_word2 = address_grab % 0x800000;
|
||||
grab_pteg2_ptr = machine_iocontrolcdma_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0xBF80000){
|
||||
pte_word2 = address_grab % 33554432;
|
||||
grab_pteg2_ptr = machine_loweriocontrol_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0xC0000000){
|
||||
pte_word2 = address_grab % 16;
|
||||
grab_pteg2_ptr = machine_interruptack_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0xF0000000){
|
||||
printf("Invalid Memory Attempt: %x \n", address_grab);
|
||||
return;
|
||||
}
|
||||
else if (address_grab < 0xF8000000){
|
||||
pte_word2 = address_grab % 67108864;
|
||||
grab_pteg2_ptr = machine_iocontrolmem_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < rom_file_begin){
|
||||
//Get back to this! (weeny1)
|
||||
if (address_grab < 0xFE000000){
|
||||
pte_word2 = address_grab % 4096;
|
||||
grab_pteg2_ptr = machine_f8xxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEC00000){
|
||||
pte_word2 = address_grab % 65536;
|
||||
grab_pteg2_ptr = machine_fexxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEE00000){
|
||||
pte_word2 = 0x0CF8; //CONFIG_ADDR
|
||||
grab_pteg2_ptr = machine_fecxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFF000000){
|
||||
pte_word2 = 0x0CFC; //CONFIG_DATA
|
||||
grab_pteg2_ptr = machine_feexxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFF800000){
|
||||
pte_word2 = address_grab % 4096;
|
||||
grab_pteg2_ptr = machine_ff00xx_mem;
|
||||
}
|
||||
else{
|
||||
pte_word2 = (address_grab % 1048576) + 0x400000;
|
||||
grab_pteg2_ptr = machine_sysram_mem;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pte_word2 = address_grab % rom_file_setsize;
|
||||
grab_pteg2_ptr = machine_sysrom_mem;
|
||||
}
|
||||
}
|
||||
|
||||
void primary_generate_pa(){
|
||||
pteg_address1 |= ppc_state.ppc_spr[25] & 0xFE000000;
|
||||
pteg_temp1 = (((ppc_state.ppc_spr[25] & 0x1FF) << 10) & (pteg_hash1 & 0x7FC00));
|
||||
pteg_address1 |= ((ppc_state.ppc_spr[25] & 0x1FF0000) | pteg_temp1);
|
||||
pteg_address1 |= (pteg_hash1 & 0x3FF) << 6;
|
||||
}
|
||||
|
||||
void secondary_generate_pa(){
|
||||
pteg_address2 |= ppc_state.ppc_spr[25] & 0xFE000000;
|
||||
pteg_temp2 = (((ppc_state.ppc_spr[25] & 0x1FF) << 10) & (pteg_hash2 & 0x7FC00));
|
||||
pteg_address2 |= ((ppc_state.ppc_spr[25] & 0x1FF0000) | pteg_temp2);
|
||||
pteg_address2 |= (pteg_hash2 & 0x3FF) << 6;
|
||||
}
|
||||
|
||||
void primary_hash_check(uint32_t vpid_known){
|
||||
|
||||
uint32_t entries_size = ((ppc_state.ppc_spr[25] & 0x1FF) > 0)? ((ppc_state.ppc_spr[25] & 0x1FF) << 9): 65536;
|
||||
uint32_t entries_area = pte_word1 + entries_size;
|
||||
|
||||
uint32_t check_vpid = 0;
|
||||
|
||||
do{
|
||||
if (!hash_found){
|
||||
check_vpid |= grab_pteg1_ptr[pte_word1++] << 24;
|
||||
check_vpid |= grab_pteg1_ptr[pte_word1++] << 16;
|
||||
check_vpid |= grab_pteg1_ptr[pte_word1++] << 8;
|
||||
check_vpid |= grab_pteg1_ptr[pte_word1++];
|
||||
|
||||
check_vpid = (check_vpid >> 7) & 0xFFFFFF;
|
||||
|
||||
if ((check_vpid >> 31) && 0x01){
|
||||
if (vpid_known == check_vpid){
|
||||
hash_found = true;
|
||||
pteg_answer |= grab_pteg1_ptr[pte_word1++] << 24;
|
||||
pteg_answer |= grab_pteg1_ptr[pte_word1++] << 16;
|
||||
pteg_answer |= grab_pteg1_ptr[pte_word1++] << 8;
|
||||
pteg_answer |= grab_pteg1_ptr[pte_word1++];
|
||||
break;
|
||||
}
|
||||
else{
|
||||
pte_word1 += 4;
|
||||
check_vpid = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pte_word1 += 4;
|
||||
check_vpid = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pte_word1 = entries_area;
|
||||
}
|
||||
|
||||
}while (pte_word1 < entries_area);
|
||||
}
|
||||
|
||||
void secondary_hash_check(uint32_t vpid_known){
|
||||
|
||||
uint32_t entries_size = ((ppc_state.ppc_spr[25] & 0x1FF) > 0)? ((ppc_state.ppc_spr[25] & 0x1FF) << 9): 65536;
|
||||
uint32_t entries_area = pte_word1 + entries_size;
|
||||
|
||||
uint32_t check_vpid = 0;
|
||||
|
||||
do{
|
||||
if (!hash_found){
|
||||
check_vpid |= grab_pteg2_ptr[pte_word2++] << 24;
|
||||
check_vpid |= grab_pteg2_ptr[pte_word2++] << 16;
|
||||
check_vpid |= grab_pteg2_ptr[pte_word2++] << 8;
|
||||
check_vpid |= grab_pteg2_ptr[pte_word2++];
|
||||
|
||||
check_vpid = (check_vpid >> 7) & 0xFFFFFF;
|
||||
|
||||
if ((check_vpid >> 31) && 0x01){
|
||||
if (vpid_known == check_vpid){
|
||||
hash_found = true;
|
||||
pteg_answer |= grab_pteg2_ptr[pte_word2++] << 24;
|
||||
pteg_answer |= grab_pteg2_ptr[pte_word2++] << 16;
|
||||
pteg_answer |= grab_pteg2_ptr[pte_word2++] << 8;
|
||||
pteg_answer |= grab_pteg2_ptr[pte_word2++];
|
||||
break;
|
||||
}
|
||||
else{
|
||||
pte_word2 += 4;
|
||||
check_vpid = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pte_word2 += 4;
|
||||
check_vpid = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
pte_word2 = entries_area;
|
||||
}
|
||||
|
||||
}while (pte_word2 < entries_area);
|
||||
}
|
||||
|
||||
void pteg_translate(uint32_t address_grab){
|
||||
uint32_t choose_sr = (ppc_effective_address >> 28) & 0x0F;
|
||||
pteg_hash1 = ppc_state.ppc_sr[choose_sr] & 0x7FFFF;
|
||||
uint32_t page_index = (ppc_effective_address & 0xFFFF000) >> 12;
|
||||
pteg_hash1 = (pteg_hash1 ^ page_index);
|
||||
pteg_hash2 = ~pteg_hash1;
|
||||
|
||||
std::thread primary_pa_check(&primary_generate_pa);
|
||||
std::thread secondary_pa_check(&secondary_generate_pa);
|
||||
|
||||
primary_pa_check.join();
|
||||
secondary_pa_check.join();
|
||||
|
||||
uint32_t grab_val = ppc_state.ppc_sr[choose_sr] & 0xFFFFFF;
|
||||
|
||||
std::thread primary_pteg_check(&primary_hash_check, std::ref(grab_val));
|
||||
std::thread secondary_pteg_check(&secondary_hash_check, std::ref(grab_val));
|
||||
|
||||
primary_pteg_check.join();
|
||||
secondary_pteg_check.join();
|
||||
}
|
||||
|
||||
void address_quickinsert_translate(uint32_t address_grab, uint32_t value_insert, uint8_t bit_num){
|
||||
//Insert a value into memory from a register
|
||||
|
||||
printf("Inserting into address %x with %x", address_grab, value_insert);
|
||||
|
||||
uint32_t storage_area = 0;
|
||||
uint32_t grab_batl = 537;
|
||||
uint32_t blocklen = 0;
|
||||
bool bat_to_go=0;
|
||||
bool pteg_to_go=0;
|
||||
|
||||
//data bat
|
||||
if ((ppc_state.ppc_msr >> 4) & 0x1){
|
||||
printf("DATA RELOCATION GO! - INSERTING \n");
|
||||
uint32_t min_val;
|
||||
uint32_t max_val;
|
||||
|
||||
pteg_to_go = 1;
|
||||
|
||||
for (uint32_t grab_loop = 0; grab_loop < 4; grab_loop++){
|
||||
if ((dbat_array_map[grab_loop][0] >> 1) && 0x1){
|
||||
min_val = dbat_array_map[grab_loop][1];
|
||||
max_val = dbat_array_map[grab_loop][2];
|
||||
if ((address_grab >= min_val) && (address_grab < max_val) && (max_val != 0)){
|
||||
blocklen = max_val - min_val;
|
||||
bat_to_go = 1;
|
||||
pteg_to_go = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
grab_batl += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (bat_to_go){
|
||||
uint32_t final_grab = 0;
|
||||
final_grab |= (((address_grab & 0x0FFE0000) & blocklen) | (ppc_state.ppc_spr[grab_batl] & 0xFFFE0000));
|
||||
final_grab |= (address_grab & 0x1FFFF);
|
||||
//Check the PP Tags in the batl
|
||||
//if (!(ppc_state.ppc_spr[grab_batl] == 0x2)){
|
||||
// ppc_expection_handler(0x0300, 0x0);
|
||||
// }
|
||||
address_grab = final_grab;
|
||||
}
|
||||
else if (pteg_to_go){
|
||||
pteg_translate(address_grab);
|
||||
if (hash_found == true){
|
||||
address_grab &= 0xFFF;
|
||||
address_grab |= (pteg_answer & 0xFFFFF000);
|
||||
}
|
||||
}
|
||||
|
||||
//regular grabbing
|
||||
if (address_grab < 0x80000000){
|
||||
if (address_grab > 0x03ffffff){ //for debug purposes
|
||||
storage_area = address_grab;
|
||||
grab_macmem_ptr = machine_sysram_mem;
|
||||
}
|
||||
else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){
|
||||
storage_area = address_grab % 0x2000;
|
||||
grab_macmem_ptr = machine_sysconfig_mem;
|
||||
}
|
||||
else{
|
||||
storage_area = address_grab % 0x04000000;
|
||||
grab_macmem_ptr = machine_sysram_mem;
|
||||
printf("Uncharted territory: %x \n", address_grab);
|
||||
}
|
||||
}
|
||||
else if (address_grab < 0x80800000){
|
||||
storage_area = address_grab % 0x800000;
|
||||
if (address_grab == 0x80000CF8){
|
||||
storage_area = 0x0CF8; //CONFIG_ADDR
|
||||
value_insert = rev_endian32(value_insert);
|
||||
grab_macmem_ptr = machine_fecxxx_mem;
|
||||
uint32_t reg_num = (value_insert & 0x07FC) >> 2;
|
||||
uint32_t dev_num = (value_insert & 0xF800) >> 11;
|
||||
printf("ADDRESS SET FOR GRACKLE \n");
|
||||
printf("Device Number: %d ", dev_num);
|
||||
printf("Register Number: %d \n", reg_num);
|
||||
mpc106_address = value_insert;
|
||||
}
|
||||
else{
|
||||
grab_macmem_ptr = machine_upperiocontrol_mem;
|
||||
}
|
||||
|
||||
|
||||
if ((address_grab >= 0x80040000) && (address_grab < 0x80080000)){
|
||||
openpic_address = address_grab - 0x80000000;
|
||||
openpic_read_word = value_insert;
|
||||
openpic_read();
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Uncharted territory: %x \n", address_grab);
|
||||
}
|
||||
else if (address_grab < 0x81000000){
|
||||
if (address_grab > 0x83FFFFFF){
|
||||
return;
|
||||
}
|
||||
storage_area = address_grab;
|
||||
printf("Uncharted territory: %x \n", address_grab);
|
||||
grab_macmem_ptr = machine_iocontrolcdma_mem;
|
||||
}
|
||||
else if (address_grab < 0xBF800000){
|
||||
storage_area = address_grab % 33554432;
|
||||
printf("Uncharted territory: %x \n", address_grab);
|
||||
grab_macmem_ptr = machine_loweriocontrol_mem;
|
||||
}
|
||||
else if (address_grab < 0xC0000000){
|
||||
storage_area = address_grab % 16;
|
||||
printf("Uncharted territory: %x \n", address_grab);
|
||||
grab_macmem_ptr = machine_interruptack_mem;
|
||||
}
|
||||
else if (address_grab < 0xF0000000){
|
||||
printf("Invalid Memory Attempt: %x \n", address_grab);
|
||||
return;
|
||||
}
|
||||
else if (address_grab < 0xF8000000){
|
||||
storage_area = address_grab % 67108864;
|
||||
if ((address_grab >= 0xF3013000) && (address_grab < 0xF3013040)){
|
||||
mac_serial_address = storage_area;
|
||||
serial_write_byte = (uint8_t)value_insert;
|
||||
printf("Writing byte to Serial address %x ... %x \n", address_grab, via_write_byte);
|
||||
mac_serial_write();
|
||||
return;
|
||||
}
|
||||
else if ((address_grab >= 0xF3015000) && (address_grab < 0xF3016000)){
|
||||
mac_swim3_address = storage_area;
|
||||
swim3_write_byte = (uint8_t)value_insert;
|
||||
printf("Writing byte to SWIM3 address %x ... %x \n", address_grab, swim3_write_byte);
|
||||
mac_swim3_write();
|
||||
return;
|
||||
}
|
||||
else if ((address_grab >= 0xF3016000) && (address_grab < 0xF3018000)){
|
||||
via_cuda_address = storage_area;
|
||||
via_write_byte = (uint8_t)value_insert;
|
||||
printf("Writing byte to CUDA address %x ... %x \n", address_grab, via_write_byte);
|
||||
via_cuda_write();
|
||||
return;
|
||||
}
|
||||
else if (address_grab > 0xF3FFFFFF){
|
||||
printf("Uncharted territory: %x", address_grab);
|
||||
return;
|
||||
}
|
||||
grab_macmem_ptr = machine_iocontrolmem_mem;
|
||||
}
|
||||
else if (address_grab < rom_file_begin){
|
||||
//Get back to this! (weeny1)
|
||||
|
||||
if (address_grab < 0xFE000000){
|
||||
storage_area = address_grab % 4096;
|
||||
grab_macmem_ptr = machine_f8xxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEC00000){
|
||||
storage_area = address_grab % 65536;
|
||||
grab_macmem_ptr = machine_fexxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEE00000){
|
||||
storage_area = 0x0CF8; //CONFIG_ADDR
|
||||
grab_macmem_ptr = machine_fecxxx_mem;
|
||||
value_insert = rev_endian32(value_insert);
|
||||
uint32_t reg_num = (value_insert & 0x07FC) >> 2;
|
||||
uint32_t dev_num = (value_insert & 0xF800) >> 11;
|
||||
printf("ADDRESS SET FOR GRACKLE \n");
|
||||
printf("Device Number: %d ", dev_num);
|
||||
printf("Register Number: %d \n", reg_num);
|
||||
mpc106_address = value_insert;
|
||||
}
|
||||
else if (address_grab < 0xFF000000){
|
||||
storage_area = 0x0CFC; //CONFIG_DATA
|
||||
grab_macmem_ptr = machine_feexxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFF800000){
|
||||
storage_area = address_grab % 4096;
|
||||
grab_macmem_ptr = machine_ff00xx_mem;
|
||||
}
|
||||
else{
|
||||
storage_area = (address_grab % 1048576) + 0x400000;
|
||||
grab_macmem_ptr = machine_sysram_mem;
|
||||
}
|
||||
}
|
||||
else{
|
||||
storage_area = address_grab % rom_file_setsize;
|
||||
grab_macmem_ptr = machine_sysrom_mem;
|
||||
}
|
||||
|
||||
switch (ppc_state.ppc_msr & 0x1){
|
||||
case 0:
|
||||
if (bit_num == 1){
|
||||
grab_macmem_ptr[storage_area] = (uint8_t)value_insert;
|
||||
}
|
||||
else if (bit_num == 2){
|
||||
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 8);
|
||||
grab_macmem_ptr[storage_area] = (uint8_t)value_insert;
|
||||
}
|
||||
else if (bit_num == 4){
|
||||
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 24);
|
||||
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 16);
|
||||
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 8);
|
||||
grab_macmem_ptr[storage_area] = (uint8_t)value_insert;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (bit_num == 1){
|
||||
grab_macmem_ptr[storage_area] = (uint8_t)value_insert;
|
||||
}
|
||||
else if (bit_num == 2){
|
||||
grab_macmem_ptr[storage_area++] = (uint8_t)value_insert;
|
||||
grab_macmem_ptr[storage_area] = (uint8_t)(value_insert >> 8);
|
||||
}
|
||||
else if (bit_num == 4){
|
||||
grab_macmem_ptr[storage_area++] = (uint8_t)value_insert;
|
||||
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 8);
|
||||
grab_macmem_ptr[storage_area++] = (uint8_t)(value_insert >> 16);
|
||||
grab_macmem_ptr[storage_area] = (uint8_t)(value_insert >> 24);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void address_quickgrab_translate(uint32_t address_grab, uint32_t value_extract, uint8_t bit_num){
|
||||
//Grab a value from memory into a register
|
||||
|
||||
printf("Grabbing from address %x", address_grab);
|
||||
|
||||
uint32_t storage_area = 0;
|
||||
uint32_t grab_batl = 537;
|
||||
uint32_t blocklen = 0;
|
||||
bool bat_to_go=0;
|
||||
bool pteg_to_go=0;
|
||||
|
||||
return_value = 0; //reset this before going into the real fun.
|
||||
|
||||
//data bat
|
||||
if ((ppc_state.ppc_msr >> 4) & 0x1){
|
||||
printf("DATA RELOCATION GO! - GRABBING \n");
|
||||
uint32_t min_val;
|
||||
uint32_t max_val;
|
||||
|
||||
pteg_to_go = 1;
|
||||
|
||||
for (uint32_t grab_loop = 0; grab_loop < 4; grab_loop++){
|
||||
if (dbat_array_map[grab_loop][0] && 0x1){
|
||||
min_val = dbat_array_map[grab_loop][1];
|
||||
max_val = dbat_array_map[grab_loop][2];
|
||||
if ((address_grab >= min_val) && (address_grab <= max_val) && (max_val != 0)){
|
||||
blocklen = max_val - min_val;
|
||||
bat_to_go = 1;
|
||||
pteg_to_go = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
grab_batl += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (bat_to_go){
|
||||
uint32_t final_grab = 0;
|
||||
final_grab |= (((address_grab & 0x0FFE0000) & blocklen) | (ppc_state.ppc_spr[grab_batl] & 0xFFFE0000));
|
||||
final_grab |= (address_grab & 0x1FFFF);
|
||||
//Check the PP Tags in the batl
|
||||
//if ((ppc_state.ppc_spr[grab_batl] & 0x3) == 0x0){
|
||||
// ppc_expection_handler(0x0300, 0x0);
|
||||
//}
|
||||
address_grab = final_grab;
|
||||
}
|
||||
else if (pteg_to_go){
|
||||
pteg_translate(address_grab);
|
||||
if (hash_found == true){
|
||||
address_grab &= 0xFFF;
|
||||
address_grab |= (pteg_answer & 0xFFFFF000);
|
||||
}
|
||||
}
|
||||
|
||||
//regular grabbing
|
||||
if (address_grab < 0x80000000){
|
||||
if (address_grab > 0x03ffffff){ //for debug purposes
|
||||
storage_area = address_grab;
|
||||
grab_macmem_ptr = machine_sysram_mem;
|
||||
}
|
||||
else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){
|
||||
storage_area = address_grab % 0x2000;
|
||||
grab_macmem_ptr = machine_sysconfig_mem;
|
||||
}
|
||||
else{
|
||||
return_value = (bit_num == 1)?0xFF:(bit_num == 2)?0xFFFF:0xFFFFFFFF;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (address_grab < 0x80800000){
|
||||
if ((address_grab >= 0x80040000) && (address_grab < 0x80080000)){
|
||||
openpic_address = address_grab - 0x80000000;
|
||||
openpic_write();
|
||||
return_value = openpic_write_word;
|
||||
return;
|
||||
}
|
||||
|
||||
storage_area = address_grab % 0x800000;
|
||||
printf("Uncharted territory: %x \n", address_grab);
|
||||
grab_macmem_ptr = machine_upperiocontrol_mem;
|
||||
}
|
||||
else if (address_grab < 0x81000000){
|
||||
storage_area = address_grab;
|
||||
if (address_grab > 0x83FFFFFF){
|
||||
return_value = (bit_num == 1)?0xFF:(bit_num == 2)?0xFFFF:0xFFFFFFFF;
|
||||
return;
|
||||
}
|
||||
printf("Uncharted territory: %x \n", address_grab);
|
||||
grab_macmem_ptr = machine_iocontrolcdma_mem;
|
||||
}
|
||||
else if (address_grab < 0xBF800000){
|
||||
storage_area = address_grab % 33554432;
|
||||
printf("Uncharted territory: %x \n", address_grab);
|
||||
grab_macmem_ptr = machine_loweriocontrol_mem;
|
||||
}
|
||||
else if (address_grab < 0xC0000000){
|
||||
storage_area = address_grab % 16;
|
||||
printf("Uncharted territory: %x \n", address_grab);
|
||||
grab_macmem_ptr = machine_interruptack_mem;
|
||||
}
|
||||
else if (address_grab < 0xF0000000){
|
||||
return_value = (bit_num == 1)?0xFF:(bit_num == 2)?0xFFFF:0xFFFFFFFF;
|
||||
return;
|
||||
}
|
||||
else if (address_grab < 0xF8000000){
|
||||
storage_area = address_grab % 67108864;
|
||||
if ((address_grab >= 0xF3013000) && (address_grab < 0xF3013040)){
|
||||
mac_serial_address = storage_area;
|
||||
mac_serial_read();
|
||||
return_value = serial_read_byte;
|
||||
printf("\n Read from Serial: %x \n", return_value);
|
||||
return;
|
||||
}
|
||||
else if ((address_grab >= 0xF3015000) && (address_grab < 0xF3016000)){
|
||||
mac_swim3_address = storage_area;
|
||||
mac_swim3_read();
|
||||
return_value = swim3_read_byte;
|
||||
printf("\n Read from Swim3: %x \n", return_value);
|
||||
return;
|
||||
}
|
||||
else if ((address_grab >= 0xF3016000) && (address_grab < 0xF3018000)){
|
||||
via_cuda_address = storage_area;
|
||||
via_cuda_read();
|
||||
return_value = via_read_byte;
|
||||
printf("\n Read from CUDA: %x \n", return_value);
|
||||
return;
|
||||
}
|
||||
if ((address_grab >= 0xF3040000) && (address_grab < 0xF3080000)){
|
||||
openpic_address = address_grab - 0x80000000;
|
||||
openpic_write();
|
||||
return_value = openpic_write_word;
|
||||
return;
|
||||
}
|
||||
else if (address_grab > 0xF3FFFFFF){
|
||||
return_value = (bit_num == 1)?0xFF:(bit_num == 2)?0xFFFF:0xFFFFFFFF;
|
||||
return;
|
||||
}
|
||||
grab_macmem_ptr = machine_iocontrolmem_mem;
|
||||
}
|
||||
else if (address_grab < rom_file_begin){
|
||||
//Get back to this! (weeny1)
|
||||
if (address_grab < 0xFE000000){
|
||||
storage_area = address_grab % 4096;
|
||||
grab_macmem_ptr = machine_f8xxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEC00000){
|
||||
storage_area = address_grab % 65536;
|
||||
grab_macmem_ptr = machine_fexxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEE00000){
|
||||
return_value = (bit_num == 1)? (mpc106_address & 0xFF):(bit_num == 2)?(mpc106_address & 0xFFFF):mpc106_address;
|
||||
return;
|
||||
}
|
||||
else if (address_grab < 0xFF000000){
|
||||
storage_area = 0x0CFC; //CONFIG_DATA
|
||||
grab_macmem_ptr = machine_feexxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFF800000){
|
||||
storage_area = address_grab % 4096;
|
||||
grab_macmem_ptr = machine_ff00xx_mem;
|
||||
}
|
||||
else{
|
||||
storage_area = (address_grab % 1048576) + 0x400000;
|
||||
grab_macmem_ptr = machine_sysram_mem;
|
||||
}
|
||||
}
|
||||
else{
|
||||
printf("Charting ROM Area: %x \n", address_grab);
|
||||
storage_area = address_grab % rom_file_setsize;
|
||||
grab_macmem_ptr = machine_sysrom_mem;
|
||||
}
|
||||
|
||||
//Put the final result in return_value here
|
||||
//This is what gets put back into the register
|
||||
switch (ppc_state.ppc_msr & 0x1){
|
||||
case 0:
|
||||
if (bit_num == 1){
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area]));
|
||||
}
|
||||
else if (bit_num == 2){
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 8;
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area]));
|
||||
}
|
||||
else if (bit_num == 4){
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 24;
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 16;
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 8;
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area]));
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (bit_num == 1){
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area]));
|
||||
}
|
||||
else if (bit_num == 2){
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) ;
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area])) << 8;
|
||||
}
|
||||
else if (bit_num == 4){
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) ;
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 8;
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area++])) << 16;
|
||||
return_value |= ((uint32_t)(grab_macmem_ptr[storage_area])) << 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void quickinstruction_translate(uint32_t address_grab){
|
||||
uint32_t storage_area = 0;
|
||||
uint32_t grab_batl = 537;
|
||||
uint32_t blocklen = 0;
|
||||
bool bat_to_go=0;
|
||||
bool pteg_to_go=0;
|
||||
|
||||
return_value = 0; //reset this before going into the real fun.
|
||||
|
||||
//instruction bat
|
||||
if ((ppc_state.ppc_msr >> 5) & 0x1) {
|
||||
printf("INSTRUCTION RELOCATION GO! \n");
|
||||
|
||||
uint32_t min_val;
|
||||
uint32_t max_val;
|
||||
|
||||
pteg_to_go = 1;
|
||||
|
||||
for (uint32_t grab_loop = 0; grab_loop < 4; grab_loop++){
|
||||
if (ibat_array_map[grab_loop][0] && 0x1){
|
||||
min_val = ibat_array_map[grab_loop][1];
|
||||
max_val = ibat_array_map[grab_loop][2];
|
||||
if ((address_grab >= min_val) && (address_grab <= max_val) && (max_val != 0)){
|
||||
blocklen = max_val - min_val;
|
||||
bat_to_go = 1;
|
||||
pteg_to_go = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
grab_batl += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (bat_to_go){
|
||||
uint32_t final_grab = 0;
|
||||
final_grab |= (((address_grab & 0x0FFE0000) & blocklen) | (ppc_state.ppc_spr[grab_batl] & 0xFFFE0000));
|
||||
final_grab |= (address_grab & 0x1FFFF);
|
||||
//if ((ppc_state.ppc_spr[grab_batl] & 0x3) == 0x0){
|
||||
// ppc_expection_handler(0x0400, 0x0);
|
||||
//}
|
||||
address_grab = final_grab;
|
||||
}
|
||||
else if (pteg_to_go){
|
||||
pteg_translate(address_grab);
|
||||
if (hash_found == true){
|
||||
address_grab &= 0xFFF;
|
||||
address_grab |= (pteg_answer & 0xFFFFF000);
|
||||
}
|
||||
}
|
||||
|
||||
if ((address_grab < 0x100000) && ((ppc_state.ppc_msr >> 6) & 1)){
|
||||
address_grab |= 0xFFF00000;
|
||||
}
|
||||
|
||||
//grab opcode from memory area
|
||||
if (address_grab < 0x80000000){
|
||||
if (address_grab < 0x040000000){ //for debug purposes
|
||||
storage_area = address_grab;
|
||||
grab_macmem_ptr = machine_sysram_mem;
|
||||
}
|
||||
else if ((address_grab >= 0x5fffe000) && (address_grab <= 0x5fffffff)){
|
||||
storage_area = address_grab % 0x2000;
|
||||
grab_macmem_ptr = machine_sysconfig_mem;
|
||||
}
|
||||
else{
|
||||
storage_area = address_grab % 0x04000000;
|
||||
grab_macmem_ptr = machine_sysram_mem;
|
||||
printf("Uncharted territory: %x", address_grab);
|
||||
}
|
||||
}
|
||||
else if (address_grab < 0x80800000){
|
||||
storage_area = address_grab % 0x800000;
|
||||
grab_macmem_ptr = machine_upperiocontrol_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0x81000000){
|
||||
storage_area = address_grab % 0x800000;
|
||||
grab_macmem_ptr = machine_iocontrolcdma_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0xBF80000){
|
||||
storage_area = address_grab % 33554432;
|
||||
grab_macmem_ptr = machine_loweriocontrol_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0xC0000000){
|
||||
storage_area = address_grab % 16;
|
||||
grab_macmem_ptr = machine_interruptack_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < 0xF0000000){
|
||||
printf("Invalid Memory Attempt: %x \n", address_grab);
|
||||
return;
|
||||
}
|
||||
else if (address_grab < 0xF8000000){
|
||||
storage_area = address_grab % 67108864;
|
||||
grab_macmem_ptr = machine_iocontrolmem_mem;
|
||||
|
||||
}
|
||||
else if (address_grab < rom_file_begin){
|
||||
//Get back to this! (weeny1)
|
||||
|
||||
if (address_grab < 0xFE000000){
|
||||
storage_area = address_grab % 4096;
|
||||
grab_macmem_ptr = machine_f8xxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEC00000){
|
||||
storage_area = address_grab % 65536;
|
||||
grab_macmem_ptr = machine_fexxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFEE00000){
|
||||
storage_area = 0x0CF8; //CONFIG_ADDR
|
||||
grab_macmem_ptr = machine_fecxxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFF000000){
|
||||
storage_area = 0x0CFC; //CONFIG_DATA
|
||||
grab_macmem_ptr = machine_feexxx_mem;
|
||||
}
|
||||
else if (address_grab < 0xFF800000){
|
||||
storage_area = address_grab % 4096;
|
||||
grab_macmem_ptr = machine_ff00xx_mem;
|
||||
}
|
||||
else{
|
||||
storage_area = (address_grab % 1048576) + 0x400000;
|
||||
grab_macmem_ptr = machine_sysram_mem;
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
storage_area = address_grab % rom_file_setsize;
|
||||
grab_macmem_ptr = machine_sysrom_mem;
|
||||
}
|
||||
|
||||
ppc_cur_instruction += (grab_macmem_ptr[(storage_area++)]) << 24;
|
||||
ppc_cur_instruction += (grab_macmem_ptr[(storage_area++)]) << 16;
|
||||
ppc_cur_instruction += (grab_macmem_ptr[(storage_area++)]) << 8;
|
||||
ppc_cur_instruction += (grab_macmem_ptr[(storage_area)]);
|
||||
}
|
42
ppcmemory.h
Normal file
42
ppcmemory.h
Normal file
@ -0,0 +1,42 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
// The opcodes for the processor - ppcopcodes.cpp
|
||||
|
||||
#ifndef PPCMEMORY_H
|
||||
#define PPCMEMORY_H
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
extern uint32_t bat_srch;
|
||||
extern uint32_t bepi_chk;
|
||||
|
||||
extern uint32_t msr_ir_test;
|
||||
extern uint32_t msr_dr_test;
|
||||
extern uint32_t msr_ip_test;
|
||||
|
||||
extern unsigned char * grab_macmem_ptr;
|
||||
|
||||
/**
|
||||
struct pte {
|
||||
uint32_t page_index_no;
|
||||
uint32_t entry[];
|
||||
pte *next;
|
||||
} PTE;
|
||||
**/
|
||||
|
||||
extern void ibat_update();
|
||||
extern void dbat_update();
|
||||
|
||||
extern void msr_status_update();
|
||||
|
||||
extern void address_quickinsert_translate(uint32_t address_grab, uint32_t value_insert, uint8_t bit_num);
|
||||
extern void address_quickgrab_translate(uint32_t address_grab, uint32_t value_extract, uint8_t bit_num);
|
||||
extern void quickinstruction_translate(uint32_t address_grab);
|
||||
|
||||
#endif // PPCMEMORY_H
|
2411
ppcopcodes.cpp
Normal file
2411
ppcopcodes.cpp
Normal file
File diff suppressed because it is too large
Load Diff
153
viacuda.cpp
Normal file
153
viacuda.cpp
Normal file
@ -0,0 +1,153 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
//Functionality for the VIA CUDA
|
||||
|
||||
#include <iostream>
|
||||
#include <cinttypes>
|
||||
#include "viacuda.h"
|
||||
#include "ppcemumain.h"
|
||||
|
||||
uint32_t via_cuda_address;
|
||||
uint32_t via_set_mode;
|
||||
|
||||
uint8_t via_opcode_store_bit;
|
||||
uint8_t via_write_byte;
|
||||
uint8_t via_read_byte;
|
||||
|
||||
unsigned char porta_ca1, porta_ca2 = 0;
|
||||
unsigned char porta_cb1, porta_cb2 = 0;
|
||||
|
||||
bool via_cuda_confirm;
|
||||
bool via_cuda_signal_read;
|
||||
bool via_cuda_signal_write;
|
||||
|
||||
void via_ifr_update(){
|
||||
if ((machine_iocontrolmem_mem[VIACUDA_IFR] && 127) && (machine_iocontrolmem_mem[VIACUDA_IER] && 127)){
|
||||
machine_iocontrolmem_mem[VIACUDA_IFR] |= 128;
|
||||
}
|
||||
else{
|
||||
machine_iocontrolmem_mem[VIACUDA_IFR] &= 127;
|
||||
}
|
||||
}
|
||||
|
||||
void via_t1_update(){
|
||||
if (machine_iocontrolmem_mem[VIACUDA_T1CH] > 0){
|
||||
machine_iocontrolmem_mem[VIACUDA_T1CH]--;
|
||||
}
|
||||
else{
|
||||
machine_iocontrolmem_mem[VIACUDA_T1CH] = machine_iocontrolmem_mem[VIACUDA_T1LH];
|
||||
}
|
||||
|
||||
|
||||
if (machine_iocontrolmem_mem[VIACUDA_T1CL] > 0){
|
||||
machine_iocontrolmem_mem[VIACUDA_T1CL]--;
|
||||
}
|
||||
else{
|
||||
machine_iocontrolmem_mem[VIACUDA_T1CL] = machine_iocontrolmem_mem[VIACUDA_T1LL];
|
||||
}
|
||||
}
|
||||
|
||||
void via_cuda_init(){
|
||||
machine_iocontrolmem_mem[VIACUDA_A] = 0x80;
|
||||
machine_iocontrolmem_mem[VIACUDA_DIRB] = 0xFF;
|
||||
machine_iocontrolmem_mem[VIACUDA_DIRA] = 0xFF;
|
||||
machine_iocontrolmem_mem[VIACUDA_T1LL] = 0xFF;
|
||||
machine_iocontrolmem_mem[VIACUDA_T1LH] = 0xFF;
|
||||
machine_iocontrolmem_mem[VIACUDA_IER] = 0x7F;
|
||||
}
|
||||
|
||||
void via_cuda_read(){
|
||||
switch(via_cuda_address){
|
||||
case VIACUDA_B:
|
||||
if (machine_iocontrolmem_mem[VIACUDA_DIRB] != 0){
|
||||
via_read_byte = (via_write_byte & ~machine_iocontrolmem_mem[VIACUDA_DIRB]) | (machine_iocontrolmem_mem[VIACUDA_B] & machine_iocontrolmem_mem[VIACUDA_DIRB]);
|
||||
break;
|
||||
}
|
||||
case VIACUDA_A:
|
||||
machine_iocontrolmem_mem[VIACUDA_IFR] = ~porta_ca1;
|
||||
|
||||
via_read_byte = (machine_iocontrolmem_mem[VIACUDA_A] & ~machine_iocontrolmem_mem[VIACUDA_DIRA]) | (machine_iocontrolmem_mem[VIACUDA_A] & machine_iocontrolmem_mem[VIACUDA_DIRA]);
|
||||
break;
|
||||
case VIACUDA_IER:
|
||||
via_read_byte = machine_iocontrolmem_mem[VIACUDA_IER] | 0x80;
|
||||
break;
|
||||
case VIACUDA_ANH:
|
||||
via_read_byte = machine_iocontrolmem_mem[VIACUDA_A] & ~machine_iocontrolmem_mem[VIACUDA_DIRA];
|
||||
break;
|
||||
default:
|
||||
via_read_byte = machine_iocontrolmem_mem[via_cuda_address];
|
||||
}
|
||||
via_read_byte = machine_iocontrolmem_mem[via_cuda_address];
|
||||
}
|
||||
|
||||
void via_cuda_write(){
|
||||
switch(via_cuda_address){
|
||||
case VIACUDA_B:
|
||||
machine_iocontrolmem_mem[VIACUDA_B] = via_write_byte & machine_iocontrolmem_mem[VIACUDA_DIRB];
|
||||
break;
|
||||
case VIACUDA_A:
|
||||
machine_iocontrolmem_mem[VIACUDA_IFR] = ~porta_ca1;
|
||||
if ((machine_iocontrolmem_mem[VIACUDA_PCR] & 0x0A) != 0x02){
|
||||
machine_iocontrolmem_mem[VIACUDA_IFR] = ~porta_ca2;
|
||||
}
|
||||
via_ifr_update();
|
||||
machine_iocontrolmem_mem[VIACUDA_A] = (via_write_byte & machine_iocontrolmem_mem[VIACUDA_DIRA]) | (~machine_iocontrolmem_mem[VIACUDA_DIRA]);
|
||||
break;
|
||||
case VIACUDA_DIRB:
|
||||
machine_iocontrolmem_mem[VIACUDA_DIRB] = via_write_byte;
|
||||
break;
|
||||
case VIACUDA_DIRA:
|
||||
machine_iocontrolmem_mem[VIACUDA_DIRA] = via_write_byte;
|
||||
break;
|
||||
case VIACUDA_T1LL:
|
||||
case VIACUDA_T1LH:
|
||||
via_t1_update();
|
||||
machine_iocontrolmem_mem[via_cuda_address] = via_write_byte;
|
||||
break;
|
||||
case VIACUDA_T2CH:
|
||||
via_t1_update();
|
||||
machine_iocontrolmem_mem[VIACUDA_T2CH] = via_write_byte;
|
||||
break;
|
||||
case VIACUDA_PCR:
|
||||
machine_iocontrolmem_mem[VIACUDA_PCR] = via_write_byte;
|
||||
if ((via_write_byte & 0x0E) == 0x0C){
|
||||
porta_ca2 = 0;
|
||||
}
|
||||
else if ((via_write_byte & 0x08)){
|
||||
porta_ca2 = 1;
|
||||
}
|
||||
|
||||
if ((via_write_byte & 0xE0) == 0xC0){
|
||||
porta_cb2 = 0;
|
||||
}
|
||||
if ((via_write_byte & 0x80)){
|
||||
porta_cb2 = 1;
|
||||
}
|
||||
break;
|
||||
case VIACUDA_IFR:
|
||||
if (via_write_byte & 0x80){
|
||||
machine_iocontrolmem_mem[VIACUDA_IFR] &= (via_write_byte & 0x7F);
|
||||
}
|
||||
else{
|
||||
machine_iocontrolmem_mem[VIACUDA_IFR] &= ~(via_write_byte & 0x7F);
|
||||
}
|
||||
via_ifr_update();
|
||||
break;
|
||||
case VIACUDA_IER:
|
||||
machine_iocontrolmem_mem[VIACUDA_IER] &= ~(via_write_byte & 0x7F);
|
||||
via_ifr_update();
|
||||
break;
|
||||
case VIACUDA_ANH:
|
||||
machine_iocontrolmem_mem[VIACUDA_A] = (via_write_byte & machine_iocontrolmem_mem[VIACUDA_DIRA]) | (~machine_iocontrolmem_mem[VIACUDA_DIRA]);
|
||||
break;
|
||||
default:
|
||||
machine_iocontrolmem_mem[via_cuda_address] = via_write_byte;
|
||||
|
||||
}
|
||||
machine_iocontrolmem_mem[via_cuda_address] = via_write_byte;
|
||||
}
|
48
viacuda.h
Normal file
48
viacuda.h
Normal file
@ -0,0 +1,48 @@
|
||||
//DingusPPC - Prototype 5bf2
|
||||
//Written by divingkatae
|
||||
//(c)2018-20 (theweirdo)
|
||||
//Please ask for permission
|
||||
//if you want to distribute this.
|
||||
//(divingkatae#1017 on Discord)
|
||||
|
||||
#ifndef VIACUDA_H_
|
||||
#define VIACUDA_H_
|
||||
|
||||
#define VIACUDA_B 0x3016000 /* B-side data */
|
||||
#define VIACUDA_A 0x3016200 /* A-side data */
|
||||
#define VIACUDA_DIRB 0x3016400 /* B-side direction (1=output) */
|
||||
#define VIACUDA_DIRA 0x3016600 /* A-side direction (1=output) */
|
||||
#define VIACUDA_T1CL 0x3016800 /* Timer 1 ctr/latch (low 8 bits) */
|
||||
#define VIACUDA_T1CH 0x3016A00 /* Timer 1 counter (high 8 bits) */
|
||||
#define VIACUDA_T1LL 0x3016C00 /* Timer 1 latch (low 8 bits) */
|
||||
#define VIACUDA_T1LH 0x3016E00 /* Timer 1 latch (high 8 bits) */
|
||||
#define VIACUDA_T2CL 0x3017000 /* Timer 2 ctr/latch (low 8 bits) */
|
||||
#define VIACUDA_T2CH 0x3017200 /* Timer 2 counter (high 8 bits) */
|
||||
#define VIACUDA_SR 0x3017400 /* Shift register */
|
||||
#define VIACUDA_ACR 0x3017600 /* Auxiliary control register */
|
||||
#define VIACUDA_PCR 0x3017800 /* Peripheral control register */
|
||||
#define VIACUDA_IFR 0x3017A00 /* Interrupt flag register */
|
||||
#define VIACUDA_IER 0x3017C00 /* Interrupt enable register */
|
||||
#define VIACUDA_ANH 0x3017E00 /* A-side data, no handshake */
|
||||
|
||||
extern uint32_t via_cuda_address;
|
||||
extern uint8_t via_opcode_store_bit;
|
||||
|
||||
extern uint8_t via_write_byte;
|
||||
extern uint8_t via_read_byte;
|
||||
|
||||
extern bool via_cuda_confirm;
|
||||
extern bool via_cuda_signal_read;
|
||||
extern bool via_cuda_signal_write;
|
||||
|
||||
extern unsigned char porta_ca1, porta_ca2;
|
||||
extern unsigned char porta_cb1, porta_cb2;
|
||||
extern uint32_t via_set_mode;
|
||||
|
||||
extern void via_ifr_update();
|
||||
extern void via_t1_update();
|
||||
extern void via_cuda_init();
|
||||
extern void via_cuda_read();
|
||||
extern void via_cuda_write();
|
||||
|
||||
#endif // VIACUDA_H
|
Loading…
x
Reference in New Issue
Block a user