// cmd/7l/list.c and cmd/7l/sub.c from Vita Nuova. // https://bitbucket.org/plan9-from-bell-labs/9-cc/src/master/ // // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) // Portions Copyright © 1997-1999 Vita Nuova Limited // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) // Portions Copyright © 2004,2006 Bruce Ellis // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others // Portions Copyright © 2009 The Go Authors. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. package arm64 import ( "cmd/internal/obj" "fmt" ) var strcond = [16]string{ "EQ", "NE", "HS", "LO", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "AL", "NV", } func init() { obj.RegisterRegister(obj.RBaseARM64, REG_SPECIAL+1024, rconv) obj.RegisterOpcode(obj.ABaseARM64, Anames) obj.RegisterRegisterList(obj.RegListARM64Lo, obj.RegListARM64Hi, rlconv) obj.RegisterOpSuffix("arm64", obj.CConvARM) obj.RegisterSpecialOperands(int64(SPOP_BEGIN), int64(SPOP_END), SPCconv) } func arrange(a int) string { switch a { case ARNG_8B: return "B8" case ARNG_16B: return "B16" case ARNG_4H: return "H4" case ARNG_8H: return "H8" case ARNG_2S: return "S2" case ARNG_4S: return "S4" case ARNG_1D: return "D1" case ARNG_2D: return "D2" case ARNG_B: return "B" case ARNG_H: return "H" case ARNG_S: return "S" case ARNG_D: return "D" case ARNG_1Q: return "Q1" default: return "" } } func rconv(r int) string { ext := (r >> 5) & 7 if r == REGG { return "g" } switch { case REG_R0 <= r && r <= REG_R30: return fmt.Sprintf("R%d", r-REG_R0) case r == REG_R31: return "ZR" case REG_F0 <= r && r <= REG_F31: return fmt.Sprintf("F%d", r-REG_F0) case REG_V0 <= r && r <= REG_V31: return fmt.Sprintf("V%d", r-REG_V0) case r == REGSP: return "RSP" case REG_UXTB <= r && r < REG_UXTH: if ext != 0 { return fmt.Sprintf("%s.UXTB<<%d", regname(r), ext) } else { return fmt.Sprintf("%s.UXTB", regname(r)) } case REG_UXTH <= r && r < REG_UXTW: if ext != 0 { return fmt.Sprintf("%s.UXTH<<%d", regname(r), ext) } else { return fmt.Sprintf("%s.UXTH", regname(r)) } case REG_UXTW <= r && r < REG_UXTX: if ext != 0 { return fmt.Sprintf("%s.UXTW<<%d", regname(r), ext) } else { return fmt.Sprintf("%s.UXTW", regname(r)) } case REG_UXTX <= r && r < REG_SXTB: if ext != 0 { return fmt.Sprintf("%s.UXTX<<%d", regname(r), ext) } else { return fmt.Sprintf("%s.UXTX", regname(r)) } case REG_SXTB <= r && r < REG_SXTH: if ext != 0 { return fmt.Sprintf("%s.SXTB<<%d", regname(r), ext) } else { return fmt.Sprintf("%s.SXTB", regname(r)) } case REG_SXTH <= r && r < REG_SXTW: if ext != 0 { return fmt.Sprintf("%s.SXTH<<%d", regname(r), ext) } else { return fmt.Sprintf("%s.SXTH", regname(r)) } case REG_SXTW <= r && r < REG_SXTX: if ext != 0 { return fmt.Sprintf("%s.SXTW<<%d", regname(r), ext) } else { return fmt.Sprintf("%s.SXTW", regname(r)) } case REG_SXTX <= r && r < REG_SPECIAL: if ext != 0 { return fmt.Sprintf("%s.SXTX<<%d", regname(r), ext) } else { return fmt.Sprintf("%s.SXTX", regname(r)) } // bits 0-4 indicate register, bits 5-7 indicate shift amount, bit 8 equals to 0. case REG_LSL <= r && r < (REG_LSL+1<<8): return fmt.Sprintf("R%d<<%d", r&31, (r>>5)&7) case REG_ARNG <= r && r < REG_ELEM: return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15)) case REG_ELEM <= r && r < REG_ELEM_END: return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15)) } // Return system register name. name, _, _ := SysRegEnc(int16(r)) if name != "" { return name } return fmt.Sprintf("badreg(%d)", r) } func DRconv(a int) string { if a >= C_NONE && a <= C_NCLASS { return cnames7[a] } return "C_??" } func SPCconv(a int64) string { spc := SpecialOperand(a) if spc >= SPOP_BEGIN && spc < SPOP_END { return fmt.Sprintf("%s", spc) } return "SPC_??" } func rlconv(list int64) string { str := "" // ARM64 register list follows ARM64 instruction decode schema // | 31 | 30 | ... | 15 - 12 | 11 - 10 | ... | // +----+----+-----+---------+---------+-----+ // | | Q | ... | opcode | size | ... | firstReg := int(list & 31) opcode := (list >> 12) & 15 var regCnt int var t string switch opcode { case 0x7: regCnt = 1 case 0xa: regCnt = 2 case 0x6: regCnt = 3 case 0x2: regCnt = 4 default: regCnt = -1 } // Q:size arng := ((list>>30)&1)<<2 | (list>>10)&3 switch arng { case 0: t = "B8" case 4: t = "B16" case 1: t = "H4" case 5: t = "H8" case 2: t = "S2" case 6: t = "S4" case 3: t = "D1" case 7: t = "D2" } for i := 0; i < regCnt; i++ { if str == "" { str += "[" } else { str += "," } str += fmt.Sprintf("V%d.", (firstReg+i)&31) str += t } str += "]" return str } func regname(r int) string { if r&31 == 31 { return "ZR" } return fmt.Sprintf("R%d", r&31) }