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

Method process_unary_op

LiveRecomp/live_generator.cpp:893–1167  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

891}
892
893void N64Recomp::LiveGenerator::process_unary_op(const UnaryOp& op, const InstructionContext& ctx) const {
894 // Skip instructions that output to $zero
895 if (outputs_to_zero(op.output, ctx)) {
896 return;
897 }
898
899 // A unary op may have a float u32l as the source or destination, but not both.
900 if (is_fpr_u32l(op.input) && is_fpr_u32l(op.output)) {
901 assert(false);
902 errored = true;
903 return;
904 }
905
906 sljit_sw dst;
907 sljit_sw dstw;
908 sljit_sw src;
909 sljit_sw srcw;
910 bool output_good = get_operand_values(op.output, ctx, dst, dstw, compiler, Registers::arithmetic_temp3);
911 bool input_good = get_operand_values(op.input, ctx, src, srcw, compiler, Registers::arithmetic_temp3);
912
913 if (!output_good || !input_good) {
914 assert(false);
915 errored = true;
916 return;
917 }
918
919 // If a relocation is needed for the input operand, perform the relocation and store the result directly.
920 if (ctx.reloc_type != RelocType::R_MIPS_NONE) {
921 // Only allow relocation of lui with an immediate.
922 if (op.operation != UnaryOpType::Lui || op.input != Operand::ImmU16) {
923 assert(false);
924 errored = true;
925 return;
926 }
927 // Only allow HI16 relocs.
928 if (ctx.reloc_type != RelocType::R_MIPS_HI16) {
929 assert(false);
930 errored = true;
931 return;
932 }
933 // Load the relocated address into temp1.
934 load_relocated_address(ctx, Registers::arithmetic_temp1);
935
936 // HI16 reloc on a lui
937 // The 32-bit address (a) is equal to section address + section offset
938 // The 16-bit immediate is equal to (a - (int16_t)a) >> 16
939 // Therefore, the register should be set to (int32_t)(a - (int16_t)a) as the shifts cancel out and the lower 16 bits are zero.
940
941 // Extract a sign extended 16-bit value from the lower half of the relocated address and put it in temp2.
942 sljit_emit_op1(compiler, SLJIT_MOV_S16, Registers::arithmetic_temp2, 0, Registers::arithmetic_temp1, 0);
943
944 // Subtract the sign extended 16-bit value from the full address to get the HI16 value and place it in the destination.
945 sljit_emit_op2(compiler, SLJIT_SUB, dst, dstw, Registers::arithmetic_temp1, 0, Registers::arithmetic_temp2, 0);
946 return;
947 }
948
949 sljit_s32 jit_op = SLJIT_BREAKPOINT;
950

Callers

nothing calls this directly

Calls 3

outputs_to_zeroFunction · 0.85
is_fpr_u32lFunction · 0.85
get_operand_valuesFunction · 0.85

Tested by

no test coverage detected