patch another gpulib alignment issue
[pcsx_rearmed.git] / deps / lightrec / optimizer.c
index c01e024..792f35c 100644 (file)
@@ -114,6 +114,8 @@ static u64 opcode_read_mask(union code op)
        case OP_SWL:
        case OP_SW:
        case OP_SWR:
+       case OP_META_LWU:
+       case OP_META_SWU:
                return BIT(op.i.rs) | BIT(op.i.rt);
        case OP_META:
                return BIT(op.m.rs);
@@ -186,6 +188,7 @@ u64 opcode_write_mask(union code op)
        case OP_LBU:
        case OP_LHU:
        case OP_LWR:
+       case OP_META_LWU:
                return BIT(op.i.rt);
        case OP_JAL:
                return BIT(31);
@@ -296,6 +299,9 @@ static bool reg_is_dead(const struct opcode *list, unsigned int offset, u8 reg)
                if (opcode_writes_register(list[i].c, reg))
                        return true;
 
+               if (is_syscall(list[i].c))
+                       return false;
+
                if (has_delay_slot(list[i].c)) {
                        if (op_flag_no_ds(list[i].flags) ||
                            opcode_reads_register(list[i + 1].c, reg))
@@ -382,6 +388,7 @@ bool opcode_is_load(union code op)
        case OP_LHU:
        case OP_LWR:
        case OP_LWC2:
+       case OP_META_LWU:
                return true;
        default:
                return false;
@@ -397,6 +404,7 @@ static bool opcode_is_store(union code op)
        case OP_SWL:
        case OP_SWR:
        case OP_SWC2:
+       case OP_META_SWU:
                return true;
        default:
                return false;
@@ -438,6 +446,7 @@ static bool is_nop(union code op)
                case OP_LBU:
                case OP_LHU:
                case OP_LWR:
+               case OP_META_LWU:
                        return false;
                default:
                        return true;
@@ -822,6 +831,7 @@ static void lightrec_patch_known_zero(struct opcode *op,
        case OP_SWL:
        case OP_SW:
        case OP_SWR:
+       case OP_META_SWU:
                if (is_known_zero(v, op->i.rt))
                        op->i.rt = 0;
                fallthrough;
@@ -834,6 +844,7 @@ static void lightrec_patch_known_zero(struct opcode *op,
        case OP_LWR:
        case OP_LWC2:
        case OP_SWC2:
+       case OP_META_LWU:
                if (is_known(v, op->i.rs)
                    && kunseg(v[op->i.rs].value) == 0)
                        op->i.rs = 0;
@@ -879,6 +890,7 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl
        struct constprop_data v[32] = LIGHTREC_CONSTPROP_INITIALIZER;
        unsigned int i;
        bool local;
+       int idx;
        u8 tmp;
 
        for (i = 0; i < block->nb_ops; i++) {
@@ -1016,6 +1028,40 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl
                                }
                        }
                        break;
+               case OP_LWL:
+               case OP_LWR:
+                       if (i == 0 || !has_delay_slot(list[i - 1].c)) {
+                               idx = find_next_reader(list, i + 1, op->i.rt);
+                               if (idx > 0 && list[idx].i.op == (op->i.op ^ 0x4)
+                                   && list[idx].i.rs == op->i.rs
+                                   && list[idx].i.rt == op->i.rt
+                                   && abs((s16)op->i.imm - (s16)list[idx].i.imm) == 3) {
+                                       /* Replace a LWL/LWR combo with a META_LWU */
+                                       if (op->i.op == OP_LWL)
+                                               op->i.imm -= 3;
+                                       op->i.op = OP_META_LWU;
+                                       list[idx].opcode = 0;
+                                       pr_debug("Convert LWL/LWR to LWU\n");
+                               }
+                       }
+                       break;
+               case OP_SWL:
+               case OP_SWR:
+                       if (i == 0 || !has_delay_slot(list[i - 1].c)) {
+                               idx = find_next_reader(list, i + 1, op->i.rt);
+                               if (idx > 0 && list[idx].i.op == (op->i.op ^ 0x4)
+                                   && list[idx].i.rs == op->i.rs
+                                   && list[idx].i.rt == op->i.rt
+                                   && abs((s16)op->i.imm - (s16)list[idx].i.imm) == 3) {
+                                       /* Replace a SWL/SWR combo with a META_SWU */
+                                       if (op->i.op == OP_SWL)
+                                               op->i.imm -= 3;
+                                       op->i.op = OP_META_SWU;
+                                       list[idx].opcode = 0;
+                                       pr_debug("Convert SWL/SWR to SWU\n");
+                               }
+                       }
+                       break;
                case OP_REGIMM:
                        switch (op->r.rt) {
                        case OP_REGIMM_BLTZ: