#include "stdafx.h" #include "CompilerELF.h" void Write8(wxFile& f, const u8 data) { f.Write(&data, 1); } void Write16(wxFile& f, const u16 data) { Write8(f, data >> 8); Write8(f, data); } void Write32(wxFile& f, const u32 data) { Write16(f, data >> 16); Write16(f, data); } void Write64(wxFile& f, const u64 data) { Write32(f, data >> 32); Write32(f, data); } enum CompilerIDs { id_analyze_code = 0x555, id_compile_code, id_load_elf, }; wxFont GetFont(int size) { return wxFont(size, wxMODERN, wxNORMAL, wxNORMAL); } u32 SetField(u32 src, u32 from, u32 to) { return (src & ((1 << ((to - from) + 1)) - 1)) << (31 - to); } u32 SetField(s32 src, u32 p) { return (src & 0x1) << (31 - p); } u32 ToOpcode(u32 i) { return SetField(i, 0, 5); } u32 ToRS(u32 i) { return SetField(i, 6, 10); } u32 ToRD(u32 i) { return SetField(i, 6, 10); } u32 ToRA(u32 i) { return SetField(i, 11, 15); } u32 ToRB(u32 i) { return SetField(i, 16, 20); } u32 ToLL(u32 i) { return i & 0x03fffffc; } u32 ToAA(u32 i) { return SetField(i, 30); } u32 ToLK(u32 i) { return SetField(i, 31); } u32 ToIMM16(s32 i) { return SetField(i, 16, 31); } u32 ToD(s32 i) { return SetField(i, 16, 31); } u32 ToDS(s32 i) { if(i < 0) return ToD(i + 1); return ToD(i); } u32 ToSYS(u32 i) { return SetField(i, 6, 31); } u32 ToBF(u32 i) { return SetField(i, 6, 10); } u32 ToBO(u32 i) { return SetField(i, 6, 10); } u32 ToBI(u32 i) { return SetField(i, 11, 15); } u32 ToBD(u32 i) { return i & 0xfffc; } u32 ToMB(u32 i) { return SetField(i, 21, 25); } u32 ToME(u32 i) { return SetField(i, 26, 30); } u32 ToSH(u32 i) { return SetField(i, 16, 20); } u32 ToRC(u32 i) { return SetField(i, 31); } u32 ToOE(u32 i) { return SetField(i, 21); } u32 ToL(u32 i) { return SetField(i, 10); } u32 ToCRFD(u32 i) { return SetField(i, 6, 8); } struct InstrField { u32 (*To)(u32 i); } RA = {ToRA}, RS = {ToRS}, RD = {ToRD}; enum MASKS { MASK_ERROR = -1, MASK_UNK, MASK_NO_ARG, MASK_RSD_RA_IMM16, MASK_RA_RST_IMM16, MASK_CRFD_RA_IMM16, MASK_BI_BD, MASK_BO_BI_BD, MASK_SYS, MASK_LL, MASK_RA_RS_SH_MB_ME, MASK_RA_RS_RB_MB_ME, MASK_RST_RA_D, MASK_RST_RA_DS, MASK_TO_RA_IMM16, MASK_RSD_IMM16, }; enum SMASKS { SMASK_ERROR = -1, SMASK_NULL, SMASK_AA = (1 << 0), SMASK_LK = (1 << 1), SMASK_OE = (1 << 2), SMASK_RC = (1 << 3), SMASK_L = (1 << 4), SMASK_BO = (1 << 5), SMASK_BI = (1 << 6), BO_MASK_BO4 = (1 << 0), BO_MASK_BO3 = (1 << 1), BO_MASK_BO2 = (1 << 2), BO_MASK_BO1 = (1 << 3), BO_MASK_BO0 = (1 << 4), BI_LT = 0, BI_GT = 1, BI_EQ = 2, BI_GE = 0, BI_LE = 1, BI_NE = 2, }; static const struct Instruction { MASKS mask; wxString name; u32 op_num; u32 op_g; u32 smask; u32 bo; u32 bi; } m_instructions[] = { {MASK_NO_ARG, "nop", ORI, 0, SMASK_NULL}, {MASK_TO_RA_IMM16, "tdi", TDI, 0, SMASK_NULL}, {MASK_TO_RA_IMM16, "twi", TWI, 0, SMASK_NULL}, //G_04 = 0x04, {MASK_RSD_RA_IMM16, "mulli", MULLI, 0, SMASK_NULL}, {MASK_RSD_RA_IMM16, "subfic", SUBFIC, 0, SMASK_NULL}, {MASK_CRFD_RA_IMM16, "cmplwi", CMPLI, 0, SMASK_NULL}, {MASK_CRFD_RA_IMM16, "cmpldi", CMPLI, 0, SMASK_L}, {MASK_CRFD_RA_IMM16, "cmpwi", CMPI, 0, SMASK_NULL}, {MASK_CRFD_RA_IMM16, "cmpdi", CMPI, 0, SMASK_L}, {MASK_RSD_RA_IMM16, "addic", ADDIC, 0, SMASK_NULL}, {MASK_RSD_RA_IMM16, "addic.", ADDIC_, 0, SMASK_RC}, {MASK_RSD_RA_IMM16, "addi", ADDI, 0, SMASK_NULL}, {MASK_RSD_IMM16, "li", ADDI, 0, SMASK_NULL}, {MASK_RSD_RA_IMM16, "addis", ADDIS, 0, SMASK_NULL}, {MASK_BO_BI_BD, "bc", BC, 0, SMASK_NULL}, {MASK_BO_BI_BD, "bca", BC, 0, SMASK_AA}, {MASK_BO_BI_BD, "bcl", BC, 0, SMASK_LK}, {MASK_BO_BI_BD, "bcla", BC, 0, SMASK_AA | SMASK_LK}, {MASK_BI_BD, "bdz", BC, 0, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO3}, {MASK_BI_BD, "bdz-", BC, 0, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO1 | BO_MASK_BO3}, {MASK_BI_BD, "bdz+", BC, 0, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO1 | BO_MASK_BO3 | BO_MASK_BO4}, {MASK_BI_BD, "bdnz", BC, 0, SMASK_BO, BO_MASK_BO0}, {MASK_BI_BD, "bdnz-", BC, 0, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO1}, {MASK_BI_BD, "bdnz+", BC, 0, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO1 | BO_MASK_BO4}, {MASK_BI_BD, "bge", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO2, BI_GE}, {MASK_BI_BD, "ble", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO2, BI_LE}, {MASK_BI_BD, "bne", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO2, BI_NE}, {MASK_BI_BD, "bge-", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3, BI_GE}, {MASK_BI_BD, "ble-", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3, BI_LE}, {MASK_BI_BD, "bne-", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3, BI_NE}, {MASK_BI_BD, "bge+", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_GE}, {MASK_BI_BD, "ble+", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_LE}, {MASK_BI_BD, "bne+", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_NE}, {MASK_BI_BD, "bgt", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2, BI_GT}, {MASK_BI_BD, "blt", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2, BI_LT}, {MASK_BI_BD, "beq", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2, BI_EQ}, {MASK_BI_BD, "bgt-", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3, BI_GT}, {MASK_BI_BD, "blt-", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3, BI_LT}, {MASK_BI_BD, "beq-", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3, BI_EQ}, {MASK_BI_BD, "bgt+", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_GT}, {MASK_BI_BD, "blt+", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_LT}, {MASK_BI_BD, "beq+", BC, 0, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_EQ}, {MASK_SYS, "sc", SC, 0, SMASK_NULL}, {MASK_LL, "b", B, 0, SMASK_NULL}, {MASK_LL, "ba", B, 0, SMASK_AA}, {MASK_LL, "bl", B, 0, SMASK_LK}, {MASK_LL, "bla", B, 0, SMASK_AA | SMASK_LK}, //G_13 = 0x13, {MASK_RA_RS_SH_MB_ME, "rlwimi", RLWIMI, 0, SMASK_NULL}, {MASK_RA_RS_SH_MB_ME, "rlwimi.", RLWIMI, 0, SMASK_RC}, {MASK_RA_RS_SH_MB_ME, "rlwinm", RLWINM, 0, SMASK_NULL}, {MASK_RA_RS_SH_MB_ME, "rlwinm.", RLWINM, 0, SMASK_RC}, {MASK_RA_RS_RB_MB_ME, "rlwnm", RLWNM, 0, SMASK_NULL}, {MASK_RA_RS_RB_MB_ME, "rlwnm.", RLWNM, 0, SMASK_RC}, {MASK_RSD_RA_IMM16, "ori", ORI, 0, SMASK_NULL}, {MASK_RSD_RA_IMM16, "oris", ORIS, 0, SMASK_NULL}, {MASK_RSD_RA_IMM16, "xori", XORI, 0, SMASK_NULL}, {MASK_RSD_RA_IMM16, "xoris", XORIS, 0, SMASK_NULL}, {MASK_RA_RST_IMM16, "andi.", ANDI_, 0, SMASK_RC}, {MASK_RA_RST_IMM16, "andis.", ANDIS_, 0, SMASK_RC}, //G_1e = 0x1e, //G_1f = 0x1f, {MASK_RST_RA_D, "lwz", LWZ, 0, SMASK_NULL}, {MASK_RST_RA_D, "lwzu", LWZU, 0, SMASK_NULL}, {MASK_RST_RA_D, "lbz", LBZ, 0, SMASK_NULL}, {MASK_RST_RA_D, "lbzu", LBZU, 0, SMASK_NULL}, {MASK_RST_RA_D, "stw", STW, 0, SMASK_NULL}, {MASK_RST_RA_D, "stwu", STWU, 0, SMASK_NULL}, {MASK_RST_RA_D, "stb", STB, 0, SMASK_NULL}, {MASK_RST_RA_D, "stbu", STBU, 0, SMASK_NULL}, {MASK_RST_RA_D, "lhz", LHZ, 0, SMASK_NULL}, {MASK_RST_RA_D, "lhzu", LHZU, 0, SMASK_NULL}, {MASK_RST_RA_D, "lha", LHA, 0, SMASK_NULL}, {MASK_RST_RA_D, "lhau", LHAU, 0, SMASK_NULL}, {MASK_RST_RA_D, "sth", STH, 0, SMASK_NULL}, //{0, "lmw", LMW, 0, false, false}, //LFS = 0x30, //LFSU = 0x31, //LFD = 0x32, //LFDU = 0x33, //STFS = 0x34, //STFD = 0x36, //LFQ = 0x38, //LFQU = 0x39, //G_3a = 0x3a, //G_3b = 0x3b, //G_3e = 0x3e, //G_3f = 0x3f, {MASK_UNK, "unk", 0, 0, SMASK_NULL}, }, m_error_instr = {MASK_ERROR, "err", 0, 0, SMASK_ERROR}; static const u32 instr_count = WXSIZEOF(m_instructions); enum ArgType { ARG_ERR = 0, ARG_NUM = 1 << 0, ARG_NUM16 = 1 << 1, ARG_TXT = 1 << 2, ARG_REG_R = 1 << 3, ARG_REG_F = 1 << 4, ARG_REG_V = 1 << 5, ARG_REG_CR = 1 << 6, ARG_BRANCH = 1 << 7, ARG_INSTR = 1 << 8, ARG_IMM = ARG_NUM | ARG_NUM16 | ARG_BRANCH, }; struct Arg { wxString string; u32 value; ArgType type; Arg(const wxString& _string, const u32 _value = 0, const ArgType _type = ARG_ERR) : string(_string) , value(_value) , type(_type) { } }; Instruction GetInstruction(const wxString& str) { for(u32 i=0; i& arr) { u32 code = ToOE(instr.smask & SMASK_OE) | ToRC(instr.smask & SMASK_RC) | ToAA(instr.smask & SMASK_AA) | ToLK(instr.smask & SMASK_LK) | ToL (instr.smask & SMASK_L ); if(instr.smask & SMASK_BO) code |= ToBO(instr.bo); if(instr.smask & SMASK_BI) code |= ToBI(instr.bi); code |= ToOpcode(instr.op_num); switch(instr.mask) { case MASK_RSD_RA_IMM16: return code | ToRS(arr[0].value) | ToRA(arr[1].value) | ToIMM16(arr[2].value); case MASK_RA_RST_IMM16: return code | ToRA(arr[0].value) | ToRS(arr[1].value) | ToIMM16(arr[2].value); case MASK_CRFD_RA_IMM16: return code | ToCRFD(arr[0].value) | ToRA(arr[1].value) | ToIMM16(arr[2].value); case MASK_BO_BI_BD: return code | ToBO(arr[0].value) | ToBI(arr[1].value) | ToBD(arr[2].value); case MASK_BI_BD: return code | ToBI(arr[0].value * 4) | ToBD(arr[1].value); case MASK_SYS: return code | ToSYS(arr[0].value); case MASK_LL: return code | ToLL(arr[0].value); case MASK_RA_RS_SH_MB_ME: return code | ToRA(arr[0].value) | ToRS(arr[1].value) | ToSH(arr[2].value) | ToMB(arr[3].value) | ToME(arr[4].value); case MASK_RST_RA_D: return code | ToRS(arr[0].value) | ToRA(arr[1].value) | ToD(arr[2].value); case MASK_RST_RA_DS: return code | ToRS(arr[0].value) | ToRA(arr[1].value) | ToDS(arr[2].value); case MASK_RSD_IMM16: return code | ToRS(arr[0].value) | ToIMM16(arr[1].value); case MASK_UNK: return arr[0].value; case MASK_NO_ARG: return code; } return 0; } ArrayF sections_list; u32 section_name_offs = 0; u32 section_offs = 0; SectionInfo::SectionInfo(const wxString& _name) : name(_name) { memset(&shdr, 0, sizeof(Elf64_Shdr)); section_num = sections_list.Add(this); shdr.sh_offset = section_offs; shdr.sh_name = section_name_offs; section_name_offs += name.Len() + 1; } void SectionInfo::SetDataSize(u32 size, u32 align) { if(align) shdr.sh_addralign = align; if(shdr.sh_addralign) size = Memory.AlignAddr(size, shdr.sh_addralign); if(code.GetCount()) { for(u32 i=section_num + 1; iGetId(), wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(CompilerELF::OnUpdate)); Connect(id_analyze_code, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CompilerELF::AnalyzeCode)); Connect(id_compile_code, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CompilerELF::CompileCode)); Connect(id_load_elf, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CompilerELF::LoadElf)); asm_list->SetFont(wxFont(-1, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); hex_list->SetFont(wxFont(-1, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); wxGetApp().Connect(wxEVT_SCROLLWIN_TOP, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); wxGetApp().Connect(wxEVT_SCROLLWIN_BOTTOM, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); wxGetApp().Connect(wxEVT_SCROLLWIN_LINEUP, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); wxGetApp().Connect(wxEVT_SCROLLWIN_LINEDOWN, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); wxGetApp().Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); wxGetApp().Connect(wxEVT_SCROLLWIN_THUMBRELEASE,wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); wxGetApp().Connect(asm_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(CompilerELF::MouseWheel), (wxObject*)0, this); wxGetApp().Connect(hex_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(CompilerELF::MouseWheel), (wxObject*)0, this); wxGetApp().Connect(asm_list->GetId(), wxEVT_KEY_DOWN, wxKeyEventHandler(CompilerELF::OnKeyDown), (wxObject*)0, this); wxGetApp().Connect(hex_list->GetId(), wxEVT_KEY_DOWN, wxKeyEventHandler(CompilerELF::OnKeyDown), (wxObject*)0, this); asm_list->WriteText( "[sysPrxForUser, sys_initialize_tls, 0x744680a2]\n" "[sysPrxForUser, sys_process_exit, 0xe6f2c1e7]\n" "[sys_fs, cellFsOpen, 0x718bf5f8]\n" "[sys_fs, cellFsClose, 0x2cb51f0d]\n" "[sys_fs, cellFsRead, 0x4d5ff8e2]\n" "[sys_fs, cellFsWrite, 0xecdcf2ab]\n" "[sys_fs, cellFsLseek, 0xa397d042]\n" "[sys_fs, cellFsMkdir, 0xba901fe6]\n" "\n" ".int [flags, 577] #LV2_O_WRONLY | LV2_O_CREAT | LV2_O_TRUNC\n" ".string [path, \"dev_hdd0/game/TEST12345/USRDIR/test.txt\"]\n" ".string [str, \"Hello World!\"]\n" ".strlen [str_len, str]\n" ".buf [fd, 8]\n" "\n" ".srr [fd_hi, fd, 16]\n" ".and [fd_lo, fd, 0xffff]\n" "\n" ".srr [path_hi, path, 16]\n" ".and [path_lo, path, 0xffff]\n" "\n" ".srr [str_hi, str, 16]\n" ".and [str_lo, str, 0xffff]\n" "\n" "\tbl \tsys_initialize_tls\n" "\n" "\tli \tr3, path_lo\n" "\toris \tr3, r3, path_hi\n" "\tli \tr4, flags\n" "\tli \tr5, fd_lo\n" "\toris \tr5, r5, fd_hi\n" "\tli \tr6, 0\n" "\tli \tr7, 0\n" "\tbl \tcellFsOpen\n" "\tcmpwi \tcr7, r3, 0\n" "\tblt- \tcr7, exit_err\n" "\n" "\tli \tr3, fd_lo\n" "\toris \tr3, r3, fd_hi\n" "\tlwz \tr3, r3, 0\n" "\tli \tr4, str_lo\n" "\toris \tr4, r4, str_hi\n" "\tli \tr5, str_len\n" "\tli \tr6, 0\n" "\tbl \tcellFsWrite\n" "\tcmpwi \tcr7, r3, 0\n" "\tblt- \tcr7, exit_err\n" "\n" "\tli \tr3, fd_lo\n" "\toris \tr3, r3, fd_hi\n" "\tlwz \tr3, r3, 0\n" "\tbl \tcellFsClose\n" "\tcmpwi \tcr7, r3, 0\n" "\tblt- \tcr7, exit_err\n" "\n" "exit_ok:\n" "\tli \tr3, 0\n" "\tb \texit\n" "\n" "exit_err:\n" ".string [str, \"error.\\n\"]\n" ".srr [str_hi, str, 16]\n" ".and [str_lo, str, 0xffff]\n" ".strlen [str_len, str]\n" ".int [written_len_lo, fd_lo]\n" ".int [written_len_hi, fd_hi]\n" "\tli \tr3, 1\n" "\tli \tr4, str_lo\n" "\toris \tr4, r4, str_hi\n" "\tli \tr5, str_len\n" "\tli \tr6, written_len_lo\n" "\toris \tr6, r6, written_len_hi\n" "\tli \tr11, 403\n" "\tsc\n" "\tli \tr3, 1\n" "\tb \texit\n" "\n" "exit:\n" "\tbl \tsys_process_exit\n" "\tli \tr3, 1\n" "\tb \texit\n" ); ::SendMessage((HWND)hex_list->GetHWND(), WM_VSCROLL, SB_BOTTOM, 0); ::SendMessage((HWND)asm_list->GetHWND(), WM_VSCROLL, SB_BOTTOM, 0); } CompilerELF::~CompilerELF() { m_aui_mgr.UnInit(); } void CompilerELF::MouseWheel(wxMouseEvent& event) { int value = (event.m_wheelRotation / event.m_wheelDelta); wxScrollWinEvent scrool_event; scrool_event.SetEventType(value > 0 ? wxEVT_SCROLLWIN_LINEUP : wxEVT_SCROLLWIN_LINEDOWN); scrool_event.SetOrientation(wxVERTICAL); if(value < 0) value = -value; value *= event.m_linesPerAction; while(value--) { scrool_event.SetEventObject(asm_list); OnScroll(scrool_event); scrool_event.SetEventObject(hex_list); OnScroll(scrool_event); } } void CompilerELF::UpdateStatus(int offset) { long line; if(asm_list->PositionToXY(asm_list->GetInsertionPoint() - 2, nullptr, &line)) { m_status_bar.SetStatusText(wxString::Format("line %d", line), 0); return; } m_status_bar.SetStatusText(wxEmptyString, 0); } void CompilerELF::OnKeyDown(wxKeyEvent& event) { wxScrollWinEvent scrool_event; scrool_event.SetOrientation(wxVERTICAL); switch(event.GetKeyCode()) { case WXK_RETURN: UpdateStatus( 1); break; case WXK_UP: UpdateStatus(-1); break; case WXK_DOWN: UpdateStatus( 1); break; case WXK_LEFT: case WXK_RIGHT: UpdateStatus(); break; case WXK_PAGEUP: scrool_event.SetEventType(wxEVT_SCROLLWIN_PAGEUP); scrool_event.SetEventObject(asm_list); OnScroll(scrool_event); scrool_event.SetEventObject(hex_list); OnScroll(scrool_event); return; case WXK_PAGEDOWN: scrool_event.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN); scrool_event.SetEventObject(asm_list); OnScroll(scrool_event); scrool_event.SetEventObject(hex_list); OnScroll(scrool_event); return; } event.Skip(); } void CompilerELF::OnUpdate(wxCommandEvent& event) { UpdateStatus(); DoAnalyzeCode(false); return; asm_list->Freeze(); asm_list->SetStyle(0, asm_list->GetValue().Len(), wxTextAttr("Black")); for(u32 i=0; iGetValue().find('#', p)) >= 0;) { const int from = p++; p = asm_list->GetValue().find('\n', p); if(p < 0) p = asm_list->GetValue().Len(); asm_list->SetStyle(from, p, wxTextAttr(0x009900)); } for(int p=0; (p = asm_list->GetValue().find('"', p)) >= 0;) { const int from = p++; const int p1 = asm_list->GetValue().find('\n', p); int p2 = p; for(;;) { p2 = asm_list->GetValue().find('"', p2); if(p2 == -1) break; if(asm_list->GetValue()[p2 - 1] == '\\') { if(p2 > 2 && asm_list->GetValue()[p2 - 2] == '\\') break; p2++; continue; } break; } if(p1 < 0 && p2 < 0) { p = asm_list->GetValue().Len(); } else if(p1 >= 0 && p2 < 0) { p = p1; } else if(p2 >= 0 && p1 < 0) { p = p2 + 1; } else { p = p1 > p2 ? p2 + 1 : p1; } asm_list->SetStyle(from, p, wxTextAttr(0x000099)); } asm_list->Thaw(); UpdateScroll(true, wxVERTICAL); } void CompilerELF::OnScroll(wxScrollWinEvent& event) { const int id = event.GetEventObject() ? ((wxScrollBar*)event.GetEventObject())->GetId() : -1; wxTextCtrl* src = NULL; wxTextCtrl* dst = NULL; if(id == hex_list->GetId()) { src = hex_list; dst = asm_list; } else if(id == asm_list->GetId()) { src = asm_list; dst = hex_list; } if(!m_disable_scroll && src && dst && event.GetOrientation() == wxVERTICAL) { s64 kind = -1; if(event.GetEventType() == wxEVT_SCROLLWIN_TOP) { kind = SB_TOP; } else if(event.GetEventType() == wxEVT_SCROLLWIN_BOTTOM) { kind = SB_BOTTOM; } else if(event.GetEventType() == wxEVT_SCROLLWIN_LINEUP) { kind = SB_LINEUP; } else if(event.GetEventType() == wxEVT_SCROLLWIN_LINEDOWN) { kind = SB_LINEDOWN; } else if(event.GetEventType() == wxEVT_SCROLLWIN_PAGEUP) { kind = SB_PAGEUP; } else if(event.GetEventType() == wxEVT_SCROLLWIN_PAGEDOWN) { kind = SB_PAGEDOWN; } else if(event.GetEventType() == wxEVT_SCROLLWIN_THUMBTRACK) { kind = MAKEWPARAM(SB_THUMBTRACK, event.GetPosition()); //dst->SetScrollPos(event.GetOrientation(), event.GetPosition()); } else if(event.GetEventType() == wxEVT_SCROLLWIN_THUMBRELEASE) { kind = MAKEWPARAM(SB_THUMBPOSITION, event.GetPosition()); //dst->SetScrollPos(event.GetOrientation(), event.GetPosition()); } if(kind >= 0) { m_disable_scroll = true; ::SendMessage((HWND)dst->GetHWND(), (event.GetOrientation() == wxVERTICAL ? WM_VSCROLL : WM_HSCROLL), kind, 0); m_disable_scroll = false; } } event.Skip(); } void CompilerELF::UpdateScroll(bool is_hex, int orient) { wxScrollWinEvent event; event.SetEventType(wxEVT_SCROLLWIN_THUMBRELEASE); event.SetEventObject(is_hex ? asm_list : hex_list); event.SetPosition(is_hex ? asm_list->GetScrollPos(orient) : hex_list->GetScrollPos(orient)); event.SetOrientation(orient); OnScroll(event); } void WriteEhdr(wxFile& f, Elf64_Ehdr& ehdr) { Write32(f, ehdr.e_magic); Write8(f, ehdr.e_class); Write8(f, ehdr.e_data); Write8(f, ehdr.e_curver); Write8(f, ehdr.e_os_abi); Write64(f, ehdr.e_abi_ver); Write16(f, ehdr.e_type); Write16(f, ehdr.e_machine); Write32(f, ehdr.e_version); Write64(f, ehdr.e_entry); Write64(f, ehdr.e_phoff); Write64(f, ehdr.e_shoff); Write32(f, ehdr.e_flags); Write16(f, ehdr.e_ehsize); Write16(f, ehdr.e_phentsize); Write16(f, ehdr.e_phnum); Write16(f, ehdr.e_shentsize); Write16(f, ehdr.e_shnum); Write16(f, ehdr.e_shstrndx); } void WritePhdr(wxFile& f, Elf64_Phdr& phdr) { Write32(f, phdr.p_type); Write32(f, phdr.p_flags); Write64(f, phdr.p_offset); Write64(f, phdr.p_vaddr); Write64(f, phdr.p_paddr); Write64(f, phdr.p_filesz); Write64(f, phdr.p_memsz); Write64(f, phdr.p_align); } void WriteShdr(wxFile& f, Elf64_Shdr& shdr) { Write32(f, shdr.sh_name); Write32(f, shdr.sh_type); Write64(f, shdr.sh_flags); Write64(f, shdr.sh_addr); Write64(f, shdr.sh_offset); Write64(f, shdr.sh_size); Write32(f, shdr.sh_link); Write32(f, shdr.sh_info); Write64(f, shdr.sh_addralign); Write64(f, shdr.sh_entsize); } void CompilerELF::LoadElf(wxCommandEvent& event) { wxFileDialog ctrl(this, L"Select ELF", wxEmptyString, wxEmptyString, "Elf Files (*.elf, *.bin)|*.elf;*.bin|" "All Files (*.*)|*.*", wxFD_OPEN | wxFD_FILE_MUST_EXIST); if(ctrl.ShowModal() == wxID_CANCEL) return; LoadElf(ctrl.GetPath()); } #include "Emu/Cell/PPUDisAsm.h" #include "Emu/Cell/PPUDecoder.h" void CompilerELF::LoadElf(const wxString& path) { } struct CompileProgram { struct Branch { wxString m_name; s32 m_pos; s32 m_id; s32 m_addr; Branch(const wxString& name, s32 pos) : m_name(name) , m_pos(pos) , m_id(-1) , m_addr(-1) { } Branch(const wxString& name, u32 id, u32 addr) : m_name(name) , m_pos(-1) , m_id(id) , m_addr(addr) { } }; bool m_analyze; s64 p; u64 m_line; const wxString& m_asm; wxTextCtrl& m_asm_list; wxTextCtrl& m_hex_list; wxTextCtrl& m_err_list; bool m_error; Array m_code; bool m_end_args; Array m_branches; s32 m_branch_pos; u32 m_text_addr; struct SpData { wxString m_data; u32 m_addr; SpData(const wxString& data, u32 addr) : m_data(data) , m_addr(addr) { } }; Array m_sp_string; CompileProgram(const wxString& asm_, wxTextCtrl* asm_list, wxTextCtrl* hex_list, wxTextCtrl* err_list, bool analyze) : m_asm(asm_) , m_asm_list(*asm_list) , m_hex_list(*hex_list) , m_err_list(*err_list) , m_analyze(analyze) , p(0) , m_error(false) , m_line(1) , m_end_args(false) , m_branch_pos(0) , m_text_addr(0) { } static bool IsSkip(const char c) { return c == ' ' || c == '\t'; } static bool IsCommit(const char c) { return c == '#'; } bool IsEnd() const { return p >= m_asm.Len(); } bool IsEndLn(const char c) const { return c == '\n' || p - 1 >= m_asm.Len(); } char NextChar() { return *m_asm(p++, 1); } void NextLn() { while( !IsEndLn(NextChar()) ); if(!IsEnd()) m_line++; } void EndLn() { NextLn(); p--; m_line--; } void FirstChar() { p = 0; m_line = 1; m_branch_pos = 0; } void PrevArg() { while( --p >= 0 && (IsSkip(m_asm[p]) || m_asm[p] == ',')); while( --p >= 0 && !IsSkip(m_asm[p]) && !IsEndLn(m_asm[p]) ); if(IsEndLn(m_asm[p])) p++; } bool GetOp(wxString& result) { s64 from = -1; for(;;) { const char cur_char = NextChar(); const bool skip = IsSkip(cur_char); const bool commit = IsCommit(cur_char); const bool endln = IsEndLn(cur_char); if(endln) p--; if(from == -1) { if(endln || commit) return false; if(!skip) from = p - 1; continue; } if(skip || endln || commit) { const s64 to = (endln ? p : p - 1) - from; result = m_asm(from, to); return true; } } return false; } bool GetArg(wxString& result, bool func = false) { s64 from = -1; for(;;) { const char cur_char = NextChar(); const bool skip = IsSkip(cur_char); const bool commit = IsCommit(cur_char); const bool endln = IsEndLn(cur_char); const bool end = cur_char == ',' || (func && cur_char == ']'); if(endln) p--; if(from == -1) { if(endln || commit || end) return false; if(!skip) from = p - 1; continue; } const bool text = m_asm[from] == '"'; const bool end_text = cur_char == '"'; if((text ? end_text : skip || commit || end) || endln) { if(text && p > 2 && m_asm[p - 2] == '\\' && (p <= 3 || m_asm[p - 3] != '\\')) { continue; } if(text && !end_text) { WriteError(wxString::Format("'\"' not found.")); m_error = true; } const s64 to = (endln || text ? p : p - 1) - from; bool ret = true; if(skip || text) { for(;;) { const char cur_char = NextChar(); const bool skip = IsSkip(cur_char); const bool commit = IsCommit(cur_char); const bool endln = IsEndLn(cur_char); const bool end = cur_char == ',' || (func && cur_char == ']'); if(skip) continue; if(end) break; if(commit) { ret = false; EndLn(); break; } if(endln) { ret = false; p--; break; } WriteError(wxString::Format("Bad symbol '%c'", cur_char)); m_error = true; } } result = m_asm(from, to); if(text) { for(u32 pos = 0; (s32)(pos = result.find('\\', pos)) >= 0;) { if(pos + 1 < result.Len() && result[pos + 1] == '\\') { pos += 2; continue; } const char v = result[pos + 1]; switch(v) { case 'n': result = result(0, pos) + '\n' + result(pos+2, result.Len()-(pos+2)); break; case 'r': result = result(0, pos) + '\r' + result(pos+2, result.Len()-(pos+2)); break; case 't': result = result(0, pos) + '\t' + result(pos+2, result.Len()-(pos+2)); break; } pos++; } } return ret; } } } bool CheckEnd(bool show_err = true) { for(;;) { const char cur_char = NextChar(); const bool skip = IsSkip(cur_char); const bool commit = IsCommit(cur_char); const bool endln = IsEndLn(cur_char); if(skip) continue; if(commit) { NextLn(); return true; } if(endln) { p--; NextLn(); return true; } WriteError(wxString::Format("Bad symbol '%c'", cur_char)); NextLn(); return false; } return false; } void WriteError(const wxString& error) { m_err_list.WriteText(wxString::Format("line %lld: %s\n", m_line, error)); } Array m_args; u32 m_cur_arg; void DetectArgInfo(Arg& arg) { const wxString str = arg.string; if(str.Len() <= 0) { arg.type = ARG_ERR; return; } if(GetInstruction(str).mask != MASK_ERROR) { arg.type = ARG_INSTR; return; } if(str.Len() > 1) { for(u32 i=0; i '9') { arg.type = ARG_ERR; return; } } u32 reg; sscanf(str(1, str.Len() - 1), "%d", ®); if(reg >= 32) { arg.type = ARG_ERR; return; } switch(str[0]) { case 'r': arg.type = ARG_REG_R; break; case 'f': arg.type = ARG_REG_F; break; case 'v': arg.type = ARG_REG_V; break; default: arg.type = ARG_ERR; break; } arg.value = reg; return; case 'c': if(str.Len() > 2 && str[1] == 'r') { for(u32 i=2; i '9') { arg.type = ARG_ERR; return; } } u32 reg; sscanf(str, "cr%d", ®); if(reg < 8) { arg.type = ARG_REG_CR; arg.value = reg; } else { arg.type = ARG_ERR; } return; } break; case '"': if(str.Len() < 2) { arg.type = ARG_ERR; return; } if(str[str.Len() - 1] != '"') { arg.type = ARG_ERR; return; } arg.string = str(1, str.Len() - 2); arg.type = ARG_TXT; return; } if(str.Len() > 2 && str(0, 2).Cmp("0x") == 0) { for(u32 i=2; i= '0' && str[i] <= '9') || (str[i] >= 'a' && str[i] <= 'f') || (str[i] >= 'A' && str[i] <= 'F') ) continue; arg.type = ARG_ERR; return; } u32 val; sscanf(str, "0x%x", &val); arg.type = ARG_NUM16; arg.value = val; return; } for(u32 i= str[0] == '-' ? 1 : 0; i '9') { arg.type = ARG_ERR; return; } } u32 val; sscanf(str, "%d", &val); arg.type = ARG_NUM; arg.value = val; } void LoadArgs() { m_args.Clear(); m_cur_arg = 0; wxString str; while(GetArg(str)) { Arg arg(str); DetectArgInfo(arg); m_args.AddCpy(arg); } m_end_args = true; } u32 GetBranchValue(const wxString& branch) { for(u32 i=0; i= 0) return m_text_addr + m_branches[i].m_pos * 4; return m_branches[i].m_addr; } return 0; } bool SetNextArgType(u32 types, bool show_err = true) { if(m_error) return false; if(m_cur_arg >= m_args.GetCount()) { if(show_err) { WriteError(wxString::Format("%d arg not found", m_cur_arg + 1)); m_error = true; } return false; } const Arg& arg = m_args[m_cur_arg]; if(arg.type & types) { m_cur_arg++; return true; } if(show_err) { WriteError(wxString::Format("Bad arg '%s'", arg.string)); m_error = true; } return false; } bool SetNextArgBranch(u8 aa, bool show_err = true) { const u32 pos = m_cur_arg; const bool ret = SetNextArgType(ARG_BRANCH | ARG_IMM, show_err); if(!aa && pos < m_args.GetCount()) { switch(m_args[pos].type) { case ARG_NUM: m_args[pos].value += m_text_addr + m_branch_pos * 4; break; case ARG_BRANCH: m_args[pos].value -= m_text_addr + m_branch_pos * 4; break; } } return ret; } bool IsBranchOp(const wxString& op) const { return op.Len() > 1 && op[op.Len() - 1] == ':'; } bool IsFuncOp(const wxString& op) const { return op.Len() >= 1 && op[0] == '['; } enum SP_TYPE { SP_ERR, SP_INT, SP_STRING, SP_STRLEN, SP_BUF, SP_SRL, SP_SRR, SP_MUL, SP_DIV, SP_ADD, SP_SUB, SP_AND, SP_OR, SP_XOR, SP_NOT, SP_NOR, }; SP_TYPE GetSpType(const wxString& op) const { if(op.Cmp(".int") == 0) return SP_INT; if(op.Cmp(".string") == 0) return SP_STRING; if(op.Cmp(".strlen") == 0) return SP_STRLEN; if(op.Cmp(".buf") == 0) return SP_BUF; if(op.Cmp(".srl") == 0) return SP_SRL; if(op.Cmp(".srr") == 0) return SP_SRR; if(op.Cmp(".mul") == 0) return SP_MUL; if(op.Cmp(".div") == 0) return SP_DIV; if(op.Cmp(".add") == 0) return SP_ADD; if(op.Cmp(".sub") == 0) return SP_SUB; if(op.Cmp(".and") == 0) return SP_AND; if(op.Cmp(".or") == 0) return SP_OR; if(op.Cmp(".xor") == 0) return SP_XOR; if(op.Cmp(".not") == 0) return SP_NOT; if(op.Cmp(".nor") == 0) return SP_NOR; return SP_ERR; } wxString GetSpStyle(const SP_TYPE sp) const { switch(sp) { case SP_INT: case SP_STRING: case SP_STRLEN: case SP_NOT: return "[dst, src]"; case SP_BUF: return "[dst, size]"; case SP_SRL: case SP_SRR: case SP_MUL: case SP_DIV: case SP_ADD: case SP_SUB: case SP_AND: case SP_OR: case SP_XOR: case SP_NOR: return "[dst, src1, src2]"; } return "error"; } bool IsSpOp(const wxString& op) const { return GetSpType(op) != SP_ERR; } Branch& GetBranch(const wxString& name) { for(u32 i=0; i 0 && m_asm[p] != '[') p--; p++; wxString dst; if(!GetArg(dst)) { if(m_analyze) m_hex_list.WriteText("error\n"); WriteError(wxString::Format("dst not found. style: %s", GetSpStyle(sp))); m_error = true; NextLn(); return; } Arg a_dst(dst); DetectArgInfo(a_dst); Branch* dst_branch = NULL; switch(a_dst.type) { case ARG_BRANCH: { Branch& b = GetBranch(dst); if(b.m_addr >= 0 && b.m_id < 0 && b.m_pos < 0) dst_branch = &b; } break; case ARG_ERR: { m_branches.Add(new Branch(wxEmptyString, -1, 0)); dst_branch = &m_branches[m_branches.GetCount() - 1]; } break; } if(!dst_branch) { if(m_analyze) m_hex_list.WriteText("error\n"); WriteError(wxString::Format("bad dst type. style: %s", GetSpStyle(sp))); m_error = true; NextLn(); return; } switch(sp) { case SP_INT: case SP_STRING: case SP_STRLEN: case SP_BUF: case SP_NOT: { wxString src1; if(!GetArg(src1, true)) { if(m_analyze) m_hex_list.WriteText("error\n"); WriteError(wxString::Format("src not found. style: %s", GetSpStyle(sp))); m_error = true; NextLn(); return; } Arg a_src1(src1); DetectArgInfo(a_src1); if(sp == SP_STRLEN ? ~(ARG_TXT | ARG_BRANCH) & a_src1.type : sp == SP_STRING ? ~ARG_TXT & a_src1.type : ~(ARG_IMM | ARG_BRANCH) & a_src1.type) { if(m_analyze) m_hex_list.WriteText("error\n"); WriteError(wxString::Format("bad src type. style: %s", GetSpStyle(sp))); m_error = true; NextLn(); return; } if(m_asm[p - 1] != ']') { if(m_analyze) m_hex_list.WriteText("error\n"); WriteError(wxString::Format("']' not found. style: %s", GetSpStyle(sp))); m_error = true; NextLn(); return; } if(!CheckEnd()) { if(m_analyze) m_hex_list.WriteText("error\n"); return; } if(sp == SP_STRING) { src1 = src1(1, src1.Len()-2); bool founded = false; for(u32 i=0; i> a_src2.value); break; case SP_MUL: *dst_branch = Branch(dst, -1, a_src1.value * a_src2.value); break; case SP_DIV: *dst_branch = Branch(dst, -1, a_src1.value / a_src2.value); break; case SP_ADD: *dst_branch = Branch(dst, -1, a_src1.value + a_src2.value); break; case SP_SUB: *dst_branch = Branch(dst, -1, a_src1.value - a_src2.value); break; case SP_AND: *dst_branch = Branch(dst, -1, a_src1.value & a_src2.value); break; case SP_OR: *dst_branch = Branch(dst, -1, a_src1.value | a_src2.value); break; case SP_XOR: *dst_branch = Branch(dst, -1, a_src1.value ^ a_src2.value); break; case SP_NOR: *dst_branch = Branch(dst, -1, ~(a_src1.value | a_src2.value)); break; } } break; } if(m_analyze) m_hex_list.WriteText("\n"); } void Compile() { m_err_list.Freeze(); m_err_list.Clear(); if(m_analyze) { m_hex_list.Freeze(); m_hex_list.Clear(); } m_code.Clear(); for(u32 i=0; i m_imports; Module(const wxString& name, u32 import) : m_name(name) { Add(import); } void Add(u32 import) { m_imports.AddCpy(import); } void Clear() { m_name.Clear(); m_imports.Clear(); } }; Array modules; FirstChar(); while(!IsEnd()) { wxString op; if(!GetOp(op) || !IsFuncOp(op)) { NextLn(); continue; } while(p > 0 && m_asm[p] != '[') p--; p++; wxString module, name, id; if(!GetArg(module)) { WriteError("module not found. style: [module, name, id]"); m_error = true; NextLn(); continue; } Arg a_module(module); DetectArgInfo(a_module); if(~ARG_ERR & a_module.type) { WriteError("bad module type. style: [module, name, id]"); m_error = true; NextLn(); continue; } if(!GetArg(name)) { WriteError("name not found. style: [module, name, id]"); m_error = true; NextLn(); continue; } Arg a_name(name); DetectArgInfo(a_name); if(~ARG_ERR & a_name.type) { WriteError("bad name type. style: [module, name, id]"); m_error = true; NextLn(); continue; } if(!GetArg(id, true)) { WriteError("id not found. style: [module, name, id]"); m_error = true; NextLn(); continue; } Arg a_id(id); DetectArgInfo(a_id); if(~ARG_IMM & a_id.type) { WriteError("bad id type. style: [module, name, id]"); m_error = true; NextLn(); continue; } if(m_asm[p - 1] != ']') { WriteError("']' not found. style: [module, name, id]"); m_error = true; NextLn(); continue; } if(!CheckEnd()) continue; m_branches.Add(new Branch(name, a_id.value, 0)); const u32 import = m_branches.GetCount() - 1; bool founded = false; for(u32 i=0; i 0) { switch(m_args[0].type) { case ARG_REG_CR: SetNextArgType(ARG_REG_R); break; case ARG_REG_R: m_args.InsertCpy(0, Arg("cr0", 0, ARG_REG_CR)); break; } } SetNextArgType(ARG_IMM); break; case MASK_BO_BI_BD: SetNextArgType(ARG_IMM); SetNextArgType(ARG_REG_CR); SetNextArgBranch(instr.smask & SMASK_AA); break; case MASK_BI_BD: if(!SetNextArgType(ARG_REG_CR, false)) { m_args.InsertCpy(0, Arg("cr0", 0, ARG_REG_CR)); } SetNextArgBranch(instr.smask & SMASK_AA); break; case MASK_SYS: if(!SetNextArgType(ARG_IMM, false)) m_args.AddCpy(Arg("2", 2, ARG_IMM)); break; case MASK_LL: SetNextArgBranch(instr.smask & SMASK_AA); break; case MASK_RA_RS_SH_MB_ME: SetNextArgType(ARG_REG_R); SetNextArgType(ARG_REG_R); SetNextArgType(ARG_IMM); SetNextArgType(ARG_IMM); SetNextArgType(ARG_IMM); break; case MASK_RA_RS_RB_MB_ME: SetNextArgType(ARG_REG_R); SetNextArgType(ARG_REG_R); SetNextArgType(ARG_REG_R); SetNextArgType(ARG_IMM); SetNextArgType(ARG_IMM); break; case MASK_RST_RA_D: SetNextArgType(ARG_REG_R); SetNextArgType(ARG_REG_R); SetNextArgType(ARG_IMM); break; case MASK_RST_RA_DS: SetNextArgType(ARG_REG_R); SetNextArgType(ARG_REG_R); SetNextArgType(ARG_IMM); break; case MASK_TO_RA_IMM16: SetNextArgType(ARG_IMM); SetNextArgType(ARG_REG_R); SetNextArgType(ARG_IMM); break; case MASK_RSD_IMM16: SetNextArgType(ARG_REG_R); SetNextArgType(ARG_IMM); break; } CheckEnd(); if(m_error) { if(m_analyze) { m_hex_list.WriteText("error\n"); m_error = false; continue; } break; } const u32 code = CompileInstruction(instr, m_args); if(m_analyze) m_hex_list.WriteText(wxString::Format("0x%08x\n", code)); if(!m_analyze) m_code.AddCpy(code); m_branch_pos++; } if(!m_analyze && !m_error) { s_opd.sh_size = Memory.AlignAddr(s_opd.sh_size, s_opd.sh_addralign); section_offset += s_opd.sh_size; const u32 prog_load_1_end = section_offset; Elf64_Shdr s_shstrtab; memset(&s_shstrtab, 0, sizeof(Elf64_Shdr)); s_shstrtab.sh_addralign = 1; section_offset = Memory.AlignAddr(section_offset, s_shstrtab.sh_addralign); s_shstrtab.sh_name = section_name_offset; s_shstrtab.sh_type = 3; s_shstrtab.sh_offset = section_offset; s_shstrtab.sh_addr = 0; sections_names.Add(".shstrtab"); section_name_offset += wxString(".shstrtab").Len() + 1; s_shstrtab.sh_size = section_name_offset; section_offset += s_shstrtab.sh_size; wxFile f("compiled.elf", wxFile::write); elf_info.e_magic = 0x7F454C46; elf_info.e_class = 2; //ELF64 elf_info.e_data = 2; elf_info.e_curver = 1; //ver 1 elf_info.e_os_abi = 0x66; //Cell OS LV-2 elf_info.e_abi_ver = 0; elf_info.e_type = 2; //EXEC (Executable file) elf_info.e_machine = MACHINE_PPC64; //PowerPC64 elf_info.e_version = 1; //ver 1 elf_info.e_flags = 0x0; elf_info.e_shoff = Memory.AlignAddr(section_offset, 4); u8* opd_data = new u8[s_opd.sh_size]; u32 entry_point = s_text.sh_addr; for(u32 i=0; i> 16)); //oris r12,r12,addr>>16 Write32(f, ToOpcode(LWZ) | ToRD(12) | ToRA(12) | ToIMM16(addr)); //lwz r12,addr&0xffff(r12) Write32(f, 0xf8410028); //std r2,40(r1) Write32(f, ToOpcode(LWZ) | ToRD(0) | ToRA(12) | ToIMM16(0)); //lwz r0,0(r12) Write32(f, ToOpcode(LWZ) | ToRD(2) | ToRA(12) | ToIMM16(4)); //lwz r2,4(r12) Write32(f, 0x7c0903a6); //mtctr r0 Write32(f, 0x4e800420); //bctr } f.Seek(s_lib_stub_top.sh_offset); f.Seek(s_lib_stub_top.sh_size, wxFromCurrent); f.Seek(s_lib_stub.sh_offset); for(u32 i=0, nameoffs=4, dataoffs=0; i= text.Len() || text[i + op.Len()] == '\n' || CompileProgram::IsSkip(text[i + op.Len()])) return i; } } return -1; } void CompilerELF::SetTextStyle(const wxString& text, const wxColour& color, bool bold) { for(int p=0; (p = asm_list->GetValue().find(text, p)) >= 0; p += text.Len()) { asm_list->SetStyle(p, p + text.Len(), wxTextAttr(color, wxNullColour, wxFont(-1, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL))); } } void CompilerELF::SetOpStyle(const wxString& text, const wxColour& color, bool bold) { for(int p=0; (p = FindOp(asm_list->GetValue(), text, p)) >= 0; p += text.Len()) { asm_list->SetStyle(p, p + text.Len(), wxTextAttr(color, wxNullColour, wxFont(-1, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL))); } } void CompilerELF::DoAnalyzeCode(bool compile) { CompileProgram(asm_list->GetValue(), asm_list, hex_list, err_list, !compile).Compile(); /* return; MTProgressDialog* progress_dial = new MTProgressDialog(this, wxDefaultSize, "Analyze code...", "Loading...", wxArrayLong(), 1); (new AnalyzeThread())->DoAnalyze(compile, progress_dial, this); */ }