Refactored floating point emulation

Refactored for better 64-bit value loading and storing. I also added missing opcodes.
This commit is contained in:
dingusdev 2020-01-25 19:30:55 -07:00
parent a3601f224c
commit 7c6d875ec8
9 changed files with 1358 additions and 1040 deletions

View File

@ -17,265 +17,265 @@
#include <cmath>
#include <limits>
void power_abs(){
void power_abs() {
ppc_grab_regsda();
if (ppc_result_a == 0x80000000){
if (ppc_result_a == 0x80000000) {
ppc_result_d = ppc_result_a;
}
else{
else {
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_store_result_regd();
}
void power_absdot(){
void power_absdot() {
ppc_grab_regsda();
if (ppc_result_a == 0x80000000){
if (ppc_result_a == 0x80000000) {
ppc_result_d = ppc_result_a;
}
else{
else {
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_changecrf0(ppc_result_d);
ppc_store_result_regd();
}
void power_abso(){
void power_abso() {
ppc_grab_regsda();
if (ppc_result_a == 0x80000000){
if (ppc_result_a == 0x80000000) {
ppc_result_d = ppc_result_a;
ppc_state.ppc_spr[1] |= 0x40000000;
}
else{
else {
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_store_result_regd();
}
void power_absodot(){
void power_absodot() {
ppc_grab_regsda();
if (ppc_result_a == 0x80000000){
if (ppc_result_a == 0x80000000) {
ppc_result_d = ppc_result_a;
ppc_state.ppc_spr[1] |= 0x40000000;
}
else{
else {
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
}
ppc_changecrf0(ppc_result_d);
ppc_store_result_regd();
}
void power_clcs(){
void power_clcs() {
ppc_grab_regsda();
switch(reg_a){
case 12:
case 13:
case 14:
case 15:
ppc_result_d = 65535;
break;
default:
ppc_result_d = 0;
switch (reg_a) {
case 12:
case 13:
case 14:
case 15:
ppc_result_d = 65535;
break;
default:
ppc_result_d = 0;
}
ppc_store_result_regd();
}
void power_clcsdot(){
switch(reg_a){
case 12:
case 13:
case 14:
case 15:
ppc_result_d = 65535;
break;
default:
ppc_result_d = 0;
void power_clcsdot() {
switch (reg_a) {
case 12:
case 13:
case 14:
case 15:
ppc_result_d = 65535;
break;
default:
ppc_result_d = 0;
}
ppc_changecrf0(ppc_result_d);
printf("Does RC do anything here? (TODO) \n");
ppc_store_result_regd();
}
void power_div(){
void power_div() {
ppc_grab_regsdab();
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
ppc_store_result_regd();
}
void power_divdot(){
void power_divdot() {
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
}
void power_divo(){
void power_divo() {
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
}
void power_divodot(){
void power_divodot() {
ppc_result_d = (ppc_result_a | ppc_state.ppc_spr[0]) / ppc_result_b;
ppc_state.ppc_spr[0] = (ppc_result_a | ppc_state.ppc_spr[0]) % ppc_result_b;
}
void power_divs(){
void power_divs() {
ppc_grab_regsdab();
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
ppc_state.ppc_spr[0] = (ppc_result_a % ppc_result_b);
ppc_store_result_regd();
}
void power_divsdot(){
void power_divsdot() {
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
ppc_state.ppc_spr[0] = (ppc_result_a % ppc_result_b);
}
void power_divso(){
void power_divso() {
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
ppc_state.ppc_spr[0] = (ppc_result_a % ppc_result_b);
}
void power_divsodot(){
void power_divsodot() {
ppc_result_d = ppc_result_a / ppc_result_b;
ppc_state.ppc_spr[0] =(ppc_result_a % ppc_result_b);
ppc_state.ppc_spr[0] = (ppc_result_a % ppc_result_b);
}
void power_doz(){
void power_doz() {
ppc_grab_regsdab();
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
ppc_result_d = 0;
}
else{
else {
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
}
ppc_store_result_rega();
}
void power_dozdot(){
void power_dozdot() {
ppc_grab_regsdab();
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
ppc_result_d = 0;
}
else{
else {
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
}
ppc_changecrf0(ppc_result_d);
ppc_store_result_rega();
}
void power_dozo(){
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
void power_dozo() {
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
ppc_result_d = 0;
}
else{
else {
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
}
}
void power_dozodot(){
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)){
void power_dozodot() {
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
ppc_result_d = 0;
}
else{
else {
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
}
}
void power_dozi(){
void power_dozi() {
ppc_grab_regsdab();
if (((int32_t)ppc_result_a) > simm){
if (((int32_t)ppc_result_a) > simm) {
ppc_result_d = 0;
}
else{
else {
ppc_result_d = ~ppc_result_a + simm + 1;
}
ppc_store_result_rega();
}
void power_lscbx(){
void power_lscbx() {
ppc_grab_regsdab();
uint32_t bytes_copied = 0;
bool match_found = false;
uint32_t shift_amount = 0;
uint8_t byte_compared = (uint8_t)((ppc_state.ppc_spr[1] & 0xFF00) >> 8);
if ((ppc_state.ppc_spr[1] & 0x7f) == 0){
if ((ppc_state.ppc_spr[1] & 0x7f) == 0) {
return;
}
uint32_t bytes_to_load = (ppc_state.ppc_spr[1] & 0x7f) + 1;
ppc_effective_address = (reg_a == 0)?ppc_result_b:ppc_result_a + ppc_result_b;
do{
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
do {
ppc_effective_address++;
bytes_to_load--;
if (match_found == false){
switch(shift_amount){
case 0:
address_quickgrab_translate(ppc_effective_address, 1);
ppc_result_d = (ppc_result_d & 0x00FFFFFF) | (return_value << 24);
ppc_store_result_regd();
break;
case 1:
address_quickgrab_translate(ppc_effective_address, 1);
ppc_result_d = (ppc_result_d & 0xFF00FFFF) | (return_value << 16);
ppc_store_result_regd();
break;
case 2:
address_quickgrab_translate(ppc_effective_address, 1);
ppc_result_d = (ppc_result_d & 0xFFFF00FF) | (return_value << 8);
ppc_store_result_regd();
break;
case 3:
address_quickgrab_translate(ppc_effective_address, 1);
ppc_result_d = (ppc_result_d & 0xFFFFFF00) | return_value;
ppc_store_result_regd();
break;
if (match_found == false) {
switch (shift_amount) {
case 0:
address_grab8bit_translate(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0x00FFFFFF) | ((uint32_t)return_value << 24);
ppc_store_result_regd();
break;
case 1:
address_grab8bit_translate(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0xFF00FFFF) | ((uint32_t)return_value << 16);
ppc_store_result_regd();
break;
case 2:
address_grab8bit_translate(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0xFFFF00FF) | ((uint32_t)return_value << 8);
ppc_store_result_regd();
break;
case 3:
address_grab8bit_translate(ppc_effective_address);
ppc_result_d = (ppc_result_d & 0xFFFFFF00) | (uint32_t)return_value;
ppc_store_result_regd();
break;
}
bytes_copied++;
}
if (((uint8_t)return_value) == byte_compared){
if (((uint8_t)return_value) == byte_compared) {
break;
}
return_value = 0;
if (shift_amount == 3){
if (shift_amount == 3) {
shift_amount = 0;
reg_d = (reg_d + 1) & 0x1F;
}
else{
else {
shift_amount++;
}
}while (bytes_to_load > 0);
} while (bytes_to_load > 0);
ppc_state.ppc_spr[1] = (ppc_state.ppc_spr[1] & 0xFFFFFF80) | bytes_copied;
ppc_store_result_regd();
}
void power_lscbxdot(){
printf("OOPS! Placeholder!!! \n");
void power_lscbxdot() {
printf("OOPS! Placeholder!!! \n");
}
void power_maskg(){
void power_maskg() {
ppc_grab_regssab();
uint32_t mask_start = ppc_result_d & 31;
uint32_t mask_end = ppc_result_b & 31;
uint32_t insert_mask = 0;
if (mask_start < (mask_end + 1)){
for (uint32_t i = mask_start; i < mask_end; i++){
if (mask_start < (mask_end + 1)) {
for (uint32_t i = mask_start; i < mask_end; i++) {
insert_mask |= (0x80000000 >> i);
}
}
else if (mask_start == (mask_end + 1)){
else if (mask_start == (mask_end + 1)) {
insert_mask = 0xFFFFFFFF;
}
else{
else {
insert_mask = 0xFFFFFFFF;
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++){
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++) {
insert_mask &= (~(0x80000000 >> i));
}
}
@ -284,23 +284,23 @@ void power_maskg(){
ppc_store_result_rega();
}
void power_maskgdot(){
void power_maskgdot() {
ppc_grab_regssab();
uint32_t mask_start = ppc_result_d & 31;
uint32_t mask_end = ppc_result_b & 31;
uint32_t insert_mask = 0;
if (mask_start < (mask_end + 1)){
for (uint32_t i = mask_start; i < mask_end; i++){
if (mask_start < (mask_end + 1)) {
for (uint32_t i = mask_start; i < mask_end; i++) {
insert_mask |= (0x80000000 >> i);
}
}
else if (mask_start == (mask_end + 1)){
else if (mask_start == (mask_end + 1)) {
insert_mask = 0xFFFFFFFF;
}
else{
else {
insert_mask = 0xFFFFFFFF;
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++){
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++) {
insert_mask &= (~(0x80000000 >> i));
}
}
@ -309,40 +309,40 @@ void power_maskgdot(){
ppc_store_result_rega();
}
void power_maskir(){
void power_maskir() {
ppc_grab_regssab();
uint32_t mask_insert = ppc_result_a;
uint32_t insert_rot = 0x80000000;
do{
if (ppc_result_b & insert_rot){
do {
if (ppc_result_b & insert_rot) {
mask_insert &= ~insert_rot;
mask_insert |= (ppc_result_d & insert_rot);
}
insert_rot = insert_rot>> 1;
}while(insert_rot > 0);
insert_rot = insert_rot >> 1;
} while (insert_rot > 0);
ppc_result_a = (ppc_result_d & ppc_result_b);
ppc_store_result_rega();
}
void power_maskirdot(){
void power_maskirdot() {
ppc_grab_regssab();
uint32_t mask_insert = ppc_result_a;
uint32_t insert_rot = 0x80000000;
do{
if (ppc_result_b & insert_rot){
do {
if (ppc_result_b & insert_rot) {
mask_insert &= ~insert_rot;
mask_insert |= (ppc_result_d & insert_rot);
}
insert_rot = insert_rot>> 1;
}while(insert_rot > 0);
insert_rot = insert_rot >> 1;
} while (insert_rot > 0);
ppc_result_a = (ppc_result_d & ppc_result_b);
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_mul(){
void power_mul() {
ppc_grab_regsdab();
uint64_t product;
@ -353,7 +353,7 @@ void power_mul(){
}
void power_muldot(){
void power_muldot() {
ppc_grab_regsdab();
uint64_t product;
@ -365,7 +365,7 @@ void power_muldot(){
}
void power_mulo(){
void power_mulo() {
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
@ -374,7 +374,7 @@ void power_mulo(){
}
void power_mulodot(){
void power_mulodot() {
uint64_t product;
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
@ -383,42 +383,42 @@ void power_mulodot(){
}
void power_nabs(){
void power_nabs() {
ppc_grab_regsda();
ppc_result_d = (0x80000000 | ppc_result_a);
ppc_store_result_regd();
}
void power_nabsdot(){
void power_nabsdot() {
ppc_result_d = (0x80000000 | ppc_result_a);
}
void power_nabso(){
void power_nabso() {
ppc_result_d = (0x80000000 | ppc_result_a);
}
void power_nabsodot(){
void power_nabsodot() {
ppc_result_d = (0x80000000 | ppc_result_a);
}
void power_rlmi(){
void power_rlmi() {
ppc_grab_regssab();
unsigned rot_mb = (ppc_cur_instruction >> 6) & 31;
unsigned rot_me = (ppc_cur_instruction >> 1) & 31;
uint32_t rot_amt = ppc_result_b & 31;
uint32_t insert_mask = 0;
if (rot_mb < (rot_me + 1)){
for (uint32_t i = rot_mb; i < rot_me; i++){
if (rot_mb < (rot_me + 1)) {
for (uint32_t i = rot_mb; i < rot_me; i++) {
insert_mask |= (0x80000000 >> i);
}
}
else if (rot_mb == (rot_me + 1)){
else if (rot_mb == (rot_me + 1)) {
insert_mask = 0xFFFFFFFF;
}
else{
else {
insert_mask = 0xFFFFFFFF;
for (uint32_t i = (rot_me + 1); i < (rot_mb - 1); i++){
for (uint32_t i = (rot_me + 1); i < (rot_mb - 1); i++) {
insert_mask &= (~(0x80000000 >> i));
}
}
@ -428,34 +428,34 @@ void power_rlmi(){
ppc_store_result_rega();
}
void power_rrib(){
void power_rrib() {
ppc_grab_regssab();
if (ppc_result_d & 0x80000000){
if (ppc_result_d & 0x80000000) {
ppc_result_a |= (0x80000000 >> ppc_result_b);
}
else{
else {
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
}
ppc_store_result_rega();
}
void power_rribdot(){
void power_rribdot() {
ppc_grab_regssab();
if (ppc_result_d & 0x80000000){
if (ppc_result_d & 0x80000000) {
ppc_result_a |= (0x80000000 >> ppc_result_b);
}
else{
else {
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
}
ppc_changecrf0(ppc_result_a);
ppc_store_result_rega();
}
void power_sle(){
void power_sle() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
@ -464,11 +464,11 @@ void power_sle(){
ppc_store_result_rega();
}
void power_sledot(){
void power_sledot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
@ -478,18 +478,18 @@ void power_sledot(){
ppc_store_result_rega();
}
void power_sleq(){
void power_sleq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
uint32_t insert_start = ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -500,18 +500,18 @@ void power_sleq(){
ppc_store_result_rega();
}
void power_sleqdot(){
void power_sleqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
uint32_t insert_start = ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -523,18 +523,18 @@ void power_sleqdot(){
ppc_store_result_rega();
}
void power_sliq(){
void power_sliq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -545,18 +545,18 @@ void power_sliq(){
ppc_store_result_rega();
}
void power_sliqdot(){
void power_sliqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -568,18 +568,18 @@ void power_sliqdot(){
ppc_store_result_rega();
}
void power_slliq(){
void power_slliq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -590,18 +590,18 @@ void power_slliq(){
ppc_store_result_rega();
}
void power_slliqdot(){
void power_slliqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -613,43 +613,43 @@ void power_slliqdot(){
ppc_store_result_rega();
}
void power_sllq(){
printf("OOPS! Placeholder!!! \n");
void power_sllq() {
printf("OOPS! Placeholder!!! \n");
}
void power_sllqdot(){
printf("OOPS! Placeholder!!! \n");
void power_sllqdot() {
printf("OOPS! Placeholder!!! \n");
}
void power_slq(){
printf("OOPS! Placeholder!!! \n");
void power_slq() {
printf("OOPS! Placeholder!!! \n");
}
void power_slqdot(){
printf("OOPS! Placeholder!!! \n");
void power_slqdot() {
printf("OOPS! Placeholder!!! \n");
}
void power_sraiq(){
printf("OOPS! Placeholder!!! \n");
void power_sraiq() {
printf("OOPS! Placeholder!!! \n");
}
void power_sraiqdot(){
printf("OOPS! Placeholder!!! \n");
void power_sraiqdot() {
printf("OOPS! Placeholder!!! \n");
}
void power_sraq(){
printf("OOPS! Placeholder!!! \n");
void power_sraq() {
printf("OOPS! Placeholder!!! \n");
}
void power_sraqdot(){
printf("OOPS! Placeholder!!! \n");
void power_sraqdot() {
printf("OOPS! Placeholder!!! \n");
}
void power_sre(){
void power_sre() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
@ -658,11 +658,11 @@ void power_sre(){
ppc_store_result_rega();
}
void power_sredot(){
void power_sredot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
uint32_t rot_amt = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_amt; i--){
for (uint32_t i = 31; i > rot_amt; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
@ -672,26 +672,26 @@ void power_sredot(){
ppc_store_result_rega();
}
void power_srea(){
printf("OOPS! Placeholder!!! \n");
void power_srea() {
printf("OOPS! Placeholder!!! \n");
}
void power_sreadot(){
printf("OOPS! Placeholder!!! \n");
void power_sreadot() {
printf("OOPS! Placeholder!!! \n");
}
void power_sreq(){
void power_sreq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_sh; i--){
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -702,18 +702,18 @@ void power_sreq(){
ppc_store_result_rega();
}
void power_sreqdot(){
void power_sreqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = ppc_result_b & 31;
for (uint32_t i = 31; i > rot_sh; i--){
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -725,18 +725,18 @@ void power_sreqdot(){
ppc_store_result_rega();
}
void power_sriq(){
void power_sriq() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -747,18 +747,18 @@ void power_sriq(){
ppc_store_result_rega();
}
void power_sriqdot(){
void power_sriqdot() {
ppc_grab_regssa();
uint32_t insert_mask = 0;
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
for (uint32_t i = 31; i > rot_sh; i--){
for (uint32_t i = 31; i > rot_sh; i--) {
insert_mask |= (1 << i);
}
uint32_t insert_start= ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
uint32_t insert_end = ppc_state.ppc_spr[0];
for (int i = 0; i < 32; i++){
if (insert_mask & (1 << i)){
for (int i = 0; i < 32; i++) {
if (insert_mask & (1 << i)) {
insert_end &= ~(1 << i);
insert_end |= (insert_start & (1 << i));
}
@ -770,26 +770,26 @@ void power_sriqdot(){
ppc_store_result_rega();
}
void power_srliq(){
printf("OOPS! Placeholder!!! \n");
void power_srliq() {
printf("OOPS! Placeholder!!! \n");
}
void power_srliqdot(){
printf("OOPS! Placeholder!!! \n");
void power_srliqdot() {
printf("OOPS! Placeholder!!! \n");
}
void power_srlq(){
printf("OOPS! Placeholder!!! \n");
void power_srlq() {
printf("OOPS! Placeholder!!! \n");
}
void power_srlqdot(){
printf("OOPS! Placeholder!!! \n");
void power_srlqdot() {
printf("OOPS! Placeholder!!! \n");
}
void power_srq(){
printf("OOPS! Placeholder!!! \n");
void power_srq() {
printf("OOPS! Placeholder!!! \n");
}
void power_srqdot(){
printf("OOPS! Placeholder!!! \n");
}
void power_srqdot() {
printf("OOPS! Placeholder!!! \n");
}

View File

@ -24,12 +24,12 @@
//Uncomment this to use Visual Studio built-in functions.
//#define USE_VS_BUILTINS 1
enum endian_switch {big_end = 0, little_end = 1};
enum endian_switch { big_end = 0, little_end = 1 };
typedef void (*PPCOpcode)(void);
union FPR_storage {
double dbl64_r; // double floating-point representation
double dbl64_r = 0.0; // double floating-point representation
uint64_t int64_r; // double integer representation
};
@ -48,16 +48,16 @@ fpscr = FP Status and Condition Register
**/
typedef struct struct_ppc_state {
FPR_storage ppc_fpr [32];
uint32_t ppc_pc; //Referred as the CIA in the PPC manual
uint32_t ppc_gpr [32];
uint32_t ppc_cr;
uint32_t ppc_fpscr;
uint32_t ppc_tbr [2];
uint32_t ppc_spr [1024];
uint32_t ppc_msr;
uint32_t ppc_sr [16];
bool ppc_reserve; //reserve bit used for lwarx and stcwx
FPR_storage ppc_fpr[32] = { 0 };
uint32_t ppc_pc = 0; //Referred as the CIA in the PPC manual
uint32_t ppc_gpr[32] = { 0 };
uint32_t ppc_cr = 0;
uint32_t ppc_fpscr = 0;
uint32_t ppc_tbr[2] = { 0 };
uint32_t ppc_spr[1024] = { 0 };
uint32_t ppc_msr = 0;
uint32_t ppc_sr[16] = { 0 };
bool ppc_reserve = 0; //reserve bit used for lwarx and stcwx
} SetPRS;
extern SetPRS ppc_state;
@ -101,7 +101,7 @@ SUPERVISOR MODEL
536 - 543 are the Data BAT registers
**/
extern uint32_t return_value; //used for loading from memory
extern uint64_t return_value; //used for loading from memory
extern uint32_t opcode_value; //used for interpreting opcodes
extern uint32_t ram_size_set;
@ -163,7 +163,7 @@ extern uint64_t ppc_result64_d;
/* The precise end of a basic block. */
enum class BB_end_kind {
BB_NONE = 0, /* no basic block end is reached */
BB_NONE = 0, /* no basic block end is reached */
BB_BRANCH = 1, /* a branch instruction is encountered */
BB_EXCEPTION, /* an exception is occured */
BB_RFI /* the rfi instruction is encountered */
@ -181,7 +181,7 @@ enum class Except_Type {
EXC_NO_FPU,
EXC_DECR,
EXC_SYSCALL = 12,
EXC_TRACE = 13
EXC_TRACE = 13
};
//extern bool bb_end;
@ -265,13 +265,13 @@ void ppc_fp_changecrf1();
void ppc_tbr_update();
[[noreturn]] void ppc_exception_handler(Except_Type exception_type,
uint32_t srr1_bits);
uint32_t srr1_bits);
//MEMORY DECLARATIONS
extern MemCtrlBase *mem_ctrl_instance;
extern MemCtrlBase* mem_ctrl_instance;
extern unsigned char * machine_sysram_mem;
extern unsigned char * machine_sysrom_mem;
extern unsigned char* machine_sysram_mem;
extern unsigned char* machine_sysrom_mem;
//The functions used by the PowerPC processor
extern void ppc_bcctr();
@ -490,12 +490,15 @@ extern void ppc_xoris();
extern void ppc_lfs();
extern void ppc_lfsu();
extern void ppc_lfsux();
extern void ppc_lfsx();
extern void ppc_lfsux();
extern void ppc_lfd();
extern void ppc_lfdu();
extern void ppc_lfdx();
extern void ppc_lfdux();
extern void ppc_stfs();
extern void ppc_stfsu();
extern void ppc_stfsx();
extern void ppc_stfsux();
extern void ppc_stfd();
extern void ppc_stfdu();
@ -647,4 +650,4 @@ extern void ppc_exec(void);
extern void ppc_exec_single(void);
extern void ppc_exec_until(uint32_t goal_addr);
#endif /* PPCEMU_H */
#endif /* PPCEMU_H */

View File

@ -104,10 +104,13 @@ static std::unordered_map<uint16_t, PPCOpcode> SubOpcode31Grabber = {
{1083, &power_maskirdot}, {1104, &ppc_subfo}, {1105, &ppc_subfodot},
{1132, &ppc_tlbsync},
{1134, &ppc_lfsux}, {1190, &ppc_mfsr}, {1194, &ppc_lswi},
{1196, &ppc_sync}, {1232, &ppc_nego}, {1233, &ppc_negodot},
{1238, &power_mulo}, {1239, &power_mulodot}, {1300, &ppc_addeo},
{1196, &ppc_sync}, {1198, &ppc_lfdx},
{1232, &ppc_nego}, {1233, &ppc_negodot},
{1238, &power_mulo}, {1239, &power_mulodot},
{1262, &ppc_lfdux}, {1300, &ppc_addeo},
{1301, &ppc_addeodot}, {1318, &ppc_mfsrin}, {1322, &ppc_stswx},
{1324, &ppc_stwbrx}, {1328, &power_srq}, {1329, &power_srqdot},
{1324, &ppc_stwbrx}, {1326, &ppc_stfsx},
{1328, &power_srq}, {1329, &power_srqdot},
{1330, &power_sre}, {1331, &power_sredot}, {1390, &ppc_stfsux},
{1392, &power_sriq}, {1393, &power_sriqdot}, {1428, &ppc_addzeo},
{1429, &ppc_addzeodot}, {1450, &ppc_stswi}, {1454, &ppc_stfdx},
@ -270,7 +273,7 @@ static std::unordered_map<uint16_t, PPCOpcode> SubOpcode63Grabber = {
{ 239, &ppc_fseldot}, { 242, &ppc_fmult}, { 243, &ppc_fmultdot},
{ 248, &ppc_fmsub}, { 249, &ppc_fmsubdot}, { 250, &ppc_fmadd},
{ 251, &ppc_fmadddot}, { 252, &ppc_fnmsub}, { 253, &ppc_fnmsubdot},
{ 254, &ppc_fnmadd}, { 255, &ppc_fnmadddot}, { 268, &ppc_mtfsfi},
{ 254, &ppc_fnmadd}, { 255, &ppc_fnmadddot}, { 268, &ppc_mtfsfi},
{ 272, &ppc_fnabs}, { 273, &ppc_fnabsdot},
{ 302, &ppc_fsel}, { 303, &ppc_fseldot},
{ 306, &ppc_fmult}, { 307, &ppc_fmultdot}, { 312, &ppc_fmsub},
@ -391,20 +394,20 @@ static std::unordered_map<uint16_t, PPCOpcode> SubOpcode63Grabber = {
/** Opcode decoding functions. */
void ppc_illegalop(){
void ppc_illegalop() {
uint8_t illegal_code = ppc_cur_instruction >> 26;
uint32_t grab_it = (uint32_t) illegal_code;
uint32_t grab_it = (uint32_t)illegal_code;
printf("Illegal opcode reported: %d Report this! \n", grab_it);
exit(-1);
}
void ppc_illegalsubop31(){
void ppc_illegalsubop31() {
uint16_t illegal_subcode = ppc_cur_instruction & 2047;
uint32_t grab_it = (uint32_t) illegal_subcode;
uint32_t grab_it = (uint32_t)illegal_subcode;
printf("Illegal subopcode for 31 reported: %d Report this! \n", grab_it);
}
void ppc_opcode4(){
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;
@ -412,83 +415,83 @@ void ppc_opcode4(){
exit(0);
}
void ppc_opcode16(){
void ppc_opcode16() {
SubOpcode16Grabber[ppc_cur_instruction & 3]();
}
void ppc_opcode18(){
void ppc_opcode18() {
SubOpcode18Grabber[ppc_cur_instruction & 3]();
}
void ppc_opcode19(){
void ppc_opcode19() {
uint16_t subop_grab = ppc_cur_instruction & 2047;
#ifdef EXHAUSTIVE_DEBUG
#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){
if (SubOpcode19Grabber.count(subop_grab) == 1) {
SubOpcode19Grabber[subop_grab]();
}
else{
else {
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
}
#else
#else
SubOpcode19Grabber[subop_grab]();
#endif // EXHAUSTIVE_DEBUG
#endif // EXHAUSTIVE_DEBUG
}
void ppc_opcode31(){
void ppc_opcode31() {
uint16_t subop_grab = ppc_cur_instruction & 2047;
#ifdef EXHAUSTIVE_DEBUG
#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){
if (SubOpcode31Grabber.count(subop_grab) == 1) {
SubOpcode31Grabber[subop_grab]();
}
else{
else {
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
}
#else
#else
SubOpcode31Grabber[subop_grab]();
#endif // EXHAUSTIVE_DEBUG
#endif // EXHAUSTIVE_DEBUG
}
void ppc_opcode59(){
void ppc_opcode59() {
uint16_t subop_grab = ppc_cur_instruction & 2047;
#ifdef EXHAUSTIVE_DEBUG
#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){
if (SubOpcode59Grabber.count(subop_grab) == 1) {
SubOpcode59Grabber[subop_grab]();
}
else{
else {
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
}
#else
#else
SubOpcode59Grabber[subop_grab]();
#endif // EXHAUSTIVE_DEBUG
#endif // EXHAUSTIVE_DEBUG
}
void ppc_opcode63(){
void ppc_opcode63() {
uint16_t subop_grab = ppc_cur_instruction & 2047;
#ifdef EXHAUSTIVE_DEBUG
#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){
if (SubOpcode63Grabber.count(subop_grab) == 1) {
SubOpcode63Grabber[subop_grab]();
}
else{
else {
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
}
#else
#else
SubOpcode63Grabber[subop_grab]();
#endif // EXHAUSTIVE_DEBUG
#endif // EXHAUSTIVE_DEBUG
}
void ppc_main_opcode(){
void ppc_main_opcode() {
//Grab the main opcode
uint8_t ppc_mainop = (ppc_cur_instruction >> 26) & 63;
OpcodeGrabber[ppc_mainop]();
@ -498,23 +501,23 @@ void ppc_main_opcode(){
void ppc_tbr_update()
{
clock_t clock_test_current = clock();
uint32_t test_clock = ((uint32_t) (clock_test_current - clock_test_begin)) / CLOCKS_PER_SEC;
if (test_clock){
if (ppc_state.ppc_tbr[0] != 0xFFFFFFFF){
uint32_t test_clock = ((uint32_t)(clock_test_current - clock_test_begin)) / CLOCKS_PER_SEC;
if (test_clock) {
if (ppc_state.ppc_tbr[0] != 0xFFFFFFFF) {
ppc_state.ppc_tbr[0]++;
}
else{
else {
ppc_state.ppc_tbr[0] = 0;
if (ppc_state.ppc_tbr[1] !=0xFFFFFFFF){
if (ppc_state.ppc_tbr[1] != 0xFFFFFFFF) {
ppc_state.ppc_tbr[1]++;
}
else{
else {
ppc_state.ppc_tbr[1] = 0;
}
}
clock_test_begin = clock();
//Placeholder Decrementing Code
if(ppc_state.ppc_spr[22] > 0){
if (ppc_state.ppc_spr[22] > 0) {
ppc_state.ppc_spr[22]--;
}
}
@ -524,22 +527,22 @@ void ppc_tbr_update()
#if 0
void ppc_exec()
{
while (power_on){
while (power_on) {
//printf("PowerPC Address: %x \n", ppc_state.ppc_pc);
quickinstruction_translate(ppc_state.ppc_pc);
ppc_main_opcode();
if (grab_branch & !grab_exception){
if (grab_branch & !grab_exception) {
ppc_state.ppc_pc = ppc_next_instruction_address;
grab_branch = 0;
ppc_tbr_update();
}
else if (grab_return | grab_exception){
else if (grab_return | grab_exception) {
ppc_state.ppc_pc = ppc_next_instruction_address;
grab_exception = 0;
grab_return = 0;
ppc_tbr_update();
}
else{
else {
ppc_state.ppc_pc += 4;
ppc_tbr_update();
}
@ -549,7 +552,7 @@ void ppc_exec()
void ppc_exec()
{
uint32_t bb_start_la, page_start;
uint8_t *pc_real;
uint8_t* pc_real;
/* start new basic block */
bb_start_la = ppc_state.ppc_pc;
@ -581,13 +584,15 @@ again:
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
page_start = bb_start_la & 0xFFFFF000;
pc_real = quickinstruction_translate(bb_start_la);
} else {
}
else {
pc_real += (int)bb_start_la - (int)ppc_state.ppc_pc;
ppc_set_cur_instruction(pc_real);
}
ppc_state.ppc_pc = bb_start_la;
bb_kind = BB_end_kind::BB_NONE;
} else {
}
else {
ppc_state.ppc_pc += 4;
pc_real += 4;
ppc_set_cur_instruction(pc_real);
@ -634,7 +639,8 @@ void ppc_exec_single()
if (bb_kind != BB_end_kind::BB_NONE) {
ppc_state.ppc_pc = ppc_next_instruction_address;
bb_kind = BB_end_kind::BB_NONE;
} else {
}
else {
ppc_state.ppc_pc += 4;
}
timebase_counter += 1;
@ -670,7 +676,7 @@ void ppc_exec_until(uint32_t goal_addr)
void ppc_exec_until(uint32_t goal_addr)
{
uint32_t bb_start_la, page_start;
uint8_t *pc_real;
uint8_t* pc_real;
/* start new basic block */
bb_start_la = ppc_state.ppc_pc;
@ -702,13 +708,15 @@ again:
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
page_start = bb_start_la & 0xFFFFF000;
pc_real = quickinstruction_translate(bb_start_la);
} else {
}
else {
pc_real += (int)bb_start_la - (int)ppc_state.ppc_pc;
ppc_set_cur_instruction(pc_real);
}
ppc_state.ppc_pc = bb_start_la;
bb_kind = BB_end_kind::BB_NONE;
} else {
}
else {
ppc_state.ppc_pc += 4;
pc_real += 4;
ppc_set_cur_instruction(pc_real);
@ -721,4 +729,4 @@ void ppc_init()
{
clock_test_begin = clock();
timebase_counter = 0;
}
}

View File

@ -242,6 +242,8 @@ bool ppc_confirm_inf_nan(uint64_t input_a, uint64_t input_b, bool is_single, uin
return true;
}
break;
default:
return false;
}
}
else {
@ -280,8 +282,11 @@ bool ppc_confirm_inf_nan(uint64_t input_a, uint64_t input_b, bool is_single, uin
return true;
}
break;
default:
return false;
}
}
return false;
}
@ -773,7 +778,7 @@ void ppc_fsqrtsdot() {
void ppc_frsqrte() {
ppc_grab_regsfpdb(false);
double testd2 = (double)ppc_result64_b;
for (int i = 0; i < 10; i++){
for (int i = 0; i < 10; i++) {
testd2 = testd2 * (1.5 - (testd2 * .5) * testd2 * testd2);
}
ppc_dblresult64_d = testd2;
@ -796,8 +801,8 @@ void ppc_frsqrtedot() {
void ppc_frsp() {
ppc_grab_regsfpdb(false);
double testd2 = (double)ppc_result64_b;
float testf2 = (float) testd2;
ppc_result64_d = (double) testf2;
float testf2 = (float)testd2;
ppc_dblresult64_d = (double)testf2;
ppc_store_dfpresult(false);
}
@ -805,7 +810,7 @@ void ppc_frspdot() {
ppc_grab_regsfpdb(false);
double testd2 = (double)ppc_result64_b;
float testf2 = (float)testd2;
ppc_result64_d = (double)testf2;
ppc_dblresult64_d = (double)testf2;
ppc_store_dfpresult(false);
ppc_changecrf1();
}
@ -829,45 +834,43 @@ void ppc_fresdot() {
void ppc_fctiw() {
//PLACEHOLDER!
/*ppc_grab_regsfpdiab();
double testd1 = (double)ppc_result64_b;
ppc_grab_regsfpdiab(false);
ppc_result_d = (uint32_t)(testd1);
ppc_result_d = (uint32_t)(ppc_dblresult64_d);
ppc_store_result_regd();
ppc_changecrf1(); */
}
void ppc_fctiwdot() {
//PLACEHOLDER!
/*ppc_grab_regsfpdiab();
double testd1 = (double)ppc_result64_b;
ppc_grab_regsfpdiab(false);
ppc_result_d = (uint32_t)(testd1);
ppc_result_d = (uint32_t)(ppc_dblresult64_d);
ppc_store_result_regd(); */
ppc_store_result_regd();
ppc_changecrf1();
}
void ppc_fctiwz() {
//PLACEHOLDER!
/*ppc_grab_regsfpdiab();
ppc_grab_regsfpdiab(false);
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();
ppc_grab_regsfpdiab(false);
double testd1 = (double)ppc_result64_a;
ppc_result_d = (uint32_t)(testd1);
ppc_store_result_regd();*/
ppc_store_result_regd();
ppc_changecrf1();
}
//Floating Point Store and Load
@ -876,7 +879,7 @@ void ppc_lfs() {
ppc_grab_regsfpdia(true);
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
address_quickgrab_translate(ppc_effective_address, 4);
address_grab32bit_translate(ppc_effective_address);
ppc_result64_d = (uint64_t)return_value;
ppc_store_dfpresult(true);
}
@ -884,132 +887,175 @@ void ppc_lfs() {
void ppc_lfsu() {
ppc_grab_regsfpdia(true);
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
address_quickgrab_translate(ppc_effective_address, 4);
ppc_result64_d = (uint64_t)return_value;
ppc_result_a = ppc_effective_address;
ppc_store_dfpresult(true);
ppc_store_result_rega();
if (reg_a == 0) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
address_grab32bit_translate(ppc_effective_address);
ppc_result64_d = (uint64_t)return_value;
ppc_result_a = ppc_effective_address;
ppc_store_dfpresult(true);
ppc_store_result_rega();
}
else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
void ppc_lfsx() {
ppc_grab_regsfpdiab(true);
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
address_quickgrab_translate(ppc_effective_address, 4);
address_grab32bit_translate(ppc_effective_address);
ppc_result64_d = (uint64_t)return_value;
ppc_store_dfpresult(true);
}
void ppc_lfsux() {
ppc_grab_regsfpdiab(true);
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
address_quickgrab_translate(ppc_effective_address, 4);
ppc_result64_d = (uint64_t)return_value;
ppc_result_a = ppc_effective_address;
ppc_store_dfpresult(true);
ppc_store_result_rega();
if (reg_a == 0) {
ppc_effective_address = ppc_result_a + ppc_result_b;
address_grab32bit_translate(ppc_effective_address);
ppc_result64_d = (uint64_t)return_value;
ppc_result_a = ppc_effective_address;
ppc_store_dfpresult(true);
ppc_store_result_rega();
}
else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
void ppc_lfd() {
ppc_grab_regsfpdia(true);
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
address_quickgrab_translate(ppc_effective_address, 4);
uint64_t combine_result1 = (uint64_t)(return_value);
address_quickgrab_translate((ppc_effective_address + 4), 4);
uint64_t combine_result2 = (uint64_t)(return_value);
ppc_result64_d = (combine_result1 << 32) | combine_result2;
address_grab64bit_translate(ppc_effective_address);
ppc_result64_d = return_value;
ppc_store_dfpresult(true);
}
void ppc_lfdu() {
ppc_grab_regsfpdia(true);
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
address_quickgrab_translate(ppc_effective_address, 4);
uint64_t combine_result1 = (uint64_t)(return_value);
address_quickgrab_translate((ppc_effective_address + 4), 4);
uint64_t combine_result2 = (uint64_t)(return_value);
ppc_result64_d = (combine_result1 << 32) | combine_result2;
if (reg_a == 0) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += ppc_result_a;
address_grab64bit_translate(ppc_effective_address);
ppc_result64_d = return_value;
ppc_store_dfpresult(true);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
void ppc_lfdx() {
ppc_grab_regsfpdia(true);
ppc_effective_address += (reg_a > 0) ? ppc_result_a + ppc_result_b : ppc_result_b;
address_grab64bit_translate(ppc_effective_address);
ppc_result64_d = return_value;
ppc_store_dfpresult(true);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
void ppc_lfdux() {
ppc_grab_regsfpdiab(true);
if (reg_a == 0) {
ppc_effective_address = ppc_result_a + ppc_result_b;
address_grab64bit_translate(ppc_effective_address);
ppc_result64_d = return_value;
ppc_store_dfpresult(true);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
void ppc_stfs() {
ppc_grab_regsfpsia(true);
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
address_quickinsert_translate(uint32_t(ppc_state.ppc_fpr[reg_s].int64_r), ppc_effective_address, 4);
address_insert32bit_translate(uint32_t(ppc_state.ppc_fpr[reg_s].int64_r), ppc_effective_address);
}
void ppc_stfsu() {
ppc_grab_regsfpsia(true);
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
address_quickinsert_translate(uint32_t(ppc_state.ppc_fpr[reg_s].int64_r), ppc_effective_address, 4);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
if (reg_a == 0) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += ppc_result_a;
address_insert32bit_translate(uint32_t(ppc_state.ppc_fpr[reg_s].int64_r), ppc_effective_address);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
void ppc_stfsx() {
ppc_grab_regsfpsiab(true);
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
address_insert32bit_translate(uint32_t(ppc_state.ppc_fpr[reg_s].int64_r), ppc_effective_address);
}
void ppc_stfsux() {
ppc_grab_regsfpsiab(true);
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
address_quickinsert_translate(uint32_t(ppc_state.ppc_fpr[reg_s].int64_r), ppc_effective_address, 4);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
if (reg_a == 0) {
ppc_effective_address = ppc_result_a + ppc_result_b;
address_insert32bit_translate(uint32_t(ppc_state.ppc_fpr[reg_s].int64_r), ppc_effective_address);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
void ppc_stfd() {
ppc_grab_regsfpsia(true);
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s].int64_r >> 32);
address_quickinsert_translate(split_result1, ppc_effective_address, 4);
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s].int64_r);
address_quickinsert_translate(split_result2, ppc_effective_address, 4);
address_insert64bit_translate(ppc_state.ppc_fpr[reg_s].int64_r, ppc_effective_address);
}
void ppc_stfdu() {
ppc_grab_regsfpsia(true);
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
uint32_t split_result1 = (uint32_t)(ppc_state.ppc_fpr[reg_s].int64_r >> 32);
address_quickinsert_translate(split_result1, ppc_effective_address, 4);
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s].int64_r);
address_quickinsert_translate(split_result2, ppc_effective_address, 4);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
if (reg_a == 0) {
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
ppc_effective_address += ppc_result_a;
address_insert64bit_translate(ppc_state.ppc_fpr[reg_s].int64_r, ppc_effective_address);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
void ppc_stfdx() {
ppc_grab_regsfpsiab(true);
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].int64_r >> 32);
address_quickinsert_translate(split_result1, ppc_effective_address, 4);
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s].int64_r);
address_quickinsert_translate(split_result2, ppc_effective_address, 4);
address_insert64bit_translate(ppc_state.ppc_fpr[reg_s].int64_r, ppc_effective_address);
}
void ppc_stfdux() {
ppc_grab_regsfpsiab(true);
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].int64_r >> 32);
address_quickinsert_translate(split_result1, ppc_effective_address, 4);
uint32_t split_result2 = (uint32_t)(ppc_state.ppc_fpr[reg_s].int64_r);
address_quickinsert_translate(split_result2, ppc_effective_address, 4);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
if (reg_a == 0) {
ppc_effective_address = ppc_result_a + ppc_result_b;
address_insert64bit_translate(ppc_state.ppc_fpr[reg_s].int64_r, ppc_effective_address);
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
}
else {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
void ppc_stfiwx() {
ppc_grab_regsfpsiab(true);
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].int64_r);
address_quickinsert_translate(split_result1, ppc_effective_address, 4);
address_insert32bit_translate((uint32_t)(ppc_state.ppc_fpr[reg_s].int64_r), ppc_effective_address);
}
//Floating Point Register Transfer
@ -1193,4 +1239,4 @@ void ppc_fcmpu() {
if ((db_test_a == snan) || (db_test_b == snan)) {
ppc_state.ppc_fpscr |= 0x1000000;
}
}
}

View File

@ -29,77 +29,97 @@
#include "devices/mpc106.h"
/** PowerPC-style MMU BAT arrays (NULL initialization isn't prescribed). */
PPC_BAT_entry ibat_array[4] = {{0}};
PPC_BAT_entry dbat_array[4] = {{0}};
/** PowerPC-style MMU BAT arrays (NULL initialization isn't prescribed). */
PPC_BAT_entry ibat_array[4] = { {0} };
PPC_BAT_entry dbat_array[4] = { {0} };
void ppc_set_cur_instruction(const uint8_t *ptr)
void ppc_set_cur_instruction(const uint8_t* ptr)
{
ppc_cur_instruction = READ_DWORD_BE_A(ptr);
}
static inline void ppc_set_return_val(const uint8_t *ptr, int num_size)
{
//Put the final result in return_value here
//This is what gets put back into the register
if (num_size == 1) { // BYTE
return_value = ptr[0];
static inline void ppc_set_retval_16bit(const uint8_t* ptr) {
if (ppc_state.ppc_msr & 1) {
return_value = READ_WORD_LE_A(ptr);
}
if (ppc_state.ppc_msr & 1) { /* little-endian byte ordering */
if (num_size == 2) { // WORD
return_value = READ_WORD_LE_A(ptr);
}
else if (num_size == 4) { // DWORD
return_value = READ_DWORD_LE_A(ptr);
}
} else { /* big-endian byte ordering */
if (num_size == 2) { // WORD
return_value = READ_WORD_BE_A(ptr);
}
else if (num_size == 4) { // DWORD
return_value = READ_DWORD_BE_A(ptr);
}
else {
return_value = READ_WORD_BE_A(ptr);
}
}
static inline void ppc_memstore_value(unsigned char *ptr, uint32_t value,
uint32_t offset, int num_size)
{
if (ppc_state.ppc_msr & 1) { /* little-endian byte ordering */
if (num_size >= 1) { // BYTE
ptr[offset] = value & 0xFF;
}
if (num_size >= 2) { // WORD
ptr[offset+1] = (value >> 8) & 0xFF;
}
if (num_size == 4) { // DWORD
ptr[offset+2] = (value >> 16) & 0xFF;
ptr[offset+3] = (value >> 24) & 0xFF;
}
} else { /* big-endian byte ordering */
if (num_size == 1) { // BYTE
ptr[offset] = value & 0xFF;
}
else if (num_size == 2) { // WORD
ptr[offset] = (value >> 8) & 0xFF;
ptr[offset+1] = value & 0xFF;
}
else if (num_size == 4) { // DWORD
ptr[offset] = (value >> 24) & 0xFF;
ptr[offset+1] = (value >> 16) & 0xFF;
ptr[offset+2] = (value >> 8) & 0xFF;
ptr[offset+3] = value & 0xFF;
}
static inline void ppc_set_retval_32bit(const uint8_t* ptr) {
if (ppc_state.ppc_msr & 1) {
return_value = READ_DWORD_LE_A(ptr);
}
else {
return_value = READ_DWORD_BE_A(ptr);
}
}
static inline void ppc_set_retval_64bit(const uint8_t* ptr) {
if (ppc_state.ppc_msr & 1) {
return_value = READ_QWORD_LE_A(ptr);
}
else {
return_value = READ_QWORD_BE_A(ptr);
}
}
static inline void ppc_memstore_16bit(unsigned char* ptr, uint16_t value, uint32_t offset) {
if (ppc_state.ppc_msr & 1) { /* little-endian byte ordering */
ptr[offset] = value & 0xFF;
ptr[offset + 1] = (value >> 8) & 0xFF;
}
else { /* big-endian byte ordering */
ptr[offset] = (value >> 8) & 0xFF;
ptr[offset + 1] = value & 0xFF;
}
}
static inline void ppc_memstore_32bit(unsigned char* ptr, uint32_t value, uint32_t offset) {
if (ppc_state.ppc_msr & 1) { /* little-endian byte ordering */
ptr[offset] = value & 0xFF;
ptr[offset + 1] = (value >> 8) & 0xFF;
ptr[offset + 2] = (value >> 16) & 0xFF;
ptr[offset + 3] = (value >> 24) & 0xFF;
}
else { /* big-endian byte ordering */
ptr[offset] = (value >> 24) & 0xFF;
ptr[offset + 1] = (value >> 16) & 0xFF;
ptr[offset + 2] = (value >> 8) & 0xFF;
ptr[offset + 3] = value & 0xFF;
}
}
static inline void ppc_memstore_64bit(unsigned char* ptr, uint64_t value, uint32_t offset) {
if (ppc_state.ppc_msr & 1) { /* little-endian byte ordering */
ptr[offset] = value & 0xFF;
ptr[offset + 1] = (value >> 8) & 0xFF;
ptr[offset + 2] = (value >> 16) & 0xFF;
ptr[offset + 3] = (value >> 24) & 0xFF;
ptr[offset + 4] = (value >> 32) & 0xFF;
ptr[offset + 5] = (value >> 40) & 0xFF;
ptr[offset + 6] = (value >> 48) & 0xFF;
ptr[offset + 7] = (value >> 56) & 0xFF;
}
else { /* big-endian byte ordering */
ptr[offset] = (value >> 56) & 0xFF;
ptr[offset + 1] = (value >> 48) & 0xFF;
ptr[offset + 2] = (value >> 40) & 0xFF;
ptr[offset + 3] = (value >> 32) & 0xFF;
ptr[offset + 4] = (value >> 24) & 0xFF;
ptr[offset + 5] = (value >> 16) & 0xFF;
ptr[offset + 6] = (value >> 8) & 0xFF;
ptr[offset + 7] = value & 0xFF;
}
}
void ibat_update(uint32_t bat_reg)
{
int upper_reg_num;
uint32_t bl, lo_mask;
PPC_BAT_entry *bat_entry;
PPC_BAT_entry* bat_entry;
upper_reg_num = bat_reg & 0xFFFFFFFE;
@ -108,11 +128,11 @@ void ibat_update(uint32_t bat_reg)
bl = (ppc_state.ppc_spr[upper_reg_num] >> 2) & 0x7FF;
lo_mask = (bl << 17) | 0x1FFFF;
bat_entry->access = ppc_state.ppc_spr[upper_reg_num] & 3;
bat_entry->prot = ppc_state.ppc_spr[upper_reg_num + 1] & 3;
bat_entry->access = ppc_state.ppc_spr[upper_reg_num] & 3;
bat_entry->prot = ppc_state.ppc_spr[upper_reg_num + 1] & 3;
bat_entry->lo_mask = lo_mask;
bat_entry->phys_hi = ppc_state.ppc_spr[upper_reg_num + 1] & ~lo_mask;
bat_entry->bepi = ppc_state.ppc_spr[upper_reg_num] & ~lo_mask;
bat_entry->bepi = ppc_state.ppc_spr[upper_reg_num] & ~lo_mask;
}
}
@ -120,7 +140,7 @@ void dbat_update(uint32_t bat_reg)
{
int upper_reg_num;
uint32_t bl, lo_mask;
PPC_BAT_entry *bat_entry;
PPC_BAT_entry* bat_entry;
upper_reg_num = bat_reg & 0xFFFFFFFE;
@ -129,20 +149,20 @@ void dbat_update(uint32_t bat_reg)
bl = (ppc_state.ppc_spr[upper_reg_num] >> 2) & 0x7FF;
lo_mask = (bl << 17) | 0x1FFFF;
bat_entry->access = ppc_state.ppc_spr[upper_reg_num] & 3;
bat_entry->prot = ppc_state.ppc_spr[upper_reg_num + 1] & 3;
bat_entry->access = ppc_state.ppc_spr[upper_reg_num] & 3;
bat_entry->prot = ppc_state.ppc_spr[upper_reg_num + 1] & 3;
bat_entry->lo_mask = lo_mask;
bat_entry->phys_hi = ppc_state.ppc_spr[upper_reg_num + 1] & ~lo_mask;
bat_entry->bepi = ppc_state.ppc_spr[upper_reg_num] & ~lo_mask;
bat_entry->bepi = ppc_state.ppc_spr[upper_reg_num] & ~lo_mask;
}
}
/* remember page table memory region for quicker translation. */
uint32_t page_table_pa_start = 0;
uint32_t page_table_pa_end = 0;
unsigned char *page_table_ptr = 0;
uint32_t page_table_pa_start = 0;
uint32_t page_table_pa_end = 0;
unsigned char* page_table_ptr = 0;
static inline uint8_t *calc_pteg_addr(uint32_t hash)
static inline uint8_t* calc_pteg_addr(uint32_t hash)
{
uint32_t sdr1_val, pteg_addr;
@ -150,31 +170,33 @@ static inline uint8_t *calc_pteg_addr(uint32_t hash)
pteg_addr = sdr1_val & 0xFE000000;
pteg_addr |= (sdr1_val & 0x01FF0000) |
(((sdr1_val & 0x1FF) << 16) & ((hash & 0x7FC00) << 6));
(((sdr1_val & 0x1FF) << 16) & ((hash & 0x7FC00) << 6));
pteg_addr |= (hash & 0x3FF) << 6;
if (pteg_addr >= page_table_pa_start && pteg_addr <= page_table_pa_end) {
return page_table_ptr + (pteg_addr - page_table_pa_start);
} else {
AddressMapEntry *entry = mem_ctrl_instance->find_range(pteg_addr);
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(pteg_addr);
if (entry && entry->type & (RT_ROM | RT_RAM)) {
page_table_pa_start = entry->start;
page_table_pa_end = entry->end;
page_table_ptr = entry->mem_ptr;
page_table_pa_end = entry->end;
page_table_ptr = entry->mem_ptr;
return page_table_ptr + (pteg_addr - page_table_pa_start);
} else {
}
else {
printf("SOS: no page table region was found at %08X!\n", pteg_addr);
exit(-1); // FIXME: ugly error handling, must be the proper exception!
}
}
}
static bool search_pteg(uint8_t *pteg_addr, uint8_t **ret_pte_addr,
uint32_t vsid, uint16_t page_index, uint8_t pteg_num)
static bool search_pteg(uint8_t* pteg_addr, uint8_t** ret_pte_addr,
uint32_t vsid, uint16_t page_index, uint8_t pteg_num)
{
/* construct PTE matching word */
uint32_t pte_check = 0x80000000 | (vsid << 7) | (pteg_num << 6) |
(page_index >> 10);
(page_index >> 10);
#ifdef MMU_INTEGRITY_CHECKS
/* PTEG integrity check that ensures that all matching PTEs have
@ -189,7 +211,8 @@ static bool search_pteg(uint8_t *pteg_addr, uint8_t **ret_pte_addr,
printf("Multiple PTEs with different RPN/WIMG/PP found!\n");
exit(-1);
}
} else {
}
else {
/* isolate RPN, WIMG and PP fields */
pte_word2_check = READ_DWORD_BE_A(pteg_addr) & 0xFFFFF07B;
*ret_pte_addr = pteg_addr;
@ -209,11 +232,11 @@ static bool search_pteg(uint8_t *pteg_addr, uint8_t **ret_pte_addr,
}
static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
unsigned msr_pr, int is_write)
unsigned msr_pr, int is_write)
{
uint32_t sr_val, page_index, pteg_hash1, vsid, pte_word2;
unsigned key, pp;
uint8_t *pte_addr;
uint8_t* pte_addr;
sr_val = ppc_state.ppc_sr[(la >> 28) & 0x0F];
if (sr_val & 0x80000000) {
@ -234,7 +257,8 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
if (!search_pteg(calc_pteg_addr(~pteg_hash1), &pte_addr, vsid, page_index, 1)) {
if (is_instr_fetch) {
ppc_exception_handler(Except_Type::EXC_ISI, 0x40000000);
} else {
}
else {
ppc_state.ppc_spr[18] = 0x40000000 | (is_write << 25);
ppc_state.ppc_spr[19] = la;
ppc_exception_handler(Except_Type::EXC_DSI, 0);
@ -244,7 +268,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
pte_word2 = READ_DWORD_BE_A(pte_addr + 4);
key = (((sr_val >> 29) & 1) & msr_pr) | (((sr_val >> 30) & 1) & (msr_pr ^ 1));
key = (((sr_val >> 29) & 1)& msr_pr) | (((sr_val >> 30) & 1)& (msr_pr ^ 1));
/* check page access */
pp = pte_word2 & 3;
@ -256,7 +280,8 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
if ((key && (!pp || (pp == 1 && is_write))) || (pp == 3 && is_write)) {
if (is_instr_fetch) {
ppc_exception_handler(Except_Type::EXC_ISI, 0x08000000);
} else {
}
else {
ppc_state.ppc_spr[18] = 0x08000000 | (is_write << 25);
ppc_state.ppc_spr[19] = la;
ppc_exception_handler(Except_Type::EXC_DSI, 0);
@ -287,8 +312,8 @@ static uint32_t ppc_mmu_instr_translate(uint32_t la)
// Those bits are mutually exclusive
unsigned access_bits = (~msr_pr << 1) | msr_pr;
for (int bat_index = 0; bat_index < 4; bat_index++){
PPC_BAT_entry *bat_entry = &ibat_array[bat_index];
for (int bat_index = 0; bat_index < 4; bat_index++) {
PPC_BAT_entry* bat_entry = &ibat_array[bat_index];
if ((bat_entry->access & access_bits) &&
((la & ~bat_entry->lo_mask) == bat_entry->bepi)) {
@ -326,8 +351,8 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write)
// Those bits are mutually exclusive
unsigned access_bits = (~msr_pr << 1) | msr_pr;
for (int bat_index = 0; bat_index < 4; bat_index++){
PPC_BAT_entry *bat_entry = &dbat_array[bat_index];
for (int bat_index = 0; bat_index < 4; bat_index++) {
PPC_BAT_entry* bat_entry = &dbat_array[bat_index];
if ((bat_entry->access & access_bits) &&
((la & ~bat_entry->lo_mask) == bat_entry->bepi)) {
@ -349,11 +374,17 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write)
}
uint32_t write_last_pa_start = 0;
uint32_t write_last_pa_end = 0;
unsigned char *write_last_ptr = 0;
uint32_t write_last_pa_start = 0;
uint32_t write_last_pa_end = 0;
unsigned char* write_last_ptr = 0;
void address_quickinsert_translate(uint32_t value, uint32_t addr, uint8_t num_bytes)
void set_write_pa_ptr(AddressMapEntry* entry) {
write_last_pa_start = entry->start;
write_last_pa_end = entry->end;
write_last_ptr = entry->mem_ptr;
}
void address_insert8bit_translate(uint8_t value, uint32_t addr)
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
@ -361,33 +392,132 @@ void address_quickinsert_translate(uint32_t value, uint32_t addr, uint8_t num_by
}
if (addr >= write_last_pa_start && addr <= write_last_pa_end) {
ppc_memstore_value(write_last_ptr, value, addr - write_last_pa_start, num_bytes);
} else {
AddressMapEntry *entry = mem_ctrl_instance->find_range(addr);
uint32_t offset = addr - write_last_pa_start;
write_last_ptr[offset] = value;
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
if (entry) {
if (entry->type & RT_RAM) {
write_last_pa_start = entry->start;
write_last_pa_end = entry->end;
write_last_ptr = entry->mem_ptr;
ppc_memstore_value(write_last_ptr, value, addr - entry->start, num_bytes);
} else if (entry->type & RT_MMIO) {
entry->devobj->write(addr - entry->start, value, num_bytes);
} else {
set_write_pa_ptr(entry);
uint32_t offset = addr - entry->start;
write_last_ptr[offset] = value;
}
else if (entry->type & RT_MMIO) {
entry->devobj->write(addr - entry->start, (uint32_t)value, 1);
}
else {
printf("Please check your address map!\n");
}
} else {
}
else {
printf("WARNING: write attempt to unmapped memory at 0x%08X!\n", addr);
}
}
}
void address_insert16bit_translate(uint16_t value, uint32_t addr)
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
uint32_t read_last_pa_start = 0;
uint32_t read_last_pa_end = 0;
unsigned char *read_last_ptr = 0;
if (addr >= write_last_pa_start && addr <= write_last_pa_end) {
ppc_memstore_16bit(write_last_ptr, value, addr - write_last_pa_start);
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
if (entry) {
if (entry->type & RT_RAM) {
set_write_pa_ptr(entry);
ppc_memstore_16bit(write_last_ptr, value, addr - write_last_pa_start);
}
else if (entry->type & RT_MMIO) {
entry->devobj->write(addr - entry->start, (uint32_t)value, 2);
}
else {
printf("Please check your address map!\n");
}
}
else {
printf("WARNING: write attempt to unmapped memory at 0x%08X!\n", addr);
}
}
}
void address_insert32bit_translate(uint32_t value, uint32_t addr)
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
if (addr >= write_last_pa_start && addr <= write_last_pa_end) {
ppc_memstore_32bit(write_last_ptr, value, addr - write_last_pa_start);
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
if (entry) {
if (entry->type & RT_RAM) {
set_write_pa_ptr(entry);
ppc_memstore_32bit(write_last_ptr, value, addr - write_last_pa_start);
}
else if (entry->type & RT_MMIO) {
entry->devobj->write(addr - entry->start, value, 4);
}
else {
printf("Please check your address map!\n");
}
}
else {
printf("WARNING: write attempt to unmapped memory at 0x%08X!\n", addr);
}
}
}
void address_insert64bit_translate(uint64_t value, uint32_t addr)
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 1);
}
if (addr >= write_last_pa_start && addr <= write_last_pa_end) {
ppc_memstore_64bit(write_last_ptr, value, addr - write_last_pa_start);
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
if (entry) {
if (entry->type & RT_RAM) {
set_write_pa_ptr(entry);
ppc_memstore_64bit(write_last_ptr, value, addr - write_last_pa_start);
}
else if (entry->type & RT_MMIO) {
entry->devobj->write(addr - entry->start, (uint32_t)value, 4);
}
else {
printf("Please check your address map!\n");
}
}
else {
printf("WARNING: write attempt to unmapped memory at 0x%08X!\n", addr);
}
}
}
uint32_t read_last_pa_start = 0;
uint32_t read_last_pa_end = 0;
unsigned char* read_last_ptr = 0;
void set_read_pa_ptr(AddressMapEntry* entry) {
read_last_pa_start = entry->start;
read_last_pa_end = entry->end;
read_last_ptr = entry->mem_ptr;
}
/** Grab a value from memory into a register */
void address_quickgrab_translate(uint32_t addr, uint8_t num_bytes)
void address_grab8bit_translate(uint32_t addr)
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
@ -395,24 +525,135 @@ void address_quickgrab_translate(uint32_t addr, uint8_t num_bytes)
}
if (addr >= read_last_pa_start && addr <= read_last_pa_end) {
ppc_set_return_val(read_last_ptr + (addr - read_last_pa_start), num_bytes);
} else {
AddressMapEntry *entry = mem_ctrl_instance->find_range(addr);
uint8_t* pointer = (read_last_ptr + (addr - read_last_pa_start));
return_value = (*(uint8_t*)((pointer)));
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
if (entry) {
if (entry->type & (RT_ROM | RT_RAM)) {
read_last_pa_start = entry->start;
read_last_pa_end = entry->end;
read_last_ptr = entry->mem_ptr;
ppc_set_return_val(read_last_ptr + (addr - entry->start), num_bytes);
} else if (entry->type & RT_MMIO) {
return_value = entry->devobj->read(addr - entry->start, num_bytes);
} else {
set_read_pa_ptr(entry);
uint8_t* pointer = (read_last_ptr + (addr - entry->start));
return_value = (*(uint8_t*)((pointer)));
}
else if (entry->type & RT_MMIO) {
return_value = entry->devobj->read(addr - entry->start, 1);
}
else {
printf("Please check your address map!\n");
}
} else {
}
else {
printf("WARNING: read attempt from unmapped memory at 0x%08X!\n", addr);
/* reading from unmapped memory will return unmapped value */
return_value = 0xFF;
}
}
}
void address_grab16bit_translate(uint32_t addr)
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 0);
}
if (addr >= read_last_pa_start && addr <= read_last_pa_end) {
ppc_set_retval_16bit(read_last_ptr + (addr - read_last_pa_start));
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
if (entry) {
if (entry->type & (RT_ROM | RT_RAM)) {
set_read_pa_ptr(entry);
ppc_set_retval_16bit(read_last_ptr + (addr - entry->start));
}
else if (entry->type & RT_MMIO) {
return_value = entry->devobj->read(addr - entry->start, 4);
}
else {
printf("Please check your address map!\n");
}
}
else {
printf("WARNING: read attempt from unmapped memory at 0x%08X!\n", addr);
/* reading from unmapped memory will return unmapped value */
uint8_t num_bytes = 2;
for (return_value = 0xFF; --num_bytes > 0;)
return_value = (return_value << 8) | 0xFF;
}
}
}
void address_grab32bit_translate(uint32_t addr)
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 0);
}
if (addr >= read_last_pa_start && addr <= read_last_pa_end) {
ppc_set_retval_32bit(read_last_ptr + (addr - read_last_pa_start));
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
if (entry) {
if (entry->type & (RT_ROM | RT_RAM)) {
set_read_pa_ptr(entry);
ppc_set_retval_32bit(read_last_ptr + (addr - entry->start));
}
else if (entry->type & RT_MMIO) {
return_value = entry->devobj->read(addr - entry->start, 4);
}
else {
printf("Please check your address map!\n");
}
}
else {
printf("WARNING: read attempt from unmapped memory at 0x%08X!\n", addr);
/* reading from unmapped memory will return unmapped value */
uint8_t num_bytes = 4;
for (return_value = 0xFF; --num_bytes > 0;)
return_value = (return_value << 8) | 0xFF;
}
}
}
void address_grab64bit_translate(uint32_t addr)
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, 0);
}
if (addr >= read_last_pa_start && addr <= read_last_pa_end) {
ppc_set_retval_64bit(read_last_ptr + (addr - read_last_pa_start));
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
if (entry) {
if (entry->type & (RT_ROM | RT_RAM)) {
set_read_pa_ptr(entry);
ppc_set_retval_64bit(read_last_ptr + (addr - entry->start));
}
else if (entry->type & RT_MMIO) {
return_value = entry->devobj->read(addr - entry->start, 4);
}
else {
printf("Please check your address map!\n");
}
}
else {
printf("WARNING: read attempt from unmapped memory at 0x%08X!\n", addr);
/* reading from unmapped memory will return unmapped value */
uint8_t num_bytes = 8;
for (return_value = 0xFF; --num_bytes > 0;)
return_value = (return_value << 8) | 0xFF;
}
@ -420,13 +661,13 @@ void address_quickgrab_translate(uint32_t addr, uint8_t num_bytes)
}
/* remember recently used memory region for quicker translation. */
uint32_t exec_last_pa_start = 0;
uint32_t exec_last_pa_end = 0;
unsigned char *exec_last_ptr = 0;
uint32_t exec_last_pa_start = 0;
uint32_t exec_last_pa_end = 0;
unsigned char* exec_last_ptr = 0;
uint8_t *quickinstruction_translate(uint32_t addr)
uint8_t* quickinstruction_translate(uint32_t addr)
{
uint8_t *real_addr;
uint8_t* real_addr;
/* perform instruction address translation if enabled */
if (ppc_state.ppc_msr & 0x20) {
@ -436,19 +677,21 @@ uint8_t *quickinstruction_translate(uint32_t addr)
if (addr >= exec_last_pa_start && addr <= exec_last_pa_end) {
real_addr = exec_last_ptr + (addr - exec_last_pa_start);
ppc_set_cur_instruction(real_addr);
} else {
AddressMapEntry *entry = mem_ctrl_instance->find_range(addr);
}
else {
AddressMapEntry* entry = mem_ctrl_instance->find_range(addr);
if (entry && entry->type & (RT_ROM | RT_RAM)) {
exec_last_pa_start = entry->start;
exec_last_pa_end = entry->end;
exec_last_pa_end = entry->end;
exec_last_ptr = entry->mem_ptr;
real_addr = exec_last_ptr + (addr - exec_last_pa_start);
ppc_set_cur_instruction(real_addr);
} else {
}
else {
printf("WARNING: attempt to execute code at %08X!\n", addr);
exit(-1); // FIXME: ugly error handling, must be the proper exception!
}
}
return real_addr;
}
}

View File

@ -29,9 +29,15 @@ typedef struct PPC_BAT_entry {
extern void ibat_update(uint32_t bat_reg);
extern void dbat_update(uint32_t bat_reg);
extern void ppc_set_cur_instruction(const uint8_t *ptr);
extern void address_quickinsert_translate(uint32_t value_insert, uint32_t address_grab, uint8_t num_bytes);
extern void address_quickgrab_translate(uint32_t address_grab, uint8_t num_bytes);
extern uint8_t *quickinstruction_translate(uint32_t address_grab);
extern void ppc_set_cur_instruction(const uint8_t* ptr);
extern void address_insert8bit_translate(uint8_t value, uint32_t addr);
extern void address_insert16bit_translate(uint16_t value, uint32_t addr);
extern void address_insert32bit_translate(uint32_t value, uint32_t addr);
extern void address_insert64bit_translate(uint64_t value, uint32_t addr);
extern void address_grab8bit_translate(uint32_t addr);
extern void address_grab16bit_translate(uint32_t addr);
extern void address_grab32bit_translate(uint32_t addr);
extern void address_grab64bit_translate(uint32_t addr);
extern uint8_t* quickinstruction_translate(uint32_t address_grab);
#endif // PPCMEMORY_H
#endif // PPCMEMORY_H

File diff suppressed because it is too large Load Diff

View File

@ -68,7 +68,7 @@ uint32_t ppc_effective_address;
uint32_t ppc_real_address;
uint32_t ppc_next_instruction_address; //Used for branching, setting up the NIA
uint32_t return_value;
uint64_t return_value;
MemCtrlBase *mem_ctrl_instance = 0;
HeathrowIC *heathrow = 0;

View File

@ -8,18 +8,23 @@
#include <cinttypes>
#include "endianswap.h"
/* read an aligned big-endian WORD (16bit) */
/* read an aligned big-endian WORD (16bit) */
#define READ_WORD_BE_A(addr) (BYTESWAP_16(*((uint16_t *)((addr)))))
/* read an aligned big-endian DWORD (32bit) */
#define READ_DWORD_BE_A(addr) (BYTESWAP_32(*((uint32_t *)((addr)))))
/* read an aligned big-endian QWORD (64bit) */
#define READ_QWORD_BE_A(addr) (BYTESWAP_64(*((uint64_t *)((addr)))))
/* read an aligned little-endian WORD (16bit) */
#define READ_WORD_LE_A(addr) (*(uint16_t *)((addr)))
/* read an aligned little-endian DWORD (32bit) */
#define READ_DWORD_LE_A(addr) (*(uint32_t *)((addr)))
/* read an aligned little-endian QWORD (64bit) */
#define READ_QWORD_LE_A(addr) (*(uint64_t *)((addr)))
/* read an unaligned big-endian WORD (16bit) */
#define READ_WORD_BE_U(addr) (((addr)[0] << 8) | (addr)[1])
@ -28,6 +33,12 @@
#define READ_DWORD_BE_U(addr) (((addr)[0] << 24) | ((addr)[1] << 16) | \
((addr)[2] << 8) | (addr)[3])
/* read an unaligned big-endian QWORD (32bit) */
#define READ_QWORD_BE_U(addr) (((addr)[0] << 56) | ((addr)[1] << 48) | \
((addr)[2] << 40) | ((addr)[3] << 32) | \
((addr)[4] << 24) | ((addr)[5] << 16) | \
((addr)[6] << 8) | (addr)[7])
/* read an unaligned little-endian WORD (16bit) */
#define READ_WORD_LE_U(addr) (((addr)[1] << 8) | (ptr)[0])
@ -35,4 +46,9 @@
#define READ_DWORD_LE_U(addr) (((addr)[3] << 24) | ((addr)[2] << 16) | \
((addr)[1] << 8) | (addr)[0])
#endif /* MEM_READ_WRITE_H */
/* read an unaligned little-endian DWORD (32bit) */
#define READ_QWORD_LE_U(addr) (((addr)[7] << 56) | ((addr)[6] << 48) | \
((addr)[5] << 40) | ((addr)[4] << 32) | \
((addr)[3] << 24) | ((addr)[2] << 16) | \
((addr)[1] << 8) | (addr)[0])
#endif /* MEM_READ_WRITE_H */