Avoid some undefined behavior

The `SubOpcode31Grabber[1024] = { ppc_illegalop }` initializer only
populates the first entry with ppc_illegalop (at least on some compilers),
switch to explicitly initializing the entire array with std::fill_n.

Also fix a couple of sign and overflow issues flagged by the Xcode
undefined behavior sanitizer.
This commit is contained in:
Mihai Parparita 2023-12-07 23:59:49 -08:00
parent 4d7204debc
commit e9bc8926ab
2 changed files with 12 additions and 8 deletions

View File

@ -161,9 +161,9 @@ static PPCOpcode SubOpcode18Grabber[] = {
/** Instructions decoding tables for integer,
single floating-point, and double-floating point ops respectively */
PPCOpcode SubOpcode31Grabber[1024] = { ppc_illegalop };
PPCOpcode SubOpcode59Grabber[32] = { ppc_illegalop };
PPCOpcode SubOpcode63Grabber[1024] = { ppc_illegalop };
PPCOpcode SubOpcode31Grabber[1024];
PPCOpcode SubOpcode59Grabber[32];
PPCOpcode SubOpcode63Grabber[1024];
/** Exception helpers. */
@ -575,6 +575,7 @@ void ppc_exec_dbg(volatile uint32_t start_addr, volatile uint32_t size)
}
void initialize_ppc_opcode_tables() {
std::fill_n(SubOpcode31Grabber, 1024, ppc_illegalop);
SubOpcode31Grabber[0] = ppc_cmp;
SubOpcode31Grabber[4] = ppc_tw;
SubOpcode31Grabber[32] = ppc_cmpl;
@ -709,6 +710,7 @@ void initialize_ppc_opcode_tables() {
SubOpcode31Grabber[978] = ppc_tlbld;
SubOpcode31Grabber[1010] = ppc_tlbli;
std::fill_n(SubOpcode59Grabber, 32, ppc_illegalop);
SubOpcode59Grabber[18] = ppc_fdivs;
SubOpcode59Grabber[20] = ppc_fsubs;
SubOpcode59Grabber[21] = ppc_fadds;
@ -720,6 +722,7 @@ void initialize_ppc_opcode_tables() {
SubOpcode59Grabber[30] = ppc_fnmsubs;
SubOpcode59Grabber[31] = ppc_fnmadds;
std::fill_n(SubOpcode63Grabber, 1024, ppc_illegalop);
SubOpcode63Grabber[0] = ppc_fcmpu;
SubOpcode63Grabber[12] = ppc_frsp;
SubOpcode63Grabber[14] = ppc_fctiw;

View File

@ -685,7 +685,7 @@ void dppc_interpreter::ppc_sraw() {
ppc_state.spr[SPR::XER] |= (ppc_result_a & 1) << 29;
} else {
uint32_t shift = ppc_result_b & 0x1F;
uint32_t mask = (1 << shift) - 1;
uint32_t mask = (1U << shift) - 1;
ppc_result_a = (int32_t)ppc_result_d >> shift;
if ((ppc_result_d & 0x80000000UL) && (ppc_result_d & mask)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
@ -703,7 +703,7 @@ void dppc_interpreter::ppc_sraw() {
void dppc_interpreter::ppc_srawi() {
ppc_grab_regssa();
unsigned shift = (ppc_cur_instruction >> 11) & 0x1F;
uint32_t mask = (1 << shift) - 1;
uint32_t mask = (1U << shift) - 1;
ppc_result_a = (int32_t)ppc_result_d >> shift;
if ((ppc_result_d & 0x80000000UL) && (ppc_result_d & mask)) {
ppc_state.spr[SPR::XER] |= 0x20000000UL;
@ -730,7 +730,7 @@ void dppc_interpreter::ppc_rlwimi() {
unsigned rot_mb = (ppc_cur_instruction >> 6) & 31;
unsigned rot_me = (ppc_cur_instruction >> 1) & 31;
uint32_t mask = rot_mask(rot_mb, rot_me);
uint32_t r = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t r = rot_sh ? ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh))) : ppc_result_d;
ppc_result_a = (ppc_result_a & ~mask) | (r & mask);
if ((ppc_cur_instruction & 0x01) == 1) {
ppc_changecrf0(ppc_result_a);
@ -744,7 +744,7 @@ void dppc_interpreter::ppc_rlwinm() {
unsigned rot_mb = (ppc_cur_instruction >> 6) & 31;
unsigned rot_me = (ppc_cur_instruction >> 1) & 31;
uint32_t mask = rot_mask(rot_mb, rot_me);
uint32_t r = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
uint32_t r = rot_sh ? ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh))) : ppc_result_d;
ppc_result_a = r & mask;
if ((ppc_cur_instruction & 0x01) == 1) {
ppc_changecrf0(ppc_result_a);
@ -757,7 +757,8 @@ void dppc_interpreter::ppc_rlwnm() {
unsigned rot_mb = (ppc_cur_instruction >> 6) & 31;
unsigned rot_me = (ppc_cur_instruction >> 1) & 31;
uint32_t mask = rot_mask(rot_mb, rot_me);
uint32_t r = ((ppc_result_d << ppc_result_b) | (ppc_result_d >> (32 - ppc_result_b)));
uint32_t rot = ppc_result_b & 0x1F;
uint32_t r = rot ? ((ppc_result_d << rot) | (ppc_result_d >> (32 - rot))) : ppc_result_d;
ppc_result_a = r & mask;
if ((ppc_cur_instruction & 0x01) == 1) {
ppc_changecrf0(ppc_result_a);