mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-11-15 17:08:19 +00:00
2552 lines
76 KiB
C++
2552 lines
76 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)
|
|
|
|
// General opcodes for the processor - ppcopcodes.cpp
|
|
|
|
#include <iostream>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
#include <cstring>
|
|
#include <cinttypes>
|
|
#include <array>
|
|
#include <thread>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdexcept>
|
|
#include "ppcemumain.h"
|
|
#include "ppcmemory.h"
|
|
|
|
uint32_t crf_d;
|
|
uint32_t crf_s;
|
|
uint32_t reg_s;
|
|
uint32_t reg_d;
|
|
uint32_t reg_a;
|
|
uint32_t reg_b;
|
|
uint32_t reg_c; //used only for floating point multiplication operations
|
|
uint32_t xercon;
|
|
uint32_t cmp_c;
|
|
uint32_t crm;
|
|
uint32_t rot_sh;
|
|
uint32_t rot_mb;
|
|
uint32_t rot_me;
|
|
uint32_t uimm;
|
|
uint32_t not_this;
|
|
uint32_t grab_sr;
|
|
uint32_t grab_inb; //This is for grabbing the number of immediate bytes for loading and storing
|
|
uint32_t grab_d; //This is for grabbing d from Store and Load instructions
|
|
uint32_t ppc_to;
|
|
int32_t simm;
|
|
int32_t adr_li;
|
|
|
|
//Used for GP calcs
|
|
uint32_t ppc_result_a = 0;
|
|
uint32_t ppc_result_b = 0;
|
|
uint32_t ppc_result_c = 0;
|
|
uint32_t ppc_result_d = 0;
|
|
|
|
int32_t sidiv_result;
|
|
uint32_t uidiv_result;
|
|
uint64_t uiproduct;
|
|
int64_t siproduct;
|
|
|
|
uint32_t strwrd_replace_value;
|
|
|
|
/** Lookup tables. */
|
|
|
|
/** Primary opcode (bits 0...5) lookup table. */
|
|
static PPCOpcode OpcodeGrabber[] = {
|
|
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_twi, ppc_opcode4,
|
|
ppc_illegalop, ppc_illegalop, ppc_mulli, ppc_subfic, power_dozi,
|
|
ppc_cmpli, ppc_cmpi, ppc_addic, ppc_addicdot, ppc_addi,
|
|
ppc_addis, ppc_opcode16, ppc_sc, ppc_opcode18, ppc_opcode19,
|
|
ppc_rlwimi, ppc_rlwinm, power_rlmi, ppc_rlwnm, ppc_ori,
|
|
ppc_oris, ppc_xori, ppc_xoris, ppc_andidot, ppc_andisdot,
|
|
ppc_illegalop, ppc_opcode31, ppc_lwz, ppc_lwzu, ppc_lbz,
|
|
ppc_lbzu, ppc_stw, ppc_stwu, ppc_stb, ppc_stbu,
|
|
ppc_lhz, ppc_lhzu, ppc_lha, ppc_lhau, ppc_sth,
|
|
ppc_sthu, ppc_lmw, ppc_stmw, ppc_lfs, ppc_lfsu,
|
|
ppc_lfd, ppc_lfdu, ppc_stfs, ppc_stfsu, ppc_stfd,
|
|
ppc_stfdu, ppc_psq_l, ppc_psq_lu, ppc_illegalop, ppc_illegalop,
|
|
ppc_psq_st, ppc_psq_stu, ppc_illegalop, ppc_opcode63
|
|
};
|
|
|
|
/** Lookup tables for branch instructions. */
|
|
static PPCOpcode SubOpcode16Grabber[] = {
|
|
ppc_bc, ppc_bcl, ppc_bca, ppc_bcla
|
|
};
|
|
|
|
static PPCOpcode SubOpcode18Grabber[] = {
|
|
ppc_b, ppc_bl, ppc_ba, ppc_bla
|
|
};
|
|
|
|
/**
|
|
Extract the registers desired and the values of the registers
|
|
This also takes the MSR into account, mainly to determine
|
|
what endian the numbers are to be stored in.
|
|
**/
|
|
|
|
//Storage and register retrieval functions for the integer functions.
|
|
void ppc_store_result_regd(){
|
|
ppc_state.ppc_gpr[reg_d] = ppc_result_d;
|
|
}
|
|
|
|
void ppc_store_result_rega(){
|
|
ppc_state.ppc_gpr[reg_a] = ppc_result_a;
|
|
}
|
|
|
|
void ppc_grab_regsdasimm(){
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
reg_a = (ppc_cur_instruction >> 16) & 31;
|
|
simm = (int32_t)((int16_t)((ppc_cur_instruction) & 65535));
|
|
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
|
}
|
|
|
|
void ppc_grab_regsdauimm(){
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
reg_a = (ppc_cur_instruction >> 16) & 31;
|
|
uimm = (uint32_t)((uint16_t)((ppc_cur_instruction) & 65535));
|
|
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
|
}
|
|
|
|
void ppc_grab_regsasimm(){
|
|
reg_a = (ppc_cur_instruction >> 16) & 31;
|
|
simm = (int32_t)((int16_t)(ppc_cur_instruction & 65535));
|
|
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
|
}
|
|
|
|
void ppc_grab_regssauimm(){
|
|
reg_s = (ppc_cur_instruction >> 21) & 31;
|
|
reg_a = (ppc_cur_instruction >> 16) & 31;
|
|
uimm = (uint32_t)((uint16_t)((ppc_cur_instruction) & 65535));
|
|
ppc_result_d = ppc_state.ppc_gpr[reg_s];
|
|
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
|
}
|
|
|
|
void ppc_grab_regsdab(){
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
reg_a = (ppc_cur_instruction >> 16) & 31;
|
|
reg_b = (ppc_cur_instruction >> 11) & 31;
|
|
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
|
ppc_result_b = ppc_state.ppc_gpr[reg_b];
|
|
}
|
|
|
|
void ppc_grab_regssab(){
|
|
reg_s = (ppc_cur_instruction >> 21) & 31;
|
|
reg_a = (ppc_cur_instruction >> 16) & 31;
|
|
reg_b = (ppc_cur_instruction >> 11) & 31;
|
|
ppc_result_d = ppc_state.ppc_gpr[reg_s];
|
|
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
|
ppc_result_b = ppc_state.ppc_gpr[reg_b];
|
|
}
|
|
|
|
void ppc_grab_regssa(){
|
|
reg_s = (ppc_cur_instruction >> 21) & 31;
|
|
reg_a = (ppc_cur_instruction >> 16) & 31;
|
|
ppc_result_d = ppc_state.ppc_gpr[reg_s];
|
|
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
|
}
|
|
|
|
void ppc_grab_regssb(){
|
|
reg_s = (ppc_cur_instruction >> 21) & 31;
|
|
reg_b = (ppc_cur_instruction >> 11) & 31;
|
|
ppc_result_d = ppc_state.ppc_gpr[reg_s];
|
|
ppc_result_b = ppc_state.ppc_gpr[reg_b];
|
|
}
|
|
|
|
void ppc_grab_regsda(){
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
reg_a = (ppc_cur_instruction >> 16) & 31;
|
|
ppc_result_a = ppc_state.ppc_gpr[reg_a];
|
|
}
|
|
|
|
void ppc_grab_regsdb(){
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
reg_b = (ppc_cur_instruction >> 11) & 31;
|
|
ppc_result_b = ppc_state.ppc_gpr[reg_b];
|
|
}
|
|
|
|
|
|
//Affects CR Field 0 - For integer operations
|
|
void ppc_changecrf0(uint32_t set_result){
|
|
ppc_state.ppc_cr &= 0x0FFFFFFF;
|
|
|
|
if (set_result == 0){
|
|
ppc_state.ppc_cr |= 0x20000000;
|
|
}
|
|
else if (set_result & 0x80000000){
|
|
ppc_state.ppc_cr |= 0x80000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr |= 0x40000000;
|
|
}
|
|
|
|
if (ppc_state.ppc_spr[1] & 0x80000000){
|
|
ppc_state.ppc_cr |= 0x10000000;
|
|
}
|
|
}
|
|
|
|
//Affects the XER register's Carry Bit
|
|
void ppc_carry(uint32_t a, uint32_t b){
|
|
if (b < a){ // TODO: ensure it works everywhere
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
}
|
|
|
|
//Affects the XER register's SO and OV Bits
|
|
void ppc_setsoov(uint32_t a, uint32_t b){
|
|
uint64_t a64b = (uint64_t)a;
|
|
uint64_t b64b = (uint64_t)b;
|
|
|
|
if ((a64b + b64b) > 0xFFFFFFFF){
|
|
ppc_state.ppc_spr[1] |= 0x40000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xBFFFFFFF;
|
|
}
|
|
|
|
if (((a64b + b64b) < 0x80000000) || (ppc_state.ppc_spr[1] & 0x40000000)){
|
|
ppc_state.ppc_spr[1] |= 0x80000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0x7FFFFFFF;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Avoid some tedious steps to breaking down the opcodes,
|
|
allowing for some nice maps to cleanly organize each opcode.
|
|
**/
|
|
|
|
void ppc_illegalop(){
|
|
uint8_t illegal_code = ppc_cur_instruction >> 26;
|
|
uint32_t grab_it = (uint32_t) illegal_code;
|
|
printf("Illegal opcode reported: %d Report this! \n", grab_it);
|
|
exit(-1);
|
|
//ppc_exception_handler(0x0700, 0x80000);
|
|
}
|
|
|
|
void ppc_illegalsubop31(){
|
|
uint16_t illegal_subcode = ppc_cur_instruction & 2047;
|
|
uint32_t grab_it = (uint32_t) illegal_subcode;
|
|
printf("Illegal subopcode for 31 reported: %d Report this! \n", grab_it);
|
|
}
|
|
|
|
void ppc_opcode4(){
|
|
printf("Reading from Opcode 4 table \n");
|
|
uint8_t subop_grab = ppc_cur_instruction & 3;
|
|
uint32_t regrab = (uint32_t)subop_grab;
|
|
printf("Executing subopcode entry %d \n .. or would if I bothered to implement it. SORRY!", regrab);
|
|
exit(0);
|
|
}
|
|
|
|
void ppc_opcode16(){
|
|
SubOpcode16Grabber[ppc_cur_instruction & 3]();
|
|
}
|
|
|
|
void ppc_opcode18(){
|
|
SubOpcode18Grabber[ppc_cur_instruction & 3]();
|
|
}
|
|
|
|
void ppc_opcode19(){
|
|
uint16_t subop_grab = ppc_cur_instruction & 2047;
|
|
#ifdef EXHAUSTIVE_DEBUG
|
|
uint32_t regrab = (uint32_t)subop_grab;
|
|
printf("Executing Opcode 19 table supopcode entry %d \n", regrab);
|
|
if (SubOpcode19Grabber.count(subop_grab) == 1){
|
|
SubOpcode19Grabber[subop_grab]();
|
|
}
|
|
else{
|
|
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
|
|
ppc_exception_handler(0x0700, 0x80000);
|
|
}
|
|
#else
|
|
SubOpcode19Grabber[subop_grab]();
|
|
#endif // EXHAUSTIVE_DEBUG
|
|
}
|
|
|
|
void ppc_opcode31(){
|
|
uint16_t subop_grab = ppc_cur_instruction & 2047;
|
|
#ifdef EXHAUSTIVE_DEBUG
|
|
uint32_t regrab = (uint32_t)subop_grab;
|
|
printf("Executing Opcode 31 table supopcode entry %d \n", regrab);
|
|
if (SubOpcode31Grabber.count(subop_grab) == 1){
|
|
SubOpcode31Grabber[subop_grab]();
|
|
}
|
|
else{
|
|
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
|
|
ppc_exception_handler(0x0700, 0x80000);
|
|
}
|
|
#else
|
|
SubOpcode31Grabber[subop_grab]();
|
|
#endif // EXHAUSTIVE_DEBUG
|
|
}
|
|
|
|
void ppc_opcode59(){
|
|
uint16_t subop_grab = ppc_cur_instruction & 2047;
|
|
#ifdef EXHAUSTIVE_DEBUG
|
|
uint32_t regrab = (uint32_t)subop_grab;
|
|
printf("Executing Opcode 59 table supopcode entry %d \n", regrab);
|
|
if (SubOpcode59Grabber.count(subop_grab) == 1){
|
|
SubOpcode59Grabber[subop_grab]();
|
|
}
|
|
else{
|
|
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
|
|
ppc_exception_handler(0x0700, 0x80000);
|
|
}
|
|
#else
|
|
SubOpcode59Grabber[subop_grab]();
|
|
#endif // EXHAUSTIVE_DEBUG
|
|
}
|
|
|
|
void ppc_opcode63(){
|
|
uint16_t subop_grab = ppc_cur_instruction & 2047;
|
|
#ifdef EXHAUSTIVE_DEBUG
|
|
uint32_t regrab = (uint32_t)subop_grab;
|
|
std::cout << "Executing Opcode 63 table subopcode entry " << regrab << std::endl;
|
|
if (SubOpcode63Grabber.count(subop_grab) == 1){
|
|
SubOpcode63Grabber[subop_grab]();
|
|
}
|
|
else{
|
|
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
|
|
ppc_exception_handler(0x0700, 0x80000);
|
|
}
|
|
#else
|
|
SubOpcode63Grabber[subop_grab]();
|
|
#endif // EXHAUSTIVE_DEBUG
|
|
}
|
|
|
|
void ppc_main_opcode(){
|
|
//Grab the main opcode
|
|
uint8_t ppc_mainop = (ppc_cur_instruction >> 26) & 63;
|
|
//printf("Main Opcode: %d \n", ppc_mainop);
|
|
OpcodeGrabber[ppc_mainop]();
|
|
}
|
|
|
|
/**
|
|
The core functionality of this PPC emulation is within all of these void functions.
|
|
This is where the opcode tables in the ppcemumain.h come into play - reducing the number of comparisons needed.
|
|
This means loads of functions, but less CPU cycles needed to determine the function (theoretically).
|
|
**/
|
|
|
|
void ppc_addi(){
|
|
ppc_grab_regsdasimm();
|
|
ppc_result_d = (reg_a == 0)?simm:(ppc_result_a + simm);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addic(){
|
|
ppc_grab_regsdasimm();
|
|
ppc_result_d = (ppc_result_a + simm);
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addicdot(){
|
|
ppc_grab_regsdasimm();
|
|
ppc_result_d = (ppc_result_a + simm);
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addis(){
|
|
ppc_grab_regsdasimm();
|
|
ppc_result_d = (reg_a == 0)?(simm << 16):(ppc_result_a + (simm << 16));
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_add(){
|
|
ppc_grab_regsdab();
|
|
ppc_result_d = ppc_result_a + ppc_result_b;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_adddot(){
|
|
ppc_grab_regsdab();
|
|
ppc_result_d = ppc_result_a + ppc_result_b;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
//addo + addodot
|
|
void ppc_addo(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
ppc_result_d = ppc_result_a + ppc_result_b;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addodot(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
ppc_result_d = ppc_result_a + ppc_result_b;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addc(){
|
|
ppc_grab_regsdab();
|
|
ppc_result_d = ppc_result_a + ppc_result_b;
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addcdot(){
|
|
ppc_grab_regsdab();
|
|
ppc_result_d = ppc_result_a + ppc_result_b;
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addco(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
ppc_result_d = ppc_result_a + ppc_result_b;
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addcodot(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
ppc_result_d = ppc_result_a + ppc_result_b;
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_adde(){
|
|
ppc_grab_regsdab();
|
|
uint32_t xer_ca = !!(ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_result_d = ppc_result_a + ppc_result_b + xer_ca;
|
|
if ((ppc_result_d < ppc_result_a) || (xer_ca && (ppc_result_d == ppc_result_a))){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addedot(){
|
|
ppc_grab_regsdab();
|
|
uint32_t xer_ca = !!(ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_result_d = ppc_result_a + ppc_result_b + xer_ca;
|
|
if ((ppc_result_d < ppc_result_a) || (xer_ca && (ppc_result_d == ppc_result_a))){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addeo(){
|
|
ppc_grab_regsdab();
|
|
uint32_t xer_ca = !!(ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_result_d = ppc_result_a + ppc_result_b + xer_ca;
|
|
if ((ppc_result_d < ppc_result_a) || (xer_ca && (ppc_result_d == ppc_result_a))){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addeodot(){
|
|
ppc_grab_regsdab();
|
|
uint32_t xer_ca = !!(ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_setsoov(ppc_result_a, (ppc_result_b + xer_ca));
|
|
ppc_result_d = ppc_result_a + ppc_result_b + xer_ca;
|
|
if ((ppc_result_d < ppc_result_a) || (xer_ca && (ppc_result_d == ppc_result_a))){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addme(){
|
|
ppc_grab_regsda();
|
|
uint32_t xer_ca = !!(ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_result_d = ppc_result_a + xer_ca - 1;
|
|
if (((xer_ca - 1) < 0xFFFFFFFF) | (ppc_result_d < ppc_result_a)){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addmedot(){
|
|
ppc_grab_regsda();
|
|
uint32_t xer_ca = !!(ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_result_d = ppc_result_a + xer_ca - 1;
|
|
if (((xer_ca - 1) < 0xFFFFFFFF) | (ppc_result_d < ppc_result_a)){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addmeo(){
|
|
ppc_grab_regsda();
|
|
uint32_t xer_ca = !!(ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_setsoov(ppc_result_a, xer_ca);
|
|
ppc_result_d = ppc_result_a + xer_ca - 1;
|
|
if (((xer_ca - 1) < 0xFFFFFFFF) | (ppc_result_d < ppc_result_a)){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addmeodot(){
|
|
ppc_grab_regsda();
|
|
uint32_t xer_ca = !!(ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_setsoov(ppc_result_a, xer_ca);
|
|
ppc_result_d = ppc_result_a + xer_ca - 1;
|
|
ppc_changecrf0(ppc_result_d);
|
|
if (((xer_ca - 1) < 0xFFFFFFFF) | (ppc_result_d < ppc_result_a)){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addze(){
|
|
ppc_grab_regsda();
|
|
uint32_t grab_xer = (ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_result_d = ppc_result_a + grab_xer;
|
|
if (ppc_result_d < ppc_result_a){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addzedot(){
|
|
ppc_grab_regsda();
|
|
uint32_t grab_xer = (ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_result_d = ppc_result_a + grab_xer;
|
|
if (ppc_result_d < ppc_result_a){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addzeo(){
|
|
ppc_grab_regsda();
|
|
uint32_t grab_xer = (ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_setsoov(ppc_result_a, grab_xer);
|
|
ppc_result_d = ppc_result_a + grab_xer;
|
|
if (ppc_result_d < ppc_result_a){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_addzeodot(){
|
|
ppc_grab_regsda();
|
|
uint32_t grab_xer = (ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_setsoov(ppc_result_a, grab_xer);
|
|
ppc_result_d = ppc_result_a + grab_xer;
|
|
if (ppc_result_d < ppc_result_a){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subf(){
|
|
ppc_grab_regsdab();
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + 1;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfdot(){
|
|
ppc_grab_regsdab();
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + 1;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfo(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + 1;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfodot(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + 1;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfc(){
|
|
ppc_grab_regsdab();
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + 1;
|
|
if (ppc_result_d <= not_this){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfcdot(){
|
|
ppc_grab_regsdab();
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + 1;
|
|
if (ppc_result_d <= not_this){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfco(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + 1;
|
|
if (ppc_result_d <= not_this){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfcodot(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + 1;
|
|
if (ppc_result_d <= not_this){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfic(){
|
|
ppc_grab_regsdasimm();
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + simm + 1;
|
|
if (ppc_result_d <= not_this) {
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfe(){
|
|
ppc_grab_regsdab();
|
|
uint32_t grab_xer = (ppc_state.ppc_spr[1] & 0x20000000);
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + (ppc_state.ppc_spr[1] & 0x20000000);
|
|
if (ppc_result_d <= (not_this + grab_xer)){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfedot(){
|
|
ppc_grab_regsdab();
|
|
uint32_t grab_xer = (ppc_state.ppc_spr[1] & 0x20000000);
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + ppc_result_b + grab_xer;
|
|
if (ppc_result_d <= (not_this + grab_xer)){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, ppc_result_d);
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfme(){
|
|
ppc_grab_regsda();
|
|
not_this = ~ppc_result_a;
|
|
uint32_t grab_xer = (ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_result_d = not_this + grab_xer - 1;
|
|
if (ppc_result_a || grab_xer){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, grab_xer);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfmedot(){
|
|
ppc_grab_regsda();
|
|
not_this = ~ppc_result_a;
|
|
uint32_t grab_xer = (ppc_state.ppc_spr[1] & 0x20000000);
|
|
ppc_result_d = not_this + grab_xer - 1;
|
|
if (ppc_result_d <= (not_this + grab_xer)){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, grab_xer);
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfze(){
|
|
ppc_grab_regsda();
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + (ppc_state.ppc_spr[1] & 0x20000000);
|
|
if (ppc_result_d <= not_this){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, (ppc_state.ppc_spr[1] & 0x20000000));
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_subfzedot(){
|
|
ppc_grab_regsda();
|
|
not_this = ~ppc_result_a;
|
|
ppc_result_d = not_this + (ppc_state.ppc_spr[1] & 0x20000000);
|
|
if (ppc_result_d <= not_this){
|
|
ppc_state.ppc_spr[1] |= 0x20000000;
|
|
}
|
|
else{
|
|
ppc_state.ppc_spr[1] &= 0xDFFFFFFF;
|
|
}
|
|
ppc_carry(ppc_result_a, (ppc_state.ppc_spr[1] & 0x20000000));
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_and(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d & ppc_result_b;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_anddot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d & ppc_result_b;
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_andc(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d & ~(ppc_result_b);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_andcdot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d & ~(ppc_result_b);
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_andidot(){
|
|
ppc_grab_regssauimm();
|
|
ppc_result_a = ppc_result_d & uimm;
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_andisdot(){
|
|
ppc_grab_regssauimm();
|
|
ppc_result_a = ppc_result_d & (uimm << 16);
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_nand(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ~(ppc_result_d & ppc_result_b);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_nanddot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ~(ppc_result_d & ppc_result_b);
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_or(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d | ppc_result_b;
|
|
printf("OR Result: %x in Reg %d from Regs %d and %d \n", ppc_result_a, reg_a, reg_s, reg_b);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_ordot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d | ppc_result_b;
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_orc(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d | ~(ppc_result_b);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_orcdot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d | ~(ppc_result_b);
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_ori(){
|
|
ppc_grab_regssauimm();
|
|
ppc_result_a = ppc_result_d | uimm;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_oris(){
|
|
ppc_grab_regssauimm();
|
|
ppc_result_a = ppc_result_d | (uimm << 16);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_eqv(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ~(ppc_result_d ^ ppc_result_b);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_eqvdot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ~(ppc_result_d ^ ppc_result_b);
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_nor(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ~(ppc_result_d | ppc_result_b);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_nordot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ~(ppc_result_d | ppc_result_b);
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_xor(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d ^ ppc_result_b;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_xordot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = ppc_result_d ^ ppc_result_b;
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_xori(){
|
|
ppc_grab_regssauimm();
|
|
ppc_result_a = ppc_result_d ^ uimm;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_xoris(){
|
|
ppc_grab_regssauimm();
|
|
ppc_result_a = ppc_result_d ^ (uimm << 16);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_neg(){
|
|
ppc_grab_regsda();
|
|
ppc_result_d = ~(ppc_result_a) + 1;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_negdot(){
|
|
ppc_grab_regsda();
|
|
ppc_result_d = ~(ppc_result_a) + 1;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_nego(){
|
|
ppc_grab_regsda();
|
|
ppc_result_d = ~(ppc_result_a) + 1;
|
|
ppc_state.ppc_spr[1] |= 0x40000000;
|
|
ppc_setsoov(ppc_result_d, 1);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_negodot(){
|
|
ppc_grab_regsda();
|
|
ppc_result_d = ~(ppc_result_a) + 1;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_state.ppc_spr[1] |= 0x40000000;
|
|
ppc_setsoov(ppc_result_d, 1);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_cntlzw(){
|
|
ppc_grab_regssa();
|
|
uint32_t trail = 0;
|
|
uint32_t bit_set = 0x80000000;
|
|
do{
|
|
if ((ppc_result_d && bit_set) == 1){
|
|
break;
|
|
}
|
|
bit_set = bit_set >> 1;
|
|
trail++;
|
|
} while (trail < 32);
|
|
ppc_result_a = trail;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_cntlzwdot(){
|
|
ppc_grab_regssa();
|
|
uint32_t trail = 0;
|
|
uint32_t bit_set = 0xF0000000;
|
|
do{
|
|
if ((ppc_result_d && bit_set) == 1){
|
|
break;
|
|
}
|
|
bit_set = bit_set >> 1;
|
|
trail++;
|
|
} while (trail < 32);
|
|
ppc_result_a = trail;
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_mulhwu(){
|
|
ppc_grab_regsdab();
|
|
uiproduct = (uint64_t) ppc_result_a * (uint64_t) ppc_result_b;
|
|
uiproduct = uiproduct >> 32;
|
|
ppc_result_d = uiproduct;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_mulhwudot(){
|
|
ppc_grab_regsdab();
|
|
uiproduct = (uint64_t) ppc_result_a * (uint64_t) ppc_result_b;
|
|
uiproduct = uiproduct >> 32;
|
|
ppc_result_d = uiproduct;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_mulhw(){
|
|
ppc_grab_regsdab();
|
|
siproduct = (int64_t) ppc_result_a * (int64_t) ppc_result_b;
|
|
siproduct = siproduct >> 32;
|
|
ppc_result_d = (uint32_t) siproduct;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_mulhwdot(){
|
|
ppc_grab_regsdab();
|
|
siproduct = (int64_t) ppc_result_a * (int64_t) ppc_result_b;
|
|
siproduct = siproduct >> 32;
|
|
ppc_result_d = (uint32_t) siproduct;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_mullw(){
|
|
ppc_grab_regsdab();
|
|
siproduct = (int64_t) ppc_result_a * (int64_t) ppc_result_b;
|
|
siproduct &= 4294967295;
|
|
ppc_result_d = (uint32_t) siproduct;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_mullwdot(){
|
|
ppc_grab_regsdab();
|
|
siproduct = ppc_result_a * ppc_result_b;
|
|
siproduct &= 4294967295;
|
|
ppc_result_d = (uint32_t) siproduct;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_mullwo(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
siproduct = ppc_result_a * ppc_result_b;
|
|
siproduct &= 4294967295;
|
|
ppc_result_d = (uint32_t) siproduct;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_mullwodot(){
|
|
ppc_grab_regsdab();
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
siproduct = ppc_result_a * ppc_result_b;
|
|
siproduct &= 4294967295;
|
|
ppc_result_d = (uint32_t) siproduct;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_mulli(){
|
|
ppc_grab_regsdasimm();
|
|
int64_t siproduct = (int64_t)((ppc_result_a) * ((int64_t)simm));
|
|
siproduct &= 4294967295;
|
|
ppc_result_d = (uint32_t) siproduct;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
|
|
void ppc_divw(){
|
|
ppc_grab_regsdab();
|
|
|
|
//handle division by zero cases
|
|
if (ppc_result_b == 0){
|
|
ppc_result_d = 0;
|
|
ppc_store_result_regd();
|
|
return;
|
|
}
|
|
else if ((ppc_result_a == 0x80000000) & (ppc_result_b == 0xFFFFFFFF)){
|
|
ppc_result_d = 0;
|
|
ppc_store_result_regd();
|
|
return;
|
|
}
|
|
|
|
sidiv_result = (int32_t) ppc_result_a / (int32_t) ppc_result_b;
|
|
ppc_result_d = (uint32_t) sidiv_result;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_divwdot(){
|
|
ppc_grab_regsdab();
|
|
|
|
//handle division by zero cases
|
|
if (ppc_result_b == 0){
|
|
ppc_result_d = 0;
|
|
ppc_store_result_regd();
|
|
ppc_state.ppc_cr &= 0x1FFFFFFF;
|
|
return;
|
|
}
|
|
else if ((ppc_result_a == 0x80000000) & (ppc_result_b == 0xFFFFFFFF)){
|
|
ppc_result_d = 0;
|
|
ppc_store_result_regd();
|
|
ppc_state.ppc_cr &= 0x1FFFFFFF;
|
|
return;
|
|
}
|
|
|
|
sidiv_result = (int32_t) ppc_result_a / (int32_t) ppc_result_b;
|
|
ppc_result_d = (uint32_t) sidiv_result;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_divwo(){
|
|
ppc_grab_regsdab();
|
|
|
|
//handle division by zero cases
|
|
if (ppc_result_b == 0){
|
|
ppc_result_d = 0;
|
|
ppc_state.ppc_cr |= 0x10000000;
|
|
ppc_store_result_regd();
|
|
return;
|
|
}
|
|
else if ((ppc_result_a == 0x80000000) & (ppc_result_b == 0xFFFFFFFF)){
|
|
ppc_result_d = 0;
|
|
ppc_state.ppc_cr |= 0x10000000;
|
|
ppc_store_result_regd();
|
|
return;
|
|
}
|
|
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
sidiv_result = (int32_t) ppc_result_a / (int32_t) ppc_result_b;
|
|
ppc_result_d = (uint32_t) sidiv_result;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_divwodot(){
|
|
ppc_grab_regsdab();
|
|
|
|
//handle division by zero cases
|
|
if (ppc_result_b == 0){
|
|
ppc_result_d = 0;
|
|
ppc_store_result_regd();
|
|
ppc_state.ppc_cr &= 0x1FFFFFFF;
|
|
ppc_state.ppc_cr |= 0x10000000;
|
|
return;
|
|
}
|
|
else if ((ppc_result_a == 0x80000000) & (ppc_result_b == 0xFFFFFFFF)){
|
|
ppc_result_d = 0;
|
|
ppc_store_result_regd();
|
|
ppc_state.ppc_cr &= 0x1FFFFFFF;
|
|
ppc_state.ppc_cr |= 0x10000000;
|
|
return;
|
|
}
|
|
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
sidiv_result = (int32_t) ppc_result_a / (int32_t) ppc_result_b;
|
|
ppc_result_d = (uint32_t) sidiv_result;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_divwu(){
|
|
ppc_grab_regsdab();
|
|
|
|
//handle division by zero cases
|
|
if (ppc_result_b == 0){
|
|
ppc_result_d = 0;
|
|
ppc_store_result_regd();
|
|
return;
|
|
}
|
|
|
|
uidiv_result = ppc_result_a / ppc_result_b;
|
|
ppc_result_d = uidiv_result;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_divwudot(){
|
|
ppc_grab_regsdab();
|
|
|
|
//handle division by zero cases
|
|
if (ppc_result_b == 0){
|
|
ppc_result_d = 0;
|
|
ppc_store_result_regd();
|
|
ppc_state.ppc_cr &= 0x1FFFFFFF;
|
|
return;
|
|
}
|
|
|
|
uidiv_result = ppc_result_a / ppc_result_b;
|
|
ppc_result_d = uidiv_result;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_divwuo(){
|
|
ppc_grab_regsdab();
|
|
|
|
//handle division by zero cases
|
|
if (ppc_result_b == 0){
|
|
ppc_result_d = 0;
|
|
ppc_state.ppc_cr |= 0x10000000;
|
|
ppc_store_result_regd();
|
|
return;
|
|
}
|
|
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
uidiv_result = ppc_result_a / ppc_result_b;
|
|
ppc_result_d = uidiv_result;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_divwuodot(){
|
|
ppc_grab_regsdab();
|
|
|
|
//handle division by zero cases
|
|
if (ppc_result_b == 0){
|
|
ppc_result_d = 0;
|
|
ppc_store_result_regd();
|
|
ppc_state.ppc_cr &= 0x1FFFFFFF;
|
|
ppc_state.ppc_cr |= 0x10000000;
|
|
return;
|
|
}
|
|
|
|
ppc_setsoov(ppc_result_a, ppc_result_b);
|
|
uidiv_result = ppc_result_a / ppc_result_b;
|
|
ppc_result_d = uidiv_result;
|
|
ppc_changecrf0(ppc_result_d);
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
//Value shifting
|
|
|
|
void ppc_slw(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = (ppc_result_b < 32)?(ppc_result_d << ppc_result_b):0;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_slwdot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = (ppc_result_b < 32)?(ppc_result_d << ppc_result_b):0;
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_srw(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = (ppc_result_b < 32)?(ppc_result_d >> ppc_result_b):0;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_srwdot(){
|
|
ppc_grab_regssab();
|
|
ppc_result_a = (ppc_result_b < 32)?(ppc_result_d >> ppc_result_b):0;
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_sraw(){
|
|
ppc_grab_regssab();
|
|
|
|
if (ppc_result_b > 32){
|
|
ppc_result_a = ((ppc_result_d) > 0x7FFFFFFF)?0xFFFFFFFF:0x0;
|
|
ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0);
|
|
}
|
|
else{
|
|
ppc_result_a = (uint32_t)((int32_t)ppc_result_d >> ppc_result_b);
|
|
ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0);
|
|
}
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_srawdot(){
|
|
ppc_grab_regssab();
|
|
if (ppc_result_b > 32){
|
|
ppc_result_a = ((ppc_result_d) > 0x7FFFFFFF)?0xFFFFFFFF:0x0;
|
|
ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0);
|
|
}
|
|
else{
|
|
ppc_result_a = (uint32_t)((int32_t)ppc_result_d >> ppc_result_b);
|
|
ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0);
|
|
}
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_srawi(){
|
|
ppc_grab_regssa();
|
|
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
|
|
|
ppc_result_a = (uint32_t)((int32_t)ppc_result_d >> rot_sh);
|
|
ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0);
|
|
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_srawidot(){
|
|
ppc_grab_regssa();
|
|
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
|
|
|
ppc_result_a = (uint32_t)((int32_t)ppc_result_d >> rot_sh);
|
|
ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xDFFFFFFF) | (((ppc_result_d) > 0x7FFFFFFF)?0x20000000:0x0);
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_rlwimi(){
|
|
ppc_grab_regssa();
|
|
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
|
rot_mb = (ppc_cur_instruction >> 6) & 31;
|
|
rot_me = (ppc_cur_instruction >> 1) & 31;
|
|
uint32_t step1 = (0xFFFFFFFFUL << (31 - rot_me)) & (0xFFFFFFFFUL >> rot_mb);
|
|
uint32_t step2 = (rot_me < rot_mb)? ~step1 : step1;
|
|
uint32_t step3 = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32-rot_sh)));
|
|
ppc_result_a = (ppc_result_a & ~step2) | (step3 & step2);
|
|
if ((ppc_cur_instruction & 0x01) == 1){
|
|
ppc_changecrf0(ppc_result_a);
|
|
}
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_rlwinm(){
|
|
ppc_grab_regssa();
|
|
rot_sh = (ppc_cur_instruction >> 11) & 31;
|
|
rot_mb = (ppc_cur_instruction >> 6) & 31;
|
|
rot_me = (ppc_cur_instruction >> 1) & 31;
|
|
uint32_t step1 = (0xFFFFFFFFUL << (31 - rot_me)) & (0xFFFFFFFFUL >> rot_mb);
|
|
uint32_t step2 = (rot_me < rot_mb)? ~step1 : step1;
|
|
uint32_t step3 = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32-rot_sh)));
|
|
ppc_result_a = step2 & step3;
|
|
if ((ppc_cur_instruction & 0x01) == 1){
|
|
ppc_changecrf0(ppc_result_a);
|
|
}
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_rlwnm(){
|
|
ppc_grab_regssab();
|
|
rot_mb = (ppc_cur_instruction >> 6) & 31;
|
|
rot_me = (ppc_cur_instruction >> 1) & 31;
|
|
uint32_t step1 = (0xFFFFFFFFUL << (31 - rot_me)) & (0xFFFFFFFFUL >> rot_mb);
|
|
uint32_t step2 = (rot_me < rot_mb)? ~step1 : step1;
|
|
uint32_t step3 = ((ppc_result_d << ppc_result_b) | (ppc_result_d >> (32-ppc_result_b)));
|
|
ppc_result_a = step2 & step3;
|
|
if ((ppc_cur_instruction & 0x01) == 1){
|
|
ppc_changecrf0(ppc_result_a);
|
|
}
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_mfcr(){
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
printf("CR: %x \n", ppc_state.ppc_cr);
|
|
ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_cr;
|
|
}
|
|
|
|
void ppc_mtsr(){
|
|
if ((ppc_state.ppc_msr & 0x4000) == 0){
|
|
reg_s = (ppc_cur_instruction >> 21) & 31;
|
|
grab_sr = (ppc_cur_instruction >> 16) & 15;
|
|
ppc_state.ppc_sr[grab_sr] = ppc_state.ppc_gpr[reg_s];
|
|
}
|
|
}
|
|
|
|
void ppc_mtsrin(){
|
|
if ((ppc_state.ppc_msr & 0x4000) == 0){
|
|
ppc_grab_regssb();
|
|
grab_sr = ppc_result_b >> 28;
|
|
ppc_state.ppc_sr[grab_sr] = ppc_result_d;
|
|
}
|
|
}
|
|
|
|
void ppc_mfsr(){
|
|
if ((ppc_state.ppc_msr & 0x4000) == 0){
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
grab_sr = (ppc_cur_instruction >> 16) & 15;
|
|
ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_sr[grab_sr];
|
|
}
|
|
}
|
|
|
|
void ppc_mfsrin(){
|
|
if ((ppc_state.ppc_msr & 0x4000) == 0){
|
|
ppc_grab_regssb();
|
|
grab_sr = ppc_result_b >> 28;
|
|
ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_sr[grab_sr];
|
|
}
|
|
}
|
|
|
|
void ppc_mfmsr(){
|
|
if ((ppc_state.ppc_msr & 0x4000) == 0){
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_msr;
|
|
}
|
|
}
|
|
|
|
void ppc_mtmsr(){
|
|
//if ((ppc_state.ppc_msr && 0x4000) == 0){
|
|
reg_s = (ppc_cur_instruction >> 21) & 31;
|
|
ppc_state.ppc_msr = ppc_state.ppc_gpr[reg_s];
|
|
msr_status_update();
|
|
//}
|
|
}
|
|
|
|
void ppc_mfspr(){
|
|
uint32_t ref_spr = (((ppc_cur_instruction >> 11) & 31) << 5) | ((ppc_cur_instruction >> 16) & 31);
|
|
//printf("MFSPR SPR REF: %d \n", ref_spr);
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_spr[ref_spr];
|
|
//printf("Contained inside Reg %d: %x \n", reg_d, ppc_state.ppc_gpr[reg_d]);
|
|
}
|
|
|
|
void ppc_mtspr(){
|
|
uint32_t ref_spr = (((ppc_cur_instruction >> 11) & 31) << 5) | ((ppc_cur_instruction >> 16) & 31);
|
|
//printf("MTSPR SPR REF: %d \n", ref_spr);
|
|
reg_s = (ppc_cur_instruction >> 21) & 31;
|
|
//printf("Contained inside Reg %d: %x \n", reg_s, ppc_state.ppc_gpr[reg_s]);
|
|
|
|
if (ref_spr != 287){
|
|
ppc_state.ppc_spr[ref_spr] = ppc_state.ppc_gpr[reg_s];
|
|
}
|
|
|
|
switch(ref_spr){
|
|
//Mirror the TBRs in the SPR range to the user-mode TBRs.
|
|
case 268:
|
|
ppc_state.ppc_tbr[0] = ppc_state.ppc_gpr[reg_s];
|
|
break;
|
|
case 269:
|
|
ppc_state.ppc_tbr[1] = ppc_state.ppc_gpr[reg_s];
|
|
break;
|
|
case 528:
|
|
case 529:
|
|
case 530:
|
|
case 531:
|
|
case 532:
|
|
case 533:
|
|
case 534:
|
|
case 535:
|
|
ibat_update(ref_spr);
|
|
std::cout << "IBAT CHANGED!" <<std::endl;
|
|
break;
|
|
case 536:
|
|
case 537:
|
|
case 538:
|
|
case 539:
|
|
case 540:
|
|
case 541:
|
|
case 542:
|
|
case 543:
|
|
dbat_update(ref_spr);
|
|
std::cout << "DBAT CHANGED!" <<std::endl;
|
|
}
|
|
}
|
|
|
|
void ppc_mftb(){
|
|
uint32_t ref_spr = (((ppc_cur_instruction >> 11) & 31) << 5) | ((ppc_cur_instruction >> 16) & 31);
|
|
reg_d = (ppc_cur_instruction >> 21) & 31;
|
|
switch(ref_spr){
|
|
case 268:
|
|
ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_tbr[0];
|
|
break;
|
|
case 269:
|
|
ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_tbr[1];
|
|
break;
|
|
default:
|
|
std::cout << "Invalid TBR access attempted!" << std::endl;
|
|
}
|
|
}
|
|
|
|
void ppc_mtcrf(){
|
|
uint32_t cr_mask = 0;
|
|
ppc_grab_regssa();
|
|
crm = ((ppc_cur_instruction >> 12) & 255);
|
|
//check this
|
|
cr_mask += (crm & 128) ? 0xF0000000 : 0x00000000;
|
|
cr_mask += (crm & 64) ? 0x0F000000 : 0x00000000;
|
|
cr_mask += (crm & 32) ? 0x00F00000 : 0x00000000;
|
|
cr_mask += (crm & 16) ? 0x000F0000 : 0x00000000;
|
|
cr_mask += (crm & 8) ? 0x0000F000 : 0x00000000;
|
|
cr_mask += (crm & 4) ? 0x00000F00 : 0x00000000;
|
|
cr_mask += (crm & 2) ? 0x000000F0 : 0x00000000;
|
|
cr_mask += (crm & 1) ? 0x0000000F : 0x00000000;
|
|
ppc_state.ppc_cr = (ppc_result_d & cr_mask) | (ppc_state.ppc_cr & ~(cr_mask));
|
|
}
|
|
|
|
void ppc_mcrxr(){
|
|
crf_d = (ppc_cur_instruction >> 23) & 7;
|
|
crf_d = crf_d << 2;
|
|
ppc_state.ppc_cr = (ppc_state.ppc_cr & ~(0xF0000000 >> crf_d)) | ((ppc_state.ppc_spr[1] & 0xF0000000) >> crf_d);
|
|
ppc_state.ppc_spr[1] &= 0x0FFFFFFF;
|
|
}
|
|
|
|
void ppc_extsb(){
|
|
ppc_grab_regssa();
|
|
ppc_result_a = (ppc_result_d < 0x80)?(ppc_result_d & 0x000000FF):(0xFFFFFF00 | (ppc_result_d & 0x000000FF));
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_extsbdot(){
|
|
ppc_grab_regssa();
|
|
ppc_result_a = (ppc_result_d < 0x80)?(ppc_result_d & 0x000000FF):(0xFFFFFF00 | (ppc_result_d & 0x000000FF));
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_extsh(){
|
|
ppc_grab_regssa();
|
|
ppc_result_a = (ppc_result_d < 0x8000)?(ppc_result_d & 0x0000FFFF):(0xFFFF0000 | (ppc_result_d & 0x0000FFFF));
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_extshdot(){
|
|
ppc_grab_regssa();
|
|
ppc_result_a = (ppc_result_d < 0x8000)?(ppc_result_d & 0x0000FFFF):(0xFFFF0000 | (ppc_result_d & 0x0000FFFF));
|
|
ppc_changecrf0(ppc_result_a);
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
//Branching Instructions
|
|
|
|
//The last two bytes of the instruction are used for determining how the branch happens.
|
|
//The middle 24 bytes are the 24-bit address to use for branching to.
|
|
|
|
|
|
void ppc_b(){
|
|
uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC);
|
|
adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000 + quick_test);
|
|
ppc_next_instruction_address = (uint32_t)(ppc_state.ppc_pc + adr_li);
|
|
grab_branch = 1;
|
|
}
|
|
|
|
void ppc_bl(){
|
|
uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC);
|
|
adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000 + quick_test);
|
|
ppc_next_instruction_address = (uint32_t)(ppc_state.ppc_pc + adr_li);
|
|
ppc_state.ppc_spr[8] = (uint32_t)(ppc_state.ppc_pc + 4);
|
|
grab_branch = 1;
|
|
}
|
|
|
|
void ppc_ba(){
|
|
uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC);
|
|
adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000 + quick_test);
|
|
ppc_next_instruction_address = adr_li;
|
|
grab_branch = 1;
|
|
}
|
|
|
|
void ppc_bla(){
|
|
uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC);
|
|
adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000 + quick_test);
|
|
ppc_next_instruction_address = adr_li;
|
|
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
|
|
grab_branch = 1;
|
|
}
|
|
|
|
void ppc_bc()
|
|
{
|
|
uint32_t ctr_ok;
|
|
uint32_t cnd_ok;
|
|
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
|
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
|
int32_t br_bd = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFC));
|
|
|
|
if (!(br_bo & 0x04)){
|
|
(ppc_state.ppc_spr[9])--; /* decrement CTR */
|
|
}
|
|
ctr_ok = (br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) == !(br_bo & 0x02));
|
|
cnd_ok = (br_bo & 0x10) || (!(ppc_state.ppc_cr & (0x80000000 >> br_bi)) == !(br_bo & 0x08));
|
|
|
|
if (ctr_ok && cnd_ok){
|
|
ppc_next_instruction_address = (ppc_state.ppc_pc + br_bd);
|
|
grab_branch = 1;
|
|
}
|
|
}
|
|
|
|
void ppc_bca()
|
|
{
|
|
uint32_t ctr_ok;
|
|
uint32_t cnd_ok;
|
|
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
|
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
|
int32_t br_bd = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFC));
|
|
|
|
if (!(br_bo & 0x04)){
|
|
(ppc_state.ppc_spr[9])--; /* decrement CTR */
|
|
}
|
|
ctr_ok = (br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) == !(br_bo & 0x02));
|
|
cnd_ok = (br_bo & 0x10) || (!(ppc_state.ppc_cr & (0x80000000 >> br_bi)) == !(br_bo & 0x08));
|
|
|
|
if (ctr_ok && cnd_ok){
|
|
ppc_next_instruction_address = br_bd;
|
|
grab_branch = 1;
|
|
}
|
|
}
|
|
|
|
void ppc_bcl()
|
|
{
|
|
uint32_t ctr_ok;
|
|
uint32_t cnd_ok;
|
|
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
|
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
|
int32_t br_bd = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFC));
|
|
|
|
if (!(br_bo & 0x04)){
|
|
(ppc_state.ppc_spr[9])--; /* decrement CTR */
|
|
}
|
|
ctr_ok = (br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) == !(br_bo & 0x02));
|
|
cnd_ok = (br_bo & 0x10) || (!(ppc_state.ppc_cr & (0x80000000 >> br_bi)) == !(br_bo & 0x08));
|
|
|
|
if (ctr_ok && cnd_ok){
|
|
ppc_next_instruction_address = (ppc_state.ppc_pc + br_bd);
|
|
grab_branch = 1;
|
|
}
|
|
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
|
|
}
|
|
|
|
void ppc_bcla()
|
|
{
|
|
uint32_t ctr_ok;
|
|
uint32_t cnd_ok;
|
|
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
|
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
|
int32_t br_bd = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFC));
|
|
|
|
if (!(br_bo & 0x04)){
|
|
(ppc_state.ppc_spr[9])--; /* decrement CTR */
|
|
}
|
|
ctr_ok = (br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) == !(br_bo & 0x02));
|
|
cnd_ok = (br_bo & 0x10) || (!(ppc_state.ppc_cr & (0x80000000 >> br_bi)) == !(br_bo & 0x08));
|
|
|
|
if (ctr_ok && cnd_ok){
|
|
ppc_next_instruction_address = br_bd;
|
|
grab_branch = 1;
|
|
}
|
|
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
|
|
}
|
|
|
|
void ppc_bcctr()
|
|
{
|
|
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
|
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
|
|
|
uint32_t cnd_ok = (br_bo & 0x10) || (!(ppc_state.ppc_cr & (0x80000000 >> br_bi)) == !(br_bo & 0x08));
|
|
|
|
if (cnd_ok){
|
|
ppc_next_instruction_address = (ppc_state.ppc_spr[9] & 0xFFFFFFFC);
|
|
grab_branch = 1;
|
|
}
|
|
}
|
|
|
|
void ppc_bcctrl()
|
|
{
|
|
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
|
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
|
|
|
uint32_t cnd_ok = (br_bo & 0x10) || (!(ppc_state.ppc_cr & (0x80000000 >> br_bi)) == !(br_bo & 0x08));
|
|
|
|
if (cnd_ok){
|
|
ppc_next_instruction_address = (ppc_state.ppc_spr[9] & 0xFFFFFFFC);
|
|
grab_branch = 1;
|
|
}
|
|
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
|
|
}
|
|
|
|
void ppc_bclr()
|
|
{
|
|
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
|
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
|
uint32_t ctr_ok;
|
|
uint32_t cnd_ok;
|
|
|
|
if (!(br_bo & 0x04)){
|
|
(ppc_state.ppc_spr[9])--; /* decrement CTR */
|
|
}
|
|
ctr_ok = (br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) == !(br_bo & 0x02));
|
|
cnd_ok = (br_bo & 0x10) || (!(ppc_state.ppc_cr & (0x80000000 >> br_bi)) == !(br_bo & 0x08));
|
|
|
|
if (ctr_ok && cnd_ok){
|
|
ppc_next_instruction_address = (ppc_state.ppc_spr[8] & 0xFFFFFFFC);
|
|
grab_branch = 1;
|
|
}
|
|
}
|
|
|
|
void ppc_bclrl()
|
|
{
|
|
uint32_t br_bo = (ppc_cur_instruction >> 21) & 31;
|
|
uint32_t br_bi = (ppc_cur_instruction >> 16) & 31;
|
|
uint32_t ctr_ok;
|
|
uint32_t cnd_ok;
|
|
|
|
if (!(br_bo & 0x04)){
|
|
(ppc_state.ppc_spr[9])--; /* decrement CTR */
|
|
}
|
|
ctr_ok = (br_bo & 0x04) || ((ppc_state.ppc_spr[9] != 0) == !(br_bo & 0x02));
|
|
cnd_ok = (br_bo & 0x10) || (!(ppc_state.ppc_cr & (0x80000000 >> br_bi)) == !(br_bo & 0x08));
|
|
|
|
if (ctr_ok && cnd_ok){
|
|
ppc_next_instruction_address = (ppc_state.ppc_spr[8] & 0xFFFFFFFC);
|
|
grab_branch = 1;
|
|
}
|
|
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
|
|
}
|
|
//Compare Instructions
|
|
|
|
void ppc_cmp(){
|
|
//if (!((ppc_cur_instruction >> 21) && 0x1)){
|
|
crf_d = (ppc_cur_instruction >> 23) & 7;
|
|
crf_d = crf_d << 2;
|
|
ppc_grab_regssab();
|
|
xercon = (ppc_state.ppc_spr[1] & 0x80000000) >> 3;
|
|
cmp_c = (((int32_t)ppc_result_a) == ((int32_t)ppc_result_b)) ? 0x20000000 : (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) ? 0x40000000 : 0x80000000;
|
|
ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
|
|
//}
|
|
//else{
|
|
// printf("Warning: Invalid CMP Instruction.");
|
|
//}
|
|
}
|
|
|
|
void ppc_cmpi(){
|
|
#ifdef CHECK_INVALID
|
|
if (ppc_cur_instruction & 0x200000) {
|
|
printf("WARNING: invalid CMPI instruction form (L=1)!\n");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
crf_d = (ppc_cur_instruction >> 23) & 7;
|
|
crf_d = crf_d << 2;
|
|
ppc_grab_regsasimm();
|
|
xercon = (ppc_state.ppc_spr[1] & 0x80000000) >> 3;
|
|
cmp_c = (((int32_t)ppc_result_a) == simm) ? 0x20000000 : (((int32_t)ppc_result_a) > simm) ? 0x40000000 : 0x80000000;
|
|
ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
|
|
}
|
|
|
|
void ppc_cmpl(){
|
|
#ifdef CHECK_INVALID
|
|
if (ppc_cur_instruction & 0x200000) {
|
|
printf("WARNING: invalid CMPL instruction form (L=1)!\n");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
crf_d = (ppc_cur_instruction >> 23) & 7;
|
|
crf_d = crf_d << 2;
|
|
ppc_grab_regssab();
|
|
xercon = (ppc_state.ppc_spr[1] & 0x80000000) >> 3;
|
|
cmp_c = (ppc_result_a == ppc_result_b) ? 0x20000000 : (ppc_result_a > ppc_result_b) ? 0x40000000 : 0x80000000;
|
|
ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
|
|
}
|
|
|
|
void ppc_cmpli(){
|
|
#ifdef CHECK_INVALID
|
|
if (ppc_cur_instruction & 0x200000) {
|
|
printf("WARNING: invalid CMPLI instruction form (L=1)!\n");
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
crf_d = (ppc_cur_instruction >> 23) & 7;
|
|
crf_d = crf_d << 2;
|
|
ppc_grab_regssauimm();
|
|
xercon = (ppc_state.ppc_spr[1] & 0x80000000) >> 3;
|
|
cmp_c = (ppc_result_a == uimm) ? 0x20000000 : (ppc_result_a > uimm) ? 0x40000000 : 0x80000000;
|
|
ppc_state.ppc_cr = ((ppc_state.ppc_cr & ~(0xf0000000 >> crf_d)) | ((cmp_c + xercon) >> crf_d));
|
|
}
|
|
|
|
//Condition Register Changes
|
|
|
|
void ppc_crand(){
|
|
ppc_grab_regsdab();
|
|
if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) & (ppc_state.ppc_cr && (0x80000000 >> reg_b))){
|
|
ppc_state.ppc_cr |= (0x80000000 >> reg_d);
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr &= ~(0x80000000 >> reg_d);
|
|
}
|
|
}
|
|
void ppc_crandc(){
|
|
ppc_grab_regsdab();
|
|
if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) & !(ppc_state.ppc_cr && (0x80000000 >> reg_b))){
|
|
ppc_state.ppc_cr |= (0x80000000 >> reg_d);
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr &= ~(0x80000000 >> reg_d);
|
|
}
|
|
}
|
|
void ppc_creqv(){
|
|
ppc_grab_regsdab();
|
|
if (!((ppc_state.ppc_cr && (0x80000000 >> reg_a)) ^ (ppc_state.ppc_cr && (0x80000000 >> reg_b)))){
|
|
ppc_state.ppc_cr |= (0x80000000 >> reg_d);
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr &= ~(0x80000000 >> reg_d);
|
|
}
|
|
}
|
|
void ppc_crnand(){
|
|
ppc_grab_regsdab();
|
|
if (!((ppc_state.ppc_cr && (0x80000000 >> reg_a)) & (ppc_state.ppc_cr && (0x80000000 >> reg_b)))){
|
|
ppc_state.ppc_cr |= (0x80000000 >> reg_d);
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr &= ~(0x80000000 >> reg_d);
|
|
}
|
|
}
|
|
void ppc_crnor(){
|
|
ppc_grab_regsdab();
|
|
if (!((ppc_state.ppc_cr && (0x80000000 >> reg_a)) | (ppc_state.ppc_cr && (0x80000000 >> reg_b)))){
|
|
ppc_state.ppc_cr |= (0x80000000 >> reg_d);
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr &= ~(0x80000000 >> reg_d);
|
|
}
|
|
}
|
|
|
|
void ppc_cror(){
|
|
ppc_grab_regsdab();
|
|
if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) | (ppc_state.ppc_cr && (0x80000000 >> reg_b))){
|
|
ppc_state.ppc_cr |= (0x80000000 >> reg_d);
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr &= ~(0x80000000 >> reg_d);
|
|
}
|
|
}
|
|
void ppc_crorc(){
|
|
ppc_grab_regsdab();
|
|
if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) | !(ppc_state.ppc_cr && (0x80000000 >> reg_b))){
|
|
ppc_state.ppc_cr |= (0x80000000 >> reg_d);
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr &= ~(0x80000000 >> reg_d);
|
|
}
|
|
}
|
|
void ppc_crxor(){
|
|
ppc_grab_regsdab();
|
|
if ((ppc_state.ppc_cr && (0x80000000 >> reg_a)) ^ (ppc_state.ppc_cr && (0x80000000 >> reg_b))){
|
|
ppc_state.ppc_cr |= (0x80000000 >> reg_d);
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr &= ~(0x80000000 >> reg_d);
|
|
}
|
|
}
|
|
|
|
//Processor MGMT Fns.
|
|
|
|
void ppc_rfi(){
|
|
uint32_t new_srr1_val = (ppc_state.ppc_spr[27] & 0x87C0FF73);
|
|
uint32_t new_msr_val = (ppc_state.ppc_msr & ~(0x87C0FF73));
|
|
ppc_state.ppc_msr = (new_msr_val | new_srr1_val) & 0xFFFBFFFF;
|
|
ppc_next_instruction_address = ppc_state.ppc_spr[26] & 0xFFFFFFFC;
|
|
|
|
grab_return = true;
|
|
}
|
|
|
|
void ppc_sc(){
|
|
ppc_exception_handler(0x0C00, 0x20000);
|
|
}
|
|
|
|
void ppc_tw(){
|
|
reg_a = (ppc_cur_instruction >> 11) & 31;
|
|
reg_b = (ppc_cur_instruction >> 16) & 31;
|
|
ppc_to = (ppc_cur_instruction >> 21) & 31;
|
|
if ((((int32_t)ppc_state.ppc_gpr[reg_a] < (int32_t)ppc_state.ppc_gpr[reg_b]) & (ppc_to & 0x10)) || \
|
|
(((int32_t)ppc_state.ppc_gpr[reg_a] > (int32_t)ppc_state.ppc_gpr[reg_b]) & (ppc_to & 0x08)) || \
|
|
(((int32_t)ppc_state.ppc_gpr[reg_a] == (int32_t)ppc_state.ppc_gpr[reg_b]) & (ppc_to & 0x04)) || \
|
|
((ppc_state.ppc_gpr[reg_a] < ppc_state.ppc_gpr[reg_b]) & (ppc_to & 0x02)) || \
|
|
((ppc_state.ppc_gpr[reg_a] > ppc_state.ppc_gpr[reg_b]) & (ppc_to & 0x01))){
|
|
ppc_exception_handler(0x0700, 0x20000);
|
|
}
|
|
}
|
|
|
|
void ppc_twi(){
|
|
simm = (int32_t)((int16_t)((ppc_cur_instruction) & 65535));
|
|
reg_b = (ppc_cur_instruction >> 16) & 31;
|
|
ppc_to = (ppc_cur_instruction >> 21) & 31;
|
|
if ((((int32_t)ppc_state.ppc_gpr[reg_a] < simm) & (ppc_to & 0x10)) || \
|
|
(((int32_t)ppc_state.ppc_gpr[reg_a] > simm) & (ppc_to & 0x08)) || \
|
|
(((int32_t)ppc_state.ppc_gpr[reg_a] == simm) & (ppc_to & 0x04)) || \
|
|
((ppc_state.ppc_gpr[reg_a] < (uint32_t)simm) & (ppc_to & 0x02)) || \
|
|
((ppc_state.ppc_gpr[reg_a] > (uint32_t)simm) & (ppc_to & 0x01))){
|
|
ppc_exception_handler(0x0700, 0x20000);
|
|
}
|
|
}
|
|
|
|
void ppc_eieio(){
|
|
std::cout << "Oops. Placeholder for eieio." << std::endl;
|
|
}
|
|
|
|
void ppc_isync(){
|
|
std::cout << "Oops. Placeholder for isync." << std::endl;
|
|
}
|
|
|
|
void ppc_sync(){
|
|
std::cout << "Oops. Placeholder for sync." << std::endl;
|
|
}
|
|
|
|
void ppc_icbi(){
|
|
std::cout << "Oops. Placeholder for icbi." << std::endl;
|
|
}
|
|
|
|
void ppc_dcbf(){
|
|
std::cout << "Oops. Placeholder for dcbf." << std::endl;
|
|
}
|
|
|
|
void ppc_dcbi(){
|
|
std::cout << "Oops. Placeholder for dcbi." << std::endl;
|
|
}
|
|
|
|
void ppc_dcbst(){
|
|
std::cout << "Oops. Placeholder for dcbst." << std::endl;
|
|
}
|
|
|
|
void ppc_dcbt(){
|
|
//Not needed, the HDI reg is touched to no-op this instruction.
|
|
return;
|
|
}
|
|
|
|
void ppc_dcbtst(){
|
|
//Not needed, the HDI reg is touched to no-op this instruction.
|
|
return;
|
|
}
|
|
|
|
void ppc_dcbz(){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
if (!(ppc_state.ppc_pc % 32) && (ppc_state.ppc_pc < 0xFFFFFFE0)){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickinsert_translate(0, ppc_effective_address, 4);
|
|
address_quickinsert_translate(0, (ppc_effective_address + 4), 4);
|
|
address_quickinsert_translate(0, (ppc_effective_address + 8), 4);
|
|
address_quickinsert_translate(0, (ppc_effective_address + 12), 4);
|
|
address_quickinsert_translate(0, (ppc_effective_address + 16), 4);
|
|
address_quickinsert_translate(0, (ppc_effective_address + 20), 4);
|
|
address_quickinsert_translate(0, (ppc_effective_address + 24), 4);
|
|
address_quickinsert_translate(0, (ppc_effective_address + 28), 4);
|
|
}
|
|
else{
|
|
ppc_exception_handler(0x0600, 0x00000);
|
|
}
|
|
}
|
|
|
|
//Integer Load and Store Functions
|
|
|
|
void ppc_stb(){
|
|
ppc_grab_regssa();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
#ifdef EXHAUSTIVE_DEBUG
|
|
printf("STB Storage Area: %x \n",ppc_effective_address);
|
|
#endif // EXHAUSTIVE_DEBUG
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 1);
|
|
}
|
|
|
|
void ppc_stbx(){
|
|
ppc_grab_regssab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 1);
|
|
}
|
|
|
|
void ppc_stbu(){
|
|
ppc_grab_regssa();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
if (reg_a != 0){
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 1);
|
|
}
|
|
}
|
|
|
|
void ppc_stbux(){
|
|
ppc_grab_regssab();
|
|
if (reg_a != 0){
|
|
ppc_effective_address = ppc_result_a + reg_b;
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 1);
|
|
}
|
|
else{
|
|
ppc_exception_handler(0x07000, 0x20000);
|
|
}
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_sth(){
|
|
ppc_grab_regssa();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 2);
|
|
}
|
|
|
|
void ppc_sthu(){
|
|
ppc_grab_regssa();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 2);
|
|
}
|
|
|
|
void ppc_sthux(){
|
|
ppc_grab_regssab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 2);
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_sthx(){
|
|
ppc_grab_regssab();
|
|
if (reg_a != 0){
|
|
ppc_effective_address = ppc_result_a + ppc_result_b;
|
|
}
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 2);
|
|
}
|
|
|
|
void ppc_sthbrx(){
|
|
ppc_grab_regssab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
ppc_result_d = (uint32_t)(rev_endian16((uint16_t)ppc_result_d));
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 2);
|
|
}
|
|
|
|
void ppc_stw(){
|
|
ppc_grab_regssa();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 4);
|
|
}
|
|
|
|
void ppc_stwx(){
|
|
ppc_grab_regssab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 4);
|
|
}
|
|
|
|
void ppc_stwcx(){
|
|
//PLACEHOLDER CODE FOR STWCX - We need to check for reserve memory
|
|
ppc_grab_regssab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
if (ppc_state.ppc_reserve){
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 4);
|
|
ppc_state.ppc_cr |= (ppc_state.ppc_spr[1] & 0x80000000) ? 0x30000000 : 0x20000000;
|
|
ppc_state.ppc_reserve = false;
|
|
}
|
|
else{
|
|
ppc_state.ppc_cr |= (ppc_state.ppc_spr[1] & 0x80000000) ? 0x10000000 : 0;
|
|
}
|
|
}
|
|
|
|
void ppc_stwu(){
|
|
ppc_grab_regssa();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 4);
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_stwux(){
|
|
ppc_grab_regssab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 4);
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_stwbrx(){
|
|
ppc_grab_regssab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
printf("STWBRX Storage Area: %x \n",ppc_effective_address);
|
|
ppc_result_d = rev_endian32(ppc_result_d);
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 4);
|
|
}
|
|
|
|
void ppc_stmw(){
|
|
ppc_grab_regssa();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
//How many words to store in memory - using a do-while for this
|
|
do{
|
|
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 4);
|
|
ppc_effective_address +=4;
|
|
reg_d++;
|
|
}while (reg_d < 32);
|
|
}
|
|
|
|
void ppc_lbz(){
|
|
ppc_grab_regsda();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
//printf("LBZ Storage Area: %x \n",ppc_effective_address);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_lbzu(){
|
|
ppc_grab_regsda();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
if ((reg_a != reg_d) || reg_a != 0){
|
|
ppc_effective_address = ppc_result_a + grab_d;
|
|
}
|
|
else{
|
|
ppc_exception_handler(0x0700, 0x20000);
|
|
}
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_regd();
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_lbzx(){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_lbzux(){
|
|
ppc_grab_regsdab();
|
|
if ((reg_a != reg_d) || reg_a != 0){
|
|
ppc_effective_address = ppc_result_a + ppc_result_b;
|
|
}
|
|
else{
|
|
ppc_exception_handler(0x0700, 0x20000);
|
|
}
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_regd();
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
|
|
void ppc_lhz(){
|
|
ppc_grab_regsda();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
address_quickgrab_translate(ppc_effective_address, 2);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_lhzu(){
|
|
ppc_grab_regsda();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = ppc_result_a + grab_d;
|
|
address_quickgrab_translate(ppc_effective_address, 2);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_regd();
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_lhzx(){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickgrab_translate(ppc_effective_address, 2);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_lhzux(){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = ppc_result_a + ppc_result_b;
|
|
address_quickgrab_translate(ppc_effective_address, 2);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_regd();
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_lha(){
|
|
ppc_grab_regsda();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(uint32_t)(ppc_result_a + grab_d);
|
|
address_quickgrab_translate(ppc_effective_address, 2);
|
|
uint16_t go_this = (uint16_t)return_value;
|
|
if (go_this & 0x8000){
|
|
ppc_result_d = 0xFFFF0000 | (uint32_t)return_value;
|
|
ppc_store_result_regd();
|
|
}
|
|
else{
|
|
ppc_result_d = (uint32_t)return_value;
|
|
ppc_store_result_regd();
|
|
}
|
|
return_value = 0;
|
|
}
|
|
|
|
void ppc_lhau(){
|
|
ppc_grab_regsda();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(uint32_t)(ppc_result_a + grab_d);
|
|
address_quickgrab_translate(ppc_effective_address, 2);
|
|
uint16_t go_this = (uint16_t)return_value;
|
|
if (go_this & 0x8000){
|
|
ppc_result_d = 0xFFFF0000 | (uint32_t)return_value;
|
|
ppc_store_result_regd();
|
|
}
|
|
else{
|
|
ppc_result_d = (uint32_t)return_value;
|
|
ppc_store_result_regd();
|
|
}
|
|
return_value = 0;
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_lhaux(){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickgrab_translate(ppc_effective_address, 2);
|
|
uint16_t go_this = (uint16_t)return_value;
|
|
if (go_this & 0x8000){
|
|
ppc_result_d = 0xFFFF0000 | (uint32_t)return_value;
|
|
ppc_store_result_regd();
|
|
}
|
|
else{
|
|
ppc_result_d = (uint32_t)return_value;
|
|
ppc_store_result_regd();
|
|
}
|
|
return_value = 0;
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_lhax(){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickgrab_translate(ppc_effective_address, 2);
|
|
uint16_t go_this = (uint16_t)return_value;
|
|
if (go_this & 0x8000){
|
|
ppc_result_d = 0xFFFF0000 | (uint32_t)return_value;
|
|
ppc_store_result_regd();
|
|
}
|
|
else{
|
|
ppc_result_d = (uint32_t)return_value;
|
|
ppc_store_result_regd();
|
|
}
|
|
return_value = 0;
|
|
}
|
|
|
|
void ppc_lhbrx(){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickgrab_translate(ppc_effective_address, 2);
|
|
ppc_result_d = (uint32_t)(rev_endian16((uint16_t)ppc_result_d));
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_lwz(){
|
|
ppc_grab_regsda();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
address_quickgrab_translate(ppc_effective_address, 4);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_lwbrx(){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
printf("LWBRX Storage Area: %x \n",ppc_effective_address);
|
|
address_quickgrab_translate(ppc_effective_address, 4);
|
|
ppc_result_d = rev_endian32(return_value);
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_lwzu(){
|
|
ppc_grab_regsda();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
if ((reg_a != reg_d) || reg_a != 0){
|
|
ppc_effective_address = ppc_result_a + grab_d;
|
|
}
|
|
else{
|
|
ppc_exception_handler(0x0700, 0x20000);
|
|
}
|
|
address_quickgrab_translate(ppc_effective_address, 4);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_lwzx(){
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
address_quickgrab_translate(ppc_effective_address, 4);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_lwzux(){
|
|
ppc_grab_regsdab();
|
|
if ((reg_a != reg_d) || reg_a != 0){
|
|
ppc_effective_address = ppc_result_a + ppc_result_b;
|
|
}
|
|
else{
|
|
ppc_exception_handler(0x0700, 0x20000);
|
|
}
|
|
address_quickgrab_translate(ppc_effective_address, 4);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_result_a = ppc_effective_address;
|
|
ppc_store_result_regd();
|
|
ppc_store_result_rega();
|
|
}
|
|
|
|
void ppc_lwarx(){
|
|
//Placeholder - Get the reservation of memory implemented!
|
|
ppc_grab_regsdab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
ppc_state.ppc_reserve = true;
|
|
address_quickgrab_translate(ppc_effective_address, 4);
|
|
ppc_result_d = return_value;
|
|
return_value = 0;
|
|
ppc_store_result_regd();
|
|
}
|
|
|
|
void ppc_lmw(){
|
|
ppc_grab_regsda();
|
|
grab_d = (uint32_t)((int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)));
|
|
ppc_effective_address = (reg_a == 0)?grab_d:(ppc_result_a + grab_d);
|
|
//How many words to load in memory - using a do-while for this
|
|
do{
|
|
address_quickgrab_translate(ppc_effective_address, 4);
|
|
ppc_state.ppc_gpr[reg_d] = return_value;
|
|
return_value = 0;
|
|
ppc_effective_address +=4;
|
|
reg_d++;
|
|
}while (reg_d < 32);
|
|
}
|
|
|
|
void ppc_lswi(){
|
|
ppc_grab_regsda();
|
|
ppc_effective_address = ppc_result_a;
|
|
grab_inb = (ppc_cur_instruction >> 11) & 31;
|
|
grab_inb = grab_inb % 32 == 0 ? 32 : grab_inb;
|
|
|
|
uint32_t shift_times = 0;
|
|
|
|
while (grab_inb > 0){
|
|
switch(shift_times){
|
|
case 0:
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_state.ppc_gpr[reg_d] = (ppc_result_d & 0x00FFFFFF) | (return_value << 24);
|
|
ppc_store_result_regd();
|
|
return_value = 0;
|
|
break;
|
|
case 1:
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = (ppc_result_d & 0xFF00FFFF) | (return_value << 16);
|
|
ppc_store_result_regd();
|
|
return_value = 0;
|
|
break;
|
|
case 2:
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = (ppc_result_d & 0xFFFF00FF) | (return_value << 8);
|
|
ppc_store_result_regd();
|
|
return_value = 0;
|
|
break;
|
|
case 3:
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = (ppc_result_d & 0xFFFFFF00) | return_value;
|
|
ppc_store_result_regd();
|
|
return_value = 0;
|
|
break;
|
|
default:
|
|
printf("Something really horrible happened with lswi.");
|
|
}
|
|
if (shift_times == 3){
|
|
shift_times = 0;
|
|
reg_d = (reg_d + 1) & 0x1F;
|
|
}
|
|
else{
|
|
shift_times++;
|
|
}
|
|
return_value = 0;
|
|
ppc_effective_address++;
|
|
grab_inb--;
|
|
}
|
|
}
|
|
|
|
void ppc_lswx(){
|
|
ppc_grab_regsdab();
|
|
//Invalid instruction forms
|
|
if ((ppc_result_d == 0) && (ppc_result_a == 0)){
|
|
ppc_exception_handler(0x0700, 0x100000);
|
|
}
|
|
if ((ppc_result_d == ppc_result_a) || (ppc_result_a == ppc_result_b)){
|
|
ppc_exception_handler(0x0700, 0x100000);
|
|
}
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
grab_inb = ppc_state.ppc_spr[1] & 127;
|
|
uint32_t shift_times = 0;
|
|
while (grab_inb > 0){
|
|
switch(shift_times){
|
|
case 0:
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = (ppc_result_d & 0x00FFFFFF) | (return_value << 24);
|
|
ppc_store_result_regd();
|
|
return_value = 0;
|
|
break;
|
|
case 1:
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = (ppc_result_d & 0xFF00FFFF) | (return_value << 16);
|
|
ppc_store_result_regd();
|
|
return_value = 0;
|
|
break;
|
|
case 2:
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = (ppc_result_d & 0xFFFF00FF) | (return_value << 8);
|
|
ppc_store_result_regd();
|
|
return_value = 0;
|
|
break;
|
|
case 3:
|
|
address_quickgrab_translate(ppc_effective_address, 1);
|
|
ppc_result_d = (ppc_result_d & 0xFFFFFF00) | return_value;
|
|
ppc_store_result_regd();
|
|
return_value = 0;
|
|
break;
|
|
default:
|
|
printf("Something really horrible happened with lswx.");
|
|
}
|
|
if (shift_times == 3){
|
|
shift_times = 0;
|
|
reg_d = (reg_d + 1) & 0x1F;
|
|
}
|
|
else{
|
|
shift_times++;
|
|
}
|
|
return_value = 0;
|
|
ppc_effective_address++;
|
|
grab_inb--;
|
|
}
|
|
|
|
}
|
|
|
|
void ppc_stswi(){
|
|
ppc_grab_regssa();
|
|
ppc_effective_address = (reg_a == 0)?0:ppc_result_a;
|
|
grab_inb = (ppc_cur_instruction >> 11) & 31;
|
|
grab_inb = grab_inb % 32 == 0 ? 32 : grab_inb;
|
|
uint32_t shift_times = 0;
|
|
while (grab_inb > 0){
|
|
switch(shift_times){
|
|
case 0:
|
|
strwrd_replace_value = (ppc_result_d >> 24);
|
|
address_quickinsert_translate(strwrd_replace_value, ppc_effective_address, 1);
|
|
break;
|
|
case 1:
|
|
strwrd_replace_value = (ppc_result_d >> 16);
|
|
address_quickinsert_translate(strwrd_replace_value, ppc_effective_address, 1);
|
|
break;
|
|
case 2:
|
|
strwrd_replace_value = (ppc_result_d >> 8);
|
|
address_quickinsert_translate(strwrd_replace_value, ppc_effective_address, 1);
|
|
break;
|
|
case 3:
|
|
strwrd_replace_value = (ppc_result_d);
|
|
address_quickinsert_translate(strwrd_replace_value, ppc_effective_address, 1);
|
|
break;
|
|
default:
|
|
printf("Something really horrible happened with stswi.");
|
|
}
|
|
if (shift_times == 3){
|
|
shift_times = 0;
|
|
reg_s = (reg_s + 1) & 0x1F;
|
|
}
|
|
else{
|
|
shift_times++;
|
|
}
|
|
return_value = 0;
|
|
ppc_effective_address++;
|
|
grab_inb--;
|
|
}
|
|
}
|
|
|
|
void ppc_stswx(){
|
|
ppc_grab_regssab();
|
|
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
|
|
grab_inb = ppc_state.ppc_spr[1] & 127;
|
|
uint32_t shift_times = 0;
|
|
while (grab_inb > 0){
|
|
switch(shift_times){
|
|
case 0:
|
|
strwrd_replace_value = (ppc_result_d >> 24);
|
|
address_quickinsert_translate(strwrd_replace_value, ppc_effective_address, 1);
|
|
break;
|
|
case 1:
|
|
strwrd_replace_value = (ppc_result_d >> 16);
|
|
address_quickinsert_translate(strwrd_replace_value, ppc_effective_address, 1);
|
|
break;
|
|
case 2:
|
|
strwrd_replace_value = (ppc_result_d >> 8);
|
|
address_quickinsert_translate(strwrd_replace_value, ppc_effective_address, 1);
|
|
break;
|
|
case 3:
|
|
strwrd_replace_value = (ppc_result_d);
|
|
address_quickinsert_translate(strwrd_replace_value, ppc_effective_address, 1);
|
|
break;
|
|
default:
|
|
printf("Something really horrible happened with stswx.");
|
|
}
|
|
if (shift_times == 3){
|
|
shift_times = 0;
|
|
reg_s = (reg_s + 1) & 0x1F;
|
|
}
|
|
else{
|
|
shift_times++;
|
|
}
|
|
return_value = 0;
|
|
ppc_effective_address++;
|
|
grab_inb--;
|
|
}
|
|
}
|
|
|
|
//TLB Instructions
|
|
|
|
void ppc_tlbie(){
|
|
/**
|
|
reg_b = (ppc_cur_instruction >> 11) & 31;
|
|
uint32_t vps = ppc_state.ppc_gpr[reg_b] & 0xFFFF000;
|
|
**/
|
|
printf("Placeholder for tlbie \n");
|
|
}
|
|
|
|
void ppc_tlbia(){
|
|
printf("Placeholder for tlbia \n");
|
|
}
|
|
|
|
void ppc_tlbld(){
|
|
printf("Placeholder for tlbld - 603 only \n");
|
|
}
|
|
|
|
void ppc_tlbli(){
|
|
printf("Placeholder for tlbli - 603 only \n");
|
|
}
|