diff options
Diffstat (limited to 'src/cmd/asm')
| -rw-r--r-- | src/cmd/asm/internal/arch/arm64.go | 6 | ||||
| -rw-r--r-- | src/cmd/asm/internal/arch/riscv64.go | 35 | ||||
| -rw-r--r-- | src/cmd/asm/internal/asm/asm.go | 21 | ||||
| -rw-r--r-- | src/cmd/asm/internal/asm/parse.go | 16 | ||||
| -rw-r--r-- | src/cmd/asm/internal/asm/testdata/riscv64.s | 24 | ||||
| -rw-r--r-- | src/cmd/asm/internal/asm/testdata/riscv64error.s | 4 |
6 files changed, 95 insertions, 11 deletions
diff --git a/src/cmd/asm/internal/arch/arm64.go b/src/cmd/asm/internal/arch/arm64.go index e63601de64..87ccb8c040 100644 --- a/src/cmd/asm/internal/arch/arm64.go +++ b/src/cmd/asm/internal/arch/arm64.go @@ -59,10 +59,10 @@ func jumpArm64(word string) bool { var arm64SpecialOperand map[string]arm64.SpecialOperand -// GetARM64SpecialOperand returns the internal representation of a special operand. -func GetARM64SpecialOperand(name string) arm64.SpecialOperand { +// ARM64SpecialOperand returns the internal representation of a special operand. +func ARM64SpecialOperand(name string) arm64.SpecialOperand { if arm64SpecialOperand == nil { - // Generate the mapping automatically when the first time the function is called. + // Generate mapping when function is first called. arm64SpecialOperand = map[string]arm64.SpecialOperand{} for opd := arm64.SPOP_BEGIN; opd < arm64.SPOP_END; opd++ { arm64SpecialOperand[opd.String()] = opd diff --git a/src/cmd/asm/internal/arch/riscv64.go b/src/cmd/asm/internal/arch/riscv64.go index 27a66c5e63..69e060a865 100644 --- a/src/cmd/asm/internal/arch/riscv64.go +++ b/src/cmd/asm/internal/arch/riscv64.go @@ -13,9 +13,8 @@ import ( "cmd/internal/obj/riscv" ) -// IsRISCV64AMO reports whether the op (as defined by a riscv.A* -// constant) is one of the AMO instructions that requires special -// handling. +// IsRISCV64AMO reports whether op is an AMO instruction that requires +// special handling. func IsRISCV64AMO(op obj.As) bool { switch op { case riscv.ASCW, riscv.ASCD, riscv.AAMOSWAPW, riscv.AAMOSWAPD, riscv.AAMOADDW, riscv.AAMOADDD, @@ -26,3 +25,33 @@ func IsRISCV64AMO(op obj.As) bool { } return false } + +// IsRISCV64VTypeI reports whether op is a vtype immediate instruction that +// requires special handling. +func IsRISCV64VTypeI(op obj.As) bool { + return op == riscv.AVSETVLI || op == riscv.AVSETIVLI +} + +var riscv64SpecialOperand map[string]riscv.SpecialOperand + +// RISCV64SpecialOperand returns the internal representation of a special operand. +func RISCV64SpecialOperand(name string) riscv.SpecialOperand { + if riscv64SpecialOperand == nil { + // Generate mapping when function is first called. + riscv64SpecialOperand = map[string]riscv.SpecialOperand{} + for opd := riscv.SPOP_BEGIN; opd < riscv.SPOP_END; opd++ { + riscv64SpecialOperand[opd.String()] = opd + } + } + if opd, ok := riscv64SpecialOperand[name]; ok { + return opd + } + return riscv.SPOP_END +} + +// RISCV64ValidateVectorType reports whether the given configuration is a +// valid vector type. +func RISCV64ValidateVectorType(vsew, vlmul, vtail, vmask int64) error { + _, err := riscv.EncodeVectorType(vsew, vlmul, vtail, vmask) + return err +} diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index 9fc7fa5598..a1f6a73d70 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -915,6 +915,19 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) { prog.To = a[5] break } + if p.arch.Family == sys.RISCV64 && arch.IsRISCV64VTypeI(op) { + prog.From = a[0] + vsew := p.getSpecial(prog, op, &a[1]) + vlmul := p.getSpecial(prog, op, &a[2]) + vtail := p.getSpecial(prog, op, &a[3]) + vmask := p.getSpecial(prog, op, &a[4]) + if err := arch.RISCV64ValidateVectorType(vsew, vlmul, vtail, vmask); err != nil { + p.errorf("invalid vtype: %v", err) + } + prog.AddRestSourceArgs([]obj.Addr{a[1], a[2], a[3], a[4]}) + prog.To = a[5] + break + } fallthrough default: p.errorf("can't handle %s instruction with %d operands", op, len(a)) @@ -965,3 +978,11 @@ func (p *Parser) getRegister(prog *obj.Prog, op obj.As, addr *obj.Addr) int16 { } return addr.Reg } + +// getSpecial checks that addr represents a special operand and returns its value. +func (p *Parser) getSpecial(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 { + if addr.Type != obj.TYPE_SPECIAL || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 { + p.errorf("%s: expected special operand; found %s", op, obj.Dconv(prog, addr)) + } + return addr.Offset +} diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go index 638f4e2fc4..8f8f6dcc34 100644 --- a/src/cmd/asm/internal/asm/parse.go +++ b/src/cmd/asm/internal/asm/parse.go @@ -21,6 +21,7 @@ import ( "cmd/asm/internal/lex" "cmd/internal/obj" "cmd/internal/obj/arm64" + "cmd/internal/obj/riscv" "cmd/internal/obj/x86" "cmd/internal/objabi" "cmd/internal/src" @@ -398,16 +399,21 @@ func (p *Parser) operand(a *obj.Addr) { tok := p.next() name := tok.String() if tok.ScanToken == scanner.Ident && !p.atStartOfRegister(name) { + // See if this is an architecture specific special operand. switch p.arch.Family { case sys.ARM64: - // arm64 special operands. - if opd := arch.GetARM64SpecialOperand(name); opd != arm64.SPOP_END { + if opd := arch.ARM64SpecialOperand(name); opd != arm64.SPOP_END { a.Type = obj.TYPE_SPECIAL a.Offset = int64(opd) - break } - fallthrough - default: + case sys.RISCV64: + if opd := arch.RISCV64SpecialOperand(name); opd != riscv.SPOP_END { + a.Type = obj.TYPE_SPECIAL + a.Offset = int64(opd) + } + } + + if a.Type != obj.TYPE_SPECIAL { // We have a symbol. Parse $sym±offset(symkind) p.symbolReference(a, p.qualifySymbol(name), prefix) } diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 9ab4e066be..cbe99ba348 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -425,6 +425,30 @@ start: BSETI $1, X10, X11 // 93151528 // + // "V" Standard Extension for Vector Operations, Version 1.0 + // + + // 31.6: Configuration Setting Instructions + VSETVLI X10, E8, M1, TU, MU, X12 // 57760500 + VSETVLI X10, E16, M1, TU, MU, X12 // 57768500 + VSETVLI X10, E32, M1, TU, MU, X12 // 57760501 + VSETVLI X10, E64, M1, TU, MU, X12 // 57768501 + VSETVLI X10, E32, M1, TU, MA, X12 // 57760509 + VSETVLI X10, E32, M1, TA, MA, X12 // 5776050d + VSETVLI X10, E32, M2, TA, MA, X12 // 5776150d + VSETVLI X10, E32, M4, TA, MA, X12 // 5776250d + VSETVLI X10, E32, M8, TA, MA, X12 // 5776350d + VSETVLI X10, E32, MF2, TA, MA, X12 // 5776550d + VSETVLI X10, E32, MF4, TA, MA, X12 // 5776650d + VSETVLI X10, E32, MF8, TA, MA, X12 // 5776750d + VSETVLI X10, E32, M1, TA, MA, X12 // 5776050d + VSETVLI $15, E32, M1, TA, MA, X12 // 57f607cd + VSETIVLI $0, E32, M1, TA, MA, X12 // 577600cd + VSETIVLI $15, E32, M1, TA, MA, X12 // 57f607cd + VSETIVLI $31, E32, M1, TA, MA, X12 // 57f60fcd + VSETVL X10, X11, X12 // 57f6a580 + + // // Privileged ISA // diff --git a/src/cmd/asm/internal/asm/testdata/riscv64error.s b/src/cmd/asm/internal/asm/testdata/riscv64error.s index 0b0184aaa7..a90f22af9f 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64error.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64error.s @@ -46,4 +46,8 @@ TEXT errors(SB),$0 SRLI $1, X5, F1 // ERROR "expected integer register in rd position but got non-integer register F1" SRLI $1, F1, X5 // ERROR "expected integer register in rs1 position but got non-integer register F1" FNES F1, (X5) // ERROR "needs an integer register output" + VSETVLI $32, E16, M1, TU, MU, X12 // ERROR "must be in range [0, 31] (5 bits)" + VSETVLI $-1, E32, M2, TA, MA, X12 // ERROR "must be in range [0, 31] (5 bits)" + VSETIVLI X10, E32, M2, TA, MA, X12 // ERROR "expected immediate value" + VSETVL X10, X11 // ERROR "expected integer register in rs1 position" RET |
