dingusppc/ppcfpopcodes.cpp
dingusdev 87acd53c86
Update for July 11, 2019
- Fixed the floating point operations dispatch table and filled in a lot of missing gaps
- Started overhauling floating point emulation
- Minor fixes for Grackle reading and writing, mostly writing
- Handle integer division by zero cases
2019-07-11 22:27:14 -07:00

1155 lines
31 KiB
C++

//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 <cfenv>
#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];
}
void ppc_divbyzero(uint64_t input_a, uint64_t input_b, bool is_single){
if (input_b == 0){
ppc_state.ppc_fpscr |= 0x84000000;
if (input_a == 0){
ppc_state.ppc_fpscr |= 0x200000;
}
}
}
void ppc_confirm_inf_nan(uint64_t input_a, uint64_t input_b, bool is_single, uint32_t op){
if (is_single){
uint32_t exp_a = (input_a >> 23) & 0xff;
uint32_t exp_b = (input_b >> 23) & 0xff;
ppc_state.ppc_fpscr &= 0x7fbfffff;
switch(op){
case 36:
if ((exp_a == 0xff) & (exp_b == 0xff)){
ppc_state.ppc_fpscr |= 0x80400000;
}
else if ((input_a == 0) & (input_b == 0)){
ppc_state.ppc_fpscr |= 0x80200000;
}
break;
case 40:
if ((exp_a == 0xff) & (exp_b == 0xff)){
ppc_state.ppc_fpscr |= 0x80800000;
}
break;
case 50:
if (((exp_a == 0xff) & (input_b == 0)) | ((exp_b == 0xff) & (input_a == 0))){
ppc_state.ppc_fpscr |= 0x80100000;
}
break;
}
}
else{
uint32_t exp_a = (input_a >> 52) & 0x7ff;
uint32_t exp_b = (input_b >> 52) & 0x7ff;
ppc_state.ppc_fpscr &= 0x7fbfffff;
switch(op){
case 36:
if ((exp_a == 0x7ff) & (exp_b == 0x7ff)){
ppc_state.ppc_fpscr |= 0x80400000;
}
else if ((input_a == 0) & (input_b == 0)){
ppc_state.ppc_fpscr |= 0x80200000;
}
break;
case 40:
if ((exp_a == 0x7ff) & (exp_b == 0x7ff)){
ppc_state.ppc_fpscr |= 0x80800000;
}
break;
case 50:
if (((exp_a == 0x7ff) & (input_b == 0)) | ((exp_b == 0x7ff) & (input_a == 0))){
ppc_state.ppc_fpscr |= 0x80100000;
}
break;
}
}
}
void ppc_fpresult_update(uint64_t set_result, bool confirm_arc){
bool confirm_ov = (bool)std::fetestexcept(FE_OVERFLOW);
if (confirm_ov){
ppc_state.ppc_fpscr |= 0x80001000;
}
if (confirm_arc){
ppc_state.ppc_fpscr |= 0x80010000;
ppc_state.ppc_fpscr &= 0xFFFF0FFF;
if (set_result < 0){
ppc_state.ppc_fpscr |= 0x8000;
}
else if (set_result > 0){
ppc_state.ppc_fpscr |= 0x4000;
}
else if (set_result == 0){
ppc_state.ppc_fpscr |= 0x2000;
}
else{
ppc_state.ppc_fpscr |= 0x1000;
}
}
}
void ppc_changecrf1(){
ppc_state.ppc_cr &= 0xF0FFFFFF;
ppc_state.ppc_cr |= (ppc_state.ppc_fpscr & 0xF0000000) >> 4;
}
//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_fadddot(){
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();
ppc_changecrf1();
}
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_fsubdot(){
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();
ppc_changecrf1();
}
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_fdivdot(){
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();
ppc_changecrf1();
}
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_fmultdot(){
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();
ppc_changecrf1();
}
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);
testd4 += testd2;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
}
void ppc_fmadddot(){
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);
testd4 += testd2;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
ppc_changecrf1();
}
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);
testd4 -= testd2;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
}
void ppc_fmsubdot(){
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);
testd4 -= testd2;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
ppc_changecrf1();
}
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);
testd4 += testd2;
testd4 = -testd4;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
}
void ppc_fnmadddot(){
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);
testd4 += testd2;
testd4 = -testd4;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
ppc_changecrf1();
}
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);
testd4 -= testd2;
testd4 = -testd4;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
}
void ppc_fnmsubdot(){
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);
testd4 -= testd2;
testd4 = -testd4;
ppc_result64_d = (uint64_t)testd4;
ppc_store_dfpresult();
ppc_changecrf1();
}
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_faddsdot(){
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();
ppc_changecrf1();
}
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_fsubsdot(){
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();
ppc_changecrf1();
}
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_fmultsdot(){
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();
ppc_changecrf1();
}
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_fdivsdot(){
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();
ppc_changecrf1();
}
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);
testf4 += testf2;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
}
void ppc_fmaddsdot(){
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);
testf4 += testf2;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
ppc_changecrf1();
}
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);
testf4 -= testf2;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
}
void ppc_fmsubsdot(){
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);
testf4 -= testf2;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
ppc_changecrf1();
}
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);
testf4 += testf2;
testf4 = -testf4;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
}
void ppc_fnmaddsdot(){
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);
testf4 += testf2;
testf4 = -testf4;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
ppc_changecrf1();
}
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);
testf4 -= testf2;
testf4 = -testf4;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
}
void ppc_fnmsubsdot(){
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);
testf4 -= testf2;
testf4 = -testf4;
ppc_result64_d = (uint64_t)testf4;
ppc_store_dfpresult();
ppc_changecrf1();
}
void ppc_fabs(){
ppc_grab_regsfpdb();
double testd1 = (double)ppc_result64_b;
ppc_result64_d = (uint64_t)(abs(testd1));
ppc_store_dfpresult();
}
void ppc_fabsdot(){
ppc_grab_regsfpdb();
double testd1 = (double)ppc_result64_b;
ppc_result64_d = (uint64_t)-(abs(testd1));
ppc_store_dfpresult();
ppc_changecrf1();
}
void ppc_fnabs(){
ppc_grab_regsfpdb();
double testd1 = (double)ppc_result64_b;
ppc_result64_d = (uint64_t)(abs(testd1));
ppc_store_dfpresult();
}
void ppc_fnabsdot(){
ppc_grab_regsfpdb();
double testd1 = (double)ppc_result64_b;
ppc_result64_d = (uint64_t)-(abs(testd1));
ppc_store_dfpresult();
ppc_changecrf1();
}
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_fnegdot(){
ppc_grab_regsfpdb();
double testd1 = (double)ppc_result64_a;
double testd3 = -testd1;
ppc_result64_d = (double)testd3;
ppc_store_dfpresult();
ppc_changecrf1();
}
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_fseldot(){
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();
ppc_changecrf1();
}
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_fsqrtdot(){
ppc_grab_regsfpdb();
double test = (double)ppc_result64_b;
std::sqrt(test);
ppc_result64_d = (uint64_t)test;
ppc_store_dfpresult();
ppc_changecrf1();
}
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_fsqrtsdot(){
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();
ppc_changecrf1();
}
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_frsqrtedot(){
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();
ppc_changecrf1();
}
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_frspdot(){
ppc_grab_regsfpdb();
double testd2 = (double)ppc_result64_b;
float testf2 = (float) testd2;
ppc_result64_d = (uint64_t) testf2;
ppc_store_dfpresult();
ppc_changecrf1();
}
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_fresdot(){
ppc_grab_regsfpdb();
float testf2 = (float)ppc_result64_b;
testf2 = 1/testf2;
ppc_result64_d = (uint64_t) testf2;
ppc_store_dfpresult();
ppc_changecrf1();
}
void ppc_fctiw(){
//PLACEHOLDER!
ppc_grab_regsfpdiab();
double testd1 = (double)ppc_result64_b;
ppc_result_d = (uint32_t)(testd1);
ppc_store_result_regd();
ppc_changecrf1();
}
void ppc_fctiwdot(){
//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();
ppc_changecrf1();
}
void ppc_fctiwzdot(){
//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_mffsdot(){
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_mtfsfdot(){
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;
}
}