65816-llvm-mos/tests/regress/genI64Cmp.py
2026-10-06 17:01:51 -05:00

148 lines
5.9 KiB
Python

#!/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))