MCPcopy Create free account
hub / github.com/N64Recomp/N64Recomp / process_store_op

Method process_store_op

LiveRecomp/live_generator.cpp:1169–1304  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1167}
1168
1169void N64Recomp::LiveGenerator::process_store_op(const StoreOp& op, const InstructionContext& ctx) const {
1170 sljit_sw src;
1171 sljit_sw srcw;
1172 sljit_sw imm = (sljit_sw)(int16_t)ctx.imm16;
1173
1174 get_operand_values(op.value_input, ctx, src, srcw, compiler, Registers::arithmetic_temp2);
1175
1176 // Only LO16 relocs are valid on stores.
1177 if (ctx.reloc_type != RelocType::R_MIPS_NONE && ctx.reloc_type != RelocType::R_MIPS_LO16) {
1178 assert(false);
1179 errored = true;
1180 return;
1181 }
1182
1183 if (ctx.reloc_type == RelocType::R_MIPS_LO16) {
1184 // Load the relocated address into temp1.
1185 load_relocated_address(ctx, Registers::arithmetic_temp1);
1186 // Extract the LO16 value from the full address (sign extended lower 16 bits).
1187 sljit_emit_op1(compiler, SLJIT_MOV_S16, Registers::arithmetic_temp1, 0, Registers::arithmetic_temp1, 0);
1188 // Add the base register (rs) to the LO16 immediate.
1189 sljit_emit_op2(compiler, SLJIT_ADD, Registers::arithmetic_temp1, 0, Registers::arithmetic_temp1, 0, SLJIT_MEM1(Registers::ctx), get_gpr_context_offset(ctx.rs));
1190 }
1191 else {
1192 // TODO 0 immediate optimization.
1193
1194 // Add the base register (rs) and the immediate to get the address and store it in the arithemtic temp.
1195 sljit_emit_op2(compiler, SLJIT_ADD, Registers::arithmetic_temp1, 0, SLJIT_MEM1(Registers::ctx), get_gpr_context_offset(ctx.rs), SLJIT_IMM, imm);
1196 }
1197
1198 auto do_unaligned_store_op = [src, srcw, this](bool left, bool doubleword) {
1199 // Determine the shift direction to use for calculating the mask and shifting the loaded value.
1200 sljit_sw shift_op = left ? SLJIT_LSHR : SLJIT_SHL;
1201 // Determine the operation's word size.
1202 sljit_sw word_size = doubleword ? 8 : 4;
1203
1204 // Mask the address with the alignment mask to get the misalignment and put it in temp2.
1205 // misalignment = addr & (word_size - 1);
1206 sljit_emit_op2(compiler, SLJIT_AND, Registers::arithmetic_temp2, 0, Registers::arithmetic_temp1, 0, SLJIT_IMM, word_size - 1);
1207
1208 // Mask the address with ~alignment_mask to get the aligned address and put it in temp1.
1209 // addr = addr & ~(word_size - 1);
1210 sljit_emit_op2(compiler, SLJIT_AND, Registers::arithmetic_temp1, 0, Registers::arithmetic_temp1, 0, SLJIT_IMM, ~(word_size - 1));
1211
1212 // Load the word at rdram + aligned address into the temp1 with sign-extension.
1213 // loaded_value = *addr
1214 if (doubleword) {
1215 // Rotate the loaded doubleword by 32 bits to swap the two words into the right order.
1216 sljit_emit_op2(compiler, SLJIT_ROTL, Registers::arithmetic_temp3, 0, SLJIT_MEM2(Registers::rdram, Registers::arithmetic_temp1), 0, SLJIT_IMM, 32);
1217 }
1218 else {
1219 // Use MOV_S32 to sign-extend the loaded word.
1220 sljit_emit_op1(compiler, SLJIT_MOV_S32, Registers::arithmetic_temp3, 0, SLJIT_MEM2(Registers::rdram, Registers::arithmetic_temp1), 0);
1221 }
1222
1223 // Inverse the misalignment if this is a right load.
1224 if (!left) {
1225 // misalignment = (word_size - 1 - misalignment) * 8
1226 sljit_emit_op2(compiler, SLJIT_SUB, Registers::arithmetic_temp2, 0, SLJIT_IMM, word_size - 1, Registers::arithmetic_temp2, 0);

Callers

nothing calls this directly

Calls 2

get_operand_valuesFunction · 0.85
get_gpr_context_offsetFunction · 0.85

Tested by

no test coverage detected