mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-24 14:49:47 +00:00
update
This commit is contained in:
parent
5b4b5c238e
commit
dc32b59217
50
doc/code_status.md
Normal file
50
doc/code_status.md
Normal file
@ -0,0 +1,50 @@
|
||||
## gcommon.gc
|
||||
Missing stuff.
|
||||
|
||||
## gstring-h.gc
|
||||
Empty file.
|
||||
|
||||
## gkernel-h.gc
|
||||
Likely missing some macros. Missing `handle`, a child type of integer.
|
||||
|
||||
## gkernel.gc
|
||||
Missing lots of stuff. Will need x86-64 inline assembly and some tweaking for x86.
|
||||
|
||||
## pskernel.gc
|
||||
Possibly can be entirely left out. Seems to be mostly unused, or only used for PS2 debugging?
|
||||
|
||||
## gstring.gc
|
||||
Missing lots
|
||||
|
||||
## dgo-h.gc
|
||||
Done!
|
||||
|
||||
## gstate.gc
|
||||
Not started, probably needs state support in the compiler
|
||||
|
||||
## types.gc
|
||||
Needs child types of integer
|
||||
|
||||
## vu-macros.gc
|
||||
Empty.
|
||||
|
||||
## math.gc
|
||||
Has a unit test for a lot of functions.
|
||||
rand-vu-init, rand-vu, rand-vu-nostep, rand-vu-float-range, rand-vu-percent?, rand-vu-int-range, rand-vu-int-count aren't implemented
|
||||
|
||||
rand-uint31-gen might be wrong.
|
||||
|
||||
## vector.gc
|
||||
Partially done
|
||||
|
||||
## gravity-h.gc
|
||||
Empty file
|
||||
|
||||
## bounding-box-h.gc
|
||||
Just types. Done!
|
||||
|
||||
## matrix-h.gc
|
||||
Types and one function. Done, but the matrix-copy! function isn't that efficient.
|
||||
|
||||
## quaternion-h.gc
|
||||
Done!
|
@ -5,3 +5,43 @@
|
||||
;; name in dgo: bounding-box-h
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
;; Types related to bounding boxes.
|
||||
|
||||
;; floating point bounding box.
|
||||
(deftype bounding-box (structure)
|
||||
((min vector :inline :offset-assert 0)
|
||||
(max vector :inline :offset-assert 16)
|
||||
)
|
||||
:method-count-assert 16
|
||||
:size-assert #x20
|
||||
:flag-assert #x1000000020
|
||||
(:methods
|
||||
(dummy-9 () none 9)
|
||||
(dummy-10 () none 10)
|
||||
(dummy-11 () none 11)
|
||||
(dummy-12 () none 12)
|
||||
(dummy-13 () none 13)
|
||||
(dummy-14 () none 14)
|
||||
(dummy-15 () none 15)
|
||||
)
|
||||
)
|
||||
|
||||
;; integer (word) bounding box.
|
||||
(deftype bounding-box4w (structure)
|
||||
((min vector4w :inline :offset-assert 0)
|
||||
(max vector4w :inline :offset-assert 16)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x20
|
||||
:flag-assert #x900000020
|
||||
)
|
||||
|
||||
;; bounding both that has both a box and box4w.
|
||||
(deftype bounding-box-both (structure)
|
||||
((box bounding-box :inline :offset-assert 0)
|
||||
(box4w bounding-box4w :inline :offset-assert 32)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x40
|
||||
:flag-assert #x900000040
|
||||
)
|
@ -148,13 +148,32 @@
|
||||
;; I wonder who wrote this code.
|
||||
(set! (-> *random-generator* seed) #x666EDD1E)
|
||||
|
||||
(defmacro sext32-64 (x)
|
||||
`(sarv (shlv ,x 32) 32)
|
||||
)
|
||||
|
||||
(defun rand-uint31-gen ((gen random-generator))
|
||||
"Generate a supposedly random integer"
|
||||
(let ((result (-> gen seed)))
|
||||
;; addiu v1, r0, 16807
|
||||
(+! result 16807)
|
||||
;; to 32 bit, doing sign extension.
|
||||
(set! result (shlv result 32))
|
||||
(set! result (sarv result 32))
|
||||
"Generate a supposedly random integer.
|
||||
Note, this might not quite be right.
|
||||
But the highest bit is always zero, like it says
|
||||
and it looks kinda random to me."
|
||||
(let* ((sd (-> gen seed))
|
||||
;; addiu v1, r0, 16807
|
||||
;; mult3 v0, v1, a1
|
||||
(prod (imul64 16807 sd))
|
||||
;; mfhi v1
|
||||
(hi (shrv prod 32)) ;; sign extend this?
|
||||
(lo (sarv (shlv prod 32) 32))
|
||||
;; daddu v1, v1, v1
|
||||
(v1 (+ hi hi))
|
||||
;; srl a1, v0, 31
|
||||
(a1 (logand #xffffffff (shrv lo 31)))
|
||||
;; or v1, v1, a1
|
||||
;; daddu v0, v0 v1
|
||||
(result (+ lo (logior v1 a1)))
|
||||
)
|
||||
(set! result (shrv (logand #xffffffff (shlv result 1)) 1))
|
||||
(set! (-> gen seed) result)
|
||||
result
|
||||
)
|
||||
)
|
@ -5,3 +5,45 @@
|
||||
;; name in dgo: matrix-h
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
;; matrix-h
|
||||
(deftype matrix (structure)
|
||||
((data float 16 :offset-assert 0)
|
||||
(vector vector 4 :offset 0)
|
||||
(quad uint128 4 :offset 0)
|
||||
)
|
||||
:method-count-assert 10
|
||||
:size-assert #x40
|
||||
:flag-assert #xa00000040
|
||||
(:methods
|
||||
(dummy-9 () none 9)
|
||||
)
|
||||
)
|
||||
|
||||
(deftype matrix3 (structure)
|
||||
((data float 12 :offset-assert 0)
|
||||
(vector vector 3 :offset 0)
|
||||
(quad uint128 3 :offset 0)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x30
|
||||
:flag-assert #x900000030
|
||||
)
|
||||
|
||||
;; guess on signs here
|
||||
(deftype matrix4h (structure)
|
||||
((data int16 16 :offset-assert 0)
|
||||
(vector4h vector4h 4 :offset 0)
|
||||
(long int64 4 :offset 0)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x20
|
||||
:flag-assert #x900000020
|
||||
)
|
||||
|
||||
(defun matrix-copy! ((dst matrix) (src matrix))
|
||||
"Copy src to dst."
|
||||
;; actual implementation is in assembly, unrolled quad copies, loads/stores spaced out.
|
||||
(dotimes (i 16 dst)
|
||||
(set! (-> dst data i) (-> src data i))
|
||||
)
|
||||
)
|
@ -5,3 +5,18 @@
|
||||
;; name in dgo: quaternion-h
|
||||
;; dgos: GAME, ENGINE
|
||||
|
||||
(deftype quaternion (structure)
|
||||
((data float 4 :offset-assert 0)
|
||||
(x float :offset 0)
|
||||
(y float :offset 4)
|
||||
(z float :offset 8)
|
||||
(w float :offset 12)
|
||||
(vec vector :inline :offset 0)
|
||||
(quad uint128 :offset 0)
|
||||
)
|
||||
:method-count-assert 9
|
||||
:size-assert #x10
|
||||
:flag-assert #x900000010
|
||||
)
|
||||
|
||||
(define *unity-quaternion* (new 'static 'quaternion :x 0.0 :y 0.0 :z 0.0 :w 1.0))
|
@ -218,9 +218,9 @@ class Compiler {
|
||||
|
||||
// Math
|
||||
Val* compile_add(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
|
||||
Val* compile_sub(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_mul(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_imul64(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_div(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_shlv(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
Val* compile_sarv(const goos::Object& form, const goos::Object& rest, Env* env);
|
||||
|
@ -400,6 +400,8 @@ std::string IR_IntegerMath::print() {
|
||||
return fmt::format("subi {}, {}", m_dest->print(), m_arg->print());
|
||||
case IntegerMathKind::IMUL_32:
|
||||
return fmt::format("imul {}, {}", m_dest->print(), m_arg->print());
|
||||
case IntegerMathKind::IMUL_64:
|
||||
return fmt::format("imul64 {}, {}", m_dest->print(), m_arg->print());
|
||||
case IntegerMathKind::IDIV_32:
|
||||
return fmt::format("idiv {}, {}", m_dest->print(), m_arg->print());
|
||||
case IntegerMathKind::IMOD_32:
|
||||
@ -483,13 +485,15 @@ void IR_IntegerMath::do_codegen(emitter::ObjectGenerator* gen,
|
||||
gen->add_instr(IGen::imul_gpr32_gpr32(dr, get_reg(m_arg, allocs, irec)), irec);
|
||||
gen->add_instr(IGen::movsx_r64_r32(dr, dr), irec);
|
||||
} break;
|
||||
|
||||
case IntegerMathKind::IMUL_64: {
|
||||
auto dr = get_reg(m_dest, allocs, irec);
|
||||
gen->add_instr(IGen::imul_gpr64_gpr64(dr, get_reg(m_arg, allocs, irec)), irec);
|
||||
} break;
|
||||
case IntegerMathKind::IDIV_32: {
|
||||
gen->add_instr(IGen::cdq(), irec);
|
||||
gen->add_instr(IGen::idiv_gpr32(get_reg(m_arg, allocs, irec)), irec);
|
||||
gen->add_instr(IGen::movsx_r64_r32(get_reg(m_dest, allocs, irec), emitter::RAX), irec);
|
||||
} break;
|
||||
|
||||
case IntegerMathKind::IMOD_32: {
|
||||
gen->add_instr(IGen::cdq(), irec);
|
||||
gen->add_instr(IGen::idiv_gpr32(get_reg(m_arg, allocs, irec)), irec);
|
||||
|
@ -193,6 +193,7 @@ enum class IntegerMathKind {
|
||||
ADD_64,
|
||||
SUB_64,
|
||||
IMUL_32,
|
||||
IMUL_64,
|
||||
IDIV_32,
|
||||
SHLV_64,
|
||||
SARV_64,
|
||||
|
@ -101,6 +101,7 @@ static const std::unordered_map<
|
||||
{"+", &Compiler::compile_add},
|
||||
{"-", &Compiler::compile_sub},
|
||||
{"*", &Compiler::compile_mul},
|
||||
{"imul64", &Compiler::compile_imul64},
|
||||
{"/", &Compiler::compile_div},
|
||||
{"shlv", &Compiler::compile_shlv},
|
||||
{"shrv", &Compiler::compile_shrv},
|
||||
|
@ -160,6 +160,7 @@ Val* Compiler::compile_mul(const goos::Object& form, const goos::Object& rest, E
|
||||
auto math_type = get_math_mode(first_type);
|
||||
switch (math_type) {
|
||||
case MATH_INT: {
|
||||
// todo, signed vs unsigned?
|
||||
auto result = env->make_gpr(first_type);
|
||||
env->emit(std::make_unique<IR_RegSet>(result, first_val->to_gpr(env)));
|
||||
|
||||
@ -194,6 +195,41 @@ Val* Compiler::compile_mul(const goos::Object& form, const goos::Object& rest, E
|
||||
return get_none();
|
||||
}
|
||||
|
||||
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()) {
|
||||
throw_compile_error(form, "Invalid * form");
|
||||
}
|
||||
|
||||
// look at the first value to determine the math mode
|
||||
auto first_val = compile_error_guard(args.unnamed.at(0), env);
|
||||
auto first_type = first_val->type();
|
||||
auto math_type = get_math_mode(first_type);
|
||||
switch (math_type) {
|
||||
case MATH_INT: {
|
||||
auto result = env->make_gpr(first_type);
|
||||
env->emit(std::make_unique<IR_RegSet>(result, first_val->to_gpr(env)));
|
||||
|
||||
for (size_t i = 1; i < args.unnamed.size(); i++) {
|
||||
env->emit(std::make_unique<IR_IntegerMath>(
|
||||
IntegerMathKind::IMUL_64, result,
|
||||
to_math_type(compile_error_guard(args.unnamed.at(i), env), math_type, env)
|
||||
->to_gpr(env)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
case MATH_FLOAT:
|
||||
case MATH_INVALID:
|
||||
throw_compile_error(
|
||||
form, "Cannot determine the math mode for object of type " + first_type.print());
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
assert(false);
|
||||
return get_none();
|
||||
}
|
||||
|
||||
Val* Compiler::compile_sub(const goos::Object& form, const goos::Object& rest, Env* env) {
|
||||
auto args = get_va(form, rest);
|
||||
if (!args.named.empty() || args.unnamed.empty()) {
|
||||
|
@ -1387,6 +1387,19 @@ class IGen {
|
||||
return instr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Multiply gprs (64-bit, signed).
|
||||
* DANGER - this treats all operands as 64-bit. This is not like the EE.
|
||||
*/
|
||||
static Instruction imul_gpr64_gpr64(Register dst, Register src) {
|
||||
Instruction instr(0xf);
|
||||
instr.set_op2(0xaf);
|
||||
assert(dst.is_gpr());
|
||||
assert(src.is_gpr());
|
||||
instr.set_modrm_and_rex(dst.hw_id(), src.hw_id(), 3, true);
|
||||
return instr;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Divide (idiv, 32 bit)
|
||||
* todo UNTESTED
|
||||
|
@ -0,0 +1,2 @@
|
||||
(* #x12341234 #x12341234)
|
||||
|
@ -0,0 +1,2 @@
|
||||
(imul64 #x12341234 #x12341234)
|
||||
|
@ -236,3 +236,8 @@ TEST_F(ArithmeticTests, Subtraction) {
|
||||
runner.run_static_test(env, testCategory, "subtract-2.static.gc", {"4\n"});
|
||||
runner.run_static_test(env, testCategory, "subtract-let.static.gc", {"3\n"});
|
||||
}
|
||||
|
||||
TEST_F(ArithmeticTests, Multiplication2) {
|
||||
runner.run_static_test(env, testCategory, "multiply32.static.gc", {"-1234478448\n"});
|
||||
runner.run_static_test(env, testCategory, "multiply64.static.gc", {"93270638141856400\n"});
|
||||
}
|
Loading…
Reference in New Issue
Block a user