FAILURE MAP
← Case archive

FA-89626 / Instruction set emulation / Open access

High-digit adjust tests the already adjusted value · case 01

A low-digit adjust that pushes the byte past 0x99 triggers a spurious +0x60.

Verified by executionVariant 1 · 10 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The second adjust condition uses the value after the +6 correction.

VERIFIED REPAIR

Compare the value before any adjustment against 0x99.

Unsuccessful approach: A 0x9F threshold misses high digits of A..F with a small low digit.

Case contract

Input [xs, ys, c]: little-endian packed-BCD byte lists and a carry-in. For each byte: s = a+b+c; AF = low-nibble sum (with carry) > 0x0F; CF = s > 0xFF; al = s & 0xFF. Decimal adjust: if (al & 0x0F) > 9 or AF then al += 6 (8-bit wrap); then if the pre-adjust al > 0x99 or CF then al += 0x60 (8-bit wrap) and carry-out = 1, else carry-out = 0. The carry-out feeds the next byte. Return [result bytes, final carry].

Why this case matters

Decimal-adjust instructions are among the hardest to emulate; the flag inputs and the pre-adjust comparison decide the result.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(*args):
    xs, ys, c = args
    out = []
    for a, b in zip(xs, ys):
        s = a + b + c
        af = int((a & 0x0F) + (b & 0x0F) + c > 0x0F)
        cf = int(s > 0xFF)
        al = s & 0xFF
        old_al, old_cf = al, cf
        if (al & 0x0F) > 9 or af:
            al = (al + 6) & 0xFF
        if al > 0x99 or old_cf:
            al = (al + 0x60) & 0xFF
            c = 1
        else:
            c = 0
        out.append(al)
    return [out, c]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[24, 0], [8, 0], 0], [[38, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[24, 0], [7, 0], 1], [[38, 0], 0]), ('high digit overflow and carry out', [[144, 85], [48, 68], 0], [[32, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 1], 0], [[152, 1], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 2], 0], [[156, 2], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[25, 0], [8, 0], 0], [[39, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[40, 0], [7, 0], 1], [[54, 0], 0]), ('high digit overflow and carry out', [[144, 85], [64, 68], 0], [[48, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 2], 0], [[152, 2], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 3], 0], [[156, 3], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[24, 0], [8, 0], 0], [[38, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[8, 0], [7, 0], 1], [[22, 0], 0]), ('high digit overflow and carry out', [[144, 85], [32, 68], 0], [[16, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 3], 0], [[152, 3], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 4], 0], [[156, 4], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[25, 0], [8, 0], 0], [[39, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[24, 0], [7, 0], 1], [[38, 0], 0]), ('high digit overflow and carry out', [[144, 85], [48, 68], 0], [[32, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 4], 0], [[152, 4], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 5], 0], [[156, 5], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[24, 0], [8, 0], 0], [[38, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[40, 0], [7, 0], 1], [[54, 0], 0]), ('high digit overflow and carry out', [[144, 85], [64, 68], 0], [[48, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 5], 0], [[152, 5], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 6], 0], [[156, 6], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])]]
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 fixtureActualExpectedOutcome
digits without adjust[[51, 119], 0][[51, 119], 0]Passed
low digit overflow[[38, 0], 0][[38, 0], 0]Passed
half carry without low digit above nine[[24, 16], 0][[24, 16], 0]Passed
carry-in feeds half carry[[38, 0], 0][[38, 0], 0]Passed
high digit overflow and carry out[[32, 0], 1][[32, 0], 1]Passed
low adjust pushes high digit[[0, 1], 0][[0, 1], 0]Passed
binary carry from high digits[[152, 1], 1][[152, 1], 1]Passed
carry chains across bytes[[1, 16, 0], 0][[1, 16, 0], 0]Passed
non-decimal low digit[[252, 3], 0][[156, 2], 0]Failed
high digit exactly A[[0, 2], 0][[0, 2], 0]Passed

SHA-256 / f5efdf874cf97fb4bf8f35826666c364eba77f257d1796b8fc8cc043ad4218a3

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(*args):
    xs, ys, c = args
    out = []
    for a, b in zip(xs, ys):
        s = a + b + c
        af = int((a & 0x0F) + (b & 0x0F) + c > 0x0F)
        cf = int(s > 0xFF)
        al = s & 0xFF
        old_al, old_cf = al, cf
        if (al & 0x0F) > 9 or af:
            al = (al + 6) & 0xFF
        if old_al > 0x9F or old_cf:
            al = (al + 0x60) & 0xFF
            c = 1
        else:
            c = 0
        out.append(al)
    return [out, c]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[24, 0], [8, 0], 0], [[38, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[24, 0], [7, 0], 1], [[38, 0], 0]), ('high digit overflow and carry out', [[144, 85], [48, 68], 0], [[32, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 1], 0], [[152, 1], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 2], 0], [[156, 2], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[25, 0], [8, 0], 0], [[39, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[40, 0], [7, 0], 1], [[54, 0], 0]), ('high digit overflow and carry out', [[144, 85], [64, 68], 0], [[48, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 2], 0], [[152, 2], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 3], 0], [[156, 3], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[24, 0], [8, 0], 0], [[38, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[8, 0], [7, 0], 1], [[22, 0], 0]), ('high digit overflow and carry out', [[144, 85], [32, 68], 0], [[16, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 3], 0], [[152, 3], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 4], 0], [[156, 4], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[25, 0], [8, 0], 0], [[39, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[24, 0], [7, 0], 1], [[38, 0], 0]), ('high digit overflow and carry out', [[144, 85], [48, 68], 0], [[32, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 4], 0], [[152, 4], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 5], 0], [[156, 5], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[24, 0], [8, 0], 0], [[38, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[40, 0], [7, 0], 1], [[54, 0], 0]), ('high digit overflow and carry out', [[144, 85], [64, 68], 0], [[48, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 5], 0], [[152, 5], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 6], 0], [[156, 6], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])]]
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 fixtureActualExpectedOutcome
digits without adjust[[51, 119], 0][[51, 119], 0]Passed
low digit overflow[[38, 0], 0][[38, 0], 0]Passed
half carry without low digit above nine[[24, 16], 0][[24, 16], 0]Passed
carry-in feeds half carry[[38, 0], 0][[38, 0], 0]Passed
high digit overflow and carry out[[32, 160], 0][[32, 0], 1]Failed
low adjust pushes high digit[[160, 0], 0][[0, 1], 0]Failed
binary carry from high digits[[152, 161], 0][[152, 1], 1]Failed
carry chains across bytes[[161, 9, 0], 0][[1, 16, 0], 0]Failed
non-decimal low digit[[156, 2], 0][[156, 2], 0]Passed
high digit exactly A[[160, 1], 0][[0, 2], 0]Failed

SHA-256 / 7d9f7027ddb3051eab814d0a62b16f05e945efedd5e90b6adfdf0769dff49957

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(*args):
    xs, ys, c = args
    out = []
    for a, b in zip(xs, ys):
        s = a + b + c
        af = int((a & 0x0F) + (b & 0x0F) + c > 0x0F)
        cf = int(s > 0xFF)
        al = s & 0xFF
        old_al, old_cf = al, cf
        if (al & 0x0F) > 9 or af:
            al = (al + 6) & 0xFF
        if old_al > 0x99 or old_cf:
            al = (al + 0x60) & 0xFF
            c = 1
        else:
            c = 0
        out.append(al)
    return [out, c]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[24, 0], [8, 0], 0], [[38, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[24, 0], [7, 0], 1], [[38, 0], 0]), ('high digit overflow and carry out', [[144, 85], [48, 68], 0], [[32, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 1], 0], [[152, 1], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 2], 0], [[156, 2], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[25, 0], [8, 0], 0], [[39, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[40, 0], [7, 0], 1], [[54, 0], 0]), ('high digit overflow and carry out', [[144, 85], [64, 68], 0], [[48, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 2], 0], [[152, 2], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 3], 0], [[156, 3], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[24, 0], [8, 0], 0], [[38, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[8, 0], [7, 0], 1], [[22, 0], 0]), ('high digit overflow and carry out', [[144, 85], [32, 68], 0], [[16, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 3], 0], [[152, 3], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 4], 0], [[156, 4], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[25, 0], [8, 0], 0], [[39, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[24, 0], [7, 0], 1], [[38, 0], 0]), ('high digit overflow and carry out', [[144, 85], [48, 68], 0], [[32, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 4], 0], [[152, 4], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 5], 0], [[156, 5], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])], [('digits without adjust', [[18, 52], [33, 67], 0], [[51, 119], 0]), ('low digit overflow', [[24, 0], [8, 0], 0], [[38, 0], 0]), ('half carry without low digit above nine', [[9, 16], [9, 0], 0], [[24, 16], 0]), ('carry-in feeds half carry', [[40, 0], [7, 0], 1], [[54, 0], 0]), ('high digit overflow and carry out', [[144, 85], [64, 68], 0], [[48, 0], 1]), ('low adjust pushes high digit', [[149, 0], [5, 0], 0], [[0, 1], 0]), ('binary carry from high digits', [[153, 153], [153, 5], 0], [[152, 5], 1]), ('carry chains across bytes', [[153, 9, 0], [1, 0, 0], 1], [[1, 16, 0], 0]), ('non-decimal low digit', [[143, 0], [7, 6], 0], [[156, 6], 0]), ('high digit exactly A', [[80, 1], [74, 0], 0], [[0, 2], 0])]]
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 fixtureActualExpectedOutcome
digits without adjust[[51, 119], 0][[51, 119], 0]Passed
low digit overflow[[38, 0], 0][[38, 0], 0]Passed
half carry without low digit above nine[[24, 16], 0][[24, 16], 0]Passed
carry-in feeds half carry[[38, 0], 0][[38, 0], 0]Passed
high digit overflow and carry out[[32, 0], 1][[32, 0], 1]Passed
low adjust pushes high digit[[0, 1], 0][[0, 1], 0]Passed
binary carry from high digits[[152, 1], 1][[152, 1], 1]Passed
carry chains across bytes[[1, 16, 0], 0][[1, 16, 0], 0]Passed
non-decimal low digit[[156, 2], 0][[156, 2], 0]Passed
high digit exactly A[[0, 2], 0][[0, 2], 0]Passed

SHA-256 / f93c5508c70d57fbe14465c9a3420c9e8add4d3804d6c1352c9c6e62b8af554c

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:19.211635+00:00.

Case digest / aabed24b6b3eae75addc83ac415e98875f8c259e5eb99102a79615bf35768604