diff --git a/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc b/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc index 1d92e462b..e1234e13d 100644 --- a/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc +++ b/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc @@ -607,6 +607,27 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder) { i->Remove(); } break; + case OPCODE_VECTOR_COMPARE_SGE: + if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) { + v->set_from(i->src1.value); + v->VectorCompareSGE(i->src2.value, hir::TypeName(i->flags)); + i->Remove(); + } + break; + case OPCODE_VECTOR_COMPARE_UGT: + if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) { + v->set_from(i->src1.value); + v->VectorCompareUGT(i->src2.value, hir::TypeName(i->flags)); + i->Remove(); + } + break; + case OPCODE_VECTOR_COMPARE_UGE: + if (i->src1.value->IsConstant() && i->src2.value->IsConstant()) { + v->set_from(i->src1.value); + v->VectorCompareUGE(i->src2.value, hir::TypeName(i->flags)); + i->Remove(); + } + break; case OPCODE_VECTOR_CONVERT_F2I: if (i->src1.value->IsConstant()) { v->set_zero(VEC128_TYPE); diff --git a/src/xenia/cpu/hir/value.cc b/src/xenia/cpu/hir/value.cc index 4b129d85a..54b7c5c1c 100644 --- a/src/xenia/cpu/hir/value.cc +++ b/src/xenia/cpu/hir/value.cc @@ -248,22 +248,57 @@ void Value::Round(RoundMode round_mode) { switch (type) { case FLOAT32_TYPE: switch (round_mode) { + case ROUND_TO_ZERO: + constant.f32 = std::trunc(constant.f32); + break; case ROUND_TO_NEAREST: constant.f32 = std::round(constant.f32); return; + case ROUND_TO_MINUS_INFINITY: + constant.f32 = std::floor(constant.f32); + break; + case ROUND_TO_POSITIVE_INFINITY: + constant.f32 = std::ceil(constant.f32); + break; default: assert_unhandled_case(round_mode); return; } return; case FLOAT64_TYPE: + switch (round_mode) { + case ROUND_TO_ZERO: + constant.f64 = std::trunc(constant.f64); + break; + case ROUND_TO_NEAREST: + constant.f64 = std::round(constant.f64); + return; + case ROUND_TO_MINUS_INFINITY: + constant.f64 = std::floor(constant.f64); + break; + case ROUND_TO_POSITIVE_INFINITY: + constant.f64 = std::ceil(constant.f64); + break; + default: + assert_unhandled_case(round_mode); + return; + } return; case VEC128_TYPE: for (int i = 0; i < 4; i++) { switch (round_mode) { + case ROUND_TO_ZERO: + constant.v128.f32[i] = std::trunc(constant.v128.f32[i]); + break; case ROUND_TO_NEAREST: constant.v128.f32[i] = std::round(constant.v128.f32[i]); - return; + break; + case ROUND_TO_MINUS_INFINITY: + constant.v128.f32[i] = std::floor(constant.v128.f32[i]); + break; + case ROUND_TO_POSITIVE_INFINITY: + constant.v128.f32[i] = std::ceil(constant.v128.f32[i]); + break; default: assert_unhandled_case(round_mode); return; @@ -920,16 +955,121 @@ void Value::VectorCompareSGT(Value* other, TypeName type) { constant.v128.i32[i] > other->constant.v128.i32[i] ? -1 : 0; } break; + case INT64_TYPE: + for (int i = 0; i < 2; i++) { + constant.v128.u64[i] = + constant.v128.i64[i] > other->constant.v128.i64[i] ? -1 : 0; + } + break; case FLOAT32_TYPE: for (int i = 0; i < 4; i++) { constant.v128.u32[i] = constant.v128.f32[i] > other->constant.v128.f32[i] ? -1 : 0; } break; + default: + assert_unhandled_case(type); + break; + } +} + +void Value::VectorCompareSGE(Value* other, TypeName type) { + assert_true(this->type == VEC128_TYPE && other->type == VEC128_TYPE); + switch (type) { + case INT8_TYPE: + for (int i = 0; i < 16; i++) { + constant.v128.u8[i] = + constant.v128.i8[i] >= other->constant.v128.i8[i] ? -1 : 0; + } + break; + case INT16_TYPE: + for (int i = 0; i < 8; i++) { + constant.v128.u16[i] = + constant.v128.i16[i] >= other->constant.v128.i16[i] ? -1 : 0; + } + break; + case INT32_TYPE: + for (int i = 0; i < 4; i++) { + constant.v128.u32[i] = + constant.v128.i32[i] >= other->constant.v128.i32[i] ? -1 : 0; + } + break; case INT64_TYPE: for (int i = 0; i < 2; i++) { constant.v128.u64[i] = - constant.v128.i64[i] > other->constant.v128.i64[i] ? -1 : 0; + constant.v128.i64[i] >= other->constant.v128.i64[i] ? -1 : 0; + } + break; + case FLOAT32_TYPE: + for (int i = 0; i < 4; i++) { + constant.v128.u32[i] = + constant.v128.f32[i] >= other->constant.v128.f32[i] ? -1 : 0; + } + break; + default: + assert_unhandled_case(type); + break; + } +} + +void Value::VectorCompareUGT(Value* other, TypeName type) { + assert_true(this->type == VEC128_TYPE && other->type == VEC128_TYPE); + switch (type) { + case INT8_TYPE: + for (int i = 0; i < 16; i++) { + constant.v128.u8[i] = + constant.v128.u8[i] > other->constant.v128.u8[i] ? -1 : 0; + } + break; + case INT16_TYPE: + for (int i = 0; i < 8; i++) { + constant.v128.u16[i] = + constant.v128.u16[i] > other->constant.v128.u16[i] ? -1 : 0; + } + break; + case INT32_TYPE: + for (int i = 0; i < 4; i++) { + constant.v128.u32[i] = + constant.v128.u32[i] > other->constant.v128.u32[i] ? -1 : 0; + } + break; + case INT64_TYPE: + for (int i = 0; i < 2; i++) { + constant.v128.u64[i] = + constant.v128.u64[i] > other->constant.v128.u64[i] ? -1 : 0; + } + break; + default: + assert_unhandled_case(type); + break; + } +} + +void Value::VectorCompareUGE(Value* other, TypeName type) { + assert_true(this->type == VEC128_TYPE && other->type == VEC128_TYPE); + switch (type) { + case INT8_TYPE: + for (int i = 0; i < 16; i++) { + constant.v128.u8[i] = + constant.v128.u8[i] >= other->constant.v128.u8[i] ? -1 : 0; + } + break; + case INT16_TYPE: + for (int i = 0; i < 8; i++) { + constant.v128.u16[i] = + constant.v128.u16[i] >= other->constant.v128.u16[i] ? -1 : 0; + } + break; + case INT32_TYPE: + for (int i = 0; i < 4; i++) { + constant.v128.u32[i] = + constant.v128.u32[i] >= other->constant.v128.u32[i] ? -1 : 0; + } + break; + case INT64_TYPE: + for (int i = 0; i < 2; i++) { + constant.v128.u64[i] = + constant.v128.u64[i] >= other->constant.v128.u64[i] ? -1 : 0; } break; default: diff --git a/src/xenia/cpu/hir/value.h b/src/xenia/cpu/hir/value.h index ffba80188..ac704d543 100644 --- a/src/xenia/cpu/hir/value.h +++ b/src/xenia/cpu/hir/value.h @@ -500,6 +500,9 @@ class Value { void Splat(Value* other); void VectorCompareEQ(Value* other, TypeName type); void VectorCompareSGT(Value* other, TypeName type); + void VectorCompareSGE(Value* other, TypeName type); + void VectorCompareUGT(Value* other, TypeName type); + void VectorCompareUGE(Value* other, TypeName type); void VectorConvertI2F(Value* other); void VectorConvertF2I(Value* other); void VectorShl(Value* other, TypeName type);