FA-89486 / Instruction set emulation / Open access
Signed operands never recognised as negative · case 01
div and rem treat negative register values as huge unsigned numbers.
ROOT CAUSE
The sign test inspects bit 32, which is never set in a 32-bit value.
VERIFIED REPAIR
A register value is negative when bit 31 is set; subtract 2^32.
Unsuccessful approach: Subtracting 2^31 produces the wrong magnitude.
Case contract
Input [op, a, b] with a, b as unsigned 32-bit register values. div/rem interpret them as signed; quotient truncates toward zero and the remainder takes the dividend's sign; division by zero gives quotient all ones (0xFFFFFFFF) and remainder = dividend; the overflow case -2^31 / -1 gives -2^31 with remainder 0. divu/remu are unsigned; divu by zero gives 0xFFFFFFFF and remu by zero gives the dividend. Results are returned as unsigned 32-bit values.
Why this case matters
ISA emulators must reproduce defined results for division corner cases that host languages treat differently or trap on.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
op, a, b = args
M = 0xFFFFFFFF
def s(v):
return v - (1 << 32) if v >> 32 else v
if op == 'divu':
return M if b == 0 else a // b
if op == 'remu':
return a if b == 0 else a % b
sa, sb = s(a), s(b)
if b == 0:
return M if op == 'div' else a
q = abs(sa) // abs(sb)
if (sa < 0) != (sb < 0):
q = -q
if op == 'div':
return q & M
return (sa - q * sb) & M
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('signed division truncates toward zero', ['div', 4294967287, 2], 4294967292), ('signed division negative divisor', ['div', 9, 4294967294], 4294967292), ('signed remainder sign follows dividend', ['rem', 4294967287, 2], 4294967295), ('remainder with negative divisor', ['rem', 9, 4294967294], 1), ('signed divide by zero', ['div', 6, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967286, 0], 4294967286), ('unsigned divide by zero', ['divu', 4, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483649, 0], 2147483649), ('unsigned division of high values', ['divu', 4294967279, 3], 1431655759), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967286, 4294967294], 5)], [('signed division truncates toward zero', ['div', 4294967285, 2], 4294967291), ('signed division negative divisor', ['div', 11, 4294967294], 4294967291), ('signed remainder sign follows dividend', ['rem', 4294967285, 2], 4294967295), ('remainder with negative divisor', ['rem', 11, 4294967294], 1), ('signed divide by zero', ['div', 7, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967285, 0], 4294967285), ('unsigned divide by zero', ['divu', 5, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483650, 0], 2147483650), ('unsigned division of high values', ['divu', 4294967278, 3], 1431655759), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967285, 4294967294], 5)], [('signed division truncates toward zero', ['div', 4294967283, 2], 4294967290), ('signed division negative divisor', ['div', 13, 4294967294], 4294967290), ('signed remainder sign follows dividend', ['rem', 4294967283, 2], 4294967295), ('remainder with negative divisor', ['rem', 13, 4294967294], 1), ('signed divide by zero', ['div', 8, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967284, 0], 4294967284), ('unsigned divide by zero', ['divu', 6, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483651, 0], 2147483651), ('unsigned division of high values', ['divu', 4294967277, 3], 1431655759), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967284, 4294967294], 6)], [('signed division truncates toward zero', ['div', 4294967281, 2], 4294967289), ('signed division negative divisor', ['div', 15, 4294967294], 4294967289), ('signed remainder sign follows dividend', ['rem', 4294967281, 2], 4294967295), ('remainder with negative divisor', ['rem', 15, 4294967294], 1), ('signed divide by zero', ['div', 9, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967283, 0], 4294967283), ('unsigned divide by zero', ['divu', 7, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483652, 0], 2147483652), ('unsigned division of high values', ['divu', 4294967276, 3], 1431655758), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967283, 4294967294], 6)], [('signed division truncates toward zero', ['div', 4294967279, 2], 4294967288), ('signed division negative divisor', ['div', 17, 4294967294], 4294967288), ('signed remainder sign follows dividend', ['rem', 4294967279, 2], 4294967295), ('remainder with negative divisor', ['rem', 17, 4294967294], 1), ('signed divide by zero', ['div', 10, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967282, 0], 4294967282), ('unsigned divide by zero', ['divu', 8, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483653, 0], 2147483653), ('unsigned division of high values', ['divu', 4294967275, 3], 1431655758), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967282, 4294967294], 7)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| signed division truncates toward zero | 2147483643 | 4294967292 | Failed |
| signed division negative divisor | 0 | 4294967292 | Failed |
| signed remainder sign follows dividend | 1 | 4294967295 | Failed |
| remainder with negative divisor | 9 | 1 | Failed |
| signed divide by zero | 4294967295 | 4294967295 | Passed |
| signed remainder by zero | 4294967286 | 4294967286 | Passed |
| unsigned divide by zero | 4294967295 | 4294967295 | Passed |
| unsigned remainder by zero | 2147483649 | 2147483649 | Passed |
| unsigned division of high values | 1431655759 | 1431655759 | Passed |
| signed overflow case | 0 | 2147483648 | Failed |
| both negative | 0 | 5 | Failed |
SHA-256 / 2376a552956641419945f324d8dc59d29a1749324de7a6e9e10c3ffc7bc84109
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
op, a, b = args
M = 0xFFFFFFFF
def s(v):
return v - (1 << 31) if v >> 31 else v
if op == 'divu':
return M if b == 0 else a // b
if op == 'remu':
return a if b == 0 else a % b
sa, sb = s(a), s(b)
if b == 0:
return M if op == 'div' else a
q = abs(sa) // abs(sb)
if (sa < 0) != (sb < 0):
q = -q
if op == 'div':
return q & M
return (sa - q * sb) & M
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('signed division truncates toward zero', ['div', 4294967287, 2], 4294967292), ('signed division negative divisor', ['div', 9, 4294967294], 4294967292), ('signed remainder sign follows dividend', ['rem', 4294967287, 2], 4294967295), ('remainder with negative divisor', ['rem', 9, 4294967294], 1), ('signed divide by zero', ['div', 6, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967286, 0], 4294967286), ('unsigned divide by zero', ['divu', 4, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483649, 0], 2147483649), ('unsigned division of high values', ['divu', 4294967279, 3], 1431655759), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967286, 4294967294], 5)], [('signed division truncates toward zero', ['div', 4294967285, 2], 4294967291), ('signed division negative divisor', ['div', 11, 4294967294], 4294967291), ('signed remainder sign follows dividend', ['rem', 4294967285, 2], 4294967295), ('remainder with negative divisor', ['rem', 11, 4294967294], 1), ('signed divide by zero', ['div', 7, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967285, 0], 4294967285), ('unsigned divide by zero', ['divu', 5, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483650, 0], 2147483650), ('unsigned division of high values', ['divu', 4294967278, 3], 1431655759), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967285, 4294967294], 5)], [('signed division truncates toward zero', ['div', 4294967283, 2], 4294967290), ('signed division negative divisor', ['div', 13, 4294967294], 4294967290), ('signed remainder sign follows dividend', ['rem', 4294967283, 2], 4294967295), ('remainder with negative divisor', ['rem', 13, 4294967294], 1), ('signed divide by zero', ['div', 8, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967284, 0], 4294967284), ('unsigned divide by zero', ['divu', 6, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483651, 0], 2147483651), ('unsigned division of high values', ['divu', 4294967277, 3], 1431655759), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967284, 4294967294], 6)], [('signed division truncates toward zero', ['div', 4294967281, 2], 4294967289), ('signed division negative divisor', ['div', 15, 4294967294], 4294967289), ('signed remainder sign follows dividend', ['rem', 4294967281, 2], 4294967295), ('remainder with negative divisor', ['rem', 15, 4294967294], 1), ('signed divide by zero', ['div', 9, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967283, 0], 4294967283), ('unsigned divide by zero', ['divu', 7, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483652, 0], 2147483652), ('unsigned division of high values', ['divu', 4294967276, 3], 1431655758), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967283, 4294967294], 6)], [('signed division truncates toward zero', ['div', 4294967279, 2], 4294967288), ('signed division negative divisor', ['div', 17, 4294967294], 4294967288), ('signed remainder sign follows dividend', ['rem', 4294967279, 2], 4294967295), ('remainder with negative divisor', ['rem', 17, 4294967294], 1), ('signed divide by zero', ['div', 10, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967282, 0], 4294967282), ('unsigned divide by zero', ['divu', 8, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483653, 0], 2147483653), ('unsigned division of high values', ['divu', 4294967275, 3], 1431655758), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967282, 4294967294], 7)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| signed division truncates toward zero | 1073741819 | 4294967292 | Failed |
| signed division negative divisor | 0 | 4294967292 | Failed |
| signed remainder sign follows dividend | 1 | 4294967295 | Failed |
| remainder with negative divisor | 9 | 1 | Failed |
| signed divide by zero | 4294967295 | 4294967295 | Passed |
| signed remainder by zero | 4294967286 | 4294967286 | Passed |
| unsigned divide by zero | 4294967295 | 4294967295 | Passed |
| unsigned remainder by zero | 2147483649 | 2147483649 | Passed |
| unsigned division of high values | 1431655759 | 1431655759 | Passed |
| signed overflow case | 0 | 2147483648 | Failed |
| both negative | 0 | 5 | Failed |
SHA-256 / 1154038bdda1922cc7529cf3a2c7f321b31815d9e642e4174542a7361ce9c8fa
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(*args):
op, a, b = args
M = 0xFFFFFFFF
def s(v):
return v - (1 << 32) if v >> 31 else v
if op == 'divu':
return M if b == 0 else a // b
if op == 'remu':
return a if b == 0 else a % b
sa, sb = s(a), s(b)
if b == 0:
return M if op == 'div' else a
q = abs(sa) // abs(sb)
if (sa < 0) != (sb < 0):
q = -q
if op == 'div':
return q & M
return (sa - q * sb) & M
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('signed division truncates toward zero', ['div', 4294967287, 2], 4294967292), ('signed division negative divisor', ['div', 9, 4294967294], 4294967292), ('signed remainder sign follows dividend', ['rem', 4294967287, 2], 4294967295), ('remainder with negative divisor', ['rem', 9, 4294967294], 1), ('signed divide by zero', ['div', 6, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967286, 0], 4294967286), ('unsigned divide by zero', ['divu', 4, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483649, 0], 2147483649), ('unsigned division of high values', ['divu', 4294967279, 3], 1431655759), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967286, 4294967294], 5)], [('signed division truncates toward zero', ['div', 4294967285, 2], 4294967291), ('signed division negative divisor', ['div', 11, 4294967294], 4294967291), ('signed remainder sign follows dividend', ['rem', 4294967285, 2], 4294967295), ('remainder with negative divisor', ['rem', 11, 4294967294], 1), ('signed divide by zero', ['div', 7, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967285, 0], 4294967285), ('unsigned divide by zero', ['divu', 5, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483650, 0], 2147483650), ('unsigned division of high values', ['divu', 4294967278, 3], 1431655759), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967285, 4294967294], 5)], [('signed division truncates toward zero', ['div', 4294967283, 2], 4294967290), ('signed division negative divisor', ['div', 13, 4294967294], 4294967290), ('signed remainder sign follows dividend', ['rem', 4294967283, 2], 4294967295), ('remainder with negative divisor', ['rem', 13, 4294967294], 1), ('signed divide by zero', ['div', 8, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967284, 0], 4294967284), ('unsigned divide by zero', ['divu', 6, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483651, 0], 2147483651), ('unsigned division of high values', ['divu', 4294967277, 3], 1431655759), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967284, 4294967294], 6)], [('signed division truncates toward zero', ['div', 4294967281, 2], 4294967289), ('signed division negative divisor', ['div', 15, 4294967294], 4294967289), ('signed remainder sign follows dividend', ['rem', 4294967281, 2], 4294967295), ('remainder with negative divisor', ['rem', 15, 4294967294], 1), ('signed divide by zero', ['div', 9, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967283, 0], 4294967283), ('unsigned divide by zero', ['divu', 7, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483652, 0], 2147483652), ('unsigned division of high values', ['divu', 4294967276, 3], 1431655758), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967283, 4294967294], 6)], [('signed division truncates toward zero', ['div', 4294967279, 2], 4294967288), ('signed division negative divisor', ['div', 17, 4294967294], 4294967288), ('signed remainder sign follows dividend', ['rem', 4294967279, 2], 4294967295), ('remainder with negative divisor', ['rem', 17, 4294967294], 1), ('signed divide by zero', ['div', 10, 0], 4294967295), ('signed remainder by zero', ['rem', 4294967282, 0], 4294967282), ('unsigned divide by zero', ['divu', 8, 0], 4294967295), ('unsigned remainder by zero', ['remu', 2147483653, 0], 2147483653), ('unsigned division of high values', ['divu', 4294967275, 3], 1431655758), ('signed overflow case', ['div', 2147483648, 4294967295], 2147483648), ('both negative', ['div', 4294967282, 4294967294], 7)]]
for label, args, expected in fixtures[N-1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| signed division truncates toward zero | 4294967292 | 4294967292 | Passed |
| signed division negative divisor | 4294967292 | 4294967292 | Passed |
| signed remainder sign follows dividend | 4294967295 | 4294967295 | Passed |
| remainder with negative divisor | 1 | 1 | Passed |
| signed divide by zero | 4294967295 | 4294967295 | Passed |
| signed remainder by zero | 4294967286 | 4294967286 | Passed |
| unsigned divide by zero | 4294967295 | 4294967295 | Passed |
| unsigned remainder by zero | 2147483649 | 2147483649 | Passed |
| unsigned division of high values | 1431655759 | 1431655759 | Passed |
| signed overflow case | 2147483648 | 2147483648 | Passed |
| both negative | 5 | 5 | Passed |
SHA-256 / 3bf675347c0be212f7e143bdc9f7a017a06adaaf9b359566a7f452a4ad6b794c
Verification & scope
A deterministic bounded teaching model of one emulator rule; the instruction semantics are a stipulated contract inspired by common ISAs and are not a claim of cycle-exact or architectural conformance. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:17.933730+00:00.
Case digest / e7b24efc29cdc6d3c3370051fc84953a03c7a1ba40709a4d879b16e629fdff45