Skip to content

Commit

Permalink
[OpenGOAL] Support for 128-bit arguments and return values (WIP) (#510)
Browse files Browse the repository at this point in the history
* xmm call and return working, needs some careful double checking and tests

* clean up and test
  • Loading branch information
water111 authored May 21, 2021
1 parent 62877ed commit 663b5c7
Show file tree
Hide file tree
Showing 21 changed files with 365 additions and 111 deletions.
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

0 comments on commit 663b5c7

Please sign in to comment.