From 20665b9f891182ab9ded2a851d8234b838f6b7c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Wed, 18 Sep 2013 23:50:00 +0200 Subject: [PATCH 1/7] Improved sys_fs module - cellFsStat now accepts mounting points in the path argument. - cellFsMkdir, cellFsRmdir, cellFsUnlink and cellFsRename are now using the real path provided by the VFS. - cellFsFtruncate, cellFsTruncate and cellFsFGetBlockSize are partially implemented. Note: I have spotted a bug in cellFsRename and cellFsRmdir (this has nothing to do with the changes I made), but I don't dare to fix it since I am not sure if I will break other functions with my solution. --- rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 3 + rpcs3/Emu/SysCalls/SysCalls.h | 3 + rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp | 116 +++++++++++++++++++++-- 3 files changed, 115 insertions(+), 7 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index c4d4736cff..79cf6f1cba 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -21,4 +21,7 @@ void sys_fs_init() sys_fs.AddFunc(0x2796fdf3, cellFsRmdir); sys_fs.AddFunc(0x7f4677a8, cellFsUnlink); sys_fs.AddFunc(0xa397d042, cellFsLseek); + sys_fs.AddFunc(0x0e2939e5, cellFsFtruncate); + sys_fs.AddFunc(0xc9dc3ac5, cellFsTruncate); + sys_fs.AddFunc(0xcb588dba, cellFsFGetBlockSize); } diff --git a/rpcs3/Emu/SysCalls/SysCalls.h b/rpcs3/Emu/SysCalls/SysCalls.h index 159f168d57..c54bfc70cc 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.h +++ b/rpcs3/Emu/SysCalls/SysCalls.h @@ -189,6 +189,9 @@ extern int cellFsRename(u32 from_addr, u32 to_addr); extern int cellFsRmdir(u32 path_addr); extern int cellFsUnlink(u32 path_addr); extern int cellFsLseek(u32 fd, s64 offset, u32 whence, u32 pos_addr); +extern int cellFsFtruncate(u32 fd, u64 size); +extern int cellFsTruncate(u32 path_addr, u64 size); +extern int cellFsFGetBlockSize(u32 fd, u32 sector_size_addr, u32 block_size_addr); //cellVideo extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index a281671f61..6c409df644 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -247,6 +247,16 @@ int cellFsStat(const u32 path_addr, const u32 sb_addr) const wxString& path = Memory.ReadString(path_addr); sys_fs.Log("cellFsFstat(path: %s, sb_addr: 0x%x)", path, sb_addr); + // Check if path is a mount point. (TODO: Add information in sb_addr) + for(u32 i=0; iIsOpened()) { @@ -322,7 +332,9 @@ int cellFsFstat(u32 fd, u32 sb_addr) int cellFsMkdir(u32 path_addr, u32 mode) { - const wxString& path = Memory.ReadString(path_addr); + const wxString& ps3_path = Memory.ReadString(path_addr); + wxString path; + Emu.GetVFS().GetDevice(ps3_path, path); sys_fs.Log("cellFsMkdir(path: %s, mode: 0x%x)", path, mode); if(wxDirExists(path)) return CELL_EEXIST; if(!wxMkdir(path)) return CELL_EBUSY; @@ -331,27 +343,36 @@ int cellFsMkdir(u32 path_addr, u32 mode) int cellFsRename(u32 from_addr, u32 to_addr) { - const wxString& from = Memory.ReadString(from_addr); - const wxString& to = Memory.ReadString(to_addr); + const wxString& ps3_from = Memory.ReadString(from_addr); + const wxString& ps3_to = Memory.ReadString(to_addr); + wxString from; + wxString to; + Emu.GetVFS().GetDevice(ps3_from, from); + Emu.GetVFS().GetDevice(ps3_to, to); + sys_fs.Log("cellFsRename(from: %s, to: %s)", from, to); if(!wxFileExists(from)) return CELL_ENOENT; if(wxFileExists(to)) return CELL_EEXIST; - if(!wxRenameFile(from, to)) return CELL_EBUSY; + if(!wxRenameFile(from, to)) return CELL_EBUSY; // (TODO: RenameFile(a,b) = CopyFile(a,b) + RemoveFile(a), therefore file "a" will not be removed if it is opened) return CELL_OK; } int cellFsRmdir(u32 path_addr) { - const wxString& path = Memory.ReadString(path_addr); + const wxString& ps3_path = Memory.ReadString(path_addr); + wxString path; + Emu.GetVFS().GetDevice(ps3_path, path); sys_fs.Log("cellFsRmdir(path: %s)", path); if(!wxDirExists(path)) return CELL_ENOENT; - if(!wxRmdir(path)) return CELL_EBUSY; + if(!wxRmdir(path)) return CELL_EBUSY; // (TODO: Under certain conditions it is not able to delete the folder) return CELL_OK; } int cellFsUnlink(u32 path_addr) { - const wxString& path = Memory.ReadString(path_addr); + const wxString& ps3_path = Memory.ReadString(path_addr); + wxString path; + Emu.GetVFS().GetDevice(ps3_path, path); sys_fs.Error("cellFsUnlink(path: %s)", path); return CELL_OK; } @@ -373,5 +394,86 @@ int cellFsLseek(u32 fd, s64 offset, u32 whence, u32 pos_addr) if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; vfsStream& file = *(vfsStream*)id.m_data; Memory.Write64(pos_addr, file.Seek(offset, seek_mode)); + return CELL_OK; +} + +int cellFsFtruncate(u32 fd, u64 size) +{ + sys_fs.Log("cellFsFtruncate(fd: %d, size: %lld)", fd, size); + ID id; + if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + vfsStream& file = *(vfsStream*)id.m_data; + u64 initialSize = file.GetSize(); + + if (initialSize < size) // Is there any better way to fill the remaining bytes with 0, without allocating huge buffers in memory, or writing such a spaghetti code? + { + u64 last_pos = file.Tell(); + file.Seek(0, vfsSeekEnd); + char* nullblock = (char*)calloc(4096, sizeof(char)); + for(u64 i = (size-initialSize)/4096; i > 0; i--){ + file.Write(nullblock, 4096); + } + free(nullblock); + char nullbyte = 0; + for(u64 i = (size-initialSize)%4096; i > 0; i--){ + file.Write(&nullbyte, 1); + } + file.Seek(last_pos, vfsSeekSet); + } + + if (initialSize > size) + { + // (TODO) + } + + return CELL_OK; +} + +int cellFsTruncate(u32 path_addr, u64 size) +{ + const wxString& path = Memory.ReadString(path_addr); + sys_fs.Log("cellFsTruncate(path_addr: %s, size: %lld)", path, size); + + vfsStream* f = Emu.GetVFS().Open(path, vfsRead); + if(!f || !f->IsOpened()) + { + sys_fs.Warning("cellFsTruncate: '%s' not found.", path); + Emu.GetVFS().Close(f); + return CELL_ENOENT; + } + u64 initialSize = f->GetSize(); + + if (initialSize < size) // Is there any better way to fill the remaining bytes with 0, without allocating huge buffers in memory, or writing such a spaghetti code? + { + u64 last_pos = f->Tell(); + f->Seek(0, vfsSeekEnd); + char* nullblock = (char*)calloc(4096, sizeof(char)); + for(u64 i = (size-initialSize)/4096; i > 0; i--){ + f->Write(nullblock, 4096); + } + free(nullblock); + char nullbyte = 0; + for(u64 i = (size-initialSize)%4096; i > 0; i--){ + f->Write(&nullbyte, 1); + } + f->Seek(last_pos, vfsSeekSet); + } + + if (initialSize > size) + { + // (TODO) + } + + Emu.GetVFS().Close(f); + return CELL_OK; +} + +int cellFsFGetBlockSize(u32 fd, u32 sector_size_addr, u32 block_size_addr) +{ + sys_fs.Log("cellFsFGetBlockSize(fd: %d, sector_size_addr: 0x%x, block_size_addr: 0x%x)", fd, sector_size_addr, block_size_addr); + + Memory.Write64(sector_size_addr, 4096); // ? + Memory.Write64(block_size_addr, 4096); // ? + return CELL_OK; } \ No newline at end of file From a11de0f607b3bb81a16c0e48ea2456ce57b0824f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Thu, 19 Sep 2013 23:40:43 +0200 Subject: [PATCH 2/7] Improved image decoding modules * Huge improvement in the speed of cell{Png|Gif|Jpg}DecDecodeData when reading input files. Note: Sorry if this commit is too "small", but I need to sync every change since I use two PCs. --- rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp | 9 ++------- rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp | 9 ++------- rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp | 9 ++------- 3 files changed, 6 insertions(+), 21 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp index e35da3dd45..b8175f944c 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGifDec.cpp @@ -193,14 +193,9 @@ int cellGifDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC //Decode GIF file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; - unsigned char *gif = new unsigned char [fileSize]; - for(u32 i = 0; i < fileSize; i++){ - gif[i] = Memory.Read8(buffer+i); - } + unsigned char *gif = (unsigned char*)Memory.VirtualToRealAddr(buffer); + unsigned char *image = stbi_load_from_memory(gif, fileSize, &width, &height, &actual_components, 4); Memory.Free(buffer); - - unsigned char *image = stbi_load_from_memory((const unsigned char*)gif, fileSize, &width, &height, &actual_components, 4); - delete[] gif; if (!image) return CELL_GIFDEC_ERROR_STREAM_FORMAT; u32 image_size = width * height * 4; diff --git a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp index c9cbaba239..8f0f82c40e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellJpgDec.cpp @@ -213,14 +213,9 @@ int cellJpgDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC //Decode JPG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; - unsigned char *jpg = new unsigned char [fileSize]; - for(u32 i = 0; i < fileSize; i++){ - jpg[i] = Memory.Read8(buffer+i); - } + unsigned char *jpg = (unsigned char*)Memory.VirtualToRealAddr(buffer); + unsigned char *image = stbi_load_from_memory(jpg, fileSize, &width, &height, &actual_components, 4); Memory.Free(buffer); - - unsigned char *image = stbi_load_from_memory((const unsigned char*)jpg, fileSize, &width, &height, &actual_components, 4); - delete[] jpg; if (!image) return CELL_JPGDEC_ERROR_STREAM_FORMAT; u32 image_size = width * height * 4; diff --git a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp index 1a93351259..783ba3738e 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPngDec.cpp @@ -198,14 +198,9 @@ int cellPngDecDecodeData(u32 mainHandle, u32 subHandle, u32 data_addr, u32 dataC //Decode PNG file. (TODO: Is there any faster alternative? Can we do it without external libraries?) int width, height, actual_components; - unsigned char *png = new unsigned char [fileSize]; - for(u32 i = 0; i < fileSize; i++){ - png[i] = Memory.Read8(buffer+i); - } + unsigned char *png = (unsigned char*)Memory.VirtualToRealAddr(buffer); + unsigned char *image = stbi_load_from_memory(png, fileSize, &width, &height, &actual_components, 4); Memory.Free(buffer); - - unsigned char *image = stbi_load_from_memory((const unsigned char*)png, fileSize, &width, &height, &actual_components, 4); - delete[] png; if (!image) return CELL_PNGDEC_ERROR_STREAM_FORMAT; u32 image_size = width * height * 4; From bf293ebbfc59b2f0a652d4d5e42628b76bbf8e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Sat, 21 Sep 2013 02:40:36 +0200 Subject: [PATCH 3/7] Debugger improved: Instruction editor added How to use the instruction editor: 1. Load an .ELF file 2. Select an instruction from any valid memory address inside any thread. 3. Press 'E' key and have fun. :P Note1: I suggest to remove the function InterpreterDisAsmFrame::DClick and use InterpreterDisAsmFrame::InstrKey to do all debugging-related actions (Add breakpoint, Edit, Step, Run, etc.) using the same keyboard layout as debuggers like OllyDbg. Note2: The final binary is 200 KB larger due to this feature. This issue should be fixed in the future. This has probably something to do with the #include's. --- rpcs3/Gui/InstructionEditor.cpp | 88 +++++++++++++++++++++++++++++++++ rpcs3/Gui/InstructionEditor.h | 24 +++++++++ rpcs3/Gui/InterpreterDisAsm.cpp | 19 +++++++ rpcs3/Gui/InterpreterDisAsm.h | 1 + rpcs3/rpcs3.vcxproj | 1 + rpcs3/rpcs3.vcxproj.filters | 3 ++ 6 files changed, 136 insertions(+) create mode 100644 rpcs3/Gui/InstructionEditor.cpp create mode 100644 rpcs3/Gui/InstructionEditor.h diff --git a/rpcs3/Gui/InstructionEditor.cpp b/rpcs3/Gui/InstructionEditor.cpp new file mode 100644 index 0000000000..83011e37e7 --- /dev/null +++ b/rpcs3/Gui/InstructionEditor.cpp @@ -0,0 +1,88 @@ +#include "stdafx.h" +#include "InstructionEditor.h" + +InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm) + : wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition) + , pc(_pc) + , CPU(_CPU) + , decoder(_decoder) + , disasm(_disasm) +{ + wxBoxSizer* s_panel_margin_x(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_panel_margin_y(new wxBoxSizer(wxVERTICAL)); + + wxBoxSizer* s_panel(new wxBoxSizer(wxVERTICAL)); + wxBoxSizer* s_t1_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t2_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t3_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); + + wxStaticText* t1_text = new wxStaticText(this, wxID_ANY, "Address: "); + wxStaticText* t1_addr = new wxStaticText(this, wxID_ANY, wxString::Format("%08x",pc)); + wxStaticText* t2_text = new wxStaticText(this, wxID_ANY, "Instruction:"); + t2_instr = new wxTextCtrl(this, wxID_ANY); + wxStaticText* t3_text = new wxStaticText(this, wxID_ANY, "Preview: "); + t3_preview = new wxStaticText(this, wxID_ANY, ""); + + s_t1_panel->Add(t1_text); + s_t1_panel->AddSpacer(8); + s_t1_panel->Add(t1_addr); + + s_t2_panel->Add(t2_text); + s_t2_panel->AddSpacer(8); + s_t2_panel->Add(t2_instr); + + s_t3_panel->Add(t3_text); + s_t3_panel->AddSpacer(8); + s_t3_panel->Add(t3_preview); + + s_b_panel->Add(new wxButton(this, wxID_OK), wxLEFT, 0, 5); + s_b_panel->AddSpacer(5); + s_b_panel->Add(new wxButton(this, wxID_CANCEL), wxRIGHT, 0, 5); + + s_panel->Add(s_t1_panel); + s_panel->AddSpacer(8); + s_panel->Add(s_t3_panel); + s_panel->AddSpacer(8); + s_panel->Add(s_t2_panel); + s_panel->AddSpacer(16); + s_panel->Add(s_b_panel); + + s_panel_margin_y->AddSpacer(12); + s_panel_margin_y->Add(s_panel); + s_panel_margin_y->AddSpacer(12); + s_panel_margin_x->AddSpacer(12); + s_panel_margin_x->Add(s_panel_margin_y); + s_panel_margin_x->AddSpacer(12); + + this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview)); + t2_instr->SetValue(wxString::Format("%08x", Memory.Read32(pc))); + + this->SetSizerAndFit(s_panel_margin_x); + + if(this->ShowModal() == wxID_OK) + { + unsigned long opcode; + if (!t2_instr->GetValue().ToULong(&opcode, 16)) + wxMessageBox("This instruction could not be parsed.\nNo changes were made.","Error"); + else + Memory.Write32(CPU->GetOffset() + pc, (u32)opcode); + } +} + +void InstructionEditorDialog::updatePreview(wxCommandEvent& event) +{ + unsigned long opcode; + if (t2_instr->GetValue().ToULong(&opcode, 16)) + { + decoder->Decode((u32)opcode); + wxString preview = disasm->last_opcode; + while (preview[0] != ':') preview.Remove(0,1); + preview.Remove(0,1); + t3_preview->SetLabel(preview); + } + else + { + t3_preview->SetLabel("Could not parse instruction."); + } +} \ No newline at end of file diff --git a/rpcs3/Gui/InstructionEditor.h b/rpcs3/Gui/InstructionEditor.h new file mode 100644 index 0000000000..7edb0ef1a8 --- /dev/null +++ b/rpcs3/Gui/InstructionEditor.h @@ -0,0 +1,24 @@ +#pragma once +#include "Emu/Cell/PPCThread.h" +#include "Emu/Cell/PPUDecoder.h" +#include "Emu/Cell/PPUDisAsm.h" +#include "Emu/Cell/SPUDecoder.h" +#include "Emu/Cell/SPUDisAsm.h" + +class InstructionEditorDialog + : public wxDialog +{ + u64 pc; + PPC_DisAsm* disasm; + PPC_Decoder* decoder; + wxTextCtrl* t2_instr; + wxStaticText* t3_preview; + +public: + PPCThread* CPU; + +public: + InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm); + + void updatePreview(wxCommandEvent& event); +}; \ No newline at end of file diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index 346a03810c..2475a7f24c 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "InterpreterDisAsm.h" +#include "InstructionEditor.h" //static const int show_lines = 30; @@ -67,6 +68,7 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent) Connect(m_btn_step->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoStep)); Connect(m_btn_run->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoRun)); Connect(m_btn_pause->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoPause)); + Connect(m_list->GetId(), wxEVT_COMMAND_LIST_KEY_DOWN, wxListEventHandler(InterpreterDisAsmFrame::InstrKey)); Connect(m_list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(InterpreterDisAsmFrame::DClick)); Connect(m_choice_units->GetId(),wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(InterpreterDisAsmFrame::OnSelectUnit)); Connect(wxEVT_SIZE, wxSizeEventHandler(InterpreterDisAsmFrame::OnResize)); @@ -442,6 +444,23 @@ void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event)) ThreadBase::Start(); } +void InterpreterDisAsmFrame::InstrKey(wxListEvent& event) +{ + long i = m_list->GetFirstSelected(); + if(i < 0) return; + + const u64 start_pc = PC - m_item_count*4; + const u64 pc = start_pc + i*4; + + switch(event.GetKeyCode()) + { + case 'E': + InstructionEditorDialog(this, pc, CPU, decoder, disasm); + DoUpdate(); + return; + } +} + void InterpreterDisAsmFrame::DClick(wxListEvent& event) { long i = m_list->GetFirstSelected(); diff --git a/rpcs3/Gui/InterpreterDisAsm.h b/rpcs3/Gui/InterpreterDisAsm.h index b86db3ab2a..f14068db35 100644 --- a/rpcs3/Gui/InterpreterDisAsm.h +++ b/rpcs3/Gui/InterpreterDisAsm.h @@ -46,6 +46,7 @@ public: void DoRun(wxCommandEvent& event); void DoPause(wxCommandEvent& event); void DoStep(wxCommandEvent& event); + void InstrKey(wxListEvent& event); void DClick(wxListEvent& event); void MouseWheel(wxMouseEvent& event); diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 893c671409..0558b5154b 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -265,6 +265,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 1606f87a8a..fd5bf44ddf 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -307,6 +307,9 @@ Emu\SysCalls\lv2 + + Gui + From 9c6ae554faa76b9e21e75609fc43af9669994e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Sun, 22 Sep 2013 13:34:54 +0200 Subject: [PATCH 4/7] Debugger improved: Register editor added How to use the register editor: 1. Load an .ELF file 2. Select any instruction from a thread. (This is a workaround to activate the appropriate event listener. This will be changed in the future). 3. Press 'R' key and modify any register you want. Note: The register editor only works with PPU and SPU threads. Additional changes: * Fixed the filesize problem caused by the instruction editor dialog. * Instruction Editor: Fixed small issue in SPU threads --- rpcs3/Emu/Cell/PPCThread.h | 2 + rpcs3/Emu/Cell/PPUThread.h | 63 +++++++++++++++++++ rpcs3/Emu/Cell/SPUThread.h | 31 ++++++++++ rpcs3/Gui/InstructionEditor.cpp | 21 ++++++- rpcs3/Gui/InstructionEditor.h | 24 -------- rpcs3/Gui/InterpreterDisAsm.cpp | 8 ++- rpcs3/Gui/RegisterEditor.cpp | 105 ++++++++++++++++++++++++++++++++ rpcs3/rpcs3.vcxproj | 1 - rpcs3/rpcs3.vcxproj.filters | 3 - 9 files changed, 226 insertions(+), 32 deletions(-) delete mode 100644 rpcs3/Gui/InstructionEditor.h create mode 100644 rpcs3/Gui/RegisterEditor.cpp diff --git a/rpcs3/Emu/Cell/PPCThread.h b/rpcs3/Emu/Cell/PPCThread.h index a4f2f5ae33..63ba891b28 100644 --- a/rpcs3/Emu/Cell/PPCThread.h +++ b/rpcs3/Emu/Cell/PPCThread.h @@ -159,6 +159,8 @@ public: void Stop(); virtual wxString RegsToString() { return wxEmptyString; } + virtual wxString ReadRegString(wxString reg) { return wxEmptyString; } + virtual bool WriteRegString(wxString reg, wxString value) { return false; } virtual void Exec(); void ExecOnce(); diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 6954c31412..b6740d663f 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -753,6 +753,69 @@ public: return ret; } + virtual wxString ReadRegString(wxString reg) + { + if (reg.Contains("[")) + { + long reg_index; + reg.AfterFirst('[').RemoveLast().ToLong(®_index); + if (reg.StartsWith("GPR")) return wxString::Format("%016x", GPR[reg_index]); + if (reg.StartsWith("FPR")) return wxString::Format("%016x", FPR[reg_index]); + if (reg.StartsWith("VPR")) return wxString::Format("%032x", VPR[reg_index]); + } + if (reg == "CR") return wxString::Format("%08x", CR); + if (reg == "LR") return wxString::Format("%016x", LR); + if (reg == "CTR") return wxString::Format("%016x", CTR); + if (reg == "XER") return wxString::Format("%016x", XER); + if (reg == "FPSCR") return wxString::Format("%08x", FPSCR); + return wxEmptyString; + } + + bool WriteRegString(wxString reg, wxString value) { + while (value.Len() < 32) value = "0"+value; + if (reg.Contains("[")) + { + long reg_index; + reg.AfterFirst('[').RemoveLast().ToLong(®_index); + if (reg.StartsWith("GPR") || (reg.StartsWith("FPR"))) + { + unsigned long long reg_value; + if (!value.SubString(16,32).ToULongLong(®_value, 16)) return false; + if (reg.StartsWith("GPR")) GPR[reg_index] = (u64)reg_value; + if (reg.StartsWith("FPR")) FPR[reg_index] = (u64)reg_value; + return true; + } + if (reg.StartsWith("VPR")) + { + unsigned long long reg_value0; + unsigned long long reg_value1; + if (!value.SubString(16,32).ToULongLong(®_value0, 16)) return false; + if (!value.SubString(0,16).ToULongLong(®_value1, 16)) return false; + VPR[reg_index]._u64[0] = (u64)reg_value0; + VPR[reg_index]._u64[1] = (u64)reg_value1; + return true; + } + } + if (reg == "LR" || reg == "CTR" || reg == "XER") + { + unsigned long long reg_value; + if (!value.SubString(16,32).ToULongLong(®_value, 16)) return false; + if (reg == "LR") LR = (u64)reg_value; + if (reg == "CTR") CTR = (u64)reg_value; + if (reg == "XER") XER.XER = (u64)reg_value; + return true; + } + if (reg == "CR" || reg == "FPSCR") + { + unsigned long reg_value; + if (!value.SubString(24,32).ToULong(®_value, 16)) return false; + if (reg == "CR") CR.CR = (u32)reg_value; + if (reg == "FPSCR") FPSCR.FPSCR = (u32)reg_value; + return true; + } + return false; + } + virtual void AddArgv(const wxString& arg); public: diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 26775a6ec9..b99ae24cbd 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -249,6 +249,37 @@ public: return ret; } + virtual wxString ReadRegString(wxString reg) + { + if (reg.Contains("[")) + { + long reg_index; + reg.AfterFirst('[').RemoveLast().ToLong(®_index); + if (reg.StartsWith("GPR")) return wxString::Format("%032x", GPR[reg_index]); + } + return wxEmptyString; + } + + bool WriteRegString(wxString reg, wxString value) { + while (value.Len() < 32) value = "0"+value; + if (reg.Contains("[")) + { + long reg_index; + reg.AfterFirst('[').RemoveLast().ToLong(®_index); + if (reg.StartsWith("GPR")) + { + unsigned long long reg_value0; + unsigned long long reg_value1; + if (!value.SubString(16,32).ToULongLong(®_value0, 16)) return false; + if (!value.SubString(0,16).ToULongLong(®_value1, 16)) return false; + GPR[reg_index]._u64[0] = (u64)reg_value0; + GPR[reg_index]._u64[1] = (u64)reg_value1; + return true; + } + } + return false; + } + public: virtual void InitRegs(); virtual u64 GetFreeStackSize() const; diff --git a/rpcs3/Gui/InstructionEditor.cpp b/rpcs3/Gui/InstructionEditor.cpp index 83011e37e7..cb5491e368 100644 --- a/rpcs3/Gui/InstructionEditor.cpp +++ b/rpcs3/Gui/InstructionEditor.cpp @@ -1,5 +1,20 @@ -#include "stdafx.h" -#include "InstructionEditor.h" +class InstructionEditorDialog + : public wxDialog +{ + u64 pc; + PPC_DisAsm* disasm; + PPC_Decoder* decoder; + wxTextCtrl* t2_instr; + wxStaticText* t3_preview; + +public: + PPCThread* CPU; + +public: + InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm); + + void updatePreview(wxCommandEvent& event); +}; InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm) : wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition) @@ -56,7 +71,7 @@ InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCTh s_panel_margin_x->AddSpacer(12); this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview)); - t2_instr->SetValue(wxString::Format("%08x", Memory.Read32(pc))); + t2_instr->SetValue(wxString::Format("%08x", Memory.Read32(CPU->GetOffset() + pc))); this->SetSizerAndFit(s_panel_margin_x); diff --git a/rpcs3/Gui/InstructionEditor.h b/rpcs3/Gui/InstructionEditor.h deleted file mode 100644 index 7edb0ef1a8..0000000000 --- a/rpcs3/Gui/InstructionEditor.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "Emu/Cell/PPCThread.h" -#include "Emu/Cell/PPUDecoder.h" -#include "Emu/Cell/PPUDisAsm.h" -#include "Emu/Cell/SPUDecoder.h" -#include "Emu/Cell/SPUDisAsm.h" - -class InstructionEditorDialog - : public wxDialog -{ - u64 pc; - PPC_DisAsm* disasm; - PPC_Decoder* decoder; - wxTextCtrl* t2_instr; - wxStaticText* t3_preview; - -public: - PPCThread* CPU; - -public: - InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm); - - void updatePreview(wxCommandEvent& event); -}; \ No newline at end of file diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index 2475a7f24c..cc671c6e9d 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -1,6 +1,8 @@ #include "stdafx.h" #include "InterpreterDisAsm.h" -#include "InstructionEditor.h" + +#include "InstructionEditor.cpp" +#include "RegisterEditor.cpp" //static const int show_lines = 30; @@ -458,6 +460,10 @@ void InterpreterDisAsmFrame::InstrKey(wxListEvent& event) InstructionEditorDialog(this, pc, CPU, decoder, disasm); DoUpdate(); return; + case 'R': + RegisterEditorDialog(this, pc, CPU, decoder, disasm); + DoUpdate(); + return; } } diff --git a/rpcs3/Gui/RegisterEditor.cpp b/rpcs3/Gui/RegisterEditor.cpp new file mode 100644 index 0000000000..da190f2e11 --- /dev/null +++ b/rpcs3/Gui/RegisterEditor.cpp @@ -0,0 +1,105 @@ +class RegisterEditorDialog + : public wxDialog +{ + u64 pc; + PPC_DisAsm* disasm; + PPC_Decoder* decoder; + wxComboBox* t1_register; + wxTextCtrl* t2_value; + wxStaticText* t3_preview; + +public: + PPCThread* CPU; + +public: + RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm); + + void updateRegister(wxCommandEvent& event); + void updatePreview(wxCommandEvent& event); +}; + +RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPC_Decoder* _decoder, PPC_DisAsm* _disasm) + : wxDialog(parent, wxID_ANY, "Edit registers", wxDefaultPosition) + , pc(_pc) + , CPU(_CPU) + , decoder(_decoder) + , disasm(_disasm) +{ + wxBoxSizer* s_panel_margin_x(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_panel_margin_y(new wxBoxSizer(wxVERTICAL)); + + wxBoxSizer* s_panel(new wxBoxSizer(wxVERTICAL)); + wxBoxSizer* s_t1_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t2_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_t3_panel(new wxBoxSizer(wxHORIZONTAL)); + wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); + + wxStaticText* t1_text = new wxStaticText(this, wxID_ANY, "Register: "); + t1_register = new wxComboBox(this, wxID_ANY, wxEmptyString); + wxStaticText* t2_text = new wxStaticText(this, wxID_ANY, "Value (Hex):"); + t2_value = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200,-1)); + + s_t1_panel->Add(t1_text); + s_t1_panel->AddSpacer(8); + s_t1_panel->Add(t1_register); + + s_t2_panel->Add(t2_text); + s_t2_panel->AddSpacer(8); + s_t2_panel->Add(t2_value); + + s_b_panel->Add(new wxButton(this, wxID_OK), wxLEFT, 0, 5); + s_b_panel->AddSpacer(5); + s_b_panel->Add(new wxButton(this, wxID_CANCEL), wxLEFT, 0, 5); + + s_panel->Add(s_t1_panel); + s_panel->AddSpacer(8); + s_panel->Add(s_t2_panel); + s_panel->AddSpacer(16); + s_panel->Add(s_b_panel); + + s_panel_margin_y->AddSpacer(12); + s_panel_margin_y->Add(s_panel); + s_panel_margin_y->AddSpacer(12); + s_panel_margin_x->AddSpacer(12); + s_panel_margin_x->Add(s_panel_margin_y); + s_panel_margin_x->AddSpacer(12); + + this->Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(RegisterEditorDialog::updateRegister)); + + if (CPU->GetType() == PPC_THREAD_PPU) + { + for (int i=0; i<32; i++) t1_register->Append(wxString::Format("GPR[%d]",i)); + for (int i=0; i<32; i++) t1_register->Append(wxString::Format("FPR[%d]",i)); + for (int i=0; i<32; i++) t1_register->Append(wxString::Format("VPR[%d]",i)); + t1_register->Append("CR"); + t1_register->Append("LR"); + t1_register->Append("CTR"); + t1_register->Append("XER"); + t1_register->Append("FPSCR"); + } + if (CPU->GetType() == PPC_THREAD_SPU) + { + for (int i=0; i<128; i++) t1_register->Append(wxString::Format("GPR[%d]",i)); + } + if (CPU->GetType() == PPC_THREAD_RAW_SPU) + { + wxMessageBox("RawSPU threads not yet supported.","Error"); + return; + } + + this->SetSizerAndFit(s_panel_margin_x); + + if(this->ShowModal() == wxID_OK) + { + wxString reg = t1_register->GetStringSelection(); + wxString value = t2_value->GetValue(); + if (!CPU->WriteRegString(reg,value)) + wxMessageBox("This value could not be converted.\nNo changes were made.","Error"); + } +} + +void RegisterEditorDialog::updateRegister(wxCommandEvent& event) +{ + wxString reg = t1_register->GetStringSelection(); + t2_value->SetValue(CPU->ReadRegString(reg)); +} \ No newline at end of file diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 0558b5154b..893c671409 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -265,7 +265,6 @@ - diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index fd5bf44ddf..1606f87a8a 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -307,9 +307,6 @@ Emu\SysCalls\lv2 - - Gui - From db7e68d30861824f1062f1e94bf20fe6c166702b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Mon, 23 Sep 2013 01:50:16 +0200 Subject: [PATCH 5/7] More SPU Instructions: Floating point arithmetic Implemented Floating/Double-floating arithmetic operations: Add, Substract and Multiply: FA, FS, FM, DFA, DFS, DFM respectively. * Fixed issue in the register editor: Wrong value displayed when reading 64 bit or 128 bit registers. * Fixed issue in the register editor: Error when writing to 128 bit registers. --- rpcs3/Emu/Cell/PPUThread.h | 22 ++++++++++---------- rpcs3/Emu/Cell/SPUInterpreter.h | 36 +++++++++++++++++++++++++++------ rpcs3/Emu/Cell/SPUThread.h | 6 +++--- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index b6740d663f..49baf84edf 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -759,14 +759,14 @@ public: { long reg_index; reg.AfterFirst('[').RemoveLast().ToLong(®_index); - if (reg.StartsWith("GPR")) return wxString::Format("%016x", GPR[reg_index]); - if (reg.StartsWith("FPR")) return wxString::Format("%016x", FPR[reg_index]); - if (reg.StartsWith("VPR")) return wxString::Format("%032x", VPR[reg_index]); + if (reg.StartsWith("GPR")) return wxString::Format("%016llx", GPR[reg_index]); + if (reg.StartsWith("FPR")) return wxString::Format("%016llx", FPR[reg_index]); + if (reg.StartsWith("VPR")) return wxString::Format("%016llx%016llx", VPR[reg_index]._u64[1], VPR[reg_index]._u64[0]); } if (reg == "CR") return wxString::Format("%08x", CR); - if (reg == "LR") return wxString::Format("%016x", LR); - if (reg == "CTR") return wxString::Format("%016x", CTR); - if (reg == "XER") return wxString::Format("%016x", XER); + if (reg == "LR") return wxString::Format("%016llx", LR); + if (reg == "CTR") return wxString::Format("%016llx", CTR); + if (reg == "XER") return wxString::Format("%016llx", XER); if (reg == "FPSCR") return wxString::Format("%08x", FPSCR); return wxEmptyString; } @@ -780,7 +780,7 @@ public: if (reg.StartsWith("GPR") || (reg.StartsWith("FPR"))) { unsigned long long reg_value; - if (!value.SubString(16,32).ToULongLong(®_value, 16)) return false; + if (!value.SubString(16,31).ToULongLong(®_value, 16)) return false; if (reg.StartsWith("GPR")) GPR[reg_index] = (u64)reg_value; if (reg.StartsWith("FPR")) FPR[reg_index] = (u64)reg_value; return true; @@ -789,8 +789,8 @@ public: { unsigned long long reg_value0; unsigned long long reg_value1; - if (!value.SubString(16,32).ToULongLong(®_value0, 16)) return false; - if (!value.SubString(0,16).ToULongLong(®_value1, 16)) return false; + if (!value.SubString(16,31).ToULongLong(®_value0, 16)) return false; + if (!value.SubString(0,15).ToULongLong(®_value1, 16)) return false; VPR[reg_index]._u64[0] = (u64)reg_value0; VPR[reg_index]._u64[1] = (u64)reg_value1; return true; @@ -799,7 +799,7 @@ public: if (reg == "LR" || reg == "CTR" || reg == "XER") { unsigned long long reg_value; - if (!value.SubString(16,32).ToULongLong(®_value, 16)) return false; + if (!value.SubString(16,31).ToULongLong(®_value, 16)) return false; if (reg == "LR") LR = (u64)reg_value; if (reg == "CTR") CTR = (u64)reg_value; if (reg == "XER") XER.XER = (u64)reg_value; @@ -808,7 +808,7 @@ public: if (reg == "CR" || reg == "FPSCR") { unsigned long reg_value; - if (!value.SubString(24,32).ToULong(®_value, 16)) return false; + if (!value.SubString(24,31).ToULong(®_value, 16)) return false; if (reg == "CR") CR.CR = (u32)reg_value; if (reg == "FPSCR") FPSCR.FPSCR = (u32)reg_value; return true; diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index d34c42512f..6eced695df 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -682,15 +682,27 @@ private: } void FA(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + { + float f = *(float*)&CPU.GPR[ra]._u32[w] + *(float*)&CPU.GPR[rb]._u32[w]; + CPU.GPR[rt]._u32[w] = *(u32*)&f; + } } void FS(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + { + float f = *(float*)&CPU.GPR[ra]._u32[w] - *(float*)&CPU.GPR[rb]._u32[w]; + CPU.GPR[rt]._u32[w] = *(u32*)&f; + } } void FM(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + { + float f = *(float*)&CPU.GPR[ra]._u32[w] * *(float*)&CPU.GPR[rb]._u32[w]; + CPU.GPR[rt]._u32[w] = *(u32*)&f; + } } void CLGTH(u32 rt, u32 ra, u32 rb) { @@ -712,15 +724,27 @@ private: } void DFA(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + { + double d = *(double*)&CPU.GPR[ra]._u64[w] + *(double*)&CPU.GPR[rb]._u64[w]; + CPU.GPR[rt]._u64[w] = *(u64*)&d; + } } void DFS(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + { + double d = *(double*)&CPU.GPR[ra]._u64[w] - *(double*)&CPU.GPR[rb]._u64[w]; + CPU.GPR[rt]._u64[w] = *(u64*)&d; + } } void DFM(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + { + double d = *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w]; + CPU.GPR[rt]._u64[w] = *(u64*)&d; + } } void CLGTB(u32 rt, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index b99ae24cbd..565865e730 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -255,7 +255,7 @@ public: { long reg_index; reg.AfterFirst('[').RemoveLast().ToLong(®_index); - if (reg.StartsWith("GPR")) return wxString::Format("%032x", GPR[reg_index]); + if (reg.StartsWith("GPR")) return wxString::Format("%016llx%016llx", GPR[reg_index]._u64[1], GPR[reg_index]._u64[0]); } return wxEmptyString; } @@ -270,8 +270,8 @@ public: { unsigned long long reg_value0; unsigned long long reg_value1; - if (!value.SubString(16,32).ToULongLong(®_value0, 16)) return false; - if (!value.SubString(0,16).ToULongLong(®_value1, 16)) return false; + if (!value.SubString(16,31).ToULongLong(®_value0, 16)) return false; + if (!value.SubString(0,15).ToULongLong(®_value1, 16)) return false; GPR[reg_index]._u64[0] = (u64)reg_value0; GPR[reg_index]._u64[1] = (u64)reg_value1; return true; From 03dcfeabc3047e6a2cb4af88932828d8d5622282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Mon, 23 Sep 2013 12:48:27 +0200 Subject: [PATCH 6/7] More SPU Instructions: Floating point comparison * Implemented Floating/Double-floating comparison instructions: FCGT, FCMGT, FCEQ, FCMEQ, DFCGT, DFCMGT, DFCEQ, DFCMEQ * Implemented more Floating/Double-floating operations: FMA, FMS, FNMS, DFMA, DFMS, DFNMS, DFNMA * Implemented Double / Single floating-point conversion: FESD, FRSD --- rpcs3/Emu/Cell/SPUInterpreter.h | 79 ++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 6eced695df..917f6c1fcb 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -674,11 +674,13 @@ private: } void FCGT(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = *(float*)&CPU.GPR[ra]._u32[w] > *(float*)&CPU.GPR[rb]._u32[w] ? 0xffffffff : 0; } void DFCGT(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + CPU.GPR[rt]._u64[w] = *(double*)&CPU.GPR[ra]._u64[w] > *(float*)&CPU.GPR[rb]._u64[w] ? 0xffffffffffffffff : 0; } void FA(u32 rt, u32 ra, u32 rb) { @@ -716,11 +718,13 @@ private: } void FCMGT(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = fabs(*(float*)&CPU.GPR[ra]._u32[w]) > fabs(*(float*)&CPU.GPR[rb]._u32[w]) ? 0xffffffff : 0; } void DFCMGT(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + CPU.GPR[rt]._u64[w] = fabs(*(double*)&CPU.GPR[ra]._u64[w]) > fabs(*(float*)&CPU.GPR[rb]._u64[w]) ? 0xffffffffffffffff : 0; } void DFA(u32 rt, u32 ra, u32 rb) { @@ -757,19 +761,35 @@ private: } void DFMA(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + { + double d = *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w] + *(double*)&CPU.GPR[rt]._u64[w]; + CPU.GPR[rt]._u64[w] = *(u64*)&d; + } } void DFMS(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + { + double d = *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w] - *(double*)&CPU.GPR[rt]._u64[w]; + CPU.GPR[rt]._u64[w] = *(u64*)&d; + } } void DFNMS(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + { + double d = *(double*)&CPU.GPR[rt]._u64[w] - *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w]; + CPU.GPR[rt]._u64[w] = *(u64*)&d; + } } void DFNMA(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + { + double d = - *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w] - *(double*)&CPU.GPR[rt]._u64[w]; + CPU.GPR[rt]._u64[w] = *(u64*)&d; + } } void CEQ(u32 rt, u32 ra, u32 rb) { @@ -822,11 +842,20 @@ private: } void FESD(u32 rt, u32 ra) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + { + double d = *(float*)&CPU.GPR[ra]._u32[w*2]; + CPU.GPR[rt]._u64[w] = *(u64*)&d; + } } void FRDS(u32 rt, u32 ra) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + { + float f = *(double*)&CPU.GPR[ra]._u64[w]; + CPU.GPR[rt]._u32[w*2] = *(u32*)&f; + CPU.GPR[rt]._u32[w*2+1] = 0x00000000; + } } void FSCRWR(u32 rt, u32 ra) { @@ -838,11 +867,13 @@ private: } void FCEQ(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = *(float*)&CPU.GPR[ra]._u32[w] == *(float*)&CPU.GPR[rb]._u32[w] ? 0xffffffff : 0; } void DFCEQ(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + CPU.GPR[rt]._u64[w] = *(double*)&CPU.GPR[ra]._u64[w] == *(float*)&CPU.GPR[rb]._u64[w] ? 0xffffffffffffffff : 0; } void MPY(u32 rt, u32 ra, u32 rb) { @@ -871,11 +902,13 @@ private: } void FCMEQ(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = fabs(*(float*)&CPU.GPR[ra]._u32[w]) == fabs(*(float*)&CPU.GPR[rb]._u32[w]) ? 0xffffffff : 0; } void DFCMEQ(u32 rt, u32 ra, u32 rb) { - UNIMPLEMENTED(); + for (int w = 0; w < 2; w++) + CPU.GPR[rt]._u64[w] = fabs(*(double*)&CPU.GPR[ra]._u64[w]) > fabs(*(float*)&CPU.GPR[rb]._u64[w]) ? 0xffffffffffffffff : 0; } void MPYU(u32 rt, u32 ra, u32 rb) { @@ -1201,15 +1234,27 @@ private: } void FNMS(u32 rt, u32 ra, u32 rb, u32 rc) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + { + float f = *(float*)&CPU.GPR[rc]._u32[w] - *(float*)&CPU.GPR[ra]._u32[w] * *(float*)&CPU.GPR[rb]._u32[w]; + CPU.GPR[rt]._u32[w] = *(u32*)&f; + } } void FMA(u32 rc, u32 ra, u32 rb, u32 rt) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + { + float f = *(float*)&CPU.GPR[ra]._u32[w] * *(float*)&CPU.GPR[rb]._u32[w] + *(float*)&CPU.GPR[rc]._u32[w]; + CPU.GPR[rt]._u32[w] = *(u32*)&f; + } } void FMS(u32 rc, u32 ra, u32 rb, u32 rt) { - UNIMPLEMENTED(); + for (int w = 0; w < 4; w++) + { + float f = *(float*)&CPU.GPR[ra]._u32[w] * *(float*)&CPU.GPR[rb]._u32[w] - *(float*)&CPU.GPR[rc]._u32[w]; + CPU.GPR[rt]._u32[w] = *(u32*)&f; + } } void UNK(u32 code, u32 opcode, u32 gcode) From 7d97bbfbbf073927744f9999533b211297ab13c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandro=20S=C3=A1nchez=20Bach?= Date: Mon, 23 Sep 2013 14:20:47 +0200 Subject: [PATCH 7/7] Changed syntax of last SPU instructions --- rpcs3/Emu/Cell/SPUInterpreter.h | 160 ++++++++++++++------------------ rpcs3/Emu/Cell/SPUThread.h | 2 + 2 files changed, 70 insertions(+), 92 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 917f6c1fcb..2097e6fe9b 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -674,37 +674,36 @@ private: } void FCGT(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = *(float*)&CPU.GPR[ra]._u32[w] > *(float*)&CPU.GPR[rb]._u32[w] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._f[0] > CPU.GPR[rb]._f[0] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[1] = CPU.GPR[ra]._f[1] > CPU.GPR[rb]._f[1] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[2] = CPU.GPR[ra]._f[2] > CPU.GPR[rb]._f[2] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._f[3] > CPU.GPR[rb]._f[3] ? 0xffffffff : 0; } void DFCGT(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - CPU.GPR[rt]._u64[w] = *(double*)&CPU.GPR[ra]._u64[w] > *(float*)&CPU.GPR[rb]._u64[w] ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[0] = CPU.GPR[ra]._d[0] > CPU.GPR[rb]._d[0] ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[1] = CPU.GPR[ra]._d[1] > CPU.GPR[rb]._d[1] ? 0xffffffffffffffff : 0; } void FA(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 4; w++) - { - float f = *(float*)&CPU.GPR[ra]._u32[w] + *(float*)&CPU.GPR[rb]._u32[w]; - CPU.GPR[rt]._u32[w] = *(u32*)&f; - } + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] + CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] + CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] + CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] + CPU.GPR[rb]._f[3]; } void FS(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 4; w++) - { - float f = *(float*)&CPU.GPR[ra]._u32[w] - *(float*)&CPU.GPR[rb]._u32[w]; - CPU.GPR[rt]._u32[w] = *(u32*)&f; - } + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] - CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] - CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] - CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] - CPU.GPR[rb]._f[3]; } void FM(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 4; w++) - { - float f = *(float*)&CPU.GPR[ra]._u32[w] * *(float*)&CPU.GPR[rb]._u32[w]; - CPU.GPR[rt]._u32[w] = *(u32*)&f; - } + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; } void CLGTH(u32 rt, u32 ra, u32 rb) { @@ -718,37 +717,30 @@ private: } void FCMGT(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = fabs(*(float*)&CPU.GPR[ra]._u32[w]) > fabs(*(float*)&CPU.GPR[rb]._u32[w]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[0] = fabs(CPU.GPR[ra]._f[0]) > fabs(CPU.GPR[rb]._f[0]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[1] = fabs(CPU.GPR[ra]._f[1]) > fabs(CPU.GPR[rb]._f[1]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[2] = fabs(CPU.GPR[ra]._f[2]) > fabs(CPU.GPR[rb]._f[2]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[3] = fabs(CPU.GPR[ra]._f[3]) > fabs(CPU.GPR[rb]._f[3]) ? 0xffffffff : 0; } void DFCMGT(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - CPU.GPR[rt]._u64[w] = fabs(*(double*)&CPU.GPR[ra]._u64[w]) > fabs(*(float*)&CPU.GPR[rb]._u64[w]) ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[0] = fabs(CPU.GPR[ra]._d[0]) > fabs(CPU.GPR[rb]._d[0]) ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[1] = fabs(CPU.GPR[ra]._d[1]) > fabs(CPU.GPR[rb]._d[1]) ? 0xffffffffffffffff : 0; } void DFA(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - { - double d = *(double*)&CPU.GPR[ra]._u64[w] + *(double*)&CPU.GPR[rb]._u64[w]; - CPU.GPR[rt]._u64[w] = *(u64*)&d; - } + CPU.GPR[rt]._d[0] = CPU.GPR[ra]._d[0] + CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] = CPU.GPR[ra]._d[1] + CPU.GPR[rb]._d[1]; } void DFS(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - { - double d = *(double*)&CPU.GPR[ra]._u64[w] - *(double*)&CPU.GPR[rb]._u64[w]; - CPU.GPR[rt]._u64[w] = *(u64*)&d; - } + CPU.GPR[rt]._d[0] = CPU.GPR[ra]._d[0] - CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] = CPU.GPR[ra]._d[1] - CPU.GPR[rb]._d[1]; } void DFM(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - { - double d = *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w]; - CPU.GPR[rt]._u64[w] = *(u64*)&d; - } + CPU.GPR[rt]._d[0] = CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] = CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1]; } void CLGTB(u32 rt, u32 ra, u32 rb) { @@ -761,35 +753,23 @@ private: } void DFMA(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - { - double d = *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w] + *(double*)&CPU.GPR[rt]._u64[w]; - CPU.GPR[rt]._u64[w] = *(u64*)&d; - } + CPU.GPR[rt]._d[0] += CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] += CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1]; } void DFMS(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - { - double d = *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w] - *(double*)&CPU.GPR[rt]._u64[w]; - CPU.GPR[rt]._u64[w] = *(u64*)&d; - } + CPU.GPR[rt]._d[0] = CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0] - CPU.GPR[rt]._d[0]; + CPU.GPR[rt]._d[1] = CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1] - CPU.GPR[rt]._d[1]; } void DFNMS(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - { - double d = *(double*)&CPU.GPR[rt]._u64[w] - *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w]; - CPU.GPR[rt]._u64[w] = *(u64*)&d; - } + CPU.GPR[rt]._d[0] -= CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0]; + CPU.GPR[rt]._d[1] -= CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1]; } void DFNMA(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - { - double d = - *(double*)&CPU.GPR[ra]._u64[w] * *(double*)&CPU.GPR[rb]._u64[w] - *(double*)&CPU.GPR[rt]._u64[w]; - CPU.GPR[rt]._u64[w] = *(u64*)&d; - } + CPU.GPR[rt]._d[0] = - CPU.GPR[ra]._d[0] * CPU.GPR[rb]._d[0] - CPU.GPR[rt]._d[0] ; + CPU.GPR[rt]._d[1] = - CPU.GPR[ra]._d[1] * CPU.GPR[rb]._d[1] - CPU.GPR[rt]._d[1] ; } void CEQ(u32 rt, u32 ra, u32 rb) { @@ -842,20 +822,15 @@ private: } void FESD(u32 rt, u32 ra) { - for (int w = 0; w < 2; w++) - { - double d = *(float*)&CPU.GPR[ra]._u32[w*2]; - CPU.GPR[rt]._u64[w] = *(u64*)&d; - } + CPU.GPR[rt]._d[0] = (double)CPU.GPR[ra]._f[0]; + CPU.GPR[rt]._d[1] = (double)CPU.GPR[ra]._f[2]; } void FRDS(u32 rt, u32 ra) { - for (int w = 0; w < 2; w++) - { - float f = *(double*)&CPU.GPR[ra]._u64[w]; - CPU.GPR[rt]._u32[w*2] = *(u32*)&f; - CPU.GPR[rt]._u32[w*2+1] = 0x00000000; - } + CPU.GPR[rt]._f[0] = (float)CPU.GPR[ra]._d[0]; + CPU.GPR[rt]._f[1] = 0x00000000; + CPU.GPR[rt]._f[2] = (float)CPU.GPR[ra]._d[1]; + CPU.GPR[rt]._f[3] = 0x00000000; } void FSCRWR(u32 rt, u32 ra) { @@ -867,13 +842,15 @@ private: } void FCEQ(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = *(float*)&CPU.GPR[ra]._u32[w] == *(float*)&CPU.GPR[rb]._u32[w] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._f[0] == CPU.GPR[rb]._f[0] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[1] = CPU.GPR[ra]._f[1] == CPU.GPR[rb]._f[1] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[2] = CPU.GPR[ra]._f[2] == CPU.GPR[rb]._f[2] ? 0xffffffff : 0; + CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._f[3] == CPU.GPR[rb]._f[3] ? 0xffffffff : 0; } void DFCEQ(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - CPU.GPR[rt]._u64[w] = *(double*)&CPU.GPR[ra]._u64[w] == *(float*)&CPU.GPR[rb]._u64[w] ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[0] = CPU.GPR[ra]._d[0] == CPU.GPR[rb]._d[0] ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[1] = CPU.GPR[ra]._d[1] == CPU.GPR[rb]._d[1] ? 0xffffffffffffffff : 0; } void MPY(u32 rt, u32 ra, u32 rb) { @@ -902,13 +879,15 @@ private: } void FCMEQ(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 4; w++) - CPU.GPR[rt]._u32[w] = fabs(*(float*)&CPU.GPR[ra]._u32[w]) == fabs(*(float*)&CPU.GPR[rb]._u32[w]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[0] = fabs(CPU.GPR[ra]._f[0]) == fabs(CPU.GPR[rb]._f[0]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[1] = fabs(CPU.GPR[ra]._f[1]) == fabs(CPU.GPR[rb]._f[1]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[2] = fabs(CPU.GPR[ra]._f[2]) == fabs(CPU.GPR[rb]._f[2]) ? 0xffffffff : 0; + CPU.GPR[rt]._u32[3] = fabs(CPU.GPR[ra]._f[3]) == fabs(CPU.GPR[rb]._f[3]) ? 0xffffffff : 0; } void DFCMEQ(u32 rt, u32 ra, u32 rb) { - for (int w = 0; w < 2; w++) - CPU.GPR[rt]._u64[w] = fabs(*(double*)&CPU.GPR[ra]._u64[w]) > fabs(*(float*)&CPU.GPR[rb]._u64[w]) ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[0] = fabs(CPU.GPR[ra]._d[0]) == fabs(CPU.GPR[rb]._d[0]) ? 0xffffffffffffffff : 0; + CPU.GPR[rt]._u64[1] = fabs(CPU.GPR[ra]._d[1]) == fabs(CPU.GPR[rb]._d[1]) ? 0xffffffffffffffff : 0; } void MPYU(u32 rt, u32 ra, u32 rb) { @@ -1234,27 +1213,24 @@ private: } void FNMS(u32 rt, u32 ra, u32 rb, u32 rc) { - for (int w = 0; w < 4; w++) - { - float f = *(float*)&CPU.GPR[rc]._u32[w] - *(float*)&CPU.GPR[ra]._u32[w] * *(float*)&CPU.GPR[rb]._u32[w]; - CPU.GPR[rt]._u32[w] = *(u32*)&f; - } + CPU.GPR[rt]._f[0] -= CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] -= CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] -= CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] -= CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; } void FMA(u32 rc, u32 ra, u32 rb, u32 rt) { - for (int w = 0; w < 4; w++) - { - float f = *(float*)&CPU.GPR[ra]._u32[w] * *(float*)&CPU.GPR[rb]._u32[w] + *(float*)&CPU.GPR[rc]._u32[w]; - CPU.GPR[rt]._u32[w] = *(u32*)&f; - } + CPU.GPR[rt]._f[0] += CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0]; + CPU.GPR[rt]._f[1] += CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1]; + CPU.GPR[rt]._f[2] += CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2]; + CPU.GPR[rt]._f[3] += CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3]; } void FMS(u32 rc, u32 ra, u32 rb, u32 rt) { - for (int w = 0; w < 4; w++) - { - float f = *(float*)&CPU.GPR[ra]._u32[w] * *(float*)&CPU.GPR[rb]._u32[w] - *(float*)&CPU.GPR[rc]._u32[w]; - CPU.GPR[rt]._u32[w] = *(u32*)&f; - } + CPU.GPR[rt]._f[0] = CPU.GPR[ra]._f[0] * CPU.GPR[rb]._f[0] - CPU.GPR[rt]._f[0]; + CPU.GPR[rt]._f[1] = CPU.GPR[ra]._f[1] * CPU.GPR[rb]._f[1] - CPU.GPR[rt]._f[1]; + CPU.GPR[rt]._f[2] = CPU.GPR[ra]._f[2] * CPU.GPR[rb]._f[2] - CPU.GPR[rt]._f[2]; + CPU.GPR[rt]._f[3] = CPU.GPR[ra]._f[3] * CPU.GPR[rb]._f[3] - CPU.GPR[rt]._f[3]; } void UNK(u32 code, u32 opcode, u32 gcode) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 565865e730..77a260989b 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -110,6 +110,8 @@ union SPU_GPR_hdr s16 _i16[8]; u8 _u8[16]; s8 _i8[16]; + double _d[2]; + float _f[4]; SPU_GPR_hdr() {}