// Copyright (c) 2026 Petr BalvĂ­n (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 macro helper // ADDU16I.D has no toolchain spelling (the assembler never takes it as // input), so its "Unknown" render is the decoder's own and stays. func TestUnknownNamingBoundaries(t *testing.T) { for _, tt := range []struct { code []byte text string }{ {[]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) } } }