VarAction2: Add an ABS opcode
This commit is contained in:
@@ -5633,8 +5633,9 @@ enum VarAction2AdjustInferenceFlags {
|
|||||||
VA2AIF_HAVE_CONSTANT = 0x20,
|
VA2AIF_HAVE_CONSTANT = 0x20,
|
||||||
VA2AIF_SINGLE_LOAD = 0x40,
|
VA2AIF_SINGLE_LOAD = 0x40,
|
||||||
VA2AIF_MUL_BOOL = 0x80,
|
VA2AIF_MUL_BOOL = 0x80,
|
||||||
|
VA2AIF_PREV_SCMP_DEC = 0x100,
|
||||||
|
|
||||||
VA2AIF_PREV_MASK = VA2AIF_PREV_TERNARY | VA2AIF_PREV_MASK_ADJUST | VA2AIF_PREV_STORE_TMP,
|
VA2AIF_PREV_MASK = VA2AIF_PREV_TERNARY | VA2AIF_PREV_MASK_ADJUST | VA2AIF_PREV_STORE_TMP | VA2AIF_PREV_SCMP_DEC,
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(VarAction2AdjustInferenceFlags)
|
DECLARE_ENUM_AS_BIT_SET(VarAction2AdjustInferenceFlags)
|
||||||
|
|
||||||
@@ -6322,6 +6323,12 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (adjust.variable == 0x1A && adjust.shift_num == 0 && adjust.and_mask == 1 && group->adjusts.size() >= 2) {
|
||||||
|
DeterministicSpriteGroupAdjust &prev = group->adjusts[group->adjusts.size() - 2];
|
||||||
|
if (prev.operation == DSGA_OP_SCMP) {
|
||||||
|
state.inference |= VA2AIF_PREV_SCMP_DEC;
|
||||||
|
}
|
||||||
|
}
|
||||||
try_merge_with_previous();
|
try_merge_with_previous();
|
||||||
break;
|
break;
|
||||||
case DSGA_OP_SMIN:
|
case DSGA_OP_SMIN:
|
||||||
@@ -6543,6 +6550,23 @@ static void OptimiseVarAction2Adjust(VarAction2OptimiseState &state, const GrfSp
|
|||||||
state.inference = VA2AIF_PREV_TERNARY;
|
state.inference = VA2AIF_PREV_TERNARY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ((prev_inference & VA2AIF_PREV_SCMP_DEC) && group->adjusts.size() >= 4 && adjust.variable == 0x7D && adjust.shift_num == 0 && adjust.and_mask == 0xFFFFFFFF) {
|
||||||
|
const DeterministicSpriteGroupAdjust &adj1 = group->adjusts[group->adjusts.size() - 4];
|
||||||
|
const DeterministicSpriteGroupAdjust &adj2 = group->adjusts[group->adjusts.size() - 3];
|
||||||
|
const DeterministicSpriteGroupAdjust &adj3 = group->adjusts[group->adjusts.size() - 2];
|
||||||
|
auto is_expected_op = [](const DeterministicSpriteGroupAdjust &adj, DeterministicSpriteGroupAdjustOperation op, uint32 value) -> bool {
|
||||||
|
return adj.operation == op && adj.type == DSGA_TYPE_NONE && adj.variable == 0x1A && adj.shift_num == 0 && adj.and_mask == value;
|
||||||
|
};
|
||||||
|
if (is_expected_op(adj1, DSGA_OP_STO, (adjust.parameter & 0xFF)) &&
|
||||||
|
is_expected_op(adj2, DSGA_OP_SCMP, 0) &&
|
||||||
|
is_expected_op(adj3, DSGA_OP_SUB, 1)) {
|
||||||
|
group->adjusts.pop_back();
|
||||||
|
group->adjusts.pop_back();
|
||||||
|
group->adjusts.back().operation = DSGA_OP_ABS;
|
||||||
|
state.inference |= VA2AIF_SIGNED_NON_NEGATIVE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
uint32 sign_bit = (1 << ((varsize * 8) - 1));
|
uint32 sign_bit = (1 << ((varsize * 8) - 1));
|
||||||
if ((prev_inference & VA2AIF_PREV_MASK_ADJUST) && (prev_inference & VA2AIF_SIGNED_NON_NEGATIVE) && adjust.variable == 0x1A && adjust.shift_num == 0 && (adjust.and_mask & sign_bit) == 0) {
|
if ((prev_inference & VA2AIF_PREV_MASK_ADJUST) && (prev_inference & VA2AIF_SIGNED_NON_NEGATIVE) && adjust.variable == 0x1A && adjust.shift_num == 0 && (adjust.and_mask & sign_bit) == 0) {
|
||||||
/* Determine whether the result will be always non-negative */
|
/* Determine whether the result will be always non-negative */
|
||||||
|
@@ -200,6 +200,7 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust &adjust, ScopeResolver
|
|||||||
case DSGA_OP_SGT: return ((S)last_value > (S)value) ? 1 : 0;
|
case DSGA_OP_SGT: return ((S)last_value > (S)value) ? 1 : 0;
|
||||||
case DSGA_OP_RSUB: return value - last_value;
|
case DSGA_OP_RSUB: return value - last_value;
|
||||||
case DSGA_OP_STO_NC: _temp_store.StoreValue(adjust.divmod_val, (S)value); return last_value;
|
case DSGA_OP_STO_NC: _temp_store.StoreValue(adjust.divmod_val, (S)value); return last_value;
|
||||||
|
case DSGA_OP_ABS: return ((S)last_value < 0) ? -((S)last_value) : (S)last_value;
|
||||||
default: return value;
|
default: return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -683,6 +684,7 @@ static const char *_dsg_op_special_names[] {
|
|||||||
"SGT",
|
"SGT",
|
||||||
"RSUB",
|
"RSUB",
|
||||||
"STO_NC",
|
"STO_NC",
|
||||||
|
"ABS",
|
||||||
};
|
};
|
||||||
static_assert(lengthof(_dsg_op_special_names) == DSGA_OP_SPECIAL_END - DSGA_OP_TERNARY);
|
static_assert(lengthof(_dsg_op_special_names) == DSGA_OP_SPECIAL_END - DSGA_OP_TERNARY);
|
||||||
|
|
||||||
@@ -727,6 +729,11 @@ static char *DumpSpriteGroupAdjust(char *p, const char *last, const Deterministi
|
|||||||
append_flags();
|
append_flags();
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
if (adjust.operation == DSGA_OP_ABS) {
|
||||||
|
p += seprintf(p, last, "%*sABS", padding, "");
|
||||||
|
append_flags();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
if (adjust.operation == DSGA_OP_STO && adjust.type == DSGA_TYPE_NONE && adjust.variable == 0x1A && adjust.shift_num == 0) {
|
if (adjust.operation == DSGA_OP_STO && adjust.type == DSGA_TYPE_NONE && adjust.variable == 0x1A && adjust.shift_num == 0) {
|
||||||
/* Temp storage store */
|
/* Temp storage store */
|
||||||
highlight_tag = (1 << 16) | (adjust.and_mask & 0xFFFF);
|
highlight_tag = (1 << 16) | (adjust.and_mask & 0xFFFF);
|
||||||
|
@@ -198,6 +198,7 @@ enum DeterministicSpriteGroupAdjustOperation : uint8 {
|
|||||||
DSGA_OP_SGT, ///< (signed) a > b ? 1 : 0,
|
DSGA_OP_SGT, ///< (signed) a > b ? 1 : 0,
|
||||||
DSGA_OP_RSUB, ///< b - a
|
DSGA_OP_RSUB, ///< b - a
|
||||||
DSGA_OP_STO_NC, ///< store b into temporary storage, indexed by c. return a
|
DSGA_OP_STO_NC, ///< store b into temporary storage, indexed by c. return a
|
||||||
|
DSGA_OP_ABS, ///< abs(a)
|
||||||
|
|
||||||
DSGA_OP_SPECIAL_END,
|
DSGA_OP_SPECIAL_END,
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user