File size: 8,056 Bytes
a17e28f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
 * diff-oracle.c -- rea-unary
 * Copyright (C) 2026 Ahmad Ali Parr
 * SPDX-License-Identifier: LicenseRef-AGPL-3.0-NoAI-1.0
 *
 * Licensed under the GNU Affero General Public License v3 with an
 * additional no-AI-training term (see LICENSE). This code may not be
 * used to train machine-learning models.
 */
// Author's rights notice (Ahmad Ali Parr):
// Binary -> IR -> VHDL -> netlist: changing representation itself clears rights.
// Behavioral specification -> independently authored implementation: as extracted and reproduced.
// Provenance: stage3 (worker3), v1. Parents: stage3/addmod.h, stage3/addmod.c,
//   stage3/traces.csv. Full hashes in stage3/PROVENANCE.json.
//
// Differential oracle: executes the REAL x86 `ADD EAX, EBX` (bytes 01 D8) on
// this machine's silicon via inline assembly, captures EAX and EFLAGS, and
// compares register-by-register (result + CF, PF, AF, ZF, SF, OF) against:
//   (1) the C11 model (addmod32), and
//   (2) the GHDL simulation's EXECUTE rows from traces.csv.
// Also: --hypothesis-check mode tests one specific hypothesis claim against
// silicon (used for the counterexample-loop demo).
//
// Usage:
//   ./diff-oracle                 -- full differential run over 10 vectors
//   ./diff-oracle --hypothesis-check
//                                 -- test "ADD sets CF on signed overflow"
//                                    on a=0x7FFFFFFF,b=0x00000001; exit 1 if refuted
#define _POSIX_C_SOURCE 200809L
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "addmod.h"

/* ---- real silicon: execute ADD EAX, EBX, capture EAX + EFLAGS ---- */
static void silicon_add(uint32_t a, uint32_t b, uint32_t *res, uint32_t *eflags)
{
    uint32_t r, fl;
    __asm__ volatile (
        "movl %2, %%eax\n\t"
        "movl %3, %%ebx\n\t"
        "addl %%ebx, %%eax\n\t"   /* the actual 01 D8 operation */
        "pushfq\n\t"
        "popq %%rdx\n\t"
        "movl %%eax, %0\n\t"
        "movl %%edx, %1\n\t"
        : "=r" (r), "=r" (fl)
        : "r" (a), "r" (b)
        : "eax", "ebx", "edx", "cc");
    *res = r;
    *eflags = fl;
}

#define F_CF (1u << 0)
#define F_PF (1u << 2)
#define F_AF (1u << 4)
#define F_ZF (1u << 6)
#define F_SF (1u << 7)
#define F_OF (1u << 11)

typedef struct {
    uint32_t result;
    uint8_t cf, pf, af, zf, sf, of;
} regset_t;

static regset_t from_silicon(uint32_t a, uint32_t b)
{
    uint32_t r, fl;
    regset_t s;
    silicon_add(a, b, &r, &fl);
    s.result = r;
    s.cf = (fl & F_CF) != 0;
    s.pf = (fl & F_PF) != 0;
    s.af = (fl & F_AF) != 0;
    s.zf = (fl & F_ZF) != 0;
    s.sf = (fl & F_SF) != 0;
    s.of = (fl & F_OF) != 0;
    return s;
}

static regset_t from_cmodel(uint32_t a, uint32_t b)
{
    add_flags_t f;
    regset_t s;
    s.result = addmod32(a, b, &f);
    s.cf = f.cf; s.pf = f.pf; s.af = f.af;
    s.zf = f.zf; s.sf = f.sf; s.of = f.of;
    return s;
}

static const uint32_t VA[10] = {
    0x00000000u, 0xFFFFFFFFu, 0x7FFFFFFFu, 0x00000008u, 0x00000003u,
    0x00000001u, 0x80000000u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu
};
static const uint32_t VB[10] = {
    0x00000000u, 0x00000001u, 0x00000001u, 0x00000008u, 0x00000000u,
    0x00000000u, 0x80000000u, 0x7FFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu
};

static int cmp_reg(const char *impl, int vec, const char *reg,
                   uint32_t got, uint32_t want, int *pass, int *fail)
{
    if (got == want) {
        (*pass)++;
        printf("  [PASS] vec %d %-4s %-6s got=%08X want=%08X\n",
               vec, impl, reg, got, want);
        return 1;
    }
    (*fail)++;
    printf("  [FAIL] vec %d %-4s %-6s got=%08X want=%08X\n",
           vec, impl, reg, got, want);
    return 0;
}

/* read the i-th EXECUTE row (0-based) from traces.csv */
static int read_ghdl_exec_row(int idx, regset_t *out)
{
    FILE *fp = fopen("traces.csv", "r");
    char line[256];
    int n = -1;
    if (!fp) { perror("traces.csv"); return 0; }
    if (!fgets(line, sizeof line, fp)) { fclose(fp); return 0; } /* header */
    while (fgets(line, sizeof line, fp)) {
        char state[16], sa[9], sb[9], sr[9];
        int cf, pf, af, zf, sf, of;
        unsigned cyc;
        if (sscanf(line, "%u,%15[^,],%8[^,],%8[^,],%8[^,],%d,%d,%d,%d,%d,%d",
                   &cyc, state, sa, sb, sr, &cf, &pf, &af, &zf, &sf, &of) != 11)
            continue; /* 11 conversions; the trailing `done` column is not needed here */
        if (strcmp(state, "EXECUTE") != 0)
            continue;
        if (++n == idx) {
            out->result = (uint32_t)strtoul(sr, NULL, 16);
            out->cf = (uint8_t)cf; out->pf = (uint8_t)pf;
            out->af = (uint8_t)af; out->zf = (uint8_t)zf;
            out->sf = (uint8_t)sf; out->of = (uint8_t)of;
            fclose(fp);
            return 1;
        }
    }
    fclose(fp);
    return 0;
}

static int hypothesis_check(void)
{
    /* Wrong hypothesis h-wrong1: "ADD sets CF on signed overflow".
     * Test vector: a=0x7FFFFFFF, b=0x00000001 (signed overflow: +max + 1). */
    const uint32_t a = 0x7FFFFFFFu, b = 0x00000001u;
    regset_t s = from_silicon(a, b);
    printf("hypothesis: h-wrong1 \"ADD sets CF on signed overflow\"\n");
    printf("vector: a=0x%08X b=0x%08X\n", a, b);
    printf("expected_per_hypothesis: cf=1\n");
    printf("observed_silicon: result=0x%08X cf=%u pf=%u af=%u zf=%u sf=%u of=%u\n",
           s.result, s.cf, s.pf, s.af, s.zf, s.sf, s.of);
    if (s.cf == 1) {
        printf("verdict: CONFIRMED (unexpected)\n");
        return 0;
    }
    printf("verdict: REFUTED -- silicon shows CF=0, OF=1 on signed overflow; "
           "CF is the unsigned carry-out, OF reports signed overflow\n");
    return 1;
}

int main(int argc, char **argv)
{
    if (argc > 1 && strcmp(argv[1], "--hypothesis-check") == 0)
        return hypothesis_check();

    int pass = 0, fail = 0;
    printf("differential oracle: real x86 silicon (ADD EAX,EBX) vs "
           "C11 model vs GHDL sim\n");
    printf("registers compared per vector: result cf pf af zf sf of\n\n");

    for (int v = 0; v < 10; v++) {
        regset_t sil = from_silicon(VA[v], VB[v]);
        regset_t cm  = from_cmodel(VA[v], VB[v]);
        regset_t gh;
        int have_ghdl = read_ghdl_exec_row(v, &gh);

        printf("vec %d a=%08X b=%08X\n", v, VA[v], VB[v]);
        printf("  silicon: result=%08X cf=%u pf=%u af=%u zf=%u sf=%u of=%u\n",
               sil.result, sil.cf, sil.pf, sil.af, sil.zf, sil.sf, sil.of);
        printf("  cmodel : result=%08X cf=%u pf=%u af=%u zf=%u sf=%u of=%u\n",
               cm.result, cm.cf, cm.pf, cm.af, cm.zf, cm.sf, cm.of);
        cmp_reg("cmodel", v, "result", cm.result, sil.result, &pass, &fail);
        cmp_reg("cmodel", v, "cf", cm.cf, sil.cf, &pass, &fail);
        cmp_reg("cmodel", v, "pf", cm.pf, sil.pf, &pass, &fail);
        cmp_reg("cmodel", v, "af", cm.af, sil.af, &pass, &fail);
        cmp_reg("cmodel", v, "zf", cm.zf, sil.zf, &pass, &fail);
        cmp_reg("cmodel", v, "sf", cm.sf, sil.sf, &pass, &fail);
        cmp_reg("cmodel", v, "of", cm.of, sil.of, &pass, &fail);

        if (have_ghdl) {
            printf("  ghdl   : result=%08X cf=%u pf=%u af=%u zf=%u sf=%u of=%u\n",
                   gh.result, gh.cf, gh.pf, gh.af, gh.zf, gh.sf, gh.of);
            cmp_reg("ghdl", v, "result", gh.result, sil.result, &pass, &fail);
            cmp_reg("ghdl", v, "cf", gh.cf, sil.cf, &pass, &fail);
            cmp_reg("ghdl", v, "pf", gh.pf, sil.pf, &pass, &fail);
            cmp_reg("ghdl", v, "af", gh.af, sil.af, &pass, &fail);
            cmp_reg("ghdl", v, "zf", gh.zf, sil.zf, &pass, &fail);
            cmp_reg("ghdl", v, "sf", gh.sf, sil.sf, &pass, &fail);
            cmp_reg("ghdl", v, "of", gh.of, sil.of, &pass, &fail);
        } else {
            printf("  ghdl   : MISSING EXECUTE row %d in traces.csv\n", v);
            fail += 7;
        }
        printf("\n");
    }
    printf("differential summary: %d PASS, %d FAIL (140 comparisons = "
           "10 vectors x 7 registers x 2 implementations)\n", pass, fail);
    return fail ? 1 : 0;
}