2013-12-07 06:57:16 +00:00
|
|
|
/**
|
|
|
|
******************************************************************************
|
|
|
|
* Xenia : Xbox 360 Emulator Research Project *
|
|
|
|
******************************************************************************
|
|
|
|
* Copyright 2013 Ben Vanik. All rights reserved. *
|
|
|
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
|
|
|
******************************************************************************
|
|
|
|
*/
|
|
|
|
|
2015-03-24 15:25:58 +00:00
|
|
|
#ifndef XENIA_CPU_FUNCTION_H_
|
|
|
|
#define XENIA_CPU_FUNCTION_H_
|
2013-12-07 06:57:16 +00:00
|
|
|
|
2014-07-14 05:28:00 +00:00
|
|
|
#include <memory>
|
2014-07-10 05:28:51 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2015-03-24 15:25:58 +00:00
|
|
|
#include "xenia/cpu/debug_info.h"
|
2015-08-06 04:50:02 +00:00
|
|
|
#include "xenia/cpu/frontend/ppc_context.h"
|
|
|
|
#include "xenia/cpu/symbol.h"
|
2015-03-24 15:25:58 +00:00
|
|
|
#include "xenia/cpu/thread_state.h"
|
2015-08-06 04:50:02 +00:00
|
|
|
#include "xenia/debug/function_trace_data.h"
|
2013-12-07 06:57:16 +00:00
|
|
|
|
2015-03-24 14:46:18 +00:00
|
|
|
namespace xe {
|
|
|
|
namespace cpu {
|
2013-12-07 06:57:16 +00:00
|
|
|
|
2015-08-01 21:07:13 +00:00
|
|
|
struct SourceMapEntry {
|
2015-09-22 04:10:57 +00:00
|
|
|
uint32_t guest_address; // PPC guest address (0x82....).
|
2015-08-01 21:07:13 +00:00
|
|
|
uint32_t hir_offset; // Block ordinal (16b) | Instr ordinal (16b)
|
|
|
|
uint32_t code_offset; // Offset from emitted code start.
|
|
|
|
};
|
|
|
|
|
2015-08-06 04:50:02 +00:00
|
|
|
class Function : public Symbol {
|
|
|
|
public:
|
|
|
|
enum class Behavior {
|
|
|
|
kDefault = 0,
|
|
|
|
kProlog,
|
|
|
|
kEpilog,
|
|
|
|
kEpilogReturn,
|
|
|
|
kBuiltin,
|
|
|
|
kExtern,
|
|
|
|
};
|
|
|
|
|
|
|
|
~Function() override;
|
|
|
|
|
|
|
|
uint32_t address() const { return address_; }
|
|
|
|
bool has_end_address() const { return end_address_ > 0; }
|
|
|
|
uint32_t end_address() const { return end_address_; }
|
|
|
|
void set_end_address(uint32_t value) { end_address_ = value; }
|
|
|
|
Behavior behavior() const { return behavior_; }
|
|
|
|
void set_behavior(Behavior value) { behavior_ = value; }
|
|
|
|
bool is_guest() const { return behavior_ != Behavior::kBuiltin; }
|
|
|
|
|
|
|
|
virtual bool Call(ThreadState* thread_state, uint32_t return_address) = 0;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Function(Module* module, uint32_t address);
|
|
|
|
|
|
|
|
uint32_t end_address_ = 0;
|
|
|
|
Behavior behavior_ = Behavior::kDefault;
|
|
|
|
};
|
|
|
|
|
|
|
|
class BuiltinFunction : public Function {
|
|
|
|
public:
|
|
|
|
typedef void (*Handler)(frontend::PPCContext* ppc_context, void* arg0,
|
|
|
|
void* arg1);
|
|
|
|
|
|
|
|
BuiltinFunction(Module* module, uint32_t address);
|
|
|
|
~BuiltinFunction() override;
|
|
|
|
|
|
|
|
void SetupBuiltin(Handler handler, void* arg0, void* arg1);
|
|
|
|
|
|
|
|
Handler handler() const { return handler_; }
|
|
|
|
void* arg0() const { return arg0_; }
|
|
|
|
void* arg1() const { return arg1_; }
|
|
|
|
|
|
|
|
bool Call(ThreadState* thread_state, uint32_t return_address) override;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Handler handler_ = nullptr;
|
|
|
|
void* arg0_ = nullptr;
|
|
|
|
void* arg1_ = nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
class GuestFunction : public Function {
|
2014-07-11 03:20:00 +00:00
|
|
|
public:
|
2015-08-06 04:50:02 +00:00
|
|
|
typedef void (*ExternHandler)(frontend::PPCContext* ppc_context,
|
|
|
|
kernel::KernelState* kernel_state);
|
|
|
|
|
|
|
|
GuestFunction(Module* module, uint32_t address);
|
|
|
|
~GuestFunction() override;
|
2013-12-07 06:57:16 +00:00
|
|
|
|
2015-03-25 02:41:29 +00:00
|
|
|
uint32_t address() const { return address_; }
|
2015-08-06 04:50:02 +00:00
|
|
|
bool has_end_address() const { return end_address_ > 0; }
|
|
|
|
uint32_t end_address() const { return end_address_; }
|
|
|
|
void set_end_address(uint32_t value) { end_address_ = value; }
|
2013-12-07 06:57:16 +00:00
|
|
|
|
2015-08-01 21:07:13 +00:00
|
|
|
virtual uint8_t* machine_code() const = 0;
|
|
|
|
virtual size_t machine_code_length() const = 0;
|
|
|
|
|
2014-07-14 05:28:00 +00:00
|
|
|
DebugInfo* debug_info() const { return debug_info_.get(); }
|
|
|
|
void set_debug_info(std::unique_ptr<DebugInfo> debug_info) {
|
|
|
|
debug_info_ = std::move(debug_info);
|
|
|
|
}
|
2015-08-06 04:50:02 +00:00
|
|
|
debug::FunctionTraceData& trace_data() { return trace_data_; }
|
2015-08-01 21:07:13 +00:00
|
|
|
std::vector<SourceMapEntry>& source_map() { return source_map_; }
|
2013-12-22 17:25:44 +00:00
|
|
|
|
2015-08-06 04:50:02 +00:00
|
|
|
ExternHandler extern_handler() const { return extern_handler_; }
|
|
|
|
void SetupExtern(ExternHandler handler);
|
|
|
|
|
2015-09-22 04:10:57 +00:00
|
|
|
const SourceMapEntry* LookupGuestAddress(uint32_t guest_address) const;
|
2015-08-01 21:07:13 +00:00
|
|
|
const SourceMapEntry* LookupHIROffset(uint32_t offset) const;
|
2015-09-22 04:10:57 +00:00
|
|
|
const SourceMapEntry* LookupMachineCodeOffset(uint32_t offset) const;
|
2015-06-17 03:18:48 +00:00
|
|
|
|
2015-09-22 04:10:57 +00:00
|
|
|
uint32_t MapGuestAddressToMachineCodeOffset(uint32_t guest_address) const;
|
|
|
|
uintptr_t MapGuestAddressToMachineCode(uint32_t guest_address) const;
|
|
|
|
uint32_t MapMachineCodeToGuestAddress(uintptr_t host_address) const;
|
2015-09-21 04:31:05 +00:00
|
|
|
|
2015-08-06 04:50:02 +00:00
|
|
|
bool Call(ThreadState* thread_state, uint32_t return_address) override;
|
2013-12-07 06:57:16 +00:00
|
|
|
|
2014-07-11 03:20:00 +00:00
|
|
|
protected:
|
2015-05-06 00:21:08 +00:00
|
|
|
virtual bool CallImpl(ThreadState* thread_state, uint32_t return_address) = 0;
|
2013-12-07 06:57:16 +00:00
|
|
|
|
2014-07-11 03:20:00 +00:00
|
|
|
protected:
|
2014-07-14 05:28:00 +00:00
|
|
|
std::unique_ptr<DebugInfo> debug_info_;
|
2015-08-06 04:50:02 +00:00
|
|
|
debug::FunctionTraceData trace_data_;
|
2015-08-01 21:07:13 +00:00
|
|
|
std::vector<SourceMapEntry> source_map_;
|
2015-08-06 04:50:02 +00:00
|
|
|
ExternHandler extern_handler_ = nullptr;
|
2013-12-07 06:57:16 +00:00
|
|
|
};
|
|
|
|
|
2015-03-24 14:46:18 +00:00
|
|
|
} // namespace cpu
|
|
|
|
} // namespace xe
|
2013-12-07 06:57:16 +00:00
|
|
|
|
2015-03-24 15:25:58 +00:00
|
|
|
#endif // XENIA_CPU_FUNCTION_H_
|