/* Does this emulator branch on a predicate's low bit? * * The signal processor's conditional instructions test the least significant * bit of a predicate register. A compiler may build a predicate from a general * register (`p = r`, so `1` gives 0x01) and combine it with a comparison's * (0xff) by `xor`, leaving 0xfe for "equal": its low bit is clear, so a branch * on it is not taken. An emulator that tests the whole register takes it. * * Each case branches on the same predicate twice: written in an earlier packet * (`if (p1) jump`) and in the same packet (`if (p1.new) jump`). Both must test * the low bit. Exit status 0 when they do, 1 when the emulator differs. */ #include static int same_packet(int a, int b) { int r; __asm__ volatile( "{ p2 = %1 }\n" "{ p0 = %2 }\n" "{ p1 = xor(p2,p0)\n if (p1.new) jump:nt 1f }\n" "{ %0 = #0 ; jump 2f }\n" "1: { %0 = #1 }\n" "2:\n" : "=&r"(r) : "r"(a), "r"(b) : "p0", "p1", "p2"); return r; } static int earlier_packet(int a, int b) { int r; __asm__ volatile( "{ p2 = %1 }\n" "{ p0 = %2 }\n" "{ p1 = xor(p2,p0) }\n" "{ if (p1) jump:nt 1f }\n" "{ %0 = #0 ; jump 2f }\n" "1: { %0 = #1 }\n" "2:\n" : "=&r"(r) : "r"(a), "r"(b) : "p0", "p1", "p2"); return r; } int main(void) { /* (p2, p0): the predicate is their xor; taken iff its low bit is set. */ static const int cases[][2] = {{1, 0xff}, {0xff, 0xff}, {1, 1}, {0, 0xff}, {0, 1}, {0xfe, 0}, {2, 0}}; int bad = 0; for (unsigned i = 0; i < sizeof cases / sizeof cases[0]; i++) { int a = cases[i][0], b = cases[i][1], want = (a ^ b) & 1; int n = same_packet(a, b), o = earlier_packet(a, b); printf("predicate %#04x: same packet %s, earlier packet %s, low bit %s\n", (a ^ b) & 0xff, n ? "taken" : "not taken", o ? "taken" : "not taken", want ? "set" : "clear"); bad += (n != want) + (o != want); } printf(bad ? "this emulator does not branch on the low bit\n" : "this emulator branches on the low bit\n"); return bad != 0; }