case OP_SPECIAL_SRL:
v[c.r.rd].value = v[c.r.rt].value >> c.r.imm;
v[c.r.rd].known = (v[c.r.rt].known >> c.r.imm)
- | (BIT(c.r.imm) - 1 << 32 - c.r.imm);
+ | ((BIT(c.r.imm) - 1) << (32 - c.r.imm));
v[c.r.rd].sign = c.r.imm ? 0 : v[c.r.rt].sign;
break;
case OP_SPECIAL_SRA:
v[c.r.rd].value = (s32)v[c.r.rt].value >> c.r.imm;
+ v[c.r.rd].sign = (s32)(v[c.r.rt].sign
+ | (~v[c.r.rt].known & 0x80000000)) >> c.r.imm;
v[c.r.rd].known = (s32)v[c.r.rt].known >> c.r.imm;
- v[c.r.rd].sign = (s32)v[c.r.rt].sign >> c.r.imm;
break;
case OP_SPECIAL_SLLV:
imm = v[c.r.rs].value & 0x1f;
v[c.r.rd].value = v[c.r.rt].value >> imm;
v[c.r.rd].known = (v[c.r.rt].known >> imm)
- | (BIT(imm) - 1 << 32 - imm);
+ | ((BIT(imm) - 1) << (32 - imm));
if (imm)
v[c.r.rd].sign = 0;
} else {
if ((v[c.r.rs].known & 0x1f) == 0x1f) {
imm = v[c.r.rs].value & 0x1f;
v[c.r.rd].value = (s32)v[c.r.rt].value >> imm;
+ v[c.r.rd].sign = (s32)(v[c.r.rt].sign
+ | (~v[c.r.rt].known & 0x80000000)) >> imm;
v[c.r.rd].known = (s32)v[c.r.rt].known >> imm;
- v[c.r.rd].sign = (s32)v[c.r.rt].sign >> imm;
} else {
v[c.r.rd].known = 0;
v[c.r.rd].sign = 0;
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);
+ v[c.r.rd].value = block->pc + ((idx + 2) << 2);
break;
default:
if (OPT_FLAG_MULT_DIV && c.r.imm) {
if (c.r.op >= 32) {
- v[c.r.imm].value = v[c.r.rs].value << c.r.op - 32;
- v[c.r.imm].known = (v[c.r.rs].known << c.r.op - 32)
+ v[c.r.imm].value = v[c.r.rs].value << (c.r.op - 32);
+ v[c.r.imm].known = (v[c.r.rs].known << (c.r.op - 32))
| (BIT(c.r.op - 32) - 1);
- v[c.r.imm].sign = v[c.r.rs].sign << c.r.op - 32;
+ v[c.r.imm].sign = v[c.r.rs].sign << (c.r.op - 32);
} else if (c.i.op == OP_META_MULT2) {
- v[c.r.imm].value = (s32)v[c.r.rs].value >> 32 - c.r.op;
- v[c.r.imm].known = (s32)v[c.r.rs].known >> 32 - c.r.op;
- v[c.r.imm].sign = (s32)v[c.r.rs].sign >> 32 - c.r.op;
+ v[c.r.imm].value = (s32)v[c.r.rs].value >> (32 - c.r.op);
+ v[c.r.imm].known = (s32)v[c.r.rs].known >> (32 - c.r.op);
+ v[c.r.imm].sign = (s32)v[c.r.rs].sign >> (32 - c.r.op);
} else {
- v[c.r.imm].value = v[c.r.rs].value >> 32 - c.r.op;
- v[c.r.imm].known = v[c.r.rs].known >> 32 - c.r.op;
- v[c.r.imm].sign = v[c.r.rs].sign >> 32 - c.r.op;
+ v[c.r.imm].value = v[c.r.rs].value >> (32 - c.r.op);
+ v[c.r.imm].known = v[c.r.rs].known >> (32 - c.r.op);
+ v[c.r.imm].sign = v[c.r.rs].sign >> (32 - c.r.op);
}
}
break;
}
fallthrough;
case OP_LW:
+ case OP_META_LWU:
v[c.i.rt].known = 0;
v[c.i.rt].sign = 0;
break;
case OP_JAL:
v[31].known = 0xffffffff;
v[31].sign = 0;
- v[31].value = block->pc + (idx + 2 << 2);
+ v[31].value = block->pc + ((idx + 2) << 2);
break;
default:
if ((min & 0xe0000000) != (max & 0xe0000000))
return PSX_MAP_UNKNOWN;
- pr_debug("Min: 0x%08x max: 0x%08x Known: 0x%08x Sign: 0x%08x\n",
+ pr_debug("Min: "X32_FMT" max: "X32_FMT" Known: "X32_FMT" Sign: "X32_FMT"\n",
min, max, v[reg].known, v[reg].sign);
min = kunseg(min);