From 5d987f15137332ddf2c93bf9aabf639b1c2dccc5 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Mon, 9 Mar 2015 12:36:11 -0700 Subject: [PATCH] cmd/asm: implement MCR instruction on ARM It's an oddball that needs special treatment because it is not really an opcode, but a variant of MRC. The String method of Prog still needs updating to print it nicely. Change-Id: I6005b7f2234ccd3d4ac1f658948e3be97cf1f1c2 Reviewed-on: https://go-review.googlesource.com/7220 Reviewed-by: Dave Cheney Reviewed-by: Russ Cox --- src/cmd/asm/internal/arch/arch.go | 4 ++++ src/cmd/asm/internal/arch/arm.go | 15 +++++++++++---- src/cmd/asm/internal/asm/asm.go | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go index 01039ad35f..1bbbd0802a 100644 --- a/src/cmd/asm/internal/arch/arch.go +++ b/src/cmd/asm/internal/arch/arch.go @@ -186,6 +186,10 @@ func archArm() *Arch { // Annoying aliases. instructions["B"] = obj.AJMP instructions["BL"] = obj.ACALL + // MCR differs from MRC by the way fields of the word are encoded. + // (Details in arm.go). Here we add the instruction so parse will find + // it, but give it an opcode number known only to us. + instructions["MCR"] = aMCR return &Arch{ LinkArch: &arm.Linkarm, diff --git a/src/cmd/asm/internal/arch/arm.go b/src/cmd/asm/internal/arch/arm.go index f9de1a0483..451729fa60 100644 --- a/src/cmd/asm/internal/arch/arm.go +++ b/src/cmd/asm/internal/arch/arm.go @@ -105,19 +105,26 @@ func IsARMSTREX(op int) bool { return false } +// MCR is not defined by the obj/arm; instead we define it privately here. +// It is encoded as an MRC with a bit inside the instruction word, +// passed to arch.ARMMRCOffset. +const aMCR = arm.ALAST + 1 + // IsARMMRC reports whether the op (as defined by an arm.A* constant) is // MRC or MCR func IsARMMRC(op int) bool { switch op { - case arm.AMRC /*, arm.AMCR*/ : + case arm.AMRC, aMCR: // Note: aMCR is defined in this package. return true } return false } // ARMMRCOffset implements the peculiar encoding of the MRC and MCR instructions. -func ARMMRCOffset(op int, cond string, x0, x1, x2, x3, x4, x5 int64) (offset int64, ok bool) { - // TODO only MRC is defined. +// The difference between MRC and MCR is represented by a bit high in the word, not +// in the usual way by the opcode itself. Asm must use AMRC for both instructions, so +// we return the opcode for MRC so that asm doesn't need to import obj/arm. +func ARMMRCOffset(op int, cond string, x0, x1, x2, x3, x4, x5 int64) (offset int64, op0 int16, ok bool) { op1 := int64(0) if op == arm.AMRC { op1 = 1 @@ -136,7 +143,7 @@ func ARMMRCOffset(op int, cond string, x0, x1, x2, x3, x4, x5 int64) (offset int ((x4 & 15) << 0) | // Crm ((x5 & 7) << 5) | // coprocessor information (1 << 4) /* must be set */ - return offset, true + return offset, arm.AMRC, true } // IsARMMULA reports whether the op (as defined by an arm.A* constant) is diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index bb38b6d4ab..9019e3c91d 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -567,12 +567,13 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) { x4 := int64(p.getRegister(prog, op, &a[4])) x5 := p.getConstant(prog, op, &a[5]) // Cond is handled specially for this instruction. - offset, ok := arch.ARMMRCOffset(op, cond, x0, x1, x2, x3, x4, x5) + offset, MRC, ok := arch.ARMMRCOffset(op, cond, x0, x1, x2, x3, x4, x5) if !ok { p.errorf("unrecognized condition code .%q", cond) } prog.To.Offset = offset cond = "" + prog.As = MRC // Both instructions are coded as MRC. break } fallthrough -- 2.48.1