Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OpenGOAL] Support for 128-bit arguments and return values (WIP) #510

Merged
merged 2 commits into from
May 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common/versions.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace versions {
// language version (OpenGOAL)
constexpr s32 GOAL_VERSION_MAJOR = 0;
constexpr s32 GOAL_VERSION_MINOR = 7;
constexpr s32 GOAL_VERSION_MINOR = 8;

constexpr int DECOMPILER_VERSION = 4;

Expand Down
2 changes: 1 addition & 1 deletion decompiler/config/all-types.gc
Original file line number Diff line number Diff line change
Expand Up @@ -13248,7 +13248,7 @@
(define-extern find-temp-buffer (function int pointer))
(define-extern dgo-load-link (function dgo-header kheap symbol symbol symbol))
(define-extern destroy-mem (function (pointer uint32) (pointer uint32) none))
(define-extern string->sound-name (function string uint128))
(define-extern string->sound-name (function string sound-name))
(define-extern str-play-kick (function none))
(define-extern *dgo-time* uint)

Expand Down
2 changes: 1 addition & 1 deletion decompiler/config/jak1_ntsc_black_label/type_casts.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@
],

"string->sound-name": [
[[6, 8], "a1", "(pointer uint8)"]
[[2, 18], "a1", "(pointer uint8)"]
],

"ramdisk-load": [
Expand Down
3 changes: 3 additions & 0 deletions docs/markdown/progress-notes/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,6 @@
- Support 128-bit bitfields inside of static structure
- Support 128-bit bitfield constants
- Support dynamic construction of 128-bit bitfield values

## V0.8 New Calling Convention for 128-bit
- 128-bit values may now be used in function arguments and return values.
18 changes: 1 addition & 17 deletions goal_src/engine/load/load-dgo.gc
Original file line number Diff line number Diff line change
Expand Up @@ -266,21 +266,6 @@ struct DgoHeader {
;; DGO LOAD and LINK
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(defun string->sound-name! ((out (pointer uint128)) (in string))
"This function was added as a temporary workaround for not having
uint128 return values in OpenGOAL yet."
(set! (-> out) (the uint128 0))
(let ((out-ptr (the (pointer uint8) out))
(in-ptr (-> in data)))
(while (and (nonzero? (-> in-ptr))
(< (&- in-ptr (-> in data)) 15))
(set! (-> out-ptr) (-> in-ptr))
(&+! out-ptr 1)
(&+! in-ptr 1)
)
)
)

(define *dgo-time* (the-as uint 0))

(defun dgo-load-begin ((name string) (buffer1 int) (buffer2 int) (current-heap int))
Expand All @@ -301,8 +286,7 @@ struct DgoHeader {
(set! (-> cmd b2) (the-as uint buffer2))
(set! (-> cmd bt) (the-as uint current-heap))
;; modified due to OpenGOAL not supporting uint128 return values yet
;;(set! (-> cmd name) (string->sound-name name))
(string->sound-name! (&-> cmd name) name)
(set! (-> cmd name) (string->sound-name name))
;; call now!
(call *load-dgo-rpc* (the-as uint 0) (the-as pointer cmd) (the-as uint 32))
cmd
Expand Down
2 changes: 2 additions & 0 deletions goal_src/engine/sound/gsound-h.gc
Original file line number Diff line number Diff line change
Expand Up @@ -354,3 +354,5 @@

(define *sound-bank-1* #f)
(define *sound-bank-2* #f)

(defun-extern string->sound-name string sound-name)
20 changes: 20 additions & 0 deletions goal_src/engine/sound/gsound.gc
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,23 @@
;; name in dgo: gsound
;; dgos: GAME, ENGINE


(defun string->sound-name ((str string))
(let ((snd-name (new 'stack-no-clear 'qword)))
(set! (-> snd-name quad) (the-as uint128 0))
(let ((out-ptr (the-as (pointer uint8) snd-name))
(in-ptr (-> str data))
)
(while
(and
(nonzero? (-> in-ptr 0))
(< (&- in-ptr (the-as uint (-> str data))) 15)
)
(set! (-> out-ptr 0) (-> in-ptr 0))
(set! out-ptr (&-> out-ptr 1))
(set! in-ptr (&-> in-ptr 1))
)
)
(the-as sound-name (-> snd-name quad))
)
)
25 changes: 19 additions & 6 deletions goal_src/kernel/gcommon.gc
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,7 @@
(define format _format)

;; vec4s - this is present in the game as a 128-bit integer with 4 packed floats.
;; 128-bit integers seem to be used almost never in GOAL and I suspect they were not
;; fully implemented in the compiler. Instead, 128-bit integer code used inline assembly.
;; OpenGOAL does not support 128-bit integer types, so this is a bit useless.
;; Note - the actually used vector type stores the vector in memory, not a register.
;; inline assembly code puts the register in vf registers, not integer registers.
;; this isn't used very much.
(deftype vec4s (uint128)
((x float :offset 0)
(y float :offset 32)
Expand All @@ -221,7 +217,24 @@
:flag-assert #x900000010
)

;; NOTE: there is a print/inspect for vec4s that is not implemented.
(defmethod inspect vec4s ((obj vec4s))
(format #t "[~8x] ~A~%" obj 'vec4s)
(format #t "~Tx: ~f~%" (-> obj x))
(format #t "~Ty: ~f~%" (-> obj y))
(format #t "~Tz: ~f~%" (-> obj z))
(format #t "~Tw: ~f~%" (-> obj w))
obj
)

(defmethod print vec4s ((obj vec4s))
(format #t "#<vector ~F ~F ~F ~F @ #x~X>"
(-> obj x)
(-> obj y)
(-> obj z)
(-> obj w)
obj)
obj
)

(defmacro print128 (value &key (stream #t))
"Print a 128-bit value"
Expand Down
1 change: 1 addition & 0 deletions goalc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_library(compiler
SHARED
emitter/CallingConvention.cpp
emitter/CodeTester.cpp
emitter/ObjectFileData.cpp
emitter/ObjectGenerator.cpp
Expand Down
3 changes: 2 additions & 1 deletion goalc/compiler/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ std::unique_ptr<FunctionEnv> Compiler::compile_top_level_function(const std::str

// only move to return register if we actually got a result
if (!dynamic_cast<const None*>(result)) {
fe->emit(std::make_unique<IR_Return>(fe->make_gpr(result->type()), result->to_gpr(fe.get())));
fe->emit(std::make_unique<IR_Return>(fe->make_gpr(result->type()), result->to_gpr(fe.get()),
emitter::gRegInfo.get_gpr_ret_reg()));
}

fe->finish();
Expand Down
35 changes: 23 additions & 12 deletions goalc/compiler/IR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ void regset_common(emitter::ObjectGenerator* gen,
///////////
// Return
///////////
IR_Return::IR_Return(const RegVal* return_reg, const RegVal* value)
: m_return_reg(return_reg), m_value(value) {}
IR_Return::IR_Return(const RegVal* return_reg, const RegVal* value, emitter::Register ret_reg)
: m_return_reg(return_reg), m_value(value), m_ret_reg(ret_reg) {}
std::string IR_Return::print() {
return fmt::format("ret {} {}", m_return_reg->print(), m_value->print());
}
Expand All @@ -154,7 +154,7 @@ void IR_Return::add_constraints(std::vector<IRegConstraint>* constraints, int my

c.ireg = m_return_reg->ireg();
c.instr_idx = my_id;
c.desired_register = emitter::RAX;
c.desired_register = m_ret_reg;
constraints->push_back(c);
}

Expand All @@ -167,7 +167,8 @@ void IR_Return::do_codegen(emitter::ObjectGenerator* gen,
if (val_reg == dest_reg) {
gen->add_instr(IGen::null(), irec);
} else {
gen->add_instr(IGen::mov_gpr64_gpr64(dest_reg, val_reg), irec);
regset_common(gen, allocs, irec, m_return_reg, m_value, true);
// gen->add_instr(IGen::mov_gpr64_gpr64(dest_reg, val_reg), irec);
}
}

Expand Down Expand Up @@ -361,8 +362,16 @@ void IR_GotoLabel::resolve(const Label* dest) {
// FunctionCall
/////////////////////

IR_FunctionCall::IR_FunctionCall(const RegVal* func, const RegVal* ret, std::vector<RegVal*> args)
: m_func(func), m_ret(ret), m_args(std::move(args)) {}
IR_FunctionCall::IR_FunctionCall(const RegVal* func,
const RegVal* ret,
std::vector<RegVal*> args,
std::vector<emitter::Register> arg_regs,
std::optional<emitter::Register> ret_reg)
: m_func(func),
m_ret(ret),
m_args(std::move(args)),
m_arg_regs(std::move(arg_regs)),
m_ret_reg(ret_reg) {}

std::string IR_FunctionCall::print() {
std::string result = fmt::format("call {} (ret {}) (args ", m_func->print(), m_ret->print());
Expand Down Expand Up @@ -398,15 +407,17 @@ void IR_FunctionCall::add_constraints(std::vector<IRegConstraint>* constraints,
IRegConstraint c;
c.ireg = m_args.at(i)->ireg();
c.instr_idx = my_id;
c.desired_register = emitter::gRegInfo.get_arg_reg(i);
c.desired_register = m_arg_regs.at(i);
constraints->push_back(c);
}

IRegConstraint c;
c.ireg = m_ret->ireg();
c.desired_register = emitter::gRegInfo.get_ret_reg();
c.instr_idx = my_id;
constraints->push_back(c);
if (m_ret_reg) {
IRegConstraint c;
c.ireg = m_ret->ireg();
c.desired_register = *m_ret_reg;
c.instr_idx = my_id;
constraints->push_back(c);
}
}

void IR_FunctionCall::do_codegen(emitter::ObjectGenerator* gen,
Expand Down
11 changes: 9 additions & 2 deletions goalc/compiler/IR.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class IR {

class IR_Return : public IR {
public:
IR_Return(const RegVal* return_reg, const RegVal* value);
IR_Return(const RegVal* return_reg, const RegVal* value, emitter::Register ret_reg);
std::string print() override;
RegAllocInstr to_rai() override;
void add_constraints(std::vector<IRegConstraint>* constraints, int my_id) override;
Expand All @@ -44,6 +44,7 @@ class IR_Return : public IR {
protected:
const RegVal* m_return_reg = nullptr;
const RegVal* m_value = nullptr;
emitter::Register m_ret_reg;
};

class IR_LoadConstant64 : public IR {
Expand Down Expand Up @@ -119,7 +120,11 @@ class IR_RegSet : public IR {

class IR_FunctionCall : public IR {
public:
IR_FunctionCall(const RegVal* func, const RegVal* ret, std::vector<RegVal*> args);
IR_FunctionCall(const RegVal* func,
const RegVal* ret,
std::vector<RegVal*> args,
std::vector<emitter::Register> arg_regs,
std::optional<emitter::Register> ret_reg);
std::string print() override;
RegAllocInstr to_rai() override;
void do_codegen(emitter::ObjectGenerator* gen,
Expand All @@ -131,6 +136,8 @@ class IR_FunctionCall : public IR {
const RegVal* m_func = nullptr;
const RegVal* m_ret = nullptr;
std::vector<RegVal*> m_args;
std::vector<emitter::Register> m_arg_regs;
std::optional<emitter::Register> m_ret_reg;
};

class IR_StaticVarAddr : public IR {
Expand Down
1 change: 1 addition & 0 deletions goalc/compiler/Val.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class RegVal : public Val {
RegVal(IRegister ireg, const TypeSpec& ts) : Val(coerce_to_reg_type(ts)), m_ireg(ireg) {}
bool is_register() const override { return true; }
IRegister ireg() const override { return m_ireg; }
void change_class(RegClass new_class) { m_ireg.reg_class = new_class; }
std::string print() const override { return m_ireg.to_string(); };
RegVal* to_reg(Env* fe) override;
RegVal* to_gpr(Env* fe) override;
Expand Down
Loading