Commit 5d987f15 authored by Rob Pike's avatar Rob Pike

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/7220Reviewed-by: 's avatarDave Cheney <dave@cheney.net>
Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 7b0c73aa
......@@ -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,
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment