Swapping around vec128 to match AVX order.
Was really hoping all this would fix some bugs, but no luck :(
This commit is contained in:
parent
8ca7642226
commit
f74aafeb8a
File diff suppressed because it is too large
Load Diff
|
@ -41,6 +41,7 @@ using alloy::runtime::ThreadState;
|
|||
static const size_t MAX_CODE_SIZE = 1 * 1024 * 1024;
|
||||
|
||||
static const size_t STASH_OFFSET = 32;
|
||||
static const size_t STASH_OFFSET_HIGH = 32 + 16;
|
||||
|
||||
// If we are running with tracing on we have to store the EFLAGS in the stack,
|
||||
// otherwise our calls out to C to print will clear it before DID_CARRY/etc
|
||||
|
@ -786,8 +787,8 @@ void X64Emitter::MovMem64(const RegExp& addr, uint64_t v) {
|
|||
|
||||
Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
||||
static const vec128_t xmm_consts[] = {
|
||||
/* XMMZero */ vec128f(0.0f, 0.0f, 0.0f, 0.0f),
|
||||
/* XMMOne */ vec128f(1.0f, 1.0f, 1.0f, 1.0f),
|
||||
/* XMMZero */ vec128f(0.0f),
|
||||
/* XMMOne */ vec128f(1.0f),
|
||||
/* XMMNegativeOne */ vec128f(-1.0f, -1.0f, -1.0f, -1.0f),
|
||||
/* XMMMaskX16Y16 */ vec128i(0x0000FFFFu, 0xFFFF0000u,
|
||||
0x00000000u, 0x00000000u),
|
||||
|
@ -808,14 +809,24 @@ Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
|||
0xFFFFFFFFu, 0x7FFFFFFFu),
|
||||
/* XMMByteSwapMask */ vec128i(0x00010203u, 0x04050607u,
|
||||
0x08090A0Bu, 0x0C0D0E0Fu),
|
||||
/* XMMPermuteControl15 */ vec128b(15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15),
|
||||
/* XMMPermuteControl15 */ vec128b(15),
|
||||
/* XMMPackD3DCOLOR */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0xFFFFFFFFu, 0x0C000408u),
|
||||
/* XMMUnpackD3DCOLOR */ vec128i(0xFFFFFF0Eu, 0xFFFFFF0Du,
|
||||
0xFFFFFF0Cu, 0xFFFFFF0Fu),
|
||||
/* XMMOneOver255 */ vec128f(1.0f / 255.0f, 1.0f / 255.0f,
|
||||
1.0f / 255.0f, 1.0f / 255.0f),
|
||||
/* XMMPackFLOAT16_2 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0xFFFFFFFFu, 0x01000302u),
|
||||
/* XMMUnpackFLOAT16_2 */ vec128i(0x0D0C0F0Eu, 0xFFFFFFFFu,
|
||||
0xFFFFFFFFu, 0xFFFFFFFFu),
|
||||
/* XMMPackFLOAT16_4 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0x05040706u, 0x01000302u),
|
||||
/* XMMUnpackFLOAT16_4 */ vec128i(0x09080B0Au, 0x0D0C0F0Eu,
|
||||
0xFFFFFFFFu, 0xFFFFFFFFu),
|
||||
/* XMMPackSHORT_2 */ vec128i(0xFFFFFFFFu, 0xFFFFFFFFu,
|
||||
0xFFFFFFFFu, 0x01000504u),
|
||||
/* XMMUnpackSHORT_2 */ vec128i(0xFFFF0F0Eu, 0xFFFF0D0Cu,
|
||||
0xFFFFFFFFu, 0xFFFFFFFFu),
|
||||
/* XMMOneOver255 */ vec128f(1.0f / 255.0f),
|
||||
/* XMMMaskEvenPI16 */ vec128i(0x0000FFFFu, 0x0000FFFFu,
|
||||
0x0000FFFFu, 0x0000FFFFu),
|
||||
/* XMMShiftMaskEvenPI16 */ vec128i(0x0000000Fu, 0x0000000Fu,
|
||||
|
@ -826,8 +837,8 @@ Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
|||
0x000000FFu, 0x000000FFu),
|
||||
/* XMMUnsignedDwordMax */ vec128i(0xFFFFFFFFu, 0x00000000u,
|
||||
0xFFFFFFFFu, 0x00000000u),
|
||||
/* XMM255 */ vec128f(255.0f, 255.0f, 255.0f, 255.0f),
|
||||
/* XMMPI32 */ vec128i(32, 32, 32, 32),
|
||||
/* XMM255 */ vec128f(255.0f),
|
||||
/* XMMPI32 */ vec128i(32),
|
||||
/* XMMSignMaskI8 */ vec128i(0x80808080u, 0x80808080u,
|
||||
0x80808080u, 0x80808080u),
|
||||
/* XMMSignMaskI16 */ vec128i(0x80008000u, 0x80008000u,
|
||||
|
@ -836,6 +847,8 @@ Address X64Emitter::GetXmmConstPtr(XmmConst id) {
|
|||
0x80000000u, 0x80000000u),
|
||||
/* XMMSignMaskF32 */ vec128i(0x80000000u, 0x80000000u,
|
||||
0x80000000u, 0x80000000u),
|
||||
/* XMMShortMinPS */ vec128f(SHRT_MIN),
|
||||
/* XMMShortMaxPS */ vec128f(SHRT_MAX),
|
||||
};
|
||||
// TODO(benvanik): cache base pointer somewhere? stack? It'd be nice to
|
||||
// prevent this move.
|
||||
|
@ -901,19 +914,12 @@ void X64Emitter::LoadConstantXmm(Xbyak::Xmm dest, double v) {
|
|||
}
|
||||
}
|
||||
|
||||
Address X64Emitter::StashXmm(const Xmm& r) {
|
||||
auto addr = ptr[rsp + STASH_OFFSET];
|
||||
Address X64Emitter::StashXmm(int index, const Xmm& r) {
|
||||
auto addr = ptr[rsp + STASH_OFFSET + (index * 16)];
|
||||
vmovups(addr, r);
|
||||
return addr;
|
||||
}
|
||||
|
||||
Address X64Emitter::StashXmm(const vec128_t& v) {
|
||||
auto addr = ptr[rsp + STASH_OFFSET];
|
||||
LoadConstantXmm(xmm0, v);
|
||||
vmovups(addr, xmm0);
|
||||
return addr;
|
||||
}
|
||||
|
||||
} // namespace x64
|
||||
} // namespace backend
|
||||
} // namespace alloy
|
||||
|
|
|
@ -56,6 +56,12 @@ enum XmmConst {
|
|||
XMMPermuteControl15,
|
||||
XMMPackD3DCOLOR,
|
||||
XMMUnpackD3DCOLOR,
|
||||
XMMPackFLOAT16_2,
|
||||
XMMUnpackFLOAT16_2,
|
||||
XMMPackFLOAT16_4,
|
||||
XMMUnpackFLOAT16_4,
|
||||
XMMPackSHORT_2,
|
||||
XMMUnpackSHORT_2,
|
||||
XMMOneOver255,
|
||||
XMMMaskEvenPI16,
|
||||
XMMShiftMaskEvenPI16,
|
||||
|
@ -68,6 +74,8 @@ enum XmmConst {
|
|||
XMMSignMaskI16,
|
||||
XMMSignMaskI32,
|
||||
XMMSignMaskF32,
|
||||
XMMShortMinPS,
|
||||
XMMShortMaxPS,
|
||||
};
|
||||
|
||||
// Unfortunately due to the design of xbyak we have to pass this to the ctor.
|
||||
|
@ -158,8 +166,7 @@ class X64Emitter : public Xbyak::CodeGenerator {
|
|||
void LoadConstantXmm(Xbyak::Xmm dest, float v);
|
||||
void LoadConstantXmm(Xbyak::Xmm dest, double v);
|
||||
void LoadConstantXmm(Xbyak::Xmm dest, const vec128_t& v);
|
||||
Xbyak::Address StashXmm(const Xbyak::Xmm& r);
|
||||
Xbyak::Address StashXmm(const vec128_t& v);
|
||||
Xbyak::Address StashXmm(int index, const Xbyak::Xmm& r);
|
||||
|
||||
size_t stack_size() const { return stack_size_; }
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,6 +28,7 @@ Value* CalculateEA_0(PPCHIRBuilder& f, uint32_t ra, uint32_t rb);
|
|||
// Most of this file comes from:
|
||||
// http://biallas.net/doc/vmx128/vmx128.txt
|
||||
// https://github.com/kakaroto/ps3ida/blob/master/plugins/PPCAltivec/src/main.cpp
|
||||
// http://sannybuilder.com/forums/viewtopic.php?id=190
|
||||
|
||||
#define OP(x) ((((uint32_t)(x)) & 0x3f) << 26)
|
||||
#define VX128(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x3d0))
|
||||
|
@ -154,7 +155,7 @@ XEEMITTER(lvxl128, VX128_1(4, 707), VX128_1)(PPCHIRBuilder& f, InstrData& i) {
|
|||
|
||||
XEEMITTER(stvebx, 0x7C00010E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||
Value* el = f.And(ea, f.LoadConstant(0xFull));
|
||||
Value* el = f.And(f.Truncate(ea, INT8_TYPE), f.LoadConstant(uint8_t(0xF)));
|
||||
Value* v = f.Extract(f.LoadVR(i.X.RT), el, INT8_TYPE);
|
||||
f.Store(ea, v);
|
||||
return 0;
|
||||
|
@ -163,7 +164,8 @@ XEEMITTER(stvebx, 0x7C00010E, X)(PPCHIRBuilder& f, InstrData& i) {
|
|||
XEEMITTER(stvehx, 0x7C00014E, X)(PPCHIRBuilder& f, InstrData& i) {
|
||||
Value* ea = CalculateEA_0(f, i.X.RA, i.X.RB);
|
||||
ea = f.And(ea, f.LoadConstant(~0x1ull));
|
||||
Value* el = f.Shr(f.And(ea, f.LoadConstant(0xFull)), 1);
|
||||
Value* el =
|
||||
f.Shr(f.And(f.Truncate(ea, INT8_TYPE), f.LoadConstant(uint8_t(0xF))), 1);
|
||||
Value* v = f.Extract(f.LoadVR(i.X.RT), el, INT16_TYPE);
|
||||
f.Store(ea, f.ByteSwap(v));
|
||||
return 0;
|
||||
|
@ -173,7 +175,8 @@ int InstrEmit_stvewx_(PPCHIRBuilder& f, InstrData& i, uint32_t vd, uint32_t ra,
|
|||
uint32_t rb) {
|
||||
Value* ea = CalculateEA_0(f, ra, rb);
|
||||
ea = f.And(ea, f.LoadConstant(~0x3ull));
|
||||
Value* el = f.Shr(f.And(ea, f.LoadConstant(0xFull)), 2);
|
||||
Value* el =
|
||||
f.Shr(f.And(f.Truncate(ea, INT8_TYPE), f.LoadConstant(uint8_t(0xF))), 2);
|
||||
Value* v = f.Extract(f.LoadVR(vd), el, INT32_TYPE);
|
||||
f.Store(ea, f.ByteSwap(v));
|
||||
return 0;
|
||||
|
@ -239,8 +242,8 @@ int InstrEmit_lvrx_(PPCHIRBuilder& f, InstrData& i, uint32_t vd, uint32_t ra,
|
|||
ea = f.And(ea, f.LoadConstant(~0xFull));
|
||||
// v = (new >> (16 - eb))
|
||||
Value* v = f.Permute(f.LoadVectorShr(f.Sub(f.LoadConstant((int8_t)16), eb)),
|
||||
f.LoadZero(VEC128_TYPE),
|
||||
f.ByteSwap(f.Load(ea, VEC128_TYPE)), INT8_TYPE);
|
||||
f.ByteSwap(f.Load(ea, VEC128_TYPE)),
|
||||
f.LoadZero(VEC128_TYPE), INT8_TYPE);
|
||||
f.StoreVR(vd, v);
|
||||
return 0;
|
||||
}
|
||||
|
@ -935,8 +938,8 @@ int InstrEmit_vmrghw_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
|||
// (VD.y) = (VB.x)
|
||||
// (VD.z) = (VA.y)
|
||||
// (VD.w) = (VB.y)
|
||||
Value* v = f.Permute(f.LoadConstant(0x00040105), f.LoadVR(va), f.LoadVR(vb),
|
||||
INT32_TYPE);
|
||||
Value* v = f.Permute(f.LoadConstant(PERMUTE_MASK(0, 0, 1, 0, 0, 1, 1, 1)),
|
||||
f.LoadVR(va), f.LoadVR(vb), INT32_TYPE);
|
||||
f.StoreVR(vd, v);
|
||||
return 0;
|
||||
}
|
||||
|
@ -962,8 +965,8 @@ int InstrEmit_vmrglw_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb) {
|
|||
// (VD.y) = (VB.z)
|
||||
// (VD.z) = (VA.w)
|
||||
// (VD.w) = (VB.w)
|
||||
Value* v = f.Permute(f.LoadConstant(0x02060307), f.LoadVR(va), f.LoadVR(vb),
|
||||
INT32_TYPE);
|
||||
Value* v = f.Permute(f.LoadConstant(PERMUTE_MASK(0, 2, 1, 2, 0, 3, 1, 3)),
|
||||
f.LoadVR(va), f.LoadVR(vb), INT32_TYPE);
|
||||
f.StoreVR(vd, v);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1140,7 +1143,8 @@ XEEMITTER(vpermwi128, VX128_P(6, 528), VX128_P)(PPCHIRBuilder& f,
|
|||
const uint32_t vd = i.VX128_P.VD128l | (i.VX128_P.VD128h << 5);
|
||||
const uint32_t vb = i.VX128_P.VB128l | (i.VX128_P.VB128h << 5);
|
||||
uint32_t uimm = i.VX128_P.PERMl | (i.VX128_P.PERMh << 5);
|
||||
Value* v = f.Swizzle(f.LoadVR(vb), INT32_TYPE, uimm);
|
||||
uint32_t mask = SWIZZLE_MASK(uimm >> 6, uimm >> 4, uimm >> 2, uimm >> 0);
|
||||
Value* v = f.Swizzle(f.LoadVR(vb), INT32_TYPE, mask);
|
||||
f.StoreVR(vd, v);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1213,14 +1217,16 @@ XEEMITTER(vrfiz128, VX128_3(6, 1008), VX128_3)(PPCHIRBuilder& f, InstrData& i) {
|
|||
|
||||
XEEMITTER(vrlb, 0x10000004, VX)(PPCHIRBuilder& f, InstrData& i) {
|
||||
// (VD) <- ROTL((VA), (VB)&0x3)
|
||||
Value* v = f.VectorRotateLeft(f.LoadVR(i.VX.VA), f.LoadVR(i.VX.VB), INT8_TYPE);
|
||||
Value* v =
|
||||
f.VectorRotateLeft(f.LoadVR(i.VX.VA), f.LoadVR(i.VX.VB), INT8_TYPE);
|
||||
f.StoreVR(i.VX.VD, v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
XEEMITTER(vrlh, 0x10000044, VX)(PPCHIRBuilder& f, InstrData& i) {
|
||||
// (VD) <- ROTL((VA), (VB)&0xF)
|
||||
Value* v = f.VectorRotateLeft(f.LoadVR(i.VX.VA), f.LoadVR(i.VX.VB), INT16_TYPE);
|
||||
Value* v =
|
||||
f.VectorRotateLeft(f.LoadVR(i.VX.VA), f.LoadVR(i.VX.VB), INT16_TYPE);
|
||||
f.StoreVR(i.VX.VD, v);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1244,10 +1250,10 @@ XEEMITTER(vrlimi128, VX128_4(6, 1808), VX128_4)(PPCHIRBuilder& f,
|
|||
const uint32_t vb = i.VX128_4.VB128l | (i.VX128_4.VB128h << 5);
|
||||
uint32_t blend_mask_src = i.VX128_4.IMM;
|
||||
uint32_t blend_mask = 0;
|
||||
for (int n = 3; n >= 0; n--) {
|
||||
blend_mask |= ((blend_mask_src & 0x1) ? n : (4 + n)) << ((3 - n) * 8);
|
||||
blend_mask_src >>= 1;
|
||||
}
|
||||
blend_mask |= (((blend_mask_src >> 3) & 0x1) ? 0 : 4) << 0;
|
||||
blend_mask |= (((blend_mask_src >> 2) & 0x1) ? 1 : 5) << 8;
|
||||
blend_mask |= (((blend_mask_src >> 1) & 0x1) ? 2 : 6) << 16;
|
||||
blend_mask |= (((blend_mask_src >> 0) & 0x1) ? 3 : 7) << 24;
|
||||
uint32_t rotate = i.VX128_4.z;
|
||||
// This is just a fancy permute.
|
||||
// X Y Z W, rotated left by 2 = Z W X Y
|
||||
|
@ -1278,7 +1284,7 @@ XEEMITTER(vrlimi128, VX128_4(6, 1808), VX128_4)(PPCHIRBuilder& f,
|
|||
} else {
|
||||
v = f.LoadVR(vb);
|
||||
}
|
||||
if (blend_mask != 0x00010203) {
|
||||
if (blend_mask != PERMUTE_IDENTITY) {
|
||||
v = f.Permute(f.LoadConstant(blend_mask), v, f.LoadVR(vd), INT32_TYPE);
|
||||
}
|
||||
f.StoreVR(vd, v);
|
||||
|
@ -1382,7 +1388,7 @@ int InstrEmit_vsldoi_(PPCHIRBuilder& f, uint32_t vd, uint32_t va, uint32_t vb,
|
|||
// (VA << SH) OR (VB >> (16 - SH))
|
||||
vec128_t shift = *((vec128_t*)(__vsldoi_table[sh]));
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
shift.i4[i] = poly::byte_swap(shift.i4[i]);
|
||||
shift.u32[i] = poly::byte_swap(shift.u32[i]);
|
||||
}
|
||||
Value* control = f.LoadConstant(shift);
|
||||
Value* v = f.Permute(control, f.LoadVR(va), f.LoadVR(vb), INT8_TYPE);
|
||||
|
@ -1410,7 +1416,7 @@ XEEMITTER(vspltb, 0x1000020C, VX)(PPCHIRBuilder& f, InstrData& i) {
|
|||
// b <- UIMM*8
|
||||
// do i = 0 to 127 by 8
|
||||
// (VD)[i:i+7] <- (VB)[b:b+7]
|
||||
Value* b = f.Extract(f.LoadVR(i.VX.VB), (i.VX.VA & 0xF), INT8_TYPE);
|
||||
Value* b = f.Extract(f.LoadVR(i.VX.VB), i.VX.VA & 0xF, INT8_TYPE);
|
||||
Value* v = f.Splat(b, VEC128_TYPE);
|
||||
f.StoreVR(i.VX.VD, v);
|
||||
return 0;
|
||||
|
@ -1418,7 +1424,7 @@ XEEMITTER(vspltb, 0x1000020C, VX)(PPCHIRBuilder& f, InstrData& i) {
|
|||
|
||||
XEEMITTER(vsplth, 0x1000024C, VX)(PPCHIRBuilder& f, InstrData& i) {
|
||||
// (VD.xyzw) <- (VB.uimm)
|
||||
Value* h = f.Extract(f.LoadVR(i.VX.VB), (i.VX.VA & 0x7), INT16_TYPE);
|
||||
Value* h = f.Extract(f.LoadVR(i.VX.VB), i.VX.VA & 0x7, INT16_TYPE);
|
||||
Value* v = f.Splat(h, VEC128_TYPE);
|
||||
f.StoreVR(i.VX.VD, v);
|
||||
return 0;
|
||||
|
@ -1427,7 +1433,7 @@ XEEMITTER(vsplth, 0x1000024C, VX)(PPCHIRBuilder& f, InstrData& i) {
|
|||
int InstrEmit_vspltw_(PPCHIRBuilder& f, uint32_t vd, uint32_t vb,
|
||||
uint32_t uimm) {
|
||||
// (VD.xyzw) <- (VB.uimm)
|
||||
Value* w = f.Extract(f.LoadVR(vb), (uimm & 0x3), INT32_TYPE);
|
||||
Value* w = f.Extract(f.LoadVR(vb), uimm & 0x3, INT32_TYPE);
|
||||
Value* v = f.Splat(w, VEC128_TYPE);
|
||||
f.StoreVR(vd, v);
|
||||
return 0;
|
||||
|
@ -1856,8 +1862,8 @@ XEEMITTER(vpkd3d128, VX128_4(6, 1552), VX128_4)(PPCHIRBuilder& f,
|
|||
}
|
||||
// http://hlssmod.net/he_code/public/pixelwriter.h
|
||||
// control = prev:0123 | new:4567
|
||||
uint32_t control = 0x00010203; // original
|
||||
uint32_t src = xerotl(0x04050607, shift * 8);
|
||||
uint32_t control = PERMUTE_IDENTITY; // original
|
||||
uint32_t src = xerotl(0x07060504, shift * 8);
|
||||
uint32_t mask = 0;
|
||||
switch (pack) {
|
||||
case 1: // VPACK_32
|
||||
|
@ -1870,8 +1876,8 @@ XEEMITTER(vpkd3d128, VX128_4(6, 1552), VX128_4)(PPCHIRBuilder& f,
|
|||
mask = 0x0000FFFF << (shift * 8);
|
||||
} else {
|
||||
// w
|
||||
src = 0x00000007;
|
||||
mask = 0x000000FF;
|
||||
src = 0x07000000;
|
||||
mask = 0xFF000000;
|
||||
}
|
||||
control = (control & ~mask) | (src & mask);
|
||||
break;
|
||||
|
@ -1880,7 +1886,7 @@ XEEMITTER(vpkd3d128, VX128_4(6, 1552), VX128_4)(PPCHIRBuilder& f,
|
|||
mask = 0x0000FFFF << (shift * 8);
|
||||
} else {
|
||||
// z
|
||||
src = 0x00000006;
|
||||
src = 0x00000004;
|
||||
mask = 0x000000FF;
|
||||
}
|
||||
control = (control & ~mask) | (src & mask);
|
||||
|
|
|
@ -1072,7 +1072,7 @@ XEEMITTER(sradx, 0x7C000634, X)(PPCHIRBuilder& f, InstrData& i) {
|
|||
|
||||
Value* v = f.LoadGPR(i.X.RT);
|
||||
Value* sh = f.And(f.Truncate(f.LoadGPR(i.X.RB), INT8_TYPE),
|
||||
f.LoadConstant((int8_t)0x7F));
|
||||
f.LoadConstant((int8_t)0x3F));
|
||||
|
||||
// CA is set if any bits are shifted out of the right and if the result
|
||||
// is negative. Start tracking that here.
|
||||
|
@ -1137,14 +1137,15 @@ XEEMITTER(srawx, 0x7C000630, X)(PPCHIRBuilder& f, InstrData& i) {
|
|||
// if n >= 32: rA <- 64 sign bits of rS, XER[CA] = sign bit of lo_32(rS)
|
||||
Value* v = f.Truncate(f.LoadGPR(i.X.RT), INT32_TYPE);
|
||||
Value* sh =
|
||||
f.And(f.Truncate(f.LoadGPR(i.X.RB), INT32_TYPE), f.LoadConstant(0x7F));
|
||||
f.And(f.Truncate(f.LoadGPR(i.X.RB), INT32_TYPE), f.LoadConstant(0x1F));
|
||||
// CA is set if any bits are shifted out of the right and if the result
|
||||
// is negative.
|
||||
Value* mask = f.Not(f.Shl(f.LoadConstant(-1), sh));
|
||||
Value* ca =
|
||||
f.And(f.Truncate(f.Shr(v, 31), INT8_TYPE), f.IsTrue(f.And(v, mask)));
|
||||
f.StoreCA(ca);
|
||||
v = f.Sha(v, sh), v = f.SignExtend(v, INT64_TYPE);
|
||||
v = f.Sha(v, sh);
|
||||
v = f.SignExtend(v, INT64_TYPE);
|
||||
f.StoreGPR(i.X.RA, v);
|
||||
if (i.X.Rc) {
|
||||
f.UpdateCR(0, v);
|
||||
|
|
|
@ -51,11 +51,14 @@ enum ArithmeticFlags {
|
|||
ARITHMETIC_UNSIGNED = (1 << 2),
|
||||
ARITHMETIC_SATURATE = (1 << 3),
|
||||
};
|
||||
#define PERMUTE_MASK(sel_x, x, sel_y, y, sel_z, z, sel_w, w) \
|
||||
((((x)&0x3) << 0) | (sel_x << 2) | (((y)&0x3) << 8) | (sel_y << 10) | \
|
||||
(((z)&0x3) << 16) | (sel_z << 18) | (((w)&0x3) << 24) | (sel_w << 26))
|
||||
enum Permutes {
|
||||
PERMUTE_XY_ZW = 0x00010405,
|
||||
PERMUTE_IDENTITY = PERMUTE_MASK(0, 0, 0, 1, 0, 2, 0, 3),
|
||||
};
|
||||
#define SWIZZLE_MASK(x, y, z, w) \
|
||||
((((x)&0x3) << 6) | (((y)&0x3) << 4) | (((z)&0x3) << 2) | (((w)&0x3)))
|
||||
((((x)&0x3) << 0) | (((y)&0x3) << 2) | (((z)&0x3) << 4) | (((w)&0x3) << 6))
|
||||
enum Swizzles {
|
||||
SWIZZLE_XYZW_TO_XYZW = SWIZZLE_MASK(0, 1, 2, 3),
|
||||
SWIZZLE_XYZW_TO_YZWX = SWIZZLE_MASK(1, 2, 3, 0),
|
||||
|
|
|
@ -582,7 +582,7 @@ void Value::ByteSwap() {
|
|||
break;
|
||||
case VEC128_TYPE:
|
||||
for (int n = 0; n < 4; n++) {
|
||||
constant.v128.i4[n] = poly::byte_swap(constant.v128.i4[n]);
|
||||
constant.v128.u32[n] = poly::byte_swap(constant.v128.u32[n]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -14,6 +14,58 @@
|
|||
|
||||
namespace alloy {
|
||||
|
||||
// The first rule of vector programming is to only rely on exact positions
|
||||
// when absolutely required - prefer dumb loops to exact offsets.
|
||||
// Vectors in memory are laid out as in AVX registers on little endian
|
||||
// machines. Note that little endian is dumb, so the byte at index 0 in
|
||||
// the vector is is really byte 15 (or the high byte of short 7 or int 3).
|
||||
// Because of this, all byte access should be via the accessors instead of
|
||||
// the direct array.
|
||||
|
||||
// Altivec big endian layout: AVX little endian layout:
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 0 | int16 0 | int8 0 | | int32 3 | int16 7 | int8 15 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 1 | | | | int8 14 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 1 | int8 2 | | | int16 6 | int8 13 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 3 | | | | int8 12 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 1 | int16 2 | int8 4 | | int32 2 | int16 5 | int8 11 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 5 | | | | int8 10 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 3 | int8 6 | | | int16 4 | int8 9 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 7 | | | | int8 8 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 2 | int16 4 | int8 8 | | int32 1 | int16 3 | int8 7 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 9 | | | | int8 6 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 5 | int8 10 | | | int16 2 | int8 5 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 11 | | | | int8 4 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
// | int32 3 | int16 6 | int8 12 | | int32 0 | int16 1 | int8 3 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 13 | | | | int8 2 |
|
||||
// | +---------+---------+ | +---------+---------+
|
||||
// | | int16 7 | int8 14 | | | int16 0 | int8 1 |
|
||||
// | | +---------+ | | +---------+
|
||||
// | | | int8 15 | | | | int8 0 |
|
||||
// +---------+---------+---------+ +---------+---------+---------+
|
||||
//
|
||||
// Logical order:
|
||||
// +-----+-----+-----+-----+ +-----+-----+-----+-----+
|
||||
// | X | Y | Z | W | | W | Z | Y | X |
|
||||
// +-----+-----+-----+-----+ +-----+-----+-----+-----+
|
||||
//
|
||||
// Mapping indices is easy:
|
||||
// int32[i ^ 0x3]
|
||||
// int16[i ^ 0x7]
|
||||
// int8[i ^ 0xF]
|
||||
typedef struct alignas(16) vec128_s {
|
||||
union {
|
||||
struct {
|
||||
|
@ -23,15 +75,26 @@ typedef struct alignas(16) vec128_s {
|
|||
float w;
|
||||
};
|
||||
struct {
|
||||
uint32_t ix;
|
||||
uint32_t iy;
|
||||
uint32_t iz;
|
||||
uint32_t iw;
|
||||
int32_t ix;
|
||||
int32_t iy;
|
||||
int32_t iz;
|
||||
int32_t iw;
|
||||
};
|
||||
float f4[4];
|
||||
uint32_t i4[4];
|
||||
uint16_t s8[8];
|
||||
uint8_t b16[16];
|
||||
struct {
|
||||
uint32_t ux;
|
||||
uint32_t uy;
|
||||
uint32_t uz;
|
||||
uint32_t uw;
|
||||
};
|
||||
float f32[4];
|
||||
int8_t i8[16];
|
||||
uint8_t u8[16];
|
||||
int16_t i16[8];
|
||||
uint16_t u16[8];
|
||||
int32_t i32[4];
|
||||
uint32_t u32[4];
|
||||
int64_t i64[2];
|
||||
uint64_t u64[2];
|
||||
struct {
|
||||
uint64_t low;
|
||||
uint64_t high;
|
||||
|
@ -42,40 +105,41 @@ typedef struct alignas(16) vec128_s {
|
|||
return low == b.low && high == b.high;
|
||||
}
|
||||
} vec128_t;
|
||||
|
||||
static inline vec128_t vec128i(uint32_t src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 4; ++i) {
|
||||
v.i4[i] = src;
|
||||
v.u32[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128i(uint32_t x, uint32_t y, uint32_t z, uint32_t w) {
|
||||
vec128_t v;
|
||||
v.i4[0] = x;
|
||||
v.i4[1] = y;
|
||||
v.i4[2] = z;
|
||||
v.i4[3] = w;
|
||||
v.u32[0] = x;
|
||||
v.u32[1] = y;
|
||||
v.u32[2] = z;
|
||||
v.u32[3] = w;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128f(float src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 4; ++i) {
|
||||
v.f4[i] = src;
|
||||
v.f32[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128f(float x, float y, float z, float w) {
|
||||
vec128_t v;
|
||||
v.f4[0] = x;
|
||||
v.f4[1] = y;
|
||||
v.f4[2] = z;
|
||||
v.f4[3] = w;
|
||||
v.f32[0] = x;
|
||||
v.f32[1] = y;
|
||||
v.f32[2] = z;
|
||||
v.f32[3] = w;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128s(uint16_t src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 8; ++i) {
|
||||
v.s8[i] = src;
|
||||
v.u16[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
@ -83,20 +147,20 @@ static inline vec128_t vec128s(uint16_t x0, uint16_t x1, uint16_t y0,
|
|||
uint16_t y1, uint16_t z0, uint16_t z1,
|
||||
uint16_t w0, uint16_t w1) {
|
||||
vec128_t v;
|
||||
v.s8[0] = x0;
|
||||
v.s8[1] = x1;
|
||||
v.s8[2] = y0;
|
||||
v.s8[3] = y1;
|
||||
v.s8[4] = z0;
|
||||
v.s8[5] = z1;
|
||||
v.s8[6] = w0;
|
||||
v.s8[7] = w1;
|
||||
v.u16[0] = x1;
|
||||
v.u16[1] = x0;
|
||||
v.u16[2] = y1;
|
||||
v.u16[3] = y0;
|
||||
v.u16[4] = z1;
|
||||
v.u16[5] = z0;
|
||||
v.u16[6] = w1;
|
||||
v.u16[7] = w0;
|
||||
return v;
|
||||
}
|
||||
static inline vec128_t vec128b(uint8_t src) {
|
||||
vec128_t v;
|
||||
for (auto i = 0; i < 16; ++i) {
|
||||
v.b16[i] = src;
|
||||
v.u8[i] = src;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
@ -105,22 +169,22 @@ static inline vec128_t vec128b(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3,
|
|||
uint8_t z0, uint8_t z1, uint8_t z2, uint8_t z3,
|
||||
uint8_t w0, uint8_t w1, uint8_t w2, uint8_t w3) {
|
||||
vec128_t v;
|
||||
v.b16[0] = x3;
|
||||
v.b16[1] = x2;
|
||||
v.b16[2] = x1;
|
||||
v.b16[3] = x0;
|
||||
v.b16[4] = y3;
|
||||
v.b16[5] = y2;
|
||||
v.b16[6] = y1;
|
||||
v.b16[7] = y0;
|
||||
v.b16[8] = z3;
|
||||
v.b16[9] = z2;
|
||||
v.b16[10] = z1;
|
||||
v.b16[11] = z0;
|
||||
v.b16[12] = w3;
|
||||
v.b16[13] = w2;
|
||||
v.b16[14] = w1;
|
||||
v.b16[15] = w0;
|
||||
v.u8[0] = x3;
|
||||
v.u8[1] = x2;
|
||||
v.u8[2] = x1;
|
||||
v.u8[3] = x0;
|
||||
v.u8[4] = y3;
|
||||
v.u8[5] = y2;
|
||||
v.u8[6] = y1;
|
||||
v.u8[7] = y0;
|
||||
v.u8[8] = z3;
|
||||
v.u8[9] = z2;
|
||||
v.u8[10] = z1;
|
||||
v.u8[11] = z0;
|
||||
v.u8[12] = w3;
|
||||
v.u8[13] = w2;
|
||||
v.u8[14] = w1;
|
||||
v.u8[15] = w0;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
@ -38,6 +39,10 @@ T round_up(T value, V multiple) {
|
|||
return value + multiple - 1 - (value - 1) % multiple;
|
||||
}
|
||||
|
||||
inline float saturate(float value) {
|
||||
return std::max(std::min(1.0f, value), -1.0f);
|
||||
}
|
||||
|
||||
// Gets the next power of two value that is greater than or equal to the given
|
||||
// value.
|
||||
template <typename T>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
'dependencies': [
|
||||
'alloy',
|
||||
'xenia',
|
||||
],
|
||||
|
||||
'include_dirs': [
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
'dependencies': [
|
||||
'alloy',
|
||||
'xenia',
|
||||
],
|
||||
|
||||
'include_dirs': [
|
||||
|
@ -40,11 +41,11 @@
|
|||
#'test_div.cc',
|
||||
#'test_dot_product_3.cc',
|
||||
#'test_dot_product_4.cc',
|
||||
#'test_extract.cc',
|
||||
#'test_insert.cc',
|
||||
'test_extract.cc',
|
||||
'test_insert.cc',
|
||||
#'test_is_true_false.cc',
|
||||
#'test_load_clock.cc',
|
||||
#'test_load_vector.cc',
|
||||
'test_load_vector_shl_shr.cc',
|
||||
#'test_log2.cc',
|
||||
#'test_max.cc',
|
||||
#'test_min.cc',
|
||||
|
@ -55,32 +56,32 @@
|
|||
#'test_neg.cc',
|
||||
#'test_not.cc',
|
||||
#'test_or.cc',
|
||||
#'test_pack.cc',
|
||||
#'test_permute.cc',
|
||||
'test_pack.cc',
|
||||
'test_permute.cc',
|
||||
#'test_pow2.cc',
|
||||
#'test_rotate_left.cc',
|
||||
#'test_round.cc',
|
||||
#'test_rsqrt.cc',
|
||||
#'test_select.cc',
|
||||
#'test_sha.cc',
|
||||
#'test_shl.cc',
|
||||
#'test_shr.cc',
|
||||
'test_sha.cc',
|
||||
'test_shl.cc',
|
||||
'test_shr.cc',
|
||||
#'test_sign_extend.cc',
|
||||
#'test_splat.cc',
|
||||
#'test_sqrt.cc',
|
||||
#'test_sub.cc',
|
||||
#'test_swizzle.cc',
|
||||
'test_swizzle.cc',
|
||||
#'test_truncate.cc',
|
||||
#'test_unpack.cc',
|
||||
'test_unpack.cc',
|
||||
'test_vector_add.cc',
|
||||
#'test_vector_compare.cc',
|
||||
#'test_vector_convert.cc',
|
||||
'test_vector_max.cc',
|
||||
'test_vector_min.cc',
|
||||
#'test_vector_rotate_left.cc',
|
||||
#'test_vector_sha.cc',
|
||||
#'test_vector_shl.cc',
|
||||
#'test_vector_shr.cc',
|
||||
'test_vector_rotate_left.cc',
|
||||
'test_vector_sha.cc',
|
||||
'test_vector_shl.cc',
|
||||
'test_vector_shr.cc',
|
||||
#'test_vector_sub.cc',
|
||||
#'test_xor.cc',
|
||||
#'test_zero_extend.cc',
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("EXTRACT_INT8", "[instr]") {
|
||||
TestFunction test([](hir::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](hir::HIRBuilder& b) {
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(
|
||||
b.Extract(LoadVR(b, 4),
|
||||
b.LoadConstant(int8_t(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([](hir::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](hir::HIRBuilder& b) {
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Extract(LoadVR(b, 4),
|
||||
b.LoadConstant(int8_t(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([](hir::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](hir::HIRBuilder& b) {
|
||||
StoreGPR(b, 3,
|
||||
b.ZeroExtend(b.Extract(LoadVR(b, 4),
|
||||
b.LoadConstant(int8_t(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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("INSERT_INT8", "[instr]") {
|
||||
TestFunction test([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), LoadGPR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 5), INT8_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
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]") {
|
||||
TestFunction test([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), LoadGPR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 5), INT16_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
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]") {
|
||||
TestFunction test([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Insert(LoadVR(b, 4), LoadGPR(b, 4),
|
||||
b.Truncate(LoadGPR(b, 5), INT32_TYPE)));
|
||||
b.Return();
|
||||
});
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("LOAD_VECTOR_SHL", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::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));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("PACK_D3DCOLOR", "[instr]") {
|
||||
TestFunction test([](hir::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(0x3F800050, 0x3F800060, 0x3F800070, 0x3F800080);
|
||||
},
|
||||
[](PPCContext* ctx) {
|
||||
auto result = ctx->v[3];
|
||||
REQUIRE(result == vec128i(0, 0, 0, 0x80506070));
|
||||
});
|
||||
}
|
||||
|
||||
TEST_CASE("PACK_FLOAT16_2", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::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([](hir::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));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("PERMUTE_V128_BY_INT32_CONSTANT", "[instr]") {
|
||||
{
|
||||
uint32_t mask = PERMUTE_MASK(0, 0, 0, 1, 0, 2, 0, 3);
|
||||
TestFunction([mask](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstant(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](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstant(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](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstant(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](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.Permute(b.LoadConstant(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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3,
|
||||
b.Permute(LoadVR(b, 3), LoadVR(b, 4), LoadVR(b, 5), VEC128_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));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("SHA_I8", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::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([](hir::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([](hir::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);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("SHL_I8", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::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([](hir::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([](hir::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);
|
||||
});
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("SHR_I8", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::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([](hir::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([](hir::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);
|
||||
});
|
||||
}
|
|
@ -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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("SWIZZLE_V128", "[instr]") {
|
||||
TestFunction([](hir::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([](hir::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([](hir::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));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("UNPACK_D3DCOLOR", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::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([](hir::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([](hir::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([](hir::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([](hir::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([](hir::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([](hir::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));
|
||||
// });
|
||||
//}
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_ROTATE_LEFT_I8", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::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([](hir::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));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_SHA_I8", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), b.LoadConstant(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([](hir::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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorSha(LoadVR(b, 4), b.LoadConstant(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([](hir::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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3,
|
||||
b.VectorSha(LoadVR(b, 4), b.LoadConstant(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(b, 4,
|
||||
b.VectorSha(LoadVR(b, 5), b.LoadConstant(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));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_SHL_I8", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), b.LoadConstant(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([](hir::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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShl(LoadVR(b, 4), b.LoadConstant(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([](hir::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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3,
|
||||
b.VectorShl(LoadVR(b, 4), b.LoadConstant(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(b, 4,
|
||||
b.VectorShl(LoadVR(b, 5), b.LoadConstant(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));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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 <tools/alloy-test/util.h>
|
||||
|
||||
using namespace alloy;
|
||||
using namespace alloy::hir;
|
||||
using namespace alloy::runtime;
|
||||
using namespace alloy::test;
|
||||
using alloy::frontend::ppc::PPCContext;
|
||||
|
||||
TEST_CASE("VECTOR_SHR_I8", "[instr]") {
|
||||
TestFunction test([](hir::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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), b.LoadConstant(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([](hir::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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3, b.VectorShr(LoadVR(b, 4), b.LoadConstant(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([](hir::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([](hir::HIRBuilder& b) {
|
||||
StoreVR(b, 3,
|
||||
b.VectorShr(LoadVR(b, 4), b.LoadConstant(vec128i(0, 1, 16, 31)),
|
||||
INT32_TYPE));
|
||||
StoreVR(b, 4,
|
||||
b.VectorShr(LoadVR(b, 5), b.LoadConstant(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));
|
||||
});
|
||||
}
|
|
@ -23,7 +23,7 @@
|
|||
#include <third_party/catch/single_include/catch.hpp>
|
||||
|
||||
#define ALLOY_TEST_IVM 1
|
||||
//#define ALLOY_TEST_X64 1
|
||||
#define ALLOY_TEST_X64 1
|
||||
|
||||
namespace alloy {
|
||||
namespace test {
|
||||
|
|
Loading…
Reference in New Issue