// We have consumed the register or R prefix.
func (p *Parser) atRegisterShift() bool {
// ARM only.
- if p.arch.Family != sys.ARM {
+ if !p.arch.InFamily(sys.ARM, sys.ARM64) {
return false
}
// R1<<...
return r1, r2, scale, true
}
-// registerShift parses an ARM shifted register reference and returns the encoded representation.
+// registerShift parses an ARM/ARM64 shifted register reference and returns the encoded representation.
// There is known to be a register (current token) and a shift operator (peeked token).
func (p *Parser) registerShift(name string, prefix rune) int64 {
if prefix != 0 {
case lex.ARR:
op = 2
case lex.ROT:
+ // following instructions on ARM64 support rotate right
+ // AND, ANDS, TST, BIC, BICS, EON, EOR, ORR, MVN, ORN
op = 3
}
tok := p.next()
var count int16
switch tok.ScanToken {
case scanner.Ident:
- r2, ok := p.registerReference(str)
- if !ok {
- p.errorf("rhs of shift must be register or integer: %s", str)
+ if p.arch.Family == sys.ARM64 {
+ p.errorf("rhs of shift must be integer: %s", str)
+ } else {
+ r2, ok := p.registerReference(str)
+ if !ok {
+ p.errorf("rhs of shift must be register or integer: %s", str)
+ }
+ count = (r2&15)<<8 | 1<<4
}
- count = (r2&15)<<8 | 1<<4
case scanner.Int, '(':
p.back()
x := int64(p.expr())
- if x >= 32 {
- p.errorf("register shift count too large: %s", str)
+ if p.arch.Family == sys.ARM64 {
+ if x >= 64 {
+ p.errorf("register shift count too large: %s", str)
+ }
+ count = int16((x & 63) << 10)
+ } else {
+ if x >= 32 {
+ p.errorf("register shift count too large: %s", str)
+ }
+ count = int16((x & 31) << 7)
}
- count = int16((x & 31) << 7)
default:
p.errorf("unexpected %s in register shift", tok.String())
}
- return int64((r1 & 15) | op<<5 | count)
+ if p.arch.Family == sys.ARM64 {
+ return int64(int64(r1 & 31)<<16 | int64(op)<<22 | int64(uint16(count)))
+ } else {
+ return int64((r1 & 15) | op<<5 | count)
+ }
}
// symbolReference parses a symbol that is known not to be a register.