From 0d5817042ee34badecd22b1d044f28fcec0856b0 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Sat, 25 Dec 2021 18:44:43 +0100 Subject: [PATCH] Refactor the interpreter, part 1: loads and stores. --- cpu/ppc/ppcdefs.h | 61 +++++ cpu/ppc/ppcemu.h | 20 +- cpu/ppc/ppcexec.cpp | 30 +-- cpu/ppc/ppcopcodes.cpp | 525 ++++++++++++----------------------------- 4 files changed, 231 insertions(+), 405 deletions(-) create mode 100644 cpu/ppc/ppcdefs.h diff --git a/cpu/ppc/ppcdefs.h b/cpu/ppc/ppcdefs.h new file mode 100644 index 0000000..1682c4d --- /dev/null +++ b/cpu/ppc/ppcdefs.h @@ -0,0 +1,61 @@ +/* +DingusPPC - The Experimental PowerPC Macintosh emulator +Copyright (C) 2018-21 divingkatae and maximum + (theweirdo) spatium + +(Contact divingkatae#1017 or powermax#2286 on Discord for more info) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef PPC_DEFS_H +#define PPC_DEFS_H + +#include + +#define GET_rD_rA_OFFS(opcode) \ + uint32_t reg_d = ((opcode) >> 21) & 31; \ + uint32_t reg_a = ((opcode) >> 16) & 31; \ + int32_t offs = (int32_t)((int16_t)((opcode) & 0xFFFF)); + +#define GET_GPR(reg) ppc_state.gpr[(reg)] +#define SET_GPR(reg, val) ppc_state.gpr[(reg)] = (val) + +#define GET_rD_iA_iB(opcode) \ + uint32_t reg_d = ((opcode) >> 21) & 31; \ + uint32_t imm_a = ppc_state.gpr[((opcode) >> 16) & 31]; \ + uint32_t imm_b = ppc_state.gpr[((opcode) >> 11) & 31]; + +#define GET_rD_rA_iA_iB(opcode) \ + uint32_t reg_d = ((opcode) >> 21) & 31; \ + uint32_t reg_a = ((opcode) >> 16) & 31; \ + uint32_t imm_a = ppc_state.gpr[reg_a]; \ + uint32_t imm_b = ppc_state.gpr[((opcode) >> 11) & 31]; + +#define GET_rA_iS(opcode) \ + uint32_t reg_a = ((opcode) >> 16) & 31; \ + uint32_t imm_d = ppc_state.gpr[((opcode) >> 21) & 31]; + +#define GET_rS_rA_OFFS(opcode) \ + uint32_t reg_s = ((opcode) >> 21) & 31; \ + uint32_t reg_a = ((opcode) >> 16) & 31; \ + int32_t offs = (int32_t)((int16_t)((opcode) & 0xFFFF)); + +#define GET_rS_rA_iA_iB(opcode) \ + uint32_t reg_s = ((opcode) >> 21) & 31; \ + uint32_t reg_a = ((opcode) >> 16) & 31; \ + uint32_t imm_a = ppc_state.gpr[reg_a]; \ + uint32_t imm_b = ppc_state.gpr[((opcode) >> 11) & 31]; + +#endif // PPC_DEFS_H diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index b0596af..15b7109 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -505,14 +505,16 @@ extern void ppc_bcl(); extern void ppc_bcla(); extern void ppc_cmpi(); extern void ppc_cmpli(); -extern void ppc_lbz(); -extern void ppc_lbzu(); extern void ppc_lha(); extern void ppc_lhau(); -extern void ppc_lhz(); -extern void ppc_lhzu(); -extern void ppc_lwz(); -extern void ppc_lwzu(); +template void ppc_lz(void); +template void ppc_lzu(void); +template void ppc_lzux(void); +template void ppc_lzx(void); +template void ppc_st(void); +template void ppc_stu(void); +template void ppc_stux(void); +template void ppc_stx(void); extern void ppc_lmw(); extern void ppc_mulli(); extern void ppc_ori(); @@ -522,12 +524,6 @@ extern void ppc_rlwimi(); extern void ppc_rlwinm(); extern void ppc_rlwnm(); extern void ppc_sc(); -extern void ppc_stb(); -extern void ppc_stbu(); -extern void ppc_sth(); -extern void ppc_sthu(); -extern void ppc_stw(); -extern void ppc_stwu(); extern void ppc_stmw(); extern void ppc_subfic(); extern void ppc_twi(); diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index 3b0f711..bf78c05 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -136,9 +136,9 @@ static PPCOpcode OpcodeGrabber[] = { ppc_addic, ppc_addicdot, ppc_addi, ppc_addis, ppc_opcode16, ppc_sc, ppc_opcode18, ppc_opcode19, ppc_rlwimi, ppc_rlwinm, power_rlmi, ppc_rlwnm, ppc_ori, ppc_oris, ppc_xori, ppc_xoris, ppc_andidot, ppc_andisdot, - ppc_illegalop, ppc_opcode31, ppc_lwz, ppc_lwzu, ppc_lbz, ppc_lbzu, - ppc_stw, ppc_stwu, ppc_stb, ppc_stbu, ppc_lhz, ppc_lhzu, - ppc_lha, ppc_lhau, ppc_sth, ppc_sthu, ppc_lmw, ppc_stmw, + ppc_illegalop, ppc_opcode31, ppc_lz, ppc_lzu, ppc_lz, ppc_lzu, + ppc_st, ppc_stu, ppc_st, ppc_stu, ppc_lz, ppc_lzu, + ppc_lha, ppc_lhau, ppc_st, ppc_stu, ppc_lmw, ppc_stmw, ppc_lfs, ppc_lfsu, ppc_lfd, ppc_lfdu, ppc_stfs, ppc_stfsu, ppc_stfd, ppc_stfdu, ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_opcode59, ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_opcode63}; @@ -818,12 +818,12 @@ void initialize_ppc_opcode_tables() { SubOpcode31Grabber[491] = SubOpcode31Grabber[1003] = ppc_divw; SubOpcode31Grabber[20] = ppc_lwarx; - SubOpcode31Grabber[23] = ppc_lwzx; - SubOpcode31Grabber[55] = ppc_lwzux; - SubOpcode31Grabber[87] = ppc_lbzx; - SubOpcode31Grabber[119] = ppc_lbzux; - SubOpcode31Grabber[279] = ppc_lhzx; - SubOpcode31Grabber[311] = ppc_lhzux; + SubOpcode31Grabber[23] = ppc_lzx; + SubOpcode31Grabber[55] = ppc_lzux; + SubOpcode31Grabber[87] = ppc_lzx; + SubOpcode31Grabber[119] = ppc_lzux; + SubOpcode31Grabber[279] = ppc_lzx; + SubOpcode31Grabber[311] = ppc_lzux; SubOpcode31Grabber[343] = ppc_lhax; SubOpcode31Grabber[375] = ppc_lhaux; SubOpcode31Grabber[533] = ppc_lswx; @@ -836,12 +836,12 @@ void initialize_ppc_opcode_tables() { SubOpcode31Grabber[790] = ppc_lhbrx; SubOpcode31Grabber[150] = ppc_stwcx; - SubOpcode31Grabber[151] = ppc_stwx; - SubOpcode31Grabber[183] = ppc_stwux; - SubOpcode31Grabber[215] = ppc_stbx; - SubOpcode31Grabber[247] = ppc_stbux; - SubOpcode31Grabber[407] = ppc_sthx; - SubOpcode31Grabber[439] = ppc_sthux; + SubOpcode31Grabber[151] = ppc_stx; + SubOpcode31Grabber[183] = ppc_stux; + SubOpcode31Grabber[215] = ppc_stx; + SubOpcode31Grabber[247] = ppc_stux; + SubOpcode31Grabber[407] = ppc_stx; + SubOpcode31Grabber[439] = ppc_stux; SubOpcode31Grabber[661] = ppc_stswx; SubOpcode31Grabber[662] = ppc_stwbrx; SubOpcode31Grabber[663] = ppc_stfsx; diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index 5f9073e..bf56104 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -21,6 +21,7 @@ along with this program. If not, see . // General opcodes for the processor - ppcopcodes.cpp +#include "ppcdefs.h" #include "ppcemu.h" #include "ppcmmu.h" #include @@ -1415,203 +1416,112 @@ void dppc_interpreter::ppc_dcbz() { // Integer Load and Store Functions -void dppc_interpreter::ppc_stb() { +template +void dppc_interpreter::ppc_st() { #ifdef CPU_PROFILING num_int_stores++; #endif - ppc_grab_regssa(); - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += reg_a ? ppc_result_a : 0; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_byte(ppc_effective_address, ppc_result_d); + GET_rS_rA_OFFS(ppc_cur_instruction); + uint32_t ea = offs + (reg_a ? GET_GPR(reg_a) : 0); + mmu_write_vmem(ea, GET_GPR(reg_s)); } -void dppc_interpreter::ppc_stbx() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - ppc_grab_regssab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_byte(ppc_effective_address, ppc_result_d); -} +// explicitely instantiate all required ppc_st variants +template void dppc_interpreter::ppc_st(void); // stb +template void dppc_interpreter::ppc_st(void); // sth +template void dppc_interpreter::ppc_st(void); // stw -void dppc_interpreter::ppc_stbu() { +template +void dppc_interpreter::ppc_stu() { #ifdef CPU_PROFILING num_int_stores++; #endif - ppc_grab_regssa(); - if (reg_a != 0) { - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += ppc_result_a; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_byte(ppc_effective_address, ppc_result_d); - ppc_state.gpr[reg_a] = ppc_effective_address; - } else { + GET_rS_rA_OFFS(ppc_cur_instruction); + if (!reg_a) { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } + uint32_t ea = offs + GET_GPR(reg_a); + mmu_write_vmem(ea, GET_GPR(reg_s)); + SET_GPR(reg_a, ea); } -void dppc_interpreter::ppc_stbux() { +// explicitely instantiate all required ppc_stu variants +template void dppc_interpreter::ppc_stu(void); // stbu +template void dppc_interpreter::ppc_stu(void); // sthu +template void dppc_interpreter::ppc_stu(void); // stwu + +template +void dppc_interpreter::ppc_stx() { #ifdef CPU_PROFILING num_int_stores++; #endif - ppc_grab_regssab(); - if (reg_a != 0) { - ppc_effective_address = ppc_result_a + ppc_result_b; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_byte(ppc_effective_address, ppc_result_d); - ppc_state.gpr[reg_a] = ppc_effective_address; - } else { + GET_rS_rA_iA_iB(ppc_cur_instruction); + uint32_t ea = imm_b + ((reg_a) ? imm_a : 0); + mmu_write_vmem(ea, GET_GPR(reg_s)); +} + +// explicitely instantiate all required ppc_stx variants +template void dppc_interpreter::ppc_stx(void); // stbx +template void dppc_interpreter::ppc_stx(void); // sthx +template void dppc_interpreter::ppc_stx(void); // stwx + +template +void dppc_interpreter::ppc_stux() { +#ifdef CPU_PROFILING + num_int_stores++; +#endif + GET_rS_rA_iA_iB(ppc_cur_instruction); + if (!reg_a) { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } + uint32_t ea = imm_a + imm_b; + mmu_write_vmem(ea, GET_GPR(reg_s)); + SET_GPR(reg_a, ea); } -void dppc_interpreter::ppc_sth() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - ppc_grab_regssa(); - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_word(ppc_effective_address, ppc_result_d); -} +// explicitely instantiate all required ppc_stux variants +template void dppc_interpreter::ppc_stux(void); // stbux +template void dppc_interpreter::ppc_stux(void); // sthux +template void dppc_interpreter::ppc_stux(void); // stwux -void dppc_interpreter::ppc_sthu() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - ppc_grab_regssa(); - if (reg_a != 0) { - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += ppc_result_a; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_word(ppc_effective_address, ppc_result_d); - ppc_state.gpr[reg_a] = ppc_effective_address; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } -} - -void dppc_interpreter::ppc_sthux() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - ppc_grab_regssab(); - if (reg_a != 0) { - ppc_effective_address = ppc_result_a + ppc_result_b; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_word(ppc_effective_address, ppc_result_d); - ppc_state.gpr[reg_a] = ppc_effective_address; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } -} - -void dppc_interpreter::ppc_sthx() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - ppc_grab_regssab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_word(ppc_effective_address, ppc_result_d); -} void dppc_interpreter::ppc_sthbrx() { #ifdef CPU_PROFILING num_int_stores++; #endif - ppc_grab_regssab(); - ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b); - ppc_result_d = (uint32_t)(BYTESWAP_16((uint16_t)ppc_result_d)); - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_word(ppc_effective_address, ppc_result_d); -} - -void dppc_interpreter::ppc_stw() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - ppc_grab_regssa(); - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += reg_a ? ppc_result_a : 0; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_dword(ppc_effective_address, ppc_result_d); -} - -void dppc_interpreter::ppc_stwx() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - ppc_grab_regssab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_dword(ppc_effective_address, ppc_result_d); -} - -void dppc_interpreter::ppc_stwcx() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - // PLACEHOLDER CODE FOR STWCX - We need to check for reserve memory - if (rc_flag == 0) { - ppc_illegalop(); - } else { - ppc_grab_regssab(); - ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b); - if (ppc_state.reserve) { - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_dword(ppc_effective_address, ppc_result_d); - ppc_state.cr |= (ppc_state.spr[SPR::XER] & 0x80000000) ? 0x30000000 : 0x20000000; - ppc_state.reserve = false; - } else { - ppc_state.cr |= (ppc_state.spr[SPR::XER] & 0x80000000) ? 0x10000000 : 0; - } - } -} - -void dppc_interpreter::ppc_stwu() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - ppc_grab_regssa(); - if (reg_a != 0) { - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += ppc_result_a; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_dword(ppc_effective_address, ppc_result_d); - ppc_state.gpr[reg_a] = ppc_effective_address; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } -} - -void dppc_interpreter::ppc_stwux() { -#ifdef CPU_PROFILING - num_int_stores++; -#endif - ppc_grab_regssab(); - if (reg_a != 0) { - ppc_effective_address = ppc_result_a + ppc_result_b; - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_dword(ppc_effective_address, ppc_result_d); - ppc_state.gpr[reg_a] = ppc_effective_address; - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } + GET_rS_rA_iA_iB(ppc_cur_instruction); + uint32_t ea = imm_b + ((reg_a) ? imm_a : 0); + mmu_write_vmem(ea, BYTESWAP_16((uint16_t)(GET_GPR(reg_s)))); } void dppc_interpreter::ppc_stwbrx() { #ifdef CPU_PROFILING num_int_stores++; #endif - ppc_grab_regssab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - ppc_result_d = BYTESWAP_32(ppc_result_d); - mmu_write_vmem(ppc_effective_address, ppc_result_d); - //mem_write_dword(ppc_effective_address, ppc_result_d); + GET_rS_rA_iA_iB(ppc_cur_instruction); + uint32_t ea = imm_b + ((reg_a) ? imm_a : 0); + mmu_write_vmem(ea, BYTESWAP_32(GET_GPR(reg_s))); +} + + +void dppc_interpreter::ppc_stwcx() { +#ifdef CPU_PROFILING + num_int_stores++; +#endif + if (rc_flag == 0) { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); + } else { + // TODO: We need to check for memory reservation + ppc_grab_regssab(); + ppc_effective_address = (reg_a == 0) ? ppc_result_b : (ppc_result_a + ppc_result_b); + if (ppc_state.reserve) { + mmu_write_vmem(ppc_effective_address, ppc_result_d); + ppc_state.cr |= (ppc_state.spr[SPR::XER] & 0x80000000) ? 0x30000000 : 0x20000000; + ppc_state.reserve = false; + } else { + ppc_state.cr |= (ppc_state.spr[SPR::XER] & 0x80000000) ? 0x10000000 : 0; + } + } } void dppc_interpreter::ppc_stmw() { @@ -1634,277 +1544,136 @@ void dppc_interpreter::ppc_stmw() { } } -void dppc_interpreter::ppc_lbz() { -#ifdef CPU_PROFILING - num_int_loads++; -#endif - ppc_grab_regsda(); - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0; - //ppc_result_d = mem_grab_byte(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_store_result_regd(); -} - -void dppc_interpreter::ppc_lbzu() { -#ifdef CPU_PROFILING - num_int_loads++; -#endif - ppc_grab_regsda(); - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - if ((reg_a != reg_d) || reg_a != 0) { - ppc_effective_address += ppc_result_a; - //ppc_result_d = mem_grab_byte(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_result_a = ppc_effective_address; - ppc_store_result_regd(); - ppc_store_result_rega(); - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } -} - -void dppc_interpreter::ppc_lbzx() { -#ifdef CPU_PROFILING - num_int_loads++; -#endif - ppc_grab_regsdab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - //ppc_result_d = mem_grab_byte(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_store_result_regd(); -} - -void dppc_interpreter::ppc_lbzux() { -#ifdef CPU_PROFILING - num_int_loads++; -#endif - ppc_grab_regsdab(); - if ((reg_a != reg_d) || reg_a != 0) { - ppc_effective_address = ppc_result_a + ppc_result_b; - //ppc_result_d = mem_grab_byte(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_result_a = ppc_effective_address; - ppc_store_result_regd(); - ppc_store_result_rega(); - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } -} - - -void dppc_interpreter::ppc_lhz() { -#ifdef CPU_PROFILING - num_int_loads++; -#endif - ppc_grab_regsda(); - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += reg_a ? ppc_result_a : 0; - //ppc_result_d = mem_grab_word(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_store_result_regd(); -} - -void dppc_interpreter::ppc_lhzu() { -#ifdef CPU_PROFILING - num_int_loads++; -#endif - ppc_grab_regsda(); - if ((reg_a != reg_d) || reg_a != 0) { - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += ppc_result_a; - //ppc_result_d = mem_grab_word(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_result_a = ppc_effective_address; - ppc_store_result_regd(); - ppc_store_result_rega(); - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } -} - -void dppc_interpreter::ppc_lhzx() { -#ifdef CPU_PROFILING - num_int_loads++; -#endif - ppc_grab_regsdab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - //ppc_result_d = mem_grab_word(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_store_result_regd(); -} - -void dppc_interpreter::ppc_lhzux() { -#ifdef CPU_PROFILING - num_int_loads++; -#endif - ppc_grab_regsdab(); - if ((reg_a != reg_d) || reg_a != 0) { - ppc_effective_address = ppc_result_a + ppc_result_b; - //ppc_result_d = mem_grab_word(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_result_a = ppc_effective_address; - ppc_store_result_regd(); - ppc_store_result_rega(); - } else { - ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); - } -} - void dppc_interpreter::ppc_lha() { #ifdef CPU_PROFILING num_int_loads++; #endif - ppc_grab_regsda(); - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0; - //uint16_t val = mem_grab_word(ppc_effective_address); - uint16_t val = mmu_read_vmem(ppc_effective_address); - if (val & 0x8000) { - ppc_result_d = 0xFFFF0000UL | (uint32_t)val; - } else { - ppc_result_d = (uint32_t)val; - } - ppc_store_result_regd(); + GET_rD_rA_OFFS(ppc_cur_instruction); + uint32_t ea = offs + ((reg_a) ? ppc_state.gpr[reg_a] : 0); + SET_GPR(reg_d, (int32_t)((int16_t)mmu_read_vmem(ea))); } void dppc_interpreter::ppc_lhau() { #ifdef CPU_PROFILING num_int_loads++; #endif - ppc_grab_regsda(); - if ((reg_a != reg_d) || reg_a != 0) { - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += ppc_result_a; - //uint16_t val = mem_grab_word(ppc_effective_address); - uint16_t val = mmu_read_vmem(ppc_effective_address); - if (val & 0x8000) { - ppc_result_d = 0xFFFF0000UL | (uint32_t)val; - } else { - ppc_result_d = (uint32_t)val; - } - ppc_store_result_regd(); - ppc_result_a = ppc_effective_address; - ppc_store_result_rega(); - } else { + GET_rD_rA_OFFS(ppc_cur_instruction); + if ((reg_a == reg_d) || reg_a == 0) { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } + uint32_t ea = offs + ppc_state.gpr[reg_a]; + SET_GPR(reg_d, (int32_t)((int16_t)mmu_read_vmem(ea))); + SET_GPR(reg_a, ea); } void dppc_interpreter::ppc_lhaux() { #ifdef CPU_PROFILING num_int_loads++; #endif - ppc_grab_regsdab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - //uint16_t val = mem_grab_word(ppc_effective_address); - uint16_t val = mmu_read_vmem(ppc_effective_address); - if (val & 0x8000) { - ppc_result_d = 0xFFFF0000UL | (uint32_t)val; - } else { - ppc_result_d = (uint32_t)val; + GET_rD_rA_iA_iB(ppc_cur_instruction); + if ((reg_a == reg_d) || reg_a == 0) { + ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } - ppc_store_result_regd(); - ppc_result_a = ppc_effective_address; - ppc_store_result_rega(); + uint32_t ea = imm_a + imm_b; + SET_GPR(reg_d, (int32_t)((int16_t)mmu_read_vmem(ea))); + SET_GPR(reg_a, ea); } void dppc_interpreter::ppc_lhax() { #ifdef CPU_PROFILING num_int_loads++; #endif - ppc_grab_regsdab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - //uint16_t val = mem_grab_word(ppc_effective_address); - uint16_t val = mmu_read_vmem(ppc_effective_address); - if (val & 0x8000) { - ppc_result_d = 0xFFFF0000UL | (uint32_t)val; - } else { - ppc_result_d = (uint32_t)val; - } - ppc_store_result_regd(); + GET_rD_rA_iA_iB(ppc_cur_instruction); + uint32_t ea = imm_b + ((reg_a) ? imm_a : 0); + SET_GPR(reg_d, (int32_t)((int16_t)mmu_read_vmem(ea))); } void dppc_interpreter::ppc_lhbrx() { #ifdef CPU_PROFILING num_int_loads++; #endif - ppc_grab_regsdab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - //ppc_result_d = (uint32_t)(BYTESWAP_16(mem_grab_word(ppc_effective_address))); - ppc_result_d = (uint32_t)(BYTESWAP_16(mmu_read_vmem(ppc_effective_address))); - ppc_store_result_regd(); -} - -void dppc_interpreter::ppc_lwz() { -#ifdef CPU_PROFILING - num_int_loads++; -#endif - ppc_grab_regsda(); - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0; - //ppc_result_d = mem_grab_dword(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_store_result_regd(); + GET_rD_rA_iA_iB(ppc_cur_instruction); + uint32_t ea = imm_b + ((reg_a) ? imm_a : 0); + SET_GPR(reg_d, BYTESWAP_16(mmu_read_vmem(ea))); } void dppc_interpreter::ppc_lwbrx() { #ifdef CPU_PROFILING num_int_loads++; #endif - ppc_grab_regsdab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - //ppc_result_d = BYTESWAP_32(mem_grab_dword(ppc_effective_address)); - ppc_result_d = BYTESWAP_32(mmu_read_vmem(ppc_effective_address)); - ppc_store_result_regd(); + GET_rD_rA_iA_iB(ppc_cur_instruction); + uint32_t ea = imm_b + ((reg_a) ? imm_a : 0); + SET_GPR(reg_d, BYTESWAP_32(mmu_read_vmem(ea))); } -void dppc_interpreter::ppc_lwzu() { +template +void dppc_interpreter::ppc_lz() { #ifdef CPU_PROFILING num_int_loads++; #endif - ppc_grab_regsda(); - ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF)); - if ((reg_a != reg_d) || reg_a != 0) { - ppc_effective_address += ppc_result_a; - //ppc_result_d = mem_grab_dword(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_store_result_regd(); - ppc_result_a = ppc_effective_address; - ppc_store_result_rega(); - } else { + GET_rD_rA_OFFS(ppc_cur_instruction); + uint32_t ea = offs + ((reg_a) ? ppc_state.gpr[reg_a] : 0); + SET_GPR(reg_d, mmu_read_vmem(ea)); +} + +// explicitely instantiate all required ppc_lz variants +template void dppc_interpreter::ppc_lz(void); // lbz +template void dppc_interpreter::ppc_lz(void); // lhz +template void dppc_interpreter::ppc_lz(void); // lwz + +template +void dppc_interpreter::ppc_lzu() { +#ifdef CPU_PROFILING + num_int_loads++; +#endif + GET_rD_rA_OFFS(ppc_cur_instruction); + if ((reg_a == reg_d) || reg_a == 0) { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } + uint32_t ea = offs + ppc_state.gpr[reg_a]; + SET_GPR(reg_d, mmu_read_vmem(ea)); + SET_GPR(reg_a, ea); } -void dppc_interpreter::ppc_lwzx() { +// explicitely instantiate all required ppc_lzu variants +template void dppc_interpreter::ppc_lzu(void); // lbzu +template void dppc_interpreter::ppc_lzu(void); // lhzu +template void dppc_interpreter::ppc_lzu(void); // lwzu + +template +void dppc_interpreter::ppc_lzx() { #ifdef CPU_PROFILING num_int_loads++; #endif - ppc_grab_regsdab(); - ppc_effective_address = reg_a ? (ppc_result_a + ppc_result_b) : ppc_result_b; - //ppc_result_d = mem_grab_dword(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_store_result_regd(); + GET_rD_rA_iA_iB(ppc_cur_instruction); + uint32_t ea = imm_b + ((reg_a) ? imm_a : 0); + SET_GPR(reg_d, mmu_read_vmem(ea)); } -void dppc_interpreter::ppc_lwzux() { +// explicitely instantiate all required ppc_lzx variants +template void dppc_interpreter::ppc_lzx(void); // lbzx +template void dppc_interpreter::ppc_lzx(void); // lhzx +template void dppc_interpreter::ppc_lzx(void); // lwzx + +template +void dppc_interpreter::ppc_lzux() { #ifdef CPU_PROFILING num_int_loads++; #endif - ppc_grab_regsdab(); - if ((reg_a != reg_d) || reg_a != 0) { - ppc_effective_address = ppc_result_a + ppc_result_b; - } else { + GET_rD_rA_iA_iB(ppc_cur_instruction); + if ((reg_a == reg_d) || reg_a == 0) { ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP); } - //ppc_result_d = mem_grab_dword(ppc_effective_address); - ppc_result_d = mmu_read_vmem(ppc_effective_address); - ppc_result_a = ppc_effective_address; - ppc_store_result_regd(); - ppc_store_result_rega(); + uint32_t ea = imm_a + imm_b; + SET_GPR(reg_d, mmu_read_vmem(ea)); + SET_GPR(reg_a, ea); } +// explicitely instantiate all required ppc_lzux variants +template void dppc_interpreter::ppc_lzux(void); // lbzux +template void dppc_interpreter::ppc_lzux(void); // lhzux +template void dppc_interpreter::ppc_lzux(void); // lwzux + void dppc_interpreter::ppc_lwarx() { #ifdef CPU_PROFILING num_int_loads++;