From: Alexandra Hájková Date: Wed, 14 Jan 2026 14:23:55 +0000 (-0500) Subject: Add SSE4.1 BLENDPD instruction for x86 32 bit X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=845145359800ae1f55519caf5c90f7c509f51d3a;p=thirdparty%2Fvalgrind.git Add SSE4.1 BLENDPD instruction for x86 32 bit Support blendpd (Blend Packed Double Precision Floating-Point Values (XMM)) instruction in guest_x86_toIR.c. To be able to use amd64 math_BLENDPD_128 function for x86 implementation, add a new VEX/priv/guest_generic_sse.h header and move math_BLENDPD_128 there. mkV128() was moveda from line 1671 in guest_amd64_toIR.c to line 295, grouping it with other mkU* constant-creation helpers (mkU8, mkU16, mkU32, mkU64). This allows guest_generic_sse.h to be included much earlier (line 300 vs. line 1676), making the code organization more natural. The header includes an explaination why it must be included mid-file (after IR helpers like newTemp, assign, binop, etc. are defined) and why those helpers cannot be moved to a shared header (they depend on file-local global state, particularly the 'irsb' variable). Add test function to sse4-common.h and update none/tests/x86/sse4-x86.c to test the instruction. BZ: https://bugs.kde.org/show_bug.cgi?id=514596 --- diff --git a/Makefile.vex.am b/Makefile.vex.am index f7371df78..fc496d22e 100644 --- a/Makefile.vex.am +++ b/Makefile.vex.am @@ -41,6 +41,7 @@ noinst_HEADERS = \ priv/ir_opt.h \ priv/guest_generic_bb_to_IR.h \ priv/guest_generic_x87.h \ + priv/guest_generic_sse.h \ priv/guest_x86_defs.h \ priv/guest_amd64_defs.h \ priv/guest_ppc_defs.h \ diff --git a/NEWS b/NEWS index 5f7eb03bf..9091f0a39 100644 --- a/NEWS +++ b/NEWS @@ -71,6 +71,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. 514094 readlink("/proc/self/exe") overwrites buffer beyond its return value 514206 Assertion '!sr_isError(sr)' failed - mmap fd points to an open descriptor to a PCI device +514596 Add SSE4.1 BLENDPD instruction for x86 32 bit 514613 Unclosed leak_summary/still_reachable tag in xml output 514659 ltp 20250930 vs linux 6.18.3 doesn't build 514762 Many "Bad file descriptor" messages when using --track-fds=yes and diff --git a/VEX/priv/guest_amd64_toIR.c b/VEX/priv/guest_amd64_toIR.c index 0319578f2..5faf9c07c 100644 --- a/VEX/priv/guest_amd64_toIR.c +++ b/VEX/priv/guest_amd64_toIR.c @@ -292,6 +292,13 @@ static IRExpr* mkU ( IRType ty, ULong i ) } } +static IRExpr* mkV128 ( UShort mask ) +{ + return IRExpr_Const(IRConst_V128(mask)); +} + +#include "guest_generic_sse.h" + static void storeLE ( IRExpr* addr, IRExpr* data ) { stmt( IRStmt_Store(Iend_LE, addr, data) ); @@ -1668,11 +1675,6 @@ static void putYMMRegLane32 ( UInt ymmreg, Int laneno, IRExpr* e ) stmt( IRStmt_Put( ymmGuestRegLane32offset(ymmreg,laneno), e ) ); } -static IRExpr* mkV128 ( UShort mask ) -{ - return IRExpr_Const(IRConst_V128(mask)); -} - /* Write the low half of a YMM reg and zero out the upper half. */ static void putYMMRegLoAndZU ( UInt ymmreg, IRExpr* e ) { @@ -11233,30 +11235,6 @@ static IRTemp math_SHUFPD_256 ( IRTemp sV, IRTemp dV, UInt imm8 ) } -static IRTemp math_BLENDPD_128 ( IRTemp sV, IRTemp dV, UInt imm8 ) -{ - UShort imm8_mask_16; - IRTemp imm8_mask = newTemp(Ity_V128); - - switch( imm8 & 3 ) { - case 0: imm8_mask_16 = 0x0000; break; - case 1: imm8_mask_16 = 0x00FF; break; - case 2: imm8_mask_16 = 0xFF00; break; - case 3: imm8_mask_16 = 0xFFFF; break; - default: vassert(0); break; - } - assign( imm8_mask, mkV128( imm8_mask_16 ) ); - - IRTemp res = newTemp(Ity_V128); - assign ( res, binop( Iop_OrV128, - binop( Iop_AndV128, mkexpr(sV), - mkexpr(imm8_mask) ), - binop( Iop_AndV128, mkexpr(dV), - unop( Iop_NotV128, mkexpr(imm8_mask) ) ) ) ); - return res; -} - - static IRTemp math_BLENDPD_256 ( IRTemp sV, IRTemp dV, UInt imm8 ) { IRTemp sVhi = IRTemp_INVALID, sVlo = IRTemp_INVALID; diff --git a/VEX/priv/guest_generic_sse.h b/VEX/priv/guest_generic_sse.h new file mode 100644 index 000000000..28f6079ff --- /dev/null +++ b/VEX/priv/guest_generic_sse.h @@ -0,0 +1,90 @@ +/*---------------------------------------------------------------*/ +/*--- begin guest_generic_sse.h ---*/ +/*---------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2025-2026 Alexandra Hájková + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + The GNU General Public License is contained in the file COPYING. +*/ + +/* This file contains functions for SSE/SSE2/SSE3/SSE4-specific + operations. Both the amd64 and x86 front ends (guests) call + these functions. By putting them here, code duplication is + avoided. Some of these functions are tricky and hard to verify, + so there is much to be said for only having one copy thereof. + + IMPORTANT: This header must be included AFTER the following + helper functions/macros are defined in the including file: + - newTemp(IRType) - allocate a new IRTemp + - assign(IRTemp, IRExpr*) - create assignment statement + - mkV128(UShort) - create V128 constant expression + - binop(IROp, IRExpr*, IRExpr*) - create binary operation + - unop(IROp, IRExpr*) - create unary operation + - mkexpr(IRTemp) - create IRTemp expression + - vassert(Bool) - assertion macro + + These helper functions are defined locally in each guest_*_toIR.c + file because they rely on file-local global state, particularly + the 'irsb' variable (the IR super block being built). Moving them + to a shared header would require either passing 'irsb' as a + parameter to each call (breaking thousands of call sites) or + making 'irsb' a shared extern (architecturally problematic). + + Therefore, this header is included after those helpers are defined, + typically around line 300 in guest_*_toIR.c files. +*/ + +#ifndef __VEX_GUEST_GENERIC_SSE_H +#define __VEX_GUEST_GENERIC_SSE_H + +#include "libvex_basictypes.h" +#include "libvex_ir.h" +#include "libvex.h" + + +/* BLENDPD 128-bit */ +static inline IRTemp math_BLENDPD_128 ( IRTemp sV, IRTemp dV, UInt imm8 ) +{ + UShort imm8_mask_16; + IRTemp imm8_mask = newTemp(Ity_V128); + + switch( imm8 & 3 ) { + case 0: imm8_mask_16 = 0x0000; break; + case 1: imm8_mask_16 = 0x00FF; break; + case 2: imm8_mask_16 = 0xFF00; break; + case 3: imm8_mask_16 = 0xFFFF; break; + default: vassert(0); break; + } + assign( imm8_mask, mkV128( imm8_mask_16 ) ); + + IRTemp res = newTemp(Ity_V128); + assign ( res, binop( Iop_OrV128, + binop( Iop_AndV128, mkexpr(sV), + mkexpr(imm8_mask) ), + binop( Iop_AndV128, mkexpr(dV), + unop( Iop_NotV128, mkexpr(imm8_mask) ) ) ) ); + return res; +} + +#endif /* ndef __VEX_GUEST_GENERIC_SSE_H */ + +/*---------------------------------------------------------------*/ +/*--- end guest_generic_sse.h ---*/ +/*---------------------------------------------------------------*/ diff --git a/VEX/priv/guest_x86_toIR.c b/VEX/priv/guest_x86_toIR.c index 710905ad1..5312fab87 100644 --- a/VEX/priv/guest_x86_toIR.c +++ b/VEX/priv/guest_x86_toIR.c @@ -695,6 +695,8 @@ static IRExpr* mkV128 ( UShort mask ) return IRExpr_Const(IRConst_V128(mask)); } +#include "guest_generic_sse.h" + static IRExpr* loadLE ( IRType ty, IRExpr* addr ) { return IRExpr_Load(Iend_LE, ty, addr); @@ -12999,6 +13001,57 @@ DisResult disInstr_X86_WRK ( goto decode_success; } + /* 66 0F 3A 0D /r ib = BLENDPD xmm1, xmm2/m128, imm8 + Blend Packed Double Precision Floating-Point Values (XMM) + - 66 = mandatory prefix (this is what makes sz == 2) + - 0F 3A 0D = three opcode bytes + - /r = ModR/M byte follows (specifies registers or memory addressing) + - ib = immediate byte follows (1 byte immediate value) + insn[] array layout: + + insn[0] = 0x0F (first opcode byte) + insn[1] = 0x3A (second opcode byte) + insn[2] = 0x0D (third opcode byte) + insn[3] = ModR/M (specifies source/dest registers or memory mode) + + Register-to-register form: + insn[3] = ModR/M byte (tells us which registers) + insn[4] = immediate byte + alen var tells us how many bytes the addressing mode consumed after the ModR/M byte +*/ + if (sz == 2 && insn[0] == 0x0F && insn[1] == 0x3A && insn[2] == 0x0D) { + Int imm8; + IRTemp dst_vec = newTemp(Ity_V128); + IRTemp src_vec = newTemp(Ity_V128); + + modrm = insn[3]; + //no REX prefix on 32bit + assign( dst_vec, getXMMReg( gregOfRM(modrm) ) ); + + if ( epartIsReg( modrm ) ) { + imm8 = insn[4]; + assign( src_vec, getXMMReg( eregOfRM(modrm) ) ); + //skip 0F 3A 0D opcode bytes: +3 + delta += 1+1 + 3; + DIP( "blendpd $%d, %s,%s\n", imm8, + nameXMMReg( eregOfRM(modrm) ), + nameXMMReg( gregOfRM(modrm) ) ); + } else { + //delta+3 skips the 0F 3A 0D bytes + addr = disAMode( &alen, sorb, delta + 3, dis_buf); + assign( src_vec, loadLE( Ity_V128, mkexpr(addr) ) ); + imm8 = insn[3+alen]; + //skip 0F 3A 0D opcode bytes: +3 + delta += alen+1 + 3; + DIP( "blendpd $%d, %s,%s\n", + imm8, dis_buf, nameXMMReg( gregOfRM(modrm) ) ); + } + + putXMMReg( gregOfRM(modrm), + mkexpr( math_BLENDPD_128( src_vec, dst_vec, imm8) ) ); + goto decode_success; + } + /* 66 0F 38 38 /r - PMINSB xmm1, xmm2/m128 66 0F 38 3C /r - PMAXSB xmm1, xmm2/m128 Minimum/Maximum of Packed Signed Byte Integers (XMM) diff --git a/none/tests/amd64/sse4-64.c b/none/tests/amd64/sse4-64.c index a4614016e..9ba5162fd 100644 --- a/none/tests/amd64/sse4-64.c +++ b/none/tests/amd64/sse4-64.c @@ -152,20 +152,6 @@ void set_sse_roundingmode ( UInt m ) -void test_BLENDPD ( void ) -{ - V128 src, dst; - Int i; - for (i = 0; i < 10; i++) { - randV128(&src); - randV128(&dst); - DO_imm_mandr_r("blendpd", 0, src, dst); - DO_imm_mandr_r("blendpd", 1, src, dst); - DO_imm_mandr_r("blendpd", 2, src, dst); - DO_imm_mandr_r("blendpd", 3, src, dst); - } -} - void test_BLENDPS ( void ) { V128 src, dst; diff --git a/none/tests/sse4-common.h b/none/tests/sse4-common.h index 5576c1f73..62c112548 100644 --- a/none/tests/sse4-common.h +++ b/none/tests/sse4-common.h @@ -351,4 +351,18 @@ static inline void test_PMULLD ( void ) } } +static inline void test_BLENDPD ( void ) +{ + V128 src, dst; + Int i; + for (i = 0; i < 10; i++) { + randV128(&src); + randV128(&dst); + DO_imm_mandr_r("blendpd", 0, src, dst); + DO_imm_mandr_r("blendpd", 1, src, dst); + DO_imm_mandr_r("blendpd", 2, src, dst); + DO_imm_mandr_r("blendpd", 3, src, dst); + } +} + #endif /* __SSE4_COMMON_H */ diff --git a/none/tests/x86/sse4-x86.c b/none/tests/x86/sse4-x86.c index f65e6467d..c834758ec 100644 --- a/none/tests/x86/sse4-x86.c +++ b/none/tests/x86/sse4-x86.c @@ -113,6 +113,7 @@ int main(void) test_PMINUD(); test_PMINUW(); test_PMULLD(); + test_BLENDPD(); return 0; } diff --git a/none/tests/x86/sse4-x86.stdout.exp b/none/tests/x86/sse4-x86.stdout.exp index de3810a0e..db6addce9 100644 --- a/none/tests/x86/sse4-x86.stdout.exp +++ b/none/tests/x86/sse4-x86.stdout.exp @@ -186,3 +186,83 @@ r pmulld a77700084a491a0ef099b6dd61462ec3 e70a9c61f55fce335d68e1a25652a804 3 m pmulld a77700084a491a0ef099b6dd61462ec3 e70a9c61f55fce335d68e1a25652a804 306be308b0b974caedc5f4da103eb30c r pmulld 1dd493f59184345437d5e366d0e20c30 c50f1401e45b82d3086a7a39a1e6217d edbeb7f57c65c93cb53a3db645122370 m pmulld 1dd493f59184345437d5e366d0e20c30 c50f1401e45b82d3086a7a39a1e6217d edbeb7f57c65c93cb53a3db645122370 +r blendpd $0 3a542e238fe5d1793d1148867eb08f81 b79cd058188318692112ca1cf9f1dd31 b79cd058188318692112ca1cf9f1dd31 +m blendpd $0 3a542e238fe5d1793d1148867eb08f81 b79cd058188318692112ca1cf9f1dd31 b79cd058188318692112ca1cf9f1dd31 +r blendpd $1 3a542e238fe5d1793d1148867eb08f81 b79cd058188318692112ca1cf9f1dd31 b79cd058188318693d1148867eb08f81 +m blendpd $1 3a542e238fe5d1793d1148867eb08f81 b79cd058188318692112ca1cf9f1dd31 b79cd058188318693d1148867eb08f81 +r blendpd $2 3a542e238fe5d1793d1148867eb08f81 b79cd058188318692112ca1cf9f1dd31 3a542e238fe5d1792112ca1cf9f1dd31 +m blendpd $2 3a542e238fe5d1793d1148867eb08f81 b79cd058188318692112ca1cf9f1dd31 3a542e238fe5d1792112ca1cf9f1dd31 +r blendpd $3 3a542e238fe5d1793d1148867eb08f81 b79cd058188318692112ca1cf9f1dd31 3a542e238fe5d1793d1148867eb08f81 +m blendpd $3 3a542e238fe5d1793d1148867eb08f81 b79cd058188318692112ca1cf9f1dd31 3a542e238fe5d1793d1148867eb08f81 +r blendpd $0 5842cbfee0f72e2ade18612787bc73e3 19ffced22c62cba0822c4c377b82984c 19ffced22c62cba0822c4c377b82984c +m blendpd $0 5842cbfee0f72e2ade18612787bc73e3 19ffced22c62cba0822c4c377b82984c 19ffced22c62cba0822c4c377b82984c +r blendpd $1 5842cbfee0f72e2ade18612787bc73e3 19ffced22c62cba0822c4c377b82984c 19ffced22c62cba0de18612787bc73e3 +m blendpd $1 5842cbfee0f72e2ade18612787bc73e3 19ffced22c62cba0822c4c377b82984c 19ffced22c62cba0de18612787bc73e3 +r blendpd $2 5842cbfee0f72e2ade18612787bc73e3 19ffced22c62cba0822c4c377b82984c 5842cbfee0f72e2a822c4c377b82984c +m blendpd $2 5842cbfee0f72e2ade18612787bc73e3 19ffced22c62cba0822c4c377b82984c 5842cbfee0f72e2a822c4c377b82984c +r blendpd $3 5842cbfee0f72e2ade18612787bc73e3 19ffced22c62cba0822c4c377b82984c 5842cbfee0f72e2ade18612787bc73e3 +m blendpd $3 5842cbfee0f72e2ade18612787bc73e3 19ffced22c62cba0822c4c377b82984c 5842cbfee0f72e2ade18612787bc73e3 +r blendpd $0 d4ec68f21f468712f7b8ab3708137382 478209dbbd84d92508847c7642a20df9 478209dbbd84d92508847c7642a20df9 +m blendpd $0 d4ec68f21f468712f7b8ab3708137382 478209dbbd84d92508847c7642a20df9 478209dbbd84d92508847c7642a20df9 +r blendpd $1 d4ec68f21f468712f7b8ab3708137382 478209dbbd84d92508847c7642a20df9 478209dbbd84d925f7b8ab3708137382 +m blendpd $1 d4ec68f21f468712f7b8ab3708137382 478209dbbd84d92508847c7642a20df9 478209dbbd84d925f7b8ab3708137382 +r blendpd $2 d4ec68f21f468712f7b8ab3708137382 478209dbbd84d92508847c7642a20df9 d4ec68f21f46871208847c7642a20df9 +m blendpd $2 d4ec68f21f468712f7b8ab3708137382 478209dbbd84d92508847c7642a20df9 d4ec68f21f46871208847c7642a20df9 +r blendpd $3 d4ec68f21f468712f7b8ab3708137382 478209dbbd84d92508847c7642a20df9 d4ec68f21f468712f7b8ab3708137382 +m blendpd $3 d4ec68f21f468712f7b8ab3708137382 478209dbbd84d92508847c7642a20df9 d4ec68f21f468712f7b8ab3708137382 +r blendpd $0 0b9c016be95f18de62bba1a11cc04c89 9c727edf66767ca38fe6d7c56a5ff965 9c727edf66767ca38fe6d7c56a5ff965 +m blendpd $0 0b9c016be95f18de62bba1a11cc04c89 9c727edf66767ca38fe6d7c56a5ff965 9c727edf66767ca38fe6d7c56a5ff965 +r blendpd $1 0b9c016be95f18de62bba1a11cc04c89 9c727edf66767ca38fe6d7c56a5ff965 9c727edf66767ca362bba1a11cc04c89 +m blendpd $1 0b9c016be95f18de62bba1a11cc04c89 9c727edf66767ca38fe6d7c56a5ff965 9c727edf66767ca362bba1a11cc04c89 +r blendpd $2 0b9c016be95f18de62bba1a11cc04c89 9c727edf66767ca38fe6d7c56a5ff965 0b9c016be95f18de8fe6d7c56a5ff965 +m blendpd $2 0b9c016be95f18de62bba1a11cc04c89 9c727edf66767ca38fe6d7c56a5ff965 0b9c016be95f18de8fe6d7c56a5ff965 +r blendpd $3 0b9c016be95f18de62bba1a11cc04c89 9c727edf66767ca38fe6d7c56a5ff965 0b9c016be95f18de62bba1a11cc04c89 +m blendpd $3 0b9c016be95f18de62bba1a11cc04c89 9c727edf66767ca38fe6d7c56a5ff965 0b9c016be95f18de62bba1a11cc04c89 +r blendpd $0 579f90d5d9cd1c3afceebf50e0d0ba24 761b274ac4c4f0c7f31ed81010c417bc 761b274ac4c4f0c7f31ed81010c417bc +m blendpd $0 579f90d5d9cd1c3afceebf50e0d0ba24 761b274ac4c4f0c7f31ed81010c417bc 761b274ac4c4f0c7f31ed81010c417bc +r blendpd $1 579f90d5d9cd1c3afceebf50e0d0ba24 761b274ac4c4f0c7f31ed81010c417bc 761b274ac4c4f0c7fceebf50e0d0ba24 +m blendpd $1 579f90d5d9cd1c3afceebf50e0d0ba24 761b274ac4c4f0c7f31ed81010c417bc 761b274ac4c4f0c7fceebf50e0d0ba24 +r blendpd $2 579f90d5d9cd1c3afceebf50e0d0ba24 761b274ac4c4f0c7f31ed81010c417bc 579f90d5d9cd1c3af31ed81010c417bc +m blendpd $2 579f90d5d9cd1c3afceebf50e0d0ba24 761b274ac4c4f0c7f31ed81010c417bc 579f90d5d9cd1c3af31ed81010c417bc +r blendpd $3 579f90d5d9cd1c3afceebf50e0d0ba24 761b274ac4c4f0c7f31ed81010c417bc 579f90d5d9cd1c3afceebf50e0d0ba24 +m blendpd $3 579f90d5d9cd1c3afceebf50e0d0ba24 761b274ac4c4f0c7f31ed81010c417bc 579f90d5d9cd1c3afceebf50e0d0ba24 +r blendpd $0 1541139c8b1cd0d1a11d81326f4e7880 30c9028972f8733d11f7fa4450de2529 30c9028972f8733d11f7fa4450de2529 +m blendpd $0 1541139c8b1cd0d1a11d81326f4e7880 30c9028972f8733d11f7fa4450de2529 30c9028972f8733d11f7fa4450de2529 +r blendpd $1 1541139c8b1cd0d1a11d81326f4e7880 30c9028972f8733d11f7fa4450de2529 30c9028972f8733da11d81326f4e7880 +m blendpd $1 1541139c8b1cd0d1a11d81326f4e7880 30c9028972f8733d11f7fa4450de2529 30c9028972f8733da11d81326f4e7880 +r blendpd $2 1541139c8b1cd0d1a11d81326f4e7880 30c9028972f8733d11f7fa4450de2529 1541139c8b1cd0d111f7fa4450de2529 +m blendpd $2 1541139c8b1cd0d1a11d81326f4e7880 30c9028972f8733d11f7fa4450de2529 1541139c8b1cd0d111f7fa4450de2529 +r blendpd $3 1541139c8b1cd0d1a11d81326f4e7880 30c9028972f8733d11f7fa4450de2529 1541139c8b1cd0d1a11d81326f4e7880 +m blendpd $3 1541139c8b1cd0d1a11d81326f4e7880 30c9028972f8733d11f7fa4450de2529 1541139c8b1cd0d1a11d81326f4e7880 +r blendpd $0 a1cd852d9cd970502d146432e64644c9 25c80a060da03fb0c33ebc4b44b8ddd8 25c80a060da03fb0c33ebc4b44b8ddd8 +m blendpd $0 a1cd852d9cd970502d146432e64644c9 25c80a060da03fb0c33ebc4b44b8ddd8 25c80a060da03fb0c33ebc4b44b8ddd8 +r blendpd $1 a1cd852d9cd970502d146432e64644c9 25c80a060da03fb0c33ebc4b44b8ddd8 25c80a060da03fb02d146432e64644c9 +m blendpd $1 a1cd852d9cd970502d146432e64644c9 25c80a060da03fb0c33ebc4b44b8ddd8 25c80a060da03fb02d146432e64644c9 +r blendpd $2 a1cd852d9cd970502d146432e64644c9 25c80a060da03fb0c33ebc4b44b8ddd8 a1cd852d9cd97050c33ebc4b44b8ddd8 +m blendpd $2 a1cd852d9cd970502d146432e64644c9 25c80a060da03fb0c33ebc4b44b8ddd8 a1cd852d9cd97050c33ebc4b44b8ddd8 +r blendpd $3 a1cd852d9cd970502d146432e64644c9 25c80a060da03fb0c33ebc4b44b8ddd8 a1cd852d9cd970502d146432e64644c9 +m blendpd $3 a1cd852d9cd970502d146432e64644c9 25c80a060da03fb0c33ebc4b44b8ddd8 a1cd852d9cd970502d146432e64644c9 +r blendpd $0 5791e2f2a78f37627c9fe23c60c5d82b b3633c2f304791cde6c097130b5efcf6 b3633c2f304791cde6c097130b5efcf6 +m blendpd $0 5791e2f2a78f37627c9fe23c60c5d82b b3633c2f304791cde6c097130b5efcf6 b3633c2f304791cde6c097130b5efcf6 +r blendpd $1 5791e2f2a78f37627c9fe23c60c5d82b b3633c2f304791cde6c097130b5efcf6 b3633c2f304791cd7c9fe23c60c5d82b +m blendpd $1 5791e2f2a78f37627c9fe23c60c5d82b b3633c2f304791cde6c097130b5efcf6 b3633c2f304791cd7c9fe23c60c5d82b +r blendpd $2 5791e2f2a78f37627c9fe23c60c5d82b b3633c2f304791cde6c097130b5efcf6 5791e2f2a78f3762e6c097130b5efcf6 +m blendpd $2 5791e2f2a78f37627c9fe23c60c5d82b b3633c2f304791cde6c097130b5efcf6 5791e2f2a78f3762e6c097130b5efcf6 +r blendpd $3 5791e2f2a78f37627c9fe23c60c5d82b b3633c2f304791cde6c097130b5efcf6 5791e2f2a78f37627c9fe23c60c5d82b +m blendpd $3 5791e2f2a78f37627c9fe23c60c5d82b b3633c2f304791cde6c097130b5efcf6 5791e2f2a78f37627c9fe23c60c5d82b +r blendpd $0 94d7265949ca62b46a8a793cf9d5f0d1 35e7926e777aa43f56470887bfdd3daf 35e7926e777aa43f56470887bfdd3daf +m blendpd $0 94d7265949ca62b46a8a793cf9d5f0d1 35e7926e777aa43f56470887bfdd3daf 35e7926e777aa43f56470887bfdd3daf +r blendpd $1 94d7265949ca62b46a8a793cf9d5f0d1 35e7926e777aa43f56470887bfdd3daf 35e7926e777aa43f6a8a793cf9d5f0d1 +m blendpd $1 94d7265949ca62b46a8a793cf9d5f0d1 35e7926e777aa43f56470887bfdd3daf 35e7926e777aa43f6a8a793cf9d5f0d1 +r blendpd $2 94d7265949ca62b46a8a793cf9d5f0d1 35e7926e777aa43f56470887bfdd3daf 94d7265949ca62b456470887bfdd3daf +m blendpd $2 94d7265949ca62b46a8a793cf9d5f0d1 35e7926e777aa43f56470887bfdd3daf 94d7265949ca62b456470887bfdd3daf +r blendpd $3 94d7265949ca62b46a8a793cf9d5f0d1 35e7926e777aa43f56470887bfdd3daf 94d7265949ca62b46a8a793cf9d5f0d1 +m blendpd $3 94d7265949ca62b46a8a793cf9d5f0d1 35e7926e777aa43f56470887bfdd3daf 94d7265949ca62b46a8a793cf9d5f0d1 +r blendpd $0 b2ed4ecc1e172df2d3a0a41fce854ae7 06a10a317fc4b5b3ef9f8c927c405d2f 06a10a317fc4b5b3ef9f8c927c405d2f +m blendpd $0 b2ed4ecc1e172df2d3a0a41fce854ae7 06a10a317fc4b5b3ef9f8c927c405d2f 06a10a317fc4b5b3ef9f8c927c405d2f +r blendpd $1 b2ed4ecc1e172df2d3a0a41fce854ae7 06a10a317fc4b5b3ef9f8c927c405d2f 06a10a317fc4b5b3d3a0a41fce854ae7 +m blendpd $1 b2ed4ecc1e172df2d3a0a41fce854ae7 06a10a317fc4b5b3ef9f8c927c405d2f 06a10a317fc4b5b3d3a0a41fce854ae7 +r blendpd $2 b2ed4ecc1e172df2d3a0a41fce854ae7 06a10a317fc4b5b3ef9f8c927c405d2f b2ed4ecc1e172df2ef9f8c927c405d2f +m blendpd $2 b2ed4ecc1e172df2d3a0a41fce854ae7 06a10a317fc4b5b3ef9f8c927c405d2f b2ed4ecc1e172df2ef9f8c927c405d2f +r blendpd $3 b2ed4ecc1e172df2d3a0a41fce854ae7 06a10a317fc4b5b3ef9f8c927c405d2f b2ed4ecc1e172df2d3a0a41fce854ae7 +m blendpd $3 b2ed4ecc1e172df2d3a0a41fce854ae7 06a10a317fc4b5b3ef9f8c927c405d2f b2ed4ecc1e172df2d3a0a41fce854ae7