"JMP": true,
"TBNZ": true,
"TBZ": true,
+
+ // ADR isn't really a jump, but it takes a PC or label reference,
+ // which needs to patched like a jump.
+ "ADR": true,
+ "ADRP": true,
}
func jumpArm64(word string) bool {
return arm64.SPOP_END
}
+// IsARM64ADR reports whether the op (as defined by an arm64.A* constant) is
+// one of the comparison instructions that require special handling.
+func IsARM64ADR(op obj.As) bool {
+ switch op {
+ case arm64.AADR, arm64.AADRP:
+ return true
+ }
+ return false
+}
+
// IsARM64CMP reports whether the op (as defined by an arm64.A* constant) is
// one of the comparison instructions that require special handling.
func IsARM64CMP(op obj.As) bool {
Pos: p.pos(),
As: op,
}
+ targetAddr := &prog.To
switch len(a) {
case 0:
if p.arch.Family == sys.Wasm {
target = &a[0]
case 2:
// Special 2-operand jumps.
- target = &a[1]
- prog.From = a[0]
+ if p.arch.Family == sys.ARM64 && arch.IsARM64ADR(op) {
+ // ADR label, R. Label is in From.
+ target = &a[0]
+ prog.To = a[1]
+ targetAddr = &prog.From
+ } else {
+ target = &a[1]
+ prog.From = a[0]
+ }
case 3:
if p.arch.Family == sys.PPC64 {
// Special 3-operand jumps.
switch {
case target.Type == obj.TYPE_BRANCH:
// JMP 4(PC)
- prog.To = obj.Addr{
+ *targetAddr = obj.Addr{
Type: obj.TYPE_BRANCH,
Offset: p.pc + 1 + target.Offset, // +1 because p.pc is incremented in append, below.
}
case target.Type == obj.TYPE_REG:
// JMP R1
- prog.To = *target
+ *targetAddr = *target
case target.Type == obj.TYPE_MEM && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
// JMP main·morestack(SB)
- prog.To = *target
+ *targetAddr = *target
case target.Type == obj.TYPE_INDIR && (target.Name == obj.NAME_EXTERN || target.Name == obj.NAME_STATIC):
// JMP *main·morestack(SB)
- prog.To = *target
- prog.To.Type = obj.TYPE_INDIR
+ *targetAddr = *target
+ targetAddr.Type = obj.TYPE_INDIR
case target.Type == obj.TYPE_MEM && target.Reg == 0 && target.Offset == 0:
// JMP exit
if target.Sym == nil {
}
targetProg := p.labels[target.Sym.Name]
if targetProg == nil {
- p.toPatch = append(p.toPatch, Patch{prog, target.Sym.Name})
+ p.toPatch = append(p.toPatch, Patch{targetAddr, target.Sym.Name})
} else {
- p.branch(prog, targetProg)
+ p.branch(targetAddr, targetProg)
}
case target.Type == obj.TYPE_MEM && target.Name == obj.NAME_NONE:
// JMP 4(R0)
- prog.To = *target
+ *targetAddr = *target
// On the ppc64, 9a encodes BR (CTR) as BR CTR. We do the same.
if p.arch.Family == sys.PPC64 && target.Offset == 0 {
- prog.To.Type = obj.TYPE_REG
+ targetAddr.Type = obj.TYPE_REG
}
case target.Type == obj.TYPE_CONST:
// JMP $4
- prog.To = a[0]
+ *targetAddr = a[0]
case target.Type == obj.TYPE_NONE:
// JMP
default:
p.errorf("undefined label %s", patch.label)
return
}
- p.branch(patch.prog, targetProg)
+ p.branch(patch.addr, targetProg)
}
p.toPatch = p.toPatch[:0]
}
-func (p *Parser) branch(jmp, target *obj.Prog) {
- jmp.To = obj.Addr{
+func (p *Parser) branch(addr *obj.Addr, target *obj.Prog) {
+ *addr = obj.Addr{
Type: obj.TYPE_BRANCH,
Index: 0,
}
- jmp.To.Val = target
+ addr.Val = target
}
// asmInstruction assembles an instruction.