From: Julian Seward Date: Thu, 4 Aug 2016 09:13:11 +0000 (+0000) Subject: Implement CRC32{B,H,W,X} and CRC32C{B,H,W,X}. Fixes #366344. X-Git-Tag: svn/VALGRIND_3_12_0^2~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6c99d37dd036d562b6a56cce576d125d0d239a3a;p=thirdparty%2Fvalgrind.git Implement CRC32{B,H,W,X} and CRC32C{B,H,W,X}. Fixes #366344. git-svn-id: svn://svn.valgrind.org/vex/trunk@3237 --- diff --git a/VEX/priv/guest_arm64_defs.h b/VEX/priv/guest_arm64_defs.h index 7ec6439d13..ad1ab96e6d 100644 --- a/VEX/priv/guest_arm64_defs.h +++ b/VEX/priv/guest_arm64_defs.h @@ -110,6 +110,15 @@ ULong arm64g_calculate_condition ( /* ARM64Condcode << 4 | cc_op */ //ZZ UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2, //ZZ UInt resR1, UInt resR2 ); +extern ULong arm64g_calc_crc32b ( ULong acc, ULong bits ); +extern ULong arm64g_calc_crc32h ( ULong acc, ULong bits ); +extern ULong arm64g_calc_crc32w ( ULong acc, ULong bits ); +extern ULong arm64g_calc_crc32x ( ULong acc, ULong bits ); + +extern ULong arm64g_calc_crc32cb ( ULong acc, ULong bits ); +extern ULong arm64g_calc_crc32ch ( ULong acc, ULong bits ); +extern ULong arm64g_calc_crc32cw ( ULong acc, ULong bits ); +extern ULong arm64g_calc_crc32cx ( ULong acc, ULong bits ); /* --- DIRTY HELPERS --- */ diff --git a/VEX/priv/guest_arm64_helpers.c b/VEX/priv/guest_arm64_helpers.c index 5346accfa7..5edeef17e5 100644 --- a/VEX/priv/guest_arm64_helpers.c +++ b/VEX/priv/guest_arm64_helpers.c @@ -677,6 +677,88 @@ ULong arm64g_calculate_condition ( /* ARM64Condcode << 4 | cc_op */ } +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +ULong arm64g_calc_crc32b ( ULong acc, ULong bits ) +{ + UInt i; + ULong crc = (bits & 0xFFULL) ^ acc; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320ULL : 0); + return crc; +} + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +ULong arm64g_calc_crc32h ( ULong acc, ULong bits ) +{ + UInt i; + ULong crc = (bits & 0xFFFFULL) ^ acc; + for (i = 0; i < 16; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320ULL : 0); + return crc; +} + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +ULong arm64g_calc_crc32w ( ULong acc, ULong bits ) +{ + UInt i; + ULong crc = (bits & 0xFFFFFFFFULL) ^ acc; + for (i = 0; i < 32; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320ULL : 0); + return crc; +} + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +ULong arm64g_calc_crc32x ( ULong acc, ULong bits ) +{ + UInt i; + ULong crc = bits ^ acc; + for (i = 0; i < 64; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320ULL : 0); + return crc; + +} + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +ULong arm64g_calc_crc32cb ( ULong acc, ULong bits ) +{ + UInt i; + ULong crc = (bits & 0xFFULL) ^ acc; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0x82F63B78ULL : 0); + return crc; +} + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +ULong arm64g_calc_crc32ch ( ULong acc, ULong bits ) +{ + UInt i; + ULong crc = (bits & 0xFFFFULL) ^ acc; + for (i = 0; i < 16; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0x82F63B78ULL : 0); + return crc; +} + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +ULong arm64g_calc_crc32cw ( ULong acc, ULong bits ) +{ + UInt i; + ULong crc = (bits & 0xFFFFFFFFULL) ^ acc; + for (i = 0; i < 32; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0x82F63B78ULL : 0); + return crc; +} + +/* CALLED FROM GENERATED CODE: CLEAN HELPER */ +ULong arm64g_calc_crc32cx ( ULong acc, ULong bits ) +{ + UInt i; + ULong crc = bits ^ acc; + for (i = 0; i < 64; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0x82F63B78ULL : 0); + return crc; +} + + /* CALLED FROM GENERATED CODE */ /* DIRTY HELPER (non-referentially-transparent) */ /* Horrible hack. On non-arm64 platforms, return 0. */ diff --git a/VEX/priv/guest_arm64_toIR.c b/VEX/priv/guest_arm64_toIR.c index a3a9078b07..ca53d9dc12 100644 --- a/VEX/priv/guest_arm64_toIR.c +++ b/VEX/priv/guest_arm64_toIR.c @@ -3497,6 +3497,75 @@ Bool dis_ARM64_data_processing_register(/*MB_OUT*/DisResult* dres, nameIReg32orZR(mm), nameIReg64orZR(aa)); return True; } + + /* -------------------- CRC32/CRC32C -------------------- */ + /* 31 30 20 15 11 9 4 + sf 00 1101 0110 m 0100 sz n d CRC32 Wd, Wn, Wm|Xm + sf 00 1101 0110 m 0101 sz n d CRC32C Wd, Wn, Wm|Xm + */ + if (INSN(30,21) == BITS10(0,0,1,1,0,1,0,1,1,0) + && INSN(15,13) == BITS3(0,1,0)) { + UInt bitSF = INSN(31,31); + UInt mm = INSN(20,16); + UInt bitC = INSN(12,12); + UInt sz = INSN(11,10); + UInt nn = INSN(9,5); + UInt dd = INSN(4,0); + vassert(sz >= 0 && sz <= 3); + if ((bitSF == 0 && sz <= BITS2(1,0)) + || (bitSF == 1 && sz == BITS2(1,1))) { + UInt ix = (bitC == 1 ? 4 : 0) | sz; + void* helpers[8] + = { &arm64g_calc_crc32b, &arm64g_calc_crc32h, + &arm64g_calc_crc32w, &arm64g_calc_crc32x, + &arm64g_calc_crc32cb, &arm64g_calc_crc32ch, + &arm64g_calc_crc32cw, &arm64g_calc_crc32cx }; + const HChar* hNames[8] + = { "arm64g_calc_crc32b", "arm64g_calc_crc32h", + "arm64g_calc_crc32w", "arm64g_calc_crc32x", + "arm64g_calc_crc32cb", "arm64g_calc_crc32ch", + "arm64g_calc_crc32cw", "arm64g_calc_crc32cx" }; + const HChar* iNames[8] + = { "crc32b", "crc32h", "crc32w", "crc32x", + "crc32cb", "crc32ch", "crc32cw", "crc32cx" }; + + IRTemp srcN = newTemp(Ity_I64); + assign(srcN, unop(Iop_32Uto64, unop(Iop_64to32, getIReg64orZR(nn)))); + + IRTemp srcM = newTemp(Ity_I64); + IRExpr* at64 = getIReg64orZR(mm); + switch (sz) { + case BITS2(0,0): + assign(srcM, binop(Iop_And64, at64, mkU64(0xFF))); break; + case BITS2(0,1): + assign(srcM, binop(Iop_And64, at64, mkU64(0xFFFF))); break; + case BITS2(1,0): + assign(srcM, binop(Iop_And64, at64, mkU64(0xFFFFFFFF))); break; + case BITS2(1,1): + assign(srcM, at64); break; + default: + vassert(0); + } + + vassert(ix >= 0 && ix <= 7); + + putIReg64orZR( + dd, + unop(Iop_32Uto64, + unop(Iop_64to32, + mkIRExprCCall(Ity_I64, 0/*regparm*/, + hNames[ix], helpers[ix], + mkIRExprVec_2(mkexpr(srcN), + mkexpr(srcM)))))); + + DIP("%s %s, %s, %s\n", iNames[ix], + nameIReg32orZR(dd), + nameIReg32orZR(nn), nameIRegOrZR(bitSF == 1, mm)); + return True; + } + /* fall through */ + } + vex_printf("ARM64 front end: data_processing_register\n"); return False; # undef INSN