diff --git a/mips/mips_emit.h b/mips/mips_emit.h index 37b2a47..e585269 100644 --- a/mips/mips_emit.h +++ b/mips/mips_emit.h @@ -2016,6 +2016,60 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address) mips_emit_jr(mips_reg_ra); \ mips_emit_nop(); +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + + /* + 400230: 00042e00 sll a1,a0,0x18 + 400234: 00041602 srl v0,a0,0x18 + 400238: 00041a02 srl v1,a0,0x8 + 40023c: 00451025 or v0,v0,a1 + 400240: 3063ff00 andi v1,v1,0xff00 + 400244: 00431025 or v0,v0,v1 + 400248: 00042200 sll a0,a0,0x8 + 40024c: 3c0300ff lui v1,0xff + 400250: 00832024 and a0,a0,v1 + 400258: 00441025 or v0,v0,a0 + */ +#define emit_eswap32(r) \ + mips_emit_sll(reg_temp, r, 24); \ + mips_emit_srl(mips_reg_k0, r, 24); \ + mips_emit_srl(mips_reg_k1, r, 8); \ + mips_emit_or(mips_reg_k0, mips_reg_k0, reg_temp); \ + mips_emit_andi(mips_reg_k1, mips_reg_k1, 0xff00); \ + mips_emit_or(mips_reg_k0, mips_reg_k0, mips_reg_k1); \ + mips_emit_sll(r, r, 8); \ + mips_emit_lui(mips_reg_k1, 0xff); \ + mips_emit_and(r, r, mips_reg_k1); \ + mips_emit_or(r, mips_reg_k0, r) + + /* + this first part's signext stuff... maybe not always necessary here? + 400218: 00021400 sll v0,v0,0x10 + 40021c: 00021403 sra v0,v0,0x10 + 400220: 3042ffff andi v0,v0,0xffff + + 400224: 00021a00 sll v1,v0,0x8 + 400228: 00021202 srl v0,v0,0x8 + 40022c: 00621025 or v0,v1,v0 + 400230: 3042ffff andi v0,v0,0xffff + */ +#define emit_eswap16(r, sext) \ + mips_emit_sll(reg_temp, r, 8); \ + mips_emit_srl(r, r, 8); \ + mips_emit_or(r, reg_temp, r); \ + mips_emit_andi(r, r, 0xffff); \ + if (sext) { \ + mips_emit_sll(r, r, 16); \ + mips_emit_sra(r, r, 16); \ + } + +#else + +#define emit_eswap32(r) +#define emit_eswap16(r, sext) + +#endif + // Pointer table to stubs, indexed by type and region extern u32 tmemld[11][16]; extern u32 tmemst[ 4][16]; @@ -2050,30 +2104,7 @@ static void emit_mem_access_loadop( switch (size) { case 2: mips_emit_lw(reg_rv, reg_rv, (base_addr & 0xffff)); - /* - 400230: 00042e00 sll a1,a0,0x18 - 400234: 00041602 srl v0,a0,0x18 - 400238: 00041a02 srl v1,a0,0x8 - 40023c: 00451025 or v0,v0,a1 - 400240: 3063ff00 andi v1,v1,0xff00 - 400244: 00431025 or v0,v0,v1 - 400248: 00042200 sll a0,a0,0x8 - 40024c: 3c0300ff lui v1,0xff - 400250: 00832024 and a0,a0,v1 - 400258: 00441025 or v0,v0,a0 - */ -#ifdef NINTENDO64 // byte order swap - mips_emit_sll(reg_temp, reg_rv, 24); - mips_emit_srl(mips_reg_k1, reg_rv, 24); - mips_emit_srl(mips_reg_k2, reg_rv, 8); - mips_emit_or(mips_reg_k1, mips_reg_k1, reg_temp); - mips_emit_andi(mips_reg_k2, mips_reg_k2, 0xff00); - mips_emit_or(mips_reg_k1, mips_reg_k1, mips_reg_k2); - mips_emit_sll(reg_rv, reg_rv, 8); - mips_emit_lui(mips_reg_k2, 0xff); - mips_emit_and(reg_rv, reg_rv, mips_reg_k2); - mips_emit_or(reg_rv, mips_reg_k1, reg_rv); -#endif + emit_eswap32(reg_rv); break; case 1: if (signext) { @@ -2086,27 +2117,7 @@ static void emit_mem_access_loadop( } else { mips_emit_lhu(reg_rv, reg_rv, (base_addr & 0xffff)); } - /* - this first part's signext stuff... maybe not always necessary here? - 400218: 00021400 sll v0,v0,0x10 - 40021c: 00021403 sra v0,v0,0x10 - 400220: 3042ffff andi v0,v0,0xffff - - 400224: 00021a00 sll v1,v0,0x8 - 400228: 00021202 srl v0,v0,0x8 - 40022c: 00621025 or v0,v1,v0 - 400230: 3042ffff andi v0,v0,0xffff - */ -#ifdef NINTENDO64 - mips_emit_sll(reg_temp, reg_rv, 8); - mips_emit_srl(reg_rv, reg_rv, 8); - mips_emit_or(reg_rv, reg_temp, reg_rv); - mips_emit_andi(reg_rv, reg_rv, 0xffff); - if (signext) { - mips_emit_sll(reg_rv, reg_rv, 16); - mips_emit_sra(reg_rv, reg_rv, 16); - } -#endif + emit_eswap16(reg_rv, signext); break; default: if (signext) { @@ -2381,8 +2392,10 @@ static void emit_pmemst_stub( // Store the data (delay slot from the SMC branch) if (realsize == 2) { + emit_eswap32(reg_a1); mips_emit_sw(reg_a1, reg_rv, base_addr); } else if (realsize == 1) { + emit_eswap16(reg_a1, false); mips_emit_sh(reg_a1, reg_rv, base_addr); } else { mips_emit_sb(reg_a1, reg_rv, base_addr);