mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-08-06 10:25:27 +00:00
First attempt at splitting decoding and execution
This commit is contained in:
@@ -37,13 +37,12 @@ static inline uint32_t power_rot_mask(unsigned rot_mb, unsigned rot_me) {
|
||||
template <field_rc rec, field_ov ov>
|
||||
void dppc_interpreter::power_abs() {
|
||||
uint32_t ppc_result_d;
|
||||
ppc_grab_regsda(ppc_cur_instruction);
|
||||
if (ppc_result_a == 0x80000000) {
|
||||
ppc_result_d = ppc_result_a;
|
||||
if (ppc_state.gpr[instr.arg1] == 0x80000000) {
|
||||
ppc_result_d = ppc_state.gpr[instr.arg1];
|
||||
if (ov)
|
||||
ppc_state.spr[SPR::XER] |= XER::SO | XER::OV;
|
||||
} else {
|
||||
ppc_result_d = (int32_t(ppc_result_a) < 0) ? -ppc_result_a : ppc_result_a;
|
||||
ppc_result_d = (int32_t(ppc_state.gpr[instr.arg1]) < 0) ? -ppc_state.gpr[instr.arg1] : ppc_state.gpr[instr.arg1];
|
||||
if (ov)
|
||||
ppc_state.spr[SPR::XER] &= ~XER::OV;
|
||||
}
|
||||
@@ -51,7 +50,7 @@ void dppc_interpreter::power_abs() {
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
ppc_store_iresult_reg(instr.arg0, ppc_result_d);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_abs<RC0, OV0>();
|
||||
@@ -60,36 +59,39 @@ template void dppc_interpreter::power_abs<RC1, OV0>();
|
||||
template void dppc_interpreter::power_abs<RC1, OV1>();
|
||||
|
||||
void dppc_interpreter::power_clcs() {
|
||||
uint32_t ppc_result_d;
|
||||
ppc_grab_da(ppc_cur_instruction);
|
||||
switch (reg_a) {
|
||||
switch (ppc_state.gpr[instr.arg1]) {
|
||||
case 12: //instruction cache line size
|
||||
case 13: //data cache line size
|
||||
case 14: //minimum line size
|
||||
case 15: //maximum line size
|
||||
default: ppc_result_d = is_601 ? 64 : 32; break;
|
||||
default:
|
||||
ppc_state.gpr[instr.arg0] = is_601 ? 64 : 32;
|
||||
break;
|
||||
case 7:
|
||||
case 23: ppc_result_d = is_601 ? 64 : 0; break;
|
||||
case 23:
|
||||
ppc_state.gpr[instr.arg0] = is_601 ? 64 : 0;
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 24:
|
||||
case 25: ppc_result_d = is_601 ? 64 : 4; break;
|
||||
case 25:
|
||||
ppc_state.gpr[instr.arg0] = is_601 ? 64 : 4;
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
case 26:
|
||||
case 27: ppc_result_d = is_601 ? 64 : 0x4000; break;
|
||||
case 27:
|
||||
ppc_state.gpr[instr.arg0] = is_601 ? 64 : 0x4000;
|
||||
break;
|
||||
}
|
||||
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
}
|
||||
|
||||
template <field_rc rec, field_ov ov>
|
||||
void dppc_interpreter::power_div() {
|
||||
uint32_t ppc_result_d;
|
||||
ppc_grab_regsdab(ppc_cur_instruction);
|
||||
|
||||
int64_t dividend = (uint64_t(ppc_result_a) << 32) | ppc_state.spr[SPR::MQ];
|
||||
int32_t divisor = ppc_result_b;
|
||||
int64_t dividend = (uint64_t(ppc_state.gpr[instr.arg1]) << 32) | ppc_state.spr[SPR::MQ];
|
||||
int32_t divisor = ppc_state.gpr[instr.arg2];
|
||||
int64_t quotient;
|
||||
int32_t remainder;
|
||||
|
||||
@@ -119,7 +121,7 @@ void dppc_interpreter::power_div() {
|
||||
if (rec)
|
||||
ppc_changecrf0(remainder);
|
||||
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
ppc_store_iresult_reg(instr.arg0, ppc_result_d);
|
||||
ppc_state.spr[SPR::MQ] = remainder;
|
||||
}
|
||||
|
||||
@@ -132,28 +134,27 @@ template <field_rc rec, field_ov ov>
|
||||
void dppc_interpreter::power_divs() {
|
||||
uint32_t ppc_result_d;
|
||||
int32_t remainder;
|
||||
ppc_grab_regsdab(ppc_cur_instruction);
|
||||
|
||||
if (!ppc_result_b) { // handle the "anything / 0" case
|
||||
if (!ppc_state.gpr[instr.arg2]) { // handle the "anything / 0" case
|
||||
ppc_result_d = -1;
|
||||
remainder = ppc_result_a;
|
||||
remainder = ppc_state.gpr[instr.arg1];
|
||||
if (ov)
|
||||
ppc_state.spr[SPR::XER] |= XER::SO | XER::OV;
|
||||
} else if (ppc_result_a == 0x80000000U && ppc_result_b == 0xFFFFFFFFU) {
|
||||
} else if (ppc_state.gpr[instr.arg1] == 0x80000000U && ppc_state.gpr[instr.arg2] == 0xFFFFFFFFU) {
|
||||
ppc_result_d = 0x80000000U;
|
||||
remainder = 0;
|
||||
if (ov)
|
||||
ppc_state.spr[SPR::XER] |= XER::SO | XER::OV;
|
||||
} else { // normal signed devision
|
||||
ppc_result_d = int32_t(ppc_result_a) / int32_t(ppc_result_b);
|
||||
remainder = (int32_t(ppc_result_a) % int32_t(ppc_result_b));
|
||||
ppc_result_d = int32_t(ppc_state.gpr[instr.arg1]) / int32_t(ppc_state.gpr[instr.arg2]);
|
||||
remainder = (int32_t(ppc_state.gpr[instr.arg1]) % int32_t(ppc_state.gpr[instr.arg2]));
|
||||
if (ov)
|
||||
ppc_state.spr[SPR::XER] &= ~XER::OV;
|
||||
}
|
||||
if (rec)
|
||||
ppc_changecrf0(remainder);
|
||||
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
ppc_store_iresult_reg(instr.arg0, ppc_result_d);
|
||||
ppc_state.spr[SPR::MQ] = remainder;
|
||||
}
|
||||
|
||||
@@ -164,9 +165,8 @@ template void dppc_interpreter::power_divs<RC1, OV1>();
|
||||
|
||||
template <field_rc rec, field_ov ov>
|
||||
void dppc_interpreter::power_doz() {
|
||||
ppc_grab_regsdab(ppc_cur_instruction);
|
||||
uint32_t ppc_result_d = (int32_t(ppc_result_a) < int32_t(ppc_result_b)) ?
|
||||
ppc_result_b - ppc_result_a : 0;
|
||||
uint32_t ppc_result_d = (int32_t(ppc_state.gpr[instr.arg1]) < int32_t(ppc_state.gpr[instr.arg2])) ?
|
||||
ppc_state.gpr[instr.arg2] - ppc_state.gpr[instr.arg1] : 0;
|
||||
|
||||
if (ov) {
|
||||
if (int32_t(ppc_result_d) < 0) {
|
||||
@@ -178,7 +178,7 @@ void dppc_interpreter::power_doz() {
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
ppc_store_iresult_reg(instr.arg0, ppc_result_d);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_doz<RC0, OV0>();
|
||||
@@ -188,19 +188,17 @@ template void dppc_interpreter::power_doz<RC1, OV1>();
|
||||
|
||||
void dppc_interpreter::power_dozi() {
|
||||
uint32_t ppc_result_d;
|
||||
ppc_grab_regsdasimm(ppc_cur_instruction);
|
||||
if (((int32_t)ppc_result_a) > simm) {
|
||||
if (((int32_t)ppc_state.gpr[instr.arg1]) > instr.i_simm) {
|
||||
ppc_result_d = 0;
|
||||
} else {
|
||||
ppc_result_d = simm - ppc_result_a;
|
||||
ppc_result_d = instr.i_simm - ppc_state.gpr[instr.arg1];
|
||||
}
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
ppc_store_iresult_reg(instr.arg0, ppc_result_d);
|
||||
}
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_lscbx() {
|
||||
ppc_grab_regsdab(ppc_cur_instruction);
|
||||
uint32_t ea = ppc_result_b + (reg_a ? ppc_result_a : 0);
|
||||
uint32_t ea = ppc_state.gpr[instr.arg2] + (instr.arg1 ? ppc_state.gpr[instr.arg1] : 0);
|
||||
|
||||
uint32_t bytes_to_load = (ppc_state.spr[SPR::XER] & 0x7F);
|
||||
uint32_t bytes_remaining = bytes_to_load;
|
||||
@@ -216,9 +214,9 @@ void dppc_interpreter::power_lscbx() {
|
||||
|
||||
ppc_result_d |= return_value << shift_amount;
|
||||
if (!shift_amount) {
|
||||
if (reg_d != reg_a && reg_d != reg_b)
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
reg_d = (reg_d + 1) & 0x1F;
|
||||
if (instr.arg0 != instr.arg1 && instr.arg0 != instr.arg2)
|
||||
ppc_store_iresult_reg(instr.arg0, ppc_result_d);
|
||||
instr.arg0 = (instr.arg0 + 1) & 0x1F;
|
||||
ppc_result_d = 0;
|
||||
shift_amount = 24;
|
||||
} else {
|
||||
@@ -235,8 +233,8 @@ void dppc_interpreter::power_lscbx() {
|
||||
}
|
||||
|
||||
// store partially loaded register if any
|
||||
if (shift_amount != 24 && reg_d != reg_a && reg_d != reg_b)
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
if (shift_amount != 24 && instr.arg0 != instr.arg1 && instr.arg0 != instr.arg2)
|
||||
ppc_store_iresult_reg(instr.arg0, ppc_result_d);
|
||||
|
||||
ppc_state.spr[SPR::XER] = (ppc_state.spr[SPR::XER] & ~0x7F) | (bytes_to_load - bytes_remaining);
|
||||
|
||||
@@ -253,9 +251,8 @@ template void dppc_interpreter::power_lscbx<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_maskg() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
uint32_t mask_start = ppc_result_d & 0x1F;
|
||||
uint32_t mask_end = ppc_result_b & 0x1F;
|
||||
uint32_t mask_start = ppc_state.gpr[instr.arg0] & 0x1F;
|
||||
uint32_t mask_end = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
uint32_t insert_mask = 0;
|
||||
|
||||
if (mask_start < (mask_end + 1)) {
|
||||
@@ -268,12 +265,12 @@ void dppc_interpreter::power_maskg() {
|
||||
insert_mask = ~(power_rot_mask(mask_end + 1, mask_start - 1));
|
||||
}
|
||||
|
||||
ppc_result_a = insert_mask;
|
||||
ppc_state.gpr[instr.arg1] = insert_mask;
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_store_iresult_reg(instr.arg1, ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_maskg<RC0>();
|
||||
@@ -281,13 +278,11 @@ template void dppc_interpreter::power_maskg<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_maskir() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
ppc_result_a = (ppc_result_a & ~ppc_result_b) | (ppc_result_d & ppc_result_b);
|
||||
ppc_state.gpr[instr.arg1] = ((ppc_state.gpr[instr.arg1] & ~ppc_state.gpr[instr.arg2]) | \
|
||||
(ppc_state.gpr[instr.arg0] & ppc_state.gpr[instr.arg2]));
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_maskir<RC0>();
|
||||
@@ -295,8 +290,7 @@ template void dppc_interpreter::power_maskir<RC1>();
|
||||
|
||||
template <field_rc rec, field_ov ov>
|
||||
void dppc_interpreter::power_mul() {
|
||||
ppc_grab_regsdab(ppc_cur_instruction);
|
||||
int64_t product = int64_t(int32_t(ppc_result_a)) * int32_t(ppc_result_b);
|
||||
int64_t product = int64_t(int32_t(ppc_state.gpr[instr.arg1])) * int32_t(ppc_state.gpr[instr.arg2]);
|
||||
uint32_t ppc_result_d = uint32_t(uint64_t(product) >> 32);
|
||||
ppc_state.spr[SPR::MQ] = uint32_t(product);
|
||||
|
||||
@@ -309,7 +303,7 @@ void dppc_interpreter::power_mul() {
|
||||
}
|
||||
if (rec)
|
||||
ppc_changecrf0(uint32_t(product));
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
ppc_store_iresult_reg(instr.arg0, ppc_result_d);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_mul<RC0, OV0>();
|
||||
@@ -319,15 +313,14 @@ template void dppc_interpreter::power_mul<RC1, OV1>();
|
||||
|
||||
template <field_rc rec, field_ov ov>
|
||||
void dppc_interpreter::power_nabs() {
|
||||
ppc_grab_regsda(ppc_cur_instruction);
|
||||
uint32_t ppc_result_d = (int32_t(ppc_result_a) < 0) ? ppc_result_a : -ppc_result_a;
|
||||
uint32_t ppc_result_d = (int32_t(ppc_state.gpr[instr.arg1]) < 0) ? ppc_state.gpr[instr.arg1] : -ppc_state.gpr[instr.arg1];
|
||||
|
||||
if (ov)
|
||||
ppc_state.spr[SPR::XER] &= ~XER::OV;
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_iresult_reg(reg_d, ppc_result_d);
|
||||
ppc_store_iresult_reg(instr.arg0, ppc_result_d);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_nabs<RC0, OV0>();
|
||||
@@ -336,37 +329,32 @@ template void dppc_interpreter::power_nabs<RC1, OV0>();
|
||||
template void dppc_interpreter::power_nabs<RC1, OV1>();
|
||||
|
||||
void dppc_interpreter::power_rlmi() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_mb = (ppc_cur_instruction >> 6) & 0x1F;
|
||||
unsigned rot_me = (ppc_cur_instruction >> 1) & 0x1F;
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
|
||||
uint32_t r = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
uint32_t mask = power_rot_mask(rot_mb, rot_me);
|
||||
uint32_t r =
|
||||
((ppc_state.gpr[instr.arg0] << rot_sh) | (ppc_state.gpr[instr.arg0] >> (32 - rot_sh)));
|
||||
uint32_t mask = power_rot_mask(instr.arg3, instr.arg4);
|
||||
|
||||
ppc_result_a = ((r & mask) | (ppc_result_a & ~mask));
|
||||
uint32_t ppc_result_a = ((r & mask) | (ppc_state.gpr[instr.arg1] & ~mask));
|
||||
|
||||
if ((ppc_cur_instruction & 0x01) == 1)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_store_iresult_reg(instr.arg1, ppc_result_a);
|
||||
}
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_rrib() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
|
||||
if (int32_t(ppc_result_d) < 0) {
|
||||
ppc_result_a |= (0x80000000U >> rot_sh);
|
||||
if (int32_t(ppc_state.gpr[instr.arg1]) < 0) {
|
||||
ppc_state.gpr[instr.arg1] |= (0x80000000U >> rot_sh);
|
||||
} else {
|
||||
ppc_result_a &= ~(0x80000000U >> rot_sh);
|
||||
ppc_state.gpr[instr.arg1] &= ~(0x80000000U >> rot_sh);
|
||||
}
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_rrib<RC0>();
|
||||
@@ -374,18 +362,18 @@ template void dppc_interpreter::power_rrib<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_sle() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
|
||||
ppc_result_a = ppc_result_d << rot_sh;
|
||||
ppc_state.spr[SPR::MQ] = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
ppc_state.gpr[instr.arg1] = ppc_state.gpr[instr.arg0] << rot_sh;
|
||||
ppc_state.spr[SPR::MQ] =
|
||||
((ppc_state.gpr[instr.arg0] << rot_sh) | (ppc_state.gpr[instr.arg0] >> (32 - rot_sh)));
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_store_iresult_reg(instr.arg1, ppc_state.gpr[instr.arg1]);
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_store_iresult_reg(instr.arg1, ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_sle<RC0>();
|
||||
@@ -393,18 +381,16 @@ template void dppc_interpreter::power_sle<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_sleq() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
uint32_t r = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
uint32_t r =
|
||||
((ppc_state.gpr[instr.arg0] << rot_sh) | (ppc_state.gpr[instr.arg0] >> (32 - rot_sh)));
|
||||
uint32_t mask = power_rot_mask(0, 31 - rot_sh);
|
||||
|
||||
ppc_result_a = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
|
||||
ppc_state.spr[SPR::MQ] = r;
|
||||
ppc_state.gpr[instr.arg1] = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
|
||||
ppc_state.spr[SPR::MQ] = r;
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_sleq<RC0>();
|
||||
@@ -412,15 +398,16 @@ template void dppc_interpreter::power_sleq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_sliq() {
|
||||
ppc_grab_regssash(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
|
||||
ppc_result_a = ppc_result_d << rot_sh;
|
||||
ppc_state.spr[SPR::MQ] = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
ppc_state.gpr[instr.arg1] = ppc_state.gpr[instr.arg0] << rot_sh;
|
||||
ppc_state.spr[SPR::MQ] =
|
||||
((ppc_state.gpr[instr.arg0] << rot_sh) | (ppc_state.gpr[instr.arg0] >> (32 - rot_sh)));
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_store_iresult_reg(instr.arg1, ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_sliq<RC0>();
|
||||
@@ -428,17 +415,17 @@ template void dppc_interpreter::power_sliq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_slliq() {
|
||||
ppc_grab_regssash(ppc_cur_instruction);
|
||||
uint32_t r = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
|
||||
uint32_t r =
|
||||
((ppc_state.gpr[instr.arg0] << rot_sh) | (ppc_state.gpr[instr.arg0] >> (32 - rot_sh)));
|
||||
uint32_t mask = power_rot_mask(0, 31 - rot_sh);
|
||||
|
||||
ppc_result_a = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
|
||||
ppc_state.spr[SPR::MQ] = r;
|
||||
ppc_state.gpr[instr.arg1] = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
|
||||
ppc_state.spr[SPR::MQ] = r;
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_slliq<RC0>();
|
||||
@@ -446,19 +433,17 @@ template void dppc_interpreter::power_slliq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_sllq() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
|
||||
if (ppc_result_b & 0x20) {
|
||||
ppc_result_a = ppc_state.spr[SPR::MQ] & (-1U << rot_sh);
|
||||
if (ppc_state.gpr[instr.arg2] & 0x20) {
|
||||
ppc_state.gpr[instr.arg1] = ppc_state.spr[SPR::MQ] & (-1U << rot_sh);
|
||||
} else {
|
||||
ppc_result_a = ((ppc_result_d << rot_sh) | (ppc_state.spr[SPR::MQ] & ((1 << rot_sh) - 1)));
|
||||
ppc_state.gpr[instr.arg1] =
|
||||
((ppc_state.gpr[instr.arg0] << rot_sh) | (ppc_state.spr[SPR::MQ] & ((1 << rot_sh) - 1)));
|
||||
}
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_sllq<RC0>();
|
||||
@@ -466,20 +451,19 @@ template void dppc_interpreter::power_sllq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_slq() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
|
||||
if (ppc_result_b & 0x20) {
|
||||
ppc_result_a = 0;
|
||||
if (ppc_state.gpr[instr.arg2] & 0x20) {
|
||||
ppc_state.gpr[instr.arg1] = 0;
|
||||
} else {
|
||||
ppc_result_a = ppc_result_d << rot_sh;
|
||||
ppc_state.gpr[instr.arg1] = ppc_state.gpr[instr.arg0] << rot_sh;
|
||||
}
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
|
||||
ppc_state.spr[SPR::MQ] = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_state.spr[SPR::MQ] =
|
||||
((ppc_state.gpr[instr.arg0] << rot_sh) | (ppc_state.gpr[instr.arg0] >> (32 - rot_sh)));
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_slq<RC0>();
|
||||
@@ -487,12 +471,12 @@ template void dppc_interpreter::power_slq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_sraiq() {
|
||||
ppc_grab_regssash(ppc_cur_instruction);
|
||||
uint32_t mask = (1 << rot_sh) - 1;
|
||||
ppc_result_a = (int32_t)ppc_result_d >> rot_sh;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
|
||||
uint32_t mask = (1 << instr.arg2) - 1;
|
||||
uint32_t ppc_result_a = (int32_t)ppc_state.gpr[instr.arg0] >> instr.arg2;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_state.gpr[instr.arg0] >> instr.arg2) |
|
||||
(ppc_state.gpr[instr.arg0] << (32 - instr.arg2));
|
||||
|
||||
if ((int32_t(ppc_result_d) < 0) && (ppc_result_d & mask)) {
|
||||
if ((int32_t(ppc_state.gpr[instr.arg1]) < 0) && (ppc_state.gpr[instr.arg1] & mask)) {
|
||||
ppc_state.spr[SPR::XER] |= XER::CA;
|
||||
} else {
|
||||
ppc_state.spr[SPR::XER] &= ~XER::CA;
|
||||
@@ -501,7 +485,7 @@ void dppc_interpreter::power_sraiq() {
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_store_iresult_reg(instr.arg1, ppc_result_a);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_sraiq<RC0>();
|
||||
@@ -509,24 +493,24 @@ template void dppc_interpreter::power_sraiq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_sraq() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
uint32_t mask = (ppc_result_b & 0x20) ? -1 : (1 << rot_sh) - 1;
|
||||
ppc_result_a = (int32_t)ppc_result_d >> ((ppc_result_b & 0x20) ? 31 : rot_sh);
|
||||
ppc_state.spr[SPR::MQ] = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
uint32_t mask = (ppc_state.gpr[instr.arg2] & 0x20) ? -1 : (1 << rot_sh) - 1;
|
||||
ppc_state.gpr[instr.arg1] = (int32_t)ppc_state.gpr[instr.arg0] >>
|
||||
((ppc_state.gpr[instr.arg2] & 0x20) ? 31 : rot_sh);
|
||||
ppc_state.spr[SPR::MQ] =
|
||||
((ppc_state.gpr[instr.arg0] << rot_sh) | (ppc_state.gpr[instr.arg0] >> (32 - rot_sh)));
|
||||
|
||||
if ((int32_t(ppc_result_d) < 0) && (ppc_result_d & mask)) {
|
||||
if ((int32_t(ppc_state.gpr[instr.arg0]) < 0) && (ppc_state.gpr[instr.arg0] & mask)) {
|
||||
ppc_state.spr[SPR::XER] |= XER::CA;
|
||||
} else {
|
||||
ppc_state.spr[SPR::XER] &= ~XER::CA;
|
||||
}
|
||||
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
|
||||
ppc_state.spr[SPR::MQ] = (ppc_state.gpr[instr.arg0] >> rot_sh) |
|
||||
(ppc_state.gpr[instr.arg0] << (32 - rot_sh));
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_sraq<RC0>();
|
||||
@@ -534,17 +518,14 @@ template void dppc_interpreter::power_sraq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_sre() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
ppc_state.gpr[instr.arg1] = ppc_state.gpr[instr.arg0] >> rot_sh;
|
||||
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
ppc_result_a = ppc_result_d >> rot_sh;
|
||||
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
|
||||
ppc_state.spr[SPR::MQ] = (ppc_state.gpr[instr.arg0] >> rot_sh) |
|
||||
(ppc_state.gpr[instr.arg0] << (32 - rot_sh));
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_sre<RC0>();
|
||||
@@ -552,13 +533,12 @@ template void dppc_interpreter::power_sre<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_srea() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
ppc_result_a = (int32_t)ppc_result_d >> rot_sh;
|
||||
uint32_t r = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
uint32_t ppc_result_a = (int32_t)ppc_state.gpr[instr.arg0] >> rot_sh;
|
||||
uint32_t r = ((ppc_state.gpr[instr.arg0] >> rot_sh) | (ppc_state.gpr[instr.arg0] << (32 - rot_sh)));
|
||||
uint32_t mask = -1U >> rot_sh;
|
||||
|
||||
if ((int32_t(ppc_result_d) < 0) && (r & ~mask)) {
|
||||
if ((int32_t(ppc_state.gpr[instr.arg0]) < 0) && (r & ~mask)) {
|
||||
ppc_state.spr[SPR::XER] |= XER::CA;
|
||||
} else {
|
||||
ppc_state.spr[SPR::XER] &= ~XER::CA;
|
||||
@@ -567,7 +547,7 @@ void dppc_interpreter::power_srea() {
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_store_iresult_reg(instr.arg1, ppc_result_a);
|
||||
ppc_state.spr[SPR::MQ] = r;
|
||||
}
|
||||
|
||||
@@ -576,17 +556,16 @@ template void dppc_interpreter::power_srea<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_sreq() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
uint32_t mask = -1U >> rot_sh;
|
||||
|
||||
ppc_result_a = (ppc_result_d >> rot_sh) | (ppc_state.spr[SPR::MQ] & ~mask);
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
|
||||
uint32_t ppc_result_a = (ppc_state.gpr[instr.arg0] >> rot_sh) | (ppc_state.spr[SPR::MQ] & ~mask);
|
||||
ppc_state.spr[SPR::MQ] = (ppc_state.gpr[instr.arg0] >> rot_sh) | (ppc_state.gpr[instr.arg0] << (32 - rot_sh));
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_store_iresult_reg(instr.arg1, ppc_result_a);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_sreq<RC0>();
|
||||
@@ -594,14 +573,12 @@ template void dppc_interpreter::power_sreq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_sriq() {
|
||||
ppc_grab_regssash(ppc_cur_instruction);
|
||||
ppc_result_a = ppc_result_d >> rot_sh;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
|
||||
uint32_t rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
ppc_state.gpr[instr.arg1] = ppc_state.gpr[instr.arg0] >> rot_sh;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_state.gpr[instr.arg0] >> rot_sh) | (ppc_state.gpr[instr.arg0] << (32 - rot_sh));
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_sriq<RC0>();
|
||||
@@ -609,17 +586,15 @@ template void dppc_interpreter::power_sriq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_srliq() {
|
||||
ppc_grab_regssash(ppc_cur_instruction);
|
||||
uint32_t r = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
|
||||
unsigned mask = power_rot_mask(rot_sh, 31);
|
||||
uint32_t rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
uint32_t r = (ppc_state.gpr[instr.arg0] >> rot_sh) | (ppc_state.gpr[instr.arg0] << (32 - rot_sh));
|
||||
unsigned mask = power_rot_mask(ppc_state.gpr[instr.arg2], 31);
|
||||
|
||||
ppc_result_a = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
|
||||
ppc_state.gpr[instr.arg1] = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
|
||||
ppc_state.spr[SPR::MQ] = r;
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_srliq<RC0>();
|
||||
@@ -627,21 +602,18 @@ template void dppc_interpreter::power_srliq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_srlq() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
uint32_t r = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
uint32_t r = (ppc_state.gpr[instr.arg0] >> rot_sh) | (ppc_state.gpr[instr.arg0] << (32 - rot_sh));
|
||||
unsigned mask = power_rot_mask(rot_sh, 31);
|
||||
|
||||
if (ppc_result_b & 0x20) {
|
||||
ppc_result_a = (ppc_state.spr[SPR::MQ] & mask);
|
||||
if (ppc_state.gpr[instr.arg2] & 0x20) {
|
||||
ppc_state.gpr[instr.arg1] = (ppc_state.spr[SPR::MQ] & mask);
|
||||
} else {
|
||||
ppc_result_a = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
|
||||
ppc_state.gpr[instr.arg1] = ((r & mask) | (ppc_state.spr[SPR::MQ] & ~mask));
|
||||
}
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_srlq<RC0>();
|
||||
@@ -649,21 +621,18 @@ template void dppc_interpreter::power_srlq<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::power_srq() {
|
||||
ppc_grab_regssab(ppc_cur_instruction);
|
||||
unsigned rot_sh = ppc_result_b & 0x1F;
|
||||
unsigned rot_sh = ppc_state.gpr[instr.arg2] & 0x1F;
|
||||
|
||||
if (ppc_result_b & 0x20) {
|
||||
ppc_result_a = 0;
|
||||
if (ppc_state.gpr[instr.arg2] & 0x20) {
|
||||
ppc_state.gpr[instr.arg1] = 0;
|
||||
} else {
|
||||
ppc_result_a = ppc_result_d >> rot_sh;
|
||||
ppc_state.gpr[instr.arg1] = ppc_state.gpr[instr.arg0] >> rot_sh;
|
||||
}
|
||||
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh));
|
||||
ppc_state.spr[SPR::MQ] = (ppc_state.gpr[instr.arg0] >> rot_sh) | (ppc_state.gpr[instr.arg0] << (32 - rot_sh));
|
||||
|
||||
if (rec)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_iresult_reg(reg_a, ppc_result_a);
|
||||
ppc_changecrf0(ppc_state.gpr[instr.arg1]);
|
||||
}
|
||||
|
||||
template void dppc_interpreter::power_srq<RC0>();
|
||||
|
@@ -68,6 +68,23 @@ fpscr = FP Status and Condition Register
|
||||
sr = Segment Register
|
||||
**/
|
||||
|
||||
typedef struct struct_ppc_instr {
|
||||
uint8_t arg0;
|
||||
uint8_t arg1;
|
||||
uint8_t arg2;
|
||||
uint8_t arg3;
|
||||
uint8_t arg4;
|
||||
int32_t addr;
|
||||
int32_t mask;
|
||||
|
||||
union {
|
||||
int32_t i_simm;
|
||||
uint32_t i_uimm;
|
||||
};
|
||||
} SetInstr;
|
||||
|
||||
SetInstr instr;
|
||||
|
||||
typedef struct struct_ppc_state {
|
||||
FPR_storage fpr[32];
|
||||
uint32_t pc; // Referred as the CIA in the PPC manual
|
||||
@@ -81,7 +98,7 @@ typedef struct struct_ppc_state {
|
||||
bool reserve; // reserve bit used for lwarx and stcwx
|
||||
} SetPRS;
|
||||
|
||||
extern SetPRS ppc_state;
|
||||
SetPRS ppc_state;
|
||||
|
||||
/** symbolic names for frequently used SPRs */
|
||||
enum SPR : int {
|
||||
@@ -406,14 +423,8 @@ void ppc_fpu_off();
|
||||
void ppc_assert_int();
|
||||
void ppc_release_int();
|
||||
|
||||
//void ppc_opcode4();
|
||||
void ppc_opcode16();
|
||||
void ppc_opcode18();
|
||||
template <field_601 for601> void ppc_opcode19();
|
||||
void ppc_opcode31();
|
||||
void ppc_opcode59();
|
||||
void ppc_opcode63();
|
||||
|
||||
void (*ref_instr)();
|
||||
void decode_instr();
|
||||
void initialize_ppc_opcode_tables(bool include_601);
|
||||
|
||||
extern double fp_return_double(uint32_t reg);
|
||||
@@ -645,7 +656,6 @@ template <field_rc rec> extern void power_srq();
|
||||
|
||||
extern uint64_t get_virt_time_ns(void);
|
||||
|
||||
extern void ppc_main_opcode(void);
|
||||
extern void ppc_exec(void);
|
||||
extern void ppc_exec_single(void);
|
||||
extern void ppc_exec_until(uint32_t goal_addr);
|
||||
|
@@ -22,6 +22,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <core/timermanager.h>
|
||||
#include <loguru.hpp>
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmacros.h"
|
||||
#include "ppcmmu.h"
|
||||
#include "ppcdisasm.h"
|
||||
|
||||
@@ -60,8 +61,6 @@ bool is_601 = false;
|
||||
bool power_on = false;
|
||||
Po_Cause power_off_reason = po_enter_debugger;
|
||||
|
||||
SetPRS ppc_state;
|
||||
|
||||
uint32_t ppc_cur_instruction; // Current instruction for the PPC
|
||||
uint32_t ppc_next_instruction_address; // Used for branching, setting up the NIA
|
||||
|
||||
@@ -229,12 +228,14 @@ void ppc_release_int() {
|
||||
|
||||
/** Opcode decoding functions. */
|
||||
|
||||
void ppc_opcode16() {
|
||||
SubOpcode16Grabber[ppc_cur_instruction & 3]();
|
||||
static void ppc_opcode16() {
|
||||
ref_instr = SubOpcode16Grabber[ppc_cur_instruction & 3];
|
||||
ppc_grab_branch(ppc_cur_instruction);
|
||||
}
|
||||
|
||||
void ppc_opcode18() {
|
||||
SubOpcode18Grabber[ppc_cur_instruction & 3]();
|
||||
static void ppc_opcode18() {
|
||||
ref_instr = SubOpcode18Grabber[ppc_cur_instruction & 3];
|
||||
ppc_grab_branch(ppc_cur_instruction);
|
||||
}
|
||||
|
||||
template<field_601 for601>
|
||||
@@ -243,49 +244,62 @@ void ppc_opcode19() {
|
||||
|
||||
switch (subop_grab) {
|
||||
case 0:
|
||||
ppc_mcrf();
|
||||
ref_instr = ppc_mcrf;
|
||||
ppc_grab_regs_crf(ppc_cur_instruction);
|
||||
break;
|
||||
case 32:
|
||||
ppc_bclr<LK0>();
|
||||
ref_instr = ppc_bclr<LK0>;
|
||||
ppc_grab_branch_cond(ppc_cur_instruction);
|
||||
break;
|
||||
case 33:
|
||||
ppc_bclr<LK1>();
|
||||
ref_instr = ppc_bclr<LK1>;
|
||||
ppc_grab_branch_cond(ppc_cur_instruction);
|
||||
break;
|
||||
case 66:
|
||||
ppc_crnor();
|
||||
ref_instr = ppc_crnor;
|
||||
ppc_grab_dab(ppc_cur_instruction);
|
||||
break;
|
||||
case 100:
|
||||
ppc_rfi();
|
||||
ref_instr = ppc_rfi;
|
||||
break;
|
||||
case 258:
|
||||
ppc_crandc();
|
||||
ref_instr = ppc_crandc;
|
||||
ppc_grab_dab(ppc_cur_instruction);
|
||||
break;
|
||||
case 300:
|
||||
ppc_isync();
|
||||
ref_instr = ppc_isync;
|
||||
break;
|
||||
case 386:
|
||||
ppc_crxor();
|
||||
ref_instr = ppc_crxor;
|
||||
ppc_grab_dab(ppc_cur_instruction);
|
||||
break;
|
||||
case 450:
|
||||
ppc_crnand();
|
||||
ref_instr = ppc_crnand;
|
||||
ppc_grab_dab(ppc_cur_instruction);
|
||||
break;
|
||||
case 514:
|
||||
ppc_crand();
|
||||
ref_instr = ppc_crand;
|
||||
ppc_grab_dab(ppc_cur_instruction);
|
||||
break;
|
||||
case 578:
|
||||
ppc_creqv();
|
||||
ref_instr = ppc_creqv;
|
||||
ppc_grab_dab(ppc_cur_instruction);
|
||||
break;
|
||||
case 834:
|
||||
ppc_crorc();
|
||||
ref_instr = ppc_crorc;
|
||||
ppc_grab_dab(ppc_cur_instruction);
|
||||
break;
|
||||
case 898:
|
||||
ppc_cror();
|
||||
ref_instr = ppc_cror;
|
||||
ppc_grab_dab(ppc_cur_instruction);
|
||||
break;
|
||||
case 1056:
|
||||
ppc_bcctr<LK0, for601>();
|
||||
ref_instr = ppc_bcctr<LK0, for601>;
|
||||
ppc_grab_branch_cond(ppc_cur_instruction);
|
||||
break;
|
||||
case 1057:
|
||||
ppc_bcctr<LK1, for601>();
|
||||
ref_instr = ppc_bcctr<LK1, for601>;
|
||||
ppc_grab_branch_cond(ppc_cur_instruction);
|
||||
break;
|
||||
default:
|
||||
ppc_illegalop();
|
||||
@@ -295,31 +309,121 @@ void ppc_opcode19() {
|
||||
template void ppc_opcode19<NOT601>();
|
||||
template void ppc_opcode19<IS601>();
|
||||
|
||||
void ppc_opcode31() {
|
||||
static void ppc_opcode31() {
|
||||
uint16_t subop_grab = ppc_cur_instruction & 0x7FFUL;
|
||||
SubOpcode31Grabber[subop_grab]();
|
||||
ref_instr = SubOpcode59Grabber[subop_grab];
|
||||
|
||||
switch ((subop_grab >> 1)) {
|
||||
case 0:
|
||||
case 32:
|
||||
ppc_grab_crfd_regsab(ppc_cur_instruction);
|
||||
case 8:
|
||||
ppc_grab_tw(ppc_cur_instruction);
|
||||
break;
|
||||
case 83:
|
||||
ppc_grab_d(ppc_cur_instruction);
|
||||
break;
|
||||
case 210:
|
||||
case 595:
|
||||
ppc_grab_sr(ppc_cur_instruction);
|
||||
break;
|
||||
case 512:
|
||||
ppc_grab_mcrxr(ppc_cur_instruction);
|
||||
break;
|
||||
default:
|
||||
ppc_grab_regsdab(ppc_cur_instruction);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_opcode59() {
|
||||
static void ppc_opcode59() {
|
||||
uint16_t subop_grab = ppc_cur_instruction & 0x3FUL;
|
||||
SubOpcode59Grabber[subop_grab]();
|
||||
ref_instr = SubOpcode59Grabber[subop_grab];
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
}
|
||||
|
||||
void ppc_opcode63() {
|
||||
static void ppc_opcode63() {
|
||||
uint16_t subop_grab = ppc_cur_instruction & 0x7FFUL;
|
||||
SubOpcode63Grabber[subop_grab]();
|
||||
ref_instr = SubOpcode59Grabber[subop_grab];
|
||||
|
||||
switch ((subop_grab >> 1)) {
|
||||
case 0:
|
||||
case 32:
|
||||
ppc_grab_regsfpsab(ppc_cur_instruction);
|
||||
break;
|
||||
case 64:
|
||||
ppc_grab_regs_crf(ppc_cur_instruction);
|
||||
case 134:
|
||||
default:
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dispatch using main opcode */
|
||||
void ppc_main_opcode()
|
||||
{
|
||||
#ifdef CPU_PROFILING
|
||||
num_executed_instrs++;
|
||||
#if defined(CPU_PROFILING_OPS)
|
||||
num_opcodes[ppc_cur_instruction]++;
|
||||
#endif
|
||||
#endif
|
||||
OpcodeGrabber[(ppc_cur_instruction >> 26) & 0x3F]();
|
||||
static void ppc_main_opcode() {
|
||||
uint32_t main_op = (ppc_cur_instruction >> 26) & 0x3F;
|
||||
ref_instr = OpcodeGrabber[main_op];
|
||||
|
||||
switch (main_op) {
|
||||
case 3:
|
||||
ppc_grab_twi(ppc_cur_instruction);
|
||||
break;
|
||||
case 7: case 8: case 9:
|
||||
case 12: case 13:
|
||||
case 14: case 15:
|
||||
ppc_grab_regs_dasimm(ppc_cur_instruction);
|
||||
break;
|
||||
case 20: case 21:
|
||||
case 22: case 23:
|
||||
ppc_grab_regs_sab_rot(ppc_cur_instruction);
|
||||
case 24: case 25:
|
||||
case 26: case 27:
|
||||
case 28: case 29:
|
||||
ppc_grab_regs_sauimm(ppc_cur_instruction);
|
||||
case 32: case 33: case 34: case 35:
|
||||
case 36: case 37: case 38: case 39:
|
||||
case 40: case 31: case 42: case 43:
|
||||
case 44: case 45: case 46: case 47:
|
||||
case 48: case 49: case 50: case 51:
|
||||
case 52: case 53: case 54: case 55:
|
||||
ppc_grab_regs_da_addr(ppc_cur_instruction);
|
||||
}
|
||||
}
|
||||
|
||||
void decode_instr() {
|
||||
uint32_t main_op = (ppc_cur_instruction >> 26) & 0x3F;
|
||||
switch (main_op) {
|
||||
case 16:
|
||||
ppc_opcode16();
|
||||
break;
|
||||
case 18:
|
||||
ppc_opcode18();
|
||||
break;
|
||||
case 19:
|
||||
if (is_601)
|
||||
ppc_opcode19<IS601>();
|
||||
else
|
||||
ppc_opcode19<NOT601>();
|
||||
break;
|
||||
case 31:
|
||||
ppc_opcode31();
|
||||
break;
|
||||
case 59:
|
||||
ppc_opcode59();
|
||||
break;
|
||||
case 63:
|
||||
ppc_opcode63();
|
||||
break;
|
||||
default:
|
||||
ppc_main_opcode();
|
||||
}
|
||||
|
||||
|
||||
#ifdef CPU_PROFILING
|
||||
num_executed_instrs++;
|
||||
#if defined(CPU_PROFILING_OPS)
|
||||
num_opcodes[ppc_cur_instruction]++;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static long long cpu_now_ns() {
|
||||
@@ -377,10 +481,11 @@ static void ppc_exec_inner()
|
||||
exec_flags = 0;
|
||||
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
decode_instr();
|
||||
|
||||
// interpret execution block
|
||||
while (power_on && ppc_state.pc < eb_end) {
|
||||
ppc_main_opcode();
|
||||
ref_instr();
|
||||
if (g_icycles++ >= max_cycles || exec_timer) {
|
||||
max_cycles = process_events();
|
||||
}
|
||||
@@ -391,10 +496,12 @@ static void ppc_exec_inner()
|
||||
if (!(exec_flags & EXEF_RFI) && (eb_start & PPC_PAGE_MASK) == page_start) {
|
||||
pc_real += (int)eb_start - (int)ppc_state.pc;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
decode_instr();
|
||||
} else {
|
||||
page_start = eb_start & PPC_PAGE_MASK;
|
||||
eb_end = page_start + PPC_PAGE_SIZE - 1;
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
eb_end = page_start + PPC_PAGE_SIZE - 1;
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
decode_instr();
|
||||
}
|
||||
ppc_state.pc = eb_start;
|
||||
exec_flags = 0;
|
||||
@@ -402,6 +509,7 @@ static void ppc_exec_inner()
|
||||
ppc_state.pc += 4;
|
||||
pc_real += 4;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
decode_instr();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -433,7 +541,7 @@ void ppc_exec_single()
|
||||
}
|
||||
|
||||
mmu_translate_imem(ppc_state.pc);
|
||||
ppc_main_opcode();
|
||||
ref_instr();
|
||||
g_icycles++;
|
||||
process_events();
|
||||
|
||||
@@ -464,11 +572,12 @@ static void ppc_exec_until_inner(const uint32_t goal_addr)
|
||||
eb_end = page_start + PPC_PAGE_SIZE - 1;
|
||||
exec_flags = 0;
|
||||
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
decode_instr();
|
||||
|
||||
// interpret execution block
|
||||
while (power_on && ppc_state.pc < eb_end) {
|
||||
ppc_main_opcode();
|
||||
ref_instr();
|
||||
if (g_icycles++ >= max_cycles || exec_timer) {
|
||||
max_cycles = process_events();
|
||||
}
|
||||
@@ -479,10 +588,12 @@ static void ppc_exec_until_inner(const uint32_t goal_addr)
|
||||
if (!(exec_flags & EXEF_RFI) && (eb_start & PPC_PAGE_MASK) == page_start) {
|
||||
pc_real += (int)eb_start - (int)ppc_state.pc;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
decode_instr();
|
||||
} else {
|
||||
page_start = eb_start & PPC_PAGE_MASK;
|
||||
eb_end = page_start + PPC_PAGE_SIZE - 1;
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
decode_instr();
|
||||
}
|
||||
ppc_state.pc = eb_start;
|
||||
exec_flags = 0;
|
||||
@@ -490,6 +601,7 @@ static void ppc_exec_until_inner(const uint32_t goal_addr)
|
||||
ppc_state.pc += 4;
|
||||
pc_real += 4;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
decode_instr();
|
||||
}
|
||||
|
||||
if (ppc_state.pc == goal_addr)
|
||||
@@ -531,12 +643,13 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size)
|
||||
eb_end = page_start + PPC_PAGE_SIZE - 1;
|
||||
exec_flags = 0;
|
||||
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
decode_instr();
|
||||
|
||||
// interpret execution block
|
||||
while (power_on && (ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size)
|
||||
&& (ppc_state.pc < eb_end)) {
|
||||
ppc_main_opcode();
|
||||
ref_instr();
|
||||
if (g_icycles++ >= max_cycles || exec_timer) {
|
||||
max_cycles = process_events();
|
||||
}
|
||||
@@ -547,10 +660,12 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size)
|
||||
if (!(exec_flags & EXEF_RFI) && (eb_start & PPC_PAGE_MASK) == page_start) {
|
||||
pc_real += (int)eb_start - (int)ppc_state.pc;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
decode_instr();
|
||||
} else {
|
||||
page_start = eb_start & PPC_PAGE_MASK;
|
||||
eb_end = page_start + PPC_PAGE_SIZE - 1;
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
pc_real = mmu_translate_imem(eb_start);
|
||||
decode_instr();
|
||||
}
|
||||
ppc_state.pc = eb_start;
|
||||
exec_flags = 0;
|
||||
@@ -558,6 +673,7 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size)
|
||||
ppc_state.pc += 4;
|
||||
pc_real += 4;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
decode_instr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -154,13 +154,14 @@ static void ppc_update_fex() {
|
||||
// Floating Point Arithmetic
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fadd() {
|
||||
ppc_grab_regsfpdab(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
|
||||
snan_double_check(reg_a, reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg2);
|
||||
max_double_check(val_reg_a, val_reg_b);
|
||||
|
||||
double ppc_dblresult64_d = val_reg_a + val_reg_b;
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
ppc_update_fex();
|
||||
|
||||
@@ -173,13 +174,13 @@ template void dppc_interpreter::ppc_fadd<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fsub() {
|
||||
ppc_grab_regsfpdab(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
|
||||
snan_double_check(reg_a, reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = val_reg_a - val_reg_b;
|
||||
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -191,12 +192,13 @@ template void dppc_interpreter::ppc_fsub<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fdiv() {
|
||||
ppc_grab_regsfpdab(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
|
||||
snan_double_check(reg_a, reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = val_reg_a / val_reg_b;
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -208,12 +210,13 @@ template void dppc_interpreter::ppc_fdiv<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fmul() {
|
||||
ppc_grab_regsfpdac(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
|
||||
double ppc_dblresult64_d = val_reg_a * val_reg_c;
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -225,13 +228,15 @@ template void dppc_interpreter::ppc_fmul<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fmadd() {
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_single_check(reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, val_reg_b);
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -243,13 +248,15 @@ template void dppc_interpreter::ppc_fmadd<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fmsub() {
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_single_check(reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = std::fma(val_reg_a, val_reg_c, -val_reg_b);
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -261,13 +268,15 @@ template void dppc_interpreter::ppc_fmsub<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fnmadd() {
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_single_check(reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = -std::fma(val_reg_a, val_reg_c, val_reg_b);
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -279,13 +288,15 @@ template void dppc_interpreter::ppc_fnmadd<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fnmsub() {
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_single_check(reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = -std::fma(val_reg_a, val_reg_c, -val_reg_b);
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -297,12 +308,13 @@ template void dppc_interpreter::ppc_fnmsub<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fadds() {
|
||||
ppc_grab_regsfpdab(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
|
||||
snan_double_check(reg_a, reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = (float)(val_reg_a + val_reg_b);
|
||||
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
@@ -315,13 +327,13 @@ template void dppc_interpreter::ppc_fadds<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fsubs() {
|
||||
ppc_grab_regsfpdab(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
|
||||
snan_double_check(reg_a, reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = (float)(val_reg_a - val_reg_b);
|
||||
|
||||
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -333,12 +345,13 @@ template void dppc_interpreter::ppc_fsubs<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fdivs() {
|
||||
ppc_grab_regsfpdab(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
|
||||
snan_double_check(reg_a, reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = (float)(val_reg_a / val_reg_b);
|
||||
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -350,12 +363,13 @@ template void dppc_interpreter::ppc_fdivs<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fmuls() {
|
||||
ppc_grab_regsfpdac(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
|
||||
double ppc_dblresult64_d = (float)(val_reg_a * val_reg_c);
|
||||
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -367,13 +381,15 @@ template void dppc_interpreter::ppc_fmuls<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fmadds() {
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_single_check(reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = (float)std::fma(val_reg_a, val_reg_c, val_reg_b);
|
||||
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -385,13 +401,15 @@ template void dppc_interpreter::ppc_fmadds<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fmsubs() {
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_single_check(reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = (float)std::fma(val_reg_a, val_reg_c, -val_reg_b);
|
||||
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -403,13 +421,15 @@ template void dppc_interpreter::ppc_fmsubs<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fnmadds() {
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_single_check(reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = -(float)std::fma(val_reg_a, val_reg_c, val_reg_b);
|
||||
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -421,13 +441,15 @@ template void dppc_interpreter::ppc_fnmadds<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fnmsubs() {
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
snan_double_check(reg_a, reg_c);
|
||||
snan_single_check(reg_b);
|
||||
snan_double_check(instr.arg1, instr.arg3);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = -(float)std::fma(val_reg_a, val_reg_c, -val_reg_b);
|
||||
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
fpresult_update(ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
@@ -439,13 +461,11 @@ template void dppc_interpreter::ppc_fnmsubs<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fabs() {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
snan_single_check(reg_b);
|
||||
double ppc_dblresult64_d = abs(GET_FPR(instr.arg2));
|
||||
|
||||
double ppc_dblresult64_d = abs(GET_FPR(reg_b));
|
||||
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -456,14 +476,12 @@ template void dppc_interpreter::ppc_fabs<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fnabs() {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
snan_single_check(reg_b);
|
||||
|
||||
double ppc_dblresult64_d = abs(GET_FPR(reg_b));
|
||||
double ppc_dblresult64_d = abs(GET_FPR(instr.arg2));
|
||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
||||
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -474,13 +492,11 @@ template void dppc_interpreter::ppc_fnabs<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fneg() {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
snan_single_check(reg_b);
|
||||
double ppc_dblresult64_d = -(GET_FPR(instr.arg2));
|
||||
|
||||
double ppc_dblresult64_d = -(GET_FPR(reg_b));
|
||||
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -491,11 +507,13 @@ template void dppc_interpreter::ppc_fneg<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fsel() {
|
||||
ppc_grab_regsfpdabc(ppc_cur_instruction);
|
||||
double val_reg_a = GET_FPR(instr.arg1);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
double val_reg_c = GET_FPR(instr.arg3);
|
||||
|
||||
double ppc_dblresult64_d = (val_reg_a >= -0.0) ? val_reg_c : val_reg_b;
|
||||
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -506,13 +524,11 @@ template void dppc_interpreter::ppc_fsel<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fsqrt() {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
snan_single_check(reg_b);
|
||||
|
||||
double testd2 = (double)(GET_FPR(reg_b));
|
||||
double testd2 = (double)(GET_FPR(instr.arg2));
|
||||
double ppc_dblresult64_d = std::sqrt(testd2);
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -523,13 +539,11 @@ template void dppc_interpreter::ppc_fsqrt<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fsqrts() {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
snan_single_check(reg_b);
|
||||
|
||||
double testd2 = (double)(GET_FPR(reg_b));
|
||||
double testd2 = (double)(GET_FPR(instr.arg2));
|
||||
double ppc_dblresult64_d = (float)std::sqrt(testd2);
|
||||
ppc_store_sfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -540,12 +554,11 @@ template void dppc_interpreter::ppc_fsqrts<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_frsqrte() {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
snan_single_check(reg_b);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double testd2 = (double)(GET_FPR(reg_b));
|
||||
double testd2 = (double)(GET_FPR(instr.arg2));
|
||||
double ppc_dblresult64_d = 1.0 / sqrt(testd2);
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -556,11 +569,10 @@ template void dppc_interpreter::ppc_frsqrte<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_frsp() {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
snan_single_check(reg_b);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
double ppc_dblresult64_d = (float)(GET_FPR(reg_b));
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
double ppc_dblresult64_d = (float)(GET_FPR(instr.arg2));
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -571,13 +583,11 @@ template void dppc_interpreter::ppc_frsp<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fres() {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
snan_single_check(instr.arg2);
|
||||
|
||||
snan_single_check(reg_b);
|
||||
|
||||
double start_num = GET_FPR(reg_b);
|
||||
double start_num = GET_FPR(instr.arg2);
|
||||
double ppc_dblresult64_d = (float)(1.0 / start_num);
|
||||
ppc_store_dfpresult_flt(reg_d, ppc_dblresult64_d);
|
||||
ppc_store_fpresult_flt(instr.arg0, ppc_dblresult64_d);
|
||||
|
||||
if (start_num == 0.0) {
|
||||
ppc_state.fpscr |= FPSCR::ZX;
|
||||
@@ -598,21 +608,20 @@ template void dppc_interpreter::ppc_fres<RC0>();
|
||||
template void dppc_interpreter::ppc_fres<RC1>();
|
||||
|
||||
static void round_to_int(const uint8_t mode, field_rc rec) {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
double val_reg_b = GET_FPR(reg_b);
|
||||
double val_reg_b = GET_FPR(instr.arg2);
|
||||
|
||||
if (std::isnan(val_reg_b)) {
|
||||
ppc_state.fpscr &= ~(FPSCR::FR | FPSCR::FI);
|
||||
ppc_state.fpscr |= (FPSCR::VXCVI | FPSCR::VX);
|
||||
|
||||
if (check_snan(reg_b)) // issnan
|
||||
if (check_snan(instr.arg2)) // issnan
|
||||
ppc_state.fpscr |= FPSCR::VXSNAN;
|
||||
|
||||
if (ppc_state.fpscr & FPSCR::VE) {
|
||||
ppc_state.fpscr |= FPSCR::FEX; // VX=1 and VE=1 cause FEX to be set
|
||||
ppc_floating_point_exception();
|
||||
} else {
|
||||
ppc_state.fpr[reg_d].int64_r = 0xFFF8000080000000ULL;
|
||||
ppc_state.fpr[instr.arg0].int64_r = 0xFFF8000080000000ULL;
|
||||
}
|
||||
} else if (val_reg_b > static_cast<double>(0x7fffffff) ||
|
||||
val_reg_b < -static_cast<double>(0x80000000)) {
|
||||
@@ -624,9 +633,9 @@ static void round_to_int(const uint8_t mode, field_rc rec) {
|
||||
ppc_floating_point_exception();
|
||||
} else {
|
||||
if (val_reg_b >= 0.0f)
|
||||
ppc_state.fpr[reg_d].int64_r = 0xFFF800007FFFFFFFULL;
|
||||
ppc_state.fpr[instr.arg0].int64_r = 0xFFF800007FFFFFFFULL;
|
||||
else
|
||||
ppc_state.fpr[reg_d].int64_r = 0xFFF8000080000000ULL;
|
||||
ppc_state.fpr[instr.arg0].int64_r = 0xFFF8000080000000ULL;
|
||||
}
|
||||
} else {
|
||||
uint64_t ppc_result64_d;
|
||||
@@ -647,7 +656,7 @@ static void round_to_int(const uint8_t mode, field_rc rec) {
|
||||
|
||||
ppc_result64_d |= 0xFFF8000000000000ULL;
|
||||
|
||||
ppc_store_dfpresult_int(reg_d, ppc_result64_d);
|
||||
ppc_store_fpresult_int(instr.arg0, ppc_result64_d);
|
||||
}
|
||||
|
||||
if (rec)
|
||||
@@ -673,173 +682,149 @@ template void dppc_interpreter::ppc_fctiwz<RC1>();
|
||||
// Floating Point Store and Load
|
||||
|
||||
void dppc_interpreter::ppc_lfs() {
|
||||
ppc_grab_regsfpdia(ppc_cur_instruction);
|
||||
uint32_t ea = int32_t(int16_t(ppc_cur_instruction));
|
||||
ea += (reg_a) ? val_reg_a : 0;
|
||||
uint32_t result = mmu_read_vmem<uint32_t>(ea);
|
||||
ppc_state.fpr[reg_d].dbl64_r = *(float*)(&result);
|
||||
instr.addr += ((instr.arg1) ? ppc_state.gpr[instr.arg1] : 0);
|
||||
uint32_t result = mmu_read_vmem<uint32_t>(instr.addr);
|
||||
ppc_state.fpr[instr.arg0].dbl64_r = *(float*)(&result);
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_lfsu() {
|
||||
ppc_grab_regsfpdia(ppc_cur_instruction);
|
||||
if (reg_a) {
|
||||
uint32_t ea = int32_t(int16_t(ppc_cur_instruction));
|
||||
ea += (reg_a) ? val_reg_a : 0;
|
||||
uint32_t result = mmu_read_vmem<uint32_t>(ea);
|
||||
ppc_state.fpr[reg_d].dbl64_r = *(float*)(&result);
|
||||
ppc_state.gpr[reg_a] = ea;
|
||||
if (instr.arg1) {
|
||||
instr.addr += ((instr.arg1) ? ppc_state.gpr[instr.arg1] : 0);
|
||||
uint32_t result = mmu_read_vmem<uint32_t>(instr.addr);
|
||||
ppc_state.fpr[instr.arg0].dbl64_r = *(float*)(&result);
|
||||
ppc_state.gpr[instr.arg1] = instr.addr;
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_lfsx() {
|
||||
ppc_grab_regsfpdiab(ppc_cur_instruction);
|
||||
uint32_t ea = val_reg_b + (reg_a ? val_reg_a : 0);
|
||||
uint32_t result = mmu_read_vmem<uint32_t>(ea);
|
||||
ppc_state.fpr[reg_d].dbl64_r = *(float*)(&result);
|
||||
instr.addr = ppc_state.gpr[instr.arg2] + (instr.arg1 ? ppc_state.gpr[instr.arg1] : 0);
|
||||
uint32_t result = mmu_read_vmem<uint32_t>(instr.addr);
|
||||
ppc_state.fpr[instr.arg0].dbl64_r = *(float*)(&result);
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_lfsux() {
|
||||
ppc_grab_regsfpdiab(ppc_cur_instruction);
|
||||
if (reg_a) {
|
||||
uint32_t ea = val_reg_a + val_reg_b;
|
||||
uint32_t result = mmu_read_vmem<uint32_t>(ea);
|
||||
ppc_state.fpr[reg_d].dbl64_r = *(float*)(&result);
|
||||
ppc_state.gpr[reg_a] = ea;
|
||||
if (ppc_state.gpr[instr.arg1]) {
|
||||
instr.addr = ppc_state.gpr[instr.arg1] + ppc_state.gpr[instr.arg2];
|
||||
uint32_t result = mmu_read_vmem<uint32_t>(instr.addr);
|
||||
ppc_state.fpr[instr.arg0].dbl64_r = *(float*)(&result);
|
||||
ppc_state.gpr[instr.arg1] = instr.addr;
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_lfd() {
|
||||
ppc_grab_regsfpdia(ppc_cur_instruction);
|
||||
uint32_t ea = int32_t(int16_t(ppc_cur_instruction));
|
||||
ea += (reg_a) ? val_reg_a : 0;
|
||||
uint64_t ppc_result64_d = mmu_read_vmem<uint64_t>(ea);
|
||||
ppc_store_dfpresult_int(reg_d, ppc_result64_d);
|
||||
instr.addr += ((instr.arg1) ? ppc_state.gpr[instr.arg1] : 0);
|
||||
uint64_t ppc_result64_d = mmu_read_vmem<uint64_t>(instr.addr);
|
||||
ppc_store_fpresult_int(instr.arg0, ppc_result64_d);
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_lfdu() {
|
||||
ppc_grab_regsfpdia(ppc_cur_instruction);
|
||||
if (reg_a != 0) {
|
||||
uint32_t ea = int32_t(int16_t(ppc_cur_instruction));
|
||||
ea += val_reg_a;
|
||||
uint64_t ppc_result64_d = mmu_read_vmem<uint64_t>(ea);
|
||||
ppc_store_dfpresult_int(reg_d, ppc_result64_d);
|
||||
ppc_state.gpr[reg_a] = ea;
|
||||
if (instr.arg1 != 0) {
|
||||
instr.addr += ppc_state.gpr[instr.arg1];
|
||||
uint64_t ppc_result64_d = mmu_read_vmem<uint64_t>(instr.addr);
|
||||
ppc_store_fpresult_int(instr.arg0, ppc_result64_d);
|
||||
ppc_state.gpr[instr.arg1] = instr.addr;
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_lfdx() {
|
||||
ppc_grab_regsfpdiab(ppc_cur_instruction);
|
||||
uint32_t ea = val_reg_b + (reg_a ? val_reg_a : 0);
|
||||
uint64_t ppc_result64_d = mmu_read_vmem<uint64_t>(ea);
|
||||
ppc_store_dfpresult_int(reg_d, ppc_result64_d);
|
||||
instr.addr = ppc_state.gpr[instr.arg2] + (instr.arg1 ? ppc_state.gpr[instr.arg1] : 0);
|
||||
uint64_t ppc_result64_d = mmu_read_vmem<uint64_t>(instr.addr);
|
||||
ppc_store_fpresult_int(instr.arg0, ppc_result64_d);
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_lfdux() {
|
||||
ppc_grab_regsfpdiab(ppc_cur_instruction);
|
||||
if (reg_a) {
|
||||
uint32_t ea = val_reg_a + val_reg_b;
|
||||
uint64_t ppc_result64_d = mmu_read_vmem<uint64_t>(ea);
|
||||
ppc_store_dfpresult_int(reg_d, ppc_result64_d);
|
||||
ppc_state.gpr[reg_a] = ea;
|
||||
if (instr.arg1) {
|
||||
instr.addr = ppc_state.gpr[instr.arg1] + ppc_state.gpr[instr.arg2];
|
||||
uint64_t ppc_result64_d = mmu_read_vmem<uint64_t>(instr.addr);
|
||||
ppc_store_fpresult_int(instr.arg0, ppc_result64_d);
|
||||
ppc_state.gpr[instr.arg1] = instr.addr;
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_stfs() {
|
||||
ppc_grab_regsfpsia(ppc_cur_instruction);
|
||||
uint32_t ea = int32_t(int16_t(ppc_cur_instruction));
|
||||
ea += (reg_a) ? val_reg_a : 0;
|
||||
float result = float(ppc_state.fpr[reg_s].dbl64_r);
|
||||
mmu_write_vmem<uint32_t>(ea, *(uint32_t*)(&result));
|
||||
instr.addr += ((instr.arg1) ? ppc_state.gpr[instr.arg1] : 0);
|
||||
float result = float(ppc_state.fpr[instr.arg0].dbl64_r);
|
||||
mmu_write_vmem<uint32_t>(instr.addr, *(uint32_t*)(&result));
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_stfsu() {
|
||||
ppc_grab_regsfpsia(ppc_cur_instruction);
|
||||
if (reg_a != 0) {
|
||||
uint32_t ea = int32_t(int16_t(ppc_cur_instruction));
|
||||
ea += val_reg_a;
|
||||
float result = float(ppc_state.fpr[reg_s].dbl64_r);
|
||||
mmu_write_vmem<uint32_t>(ea, *(uint32_t*)(&result));
|
||||
ppc_state.gpr[reg_a] = ea;
|
||||
if (instr.arg1 != 0) {
|
||||
|
||||
instr.addr += ppc_state.gpr[instr.arg1];
|
||||
float result = float(ppc_state.fpr[instr.arg0].dbl64_r);
|
||||
mmu_write_vmem<uint32_t>(instr.addr, *(uint32_t*)(&result));
|
||||
ppc_state.gpr[instr.arg1] = instr.addr;
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_stfsx() {
|
||||
ppc_grab_regsfpsiab(ppc_cur_instruction);
|
||||
uint32_t ea = val_reg_b + (reg_a ? val_reg_a : 0);
|
||||
float result = float(ppc_state.fpr[reg_s].dbl64_r);
|
||||
mmu_write_vmem<uint32_t>(ea, *(uint32_t*)(&result));
|
||||
instr.addr = ppc_state.gpr[instr.arg2] +
|
||||
(instr.arg1 ? ppc_state.gpr[instr.arg1] : 0);
|
||||
float result = float(ppc_state.fpr[instr.arg0].dbl64_r);
|
||||
mmu_write_vmem<uint32_t>(instr.addr, *(uint32_t*)(&result));
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_stfsux() {
|
||||
ppc_grab_regsfpsiab(ppc_cur_instruction);
|
||||
if (reg_a) {
|
||||
uint32_t ea = val_reg_a + val_reg_b;
|
||||
float result = float(ppc_state.fpr[reg_s].dbl64_r);
|
||||
mmu_write_vmem<uint32_t>(ea, *(uint32_t*)(&result));
|
||||
ppc_state.gpr[reg_a] = ea;
|
||||
if (ppc_state.gpr[instr.arg1]) {
|
||||
instr.addr = ppc_state.gpr[instr.arg1] + ppc_state.gpr[instr.arg2];
|
||||
float result = float(ppc_state.fpr[instr.arg0].dbl64_r);
|
||||
mmu_write_vmem<uint32_t>(instr.addr, *(uint32_t*)(&result));
|
||||
ppc_state.gpr[instr.arg1] = instr.addr;
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_stfd() {
|
||||
ppc_grab_regsfpsia(ppc_cur_instruction);
|
||||
uint32_t ea = int32_t(int16_t(ppc_cur_instruction));
|
||||
ea += reg_a ? val_reg_a : 0;
|
||||
mmu_write_vmem<uint64_t>(ea, ppc_state.fpr[reg_s].int64_r);
|
||||
instr.addr += ((instr.arg1) ? ppc_state.gpr[instr.arg1] : 0);
|
||||
mmu_write_vmem<uint64_t>(instr.addr, ppc_state.fpr[instr.arg0].int64_r);
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_stfdu() {
|
||||
ppc_grab_regsfpsia(ppc_cur_instruction);
|
||||
if (reg_a != 0) {
|
||||
uint32_t ea = int32_t(int16_t(ppc_cur_instruction));
|
||||
ea += val_reg_a;
|
||||
mmu_write_vmem<uint64_t>(ea, ppc_state.fpr[reg_s].int64_r);
|
||||
ppc_state.gpr[reg_a] = ea;
|
||||
if (instr.arg1 != 0) {
|
||||
instr.addr += ppc_state.gpr[instr.arg1];
|
||||
mmu_write_vmem<uint64_t>(instr.addr, ppc_state.fpr[instr.arg0].int64_r);
|
||||
ppc_state.gpr[instr.arg1] = instr.addr;
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_stfdx() {
|
||||
ppc_grab_regsfpsiab(ppc_cur_instruction);
|
||||
uint32_t ea = val_reg_b + (reg_a ? val_reg_a : 0);
|
||||
mmu_write_vmem<uint64_t>(ea, ppc_state.fpr[reg_s].int64_r);
|
||||
instr.addr = ppc_state.gpr[instr.arg2] + (instr.arg1 ? ppc_state.gpr[instr.arg1] : 0);
|
||||
mmu_write_vmem<uint64_t>(instr.addr, ppc_state.fpr[instr.arg0].int64_r);
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_stfdux() {
|
||||
ppc_grab_regsfpsiab(ppc_cur_instruction);
|
||||
if (reg_a != 0) {
|
||||
uint32_t ea = val_reg_a + val_reg_b;
|
||||
mmu_write_vmem<uint64_t>(ea, ppc_state.fpr[reg_s].int64_r);
|
||||
ppc_state.gpr[reg_a] = ea;
|
||||
if (instr.arg1 != 0) {
|
||||
instr.addr = ppc_state.gpr[instr.arg1] + ppc_state.gpr[instr.arg2];
|
||||
mmu_write_vmem<uint64_t>(instr.addr, ppc_state.fpr[instr.arg0].int64_r);
|
||||
ppc_state.gpr[instr.arg1] = instr.addr;
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_stfiwx() {
|
||||
ppc_grab_regsfpsiab(ppc_cur_instruction);
|
||||
uint32_t ea = val_reg_b + (reg_a ? val_reg_a : 0);
|
||||
mmu_write_vmem<uint32_t>(ea, uint32_t(ppc_state.fpr[reg_s].int64_r));
|
||||
instr.addr = ppc_state.gpr[instr.arg2] + (instr.arg1 ? ppc_state.gpr[instr.arg1] : 0);
|
||||
mmu_write_vmem<uint32_t>(instr.addr, uint32_t(ppc_state.fpr[instr.arg0].int64_r));
|
||||
}
|
||||
|
||||
// Floating Point Register Transfer
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_fmr() {
|
||||
ppc_grab_regsfpdb(ppc_cur_instruction);
|
||||
ppc_state.fpr[reg_d].dbl64_r = ppc_state.fpr[reg_b].dbl64_r;
|
||||
ppc_state.fpr[instr.arg0].dbl64_r = ppc_state.fpr[instr.arg2].dbl64_r;
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -850,9 +835,7 @@ template void dppc_interpreter::ppc_fmr<RC1>();
|
||||
|
||||
template <field_601 for601, field_rc rec>
|
||||
void dppc_interpreter::ppc_mffs() {
|
||||
int reg_d = (ppc_cur_instruction >> 21) & 31;
|
||||
|
||||
ppc_state.fpr[reg_d].int64_r = uint64_t(ppc_state.fpscr) | (for601 ? 0xFFFFFFFF00000000ULL : 0xFFF8000000000000ULL);
|
||||
ppc_state.fpr[instr.arg0].int64_r = uint64_t(ppc_state.fpscr) | (for601 ? 0xFFFFFFFF00000000ULL : 0xFFF8000000000000ULL);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -865,29 +848,34 @@ template void dppc_interpreter::ppc_mffs<IS601, RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_mtfsf() {
|
||||
int reg_b = (ppc_cur_instruction >> 11) & 0x1F;
|
||||
uint8_t fm = (ppc_cur_instruction >> 17) & 0xFF;
|
||||
|
||||
uint32_t cr_mask = 0;
|
||||
|
||||
if (fm == 0xFFU) // the fast case
|
||||
if (instr.arg4 == 0xFFU) // the fast case
|
||||
cr_mask = 0xFFFFFFFFUL;
|
||||
else { // the slow case
|
||||
if (fm & 0x80) cr_mask |= 0xF0000000UL;
|
||||
if (fm & 0x40) cr_mask |= 0x0F000000UL;
|
||||
if (fm & 0x20) cr_mask |= 0x00F00000UL;
|
||||
if (fm & 0x10) cr_mask |= 0x000F0000UL;
|
||||
if (fm & 0x08) cr_mask |= 0x0000F000UL;
|
||||
if (fm & 0x04) cr_mask |= 0x00000F00UL;
|
||||
if (fm & 0x02) cr_mask |= 0x000000F0UL;
|
||||
if (fm & 0x01) cr_mask |= 0x0000000FUL;
|
||||
if (instr.arg4 & 0x80)
|
||||
cr_mask |= 0xF0000000UL;
|
||||
if (instr.arg4 & 0x40)
|
||||
cr_mask |= 0x0F000000UL;
|
||||
if (instr.arg4 & 0x20)
|
||||
cr_mask |= 0x00F00000UL;
|
||||
if (instr.arg4 & 0x10)
|
||||
cr_mask |= 0x000F0000UL;
|
||||
if (instr.arg4 & 0x08)
|
||||
cr_mask |= 0x0000F000UL;
|
||||
if (instr.arg4 & 0x04)
|
||||
cr_mask |= 0x00000F00UL;
|
||||
if (instr.arg4 & 0x02)
|
||||
cr_mask |= 0x000000F0UL;
|
||||
if (instr.arg4 & 0x01)
|
||||
cr_mask |= 0x0000000FUL;
|
||||
}
|
||||
|
||||
// ensure neither FEX nor VX will be changed
|
||||
cr_mask &= ~(FPSCR::FEX | FPSCR::VX);
|
||||
|
||||
// copy FPR[reg_b] to FPSCR under control of cr_mask
|
||||
ppc_state.fpscr = (ppc_state.fpscr & ~cr_mask) | (ppc_state.fpr[reg_b].int64_r & cr_mask);
|
||||
ppc_state.fpscr = (ppc_state.fpscr & ~cr_mask) | (ppc_state.fpr[instr.arg2].int64_r & cr_mask);
|
||||
|
||||
if (rec)
|
||||
ppc_update_cr1();
|
||||
@@ -898,14 +886,11 @@ template void dppc_interpreter::ppc_mtfsf<RC1>();
|
||||
|
||||
template <field_rc rec>
|
||||
void dppc_interpreter::ppc_mtfsfi() {
|
||||
int crf_d = (ppc_cur_instruction >> 21) & 0x1C;
|
||||
uint32_t imm = (ppc_cur_instruction << 16) & 0xF0000000UL;
|
||||
|
||||
// prepare field mask and ensure that neither FEX nor VX will be changed
|
||||
uint32_t mask = (0xF0000000UL >> crf_d) & ~(FPSCR::FEX | FPSCR::VX);
|
||||
uint32_t mask = (0xF0000000UL >> instr.arg0) & ~(FPSCR::FEX | FPSCR::VX);
|
||||
|
||||
// copy imm to FPSCR[crf_d] under control of the field mask
|
||||
ppc_state.fpscr = (ppc_state.fpscr & ~mask) | ((imm >> crf_d) & mask);
|
||||
ppc_state.fpscr = (ppc_state.fpscr & ~mask) | ((instr.mask >> instr.arg0) & mask);
|
||||
|
||||
// Update FEX and VX according to the "usual rule"
|
||||
ppc_update_vx();
|
||||
@@ -966,17 +951,18 @@ void dppc_interpreter::ppc_mcrfs() {
|
||||
// Floating Point Comparisons
|
||||
|
||||
void dppc_interpreter::ppc_fcmpo() {
|
||||
ppc_grab_regsfpsab(ppc_cur_instruction);
|
||||
double db_test_a = GET_FPR(instr.arg1);
|
||||
double db_test_b = GET_FPR(instr.arg2);
|
||||
|
||||
uint32_t cmp_c = 0;
|
||||
|
||||
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
|
||||
cmp_c |= CRx_bit::CR_SO;
|
||||
ppc_state.fpscr |= FX | VX;
|
||||
if (check_snan(reg_a) || check_snan(reg_b)) {
|
||||
if (check_snan(instr.arg1) || check_snan(instr.arg2)) {
|
||||
ppc_state.fpscr |= VXSNAN;
|
||||
}
|
||||
if (!(ppc_state.fpscr & FEX) || check_qnan(reg_a) || check_qnan(reg_b)) {
|
||||
if (!(ppc_state.fpscr & FEX) || check_qnan(instr.arg1) || check_qnan(instr.arg2)) {
|
||||
ppc_state.fpscr |= VXVC;
|
||||
}
|
||||
}
|
||||
@@ -992,18 +978,19 @@ void dppc_interpreter::ppc_fcmpo() {
|
||||
|
||||
ppc_state.fpscr &= ~VE; //kludge to pass tests
|
||||
ppc_state.fpscr = (ppc_state.fpscr & ~FPSCR::FPCC_MASK) | (cmp_c >> 16); // update FPCC
|
||||
ppc_state.cr = ((ppc_state.cr & ~(0xF0000000 >> crf_d)) | (cmp_c >> crf_d));
|
||||
ppc_state.cr = ((ppc_state.cr & ~(0xF0000000 >> instr.arg0)) | (cmp_c >> instr.arg0));
|
||||
|
||||
}
|
||||
|
||||
void dppc_interpreter::ppc_fcmpu() {
|
||||
ppc_grab_regsfpsab(ppc_cur_instruction);
|
||||
double db_test_a = GET_FPR(instr.arg1);
|
||||
double db_test_b = GET_FPR(instr.arg2);
|
||||
|
||||
uint32_t cmp_c = 0;
|
||||
|
||||
if (std::isnan(db_test_a) || std::isnan(db_test_b)) {
|
||||
cmp_c |= CRx_bit::CR_SO;
|
||||
if (check_snan(reg_a) || check_snan(reg_b)) {
|
||||
if (check_snan(instr.arg1) || check_snan(instr.arg2)) {
|
||||
ppc_state.fpscr |= FX | VX | VXSNAN;
|
||||
}
|
||||
}
|
||||
@@ -1019,6 +1006,6 @@ void dppc_interpreter::ppc_fcmpu() {
|
||||
|
||||
ppc_state.fpscr &= ~VE; //kludge to pass tests
|
||||
ppc_state.fpscr = (ppc_state.fpscr & ~FPSCR::FPCC_MASK) | (cmp_c >> 16); // update FPCC
|
||||
ppc_state.cr = ((ppc_state.cr & ~(0xF0000000UL >> crf_d)) | (cmp_c >> crf_d));
|
||||
ppc_state.cr = ((ppc_state.cr & ~(0xF0000000UL >> instr.arg0)) | (cmp_c >> instr.arg0));
|
||||
|
||||
}
|
||||
|
@@ -23,194 +23,178 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#define PPC_MACROS_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include "ppcemu.h"
|
||||
|
||||
#define ppc_grab_regsdasimm(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int32_t simm = int32_t(int16_t(opcode)); \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
#define reg_d(opcode) ((opcode >> 21) & 0x1F)
|
||||
#define reg_a(opcode) ((opcode >> 16) & 0x1F)
|
||||
#define reg_b(opcode) ((opcode >> 11) & 0x1F)
|
||||
#define reg_c(opcode) ((opcode >> 6) & 0x1F)
|
||||
#define reg_s(opcode) reg_d(opcode)
|
||||
#define trap_to(opcode) reg_d(opcode)
|
||||
#define simm(opcode) int32_t(int16_t(opcode))
|
||||
#define uimm(opcode) uint16_t(opcode)
|
||||
#define rot_sh(opcode) reg_b(opcode)
|
||||
#define rot_mb(opcode) ((opcode >> 6) & 0x1F)
|
||||
#define rot_me(opcode) ((opcode >> 1) & 0x1F)
|
||||
#define crf_d(opcode) ((opcode >> 21) & 0x1C)
|
||||
#define crf_s(opcode) ((opcode >> 16) & 0x1C)
|
||||
#define crm(opcode) ((opcode >> 12) & 0xFFU)
|
||||
#define fcrm(opcode) crm(opcode)
|
||||
#define br_bo(opcode) reg_d(opcode)
|
||||
#define br_bi(opcode) reg_a(opcode)
|
||||
#define br_bd(opcode) int32_t(int16_t(opcode & ~3UL))
|
||||
#define adr_li(opcode) int32_t((opcode & ~3UL) << 6) >> 6
|
||||
#define adr_d(opcode) int32_t(int16_t(opcode))
|
||||
#define segreg(opcode) ((opcode >> 16) & 0xF)
|
||||
#define mtfsfi_mask(opcode) ((opcode << 16) & 0xF0000000UL)
|
||||
|
||||
#define ppc_grab_regsdauimm(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
uint32_t uimm = uint16_t(opcode); \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
#define ppc_grab_twi(opcode) \
|
||||
instr.i_simm = simm(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg0 = trap_to(opcode);
|
||||
|
||||
#define ppc_grab_regsasimm(opcode) \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int32_t simm = int32_t(int16_t(opcode)); \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
#define ppc_grab_tw(opcode) \
|
||||
instr.i_simm = simm(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg0 = trap_to(opcode);
|
||||
|
||||
#define ppc_grab_regssauimm(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
uint32_t uimm = uint16_t(opcode); \
|
||||
uint32_t ppc_result_d = ppc_state.gpr[reg_s]; \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
#define ppc_grab_mcrxr(opcode) \
|
||||
instr.arg0 = crf_d(opcode);
|
||||
|
||||
#define ppc_grab_crfd_regsauimm(opcode) \
|
||||
int crf_d = (opcode >> 21) & 0x1C; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
uint32_t uimm = uint16_t(opcode); \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
#define ppc_grab_sr(opcode) \
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = segreg(opcode);
|
||||
|
||||
#define ppc_grab_da(opcode)\
|
||||
int reg_d = (opcode >> 21) & 31;\
|
||||
int reg_a = (opcode >> 16) & 31;\
|
||||
#define ppc_grab_mtfsfi(opcode) \
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.mask = mtfsfi_mask(opcode);
|
||||
|
||||
#define ppc_grab_regs_dasimm(opcode) \
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.i_simm = simm(opcode); \
|
||||
|
||||
#define ppc_grab_regs_sauimm(opcode) \
|
||||
instr.arg0 = reg_s(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.i_simm = simm(opcode); \
|
||||
|
||||
#define ppc_grab_regs_da_addr(opcode) \
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.addr = adr_d(opcode); \
|
||||
|
||||
#define ppc_grab_branch(opcode) \
|
||||
instr.addr = adr_li(opcode);
|
||||
|
||||
#define ppc_grab_branch_cond(opcode) \
|
||||
instr.arg0 = br_bo(opcode); \
|
||||
instr.arg1 = br_bi(opcode);
|
||||
|
||||
#define ppc_grab_branch_cond(opcode) \
|
||||
instr.arg0 = br_bo(opcode); \
|
||||
instr.arg1 = br_bi(opcode);
|
||||
|
||||
#define ppc_grab_d(opcode) \
|
||||
instr.arg0 = reg_d(opcode);
|
||||
|
||||
#define ppc_grab_dab(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31;
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg2 = reg_b(opcode); \
|
||||
|
||||
#define ppc_grab_regsasimm(opcode) \
|
||||
instr.arg0 = reg_s(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.i_simm = simm(opcode); \
|
||||
|
||||
#define ppc_grab_regssauimm(opcode) \
|
||||
instr.arg0 = reg_s(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.i_simm = simm(opcode); \
|
||||
|
||||
#define ppc_grab_crfd_regsauimm(opcode) \
|
||||
instr.arg0 = crf_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.i_simm = simm(opcode); \
|
||||
|
||||
#define ppc_grab_crfd_regsab(opcode) \
|
||||
instr.arg0 = crf_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg2 = reg_b(opcode);
|
||||
|
||||
#define ppc_grab_s(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
uint32_t ppc_result_d = ppc_state.gpr[reg_s];
|
||||
instr.arg0 = reg_s(opcode); \
|
||||
|
||||
#define ppc_grab_regs_crf(opcode) \
|
||||
instr.arg0 = crf_d(opcode); \
|
||||
instr.arg1 = crf_s(opcode); \
|
||||
|
||||
#define ppc_grab_regsdab(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31; \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a]; \
|
||||
uint32_t ppc_result_b = ppc_state.gpr[reg_b];
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg2 = reg_b(opcode); \
|
||||
|
||||
#define ppc_grab_regssab(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31; \
|
||||
uint32_t ppc_result_d = ppc_state.gpr[reg_s]; \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a]; \
|
||||
uint32_t ppc_result_b = ppc_state.gpr[reg_b]; \
|
||||
|
||||
#define ppc_grab_regssab_stswx(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31; \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a]; \
|
||||
uint32_t ppc_result_b = ppc_state.gpr[reg_b];
|
||||
|
||||
#define ppc_grab_regsab(opcode) \
|
||||
int reg_a = (opcode >> 16) & 31;\
|
||||
int reg_b = (opcode >> 11) & 31;\
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];\
|
||||
uint32_t ppc_result_b = ppc_state.gpr[reg_b];
|
||||
|
||||
#define ppc_grab_regssa(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
uint32_t ppc_result_d = ppc_state.gpr[reg_s]; \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
|
||||
#define ppc_grab_regssa_stmw(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
|
||||
#define ppc_grab_regssash(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int rot_sh = (opcode >> 11) & 31; \
|
||||
uint32_t ppc_result_d = ppc_state.gpr[reg_s]; \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
|
||||
#define ppc_grab_regssash_stswi(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int rot_sh = (opcode >> 11) & 31; \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
|
||||
#define ppc_grab_regssb(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31; \
|
||||
uint32_t ppc_result_d = ppc_state.gpr[reg_s]; \
|
||||
uint32_t ppc_result_b = ppc_state.gpr[reg_b]; \
|
||||
|
||||
|
||||
#define ppc_grab_regsda(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
uint32_t reg_a = (opcode >> 16) & 31; \
|
||||
uint32_t ppc_result_a = ppc_state.gpr[reg_a];
|
||||
|
||||
|
||||
#define ppc_grab_regsdb(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
uint32_t reg_b = (opcode >> 11) & 31; \
|
||||
uint32_t ppc_result_b = ppc_state.gpr[reg_b];
|
||||
#define ppc_grab_regs_sab_rot(opcode) \
|
||||
instr.arg0 = reg_s(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg2 = reg_b(opcode); \
|
||||
instr.arg3 = rot_mb(opcode); \
|
||||
instr.arg4 = rot_me(opcode); \
|
||||
|
||||
#define ppc_store_iresult_reg(reg, ppc_result)\
|
||||
ppc_state.gpr[reg] = ppc_result;
|
||||
|
||||
#define ppc_store_sfpresult_int(reg, ppc_result64_d)\
|
||||
ppc_state.fpr[(reg)].int64_r = ppc_result64_d;
|
||||
|
||||
#define ppc_store_sfpresult_flt(reg, ppc_dblresult64_d)\
|
||||
ppc_state.fpr[(reg)].dbl64_r = ppc_dblresult64_d;
|
||||
|
||||
#define ppc_store_dfpresult_int(reg, ppc_result64_d)\
|
||||
#define ppc_store_fpresult_int(reg, ppc_result64_d)\
|
||||
ppc_state.fpr[(reg)].int64_r = ppc_result64_d;
|
||||
|
||||
#define ppc_store_dfpresult_flt(reg, ppc_dblresult64_d)\
|
||||
#define ppc_store_fpresult_flt(reg, ppc_dblresult64_d)\
|
||||
ppc_state.fpr[(reg)].dbl64_r = ppc_dblresult64_d;
|
||||
|
||||
#define ppc_grab_regsfpdb(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31;
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg2 = reg_b(opcode); \
|
||||
|
||||
#define GET_FPR(reg) \
|
||||
#define GET_FPR(reg) \
|
||||
ppc_state.fpr[(reg)].dbl64_r
|
||||
|
||||
#define ppc_grab_regsfpdiab(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31; \
|
||||
uint32_t val_reg_a = ppc_state.gpr[reg_a]; \
|
||||
uint32_t val_reg_b = ppc_state.gpr[reg_b];
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg2 = reg_b(opcode); \
|
||||
|
||||
#define ppc_grab_regsfpdia(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
uint32_t val_reg_a = ppc_state.gpr[reg_a];
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
|
||||
#define ppc_grab_regsfpsia(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
uint32_t val_reg_a = ppc_state.gpr[reg_a];
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
|
||||
#define ppc_grab_regsfpsiab(opcode) \
|
||||
int reg_s = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31; \
|
||||
uint32_t val_reg_a = ppc_state.gpr[reg_a]; \
|
||||
uint32_t val_reg_b = ppc_state.gpr[reg_b];
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg2 = reg_b(opcode); \
|
||||
|
||||
#define ppc_grab_regsfpsab(opcode) \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31; \
|
||||
int crf_d = (opcode >> 21) & 0x1C; \
|
||||
double db_test_a = GET_FPR(reg_a); \
|
||||
double db_test_b = GET_FPR(reg_b);
|
||||
instr.arg0 = crf_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg2 = reg_b(opcode); \
|
||||
|
||||
#define ppc_grab_regsfpdab(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31; \
|
||||
double val_reg_a = GET_FPR(reg_a); \
|
||||
double val_reg_b = GET_FPR(reg_b);
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg2 = reg_b(opcode); \
|
||||
|
||||
#define ppc_grab_regsfpdac(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_c = (opcode >> 6) & 31; \
|
||||
double val_reg_a = GET_FPR(reg_a); \
|
||||
double val_reg_c = GET_FPR(reg_c);
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg3 = reg_c(opcode); \
|
||||
|
||||
#define ppc_grab_regsfpdabc(opcode) \
|
||||
int reg_d = (opcode >> 21) & 31; \
|
||||
int reg_a = (opcode >> 16) & 31; \
|
||||
int reg_b = (opcode >> 11) & 31; \
|
||||
int reg_c = (opcode >> 6) & 31; \
|
||||
double val_reg_a = GET_FPR(reg_a); \
|
||||
double val_reg_b = GET_FPR(reg_b); \
|
||||
double val_reg_c = GET_FPR(reg_c);
|
||||
instr.arg0 = reg_d(opcode); \
|
||||
instr.arg1 = reg_a(opcode); \
|
||||
instr.arg2 = reg_b(opcode); \
|
||||
instr.arg3 = reg_c(opcode); \
|
||||
|
||||
#endif // PPC_MACROS_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -42,12 +42,13 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void xer_ov_test(string mnem, uint32_t opcode) {
|
||||
static void xer_ov_test(string mnem, uint32_t opcode) {
|
||||
ppc_state.gpr[3] = 2;
|
||||
ppc_state.gpr[4] = 2;
|
||||
ppc_state.spr[SPR::XER] = 0xFFFFFFFF;
|
||||
ppc_cur_instruction = opcode;
|
||||
ppc_main_opcode();
|
||||
decode_instr();
|
||||
ref_instr();
|
||||
if (ppc_state.spr[SPR::XER] & 0x40000000UL) {
|
||||
cout << "Invalid " << mnem << " emulation! XER[OV] should not be set." << endl;
|
||||
nfailed++;
|
||||
@@ -55,7 +56,7 @@ void xer_ov_test(string mnem, uint32_t opcode) {
|
||||
ntested++;
|
||||
}
|
||||
|
||||
void xer_update_test() {
|
||||
static void xer_update_test() {
|
||||
xer_ov_test("ADDCO", 0x7C632414);
|
||||
xer_ov_test("ADDCO.", 0x7C632415);
|
||||
xer_ov_test("ADDO", 0x7C632614);
|
||||
@@ -153,7 +154,8 @@ static void read_test_data() {
|
||||
|
||||
ppc_cur_instruction = opcode;
|
||||
|
||||
ppc_main_opcode();
|
||||
decode_instr();
|
||||
ref_instr();
|
||||
|
||||
ntested++;
|
||||
|
||||
@@ -172,7 +174,7 @@ static void read_test_data() {
|
||||
}
|
||||
}
|
||||
|
||||
double double_from_string(string str) {
|
||||
static double double_from_string(string str) {
|
||||
if (str == "snan")
|
||||
return std::numeric_limits<double>::signaling_NaN();
|
||||
if (str == "qnan")
|
||||
@@ -297,7 +299,8 @@ static void read_test_float_data() {
|
||||
|
||||
ppc_cur_instruction = opcode;
|
||||
|
||||
ppc_main_opcode();
|
||||
decode_instr();
|
||||
ref_instr();
|
||||
|
||||
ntested++;
|
||||
|
||||
|
Reference in New Issue
Block a user