#!/usr/bin/env python3 # Emits the C source of the smoke check "i64 compares", with kExp holding # the expected results computed here (C semantics). # # Every i64 predicate (eq ne ult ule ugt uge slt sle sgt sge) on values # that sit on each 16-bit word boundary and both sides of the sign bit: as # a branch, as a 0/1 value and as an i16 select against registers, and as # a branch and a value against ten constants (some with zero low words, # which lowerI32Cmp drops from its CMP/SBC chain), then loops whose i64 # counters cross a 32-bit boundary. Pins the four-word CMP/SBC chain # (SETCC / BR_CC / SELECT_CC on i64 are lowered by lowerI32Cmp). # # Mailbox: 0x025000 = mismatches, 0x025002 = first failing case, # 0x025004 = 0xC0DE when done. V = [ 0x0000000000000000, 0x0000000000000001, 0x000000000000FFFF, 0x0000000000010000, 0x00000000FFFFFFFF, 0x0000000100000000, 0x0000000100000001, 0x0000FFFFFFFFFFFF, 0x0001000000000000, 0x0000800000000000, 0x7FF0000000000000, 0x7FF0000000000001, 0x0001FFFF00000000, 0x7FFFFFFFFFFFFFFF, 0x8000000000000000, 0x8000000000000001, 0xFFFF000000000000, 0xFFFFFFFF00000000, 0xFFFFFFFFFFFF0000, 0xFFFFFFFFFFFFFFFF, ] K = [ 0x0000000000000000, 0x0000000000000001, 0x00000000FFFFFFFF, 0x0000000100000000, 0x7FF0000000000000, 0x7FF0000000000001, 0x7FFFFFFFFFFFFFFF, 0x8000000000000000, 0xFFFF000000000000, 0xFFFFFFFFFFFFFFFF, ] PREDS = [ ("eq", "u64", "=="), ("ne", "u64", "!="), ("ult", "u64", "<"), ("ule", "u64", "<="), ("ugt", "u64", ">"), ("uge", "u64", ">="), ("slt", "s64", "<"), ("sle", "s64", "<="), ("sgt", "s64", ">"), ("sge", "s64", ">="), ] def s64(x): return x - (1 << 64) if x & (1 << 63) else x def ev(t, op, a, b): if t == "s64": a, b = s64(a), s64(b) return {"==": a == b, "!=": a != b, "<": a < b, "<=": a <= b, ">": a > b, ">=": a >= b}[op] bits = [] for _, t, op in PREDS: for a in V: for b in V: bits.append(ev(t, op, a, b)) for _, t, op in PREDS: for k in K: for a in V: bits.append(ev(t, op, a, k)) exp = bytearray((len(bits) + 7) // 8) for i, b in enumerate(bits): if b: exp[i >> 3] |= 1 << (i & 7) o = [] w = o.append w("// i64 compares, generated by tests/regress/genI64Cmp.py; see there.") w("typedef unsigned char u8;") w("typedef unsigned short u16;") w("typedef unsigned long long u64;") w("typedef long long s64;") w("#define NV %du" % len(V)) w("#define NK %du" % len(K)) w("#define NP %du" % len(PREDS)) w('#define BAR() __asm__ volatile("" ::: "memory")') w("#define NOI __attribute__((noinline)) static") w("static volatile u16 gSink;") w("static const u64 kV[NV] = {") for i in range(0, len(V), 3): w(" " + " ".join("0x%016XULL," % v for v in V[i:i + 3])) w("};") w("static const u8 kExp[%d] = {" % len(exp)) for i in range(0, len(exp), 16): w(" " + " ".join("0x%02X," % b for b in exp[i:i + 16])) w("};") for name, t, op in PREDS: w("NOI u16 br_%s(u64 a, u64 b) { if ((%s)a %s (%s)b) { BAR(); return 1u; } return 0u; }" % (name, t, op, t)) w("NOI u16 va_%s(u64 a, u64 b) { return (u16)((%s)a %s (%s)b); }" % (name, t, op, t)) w("NOI u16 se_%s(u64 a, u64 b) { return (%s)a %s (%s)b ? 0x5A5Au : 0xA5A5u; }" % (name, t, op, t)) for i, k in enumerate(K): w("NOI u16 bk_%s_%d(u64 a) { if ((%s)a %s (%s)0x%016XULL) { BAR(); return 1u; } return 0u; }" % (name, i, t, op, t, k)) w("NOI u16 vk_%s_%d(u64 a) { return (u16)((%s)a %s (%s)0x%016XULL); }" % (name, i, t, op, t, k)) w("typedef u16 (*Fn2)(u64, u64);") w("typedef u16 (*Fn1)(u64);") for p in ("br", "va", "se"): w("static Fn2 const k%s[NP] = { %s };" % (p.capitalize(), ", ".join("%s_%s" % (p, n) for n, _, _ in PREDS))) for p in ("bk", "vk"): w("static Fn1 const k%s[NP * NK] = {" % p.capitalize()) for n, _, _ in PREDS: w(" " + " ".join("%s_%s_%d," % (p, n, i) for i in range(len(K)))) w("};") w("NOI u16 loopUlt(u64 s, u64 e) { u16 n = 0u; u64 i; for (i = s; i < e; i++) { gSink = (u16)i; n++; } return n; }") w("NOI u16 loopSge(s64 s, s64 e) { u16 n = 0u; s64 i; for (i = e; i >= s; i--) { gSink = (u16)i; n++; } return n; }") w("NOI u16 loopUgtDown(u64 s, u64 e) { u16 n = 0u; u64 i; for (i = e; i > s; i--) { gSink = (u16)i; n++; } return n; }") w("static u16 gBad;") w("static u16 gFirst = 0xFFFFu;") w("static void check(u16 got, u16 want, u16 id) {") w(" if (got != want) {") w(" if (gBad == 0u) {") w(" gFirst = id;") w(" }") w(" gBad++;") w(" }") w("}") w("int main(void) {") w(" u16 p;") w(" u16 i;") w(" u16 j;") w(" u16 bit = 0u;") w(" for (p = 0u; p < NP; p++) {") w(" for (i = 0u; i < NV; i++) {") w(" for (j = 0u; j < NV; j++) {") w(" u16 want = (u16)((kExp[bit >> 3] >> (bit & 7u)) & 1u);") w(" check(kBr[p](kV[i], kV[j]), want, bit);") w(" check(kVa[p](kV[i], kV[j]), want, (u16)(bit | 0x4000u));") w(" check(kSe[p](kV[i], kV[j]) == 0x5A5Au, want, (u16)(bit | 0x8000u));") w(" bit++;") w(" }") w(" }") w(" }") w(" for (p = 0u; p < NP * NK; p++) {") w(" for (i = 0u; i < NV; i++) {") w(" u16 want = (u16)((kExp[bit >> 3] >> (bit & 7u)) & 1u);") w(" check(kBk[p](kV[i]), want, bit);") w(" check(kVk[p](kV[i]), want, (u16)(bit | 0x4000u));") w(" bit++;") w(" }") w(" }") w(" check(loopUlt(0x00000000FFFFFFF0ULL, 0x0000000100000010ULL), 32u, 0xC000u);") w(" check(loopUlt(0x7FFFFFFFFFFFFFF0ULL, 0x8000000000000010ULL), 32u, 0xC001u);") w(" check(loopSge(-5LL, 5LL), 11u, 0xC002u);") w(" check(loopUgtDown(0x0000FFFFFFFFFFF8ULL, 0x0001000000000008ULL), 16u, 0xC003u);") w(" *(volatile u16 *)0x025000UL = gBad;") w(" *(volatile u16 *)0x025002UL = gFirst;") w(" *(volatile u16 *)0x025004UL = 0xC0DEu;") w(" for (;;) {") w(" }") w(" return 0;") w("}") print("\n".join(o))