Switching to premake. Probably with disasterous consequences.
This commit is contained in:
427
src/xenia/cpu/testing/add_test.cc
Normal file
427
src/xenia/cpu/testing/add_test.cc
Normal file
@@ -0,0 +1,427 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("ADD_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Add(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 10;
|
||||
ctx->r[5] = 25;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x23);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = -10;
|
||||
ctx->r[5] = -5;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int8_t>(ctx->r[3]);
|
||||
REQUIRE(result == -15);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = INT8_MIN;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int8_t>(ctx->r[3]);
|
||||
REQUIRE(result == INT8_MIN);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = UINT8_MAX;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == UINT8_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = INT8_MIN;
|
||||
ctx->r[5] = -1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int8_t>(ctx->r[3]);
|
||||
REQUIRE(result == INT8_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = UINT8_MAX;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("ADD_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Add(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT16_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 10;
|
||||
ctx->r[5] = 25;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x23);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = -10;
|
||||
ctx->r[5] = -5;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int16_t>(ctx->r[3]);
|
||||
REQUIRE(result == -15);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = INT16_MIN;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int16_t>(ctx->r[3]);
|
||||
REQUIRE(result == INT16_MIN);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = UINT16_MAX;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == UINT16_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = INT16_MIN;
|
||||
ctx->r[5] = -1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int16_t>(ctx->r[3]);
|
||||
REQUIRE(result == INT16_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = UINT16_MAX;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("ADD_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Add(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT32_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 10;
|
||||
ctx->r[5] = 25;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x23);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = -10;
|
||||
ctx->r[5] = -5;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int32_t>(ctx->r[3]);
|
||||
REQUIRE(result == -15);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = INT32_MIN;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int32_t>(ctx->r[3]);
|
||||
REQUIRE(result == INT32_MIN);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = UINT32_MAX;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == UINT32_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = INT32_MIN;
|
||||
ctx->r[5] = -1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int32_t>(ctx->r[3]);
|
||||
REQUIRE(result == INT32_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = UINT32_MAX;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<int32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("ADD_I64", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.Add(LoadGPR(b, 4), LoadGPR(b, 5)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 10;
|
||||
ctx->r[5] = 25;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == 0x23);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = -10;
|
||||
ctx->r[5] = -5;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == -15);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = INT64_MIN;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == INT64_MIN);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = UINT64_MAX;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == UINT64_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = INT64_MIN;
|
||||
ctx->r[5] = -1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == INT64_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = UINT64_MAX;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("ADD_F32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreFPR(b, 3, b.Convert(b.Add(b.Convert(LoadFPR(b, 4), FLOAT32_TYPE),
|
||||
b.Convert(LoadFPR(b, 5), FLOAT32_TYPE)),
|
||||
FLOAT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = 0.0;
|
||||
ctx->f[5] = 0.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == 0.0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = 5.0;
|
||||
ctx->f[5] = 7.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == 12.0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = FLT_MAX / 2.0;
|
||||
ctx->f[5] = FLT_MAX / 2.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == FLT_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = -100.0;
|
||||
ctx->f[5] = -150.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == -250.0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = FLT_MIN;
|
||||
ctx->f[5] = 0.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == FLT_MIN);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = FLT_MAX;
|
||||
ctx->f[5] = 0.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == FLT_MAX);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("ADD_F64", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreFPR(b, 3, b.Add(LoadFPR(b, 4), LoadFPR(b, 5)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = 0.0;
|
||||
ctx->f[5] = 0.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == 0.0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = 5.0;
|
||||
ctx->f[5] = 7.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == 12.0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = DBL_MAX / 2.0;
|
||||
ctx->f[5] = DBL_MAX / 2.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == DBL_MAX);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = -100.0;
|
||||
ctx->f[5] = -150.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == -250.0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = DBL_MIN;
|
||||
ctx->f[5] = 0.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == DBL_MIN);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->f[4] = DBL_MAX;
|
||||
ctx->f[5] = 0.0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->f[3];
|
||||
REQUIRE(result == DBL_MAX);
|
||||
});
|
||||
}
|
||||
46
src/xenia/cpu/testing/byte_swap_test.cc
Normal file
46
src/xenia/cpu/testing/byte_swap_test.cc
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("BYTE_SWAP_V128", "[instr]") {
|
||||
TestFunction([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.ByteSwap(LoadVR(b, 4)));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15,
|
||||
14, 13, 12));
|
||||
});
|
||||
TestFunction([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.ByteSwap(LoadVR(b, 4)));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x0C13100F, 0x0E0D0C0B, 0x0A000000, 0x00000000);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x0F10130C, 0x0B0C0D0E, 0x0000000A, 0x00000000));
|
||||
});
|
||||
}
|
||||
144
src/xenia/cpu/testing/extract_test.cc
Normal file
144
src/xenia/cpu/testing/extract_test.cc
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("EXTRACT_INT8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
INT8_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
test.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->r[4] = i;
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == i);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("EXTRACT_INT8_CONSTANT", "[instr]") {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
TestFunction([i](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4), b.LoadConstantInt8(i),
|
||||
INT8_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->r[4] = i;
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == i);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("EXTRACT_INT16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
INT16_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
test.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->r[4] = i;
|
||||
ctx->v[4] = vec128s(0x0000, 0x1001, 0x2002, 0x3003, 0x4004, 0x5005,
|
||||
0x6006, 0x7007);
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == (i | (i << 12)));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("EXTRACT_INT16_CONSTANT", "[instr]") {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
TestFunction([i](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4), b.LoadConstantInt8(i),
|
||||
INT16_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->r[4] = i;
|
||||
ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, 6, 7);
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == i);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("EXTRACT_INT32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
INT32_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
test.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->r[4] = i;
|
||||
ctx->v[4] = vec128i(0, 1, 2, 3);
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == i);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("EXTRACT_INT32_CONSTANT", "[instr]") {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
TestFunction([i](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Extract(LoadVR(b, 4), b.LoadConstantInt8(i),
|
||||
INT32_TYPE),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->r[4] = i;
|
||||
ctx->v[4] = vec128i(0, 1, 2, 3);
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->r[3];
|
||||
REQUIRE(result == i);
|
||||
});
|
||||
}
|
||||
}
|
||||
86
src/xenia/cpu/testing/insert_test.cc
Normal file
86
src/xenia/cpu/testing/insert_test.cc
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("INSERT_INT8", "[instr]") {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
TestFunction test([i](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstantInt32(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->r[4] = i;
|
||||
ctx->r[5] = 100 + i;
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
auto expected =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
expected.i8[i ^ 0x3] = 100 + i;
|
||||
REQUIRE(result == expected);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("INSERT_INT16", "[instr]") {
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
TestFunction test([i](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstantInt32(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT16_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, 6, 7);
|
||||
ctx->r[4] = i;
|
||||
ctx->r[5] = 100 + i;
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
auto expected = vec128s(0, 1, 2, 3, 4, 5, 6, 7);
|
||||
expected.i16[i ^ 0x1] = 100 + i;
|
||||
REQUIRE(result == expected);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("INSERT_INT32", "[instr]") {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
TestFunction test([i](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), b.LoadConstantInt32(i),
|
||||
b.Truncate(LoadGPR(b, 5), INT32_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[i](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 2, 3);
|
||||
ctx->r[4] = i;
|
||||
ctx->r[5] = 100 + i;
|
||||
},
|
||||
[i](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
auto expected = vec128i(0, 1, 2, 3);
|
||||
expected.i32[i] = 100 + i;
|
||||
REQUIRE(result == expected);
|
||||
});
|
||||
}
|
||||
}
|
||||
78
src/xenia/cpu/testing/load_vector_shl_shr_test.cc
Normal file
78
src/xenia/cpu/testing/load_vector_shl_shr_test.cc
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("LOAD_VECTOR_SHL", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.LoadVectorShl(b.Truncate(LoadGPR(b, 4), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->r[4] = 0; },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
13, 14, 15));
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->r[4] = 7; },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22));
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->r[4] = 15; },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||||
25, 26, 27, 28, 29, 30));
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->r[4] = 16; },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
13, 14, 15));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("LOAD_VECTOR_SHR", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.LoadVectorShr(b.Truncate(LoadGPR(b, 4), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->r[4] = 0; },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
|
||||
26, 27, 28, 29, 30, 31));
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->r[4] = 7; },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
||||
19, 20, 21, 22, 23, 24));
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->r[4] = 15; },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
13, 14, 15, 16));
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->r[4] = 16; },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
|
||||
26, 27, 28, 29, 30, 31));
|
||||
});
|
||||
}
|
||||
113
src/xenia/cpu/testing/pack_test.cc
Normal file
113
src/xenia/cpu/testing/pack_test.cc
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("PACK_D3DCOLOR", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Pack(LoadVR(b, 4), PACK_TYPE_D3DCOLOR));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128f(1.0f); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x40400050, 0x40400060, 0x40400070, 0x40400080);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 0, 0, 0x80506070));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("PACK_FLOAT16_2", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Pack(LoadVR(b, 4), PACK_TYPE_FLOAT16_2));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0, 0, 0, 0x3F800000); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x47FFE000, 0xC7FFE000, 0x00000000, 0x3F800000);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 0, 0, 0x7FFFFFFF));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x42AAA000, 0x44CCC000, 0x00000000, 0x3F800000);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 0, 0, 0x55556666));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("PACK_FLOAT16_4", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Pack(LoadVR(b, 4), PACK_TYPE_FLOAT16_4));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0, 0, 0, 0); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x449A4000, 0x45B17000, 0x41103261, 0x40922B6B);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x00000000, 0x00000000, 0x64D26D8C, 0x48824491));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("PACK_SHORT_2", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Pack(LoadVR(b, 4), PACK_TYPE_SHORT_2));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x43817E00, 0xC37CFC00, 0, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 0, 0, 0x7FFF8001));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0xC0D47D97, 0xC2256E9D, 0, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 0, 0, 0x80018001));
|
||||
});
|
||||
}
|
||||
151
src/xenia/cpu/testing/permute_test.cc
Normal file
151
src/xenia/cpu/testing/permute_test.cc
Normal file
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("PERMUTE_V128_BY_INT32_CONSTANT", "[instr]") {
|
||||
{
|
||||
uint32_t mask = PERMUTE_MASK(0, 0, 0, 1, 0, 2, 0, 3);
|
||||
TestFunction([mask](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4),
|
||||
LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 2, 3);
|
||||
ctx->v[5] = vec128i(4, 5, 6, 7);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 1, 2, 3));
|
||||
});
|
||||
}
|
||||
{
|
||||
uint32_t mask = PERMUTE_MASK(1, 0, 1, 1, 1, 2, 1, 3);
|
||||
TestFunction([mask](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4),
|
||||
LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 2, 3);
|
||||
ctx->v[5] = vec128i(4, 5, 6, 7);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(4, 5, 6, 7));
|
||||
});
|
||||
}
|
||||
{
|
||||
uint32_t mask = PERMUTE_MASK(0, 3, 0, 2, 0, 1, 0, 0);
|
||||
TestFunction([mask](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4),
|
||||
LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 2, 3);
|
||||
ctx->v[5] = vec128i(4, 5, 6, 7);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(3, 2, 1, 0));
|
||||
});
|
||||
}
|
||||
{
|
||||
uint32_t mask = PERMUTE_MASK(1, 3, 1, 2, 1, 1, 1, 0);
|
||||
TestFunction([mask](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstantUint32(mask), LoadVR(b, 4),
|
||||
LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
})
|
||||
.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 2, 3);
|
||||
ctx->v[5] = vec128i(4, 5, 6, 7);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(7, 6, 5, 4));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("PERMUTE_V128_BY_V128", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3,
|
||||
b.Permute(LoadVR(b, 3), LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[3] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[4] =
|
||||
vec128b(100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[5] = vec128b(16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||
29, 30, 31);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
13, 14, 15));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[3] = vec128b(16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||
29, 30, 31);
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[5] = vec128b(116, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||
29, 30, 31);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(116, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
|
||||
27, 28, 29, 30, 31));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[3] =
|
||||
vec128b(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
|
||||
ctx->v[4] =
|
||||
vec128b(100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[5] = vec128b(16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||
29, 30, 31);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3,
|
||||
2, 1, 100));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[3] = vec128b(31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19,
|
||||
18, 17, 16);
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[5] = vec128b(16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||
29, 30, 131);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(131, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21,
|
||||
20, 19, 18, 17, 16));
|
||||
});
|
||||
}
|
||||
17
src/xenia/cpu/testing/premake5.lua
Normal file
17
src/xenia/cpu/testing/premake5.lua
Normal file
@@ -0,0 +1,17 @@
|
||||
project_root = "../../../.."
|
||||
include(project_root.."/build_tools")
|
||||
|
||||
test_suite("xenia-cpu-tests", project_root, ".", {
|
||||
includedirs = {
|
||||
},
|
||||
links = {
|
||||
"xenia-base",
|
||||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-cpu-backend-x64",
|
||||
|
||||
-- TODO(benvanik): cut these dependencies?
|
||||
"xenia-debug",
|
||||
"xenia-kernel",
|
||||
},
|
||||
})
|
||||
84
src/xenia/cpu/testing/sandbox_main.cc
Normal file
84
src/xenia/cpu/testing/sandbox_main.cc
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/base/main.h"
|
||||
#include "xenia/cpu/cpu.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc_frontend.h"
|
||||
#include "xenia/cpu/raw_module.h"
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace sandbox {
|
||||
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
using xe::cpu::Runtime;
|
||||
|
||||
// TODO(benvanik): simple memory? move more into core?
|
||||
|
||||
int main(std::vector<std::wstring>& args) {
|
||||
#if XE_OPTION_PROFILING
|
||||
xe::Profiler::Initialize();
|
||||
xe::Profiler::ThreadEnter("main");
|
||||
#endif // XE_OPTION_PROFILING
|
||||
|
||||
size_t memory_size = 16 * 1024 * 1024;
|
||||
auto memory = std::make_unique<SimpleMemory>(memory_size);
|
||||
auto runtime = std::make_unique<Runtime>(memory.get());
|
||||
|
||||
auto frontend =
|
||||
std::make_unique<xe::cpu::frontend::ppc::PPCFrontend>(runtime.get());
|
||||
std::unique_ptr<xe::cpu::backend::Backend> backend;
|
||||
// backend =
|
||||
// std::make_unique<xe::cpu::backend::ivm::IVMBackend>(runtime.get());
|
||||
// backend =
|
||||
// std::make_unique<xe::cpu::backend::x64::X64Backend>(runtime.get());
|
||||
runtime->Initialize(std::move(frontend), std::move(backend));
|
||||
|
||||
auto module = std::make_unique<xe::cpu::RawModule>(runtime.get());
|
||||
module->LoadFile(0x00001000, L"test\\codegen\\instr_add.bin");
|
||||
runtime->AddModule(std::move(module));
|
||||
|
||||
{
|
||||
uint64_t stack_size = 64 * 1024;
|
||||
uint64_t stack_address = memory_size - stack_size;
|
||||
uint64_t thread_state_address = stack_address - 0x1000;
|
||||
auto thread_state = std::make_unique<ThreadState>(
|
||||
runtime.get(), 100, stack_address, stack_size, thread_state_address);
|
||||
|
||||
xe::cpu::Function* fn;
|
||||
runtime->ResolveFunction(0x1000, &fn);
|
||||
auto ctx = thread_state->context();
|
||||
ctx->lr = 0xBEBEBEBE;
|
||||
ctx->r[5] = 10;
|
||||
ctx->r[25] = 25;
|
||||
fn->Call(thread_state.get(), ctx->lr);
|
||||
auto result = ctx->r[11];
|
||||
printf("%llu", result);
|
||||
}
|
||||
|
||||
runtime.reset();
|
||||
memory.reset();
|
||||
|
||||
#if XE_OPTION_PROFILING
|
||||
xe::Profiler::Dump();
|
||||
xe::Profiler::ThreadExit();
|
||||
#endif // XE_OPTION_PROFILING
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace sandbox
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
DEFINE_ENTRY_POINT(L"xenia-cpu-sandbox", L"?", xe::cpu::sandbox::main);
|
||||
230
src/xenia/cpu/testing/sha_test.cc
Normal file
230
src/xenia/cpu/testing/sha_test.cc
Normal file
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("SHA_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Sha(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xF0;
|
||||
ctx->r[5] = 4;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x80;
|
||||
ctx->r[5] = 8;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7F;
|
||||
ctx->r[5] = 7;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHA_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Sha(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF00;
|
||||
ctx->r[5] = 8;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFE;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x8000;
|
||||
ctx->r[5] = 16;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFF;
|
||||
ctx->r[5] = 15;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHA_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Sha(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFF0000;
|
||||
ctx->r[5] = 16;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFE;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x80000000;
|
||||
ctx->r[5] = 32;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x80000000);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFF;
|
||||
ctx->r[5] = 31;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHA_I64", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.Sha(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFF00000000ull;
|
||||
ctx->r[5] = 32;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFFFFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFFFFFFFFFFull;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFFFFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFFFFFFFFFEull;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFFFFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x8000000000000000ull;
|
||||
ctx->r[5] = 64;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x8000000000000000ull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFFFFFFFFFFull;
|
||||
ctx->r[5] = 63;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
230
src/xenia/cpu/testing/shl_test.cc
Normal file
230
src/xenia/cpu/testing/shl_test.cc
Normal file
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("SHL_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shl(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x0F;
|
||||
ctx->r[5] = 4;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xF0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFE);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x80;
|
||||
ctx->r[5] = 8;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7F;
|
||||
ctx->r[5] = 7;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x80);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHL_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shl(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x00FF;
|
||||
ctx->r[5] = 8;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFF00);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFF;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFE);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x8000;
|
||||
ctx->r[5] = 16;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFF;
|
||||
ctx->r[5] = 15;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x8000);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHL_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shl(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x0000FFFF;
|
||||
ctx->r[5] = 16;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFF0000);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFF;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFE);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x80000000;
|
||||
ctx->r[5] = 32;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x80000000);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFF;
|
||||
ctx->r[5] = 31;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x80000000);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHL_I64", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.Shl(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x00000000FFFFFFFFull;
|
||||
ctx->r[5] = 32;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFF00000000ull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFFFFFFFFFFull;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFFFFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFFFFFFFFFFull;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFFFFFFFFFEull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x8000000000000000ull;
|
||||
ctx->r[5] = 64;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x8000000000000000ull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFFFFFFFFFFull;
|
||||
ctx->r[5] = 63;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x8000000000000000ull);
|
||||
});
|
||||
}
|
||||
278
src/xenia/cpu/testing/shr_test.cc
Normal file
278
src/xenia/cpu/testing/shr_test.cc
Normal file
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("SHR_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT8_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xF0;
|
||||
ctx->r[5] = 4;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x0F);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x7F);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x80;
|
||||
ctx->r[5] = 8;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7F;
|
||||
ctx->r[5] = 7;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint8_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHR_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT16_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFF00;
|
||||
ctx->r[5] = 8;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x00FF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFE;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x7FFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x8000;
|
||||
ctx->r[5] = 16;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFF;
|
||||
ctx->r[5] = 15;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint16_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHR_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.ZeroExtend(b.Shr(b.Truncate(LoadGPR(b, 4), INT32_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)),
|
||||
INT64_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFF0000;
|
||||
ctx->r[5] = 16;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x0000FFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFF;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFE;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x7FFFFFFF);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x80000000;
|
||||
ctx->r[5] = 32;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x80000000);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFF;
|
||||
ctx->r[5] = 31;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint32_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHR_I64", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreGPR(b, 3, b.Shr(b.Truncate(LoadGPR(b, 4), INT64_TYPE),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFF00000000ull;
|
||||
ctx->r[5] = 32;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x00000000FFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFFFFFFFFFFull;
|
||||
ctx->r[5] = 0;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0xFFFFFFFFFFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0xFFFFFFFFFFFFFFFEull;
|
||||
ctx->r[5] = 1;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x7FFFFFFFFFFFFFFFull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x8000000000000000ull;
|
||||
ctx->r[5] = 64;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0x8000000000000000ull);
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[4] = 0x7FFFFFFFFFFFFFFFull;
|
||||
ctx->r[5] = 63;
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = static_cast<uint64_t>(ctx->r[3]);
|
||||
REQUIRE(result == 0);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("SHR_V128", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Shr(LoadVR(b, 4), b.Truncate(LoadGPR(b, 1), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[1] = 0;
|
||||
ctx->v[4] = vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[1] = 1;
|
||||
ctx->v[4] = vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[1] = 2;
|
||||
ctx->v[4] = vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0x3FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->r[1] = 8;
|
||||
ctx->v[4] = vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF));
|
||||
});
|
||||
}
|
||||
49
src/xenia/cpu/testing/swizzle_test.cc
Normal file
49
src/xenia/cpu/testing/swizzle_test.cc
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("SWIZZLE_V128", "[instr]") {
|
||||
TestFunction([](HIRBuilder& b) {
|
||||
StoreVR(b, 3,
|
||||
b.Swizzle(LoadVR(b, 4), INT32_TYPE, SWIZZLE_MASK(0, 1, 2, 3)));
|
||||
b.Return();
|
||||
})
|
||||
.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0, 1, 2, 3); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 1, 2, 3));
|
||||
});
|
||||
TestFunction([](HIRBuilder& b) {
|
||||
StoreVR(b, 3,
|
||||
b.Swizzle(LoadVR(b, 4), INT32_TYPE, SWIZZLE_MASK(3, 2, 1, 0)));
|
||||
b.Return();
|
||||
})
|
||||
.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0, 1, 2, 3); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(3, 2, 1, 0));
|
||||
});
|
||||
TestFunction([](HIRBuilder& b) {
|
||||
StoreVR(b, 3,
|
||||
b.Swizzle(LoadVR(b, 4), INT32_TYPE, SWIZZLE_MASK(1, 1, 2, 2)));
|
||||
b.Return();
|
||||
})
|
||||
.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0, 1, 2, 3); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(1, 1, 2, 2));
|
||||
});
|
||||
}
|
||||
166
src/xenia/cpu/testing/unpack_test.cc
Normal file
166
src/xenia/cpu/testing/unpack_test.cc
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("UNPACK_D3DCOLOR", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Unpack(LoadVR(b, 4), PACK_TYPE_D3DCOLOR));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
uint32_t value = 0;
|
||||
ctx->v[4] = vec128i(0, 0, 0, value);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128f(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
uint32_t value = 0x80506070;
|
||||
ctx->v[4] = vec128i(0, 0, 0, value);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x3F800050, 0x3F800060, 0x3F800070, 0x3F800080));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("UNPACK_FLOAT16_2", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Unpack(LoadVR(b, 4), PACK_TYPE_FLOAT16_2));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 0, 0, 0x3F800000));
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0, 0, 0, 0x7FFFFFFF); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x47FFE000, 0xC7FFE000, 0x00000000, 0x3F800000));
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0, 0, 0, 0x55556666); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x42AAA000, 0x44CCC000, 0x00000000, 0x3F800000));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("UNPACK_FLOAT16_4", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Unpack(LoadVR(b, 4), PACK_TYPE_FLOAT16_4));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0, 0, 0, 0, 0x64D2, 0x6D8B, 0x4881, 0x4491);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x449A4000, 0x45B16000, 0x41102000, 0x40922000));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("UNPACK_SHORT_2", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Unpack(LoadVR(b, 4), PACK_TYPE_SHORT_2));
|
||||
b.Return();
|
||||
});
|
||||
test.Run([](PPCContext* ctx) { ctx->v[4] = vec128i(0); },
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x40400000, 0x40400000, 0x00000000, 0x3F800000));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x7004FD60, 0x8201C990, 0x00000000, 0x7FFF8001);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x40407FFF, 0x403F8001, 0x00000000, 0x3F800000));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 0, 0, (0x1234u << 16) | 0x5678u);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x40401234, 0x40405678, 0x00000000, 0x3F800000));
|
||||
});
|
||||
}
|
||||
|
||||
// TEST_CASE("UNPACK_S8_IN_16_LO", "[instr]") {
|
||||
// TestFunction test([](HIRBuilder& b) {
|
||||
// StoreVR(b, 3, b.Unpack(LoadVR(b, 4), PACK_TYPE_S8_IN_16_LO));
|
||||
// b.Return();
|
||||
// });
|
||||
// test.Run([](PPCContext* ctx) { ctx->v[4] = vec128b(0); },
|
||||
// [](PPCContext* ctx) {
|
||||
// auto result = ctx->v[3];
|
||||
// REQUIRE(result == vec128b(0));
|
||||
// });
|
||||
//}
|
||||
//
|
||||
// TEST_CASE("UNPACK_S8_IN_16_HI", "[instr]") {
|
||||
// TestFunction test([](HIRBuilder& b) {
|
||||
// StoreVR(b, 3, b.Unpack(LoadVR(b, 4), PACK_TYPE_S8_IN_16_HI));
|
||||
// b.Return();
|
||||
// });
|
||||
// test.Run([](PPCContext* ctx) { ctx->v[4] = vec128b(0); },
|
||||
// [](PPCContext* ctx) {
|
||||
// auto result = ctx->v[3];
|
||||
// REQUIRE(result == vec128b(0));
|
||||
// });
|
||||
//}
|
||||
//
|
||||
// TEST_CASE("UNPACK_S16_IN_32_LO", "[instr]") {
|
||||
// TestFunction test([](HIRBuilder& b) {
|
||||
// StoreVR(b, 3, b.Unpack(LoadVR(b, 4), PACK_TYPE_S16_IN_32_LO));
|
||||
// b.Return();
|
||||
// });
|
||||
// test.Run([](PPCContext* ctx) { ctx->v[4] = vec128b(0); },
|
||||
// [](PPCContext* ctx) {
|
||||
// auto result = ctx->v[3];
|
||||
// REQUIRE(result == vec128b(0));
|
||||
// });
|
||||
//}
|
||||
//
|
||||
// TEST_CASE("UNPACK_S16_IN_32_HI", "[instr]") {
|
||||
// TestFunction test([](HIRBuilder& b) {
|
||||
// StoreVR(b, 3, b.Unpack(LoadVR(b, 4), PACK_TYPE_S16_IN_32_HI));
|
||||
// b.Return();
|
||||
// });
|
||||
// test.Run([](PPCContext* ctx) { ctx->v[4] = vec128b(0); },
|
||||
// [](PPCContext* ctx) {
|
||||
// auto result = ctx->v[3];
|
||||
// REQUIRE(result == vec128b(0));
|
||||
// });
|
||||
//}
|
||||
118
src/xenia/cpu/testing/util.h
Normal file
118
src/xenia/cpu/testing/util.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_TESTING_UTIL_H_
|
||||
#define XENIA_TESTING_UTIL_H_
|
||||
|
||||
#include "xenia/base/main.h"
|
||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||
#include "xenia/cpu/frontend/ppc_context.h"
|
||||
#include "xenia/cpu/frontend/ppc_frontend.h"
|
||||
#include "xenia/cpu/hir/hir_builder.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/cpu/test_module.h"
|
||||
|
||||
#include "third_party/catch/single_include/catch.hpp"
|
||||
|
||||
#define XENIA_TEST_X64 1
|
||||
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
namespace testing {
|
||||
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
class TestFunction {
|
||||
public:
|
||||
TestFunction(std::function<void(hir::HIRBuilder& b)> generator) {
|
||||
memory_size = 16 * 1024 * 1024;
|
||||
memory.reset(new Memory());
|
||||
memory->Initialize();
|
||||
|
||||
#if XENIA_TEST_X64
|
||||
{
|
||||
auto processor =
|
||||
std::make_unique<Processor>(memory.get(), nullptr, nullptr);
|
||||
processor->Setup();
|
||||
processors.emplace_back(std::move(processor));
|
||||
}
|
||||
#endif // XENIA_TEST_X64
|
||||
|
||||
for (auto& processor : processors) {
|
||||
auto module = std::make_unique<xe::cpu::TestModule>(
|
||||
processor.get(), "Test",
|
||||
[](uint64_t address) { return address == 0x80000000; },
|
||||
[generator](hir::HIRBuilder& b) {
|
||||
generator(b);
|
||||
return true;
|
||||
});
|
||||
processor->AddModule(std::move(module));
|
||||
processor->backend()->CommitExecutableRange(0x80000000, 0x80010000);
|
||||
}
|
||||
}
|
||||
|
||||
~TestFunction() {
|
||||
processors.clear();
|
||||
memory.reset();
|
||||
}
|
||||
|
||||
void Run(std::function<void(PPCContext*)> pre_call,
|
||||
std::function<void(PPCContext*)> post_call) {
|
||||
for (auto& processor : processors) {
|
||||
xe::cpu::Function* fn;
|
||||
processor->ResolveFunction(0x80000000, &fn);
|
||||
|
||||
uint32_t stack_size = 64 * 1024;
|
||||
uint32_t stack_address = memory_size - stack_size;
|
||||
uint32_t thread_state_address = stack_address - 0x1000;
|
||||
auto thread_state = std::make_unique<ThreadState>(
|
||||
processor.get(), 0x100, ThreadStackType::kUserStack, stack_address,
|
||||
stack_size, thread_state_address);
|
||||
auto ctx = thread_state->context();
|
||||
ctx->lr = 0xBCBCBCBC;
|
||||
|
||||
pre_call(ctx);
|
||||
|
||||
fn->Call(thread_state.get(), uint32_t(ctx->lr));
|
||||
|
||||
post_call(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t memory_size;
|
||||
std::unique_ptr<Memory> memory;
|
||||
std::vector<std::unique_ptr<Processor>> processors;
|
||||
};
|
||||
|
||||
inline hir::Value* LoadGPR(hir::HIRBuilder& b, int reg) {
|
||||
return b.LoadContext(offsetof(PPCContext, r) + reg * 8, hir::INT64_TYPE);
|
||||
}
|
||||
inline void StoreGPR(hir::HIRBuilder& b, int reg, hir::Value* value) {
|
||||
b.StoreContext(offsetof(PPCContext, r) + reg * 8, value);
|
||||
}
|
||||
|
||||
inline hir::Value* LoadFPR(hir::HIRBuilder& b, int reg) {
|
||||
return b.LoadContext(offsetof(PPCContext, f) + reg * 8, hir::FLOAT64_TYPE);
|
||||
}
|
||||
inline void StoreFPR(hir::HIRBuilder& b, int reg, hir::Value* value) {
|
||||
b.StoreContext(offsetof(PPCContext, f) + reg * 8, value);
|
||||
}
|
||||
|
||||
inline hir::Value* LoadVR(hir::HIRBuilder& b, int reg) {
|
||||
return b.LoadContext(offsetof(PPCContext, v) + reg * 16, hir::VEC128_TYPE);
|
||||
}
|
||||
inline void StoreVR(hir::HIRBuilder& b, int reg, hir::Value* value) {
|
||||
b.StoreContext(offsetof(PPCContext, v) + reg * 16, value);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_TESTING_UTIL_H_
|
||||
305
src/xenia/cpu/testing/vector_add_test.cc
Normal file
305
src/xenia/cpu/testing/vector_add_test.cc
Normal file
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[5] =
|
||||
vec128b(100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(100, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22,
|
||||
24, 26, 28, 30));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(UINT8_MAX);
|
||||
ctx->v[5] = vec128b(1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I8_SAT_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_SATURATE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(INT8_MAX);
|
||||
ctx->v[5] = vec128b(1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(INT8_MAX));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(INT8_MIN);
|
||||
ctx->v[5] = vec128b(-1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(INT8_MIN));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I8_SAT_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_SATURATE | ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(UINT8_MAX);
|
||||
ctx->v[5] = vec128b(1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(UINT8_MAX));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, 6, 7);
|
||||
ctx->v[5] = vec128s(100, 1, 2, 3, 4, 5, 6, 7);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(100, 2, 4, 6, 8, 10, 12, 14));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(UINT16_MAX);
|
||||
ctx->v[5] = vec128s(1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0);
|
||||
ctx->v[5] = vec128s(-1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(UINT16_MAX));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I16_SAT_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_SATURATE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(INT16_MAX);
|
||||
ctx->v[5] = vec128s(1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(INT16_MAX));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(INT16_MIN);
|
||||
ctx->v[5] = vec128s(-1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(INT16_MIN));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I16_SAT_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_SATURATE | ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(UINT16_MAX);
|
||||
ctx->v[5] = vec128s(1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(UINT16_MAX));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 2, 3);
|
||||
ctx->v[5] = vec128i(100, 1, 2, 3);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(100, 2, 4, 6));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(UINT32_MAX);
|
||||
ctx->v[5] = vec128i(1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0);
|
||||
ctx->v[5] = vec128i(-1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(UINT32_MAX));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I32_SAT_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_SATURATE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(5);
|
||||
ctx->v[5] = vec128i(5);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(10));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(INT32_MAX);
|
||||
ctx->v[5] = vec128i(1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(INT32_MAX));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(INT32_MIN);
|
||||
ctx->v[5] = vec128i(-1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(INT32_MIN));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ADD_I32_SAT_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_SATURATE | ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(5);
|
||||
ctx->v[5] = vec128i(5);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(10));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(UINT32_MAX);
|
||||
ctx->v[5] = vec128i(1);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(UINT32_MAX));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ADD_F32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorAdd(LoadVR(b, 4), LoadVR(b, 5), FLOAT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128f(0.12f, 0.34f, 0.56f, 0.78f);
|
||||
ctx->v[5] = vec128f(0.12f, 0.34f, 0.56f, 0.78f);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x3E75C28F, 0x3F2E147B, 0x3F8F5C29, 0x3FC7AE14));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128f(FLT_MAX);
|
||||
ctx->v[5] = vec128f(FLT_MAX);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0x7F800000));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128f(-FLT_MIN);
|
||||
ctx->v[5] = vec128f(-1.0f);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0xBF800000));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128f(FLT_MAX);
|
||||
ctx->v[5] = vec128f(1.0f);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0x7F7FFFFF));
|
||||
});
|
||||
}
|
||||
123
src/xenia/cpu/testing/vector_max_test.cc
Normal file
123
src/xenia/cpu/testing/vector_max_test.cc
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_MAX_I8_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[5] = vec128b(-100, 1, 100, -3, 4, -5, 60, 7, -80, 9, 10,
|
||||
INT8_MIN, INT8_MAX, 13, 2, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0, 1, 100, 3, 4, 5, 60, 7, 8, 9, 10, 11,
|
||||
INT8_MAX, 13, 14, 15));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MAX_I8_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[5] = vec128b(-100, 1, 100, -3, 4, -5, 60, 7, -80, 9, 10,
|
||||
INT8_MIN, INT8_MAX, 13, 2, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(-100, 1, 100, -3, 4, -5, 60, 7, -80, 9, 10,
|
||||
INT8_MIN, INT8_MAX, 13, 14, 15));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MAX_I16_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, -6000, 7);
|
||||
ctx->v[5] = vec128s(-1000, 1, -2000, 3, 4, SHRT_MAX, 6, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0, 1, 2, 3, 4, SHRT_MAX, 6, 7));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MAX_I16_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, -6000, 7);
|
||||
ctx->v[5] = vec128s(-1000, 1, -2000, 3, 4, USHRT_MAX, 6, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(-1000, 1, -2000, 3, 4, USHRT_MAX, -6000, 7));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MAX_I32_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 123, 3);
|
||||
ctx->v[5] = vec128i(-1000000, 0, INT_MAX, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 1, INT_MAX, 3));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MAX_I32_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMax(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 123, 3);
|
||||
ctx->v[5] = vec128i(-1000000, 0, UINT_MAX, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(-1000000, 1, UINT_MAX, 3));
|
||||
});
|
||||
}
|
||||
123
src/xenia/cpu/testing/vector_min_test.cc
Normal file
123
src/xenia/cpu/testing/vector_min_test.cc
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_MIN_I8_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[5] = vec128b(-100, 1, 100, -3, 4, -5, 60, 7, -80, 9, 10,
|
||||
INT8_MIN, INT8_MAX, 13, 2, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(-100, 1, 2, -3, 4, -5, 6, 7, -80, 9, 10,
|
||||
INT8_MIN, 12, 13, 2, 0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MIN_I8_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
ctx->v[5] = vec128b(255, 1, 200, -3, 4, -5, 60, 7, -80, 9, 10, 11, 12,
|
||||
13, 2, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 2, 0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MIN_I16_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, -6000, 7);
|
||||
ctx->v[5] = vec128s(-1000, 1, -2000, 3, 4, SHRT_MAX, 6, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(-1000, 1, -2000, 3, 4, 5, -6000, 0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MIN_I16_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0, 1, 2, 3, 4, 5, -6000, 7);
|
||||
ctx->v[5] = vec128s(-1000, 1, -2000, 3, 4, USHRT_MAX, 6, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0, 1, 2, 3, 4, 5, 6, 0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MIN_I32_SIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 123, 3);
|
||||
ctx->v[5] = vec128i(-1000000, 0, INT_MAX, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(-1000000, 0, 123, 0));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_MIN_I32_UNSIGNED", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorMin(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE,
|
||||
ARITHMETIC_UNSIGNED));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0, 1, 123, 3);
|
||||
ctx->v[5] = vec128i(-1000000, 0, UINT_MAX, 0);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 0, 123, 0));
|
||||
});
|
||||
}
|
||||
72
src/xenia/cpu/testing/vector_rotate_left_test.cc
Normal file
72
src/xenia/cpu/testing/vector_rotate_left_test.cc
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "third_party/xbyak/xbyak/xbyak_bin2hex.h"
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_ROTATE_LEFT_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorRotateLeft(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(B00000001);
|
||||
ctx->v[5] =
|
||||
vec128b(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(B00000001, B00000010, B00000100, B00001000,
|
||||
B00010000, B00100000, B01000000, B10000000,
|
||||
B00000001, B00000010, B00000100, B00001000,
|
||||
B00010000, B00100000, B01000000, B10000000));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ROTATE_LEFT_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorRotateLeft(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0x0001, 0x0001, 0x0001, 0x0001, 0x1000, 0x1000,
|
||||
0x1000, 0x1000);
|
||||
ctx->v[5] = vec128s(0, 1, 2, 3, 14, 15, 16, 17);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0x0001, 0x0002, 0x0004, 0x0008, 0x0400,
|
||||
0x0800, 0x1000, 0x2000));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_ROTATE_LEFT_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorRotateLeft(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x00000001, 0x00000001, 0x80000000, 0x80000000);
|
||||
ctx->v[5] = vec128i(0, 1, 1, 2);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x00000001, 0x00000002, 0x00000001, 0x00000002));
|
||||
});
|
||||
}
|
||||
146
src/xenia/cpu/testing/vector_sha_test.cc
Normal file
146
src/xenia/cpu/testing/vector_sha_test.cc
Normal file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(0x7E, 0x7E, 0x7E, 0x7F, 0x80, 0xFF, 0x01, 0x12,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
ctx->v[5] =
|
||||
vec128b(0, 1, 2, 8, 4, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0x7E, 0x3F, 0x1F, 0x7F, 0xF8, 0xFF, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I8_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), b.LoadConstantVec128(vec128b(
|
||||
0, 1, 2, 8, 4, 4, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15)),
|
||||
INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(0x7E, 0x7E, 0x7E, 0x7F, 0x80, 0xFF, 0x01, 0x12,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0x7E, 0x3F, 0x1F, 0x7F, 0xF8, 0xFF, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0x7FFE, 0x7FFE, 0x7FFE, 0x7FFF, 0x8000, 0xFFFF,
|
||||
0x0001, 0x1234);
|
||||
ctx->v[5] = vec128s(0, 1, 8, 15, 15, 8, 1, 16);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0x7FFE, 0x3FFF, 0x007F, 0x0000, 0xFFFF,
|
||||
0xFFFF, 0x0000, 0x1234));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I16_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), b.LoadConstantVec128(vec128s(
|
||||
0, 1, 8, 15, 15, 8, 1, 16)),
|
||||
INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0x7FFE, 0x7FFE, 0x7FFE, 0x7FFF, 0x8000, 0xFFFF,
|
||||
0x0001, 0x1234);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0x7FFE, 0x3FFF, 0x007F, 0x0000, 0xFFFF,
|
||||
0xFFFF, 0x0000, 0x1234));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFF);
|
||||
ctx->v[5] = vec128i(0, 1, 16, 31);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x7FFFFFFE, 0x3FFFFFFF, 0x00007FFF, 0x00000000));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x80000000, 0xFFFFFFFF, 0x00000001, 0x12345678);
|
||||
ctx->v[5] = vec128i(31, 16, 1, 32);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x12345678));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I32_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(b, 4, b.VectorSha(LoadVR(b, 5),
|
||||
b.LoadConstantVec128(vec128i(31, 16, 1, 32)),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFF);
|
||||
ctx->v[5] = vec128i(0x80000000, 0xFFFFFFFF, 0x00000001, 0x12345678);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0x7FFFFFFE, 0x3FFFFFFF, 0x00007FFF, 0x00000000));
|
||||
auto result2 = ctx->v[4];
|
||||
REQUIRE(result2 ==
|
||||
vec128i(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x12345678));
|
||||
});
|
||||
}
|
||||
146
src/xenia/cpu/testing/vector_shl_test.cc
Normal file
146
src/xenia/cpu/testing/vector_shl_test.cc
Normal file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(0x7E, 0x7E, 0x7E, 0x7F, 0x80, 0xFF, 0x01, 0x12,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
ctx->v[5] =
|
||||
vec128b(0, 1, 2, 8, 4, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0x7E, 0xFC, 0xF8, 0x7F, 0x00, 0xF0, 0x40,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I8_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), b.LoadConstantVec128(vec128b(
|
||||
0, 1, 2, 8, 4, 4, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15)),
|
||||
INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(0x7E, 0x7E, 0x7E, 0x7F, 0x80, 0xFF, 0x01, 0x12,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0x7E, 0xFC, 0xF8, 0x7F, 0x00, 0xF0, 0x40,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0x7FFE, 0x7FFE, 0x7FFE, 0x7FFF, 0x8000, 0xFFFF,
|
||||
0x0001, 0x1234);
|
||||
ctx->v[5] = vec128s(0, 1, 8, 15, 15, 8, 1, 16);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0x7FFE, 0xFFFC, 0xFE00, 0x8000, 0x0000,
|
||||
0xFF00, 0x0002, 0x1234));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I16_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), b.LoadConstantVec128(vec128s(
|
||||
0, 1, 8, 15, 15, 8, 1, 16)),
|
||||
INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0x7FFE, 0x7FFE, 0x7FFE, 0x7FFF, 0x8000, 0xFFFF,
|
||||
0x0001, 0x1234);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0x7FFE, 0xFFFC, 0xFE00, 0x8000, 0x0000,
|
||||
0xFF00, 0x0002, 0x1234));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFF);
|
||||
ctx->v[5] = vec128i(0, 1, 16, 31);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x7FFFFFFE, 0xFFFFFFFC, 0xFFFE0000, 0x80000000));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x80000000, 0xFFFFFFFF, 0x00000001, 0x12345678);
|
||||
ctx->v[5] = vec128i(31, 16, 1, 32);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x00000000, 0xFFFF0000, 0x00000002, 0x12345678));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I32_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(b, 4, b.VectorShl(LoadVR(b, 5),
|
||||
b.LoadConstantVec128(vec128i(31, 16, 1, 32)),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFF);
|
||||
ctx->v[5] = vec128i(0x80000000, 0xFFFFFFFF, 0x00000001, 0x12345678);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0x7FFFFFFE, 0xFFFFFFFC, 0xFFFE0000, 0x80000000));
|
||||
auto result2 = ctx->v[4];
|
||||
REQUIRE(result2 ==
|
||||
vec128i(0x00000000, 0xFFFF0000, 0x00000002, 0x12345678));
|
||||
});
|
||||
}
|
||||
146
src/xenia/cpu/testing/vector_shr_test.cc
Normal file
146
src/xenia/cpu/testing/vector_shr_test.cc
Normal file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/cpu/testing/util.h"
|
||||
|
||||
using namespace xe;
|
||||
using namespace xe::cpu;
|
||||
using namespace xe::cpu::hir;
|
||||
using namespace xe::cpu::testing;
|
||||
using xe::cpu::frontend::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I8", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), LoadVR(b, 5), INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(0x7E, 0x7E, 0x7E, 0x7F, 0x80, 0xFF, 0x01, 0x12,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
ctx->v[5] =
|
||||
vec128b(0, 1, 2, 8, 4, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0x7E, 0x3F, 0x1F, 0x7F, 0x08, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I8_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), b.LoadConstantVec128(vec128b(
|
||||
0, 1, 2, 8, 4, 4, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 14, 15)),
|
||||
INT8_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128b(0x7E, 0x7E, 0x7E, 0x7F, 0x80, 0xFF, 0x01, 0x12,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128b(0x7E, 0x3F, 0x1F, 0x7F, 0x08, 0x0F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I16", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), LoadVR(b, 5), INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0x7FFE, 0x7FFE, 0x7FFE, 0x7FFF, 0x8000, 0xFFFF,
|
||||
0x0001, 0x1234);
|
||||
ctx->v[5] = vec128s(0, 1, 8, 15, 15, 8, 1, 16);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0x7FFE, 0x3FFF, 0x007F, 0x0000, 0x0001,
|
||||
0x00FF, 0x0000, 0x1234));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I16_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), b.LoadConstantVec128(vec128s(
|
||||
0, 1, 8, 15, 15, 8, 1, 16)),
|
||||
INT16_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128s(0x7FFE, 0x7FFE, 0x7FFE, 0x7FFF, 0x8000, 0xFFFF,
|
||||
0x0001, 0x1234);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128s(0x7FFE, 0x3FFF, 0x007F, 0x0000, 0x0001,
|
||||
0x00FF, 0x0000, 0x1234));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I32", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), LoadVR(b, 5), INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFF);
|
||||
ctx->v[5] = vec128i(0, 1, 16, 31);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x7FFFFFFE, 0x3FFFFFFF, 0x00007FFF, 0x00000000));
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x80000000, 0xFFFFFFFF, 0x00000001, 0x12345678);
|
||||
ctx->v[5] = vec128i(31, 16, 1, 32);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result ==
|
||||
vec128i(0x00000001, 0x0000FFFF, 0x00000000, 0x12345678));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I32_CONSTANT", "[instr]") {
|
||||
TestFunction test([](HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4),
|
||||
b.LoadConstantVec128(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(b, 4, b.VectorShr(LoadVR(b, 5),
|
||||
b.LoadConstantVec128(vec128i(31, 16, 1, 32)),
|
||||
INT32_TYPE));
|
||||
b.Return();
|
||||
});
|
||||
test.Run(
|
||||
[](PPCContext* ctx) {
|
||||
ctx->v[4] = vec128i(0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFE, 0x7FFFFFFF);
|
||||
ctx->v[5] = vec128i(0x80000000, 0xFFFFFFFF, 0x00000001, 0x12345678);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result1 = ctx->v[3];
|
||||
REQUIRE(result1 ==
|
||||
vec128i(0x7FFFFFFE, 0x3FFFFFFF, 0x00007FFF, 0x00000000));
|
||||
auto result2 = ctx->v[4];
|
||||
REQUIRE(result2 ==
|
||||
vec128i(0x00000001, 0x0000FFFF, 0x00000000, 0x12345678));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user