diff --git a/src/cmd/asm/internal/arch/arm.go b/src/cmd/asm/internal/arch/arm.go index fab896a79fe..f9de1a0483c 100644 --- a/src/cmd/asm/internal/arch/arm.go +++ b/src/cmd/asm/internal/arch/arm.go @@ -115,6 +115,30 @@ func IsARMMRC(op int) bool { 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. + op1 := int64(0) + if op == arm.AMRC { + op1 = 1 + } + bits, ok := ParseARMCondition(cond) + if !ok { + return + } + offset = (0xe << 24) | // opcode + (op1 << 20) | // MCR/MRC + ((int64(bits) ^ arm.C_SCOND_XOR) << 28) | // scond + ((x0 & 15) << 8) | //coprocessor number + ((x1 & 7) << 21) | // coprocessor operation + ((x2 & 15) << 12) | // ARM register + ((x3 & 15) << 16) | // Crn + ((x4 & 15) << 0) | // Crm + ((x5 & 7) << 5) | // coprocessor information + (1 << 4) /* must be set */ + return offset, true +} + // IsARMMULA reports whether the op (as defined by an arm.A* constant) is // MULA, MULAWT or MULAWB, the 4-operand instructions. func IsARMMULA(op int) bool { diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index 526b81f8bad..bd9ba91b22c 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -13,8 +13,6 @@ import ( "cmd/asm/internal/flags" "cmd/asm/internal/lex" "cmd/internal/obj" - "cmd/internal/obj/arm" - "cmd/internal/obj/ppc64" ) // TODO: configure the architecture @@ -325,7 +323,12 @@ func (p *Parser) asmJump(op int, cond string, a []obj.Addr) { Type: obj.TYPE_CONST, Offset: p.getConstant(prog, op, &a[0]), } - prog.Reg = int16(ppc64.REG_R0 + p.getConstant(prog, op, &a[1])) + reg := int16(p.getConstant(prog, op, &a[1])) + reg, ok := p.arch.RegisterNumber("R", int16(reg)) + if !ok { + p.errorf("bad register number %d", reg) + } + prog.Reg = reg break } fallthrough @@ -590,43 +593,22 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) { } p.errorf("can't handle %s instruction with 5 operands", obj.Aconv(op)) case 6: - // MCR and MRC on ARM if p.arch.Thechar == '5' && arch.IsARMMRC(op) { // Strange special case: MCR, MRC. - // TODO: Move this to arch? (It will be hard to disentangle.) prog.To.Type = obj.TYPE_CONST - bits, ok := uint8(0), false - if cond != "" { - // Cond is handled specially for this instruction. - bits, ok = arch.ParseARMCondition(cond) - if !ok { - p.errorf("unrecognized condition code .%q", cond) - } - cond = "" - } - // First argument is a condition code as a constant. x0 := p.getConstant(prog, op, &a[0]) x1 := p.getConstant(prog, op, &a[1]) x2 := int64(p.getRegister(prog, op, &a[2])) x3 := int64(p.getRegister(prog, op, &a[3])) x4 := int64(p.getRegister(prog, op, &a[4])) x5 := p.getConstant(prog, op, &a[5]) - // TODO only MCR is defined. - op1 := int64(0) - if op == arm.AMRC { - op1 = 1 + // Cond is handled specially for this instruction. + offset, ok := arch.ARMMRCOffset(op, cond, x0, x1, x2, x3, x4, x5) + if !ok { + p.errorf("unrecognized condition code .%q", cond) } - prog.To.Offset = - (0xe << 24) | // opcode - (op1 << 20) | // MCR/MRC - ((int64(bits) ^ arm.C_SCOND_XOR) << 28) | // scond - ((x0 & 15) << 8) | //coprocessor number - ((x1 & 7) << 21) | // coprocessor operation - ((x2 & 15) << 12) | // ARM register - ((x3 & 15) << 16) | // Crn - ((x4 & 15) << 0) | // Crm - ((x5 & 7) << 5) | // coprocessor information - (1 << 4) /* must be set */ + prog.To.Offset = offset + cond = "" break } fallthrough