The x87 stack controls, the D8/DC arithmetic pair, the conditional moves, the register compares, FADDDP, the memory loads and the FXSAVE pair, each pinned byte for byte against go tool asm through every corpus line the toolchain's own amd64enc.s carries for the family (78 lines). Assisted-by: GLM 5.3 Flash
111 lines
3.0 KiB
Go
111 lines
3.0 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package asm
|
|
|
|
import "testing"
|
|
|
|
// amd64X87Corpus holds every line the Go toolchain's own
|
|
// amd64enc.s carries for the x87 family (stack controls, the arithmetic pair, the compares, the memory loads and the FXSAVE pair), with the bytes go tool asm
|
|
// emits for each: the differential ground truth the family is proven
|
|
// against, line for line.
|
|
var amd64X87Corpus = []struct {
|
|
line string
|
|
want string
|
|
}{
|
|
{"F2XM1", "d9 f0"},
|
|
{"FABS", "d9 e1"},
|
|
{"FADDD F2, F0", "d8 c2"},
|
|
{"FADDD F3, F0", "d8 c3"},
|
|
{"FADDD F0, F2", "dc c2"},
|
|
{"FADDD F0, F3", "dc c3"},
|
|
{"FADDD (BX), F0", "dc 03"},
|
|
{"FADDD (R11), F0", "41 dc 03"},
|
|
{"FADDDP F0, F2", "de c2"},
|
|
{"FADDDP F0, F3", "de c3"},
|
|
{"FBLD (BX)", "df 23"},
|
|
{"FBLD (R11)", "41 df 23"},
|
|
{"FBSTP (BX)", "df 33"},
|
|
{"FBSTP (R11)", "41 df 33"},
|
|
{"FCHS", "d9 e0"},
|
|
{"FCMOVB F2, F0", "da c2"},
|
|
{"FCMOVB F3, F0", "da c3"},
|
|
{"FCMOVBE F2, F0", "da d2"},
|
|
{"FCMOVBE F3, F0", "da d3"},
|
|
{"FCMOVE F2, F0", "da ca"},
|
|
{"FCMOVE F3, F0", "da cb"},
|
|
{"FCMOVNB F2, F0", "db c2"},
|
|
{"FCMOVNB F3, F0", "db c3"},
|
|
{"FCMOVNBE F2, F0", "db d2"},
|
|
{"FCMOVNBE F3, F0", "db d3"},
|
|
{"FCMOVNE F2, F0", "db ca"},
|
|
{"FCMOVNE F3, F0", "db cb"},
|
|
{"FCMOVNU F2, F0", "db da"},
|
|
{"FCMOVNU F3, F0", "db db"},
|
|
{"FCMOVU F2, F0", "da da"},
|
|
{"FCMOVU F3, F0", "da db"},
|
|
{"FCOMD F2, F0", "d8 d2"},
|
|
{"FCOMD F3, F0", "d8 d3"},
|
|
{"FCOMD (BX), F0", "dc 13"},
|
|
{"FCOMD (R11), F0", "41 dc 13"},
|
|
{"FCOMI F2, F0", "db f2"},
|
|
{"FCOMI F3, F0", "db f3"},
|
|
{"FCOMIP F2, F0", "df f2"},
|
|
{"FCOMIP F3, F0", "df f3"},
|
|
{"FCOS", "d9 ff"},
|
|
{"FDECSTP", "d9 f6"},
|
|
{"FDIVD F2, F0", "d8 f2"},
|
|
{"FDIVD F3, F0", "d8 f3"},
|
|
{"FDIVD F0, F2", "dc fa"},
|
|
{"FDIVD F0, F3", "dc fb"},
|
|
{"FDIVD (BX), F0", "dc 33"},
|
|
{"FDIVD (R11), F0", "41 dc 33"},
|
|
{"FINCSTP", "d9 f7"},
|
|
{"FLD1", "d9 e8"},
|
|
{"FLDCW (BX)", "d9 2b"},
|
|
{"FLDCW (R11)", "41 d9 2b"},
|
|
{"FLDL2E", "d9 ea"},
|
|
{"FLDL2T", "d9 e9"},
|
|
{"FLDLG2", "d9 ec"},
|
|
{"FLDPI", "d9 eb"},
|
|
{"FNOP", "d9 d0"},
|
|
{"FPATAN", "d9 f3"},
|
|
{"FPREM", "d9 f8"},
|
|
{"FPREM1", "d9 f5"},
|
|
{"FPTAN", "d9 f2"},
|
|
{"FRNDINT", "d9 fc"},
|
|
{"FSCALE", "d9 fd"},
|
|
{"FSIN", "d9 fe"},
|
|
{"FSINCOS", "d9 fb"},
|
|
{"FSQRT", "d9 fa"},
|
|
{"FTST", "d9 e4"},
|
|
{"FXAM", "d9 e5"},
|
|
{"FXRSTOR (BX)", "0f ae 0b"},
|
|
{"FXRSTOR (R11)", "41 0f ae 0b"},
|
|
{"FXRSTOR64 (BX)", "48 0f ae 0b"},
|
|
{"FXRSTOR64 (R11)", "49 0f ae 0b"},
|
|
{"FXSAVE (BX)", "0f ae 03"},
|
|
{"FXSAVE (R11)", "41 0f ae 03"},
|
|
{"FXSAVE64 (BX)", "48 0f ae 03"},
|
|
{"FXSAVE64 (R11)", "49 0f ae 03"},
|
|
{"FXTRACT", "d9 f4"},
|
|
{"FYL2X", "d9 f1"},
|
|
{"FYL2XP1", "d9 f9"},
|
|
}
|
|
|
|
// TestAmd64X87Corpus assembles every corpus line and requires the same bytes
|
|
// go tool asm emits for it.
|
|
func TestAmd64X87Corpus(t *testing.T) {
|
|
for _, tc := range amd64X87Corpus {
|
|
fn := firstText(t, "TEXT ·p(SB), 4, $0\n\t"+tc.line+"\n")
|
|
code, _, err := Assemble(fn)
|
|
if err != nil {
|
|
t.Errorf("%s: %v", tc.line, err)
|
|
continue
|
|
}
|
|
if got := hexBytes(code); got != tc.want {
|
|
t.Errorf("%s: got %s, want %s", tc.line, got, tc.want)
|
|
}
|
|
}
|
|
}
|