]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/asm: implement MCR instruction on ARM
authorRob Pike <r@golang.org>
Mon, 9 Mar 2015 19:36:11 +0000 (12:36 -0700)
committerRob Pike <r@golang.org>
Wed, 11 Mar 2015 17:22:03 +0000 (17:22 +0000)
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 <dave@cheney.net>
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/asm/internal/arch/arch.go
src/cmd/asm/internal/arch/arm.go
src/cmd/asm/internal/asm/asm.go

index 01039ad35f293cf99ae224868e95e92585df0c38..1bbbd0802ab17c0e4717ffa59c945fae08958e24 100644 (file)
@@ -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,
index f9de1a0483c969fd25d9dd4d0444f22bd23a8987..451729fa6049adedd3f559969241f7a266a4f4ec 100644 (file)
@@ -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
index bb38b6d4abf6c2d7297212a141da42f2e90e120b..9019e3c91df46b0e8ec01c40866da43870c9dbf7 100644 (file)
@@ -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