}
}
-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;
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:
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;
}
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;
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;