void PPUThread::AddArgv(const std::string& arg) { m_stack_point -= arg.length() + 1; m_stack_point = AlignAddr(m_stack_point, 0x10) - 0x10; m_argv_addr.push_back(m_stack_point); memcpy(vm::get_ptr<char>(m_stack_point), arg.c_str(), arg.size() + 1); }
void PPUThread::InitRegs() { const u32 pc = entry ? vm::read32(entry) : 0; const u32 rtoc = entry ? vm::read32(entry + 4) : 0; //ConLog.Write("entry = 0x%x", entry); //ConLog.Write("rtoc = 0x%x", rtoc); SetPc(pc); /* const s32 thread_num = Emu.GetCPU().GetThreadNumById(GetType(), GetId()); if(thread_num < 0) { LOG_ERROR(PPU, "GetThreadNumById failed."); Emu.Pause(); return; } */ /* const s32 tls_size = Emu.GetTLSFilesz() * thread_num; if(tls_size >= Emu.GetTLSMemsz()) { LOG_ERROR(PPU, "Out of TLS memory."); Emu.Pause(); return; } */ GPR[1] = AlignAddr(m_stack_addr + m_stack_size, 0x200) - 0x200; GPR[2] = rtoc; GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060; LR = Emu.GetPPUThreadExit(); CTR = PC; CR.CR = 0x22000082; VSCR.NJ = 1; TB = 0; }
static void BinWriteMem (BinDesc* D, MemoryArea* M) /* Write the segments of one memory area to a file */ { unsigned I; /* Get the start address of this memory area */ unsigned long Addr = M->Start; /* Debugging: Check that the file offset is correct */ if (ftell (D->F) != (long)M->FileOffs) { Internal ("Invalid file offset for memory area %s: %ld/%lu", GetString (M->Name), ftell (D->F), M->FileOffs); } /* Walk over all segments in this memory area */ for (I = 0; I < CollCount (&M->SegList); ++I) { int DoWrite; /* Get the segment */ SegDesc* S = CollAtUnchecked (&M->SegList, I); /* Keep the user happy */ Print (stdout, 1, " Writing `%s'\n", GetString (S->Name)); /* Writes do only occur in the load area and not for BSS segments */ DoWrite = (S->Flags & SF_BSS) == 0 && /* No BSS segment */ S->Load == M && /* LOAD segment */ S->Seg->Dumped == 0; /* Not already written */ /* Output debugging stuff */ PrintBoolVal ("bss", S->Flags & SF_BSS); PrintBoolVal ("LoadArea", S->Load == M); PrintBoolVal ("Dumped", S->Seg->Dumped); PrintBoolVal ("DoWrite", DoWrite); PrintNumVal ("Address", Addr); PrintNumVal ("FileOffs", (unsigned long) ftell (D->F)); /* Check if the alignment for the segment from the linker config is * a multiple for that of the segment. */ if ((S->RunAlignment % S->Seg->Alignment) != 0) { /* Segment requires another alignment than configured * in the linker. */ Warning ("Segment `%s' is not aligned properly. Resulting " "executable may not be functional.", GetString (S->Name)); } /* If this is the run memory area, we must apply run alignment. If * this is not the run memory area but the load memory area (which * means that both are different), we must apply load alignment. * Beware: DoWrite may be true even if this is the run memory area, * because it may be also the load memory area. */ if (S->Run == M) { /* Handle ALIGN and OFFSET/START */ if (S->Flags & SF_ALIGN) { /* Align the address */ unsigned long NewAddr = AlignAddr (Addr, S->RunAlignment); if (DoWrite || (M->Flags & MF_FILL) != 0) { WriteMult (D->F, M->FillVal, NewAddr - Addr); PrintNumVal ("SF_ALIGN", NewAddr - Addr); } Addr = NewAddr; } else if (S->Flags & (SF_OFFSET | SF_START)) { unsigned long NewAddr = S->Addr; if (S->Flags & SF_OFFSET) { /* It's an offset, not a fixed address, make an address */ NewAddr += M->Start; } if (DoWrite || (M->Flags & MF_FILL) != 0) { WriteMult (D->F, M->FillVal, NewAddr-Addr); PrintNumVal ("SF_OFFSET", NewAddr - Addr); } Addr = NewAddr; } } else if (S->Load == M) { /* Handle ALIGN_LOAD */ if (S->Flags & SF_ALIGN_LOAD) { /* Align the address */ unsigned long NewAddr = AlignAddr (Addr, S->LoadAlignment); if (DoWrite || (M->Flags & MF_FILL) != 0) { WriteMult (D->F, M->FillVal, NewAddr - Addr); PrintNumVal ("SF_ALIGN_LOAD", NewAddr - Addr); } Addr = NewAddr; } } /* Now write the segment to disk if it is not a BSS type segment and * if the memory area is the load area. */ if (DoWrite) { unsigned long P = ftell (D->F); SegWrite (D->Filename, D->F, S->Seg, BinWriteExpr, D); PrintNumVal ("Wrote", (unsigned long) (ftell (D->F) - P)); } else if (M->Flags & MF_FILL) { WriteMult (D->F, S->Seg->FillVal, S->Seg->Size); PrintNumVal ("Filled", (unsigned long) S->Seg->Size); } /* If this was the load memory area, mark the segment as dumped */ if (S->Load == M) { S->Seg->Dumped = 1; } /* Calculate the new address */ Addr += S->Seg->Size; } /* If a fill was requested, fill the remaining space */ if ((M->Flags & MF_FILL) != 0 && M->FillLevel < M->Size) { unsigned long ToFill = M->Size - M->FillLevel; Print (stdout, 2, " Filling 0x%lx bytes with 0x%02x\n", ToFill, M->FillVal); WriteMult (D->F, M->FillVal, ToFill); M->FillLevel = M->Size; } }
void PPUThread::InitRegs() { const u32 pc = Memory.Read32(entry); const u32 rtoc = Memory.Read32(entry + 4); //ConLog.Write("entry = 0x%x", entry); //ConLog.Write("rtoc = 0x%x", rtoc); SetPc(pc); /* const s32 thread_num = Emu.GetCPU().GetThreadNumById(GetType(), GetId()); if(thread_num < 0) { LOG_ERROR(PPU, "GetThreadNumById failed."); Emu.Pause(); return; } */ /* const s32 tls_size = Emu.GetTLSFilesz() * thread_num; if(tls_size >= Emu.GetTLSMemsz()) { LOG_ERROR(PPU, "Out of TLS memory."); Emu.Pause(); return; } */ m_stack_point = AlignAddr(m_stack_point, 0x200) - 0x200; GPR[1] = m_stack_point; GPR[2] = rtoc; /* for(int i=4; i<32; ++i) { if(i != 6) GPR[i] = (i+1) * 0x10000; } */ if(m_argv_addr.size()) { u64 argc = m_argv_addr.size(); m_stack_point -= 0xc + 4 * argc; u64 argv = m_stack_point; auto argv_list = vm::ptr<be_t<u64>>::make((u32)argv); for(int i=0; i<argc; ++i) argv_list[i] = m_argv_addr[i]; GPR[3] = argc; GPR[4] = argv; GPR[5] = argv ? argv + 0xc + 4 * argc : 0; //unk } else { GPR[3] = m_args[0]; GPR[4] = m_args[1]; GPR[5] = m_args[2]; GPR[6] = m_args[3]; } GPR[0] = pc; GPR[8] = entry; GPR[11] = 0x80; GPR[12] = Emu.GetMallocPageSize(); GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060; GPR[28] = GPR[4]; GPR[29] = GPR[3]; GPR[31] = GPR[5]; LR = Emu.GetPPUThreadExit(); CTR = PC; CR.CR = 0x22000082; VSCR.NJ = 1; TB = 0; }