lightrec: Increase size of hw registers area
[pcsx_rearmed.git] / deps / lightrec / constprop.c
index 353f42f..8499c6e 100644 (file)
@@ -243,12 +243,13 @@ static void lightrec_propagate_slt(u32 rs, u32 rd, bool is_signed,
        }
 }
 
-void lightrec_consts_propagate(const struct opcode *list,
+void lightrec_consts_propagate(const struct block *block,
                               unsigned int idx,
                               struct constprop_data *v)
 {
+       const struct opcode *list = block->opcode_list;
        union code c;
-       u32 imm;
+       u32 imm, flags;
 
        if (idx == 0)
                return;
@@ -263,8 +264,13 @@ void lightrec_consts_propagate(const struct opcode *list,
                return;
        }
 
-       if (idx > 1 && !op_flag_sync(list[idx - 1].flags)) {
-               c = list[idx - 2].c;
+       flags = list[idx - 1].flags;
+
+       if (idx > 1 && !op_flag_sync(flags)) {
+               if (op_flag_no_ds(flags))
+                       c = list[idx - 1].c;
+               else
+                       c = list[idx - 2].c;
 
                switch (c.i.op) {
                case OP_BNE:
@@ -449,6 +455,13 @@ void lightrec_consts_propagate(const struct opcode *list,
                        v[c.r.rd].known = 0;
                        v[c.r.rd].sign = 0;
                        break;
+
+               case OP_SPECIAL_JALR:
+                       v[c.r.rd].known = 0xffffffff;
+                       v[c.r.rd].sign = 0;
+                       v[c.r.rd].value = block->pc + (idx + 2 << 2);
+                       break;
+
                default:
                        break;
                }
@@ -644,7 +657,7 @@ void lightrec_consts_propagate(const struct opcode *list,
                                imm = imm ? GENMASK(31, 32 - imm) : 0;
                                v[c.i.rt].sign = 0;
                        }
-                       v[c.i.rt].known &= ~imm;
+                       v[c.i.rt].known &= imm;
                        break;
                }
                fallthrough;
@@ -652,30 +665,48 @@ void lightrec_consts_propagate(const struct opcode *list,
                v[c.i.rt].known = 0;
                v[c.i.rt].sign = 0;
                break;
-       case OP_META_MOV:
-               v[c.r.rd] = v[c.r.rs];
-               break;
-       case OP_META_EXTC:
-               v[c.i.rt].value = (s32)(s8)v[c.i.rs].value;
-               if (v[c.i.rs].known & BIT(7)) {
-                       v[c.i.rt].known = v[c.i.rs].known | 0xffffff00;
-                       v[c.i.rt].sign = 0;
-               } else {
-                       v[c.i.rt].known = v[c.i.rs].known & 0x7f;
-                       v[c.i.rt].sign = 0xffffff80;
-               }
-               break;
+       case OP_META:
+               switch (c.m.op) {
+               case OP_META_MOV:
+                       v[c.m.rd] = v[c.m.rs];
+                       break;
 
-       case OP_META_EXTS:
-               v[c.i.rt].value = (s32)(s16)v[c.i.rs].value;
-               if (v[c.i.rs].known & BIT(15)) {
-                       v[c.i.rt].known = v[c.i.rs].known | 0xffff0000;
-                       v[c.i.rt].sign = 0;
-               } else {
-                       v[c.i.rt].known = v[c.i.rs].known & 0x7fff;
-                       v[c.i.rt].sign = 0xffff8000;
+               case OP_META_EXTC:
+                       v[c.m.rd].value = (s32)(s8)v[c.m.rs].value;
+                       if (v[c.m.rs].known & BIT(7)) {
+                               v[c.m.rd].known = v[c.m.rs].known | 0xffffff00;
+                               v[c.m.rd].sign = 0;
+                       } else {
+                               v[c.m.rd].known = v[c.m.rs].known & 0x7f;
+                               v[c.m.rd].sign = 0xffffff80;
+                       }
+                       break;
+
+               case OP_META_EXTS:
+                       v[c.m.rd].value = (s32)(s16)v[c.m.rs].value;
+                       if (v[c.m.rs].known & BIT(15)) {
+                               v[c.m.rd].known = v[c.m.rs].known | 0xffff0000;
+                               v[c.m.rd].sign = 0;
+                       } else {
+                               v[c.m.rd].known = v[c.m.rs].known & 0x7fff;
+                               v[c.m.rd].sign = 0xffff8000;
+                       }
+                       break;
+
+               case OP_META_COM:
+                       v[c.m.rd].known = v[c.m.rs].known;
+                       v[c.m.rd].value = ~v[c.m.rs].value;
+                       v[c.m.rd].sign = v[c.m.rs].sign;
+                       break;
+               default:
+                       break;
                }
                break;
+       case OP_JAL:
+               v[31].known = 0xffffffff;
+               v[31].sign = 0;
+               v[31].value = block->pc + (idx + 2 << 2);
+               break;
 
        default:
                break;