mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-24 06:39:51 +00:00
add float min max to the compiler
This commit is contained in:
parent
435b0da144
commit
e93b54347f
@ -47,4 +47,19 @@ Just types. Done!
|
||||
Types and one function. Done, but the matrix-copy! function isn't that efficient.
|
||||
|
||||
## quaternion-h.gc
|
||||
Done!
|
||||
Done!
|
||||
|
||||
## euler-h.gc
|
||||
Needs static arrays
|
||||
|
||||
## transform-h.gc
|
||||
Done!
|
||||
|
||||
## geometry-h.gc
|
||||
Done!
|
||||
|
||||
## trigonometry-h.gc
|
||||
Empty File.
|
||||
|
||||
## transformq-h.gc
|
||||
Not done.
|
@ -210,6 +210,8 @@
|
||||
("ENGINE.CGO"
|
||||
("types-h.o" "types-h")
|
||||
("vu1-macros.o" "vu1-macros")
|
||||
|
||||
;; the "math" section
|
||||
("math.o" "math")
|
||||
("vector-h.o" "vector-h")
|
||||
("gravity-h.o" "gravity-h")
|
||||
@ -228,6 +230,8 @@
|
||||
("euler.o" "euler")
|
||||
("geometry.o" "geometry")
|
||||
("trigonometry.o" "trigonometry")
|
||||
|
||||
|
||||
("gsound-h.o" "gsound-h")
|
||||
("timer-h.o" "timer-h")
|
||||
("timer.o" "timer")
|
||||
|
@ -5,3 +5,32 @@
|
||||
;; name in dgo: geometry-h
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
;; geometry-h
|
||||
(deftype curve (structure)
|
||||
((cverts uint32 :offset-assert 0)
|
||||
(num-cverts int32 :offset-assert 4)
|
||||
(knots uint32 :offset-assert 8)
|
||||
(num-knots int32 :offset-assert 12)
|
||||
(length float :offset-assert 16)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x14
|
||||
:flag-assert #x900000014
|
||||
)
|
||||
|
||||
;; geometry-h
|
||||
(deftype border-plane (basic)
|
||||
((name basic :offset-assert 4)
|
||||
(action basic :offset-assert 8)
|
||||
(slot int8 :offset-assert 12)
|
||||
(trans vector :inline :offset-assert 16)
|
||||
(normal vector :inline :offset-assert 32)
|
||||
)
|
||||
:method-count-assert 11
|
||||
:size-assert #x30
|
||||
:flag-assert #xb00000030
|
||||
(:methods
|
||||
(dummy-9 () none 9)
|
||||
(dummy-10 () none 10)
|
||||
)
|
||||
)
|
@ -5,30 +5,20 @@
|
||||
;; name in dgo: math
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
;; contains various math helpers
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;; float macros
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; at some point, these could be more optimized.
|
||||
;; at some point, this could be more optimized.
|
||||
;; MIPS has an explicit abs.s instruction, but x86-64 doesn't.
|
||||
;; modern clang on O3 does a comiss/branch and this is probably pretty close.
|
||||
|
||||
(defmacro fabs (x)
|
||||
;"Floating point absolute value. On MIPS there is a abs.s instruction.
|
||||
; In the future we could consider optimizing this more for x86, but this is good enough."
|
||||
`(if (< ,x 0)
|
||||
(- ,x)
|
||||
,x)
|
||||
)
|
||||
|
||||
(defmacro fmin (x y)
|
||||
`(if (< ,x ,y)
|
||||
,x
|
||||
,y)
|
||||
)
|
||||
|
||||
(defmacro fmax (x y)
|
||||
`(if (> ,x ,y)
|
||||
,x
|
||||
,y)
|
||||
`(if (< (the float ,x) 0)
|
||||
(- (the float ,x))
|
||||
(the float ,x))
|
||||
)
|
||||
|
||||
|
||||
|
@ -5,3 +5,24 @@
|
||||
;; name in dgo: transform-h
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
|
||||
(deftype transform (structure)
|
||||
((trans vector :inline :offset-assert 0)
|
||||
(rot vector :inline :offset-assert 16)
|
||||
(scale vector :inline :offset-assert 32)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x30
|
||||
:flag-assert #x900000030
|
||||
)
|
||||
|
||||
|
||||
(deftype trs (basic)
|
||||
((trans vector :inline :offset-assert 16)
|
||||
(rot vector :inline :offset-assert 32)
|
||||
(scale vector :inline :offset-assert 48)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x40
|
||||
:flag-assert #x900000040
|
||||
)
|
@ -231,6 +231,8 @@ class Compiler {
|
||||
Val* compile_logand(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_logior(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_pointer_add(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_fmin(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_fmax(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
|
||||
// Function
|
||||
Val* compile_lambda(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
|
@ -522,6 +522,10 @@ std::string IR_FloatMath::print() {
|
||||
return fmt::format("addss {}, {}", m_dest->print(), m_arg->print());
|
||||
case FloatMathKind::SUB_SS:
|
||||
return fmt::format("subss {}, {}", m_dest->print(), m_arg->print());
|
||||
case FloatMathKind::MAX_SS:
|
||||
return fmt::format("maxss {}, {}", m_dest->print(), m_arg->print());
|
||||
case FloatMathKind::MIN_SS:
|
||||
return fmt::format("minss {}, {}", m_dest->print(), m_arg->print());
|
||||
default:
|
||||
throw std::runtime_error("Unsupported FloatMathKind");
|
||||
}
|
||||
@ -555,6 +559,14 @@ void IR_FloatMath::do_codegen(emitter::ObjectGenerator* gen,
|
||||
gen->add_instr(
|
||||
IGen::subss_xmm_xmm(get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec);
|
||||
break;
|
||||
case FloatMathKind::MAX_SS:
|
||||
gen->add_instr(
|
||||
IGen::maxss_xmm_xmm(get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec);
|
||||
break;
|
||||
case FloatMathKind::MIN_SS:
|
||||
gen->add_instr(
|
||||
IGen::minss_xmm_xmm(get_reg(m_dest, allocs, irec), get_reg(m_arg, allocs, irec)), irec);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
@ -224,7 +224,7 @@ class IR_IntegerMath : public IR {
|
||||
RegVal* m_arg;
|
||||
};
|
||||
|
||||
enum class FloatMathKind { DIV_SS, MUL_SS, ADD_SS, SUB_SS };
|
||||
enum class FloatMathKind { DIV_SS, MUL_SS, ADD_SS, SUB_SS, MIN_SS, MAX_SS };
|
||||
|
||||
class IR_FloatMath : public IR {
|
||||
public:
|
||||
|
@ -124,6 +124,8 @@ static const std::unordered_map<
|
||||
{"<", &Compiler::compile_condition_as_bool},
|
||||
{">", &Compiler::compile_condition_as_bool},
|
||||
{"&+", &Compiler::compile_pointer_add},
|
||||
{"fmax", &Compiler::compile_fmax},
|
||||
{"fmin", &Compiler::compile_fmin},
|
||||
|
||||
// BUILDER (build-dgo/build-cgo?)
|
||||
{"build-dgos", &Compiler::compile_build_dgo},
|
||||
|
@ -195,6 +195,52 @@ Val* Compiler::compile_mul(const goos::Object& form, const goos::Object& rest, E
|
||||
return get_none();
|
||||
}
|
||||
|
||||
Val* Compiler::compile_fmin(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||
auto args = get_va(form, rest);
|
||||
if (!args.named.empty() || args.unnamed.empty()) {
|
||||
throw_compile_error(form, "Invalid fmin form");
|
||||
}
|
||||
|
||||
// look at the first value to determine the math mode
|
||||
auto first_val = compile_error_guard(args.unnamed.at(0), env);
|
||||
if (get_math_mode(first_val->type()) != MATH_FLOAT) {
|
||||
throw_compile_error(form, "Must use floats in fmin");
|
||||
}
|
||||
auto result = env->make_xmm(first_val->type());
|
||||
env->emit(std::make_unique<IR_RegSet>(result, first_val->to_xmm(env)));
|
||||
for (size_t i = 1; i < args.unnamed.size(); i++) {
|
||||
auto val = compile_error_guard(args.unnamed.at(i), env);
|
||||
if (get_math_mode(val->type()) != MATH_FLOAT) {
|
||||
throw_compile_error(form, "Must use floats in fmin");
|
||||
}
|
||||
env->emit(std::make_unique<IR_FloatMath>(FloatMathKind::MIN_SS, result, val->to_xmm(env)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Val* Compiler::compile_fmax(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||
auto args = get_va(form, rest);
|
||||
if (!args.named.empty() || args.unnamed.empty()) {
|
||||
throw_compile_error(form, "Invalid fmax form");
|
||||
}
|
||||
|
||||
// look at the first value to determine the math mode
|
||||
auto first_val = compile_error_guard(args.unnamed.at(0), env);
|
||||
if (get_math_mode(first_val->type()) != MATH_FLOAT) {
|
||||
throw_compile_error(form, "Must use floats in fmax");
|
||||
}
|
||||
auto result = env->make_xmm(first_val->type());
|
||||
env->emit(std::make_unique<IR_RegSet>(result, first_val->to_xmm(env)));
|
||||
for (size_t i = 1; i < args.unnamed.size(); i++) {
|
||||
auto val = compile_error_guard(args.unnamed.at(i), env);
|
||||
if (get_math_mode(val->type()) != MATH_FLOAT) {
|
||||
throw_compile_error(form, "Must use floats in fmax");
|
||||
}
|
||||
env->emit(std::make_unique<IR_FloatMath>(FloatMathKind::MAX_SS, result, val->to_xmm(env)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Val* Compiler::compile_imul64(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||
auto args = get_va(form, rest);
|
||||
if (!args.named.empty() || args.unnamed.empty()) {
|
||||
|
@ -1740,6 +1740,34 @@ class IGen {
|
||||
return instr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Floating point minimum.
|
||||
*/
|
||||
static Instruction minss_xmm_xmm(Register dst, Register src) {
|
||||
assert(dst.is_xmm());
|
||||
assert(src.is_xmm());
|
||||
Instruction instr(0xf3);
|
||||
instr.set_op2(0x0f);
|
||||
instr.set_op3(0x5d);
|
||||
instr.set_modrm_and_rex(dst.hw_id(), src.hw_id(), 3, false);
|
||||
instr.swap_op0_rex();
|
||||
return instr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Floating point maximum.
|
||||
*/
|
||||
static Instruction maxss_xmm_xmm(Register dst, Register src) {
|
||||
assert(dst.is_xmm());
|
||||
assert(src.is_xmm());
|
||||
Instruction instr(0xf3);
|
||||
instr.set_op2(0x0f);
|
||||
instr.set_op3(0x5f);
|
||||
instr.set_modrm_and_rex(dst.hw_id(), src.hw_id(), 3, false);
|
||||
instr.swap_op0_rex();
|
||||
return instr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Convert GPR int32 to XMM float (single precision)
|
||||
*/
|
||||
|
2
test/goalc/source_templates/float/float-max.static.gc
Normal file
2
test/goalc/source_templates/float/float-max.static.gc
Normal file
@ -0,0 +1,2 @@
|
||||
(define format _format)
|
||||
(format #t "~,,2f~%" (fmax 1.0 2.0 -1.2 3.7 2.2))
|
2
test/goalc/source_templates/float/float-min.static.gc
Normal file
2
test/goalc/source_templates/float/float-min.static.gc
Normal file
@ -0,0 +1,2 @@
|
||||
(define format _format)
|
||||
(format #t "~,,2f~%" (fmin 1.0 2.0 -1.2 3.7 2.2))
|
@ -75,3 +75,8 @@ TEST_F(FloatTests, Functions) {
|
||||
env, testCategory, "nested-float-functions.static.gc",
|
||||
{"i 1.4400 3.4000\nr 10.1523\ni 1.2000 10.1523\nr 17.5432\n17.543 10.152\n0\n"});
|
||||
}
|
||||
|
||||
TEST_F(FloatTests, MinMax) {
|
||||
runner.run_static_test(env, testCategory, "float-max.static.gc", {"3.70\n0\n"});
|
||||
runner.run_static_test(env, testCategory, "float-min.static.gc", {"-1.20\n0\n"});
|
||||
}
|
Loading…
Reference in New Issue
Block a user