From ced2454220e472c233d4f58a2bc9d01347dedfd3 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sun, 8 Sep 2019 04:11:07 +1000 Subject: [PATCH] cmd/internal/obj/riscv: add environment call/breakpoint and base counter/timer instructions This implements assembler support for ECALL/EBREAK, along with base counter/timer instructions. Based on riscv-go port. Updates #27532 Change-Id: I690a9fd835eeddee1fe9a5616d2b2f856d3952b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/195918 Reviewed-by: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Gobot Gobot --- src/cmd/asm/internal/asm/testdata/riscvenc.s | 13 +++++++ src/cmd/internal/obj/riscv/obj.go | 40 ++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/cmd/asm/internal/asm/testdata/riscvenc.s b/src/cmd/asm/internal/asm/testdata/riscvenc.s index 2e4d464626..1902138504 100644 --- a/src/cmd/asm/internal/asm/testdata/riscvenc.s +++ b/src/cmd/asm/internal/asm/testdata/riscvenc.s @@ -116,6 +116,19 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 REMW X5, X6, X7 // bb635302 REMUW X5, X6, X7 // bb735302 + // 10.1: Base Counters and Timers + RDCYCLE X5 // f32200c0 + RDTIME X5 // f32210c0 + RDINSTRET X5 // f32220c0 + + // Privileged ISA + + // 3.2.1: Environment Call and Breakpoint + ECALL // 73000000 + SCALL // 73000000 + EBREAK // 73001000 + SBREAK // 73001000 + // Arbitrary bytes (entered in little-endian mode) WORD $0x12345678 // WORD $305419896 // 78563412 WORD $0x9abcdef0 // WORD $2596069104 // f0debc9a diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index e97be4b69e..1182053191 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -68,6 +68,35 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { p.As = ASRAI } } + + switch p.As { + case obj.AUNDEF, AECALL, AEBREAK, ASCALL, ASBREAK, ARDCYCLE, ARDTIME, ARDINSTRET: + switch p.As { + case obj.AUNDEF: + p.As = AEBREAK + case ASCALL: + // SCALL is the old name for ECALL. + p.As = AECALL + case ASBREAK: + // SBREAK is the old name for EBREAK. + p.As = AEBREAK + } + + ins := encode(p.As) + if ins == nil { + panic("progedit: tried to rewrite nonexistent instruction") + } + + // The CSR isn't exactly an offset, but it winds up in the + // immediate area of the encoded instruction, so record it in + // the Offset field. + p.From.Type = obj.TYPE_CONST + p.From.Offset = ins.csr + p.Reg = REG_ZERO + if p.To.Type == obj.TYPE_NONE { + p.To.Type, p.To.Reg = obj.TYPE_REG, REG_ZERO + } + } } // setPCs sets the Pc field in all instructions reachable from p. @@ -391,6 +420,17 @@ var encodingForAs = [ALAST & obj.AMask]encoding{ AREMW & obj.AMask: rIIIEncoding, AREMUW & obj.AMask: rIIIEncoding, + // 10.1: Base Counters and Timers + ARDCYCLE & obj.AMask: iIEncoding, + ARDTIME & obj.AMask: iIEncoding, + ARDINSTRET & obj.AMask: iIEncoding, + + // Privileged ISA + + // 3.2.1: Environment Call and Breakpoint + AECALL & obj.AMask: iIEncoding, + AEBREAK & obj.AMask: iIEncoding, + // Escape hatch AWORD & obj.AMask: rawEncoding,