diff --git a/asm/loong64_assemble.go b/asm/loong64_assemble.go index e16070e..fbd1a75 100644 --- a/asm/loong64_assemble.go +++ b/asm/loong64_assemble.go @@ -487,6 +487,21 @@ func encodeLOONG64Instr(instr *ast.Instr, pc int, offsets map[string]int, fi loo } // Pseudo-instructions and the branches first. + // Before any of them: the toolchain's loong64 operand grammar has no + // shifted-register composition (R0<<2, R0>>R1, R0->3, R0@>3 are parse + // errors under GOARCH=loong64 go tool asm), and the shift suffix the + // shared parser records is arm64's. Encoding on would silently drop + // the composition and emit the bare register, so every operand whose + // verbatim suffix is not the element-selector index (V1.B[3] records + // the name as V1.B and the suffix "[3]", which is a real loong64 + // form) is rejected outright. + for _, op := range ops { + sfx := strings.Join(strings.Fields(op.Addr.Shift), "") + if sfx != "" && !strings.HasPrefix(sfx, "[") { + return nil, fmt.Errorf("%s: shifted register operand %s%s is not a loong64 form", + mnem, operandRegName(op), sfx) + } + } switch mnem { case "RET": return loong64Return(fi), nil