2020-02-28 16:04:28 +00:00
|
|
|
/*
|
|
|
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
|
|
|
Copyright (C) 2018-20 divingkatae and maximum
|
|
|
|
(theweirdo) spatium
|
|
|
|
|
|
|
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
// The Power-specific opcodes for the processor - ppcopcodes.cpp
|
|
|
|
// Any shared opcodes are in ppcopcodes.cpp
|
|
|
|
|
2019-12-27 19:10:36 +00:00
|
|
|
#include "ppcemu.h"
|
2019-12-27 19:00:53 +00:00
|
|
|
#include "ppcmmu.h"
|
2020-10-17 21:30:37 +00:00
|
|
|
#include <array>
|
2019-07-02 02:15:33 +00:00
|
|
|
#include <cmath>
|
2020-05-12 18:55:45 +00:00
|
|
|
#include <iostream>
|
2019-07-02 02:15:33 +00:00
|
|
|
#include <limits>
|
2020-10-17 21:30:37 +00:00
|
|
|
#include <stdexcept>
|
2020-05-12 18:55:45 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <thirdparty/loguru/loguru.hpp>
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
// Affects the XER register's SO and OV Bits
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
inline void power_setsoov(uint32_t a, uint32_t b, uint32_t d) {
|
|
|
|
if ((a ^ b) & (a ^ d) & 0x80000000UL) {
|
|
|
|
ppc_state.spr[SPR::XER] |= 0xC0000000UL;
|
2020-05-12 18:55:45 +00:00
|
|
|
} else {
|
2020-10-17 21:30:37 +00:00
|
|
|
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_abs() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regsda();
|
2020-01-26 02:30:55 +00:00
|
|
|
if (ppc_result_a == 0x80000000) {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_result_d = ppc_result_a;
|
2020-10-17 21:30:37 +00:00
|
|
|
if (oe_flag)
|
|
|
|
ppc_state.spr[SPR::XER] |= 0x40000000;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
} else {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
|
|
|
}
|
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_d);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_store_result_regd();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_clcs() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regsda();
|
2020-01-26 02:30:55 +00:00
|
|
|
switch (reg_a) {
|
|
|
|
case 12:
|
|
|
|
case 13:
|
|
|
|
case 14:
|
|
|
|
case 15:
|
|
|
|
ppc_result_d = 65535;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ppc_result_d = 0;
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag) {
|
|
|
|
ppc_changecrf0(ppc_result_d);
|
|
|
|
printf("Does RC do anything here? (TODO) \n");
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
2020-10-17 21:30:37 +00:00
|
|
|
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_store_result_regd();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_div() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regsdab();
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = (ppc_result_a | ppc_state.spr[SPR::MQ]) % ppc_result_b;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (oe_flag)
|
|
|
|
power_setsoov(ppc_result_b, ppc_result_a, ppc_result_d);
|
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_d);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
ppc_store_result_regd();
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_divs() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regsdab();
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_d = ppc_result_a / ppc_result_b;
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (oe_flag)
|
|
|
|
power_setsoov(ppc_result_b, ppc_result_a, ppc_result_d);
|
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_d);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
ppc_store_result_regd();
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_doz() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regsdab();
|
2020-01-26 02:30:55 +00:00
|
|
|
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_result_d = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
} else {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
|
|
|
}
|
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_d);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
ppc_store_result_rega();
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_dozi() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regsdab();
|
2020-01-26 02:30:55 +00:00
|
|
|
if (((int32_t)ppc_result_a) > simm) {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_result_d = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
} else {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_result_d = ~ppc_result_a + simm + 1;
|
|
|
|
}
|
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_lscbx() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regsdab();
|
|
|
|
uint32_t bytes_copied = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
bool match_found = false;
|
2019-07-02 02:15:33 +00:00
|
|
|
uint32_t shift_amount = 0;
|
2020-01-27 00:36:22 +00:00
|
|
|
uint8_t return_value;
|
2020-03-05 04:29:04 +00:00
|
|
|
uint8_t byte_compared = (uint8_t)((ppc_state.spr[SPR::XER] & 0xFF00) >> 8);
|
|
|
|
if ((ppc_state.spr[SPR::XER] & 0x7f) == 0) {
|
2019-07-02 02:15:33 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-03-05 04:29:04 +00:00
|
|
|
uint32_t bytes_to_load = (ppc_state.spr[SPR::XER] & 0x7f) + 1;
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
|
2020-01-26 02:30:55 +00:00
|
|
|
do {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_effective_address++;
|
|
|
|
bytes_to_load--;
|
2020-01-26 02:30:55 +00:00
|
|
|
if (match_found == false) {
|
|
|
|
switch (shift_amount) {
|
|
|
|
case 0:
|
2020-01-27 00:36:22 +00:00
|
|
|
return_value = mem_grab_byte(ppc_effective_address);
|
|
|
|
ppc_result_d = (ppc_result_d & 0x00FFFFFF) | (return_value << 24);
|
2020-01-26 02:30:55 +00:00
|
|
|
ppc_store_result_regd();
|
|
|
|
break;
|
|
|
|
case 1:
|
2020-01-27 00:36:22 +00:00
|
|
|
return_value = mem_grab_byte(ppc_effective_address);
|
|
|
|
ppc_result_d = (ppc_result_d & 0xFF00FFFF) | (return_value << 16);
|
2020-01-26 02:30:55 +00:00
|
|
|
ppc_store_result_regd();
|
|
|
|
break;
|
|
|
|
case 2:
|
2020-01-27 00:36:22 +00:00
|
|
|
return_value = mem_grab_byte(ppc_effective_address);
|
|
|
|
ppc_result_d = (ppc_result_d & 0xFFFF00FF) | (return_value << 8);
|
2020-01-26 02:30:55 +00:00
|
|
|
ppc_store_result_regd();
|
|
|
|
break;
|
|
|
|
case 3:
|
2020-01-27 00:36:22 +00:00
|
|
|
return_value = mem_grab_byte(ppc_effective_address);
|
|
|
|
ppc_result_d = (ppc_result_d & 0xFFFFFF00) | return_value;
|
2020-01-26 02:30:55 +00:00
|
|
|
ppc_store_result_regd();
|
|
|
|
break;
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bytes_copied++;
|
|
|
|
}
|
2020-01-27 00:36:22 +00:00
|
|
|
if (return_value == byte_compared) {
|
2019-07-02 02:15:33 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-01-26 02:30:55 +00:00
|
|
|
if (shift_amount == 3) {
|
2019-07-02 02:15:33 +00:00
|
|
|
shift_amount = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
reg_d = (reg_d + 1) & 0x1F;
|
|
|
|
} else {
|
2019-07-02 02:15:33 +00:00
|
|
|
shift_amount++;
|
|
|
|
}
|
2020-01-26 02:30:55 +00:00
|
|
|
} while (bytes_to_load > 0);
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::XER] = (ppc_state.spr[SPR::XER] & 0xFFFFFF80) | bytes_copied;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
|
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_d);
|
|
|
|
|
|
|
|
ppc_store_result_regd();
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_maskg() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssab();
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t mask_start = ppc_result_d & 31;
|
|
|
|
uint32_t mask_end = ppc_result_b & 31;
|
2019-07-02 02:15:33 +00:00
|
|
|
uint32_t insert_mask = 0;
|
|
|
|
|
2020-01-26 02:30:55 +00:00
|
|
|
if (mask_start < (mask_end + 1)) {
|
|
|
|
for (uint32_t i = mask_start; i < mask_end; i++) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask |= (0x80000000 >> i);
|
|
|
|
}
|
2020-05-12 18:55:45 +00:00
|
|
|
} else if (mask_start == (mask_end + 1)) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask = 0xFFFFFFFF;
|
2020-05-12 18:55:45 +00:00
|
|
|
} else {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask = 0xFFFFFFFF;
|
2020-01-26 02:30:55 +00:00
|
|
|
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask &= (~(0x80000000 >> i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ppc_result_a = insert_mask;
|
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_d);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_maskir() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssab();
|
|
|
|
uint32_t mask_insert = ppc_result_a;
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t insert_rot = 0x80000000;
|
2020-01-26 02:30:55 +00:00
|
|
|
do {
|
|
|
|
if (ppc_result_b & insert_rot) {
|
2019-07-02 02:15:33 +00:00
|
|
|
mask_insert &= ~insert_rot;
|
|
|
|
mask_insert |= (ppc_result_d & insert_rot);
|
|
|
|
}
|
2020-01-26 02:30:55 +00:00
|
|
|
insert_rot = insert_rot >> 1;
|
|
|
|
} while (insert_rot > 0);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_result_a = (ppc_result_d & ppc_result_b);
|
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_mul() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regsdab();
|
|
|
|
uint64_t product;
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
|
|
|
ppc_result_d = ((uint32_t)(product >> 32));
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_d);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_store_result_regd();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_nabs() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regsda();
|
|
|
|
ppc_result_d = (0x80000000 | ppc_result_a);
|
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_d);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
ppc_store_result_regd();
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_rlmi() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssab();
|
2020-05-12 18:55:45 +00:00
|
|
|
unsigned rot_mb = (ppc_cur_instruction >> 6) & 31;
|
|
|
|
unsigned rot_me = (ppc_cur_instruction >> 1) & 31;
|
|
|
|
uint32_t rot_amt = ppc_result_b & 31;
|
2019-07-02 02:15:33 +00:00
|
|
|
uint32_t insert_mask = 0;
|
|
|
|
|
2020-01-26 02:30:55 +00:00
|
|
|
if (rot_mb < (rot_me + 1)) {
|
|
|
|
for (uint32_t i = rot_mb; i < rot_me; i++) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask |= (0x80000000 >> i);
|
|
|
|
}
|
2020-05-12 18:55:45 +00:00
|
|
|
} else if (rot_mb == (rot_me + 1)) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask = 0xFFFFFFFF;
|
2020-05-12 18:55:45 +00:00
|
|
|
} else {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask = 0xFFFFFFFF;
|
2020-01-26 02:30:55 +00:00
|
|
|
for (uint32_t i = (rot_me + 1); i < (rot_mb - 1); i++) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask &= (~(0x80000000 >> i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t step2 = (ppc_result_d << rot_amt) | (ppc_result_d >> rot_amt);
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_a = step2 & insert_mask;
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_rrib() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssab();
|
|
|
|
|
2020-01-26 02:30:55 +00:00
|
|
|
if (ppc_result_d & 0x80000000) {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_result_a |= (0x80000000 >> ppc_result_b);
|
2020-05-12 18:55:45 +00:00
|
|
|
} else {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
|
|
|
|
}
|
2020-10-17 21:30:37 +00:00
|
|
|
|
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
|
|
|
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_sle() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssa();
|
|
|
|
uint32_t insert_mask = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t rot_amt = ppc_result_b & 31;
|
2020-01-26 02:30:55 +00:00
|
|
|
for (uint32_t i = 31; i > rot_amt; i--) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask |= (1 << i);
|
|
|
|
}
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_a = insert_final & insert_mask;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
|
|
|
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_sleq() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssa();
|
|
|
|
uint32_t insert_mask = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t rot_amt = ppc_result_b & 31;
|
2020-01-26 02:30:55 +00:00
|
|
|
for (uint32_t i = 31; i > rot_amt; i--) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask |= (1 << i);
|
|
|
|
}
|
2020-01-26 02:30:55 +00:00
|
|
|
uint32_t insert_start = ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-01-26 02:30:55 +00:00
|
|
|
for (int i = 0; i < 32; i++) {
|
|
|
|
if (insert_mask & (1 << i)) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_end &= ~(1 << i);
|
|
|
|
insert_end |= (insert_start & (1 << i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_a = insert_end;
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = insert_start;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_sliq() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssa();
|
|
|
|
uint32_t insert_mask = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
|
2020-01-26 02:30:55 +00:00
|
|
|
for (uint32_t i = 31; i > rot_sh; i--) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask |= (1 << i);
|
|
|
|
}
|
2020-01-26 02:30:55 +00:00
|
|
|
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-01-26 02:30:55 +00:00
|
|
|
for (int i = 0; i < 32; i++) {
|
|
|
|
if (insert_mask & (1 << i)) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_end &= ~(1 << i);
|
|
|
|
insert_end |= (insert_start & (1 << i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_a = insert_end & insert_mask;
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = insert_start;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_slliq() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssa();
|
|
|
|
uint32_t insert_mask = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
|
2020-01-26 02:30:55 +00:00
|
|
|
for (uint32_t i = 31; i > rot_sh; i--) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask |= (1 << i);
|
|
|
|
}
|
2020-01-26 02:30:55 +00:00
|
|
|
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-01-26 02:30:55 +00:00
|
|
|
for (int i = 0; i < 32; i++) {
|
|
|
|
if (insert_mask & (1 << i)) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_end &= ~(1 << i);
|
|
|
|
insert_end |= (insert_start & (1 << i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_a = insert_end;
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = insert_start;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_sllq() {
|
2020-02-25 02:50:52 +00:00
|
|
|
LOG_F(WARNING, "OOPS! Placeholder for sllq!!! \n");
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_slq() {
|
2020-02-25 02:50:52 +00:00
|
|
|
LOG_F(WARNING, "OOPS! Placeholder for slq!!! \n");
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_sraiq() {
|
2020-02-25 02:50:52 +00:00
|
|
|
LOG_F(WARNING, "OOPS! Placeholder for sraiq!!! \n");
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_sraq() {
|
2020-02-25 02:50:52 +00:00
|
|
|
LOG_F(WARNING, "OOPS! Placeholder for sraq!!! \n");
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_sre() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssa();
|
|
|
|
uint32_t insert_mask = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t rot_amt = ppc_result_b & 31;
|
2020-01-26 02:30:55 +00:00
|
|
|
for (uint32_t i = 31; i > rot_amt; i--) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask |= (1 << i);
|
|
|
|
}
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_a = insert_final;
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_srea() {
|
2020-02-25 02:50:52 +00:00
|
|
|
LOG_F(WARNING, "OOPS! Placeholder for srea!!! \n");
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_sreq() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssa();
|
|
|
|
uint32_t insert_mask = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
unsigned rot_sh = ppc_result_b & 31;
|
2020-01-26 02:30:55 +00:00
|
|
|
for (uint32_t i = 31; i > rot_sh; i--) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask |= (1 << i);
|
|
|
|
}
|
2020-01-26 02:30:55 +00:00
|
|
|
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-01-26 02:30:55 +00:00
|
|
|
for (int i = 0; i < 32; i++) {
|
|
|
|
if (insert_mask & (1 << i)) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_end &= ~(1 << i);
|
|
|
|
insert_end |= (insert_start & (1 << i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_a = insert_end;
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = insert_start;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_sriq() {
|
2019-07-02 02:15:33 +00:00
|
|
|
ppc_grab_regssa();
|
|
|
|
uint32_t insert_mask = 0;
|
2020-05-12 18:55:45 +00:00
|
|
|
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
|
2020-01-26 02:30:55 +00:00
|
|
|
for (uint32_t i = 31; i > rot_sh; i--) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_mask |= (1 << i);
|
|
|
|
}
|
2020-01-26 02:30:55 +00:00
|
|
|
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
|
2020-05-12 18:55:45 +00:00
|
|
|
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-01-26 02:30:55 +00:00
|
|
|
for (int i = 0; i < 32; i++) {
|
|
|
|
if (insert_mask & (1 << i)) {
|
2019-07-02 02:15:33 +00:00
|
|
|
insert_end &= ~(1 << i);
|
|
|
|
insert_end |= (insert_start & (1 << i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 18:55:45 +00:00
|
|
|
ppc_result_a = insert_end;
|
2020-03-05 04:29:04 +00:00
|
|
|
ppc_state.spr[SPR::MQ] = insert_start;
|
2019-07-02 02:15:33 +00:00
|
|
|
|
2020-10-17 21:30:37 +00:00
|
|
|
if (rc_flag)
|
|
|
|
ppc_changecrf0(ppc_result_a);
|
2019-07-02 02:15:33 +00:00
|
|
|
|
|
|
|
ppc_store_result_rega();
|
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_srliq() {
|
2020-02-25 02:50:52 +00:00
|
|
|
LOG_F(WARNING, "OOPS! Placeholder for slriq!!! \n");
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_srlq() {
|
2020-02-25 02:50:52 +00:00
|
|
|
LOG_F(WARNING, "OOPS! Placeholder for slrq!!! \n");
|
2019-07-02 02:15:33 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 04:46:38 +00:00
|
|
|
void dppc_interpreter::power_srq() {
|
2020-02-25 02:50:52 +00:00
|
|
|
LOG_F(WARNING, "OOPS! Placeholder for srq!!! \n");
|
2020-10-17 21:30:37 +00:00
|
|
|
}
|