mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
fix misleading comments
This commit is contained in:
parent
ba37e241ce
commit
f5a8d3d227
|
@ -1,3 +1,11 @@
|
|||
/*!
|
||||
* @file CodeTester.cpp
|
||||
* The CodeTester is a utility to run the output of the compiler as part of a unit test.
|
||||
* This is effective for tests which try all combinations of registers, etc.
|
||||
*
|
||||
* The CodeTester can't be used for tests requiring the full GOAL language/linking.
|
||||
*/
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include "CodeTester.h"
|
||||
#include "IGen.h"
|
||||
|
@ -6,6 +14,9 @@ namespace emitter {
|
|||
|
||||
CodeTester::CodeTester() : m_info(RegisterInfo::make_register_info()) {}
|
||||
|
||||
/*!
|
||||
* Convert to a string for comparison against an assembler or tests.
|
||||
*/
|
||||
std::string CodeTester::dump_to_hex_string(bool nospace) {
|
||||
std::string result;
|
||||
char buff[32];
|
||||
|
@ -26,20 +37,25 @@ std::string CodeTester::dump_to_hex_string(bool nospace) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add an instruction to the buffer.
|
||||
*/
|
||||
void CodeTester::emit(const Instruction& instr) {
|
||||
code_buffer_size += instr.emit(code_buffer + code_buffer_size);
|
||||
assert(code_buffer_size <= code_buffer_capacity);
|
||||
}
|
||||
|
||||
void CodeTester::emit_set_gpr_as_return(Register gpr) {
|
||||
assert(gpr.is_gpr());
|
||||
emit(IGen::mov_gpr64_gpr64(RAX, gpr));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add a return instruction to the buffer.
|
||||
*/
|
||||
void CodeTester::emit_return() {
|
||||
emit(IGen::ret());
|
||||
}
|
||||
|
||||
/*!
|
||||
* Pop all GPRs off of the stack. Optionally exclude rax.
|
||||
* Pops RSP always, which is weird, but doesn't cause issues.
|
||||
*/
|
||||
void CodeTester::emit_pop_all_gprs(bool exclude_rax) {
|
||||
for (int i = 16; i-- > 0;) {
|
||||
if (i != RAX || !exclude_rax) {
|
||||
|
@ -48,6 +64,10 @@ void CodeTester::emit_pop_all_gprs(bool exclude_rax) {
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Push all GPRs onto the stack. Optionally exclude RAX.
|
||||
* Pushes RSP always, which is weird, but doesn't cause issues.
|
||||
*/
|
||||
void CodeTester::emit_push_all_gprs(bool exclude_rax) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (i != RAX || !exclude_rax) {
|
||||
|
@ -56,6 +76,9 @@ void CodeTester::emit_push_all_gprs(bool exclude_rax) {
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Push all xmm registers (all 128-bits) to the stack.
|
||||
*/
|
||||
void CodeTester::emit_push_all_xmms() {
|
||||
emit(IGen::sub_gpr64_imm8s(RSP, 8));
|
||||
for (int i = 0; i < 16; i++) {
|
||||
|
@ -64,6 +87,9 @@ void CodeTester::emit_push_all_xmms() {
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Pop all xmm registers (all 128-bits) from the stack
|
||||
*/
|
||||
void CodeTester::emit_pop_all_xmms() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
emit(IGen::load128_xmm128_gpr64(XMM0 + i, RSP));
|
||||
|
@ -72,18 +98,31 @@ void CodeTester::emit_pop_all_xmms() {
|
|||
emit(IGen::add_gpr64_imm8s(RSP, 8));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Remove everything from the code buffer
|
||||
*/
|
||||
void CodeTester::clear() {
|
||||
code_buffer_size = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Execute the buffered code with no arguments, return the value of RAX.
|
||||
*/
|
||||
u64 CodeTester::execute() {
|
||||
return ((u64(*)())code_buffer)();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Execute code buffer with arguments. Use get_c_abi_arg to figure out which registers the
|
||||
* arguments will appear in (will handle windows/linux differences)
|
||||
*/
|
||||
u64 CodeTester::execute(u64 in0, u64 in1, u64 in2, u64 in3) {
|
||||
return ((u64(*)(u64, u64, u64, u64))code_buffer)(in0, in1, in2, in3);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Allocate a code buffer of the given size.
|
||||
*/
|
||||
void CodeTester::init_code_buffer(int capacity) {
|
||||
code_buffer = (u8*)mmap(nullptr, capacity, PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/*!
|
||||
* @file CodeTester.h
|
||||
* The CodeTester is a utility to run the output of the compiler as part of a unit test.
|
||||
* This is effective for tests which try all combinations of registers, etc.
|
||||
*
|
||||
* The CodeTester can't be used for tests requiring the full GOAL language/linking.
|
||||
*/
|
||||
|
||||
#ifndef JAK_CODETESTER_H
|
||||
#define JAK_CODETESTER_H
|
||||
|
||||
|
@ -17,11 +25,13 @@ class CodeTester {
|
|||
void emit_push_all_xmms();
|
||||
void emit_pop_all_xmms();
|
||||
void emit_return();
|
||||
void emit_set_gpr_as_return(Register gpr);
|
||||
void emit(const Instruction& instr);
|
||||
u64 execute();
|
||||
u64 execute(u64 in0, u64 in1, u64 in2, u64 in3);
|
||||
|
||||
/*!
|
||||
* Execute the function, get the return value in RAX, convert to a T, and return it.
|
||||
*/
|
||||
template <typename T>
|
||||
T execute_ret(u64 in0, u64 in1, u64 in2, u64 in3) {
|
||||
u64 result_u64 = ((u64(*)(u64, u64, u64, u64))code_buffer)(in0, in1, in2, in3);
|
||||
|
@ -30,6 +40,9 @@ class CodeTester {
|
|||
return result_T;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Add data to the code buffer.
|
||||
*/
|
||||
template <typename T>
|
||||
int emit_data(T x) {
|
||||
auto ret = code_buffer_size;
|
||||
|
@ -39,12 +52,8 @@ class CodeTester {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void clear();
|
||||
~CodeTester();
|
||||
|
||||
/*!
|
||||
* Should allow emitter tests which run code to do the right thing on windows.
|
||||
* Assumes RAX is return and RSP is stack pointer.
|
||||
*/
|
||||
Register get_c_abi_arg_reg(int i) {
|
||||
#ifdef _WIN32
|
||||
|
@ -76,10 +85,20 @@ class CodeTester {
|
|||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get the name of the given register, for debugging.
|
||||
*/
|
||||
std::string reg_name(Register x) { return m_info.get_info(x).name; }
|
||||
|
||||
/*!
|
||||
* Get number of bytes currently in use (offset of the next thing to be added)
|
||||
*/
|
||||
int size() const { return code_buffer_size; }
|
||||
const u8* data() const { return code_buffer; }
|
||||
|
||||
/*!
|
||||
* Write over existing data at the given offset.
|
||||
*/
|
||||
template <typename T>
|
||||
void write(T x, int at) {
|
||||
assert(at >= 0);
|
||||
|
@ -87,6 +106,9 @@ class CodeTester {
|
|||
memcpy(code_buffer + at, &x, sizeof(T));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Read existing data at the given offset.
|
||||
*/
|
||||
template <typename T>
|
||||
T read(int at) {
|
||||
assert(at >= 0);
|
||||
|
@ -96,7 +118,8 @@ class CodeTester {
|
|||
return result;
|
||||
}
|
||||
|
||||
const u8* data() const { return code_buffer; }
|
||||
void clear();
|
||||
~CodeTester();
|
||||
|
||||
private:
|
||||
int code_buffer_size = 0;
|
||||
|
|
|
@ -16,23 +16,23 @@ namespace emitter {
|
|||
// registers by name
|
||||
enum X86_REG : u8 {
|
||||
RAX, // return, temp
|
||||
RCX, // arg 3
|
||||
RDX, // arg 2
|
||||
RBX, // X saved
|
||||
RCX, // arg 3, temp
|
||||
RDX, // arg 2, temp
|
||||
RBX, // saved
|
||||
|
||||
RSP, // stack pointer !!!!
|
||||
RBP, // saved !!!!
|
||||
RSI, // arg 1
|
||||
RDI, // arg 0
|
||||
RSP, // stack pointer (special)
|
||||
RBP, // saved
|
||||
RSI, // arg 1, temp
|
||||
RDI, // arg 0, temp
|
||||
|
||||
R8, // arg 4
|
||||
R9, // arg 5, saved
|
||||
R8, // arg 4, temp
|
||||
R9, // arg 5, temp
|
||||
R10, // arg 6, saved (arg in GOAL only)
|
||||
R11, // arg 7, saved (arg in GOAL only)
|
||||
R12, // X saved - pp register (like s6) !!
|
||||
R13, // X saved - function call register (like t9) !!
|
||||
R14, // X saved - offset (added in GOAL x86)
|
||||
R15, // X saved - st (like s7)
|
||||
R12, // saved
|
||||
R13, // pp (special!)
|
||||
R14, // st (special!)
|
||||
R15, // offset (special!)
|
||||
XMM0,
|
||||
XMM1,
|
||||
XMM2,
|
||||
|
|
Loading…
Reference in a new issue