mirror of
https://github.com/open-goal/jak-project
synced 2026-07-04 21:35:47 -04:00
ad5cec1bb4
This moves the blerc math from mips2c to the Merc2 renderer, and uses floats instead. We could potentially do this on the GPU, which would be even faster, but this isn't that slow in the first place.
696 lines
34 KiB
C++
696 lines
34 KiB
C++
//--------------------------MIPS2C---------------------
|
|
|
|
#include <mutex>
|
|
|
|
#include "common/global_profiler/GlobalProfiler.h"
|
|
|
|
#include "game/kernel/jak2/kscheme.h"
|
|
#include "game/mips2c/mips2c_private.h"
|
|
|
|
// I've rewritten the math part in C here:
|
|
|
|
struct ChunkHeader {
|
|
s8 num_entries; // not including this header
|
|
s8 unk[11];
|
|
s16 overlap_val;
|
|
s16 pad;
|
|
};
|
|
static_assert(sizeof(ChunkHeader) == 16);
|
|
|
|
struct S16_8 {
|
|
s16 vals[8];
|
|
};
|
|
static_assert(sizeof(S16_8) == 16);
|
|
|
|
struct BlercBlockHeader {
|
|
u8 tag_bytes[16];
|
|
u32 vtx_count;
|
|
u32 overlap;
|
|
u32 lump_dst;
|
|
u32 lump_qwc;
|
|
};
|
|
|
|
struct BlercBlock {
|
|
u8 output[848];
|
|
BlercBlockHeader header;
|
|
};
|
|
|
|
struct BlercContext {
|
|
BlercBlock block;
|
|
s8 dummy[7312];
|
|
};
|
|
|
|
namespace {
|
|
|
|
int og_load_skip_pattern(int in) {
|
|
int base = (in >> 3) << 3;
|
|
int rem = (in & 0b111);
|
|
int pattern[8] = {0, 1, 4, 5, 8, 9, 12, 13};
|
|
return base * 2 + pattern[rem];
|
|
}
|
|
|
|
void simplified1(BlercContext* context, u8* ee_buffer) {
|
|
const s8* dummy_data = context->dummy;
|
|
const auto* first_chunk_header = (ChunkHeader*)dummy_data;
|
|
const int stride = (first_chunk_header->num_entries + 1) * 16;
|
|
int overlap = context->block.header.overlap;
|
|
u8* out = context->block.output;
|
|
|
|
// past the first chunk
|
|
const s8* data_src = dummy_data + stride; // t2/t3
|
|
S16_8* ee_s16_8 = (S16_8*)ee_buffer;
|
|
for (int i = 0; i < overlap; i++) {
|
|
const auto* this_chunk = (ChunkHeader*)data_src;
|
|
for (int j = 0; j < 8; j++) {
|
|
ee_s16_8[i].vals[j] = this_chunk->overlap_val;
|
|
}
|
|
|
|
data_src += stride; // next chunk
|
|
}
|
|
|
|
int total_count = ((ChunkHeader*)data_src)->num_entries; // lb s5, 0(t3)
|
|
data_src += 16; // now in s4
|
|
const u8* base_data_ptr = (u8*)dummy_data + 16; // ra in asm
|
|
const s8* base_data_ptr_s = dummy_data + 16; // ra in asm
|
|
|
|
memcpy(out, data_src, total_count * 16);
|
|
for (int i = 0; i < total_count * 8; i++) {
|
|
s32 base_val = base_data_ptr[i] * 8192; // ld t6 grabs 8 at a time
|
|
|
|
for (int j = 0; j < overlap; j++) {
|
|
base_val += base_data_ptr_s[i + (j + 1) * stride] * ee_s16_8[j].vals[0]; // ld t5
|
|
}
|
|
|
|
base_val >>= 13;
|
|
|
|
if (base_val < 0)
|
|
base_val = 0;
|
|
if (base_val > 255)
|
|
base_val = 255;
|
|
|
|
int oo = og_load_skip_pattern(i);
|
|
out[oo + 2] = base_val;
|
|
}
|
|
}
|
|
|
|
void blerc_c(void* a, void* b) {
|
|
simplified1((BlercContext*)a, (u8*)b);
|
|
}
|
|
} // namespace
|
|
|
|
// clang-format off
|
|
|
|
|
|
extern std::mutex g_merc_data_mutex;
|
|
|
|
using ::jak2::intern_from_c;
|
|
namespace Mips2C::jak2 {
|
|
namespace blerc_execute {
|
|
struct Cache {
|
|
void* blerc_globals; // *blerc-globals*
|
|
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
|
void* gsf_buffer; // *gsf-buffer*
|
|
void* stats_blerc; // *stats-blerc*
|
|
void* flush_cache; // flush-cache
|
|
} cache;
|
|
|
|
u64 execute(void* ctxt) {
|
|
bool hit18 = false;
|
|
bool hit19 = false;
|
|
auto pp = scoped_prof("blerc-exec");
|
|
std::unique_lock<std::mutex> lk(g_merc_data_mutex);
|
|
auto* c = (ExecutionContext*)ctxt;
|
|
bool bc = false;
|
|
u32 call_addr = 0;
|
|
u32 madr, sadr, qwc, tadr;
|
|
c->daddiu(sp, sp, -96); // daddiu sp, sp, -96
|
|
c->sd(ra, 0, sp); // sd ra, 0(sp)
|
|
c->sq(s2, 16, sp); // sq s2, 16(sp)
|
|
c->sq(s3, 32, sp); // sq s3, 32(sp)
|
|
c->sq(s4, 48, sp); // sq s4, 48(sp)
|
|
c->sq(s5, 64, sp); // sq s5, 64(sp)
|
|
c->sq(gp, 80, sp); // sq gp, 80(sp)
|
|
c->load_symbol2(v1, cache.blerc_globals); // lw v1, *blerc-globals*(s7)
|
|
c->lwu(s5, 0, v1); // lwu s5, 0(v1)
|
|
bc = c->sgpr64(s5) == 0; // beq s5, r0, L56
|
|
c->mov64(v1, s7); // or v1, s7, r0
|
|
if (bc) {goto block_33;} // branch non-likely
|
|
|
|
c->addiu(v1, r0, 0); // addiu v1, r0, 0
|
|
c->addiu(gp, r0, 0); // addiu gp, r0, 0
|
|
c->addiu(v1, r0, 0); // addiu v1, r0, 0
|
|
c->load_symbol2(v1, cache.gsf_buffer); // lw v1, *gsf-buffer*(s7)
|
|
c->load_symbol2(t9, cache.flush_cache); // lw t9, flush-cache(s7)
|
|
c->addiu(a0, r0, 0); // addiu a0, r0, 0
|
|
call_addr = c->gprs[t9].du32[0]; // function call:
|
|
c->sll(v0, ra, 0); // sll v0, ra, 0
|
|
c->jalr(call_addr); // jalr ra, t9
|
|
c->addiu(v1, r0, 848); // addiu v1, r0, 848
|
|
get_fake_spad_addr2(a0, cache.fake_scratchpad_data, 0, c);// lui a0, 28672
|
|
c->daddu(a1, v1, a0); // daddu a1, v1, a0
|
|
c->load_symbol2(v1, cache.blerc_globals); // lw v1, *blerc-globals*(s7)
|
|
c->daddu(v1, r0, v1); // daddu v1, r0, v1
|
|
// nop // sll r0, r0, 0
|
|
c->lui(a0, 4096); // lui a0, 4096
|
|
// nop // sll r0, r0, 0
|
|
c->ori(a0, a0, 54272); // ori a0, a0, 54272
|
|
c->andi(a1, a1, 16383); // andi a1, a1, 16383
|
|
|
|
/*
|
|
block_2:
|
|
c->lw(a2, 0, a0); // lw a2, 0(a0)
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
c->andi(a2, a2, 256); // andi a2, a2, 256
|
|
// nop // sll r0, r0, 0
|
|
bc = c->sgpr64(a2) != 0; // bne a2, r0, L38
|
|
c->lw(a2, 0, v1); // lw a2, 0(v1)
|
|
if (bc) {goto block_2;} // branch non-likely
|
|
*/
|
|
c->lw(a2, 0, v1);
|
|
|
|
bc = c->sgpr64(a2) == 0; // beq a2, r0, L39
|
|
// c->sw(a1, 128, a0); // sw a1, 128(a0)
|
|
sadr = c->sgpr64(a1);
|
|
if (bc) {goto block_5;} // branch non-likely
|
|
|
|
c->addiu(v1, r0, 324); // addiu v1, r0, 324
|
|
// c->sw(a2, 48, a0); // sw a2, 48(a0)
|
|
tadr = c->sgpr64(a2);
|
|
// c->sw(r0, 32, a0); // sw r0, 32(a0)
|
|
// Unknown instr: sync.l
|
|
// c->sw(v1, 0, a0); // sw v1, 0(a0)
|
|
spad_to_dma_blerc_chain(cache.fake_scratchpad_data, sadr, tadr);
|
|
// Unknown instr: sync.l
|
|
|
|
block_5:
|
|
c->gprs[v1].du64[0] = 0; // or v1, r0, r0
|
|
//beq r0, r0, L55 // beq r0, r0, L55
|
|
// nop // sll r0, r0, 0
|
|
goto block_31; // branch always
|
|
|
|
|
|
block_6:
|
|
bc = c->sgpr64(gp) != 0; // bne gp, r0, L41
|
|
// nop // sll r0, r0, 0
|
|
if (bc) {goto block_8;} // branch non-likely
|
|
|
|
get_fake_spad_addr2(v1, cache.fake_scratchpad_data, 0, c);// lui v1, 28672
|
|
c->daddu(a0, r0, v1); // daddu a0, r0, v1
|
|
//beq r0, r0, L42 // beq r0, r0, L42
|
|
// nop // sll r0, r0, 0
|
|
goto block_9; // branch always
|
|
|
|
|
|
block_8:
|
|
c->addiu(v1, r0, 8192); // addiu v1, r0, 8192
|
|
get_fake_spad_addr2(a0, cache.fake_scratchpad_data, 0, c);// lui a0, 28672
|
|
c->daddu(a0, v1, a0); // daddu a0, v1, a0
|
|
|
|
block_9:
|
|
bc = c->sgpr64(gp) != 0; // bne gp, r0, L43
|
|
// nop // sll r0, r0, 0
|
|
if (bc) {goto block_11;} // branch non-likely
|
|
|
|
c->addiu(v1, r0, 8192); // addiu v1, r0, 8192
|
|
get_fake_spad_addr2(a1, cache.fake_scratchpad_data, 0, c);// lui a1, 28672
|
|
c->daddu(a1, v1, a1); // daddu a1, v1, a1
|
|
//beq r0, r0, L44 // beq r0, r0, L44
|
|
// nop // sll r0, r0, 0
|
|
goto block_12; // branch always
|
|
|
|
|
|
block_11:
|
|
get_fake_spad_addr2(v1, cache.fake_scratchpad_data, 0, c);// lui v1, 28672
|
|
c->daddu(a1, r0, v1); // daddu a1, r0, v1
|
|
|
|
block_12:
|
|
c->daddiu(v1, a0, 848); // daddiu v1, a0, 848
|
|
c->daddu(a2, r0, a0); // daddu a2, r0, a0
|
|
c->daddiu(a3, a1, 848); // daddiu a3, a1, 848
|
|
c->daddiu(a1, v1, 12); // daddiu a1, v1, 12
|
|
// nop // sll r0, r0, 0
|
|
c->lui(a2, 4096); // lui a2, 4096
|
|
// nop // sll r0, r0, 0
|
|
c->ori(a2, a2, 54272); // ori a2, a2, 54272
|
|
c->andi(a3, a3, 16383); // andi a3, a3, 16383
|
|
|
|
/*
|
|
block_13:
|
|
c->lw(t0, 0, a2); // lw t0, 0(a2)
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
c->andi(t0, t0, 256); // andi t0, t0, 256
|
|
// nop // sll r0, r0, 0
|
|
bc = c->sgpr64(t0) != 0; // bne t0, r0, L45
|
|
c->lw(t0, 0, a1); // lw t0, 0(a1)
|
|
if (bc) {goto block_13;} // branch non-likely
|
|
*/
|
|
|
|
c->lw(t0, 0, a1);
|
|
|
|
bc = c->sgpr64(t0) == 0; // beq t0, r0, L46
|
|
// c->sw(a3, 128, a2); // sw a3, 128(a2)
|
|
sadr = c->sgpr64(a3);
|
|
if (bc) {goto block_16;} // branch non-likely
|
|
|
|
c->addiu(a1, r0, 324); // addiu a1, r0, 324
|
|
// c->sw(t0, 48, a2); // sw t0, 48(a2)
|
|
tadr = c->sgpr64(t0);
|
|
// c->sw(r0, 32, a2); // sw r0, 32(a2)
|
|
// Unknown instr: sync.l
|
|
// c->sw(a1, 0, a2); // sw a1, 0(a2)
|
|
// Unknown instr: sync.l
|
|
// tadr here is bogus, it's reading something uploaded by the other transfer.
|
|
spad_to_dma_blerc_chain(cache.fake_scratchpad_data, sadr, tadr);
|
|
|
|
|
|
block_16:
|
|
c->gprs[a1].du64[0] = 0; // or a1, r0, r0
|
|
c->mov64(a2, a0); // or a2, a0, r0
|
|
c->load_symbol2(a3, cache.gsf_buffer); // lw a3, *gsf-buffer*(s7)
|
|
|
|
// blerc_c(g_ee_main_mem + c->sgpr64(a2), g_ee_main_mem + c->sgpr64(a3));
|
|
|
|
c->daddiu(t2, a2, 880); // daddiu t2, a2, 880
|
|
c->lb(t1, 0, t2); // lb t1, 0(t2)
|
|
// nop // sll r0, r0, 0
|
|
c->mov64(t0, a2); // or t0, a2, r0
|
|
c->lw(a1, 868, a2); // lw a1, 868(a2)
|
|
c->daddiu(t3, t1, 1); // daddiu t3, t1, 1
|
|
c->mov64(t1, a3); // or t1, a3, r0
|
|
c->sll(t8, t3, 4); // sll t8, t3, 4
|
|
c->sll(t3, a1, 4); // sll t3, a1, 4
|
|
c->daddu(t9, t3, a3); // daddu t9, t3, a3
|
|
c->daddu(t3, t2, t8); // daddu t3, t2, t8
|
|
bc = c->sgpr64(a1) == 0; // beq a1, r0, L49
|
|
c->daddiu(ra, t2, 16); // daddiu ra, t2, 16
|
|
if (bc) {goto block_21;} // branch non-likely
|
|
|
|
c->lh(t5, 12, t3); // lh t5, 12(t3)
|
|
c->daddu(t2, t3, t8); // daddu t2, t3, t8
|
|
//beq r0, r0, L48 // beq r0, r0, L48
|
|
// nop // sll r0, r0, 0
|
|
goto block_19; // branch always
|
|
|
|
|
|
block_18:
|
|
hit18 = true;
|
|
c->lh(t5, 12, t2); // lh t5, 12(t2)
|
|
c->daddu(t2, t2, t8); // daddu t2, t2, t8
|
|
c->sq(t6, 0, t1); // sq t6, 0(t1)
|
|
c->daddiu(t1, t1, 16); // daddiu t1, t1, 16
|
|
|
|
block_19:
|
|
hit19 = true;
|
|
c->pcpyh(t5, t5); // pcpyh t5, t5
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
bc = c->sgpr64(t1) != c->sgpr64(t9); // bne t1, t9, L47
|
|
c->pcpyld(t6, t5, t5); // pcpyld t6, t5, t5
|
|
if (bc) {goto block_18;} // branch non-likely
|
|
|
|
c->dsubu(t3, t2, t8); // dsubu t3, t2, t8
|
|
// nop // sll r0, r0, 0
|
|
block_21:
|
|
|
|
c->addiu(t1, r0, 255); // addiu t1, r0, 255
|
|
c->addiu(t2, r0, 8192); // addiu t2, r0, 8192
|
|
c->lb(s5, 0, t3); // lb s5, 0(t3)
|
|
c->daddiu(s4, t3, 16); // daddiu s4, t3, 16
|
|
c->pcpyh(t1, t1); // pcpyh t1, t1
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pcpyld(t1, t1, t1); // pcpyld t1, t1, t1
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pcpyh(t2, t2); // pcpyh t2, t2
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pcpyld(t2, t2, t2); // pcpyld t2, t2, t2
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->mov128_gpr_gpr(t3, t1); // por t3, t1, r0
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->mov128_gpr_gpr(t4, r0); // por t4, r0, r0
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
|
|
block_22:
|
|
c->ld(t6, 0, ra); // ld t6, 0(ra)
|
|
c->daddu(s2, ra, t8); // daddu s2, ra, t8
|
|
c->daddiu(ra, ra, 8); // daddiu ra, ra, 8
|
|
c->mov64(s3, a3); // or s3, a3, r0
|
|
c->pextlb(t6, r0, t6); // pextlb t6, r0, t6
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pmulth(t7, t6, t2); // pmulth t7, t6, t2
|
|
c->ld(t5, 0, s2); // ld t5, 0(s2)
|
|
c->daddiu(s5, s5, -1); // daddiu s5, s5, -1
|
|
// nop // sll r0, r0, 0
|
|
//beq r0, r0, L52 // beq r0, r0, L52
|
|
c->daddu(s2, s2, t8); // daddu s2, s2, t8
|
|
goto block_24; // branch always
|
|
|
|
|
|
block_23:
|
|
c->pmaddh(t7, t5, t6); // pmaddh t7, t5, t6
|
|
c->ld(t5, 0, s2); // ld t5, 0(s2)
|
|
c->daddu(s2, s2, t8); // daddu s2, s2, t8
|
|
c->daddiu(s3, s3, 16); // daddiu s3, s3, 16
|
|
|
|
block_24:
|
|
c->lq(t6, 0, s3); // lq t6, 0(s3)
|
|
c->pextlb(t5, t5, r0); // pextlb t5, t5, r0
|
|
bc = c->sgpr64(s3) != c->sgpr64(t9); // bne s3, t9, L51
|
|
c->psrah(t5, t5, 8); // psrah t5, t5, 8
|
|
if (bc) {goto block_23;} // branch non-likely
|
|
|
|
// Unknown instr: pmfhl.uw t5
|
|
c->gprs[t5].du32[0] = c->lo.du32[1];
|
|
c->gprs[t5].du32[1] = c->hi.du32[1];
|
|
c->gprs[t5].du32[2] = c->lo.du32[3];
|
|
c->gprs[t5].du32[3] = c->hi.du32[3];
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->psraw(t7, t7, 13); // psraw t7, t7, 13
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->psraw(t5, t5, 13); // psraw t5, t5, 13
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pinteh(t5, t5, t7); // pinteh t5, t5, t7
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pminh(t3, t3, t5); // pminh t3, t3, t5
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pmaxh(t4, t4, t5); // pmaxh t4, t4, t5
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pminh(t5, t5, t1); // pminh t5, t5, t1
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pmaxh(t5, t5, r0); // pmaxh t5, t5, r0
|
|
c->lq(t7, 0, s4); // lq t7, 0(s4)
|
|
c->ppacb(t5, r0, t5); // ppacb t5, r0, t5
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->ppach(t7, r0, t7); // ppach t7, r0, t7
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
c->pextlh(t5, t5, t7); // pextlh t5, t5, t7
|
|
c->mfc1(r0, f31); // mfc1 r0, f31
|
|
// store modified vertex
|
|
c->sq(t5, 0, t0); // sq t5, 0(t0)
|
|
|
|
c->daddiu(t0, t0, 16); // daddiu t0, t0, 16
|
|
bc = c->sgpr64(s5) != 0; // bne s5, r0, L50
|
|
c->daddiu(s4, s4, 16); // daddiu s4, s4, 16
|
|
if (bc) {goto block_22;} // branch non-likely
|
|
// end of blerc_c stuff
|
|
|
|
c->load_symbol2(a3, cache.stats_blerc); // lw a3, *stats-blerc*(s7)
|
|
bc = c->sgpr64(a3) == c->sgpr64(s7); // beq a3, s7, L53
|
|
c->load_symbol2(a3, cache.blerc_globals); // lw a3, *blerc-globals*(s7)
|
|
if (bc) {goto block_28;} // branch non-likely
|
|
|
|
c->lw(t2, 12, a3); // lw t2, 12(a3)
|
|
c->lw(t1, 16, a3); // lw t1, 16(a3)
|
|
c->lw(t0, 20, a3); // lw t0, 20(a3)
|
|
c->lw(a2, 864, a2); // lw a2, 864(a2)
|
|
c->multu3(a1, a1, a2); // multu3 a1, a1, a2
|
|
c->daddiu(t2, t2, 1); // daddiu t2, t2, 1
|
|
c->daddu(a2, t1, a2); // daddu a2, t1, a2
|
|
c->daddu(a1, t0, a1); // daddu a1, t0, a1
|
|
c->sw(t2, 12, a3); // sw t2, 12(a3)
|
|
c->sw(a2, 16, a3); // sw a2, 16(a3)
|
|
c->sw(a1, 20, a3); // sw a1, 20(a3)
|
|
c->pcpyud(a1, t3, r0); // pcpyud a1, t3, r0
|
|
c->pminh(t3, t3, a1); // pminh t3, t3, a1
|
|
c->dsrl32(a1, t3, 0); // dsrl32 a1, t3, 0
|
|
c->pminh(t3, t3, a1); // pminh t3, t3, a1
|
|
c->dsrl(t3, t3, 16); // dsrl t3, t3, 16
|
|
c->lh(a1, 8, a3); // lh a1, 8(a3)
|
|
c->pminh(t3, t3, a1); // pminh t3, t3, a1
|
|
c->sh(t3, 8, a3); // sh t3, 8(a3)
|
|
c->pcpyud(a1, t4, r0); // pcpyud a1, t4, r0
|
|
c->pmaxh(t4, t4, a1); // pmaxh t4, t4, a1
|
|
c->dsrl32(a1, t4, 0); // dsrl32 a1, t4, 0
|
|
c->pmaxh(t4, t4, a1); // pmaxh t4, t4, a1
|
|
c->dsrl(t4, t4, 16); // dsrl t4, t4, 16
|
|
c->lh(a1, 10, a3); // lh a1, 10(a3)
|
|
c->pmaxh(t4, t4, a1); // pmaxh t4, t4, a1
|
|
c->sh(t4, 10, a3); // sh t4, 10(a3)
|
|
|
|
block_28:
|
|
c->gprs[a1].du64[0] = 0; // or a1, r0, r0
|
|
c->lwu(a1, 872, a0); // lwu a1, 872(a0)
|
|
c->mov64(a3, a0); // or a3, a0, r0
|
|
c->lwu(a0, 876, a0); // lwu a0, 876(a0)
|
|
c->lui(a2, 4096); // lui a2, 4096
|
|
// nop // sll r0, r0, 0
|
|
c->ori(a2, a2, 53248); // ori a2, a2, 53248
|
|
c->andi(a3, a3, 16383); // andi a3, a3, 16383
|
|
|
|
/*
|
|
block_29:
|
|
c->lw(t0, 0, a2); // lw t0, 0(a2)
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
c->andi(t0, t0, 256); // andi t0, t0, 256
|
|
// nop // sll r0, r0, 0
|
|
bc = c->sgpr64(t0) != 0; // bne t0, r0, L54
|
|
// nop // sll r0, r0, 0
|
|
if (bc) {goto block_29;} // branch non-likely
|
|
*/
|
|
|
|
|
|
// c->sw(a3, 128, a2); // sw a3, 128(a2)
|
|
sadr = c->sgpr64(a3);
|
|
c->addiu(a3, r0, 256); // addiu a3, r0, 256
|
|
// c->sw(a1, 16, a2); // sw a1, 16(a2)
|
|
madr = c->sgpr64(a1);
|
|
// nop // sll r0, r0, 0
|
|
// c->sw(a0, 32, a2); // sw a0, 32(a2)
|
|
qwc = c->sgpr64(a0);
|
|
// Unknown instr: sync.l
|
|
// c->sw(a3, 0, a2); // sw a3, 0(a2)
|
|
// fmt::print("blerc download 0x{:x} <- 0x{:x} ({} qwc)\n", madr, sadr, qwc);
|
|
{
|
|
spad_from_dma_no_sadr_off(cache.fake_scratchpad_data, madr, sadr, qwc);
|
|
}
|
|
// Unknown instr: sync.l
|
|
c->gprs[a0].du64[0] = 0; // or a0, r0, r0
|
|
c->addiu(a0, r0, 1); // addiu a0, r0, 1
|
|
c->dsubu(gp, a0, gp); // dsubu gp, a0, gp
|
|
c->lwu(s5, 12, v1); // lwu s5, 12(v1)
|
|
c->mov64(v1, s5); // or v1, s5, r0
|
|
|
|
block_31:
|
|
bc = c->sgpr64(s5) != 0; // bne s5, r0, L40
|
|
// nop // sll r0, r0, 0
|
|
if (bc) {goto block_6;} // branch non-likely
|
|
|
|
c->mov64(v1, s7); // or v1, s7, r0
|
|
|
|
block_33:
|
|
c->gprs[v0].du64[0] = 0; // or v0, r0, r0
|
|
c->ld(ra, 0, sp); // ld ra, 0(sp)
|
|
c->lq(gp, 80, sp); // lq gp, 80(sp)
|
|
c->lq(s5, 64, sp); // lq s5, 64(sp)
|
|
c->lq(s4, 48, sp); // lq s4, 48(sp)
|
|
c->lq(s3, 32, sp); // lq s3, 32(sp)
|
|
c->lq(s2, 16, sp); // lq s2, 16(sp)
|
|
//jr ra // jr ra
|
|
c->daddiu(sp, sp, 96); // daddiu sp, sp, 96
|
|
goto end_of_function; // return
|
|
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
end_of_function:
|
|
return c->gprs[v0].du64[0];
|
|
}
|
|
|
|
void link() {
|
|
cache.blerc_globals = intern_from_c("*blerc-globals*").c();
|
|
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
|
cache.gsf_buffer = intern_from_c("*gsf-buffer*").c();
|
|
cache.stats_blerc = intern_from_c("*stats-blerc*").c();
|
|
cache.flush_cache = intern_from_c("flush-cache").c();
|
|
gLinkedFunctionTable.reg("blerc-execute", execute, 256);
|
|
}
|
|
|
|
} // namespace blerc_execute
|
|
} // namespace Mips2C
|
|
|
|
//--------------------------MIPS2C---------------------
|
|
// clang-format off
|
|
#include "game/mips2c/mips2c_private.h"
|
|
#include "game/kernel/jak2/kscheme.h"
|
|
using ::jak2::intern_from_c;
|
|
namespace Mips2C::jak2 {
|
|
namespace setup_blerc_chains_for_one_fragment {
|
|
struct Cache {
|
|
void* blerc_globals; // *blerc-globals*
|
|
void* fake_scratchpad_data; // *fake-scratchpad-data*
|
|
} cache;
|
|
|
|
u64 execute(void* ctxt) {
|
|
auto* c = (ExecutionContext*)ctxt;
|
|
bool bc = false;
|
|
c->daddiu(sp, sp, -128); // daddiu sp, sp, -128
|
|
c->sd(ra, 0, sp); // sd ra, 0(sp)
|
|
c->sq(s0, 16, sp); // sq s0, 16(sp)
|
|
c->sq(s1, 32, sp); // sq s1, 32(sp)
|
|
c->sq(s2, 48, sp); // sq s2, 48(sp)
|
|
c->sq(s3, 64, sp); // sq s3, 64(sp)
|
|
c->sq(s4, 80, sp); // sq s4, 80(sp)
|
|
c->sq(s5, 96, sp); // sq s5, 96(sp)
|
|
c->sq(gp, 112, sp); // sq gp, 112(sp)
|
|
c->lb(v1, 0, t0); // lb v1, 0(t0)
|
|
c->addiu(t2, r0, 0); // addiu t2, r0, 0
|
|
c->mov128_gpr_gpr(t7, r0); // por t7, r0, r0
|
|
c->load_symbol2(t3, cache.blerc_globals); // lw t3, *blerc-globals*(s7)
|
|
c->lw(t3, 4, t3); // lw t3, 4(t3)
|
|
c->mov64(t4, v1); // or t4, v1, r0
|
|
|
|
block_1:
|
|
c->lui(t7, 4096); // lui t7, 4096
|
|
// nop // sll r0, r0, 0
|
|
c->daddiu(t7, t7, 1); // daddiu t7, t7, 1
|
|
// nop // sll r0, r0, 0
|
|
bc = c->sgpr64(t3) == 0; // beq t3, r0, L11
|
|
c->sq(t7, 0, a2); // sq t7, 0(a2)
|
|
if (bc) {goto block_3;} // branch non-likely
|
|
|
|
c->sw(a2, 12, t3); // sw a2, 12(t3)
|
|
// nop // sll r0, r0, 0
|
|
|
|
block_3:
|
|
c->mov64(t3, a2); // or t3, a2, r0
|
|
c->daddu(t6, t4, t4); // daddu t6, t4, t4
|
|
c->daddu(t5, v1, v1); // daddu t5, v1, v1
|
|
c->daddu(t6, t6, t4); // daddu t6, t6, t4
|
|
c->daddu(t7, t5, v1); // daddu t7, t5, v1
|
|
c->daddu(t5, t6, t6); // daddu t5, t6, t6
|
|
c->daddu(t6, t7, t7); // daddu t6, t7, t7
|
|
c->daddu(t7, t5, t5); // daddu t7, t5, t5
|
|
c->daddiu(t6, t6, 15); // daddiu t6, t6, 15
|
|
c->daddiu(t5, t5, 15); // daddiu t5, t5, 15
|
|
c->andi(t6, t6, 65520); // andi t6, t6, 65520
|
|
c->dsrl(t5, t5, 4); // dsrl t5, t5, 4
|
|
c->daddu(t8, t2, t2); // daddu t8, t2, t2
|
|
c->daddiu(t7, t7, 15); // daddiu t7, t7, 15
|
|
c->daddu(t9, t8, t2); // daddu t9, t8, t2
|
|
c->dsrl(t8, t7, 4); // dsrl t8, t7, 4
|
|
c->daddu(ra, t9, t9); // daddu ra, t9, t9
|
|
c->addiu(t9, r0, 0); // addiu t9, r0, 0
|
|
c->daddu(t7, ra, ra); // daddu t7, ra, ra
|
|
c->daddiu(s3, a2, 32); // daddiu s3, a2, 32
|
|
c->daddu(s2, ra, a3); // daddu s2, ra, a3
|
|
c->daddu(ra, t7, t1); // daddu ra, t7, t1
|
|
c->lui(t7, 12288); // lui t7, 12288
|
|
c->daddiu(gp, a0, -1); // daddiu gp, a0, -1
|
|
c->daddu(t7, t7, t5); // daddu t7, t7, t5
|
|
c->mov64(s5, a1); // or s5, a1, r0
|
|
c->sq(t7, 0, s3); // sq t7, 0(s3)
|
|
c->daddiu(s4, t0, 2); // daddiu s4, t0, 2
|
|
c->sw(s2, 4, s3); // sw s2, 4(s3)
|
|
c->daddu(s2, s2, t6); // daddu s2, s2, t6
|
|
c->daddiu(s3, s3, 16); // daddiu s3, s3, 16
|
|
// nop // sll r0, r0, 0
|
|
|
|
block_4:
|
|
c->lb(s1, 0, s4); // lb s1, 0(s4)
|
|
c->daddiu(s4, s4, 1); // daddiu s4, s4, 1
|
|
c->lh(s0, 0, s5); // lh s0, 0(s5)
|
|
c->daddiu(s5, s5, 2); // daddiu s5, s5, 2
|
|
bc = c->sgpr64(s1) == 0; // beq s1, r0, L13
|
|
c->sq(t7, 0, s3); // sq t7, 0(s3)
|
|
if (bc) {goto block_7;} // branch non-likely
|
|
|
|
c->sw(s2, 4, s3); // sw s2, 4(s3)
|
|
c->daddu(s2, s2, t6); // daddu s2, s2, t6
|
|
bc = c->sgpr64(s0) == 0; // beq s0, r0, L13
|
|
c->sw(s0, 12, s3); // sw s0, 12(s3)
|
|
if (bc) {goto block_7;} // branch non-likely
|
|
|
|
c->daddiu(s3, s3, 16); // daddiu s3, s3, 16
|
|
c->daddiu(t9, t9, 1); // daddiu t9, t9, 1
|
|
|
|
block_7:
|
|
bc = c->sgpr64(gp) != 0; // bne gp, r0, L12
|
|
c->daddiu(gp, gp, -1); // daddiu gp, gp, -1
|
|
if (bc) {goto block_4;} // branch non-likely
|
|
|
|
c->sq(t7, 0, s3); // sq t7, 0(s3)
|
|
c->mov128_gpr_gpr(t6, r0); // por t6, r0, r0
|
|
c->sw(ra, 4, s3); // sw ra, 4(s3)
|
|
get_fake_spad_addr2(t6, cache.fake_scratchpad_data, 0, c);// lui t6, 28672
|
|
c->sb(t8, 0, s3); // sb t8, 0(s3)
|
|
// nop // sll r0, r0, 0
|
|
c->sq(t6, 16, s3); // sq t6, 16(s3)
|
|
c->daddiu(t6, s3, 32); // daddiu t6, s3, 32
|
|
c->sw(t9, 20, a2); // sw t9, 20(a2)
|
|
// nop // sll r0, r0, 0
|
|
c->sw(t4, 16, a2); // sw t4, 16(a2)
|
|
// nop // sll r0, r0, 0
|
|
c->sw(ra, 24, a2); // sw ra, 24(a2)
|
|
// nop // sll r0, r0, 0
|
|
c->sw(t8, 28, a2); // sw t8, 28(a2)
|
|
// nop // sll r0, r0, 0
|
|
bc = c->sgpr64(t4) != c->sgpr64(v1); // bne t4, v1, L14
|
|
c->daddiu(t5, t5, 1); // daddiu t5, t5, 1
|
|
if (bc) {goto block_11;} // branch non-likely
|
|
|
|
c->daddiu(t7, t9, 3); // daddiu t7, t9, 3
|
|
c->multu3(t5, t5, t7); // multu3 t5, t5, t7
|
|
c->daddiu(t5, t5, -457); // daddiu t5, t5, -457
|
|
// nop // sll r0, r0, 0
|
|
bc = ((s64)c->sgpr64(t5)) <= 0; // blez t5, L14
|
|
// nop // sll r0, r0, 0
|
|
if (bc) {goto block_11;} // branch non-likely
|
|
|
|
//beq r0, r0, L10 // beq r0, r0, L10
|
|
c->addiu(t4, r0, 24); // addiu t4, r0, 24
|
|
goto block_1; // branch always
|
|
|
|
|
|
block_11:
|
|
c->mov64(a2, t6); // or a2, t6, r0
|
|
c->daddu(t2, t2, t4); // daddu t2, t2, t4
|
|
bc = c->sgpr64(t2) == c->sgpr64(v1); // beq t2, v1, L15
|
|
c->daddu(t5, t2, t4); // daddu t5, t2, t4
|
|
if (bc) {goto block_14;} // branch non-likely
|
|
|
|
c->dsubu(t5, t5, v1); // dsubu t5, t5, v1
|
|
// nop // sll r0, r0, 0
|
|
bc = ((s64)c->sgpr64(t5)) <= 0; // blez t5, L10
|
|
// nop // sll r0, r0, 0
|
|
if (bc) {goto block_1;} // branch non-likely
|
|
|
|
//beq r0, r0, L10 // beq r0, r0, L10
|
|
c->dsubu(t4, v1, t2); // dsubu t4, v1, t2
|
|
goto block_1; // branch always
|
|
|
|
|
|
block_14:
|
|
c->load_symbol2(v1, cache.blerc_globals); // lw v1, *blerc-globals*(s7)
|
|
c->sw(t3, 4, v1); // sw t3, 4(v1)
|
|
c->mov64(v0, a2); // or v0, a2, r0
|
|
c->ld(ra, 0, sp); // ld ra, 0(sp)
|
|
c->lq(gp, 112, sp); // lq gp, 112(sp)
|
|
c->lq(s5, 96, sp); // lq s5, 96(sp)
|
|
c->lq(s4, 80, sp); // lq s4, 80(sp)
|
|
c->lq(s3, 64, sp); // lq s3, 64(sp)
|
|
c->lq(s2, 48, sp); // lq s2, 48(sp)
|
|
c->lq(s1, 32, sp); // lq s1, 32(sp)
|
|
c->lq(s0, 16, sp); // lq s0, 16(sp)
|
|
//jr ra // jr ra
|
|
c->daddiu(sp, sp, 128); // daddiu sp, sp, 128
|
|
goto end_of_function; // return
|
|
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
// nop // sll r0, r0, 0
|
|
end_of_function:
|
|
return c->gprs[v0].du64[0];
|
|
}
|
|
|
|
void link() {
|
|
cache.blerc_globals = intern_from_c("*blerc-globals*").c();
|
|
cache.fake_scratchpad_data = intern_from_c("*fake-scratchpad-data*").c();
|
|
gLinkedFunctionTable.reg("setup-blerc-chains-for-one-fragment", execute, 256);
|
|
}
|
|
|
|
} // namespace setup_blerc_chains_for_one_fragment
|
|
} // namespace Mips2C
|