list7.go raw

   1  // cmd/7l/list.c and cmd/7l/sub.c from Vita Nuova.
   2  // https://code.google.com/p/ken-cc/source/browse/
   3  //
   4  // 	Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
   5  // 	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
   6  // 	Portions Copyright © 1997-1999 Vita Nuova Limited
   7  // 	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
   8  // 	Portions Copyright © 2004,2006 Bruce Ellis
   9  // 	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
  10  // 	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
  11  // 	Portions Copyright © 2009 The Go Authors. All rights reserved.
  12  //
  13  // Permission is hereby granted, free of charge, to any person obtaining a copy
  14  // of this software and associated documentation files (the "Software"), to deal
  15  // in the Software without restriction, including without limitation the rights
  16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  17  // copies of the Software, and to permit persons to whom the Software is
  18  // furnished to do so, subject to the following conditions:
  19  //
  20  // The above copyright notice and this permission notice shall be included in
  21  // all copies or substantial portions of the Software.
  22  //
  23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  29  // THE SOFTWARE.
  30  
  31  package arm64
  32  
  33  import (
  34  	"github.com/twitchyliquid64/golang-asm/obj"
  35  	"fmt"
  36  )
  37  
  38  var strcond = [16]string{
  39  	"EQ",
  40  	"NE",
  41  	"HS",
  42  	"LO",
  43  	"MI",
  44  	"PL",
  45  	"VS",
  46  	"VC",
  47  	"HI",
  48  	"LS",
  49  	"GE",
  50  	"LT",
  51  	"GT",
  52  	"LE",
  53  	"AL",
  54  	"NV",
  55  }
  56  
  57  func init() {
  58  	obj.RegisterRegister(obj.RBaseARM64, REG_SPECIAL+1024, rconv)
  59  	obj.RegisterOpcode(obj.ABaseARM64, Anames)
  60  	obj.RegisterRegisterList(obj.RegListARM64Lo, obj.RegListARM64Hi, rlconv)
  61  	obj.RegisterOpSuffix("arm64", obj.CConvARM)
  62  }
  63  
  64  func arrange(a int) string {
  65  	switch a {
  66  	case ARNG_8B:
  67  		return "B8"
  68  	case ARNG_16B:
  69  		return "B16"
  70  	case ARNG_4H:
  71  		return "H4"
  72  	case ARNG_8H:
  73  		return "H8"
  74  	case ARNG_2S:
  75  		return "S2"
  76  	case ARNG_4S:
  77  		return "S4"
  78  	case ARNG_1D:
  79  		return "D1"
  80  	case ARNG_2D:
  81  		return "D2"
  82  	case ARNG_B:
  83  		return "B"
  84  	case ARNG_H:
  85  		return "H"
  86  	case ARNG_S:
  87  		return "S"
  88  	case ARNG_D:
  89  		return "D"
  90  	case ARNG_1Q:
  91  		return "Q1"
  92  	default:
  93  		return ""
  94  	}
  95  }
  96  
  97  func rconv(r int) string {
  98  	ext := (r >> 5) & 7
  99  	if r == REGG {
 100  		return "g"
 101  	}
 102  	switch {
 103  	case REG_R0 <= r && r <= REG_R30:
 104  		return fmt.Sprintf("R%d", r-REG_R0)
 105  	case r == REG_R31:
 106  		return "ZR"
 107  	case REG_F0 <= r && r <= REG_F31:
 108  		return fmt.Sprintf("F%d", r-REG_F0)
 109  	case REG_V0 <= r && r <= REG_V31:
 110  		return fmt.Sprintf("V%d", r-REG_V0)
 111  	case COND_EQ <= r && r <= COND_NV:
 112  		return strcond[r-COND_EQ]
 113  	case r == REGSP:
 114  		return "RSP"
 115  	case r == REG_DAIFSet:
 116  		return "DAIFSet"
 117  	case r == REG_DAIFClr:
 118  		return "DAIFClr"
 119  	case r == REG_PLDL1KEEP:
 120  		return "PLDL1KEEP"
 121  	case r == REG_PLDL1STRM:
 122  		return "PLDL1STRM"
 123  	case r == REG_PLDL2KEEP:
 124  		return "PLDL2KEEP"
 125  	case r == REG_PLDL2STRM:
 126  		return "PLDL2STRM"
 127  	case r == REG_PLDL3KEEP:
 128  		return "PLDL3KEEP"
 129  	case r == REG_PLDL3STRM:
 130  		return "PLDL3STRM"
 131  	case r == REG_PLIL1KEEP:
 132  		return "PLIL1KEEP"
 133  	case r == REG_PLIL1STRM:
 134  		return "PLIL1STRM"
 135  	case r == REG_PLIL2KEEP:
 136  		return "PLIL2KEEP"
 137  	case r == REG_PLIL2STRM:
 138  		return "PLIL2STRM"
 139  	case r == REG_PLIL3KEEP:
 140  		return "PLIL3KEEP"
 141  	case r == REG_PLIL3STRM:
 142  		return "PLIL3STRM"
 143  	case r == REG_PSTL1KEEP:
 144  		return "PSTL1KEEP"
 145  	case r == REG_PSTL1STRM:
 146  		return "PSTL1STRM"
 147  	case r == REG_PSTL2KEEP:
 148  		return "PSTL2KEEP"
 149  	case r == REG_PSTL2STRM:
 150  		return "PSTL2STRM"
 151  	case r == REG_PSTL3KEEP:
 152  		return "PSTL3KEEP"
 153  	case r == REG_PSTL3STRM:
 154  		return "PSTL3STRM"
 155  	case REG_UXTB <= r && r < REG_UXTH:
 156  		if ext != 0 {
 157  			return fmt.Sprintf("%s.UXTB<<%d", regname(r), ext)
 158  		} else {
 159  			return fmt.Sprintf("%s.UXTB", regname(r))
 160  		}
 161  	case REG_UXTH <= r && r < REG_UXTW:
 162  		if ext != 0 {
 163  			return fmt.Sprintf("%s.UXTH<<%d", regname(r), ext)
 164  		} else {
 165  			return fmt.Sprintf("%s.UXTH", regname(r))
 166  		}
 167  	case REG_UXTW <= r && r < REG_UXTX:
 168  		if ext != 0 {
 169  			return fmt.Sprintf("%s.UXTW<<%d", regname(r), ext)
 170  		} else {
 171  			return fmt.Sprintf("%s.UXTW", regname(r))
 172  		}
 173  	case REG_UXTX <= r && r < REG_SXTB:
 174  		if ext != 0 {
 175  			return fmt.Sprintf("%s.UXTX<<%d", regname(r), ext)
 176  		} else {
 177  			return fmt.Sprintf("%s.UXTX", regname(r))
 178  		}
 179  	case REG_SXTB <= r && r < REG_SXTH:
 180  		if ext != 0 {
 181  			return fmt.Sprintf("%s.SXTB<<%d", regname(r), ext)
 182  		} else {
 183  			return fmt.Sprintf("%s.SXTB", regname(r))
 184  		}
 185  	case REG_SXTH <= r && r < REG_SXTW:
 186  		if ext != 0 {
 187  			return fmt.Sprintf("%s.SXTH<<%d", regname(r), ext)
 188  		} else {
 189  			return fmt.Sprintf("%s.SXTH", regname(r))
 190  		}
 191  	case REG_SXTW <= r && r < REG_SXTX:
 192  		if ext != 0 {
 193  			return fmt.Sprintf("%s.SXTW<<%d", regname(r), ext)
 194  		} else {
 195  			return fmt.Sprintf("%s.SXTW", regname(r))
 196  		}
 197  	case REG_SXTX <= r && r < REG_SPECIAL:
 198  		if ext != 0 {
 199  			return fmt.Sprintf("%s.SXTX<<%d", regname(r), ext)
 200  		} else {
 201  			return fmt.Sprintf("%s.SXTX", regname(r))
 202  		}
 203  	// bits 0-4 indicate register, bits 5-7 indicate shift amount, bit 8 equals to 0.
 204  	case REG_LSL <= r && r < (REG_LSL+1<<8):
 205  		return fmt.Sprintf("R%d<<%d", r&31, (r>>5)&7)
 206  	case REG_ARNG <= r && r < REG_ELEM:
 207  		return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15))
 208  	case REG_ELEM <= r && r < REG_ELEM_END:
 209  		return fmt.Sprintf("V%d.%s", r&31, arrange((r>>5)&15))
 210  	}
 211  	// Return system register name.
 212  	name, _, _ := SysRegEnc(int16(r))
 213  	if name != "" {
 214  		return name
 215  	}
 216  	return fmt.Sprintf("badreg(%d)", r)
 217  }
 218  
 219  func DRconv(a int) string {
 220  	if a >= C_NONE && a <= C_NCLASS {
 221  		return cnames7[a]
 222  	}
 223  	return "C_??"
 224  }
 225  
 226  func rlconv(list int64) string {
 227  	str := ""
 228  
 229  	// ARM64 register list follows ARM64 instruction decode schema
 230  	// | 31 | 30 | ... | 15 - 12 | 11 - 10 | ... |
 231  	// +----+----+-----+---------+---------+-----+
 232  	// |    | Q  | ... | opcode  |   size  | ... |
 233  
 234  	firstReg := int(list & 31)
 235  	opcode := (list >> 12) & 15
 236  	var regCnt int
 237  	var t string
 238  	switch opcode {
 239  	case 0x7:
 240  		regCnt = 1
 241  	case 0xa:
 242  		regCnt = 2
 243  	case 0x6:
 244  		regCnt = 3
 245  	case 0x2:
 246  		regCnt = 4
 247  	default:
 248  		regCnt = -1
 249  	}
 250  	// Q:size
 251  	arng := ((list>>30)&1)<<2 | (list>>10)&3
 252  	switch arng {
 253  	case 0:
 254  		t = "B8"
 255  	case 4:
 256  		t = "B16"
 257  	case 1:
 258  		t = "H4"
 259  	case 5:
 260  		t = "H8"
 261  	case 2:
 262  		t = "S2"
 263  	case 6:
 264  		t = "S4"
 265  	case 3:
 266  		t = "D1"
 267  	case 7:
 268  		t = "D2"
 269  	}
 270  	for i := 0; i < regCnt; i++ {
 271  		if str == "" {
 272  			str += "["
 273  		} else {
 274  			str += ","
 275  		}
 276  		str += fmt.Sprintf("V%d.", (firstReg+i)&31)
 277  		str += t
 278  	}
 279  	str += "]"
 280  	return str
 281  }
 282  
 283  func regname(r int) string {
 284  	if r&31 == 31 {
 285  		return "ZR"
 286  	}
 287  	return fmt.Sprintf("R%d", r&31)
 288  }
 289