128 lines
5.7 KiB
Go
128 lines
5.7 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package disasm
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"sourcedock.dev/petrbalvin/gasm-sdk/arch"
|
|
)
|
|
|
|
// TestUnknownNaming pins the loong64 re-rendering table over the corpus
|
|
// rows whose operations x/arch decodes but names "Unknown" or "?": every
|
|
// row's bytes are the corpus's own expected-encoding comments
|
|
// (machine-checked by the toolchain's assembler test suite) and every text
|
|
// is the toolchain's own spelling, operand order included.
|
|
func TestUnknownNaming(t *testing.T) {
|
|
for _, tt := range []struct {
|
|
code []byte
|
|
text string
|
|
}{
|
|
// loong64enc1.s: EXTWB R4, R5 // 855c0000 and EXTWH R4, R5 // 85580000.
|
|
{[]byte{0x85, 0x5c, 0x00, 0x00}, "EXTWB R4, R5"},
|
|
{[]byte{0x85, 0x58, 0x00, 0x00}, "EXTWH R4, R5"},
|
|
// loong64enc1.s: the bit and reverse families.
|
|
{[]byte{0x85, 0x40, 0x00, 0x00}, "REVH2W R4, R5"},
|
|
{[]byte{0x85, 0x44, 0x00, 0x00}, "REVHV R4, R5"},
|
|
{[]byte{0x85, 0x48, 0x00, 0x00}, "BITREV4B R4, R5"},
|
|
{[]byte{0x85, 0x4c, 0x00, 0x00}, "BITREV8B R4, R5"},
|
|
// loong64enc1.s: ANDN and ORN, two- and three-operand forms.
|
|
{[]byte{0xa6, 0x90, 0x16, 0x00}, "ANDN R4, R5, R6"},
|
|
{[]byte{0xa5, 0x90, 0x16, 0x00}, "ANDN R4, R5"},
|
|
{[]byte{0xa6, 0x10, 0x16, 0x00}, "ORN R4, R5, R6"},
|
|
{[]byte{0xa5, 0x10, 0x16, 0x00}, "ORN R4, R5"},
|
|
// loong64enc1.s: MULWVW and MULWVWU.
|
|
{[]byte{0xa5, 0x10, 0x1f, 0x00}, "MULWVW R4, R5"},
|
|
{[]byte{0xa6, 0x10, 0x1f, 0x00}, "MULWVW R4, R5, R6"},
|
|
{[]byte{0xa5, 0x90, 0x1f, 0x00}, "MULWVWU R4, R5"},
|
|
{[]byte{0xa6, 0x90, 0x1f, 0x00}, "MULWVWU R4, R5, R6"},
|
|
// loong64enc1.s: the pointer store and load pair. The
|
|
// displacement is the scaled field read the way the toolchain
|
|
// takes it back: 32764, not the renderer's -4.
|
|
{[]byte{0x85, 0x04, 0x00, 0x25}, "MOVWP R5, 4(R4)"},
|
|
{[]byte{0x85, 0x00, 0x00, 0x25}, "MOVWP R5, 0(R4)"},
|
|
{[]byte{0x85, 0xfc, 0x7f, 0x25}, "MOVWP R5, 32764(R4)"},
|
|
{[]byte{0xa4, 0xfc, 0x7f, 0x24}, "MOVWP 32764(R5), R4"},
|
|
{[]byte{0xa4, 0x04, 0x00, 0x24}, "MOVWP 4(R5), R4"},
|
|
{[]byte{0xa4, 0x00, 0x00, 0x26}, "MOVVP 0(R5), R4"},
|
|
{[]byte{0x85, 0xfc, 0x7f, 0x27}, "MOVVP R5, 32764(R4)"},
|
|
// loong64enc1.s: the acquire loads and release stores.
|
|
{[]byte{0xa4, 0x80, 0x57, 0x38}, "LLACQW (R5), R4"},
|
|
{[]byte{0xa4, 0x88, 0x57, 0x38}, "LLACQV (R5), R4"},
|
|
{[]byte{0xc4, 0x14, 0x57, 0x38}, "SCQ R4, R5, (R6)"},
|
|
{[]byte{0xc4, 0x84, 0x57, 0x38}, "SCRELW R4, (R6)"},
|
|
{[]byte{0xc4, 0x8c, 0x57, 0x38}, "SCRELV R4, (R6)"},
|
|
// loong64enc1.s: the floating-point minima and maxima.
|
|
{[]byte{0xa6, 0x90, 0x0c, 0x01}, "FMAXAF F4, F5, F6"},
|
|
{[]byte{0xa5, 0x90, 0x0c, 0x01}, "FMAXAF F4, F5"},
|
|
{[]byte{0xa6, 0x10, 0x0d, 0x01}, "FMAXAD F4, F5, F6"},
|
|
{[]byte{0xa6, 0x90, 0x0e, 0x01}, "FMINAF F4, F5, F6"},
|
|
{[]byte{0xa6, 0x10, 0x0f, 0x01}, "FMINAD F4, F5, F6"},
|
|
// loong64enc1.s: FSEL, FSCALEB and FLOGB.
|
|
{[]byte{0x43, 0x04, 0x00, 0x0d}, "FSEL FCC0, F1, F2, F3"},
|
|
{[]byte{0x42, 0x84, 0x00, 0x0d}, "FSEL FCC1, F1, F2, F2"},
|
|
{[]byte{0xa6, 0x90, 0x10, 0x01}, "FSCALEBF F4, F5, F6"},
|
|
{[]byte{0xa6, 0x10, 0x11, 0x01}, "FSCALEBD F4, F5, F6"},
|
|
{[]byte{0x85, 0x24, 0x14, 0x01}, "FLOGBF F4, F5"},
|
|
{[]byte{0x85, 0x28, 0x14, 0x01}, "FLOGBD F4, F5"},
|
|
// loong64enc1.s: PRELD, all three hint rows.
|
|
{[]byte{0x80, 0x00, 0xc0, 0x2a}, "PRELD (R4), $0"},
|
|
{[]byte{0x88, 0xfc, 0xff, 0x2a}, "PRELD -1(R4), $8"},
|
|
{[]byte{0x9f, 0x20, 0xc0, 0x2a}, "PRELD 8(R4), $31"},
|
|
// loong64enc1.s: the address-add-and-shift-left family, whose
|
|
// rj and rk the renderer prints crossed.
|
|
{[]byte{0x86, 0x94, 0x05, 0x00}, "ALSLW $4, R4, R5, R6"},
|
|
{[]byte{0x86, 0x94, 0x07, 0x00}, "ALSLWU $4, R4, R5, R6"},
|
|
{[]byte{0x86, 0x94, 0x2d, 0x00}, "ALSLV $4, R4, R5, R6"},
|
|
} {
|
|
ins, err := Decode(arch.LOONG64, tt.code, 0)
|
|
if err != nil {
|
|
t.Errorf("% x: %v", tt.code, err)
|
|
continue
|
|
}
|
|
if ins.Text != tt.text || ins.Len != len(tt.code) {
|
|
t.Errorf("% x: %q (%d bytes), want %q (%d)",
|
|
tt.code, ins.Text, ins.Len, tt.text, len(tt.code))
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestUnknownNamingBoundaries pins what stays untouched: the ADDU16I.D
|
|
// render. The truth of the naming question, established against the live
|
|
// toolchain: the assembler spells the family ADDV16 (loong64enc1.s pins
|
|
// the rows and go tool asm refuses "ADDU16I.D" as input), while the
|
|
// toolchain's own disassembler names the encoding ADDU16I.D with the
|
|
// "Unknown" prefix x/arch gives the ops its Plan 9 map lacks, and `go tool
|
|
// objdump` prints exactly this text ("Unknown ADDU16I.D $16, R4" for the
|
|
// 0x10004084 the loong64enc1.s corpus carries). The render is therefore
|
|
// the toolchain's own on both counts, name and prefix, and stays.
|
|
func TestUnknownNamingBoundaries(t *testing.T) {
|
|
for _, tt := range []struct {
|
|
code []byte
|
|
text string
|
|
}{
|
|
// loong64enc1.s: ADDV16 $(-32768<<16), R4, R5 // 85000012.
|
|
{[]byte{0x85, 0x00, 0x00, 0x12}, "Unknown ADDU16I.D $-32768, R4, R5"},
|
|
// loong64enc1.s: ADDV16 $(0<<16), R4, R5 // 85000010.
|
|
{[]byte{0x85, 0x00, 0x00, 0x10}, "Unknown ADDU16I.D $0, R4, R5"},
|
|
// loong64enc1.s: ADDV16 $(8<<16), R4, R5 // 85200010.
|
|
{[]byte{0x85, 0x20, 0x00, 0x10}, "Unknown ADDU16I.D $8, R4, R5"},
|
|
// loong64enc1.s: ADDV16 $(32767<<16), R4, R5 // 85fcff11.
|
|
{[]byte{0x85, 0xfc, 0xff, 0x11}, "Unknown ADDU16I.D $32767, R4, R5"},
|
|
// loong64enc1.s: ADDV16 $(16<<16), R4 // 84400010; the destination-
|
|
// only form collapses in the renderer when rd equals rj.
|
|
{[]byte{0x84, 0x40, 0x00, 0x10}, "Unknown ADDU16I.D $16, R4"},
|
|
{[]byte{0x85, 0x00, 0x17, 0x00}, "MOVW R4, R5"},
|
|
} {
|
|
ins, err := Decode(arch.LOONG64, tt.code, 0)
|
|
if err != nil {
|
|
t.Errorf("% x: %v", tt.code, err)
|
|
continue
|
|
}
|
|
if ins.Text != tt.text {
|
|
t.Errorf("% x: %q, want %q", tt.code, ins.Text, tt.text)
|
|
}
|
|
}
|
|
}
|