Skip to content

Commit

Permalink
cmd/asm,cmd/internal/obj: initial support for riscv64 assembler
Browse files Browse the repository at this point in the history
Provide the initial framework for the riscv64 assembler. For now this
only supports raw WORD instructions, but at least allows for basic
testing. Additional functionality will be added in separate changes.

Based on the riscv-go port.

Updates #27532

Change-Id: I181ffb2d37a34764a3e91eded177d13a89c69f9a
Reviewed-on: https://go-review.googlesource.com/c/go/+/194117
Reviewed-by: Cherry Zhang <cherryyz@google.com>
  • Loading branch information
4a6f656c committed Sep 12, 2019
1 parent 9428861 commit 6c6ad30
Show file tree
Hide file tree
Showing 8 changed files with 364 additions and 0 deletions.
122 changes: 122 additions & 0 deletions src/cmd/asm/internal/arch/arch.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"cmd/internal/obj/arm64"
"cmd/internal/obj/mips"
"cmd/internal/obj/ppc64"
"cmd/internal/obj/riscv"
"cmd/internal/obj/s390x"
"cmd/internal/obj/wasm"
"cmd/internal/obj/x86"
Expand Down Expand Up @@ -73,6 +74,8 @@ func Set(GOARCH string) *Arch {
return archPPC64(&ppc64.Linkppc64)
case "ppc64le":
return archPPC64(&ppc64.Linkppc64le)
case "riscv64":
return archRISCV64()
case "s390x":
return archS390x()
case "wasm":
Expand All @@ -85,6 +88,14 @@ func jumpX86(word string) bool {
return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP") || word == "XBEGIN"
}

func jumpRISCV(word string) bool {
switch word {
case "BEQ", "BNE", "BLT", "BGE", "BLTU", "BGEU", "CALL", "JAL", "JALR", "JMP":
return true
}
return false
}

func jumpWasm(word string) bool {
return word == "JMP" || word == "CALL" || word == "Call" || word == "Br" || word == "BrIf"
}
Expand Down Expand Up @@ -516,6 +527,117 @@ func archMips64(linkArch *obj.LinkArch) *Arch {
}
}

func archRISCV64() *Arch {
register := make(map[string]int16)

// Standard register names.
for i := riscv.REG_X0; i <= riscv.REG_X31; i++ {
name := fmt.Sprintf("X%d", i-riscv.REG_X0)
register[name] = int16(i)
}
for i := riscv.REG_F0; i <= riscv.REG_F31; i++ {
name := fmt.Sprintf("F%d", i-riscv.REG_F0)
register[name] = int16(i)
}

// General registers with ABI names.
register["ZERO"] = riscv.REG_ZERO
register["RA"] = riscv.REG_RA
register["SP"] = riscv.REG_SP
register["GP"] = riscv.REG_GP
register["TP"] = riscv.REG_TP
register["T0"] = riscv.REG_T0
register["T1"] = riscv.REG_T1
register["T2"] = riscv.REG_T2
register["S0"] = riscv.REG_S0
register["S1"] = riscv.REG_S1
register["A0"] = riscv.REG_A0
register["A1"] = riscv.REG_A1
register["A2"] = riscv.REG_A2
register["A3"] = riscv.REG_A3
register["A4"] = riscv.REG_A4
register["A5"] = riscv.REG_A5
register["A6"] = riscv.REG_A6
register["A7"] = riscv.REG_A7
register["S2"] = riscv.REG_S2
register["S3"] = riscv.REG_S3
register["S4"] = riscv.REG_S4
register["S5"] = riscv.REG_S5
register["S6"] = riscv.REG_S6
register["S7"] = riscv.REG_S7
register["S8"] = riscv.REG_S8
register["S9"] = riscv.REG_S9
register["S10"] = riscv.REG_S10
register["S11"] = riscv.REG_S11
register["T3"] = riscv.REG_T3
register["T4"] = riscv.REG_T4
register["T5"] = riscv.REG_T5
register["T6"] = riscv.REG_T6

// Go runtime register names.
register["g"] = riscv.REG_G
register["CTXT"] = riscv.REG_CTXT
register["TMP"] = riscv.REG_TMP

// ABI names for floating point register.
register["FT0"] = riscv.REG_FT0
register["FT1"] = riscv.REG_FT1
register["FT2"] = riscv.REG_FT2
register["FT3"] = riscv.REG_FT3
register["FT4"] = riscv.REG_FT4
register["FT5"] = riscv.REG_FT5
register["FT6"] = riscv.REG_FT6
register["FT7"] = riscv.REG_FT7
register["FS0"] = riscv.REG_FS0
register["FS1"] = riscv.REG_FS1
register["FA0"] = riscv.REG_FA0
register["FA1"] = riscv.REG_FA1
register["FA2"] = riscv.REG_FA2
register["FA3"] = riscv.REG_FA3
register["FA4"] = riscv.REG_FA4
register["FA5"] = riscv.REG_FA5
register["FA6"] = riscv.REG_FA6
register["FA7"] = riscv.REG_FA7
register["FS2"] = riscv.REG_FS2
register["FS3"] = riscv.REG_FS3
register["FS4"] = riscv.REG_FS4
register["FS5"] = riscv.REG_FS5
register["FS6"] = riscv.REG_FS6
register["FS7"] = riscv.REG_FS7
register["FS8"] = riscv.REG_FS8
register["FS9"] = riscv.REG_FS9
register["FS10"] = riscv.REG_FS10
register["FS11"] = riscv.REG_FS11
register["FT8"] = riscv.REG_FT8
register["FT9"] = riscv.REG_FT9
register["FT10"] = riscv.REG_FT10
register["FT11"] = riscv.REG_FT11

// Pseudo-registers.
register["SB"] = RSB
register["FP"] = RFP
register["PC"] = RPC

instructions := make(map[string]obj.As)
for i, s := range obj.Anames {
instructions[s] = obj.As(i)
}
for i, s := range riscv.Anames {
if obj.As(i) >= obj.A_ARCHSPECIFIC {
instructions[s] = obj.As(i) + obj.ABaseRISCV
}
}

return &Arch{
LinkArch: &riscv.LinkRISCV64,
Instructions: instructions,
Register: register,
RegisterPrefix: nil,
RegisterNumber: nilRegisterNumber,
IsJump: jumpRISCV,
}
}

func archS390x() *Arch {
register := make(map[string]int16)
// Create maps for easy lookup of instruction names etc.
Expand Down
4 changes: 4 additions & 0 deletions src/cmd/asm/internal/asm/endtoend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ func TestPPC64Encoder(t *testing.T) {
testEndToEnd(t, "ppc64", "ppc64enc")
}

func TestRISCVEncoder(t *testing.T) {
testEndToEnd(t, "riscv64", "riscvenc")
}

func TestS390XEndToEnd(t *testing.T) {
testEndToEnd(t, "s390x", "s390x")
}
11 changes: 11 additions & 0 deletions src/cmd/asm/internal/asm/testdata/riscvenc.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "../../../../../runtime/textflag.h"

TEXT asmtest(SB),DUPOK|NOSPLIT,$0

// Arbitrary bytes (entered in little-endian mode)
WORD $0x12345678 // WORD $305419896 // 78563412
WORD $0x9abcdef0 // WORD $2596069104 // f0debc9a
1 change: 1 addition & 0 deletions src/cmd/dist/buildtool.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ var bootstrapDirs = []string{
"cmd/internal/obj/arm64",
"cmd/internal/obj/mips",
"cmd/internal/obj/ppc64",
"cmd/internal/obj/riscv",
"cmd/internal/obj/s390x",
"cmd/internal/obj/x86",
"cmd/internal/obj/wasm",
Expand Down
1 change: 1 addition & 0 deletions src/cmd/internal/obj/riscv/anames.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/cmd/internal/obj/riscv/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,9 @@ const (
AMOVWU
ASEQZ
ASNEZ

// End marker
ALAST
)

// All unary instructions which write to their arguments (as opposed to reading
Expand Down
33 changes: 33 additions & 0 deletions src/cmd/internal/obj/riscv/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package riscv

import (
"fmt"

"cmd/internal/obj"
)

func init() {
obj.RegisterRegister(obj.RBaseRISCV, REG_END, regName)
obj.RegisterOpcode(obj.ABaseRISCV, Anames)
}

func regName(r int) string {
switch {
case r == 0:
return "NONE"
case r == REG_G:
return "g"
case r == REG_SP:
return "SP"
case REG_X0 <= r && r <= REG_X31:
return fmt.Sprintf("X%d", r-REG_X0)
case REG_F0 <= r && r <= REG_F31:
return fmt.Sprintf("F%d", r-REG_F0)
default:
return fmt.Sprintf("Rgok(%d)", r-obj.RBaseRISCV)
}
}
Loading

0 comments on commit 6c6ad30

Please sign in to comment.