github.com/bir3/gocompiler@v0.9.2202/src/cmd/internal/obj/arm/asm5.go (about) 1 // Inferno utils/5l/span.c 2 // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/span.c 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 arm 32 33 import ( 34 "github.com/bir3/gocompiler/src/cmd/internal/obj" 35 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 36 "fmt" 37 "github.com/bir3/gocompiler/src/internal/buildcfg" 38 "log" 39 "math" 40 "sort" 41 ) 42 43 // ctxt5 holds state while assembling a single function. 44 // Each function gets a fresh ctxt5. 45 // This allows for multiple functions to be safely concurrently assembled. 46 type ctxt5 struct { 47 ctxt *obj.Link 48 newprog obj.ProgAlloc 49 cursym *obj.LSym 50 printp *obj.Prog 51 blitrl *obj.Prog 52 elitrl *obj.Prog 53 autosize int64 54 instoffset int64 55 pc int64 56 pool struct { 57 start uint32 58 size uint32 59 extra uint32 60 } 61 } 62 63 type Optab struct { 64 as obj.As 65 a1 uint8 66 a2 int8 67 a3 uint8 68 type_ uint8 69 size int8 70 param int16 71 flag int8 72 pcrelsiz uint8 73 scond uint8 // optional flags accepted by the instruction 74 } 75 76 type Opcross [32][2][32]uint8 77 78 const ( 79 LFROM = 1 << 0 80 LTO = 1 << 1 81 LPOOL = 1 << 2 82 LPCREL = 1 << 3 83 ) 84 85 var optab = []Optab{ 86 /* struct Optab: 87 OPCODE, from, prog->reg, to, type, size, param, flag, extra data size, optional suffix */ 88 {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0, 0}, 89 {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT}, 90 {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, 91 {AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT}, 92 {AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, 93 {AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT}, 94 {AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, 95 {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, 96 {AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT}, 97 {ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0, 0}, 98 {AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT}, 99 {AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT}, 100 {AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT}, 101 {AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT}, 102 {AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT}, 103 {AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT}, 104 {AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0}, 105 {AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0}, 106 {ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0, 0}, 107 {AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT}, 108 {AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT}, 109 {AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT}, 110 {AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT}, 111 {AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT}, 112 {AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT}, 113 {AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT}, 114 {ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0, 0}, 115 {AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0, C_SBIT}, 116 {AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0, 0}, 117 {ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, 118 {ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0, 0}, 119 {ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, 120 {ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // prediction hinted form, hint ignored 121 {AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0, 0}, 122 {ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0}, 123 {ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0}, 124 {ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0, 0}, 125 {ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0, 0}, 126 {ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0, C_SBIT}, 127 {ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0, C_SBIT}, 128 {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0, C_SBIT}, 129 {ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0, C_SBIT}, 130 {ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0, 0}, 131 {ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0, 0}, 132 {AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0, 0}, 133 {AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0, 0}, 134 {AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0, 0}, 135 {AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0, 0}, 136 {AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0, 0}, 137 {AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0}, 138 {AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0}, 139 {AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0, 0}, 140 {AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4, 0}, 141 {AMVN, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0}, 142 {AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 143 {AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 144 {AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 145 {AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 146 {AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 147 {AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 148 {ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0}, 149 {AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 150 {AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 151 {AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 152 {AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 153 {AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 154 {AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT}, 155 {AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, 0}, 156 {ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0}, 157 {AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0}, 158 {AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0}, 159 {AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0}, 160 {AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0}, 161 {AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0, 0}, 162 {AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0, 0}, 163 {AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, 164 {AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, 165 {AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, 166 {AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, 167 {AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, 168 {AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT}, 169 {AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, 0}, 170 {ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0, 0}, 171 {AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0}, 172 {AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0}, 173 {AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0, 0}, 174 {AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0}, 175 {AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0}, 176 {AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0}, 177 {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0, C_SBIT}, 178 {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0, C_SBIT}, 179 {ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0, 0}, 180 {ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0, 0}, 181 {ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0, 0}, 182 {ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0, 0}, 183 {AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0, C_SBIT}, 184 {ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0, 0}, // width in From, LSB in From3 185 {ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0, 0}, // width in From, LSB in From3 186 {AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 187 {AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 188 {AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 189 {AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 190 {AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 191 {AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 192 {AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 193 {AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 194 {AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 195 {AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 196 {AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 197 {AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 198 {AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0, 0}, 199 {AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0, 0}, 200 {AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, C_SBIT}, 201 {AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, 202 {AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, 203 {AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, 204 {AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, 205 {AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, 206 {AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0}, 207 {AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 208 {AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 209 {AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 210 {AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 211 {AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 212 {AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 213 {AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 214 {AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 215 {AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 216 {AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 217 {AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 218 {AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 219 {AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0, 0}, 220 {AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0, 0}, 221 {AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 222 {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 223 {AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 224 {AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 225 {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 226 {AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 227 {AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0, C_SBIT}, 228 {AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0, 0}, 229 {AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0, 0}, 230 {AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0, 0}, 231 {AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 232 {AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 233 {ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0, 0}, 234 {ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0, 0}, 235 {AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 236 {AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 237 {AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 238 {AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 239 {AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 240 {AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 241 {AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 242 {AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 243 {AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 244 {AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 245 {AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0, 0}, 246 {AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0, 0}, 247 {AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0}, 248 {ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0}, 249 {AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0, 0}, 250 {AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0, 0}, 251 {AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 252 {AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 253 {AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 254 {AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 255 {AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 256 {AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 257 {AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 258 {AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 259 {AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 260 {AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 261 {AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 262 {AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 263 {AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 264 {AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 265 {AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 266 {AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 267 {AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 268 {AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 269 {AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 270 {AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 271 {AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 272 {AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 273 {AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 274 {AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 275 {AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 276 {AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 277 {AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 278 {AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 279 {AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 280 {AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT}, 281 {AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 282 {AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 283 {AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 284 {AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 285 {AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 286 {AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 287 {AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 288 {AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT}, 289 {AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 290 {AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 291 {AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 292 {AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 293 {AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 294 {AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 295 {AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 296 {AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 297 {AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 298 {AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 299 {AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 300 {AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 301 {AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 302 {AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 303 {AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT}, 304 {AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT}, 305 {ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0, 0}, 306 {ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0, 0}, 307 {ADMB, C_NONE, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0}, 308 {ADMB, C_LCON, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0}, 309 {ADMB, C_SPR, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0}, 310 {AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0, 0}, 311 {AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0, 0}, 312 {ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0, 0}, 313 {ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0, 0}, 314 {AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0, C_UBIT}, 315 {AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0, C_UBIT}, 316 {AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0, C_UBIT}, 317 {AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0, C_UBIT}, 318 {AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0, 0}, 319 {AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0, 0}, 320 {ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0, 0}, 321 {ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0, 0}, 322 {APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0, 0}, 323 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0, 0}, 324 {ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0, 0}, 325 {AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0, 0}, 326 {AMULA, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, C_SBIT}, 327 {AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, 0}, 328 {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0, 0}, 329 {obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0, 0}, 330 {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, 331 {obj.ANOP, C_LCON, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, // nop variants, see #40689 332 {obj.ANOP, C_REG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, 333 {obj.ANOP, C_FREG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, 334 {obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL 335 {obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL 336 {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0, 0}, 337 } 338 339 var mbOp = []struct { 340 reg int16 341 enc uint32 342 }{ 343 {REG_MB_SY, 15}, 344 {REG_MB_ST, 14}, 345 {REG_MB_ISH, 11}, 346 {REG_MB_ISHST, 10}, 347 {REG_MB_NSH, 7}, 348 {REG_MB_NSHST, 6}, 349 {REG_MB_OSH, 3}, 350 {REG_MB_OSHST, 2}, 351 } 352 353 var oprange [ALAST & obj.AMask][]Optab 354 355 var xcmp [C_GOK + 1][C_GOK + 1]bool 356 357 var ( 358 symdiv *obj.LSym 359 symdivu *obj.LSym 360 symmod *obj.LSym 361 symmodu *obj.LSym 362 ) 363 364 // Note about encoding: Prog.scond holds the condition encoding, 365 // but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0. 366 // The code that shifts the value << 28 has the responsibility 367 // for XORing with C_SCOND_XOR too. 368 369 func checkSuffix(c *ctxt5, p *obj.Prog, o *Optab) { 370 if p.Scond&C_SBIT != 0 && o.scond&C_SBIT == 0 { 371 c.ctxt.Diag("invalid .S suffix: %v", p) 372 } 373 if p.Scond&C_PBIT != 0 && o.scond&C_PBIT == 0 { 374 c.ctxt.Diag("invalid .P suffix: %v", p) 375 } 376 if p.Scond&C_WBIT != 0 && o.scond&C_WBIT == 0 { 377 c.ctxt.Diag("invalid .W suffix: %v", p) 378 } 379 if p.Scond&C_UBIT != 0 && o.scond&C_UBIT == 0 { 380 c.ctxt.Diag("invalid .U suffix: %v", p) 381 } 382 } 383 384 func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { 385 if ctxt.Retpoline { 386 ctxt.Diag("-spectre=ret not supported on arm") 387 ctxt.Retpoline = false // don't keep printing 388 } 389 390 var p *obj.Prog 391 var op *obj.Prog 392 393 p = cursym.Func().Text 394 if p == nil || p.Link == nil { // handle external functions and ELF section symbols 395 return 396 } 397 398 if oprange[AAND&obj.AMask] == nil { 399 ctxt.Diag("arm ops not initialized, call arm.buildop first") 400 } 401 402 c := ctxt5{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: p.To.Offset + 4} 403 pc := int32(0) 404 405 op = p 406 p = p.Link 407 var m int 408 var o *Optab 409 for ; p != nil || c.blitrl != nil; op, p = p, p.Link { 410 if p == nil { 411 if c.checkpool(op, pc) { 412 p = op 413 continue 414 } 415 416 // can't happen: blitrl is not nil, but checkpool didn't flushpool 417 ctxt.Diag("internal inconsistency") 418 419 break 420 } 421 422 p.Pc = int64(pc) 423 o = c.oplook(p) 424 m = int(o.size) 425 426 if m%4 != 0 || p.Pc%4 != 0 { 427 ctxt.Diag("!pc invalid: %v size=%d", p, m) 428 } 429 430 // must check literal pool here in case p generates many instructions 431 if c.blitrl != nil { 432 // Emit the constant pool just before p if p 433 // would push us over the immediate size limit. 434 if c.checkpool(op, pc+int32(m)) { 435 // Back up to the instruction just 436 // before the pool and continue with 437 // the first instruction of the pool. 438 p = op 439 continue 440 } 441 } 442 443 if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) { 444 ctxt.Diag("zero-width instruction\n%v", p) 445 continue 446 } 447 448 switch o.flag & (LFROM | LTO | LPOOL) { 449 case LFROM: 450 c.addpool(p, &p.From) 451 452 case LTO: 453 c.addpool(p, &p.To) 454 455 case LPOOL: 456 if p.Scond&C_SCOND == C_SCOND_NONE { 457 c.flushpool(p, 0, 0) 458 } 459 } 460 461 if p.As == AMOVW && p.To.Type == obj.TYPE_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE { 462 c.flushpool(p, 0, 0) 463 } 464 465 pc += int32(m) 466 } 467 468 c.cursym.Size = int64(pc) 469 470 /* 471 * if any procedure is large enough to 472 * generate a large SBRA branch, then 473 * generate extra passes putting branches 474 * around jmps to fix. this is rare. 475 */ 476 times := 0 477 478 var bflag int 479 var opc int32 480 var out [6 + 3]uint32 481 for { 482 bflag = 0 483 pc = 0 484 times++ 485 c.cursym.Func().Text.Pc = 0 // force re-layout the code. 486 for p = c.cursym.Func().Text; p != nil; p = p.Link { 487 o = c.oplook(p) 488 if int64(pc) > p.Pc { 489 p.Pc = int64(pc) 490 } 491 492 /* very large branches 493 if(o->type == 6 && p->pcond) { 494 otxt = p->pcond->pc - c; 495 if(otxt < 0) 496 otxt = -otxt; 497 if(otxt >= (1L<<17) - 10) { 498 q = emallocz(sizeof(Prog)); 499 q->link = p->link; 500 p->link = q; 501 q->as = AB; 502 q->to.type = TYPE_BRANCH; 503 q->pcond = p->pcond; 504 p->pcond = q; 505 q = emallocz(sizeof(Prog)); 506 q->link = p->link; 507 p->link = q; 508 q->as = AB; 509 q->to.type = TYPE_BRANCH; 510 q->pcond = q->link->link; 511 bflag = 1; 512 } 513 } 514 */ 515 opc = int32(p.Pc) 516 m = int(o.size) 517 if p.Pc != int64(opc) { 518 bflag = 1 519 } 520 521 //print("%v pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times); 522 pc = int32(p.Pc + int64(m)) 523 524 if m%4 != 0 || p.Pc%4 != 0 { 525 ctxt.Diag("pc invalid: %v size=%d", p, m) 526 } 527 528 if m/4 > len(out) { 529 ctxt.Diag("instruction size too large: %d > %d", m/4, len(out)) 530 } 531 if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) { 532 if p.As == obj.ATEXT { 533 c.autosize = p.To.Offset + 4 534 continue 535 } 536 537 ctxt.Diag("zero-width instruction\n%v", p) 538 continue 539 } 540 } 541 542 c.cursym.Size = int64(pc) 543 if bflag == 0 { 544 break 545 } 546 } 547 548 if pc%4 != 0 { 549 ctxt.Diag("sym->size=%d, invalid", pc) 550 } 551 552 /* 553 * lay out the code. all the pc-relative code references, 554 * even cross-function, are resolved now; 555 * only data references need to be relocated. 556 * with more work we could leave cross-function 557 * code references to be relocated too, and then 558 * perhaps we'd be able to parallelize the span loop above. 559 */ 560 561 p = c.cursym.Func().Text 562 c.autosize = p.To.Offset + 4 563 c.cursym.Grow(c.cursym.Size) 564 565 bp := c.cursym.P 566 pc = int32(p.Pc) // even p->link might need extra padding 567 var v int 568 for p = p.Link; p != nil; p = p.Link { 569 c.pc = p.Pc 570 o = c.oplook(p) 571 opc = int32(p.Pc) 572 c.asmout(p, o, out[:]) 573 m = int(o.size) 574 575 if m%4 != 0 || p.Pc%4 != 0 { 576 ctxt.Diag("final stage: pc invalid: %v size=%d", p, m) 577 } 578 579 if int64(pc) > p.Pc { 580 ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, pc, p) 581 } 582 for int64(pc) != p.Pc { 583 // emit 0xe1a00000 (MOVW R0, R0) 584 bp[0] = 0x00 585 bp = bp[1:] 586 587 bp[0] = 0x00 588 bp = bp[1:] 589 bp[0] = 0xa0 590 bp = bp[1:] 591 bp[0] = 0xe1 592 bp = bp[1:] 593 pc += 4 594 } 595 596 for i := 0; i < m/4; i++ { 597 v = int(out[i]) 598 bp[0] = byte(v) 599 bp = bp[1:] 600 bp[0] = byte(v >> 8) 601 bp = bp[1:] 602 bp[0] = byte(v >> 16) 603 bp = bp[1:] 604 bp[0] = byte(v >> 24) 605 bp = bp[1:] 606 } 607 608 pc += int32(m) 609 } 610 } 611 612 // checkpool flushes the literal pool when the first reference to 613 // it threatens to go out of range of a 12-bit PC-relative offset. 614 // 615 // nextpc is the tentative next PC at which the pool could be emitted. 616 // checkpool should be called *before* emitting the instruction that 617 // would cause the PC to reach nextpc. 618 // If nextpc is too far from the first pool reference, checkpool will 619 // flush the pool immediately after p. 620 // The caller should resume processing a p.Link. 621 func (c *ctxt5) checkpool(p *obj.Prog, nextpc int32) bool { 622 poolLast := nextpc 623 poolLast += 4 // the AB instruction to jump around the pool 624 poolLast += int32(c.pool.size) - 4 // the offset of the last pool entry 625 626 refPC := int32(c.pool.start) // PC of the first pool reference 627 628 v := poolLast - refPC - 8 // 12-bit PC-relative offset (see omvl) 629 630 if c.pool.size >= 0xff0 || immaddr(v) == 0 { 631 return c.flushpool(p, 1, 0) 632 } else if p.Link == nil { 633 return c.flushpool(p, 2, 0) 634 } 635 return false 636 } 637 638 func (c *ctxt5) flushpool(p *obj.Prog, skip int, force int) bool { 639 if c.blitrl != nil { 640 if skip != 0 { 641 if false && skip == 1 { 642 fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start) 643 } 644 q := c.newprog() 645 q.As = AB 646 q.To.Type = obj.TYPE_BRANCH 647 q.To.SetTarget(p.Link) 648 q.Link = c.blitrl 649 q.Pos = p.Pos 650 c.blitrl = q 651 } else if force == 0 && (p.Pc+int64(c.pool.size)-int64(c.pool.start) < 2048) { 652 return false 653 } 654 655 // The line number for constant pool entries doesn't really matter. 656 // We set it to the line number of the preceding instruction so that 657 // there are no deltas to encode in the pc-line tables. 658 for q := c.blitrl; q != nil; q = q.Link { 659 q.Pos = p.Pos 660 } 661 662 c.elitrl.Link = p.Link 663 p.Link = c.blitrl 664 665 c.blitrl = nil /* BUG: should refer back to values until out-of-range */ 666 c.elitrl = nil 667 c.pool.size = 0 668 c.pool.start = 0 669 c.pool.extra = 0 670 return true 671 } 672 673 return false 674 } 675 676 func (c *ctxt5) addpool(p *obj.Prog, a *obj.Addr) { 677 t := c.newprog() 678 t.As = AWORD 679 680 switch c.aclass(a) { 681 default: 682 t.To.Offset = a.Offset 683 t.To.Sym = a.Sym 684 t.To.Type = a.Type 685 t.To.Name = a.Name 686 687 if c.ctxt.Flag_shared && t.To.Sym != nil { 688 t.Rel = p 689 } 690 691 case C_HOREG, 692 C_FOREG, 693 C_HFOREG, 694 C_SOREG, 695 C_ROREG, 696 C_SROREG, 697 C_LOREG, 698 C_HAUTO, 699 C_FAUTO, 700 C_HFAUTO, 701 C_SAUTO, 702 C_LAUTO, 703 C_LACON: 704 t.To.Type = obj.TYPE_CONST 705 t.To.Offset = c.instoffset 706 } 707 708 if t.Rel == nil { 709 for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ 710 if q.Rel == nil && q.To == t.To { 711 p.Pool = q 712 return 713 } 714 } 715 } 716 717 q := c.newprog() 718 *q = *t 719 q.Pc = int64(c.pool.size) 720 721 if c.blitrl == nil { 722 c.blitrl = q 723 c.pool.start = uint32(p.Pc) 724 } else { 725 c.elitrl.Link = q 726 } 727 c.elitrl = q 728 c.pool.size += 4 729 730 // Store the link to the pool entry in Pool. 731 p.Pool = q 732 } 733 734 func (c *ctxt5) regoff(a *obj.Addr) int32 { 735 c.instoffset = 0 736 c.aclass(a) 737 return int32(c.instoffset) 738 } 739 740 func immrot(v uint32) int32 { 741 for i := 0; i < 16; i++ { 742 if v&^0xff == 0 { 743 return int32(uint32(int32(i)<<8) | v | 1<<25) 744 } 745 v = v<<2 | v>>30 746 } 747 748 return 0 749 } 750 751 // immrot2a returns bits encoding the immediate constant fields of two instructions, 752 // such that the encoded constants x, y satisfy x|y==v, x&y==0. 753 // Returns 0,0 if no such decomposition of v exists. 754 func immrot2a(v uint32) (uint32, uint32) { 755 for i := uint(1); i < 32; i++ { 756 m := uint32(1<<i - 1) 757 if x, y := immrot(v&m), immrot(v&^m); x != 0 && y != 0 { 758 return uint32(x), uint32(y) 759 } 760 } 761 // TODO: handle some more cases, like where 762 // the wraparound from the rotate could help. 763 return 0, 0 764 } 765 766 // immrot2s returns bits encoding the immediate constant fields of two instructions, 767 // such that the encoded constants y, x satisfy y-x==v, y&x==0. 768 // Returns 0,0 if no such decomposition of v exists. 769 func immrot2s(v uint32) (uint32, uint32) { 770 if immrot(v) != 0 { 771 return v, 0 772 } 773 // suppose v in the form of {leading 00, upper effective bits, lower 8 effective bits, trailing 00} 774 // omit trailing 00 775 var i uint32 776 for i = 2; i < 32; i += 2 { 777 if v&(1<<i-1) != 0 { 778 break 779 } 780 } 781 // i must be <= 24, then adjust i just above lower 8 effective bits of v 782 i += 6 783 // let x = {the complement of lower 8 effective bits, trailing 00}, y = x + v 784 x := 1<<i - v&(1<<i-1) 785 y := v + x 786 if y, x = uint32(immrot(y)), uint32(immrot(x)); y != 0 && x != 0 { 787 return y, x 788 } 789 return 0, 0 790 } 791 792 func immaddr(v int32) int32 { 793 if v >= 0 && v <= 0xfff { 794 return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */ 795 } 796 if v >= -0xfff && v < 0 { 797 return -v&0xfff | 1<<24 /* pre indexing */ 798 } 799 return 0 800 } 801 802 func immfloat(v int32) bool { 803 return v&0xC03 == 0 /* offset will fit in floating-point load/store */ 804 } 805 806 func immhalf(v int32) bool { 807 if v >= 0 && v <= 0xff { 808 return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */ 809 } 810 if v >= -0xff && v < 0 { 811 return -v&0xff|1<<24 != 0 /* pre indexing */ 812 } 813 return false 814 } 815 816 func (c *ctxt5) aclass(a *obj.Addr) int { 817 switch a.Type { 818 case obj.TYPE_NONE: 819 return C_NONE 820 821 case obj.TYPE_REG: 822 c.instoffset = 0 823 if REG_R0 <= a.Reg && a.Reg <= REG_R15 { 824 return C_REG 825 } 826 if REG_F0 <= a.Reg && a.Reg <= REG_F15 { 827 return C_FREG 828 } 829 if a.Reg == REG_FPSR || a.Reg == REG_FPCR { 830 return C_FCR 831 } 832 if a.Reg == REG_CPSR || a.Reg == REG_SPSR { 833 return C_PSR 834 } 835 if a.Reg >= REG_SPECIAL { 836 return C_SPR 837 } 838 return C_GOK 839 840 case obj.TYPE_REGREG: 841 return C_REGREG 842 843 case obj.TYPE_REGREG2: 844 return C_REGREG2 845 846 case obj.TYPE_REGLIST: 847 return C_REGLIST 848 849 case obj.TYPE_SHIFT: 850 if a.Reg == 0 { 851 // register shift R>>i 852 return C_SHIFT 853 } else { 854 // memory address with shifted offset R>>i(R) 855 return C_SHIFTADDR 856 } 857 858 case obj.TYPE_MEM: 859 switch a.Name { 860 case obj.NAME_EXTERN, 861 obj.NAME_GOTREF, 862 obj.NAME_STATIC: 863 if a.Sym == nil || a.Sym.Name == "" { 864 fmt.Printf("null sym external\n") 865 return C_GOK 866 } 867 868 c.instoffset = 0 // s.b. unused but just in case 869 if a.Sym.Type == objabi.STLSBSS { 870 if c.ctxt.Flag_shared { 871 return C_TLS_IE 872 } else { 873 return C_TLS_LE 874 } 875 } 876 877 return C_ADDR 878 879 case obj.NAME_AUTO: 880 if a.Reg == REGSP { 881 // unset base register for better printing, since 882 // a.Offset is still relative to pseudo-SP. 883 a.Reg = obj.REG_NONE 884 } 885 c.instoffset = c.autosize + a.Offset 886 if t := immaddr(int32(c.instoffset)); t != 0 { 887 if immhalf(int32(c.instoffset)) { 888 if immfloat(t) { 889 return C_HFAUTO 890 } 891 return C_HAUTO 892 } 893 894 if immfloat(t) { 895 return C_FAUTO 896 } 897 return C_SAUTO 898 } 899 900 return C_LAUTO 901 902 case obj.NAME_PARAM: 903 if a.Reg == REGSP { 904 // unset base register for better printing, since 905 // a.Offset is still relative to pseudo-FP. 906 a.Reg = obj.REG_NONE 907 } 908 c.instoffset = c.autosize + a.Offset + 4 909 if t := immaddr(int32(c.instoffset)); t != 0 { 910 if immhalf(int32(c.instoffset)) { 911 if immfloat(t) { 912 return C_HFAUTO 913 } 914 return C_HAUTO 915 } 916 917 if immfloat(t) { 918 return C_FAUTO 919 } 920 return C_SAUTO 921 } 922 923 return C_LAUTO 924 925 case obj.NAME_NONE: 926 c.instoffset = a.Offset 927 if t := immaddr(int32(c.instoffset)); t != 0 { 928 if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */ 929 if immfloat(t) { 930 return C_HFOREG 931 } 932 return C_HOREG 933 } 934 935 if immfloat(t) { 936 return C_FOREG /* n.b. that it will also satisfy immrot */ 937 } 938 if immrot(uint32(c.instoffset)) != 0 { 939 return C_SROREG 940 } 941 if immhalf(int32(c.instoffset)) { 942 return C_HOREG 943 } 944 return C_SOREG 945 } 946 947 if immrot(uint32(c.instoffset)) != 0 { 948 return C_ROREG 949 } 950 return C_LOREG 951 } 952 953 return C_GOK 954 955 case obj.TYPE_FCONST: 956 if c.chipzero5(a.Val.(float64)) >= 0 { 957 return C_ZFCON 958 } 959 if c.chipfloat5(a.Val.(float64)) >= 0 { 960 return C_SFCON 961 } 962 return C_LFCON 963 964 case obj.TYPE_TEXTSIZE: 965 return C_TEXTSIZE 966 967 case obj.TYPE_CONST, 968 obj.TYPE_ADDR: 969 switch a.Name { 970 case obj.NAME_NONE: 971 c.instoffset = a.Offset 972 if a.Reg != 0 { 973 return c.aconsize() 974 } 975 976 if immrot(uint32(c.instoffset)) != 0 { 977 return C_RCON 978 } 979 if immrot(^uint32(c.instoffset)) != 0 { 980 return C_NCON 981 } 982 if uint32(c.instoffset) <= 0xffff && buildcfg.GOARM.Version == 7 { 983 return C_SCON 984 } 985 if x, y := immrot2a(uint32(c.instoffset)); x != 0 && y != 0 { 986 return C_RCON2A 987 } 988 if y, x := immrot2s(uint32(c.instoffset)); x != 0 && y != 0 { 989 return C_RCON2S 990 } 991 return C_LCON 992 993 case obj.NAME_EXTERN, 994 obj.NAME_GOTREF, 995 obj.NAME_STATIC: 996 s := a.Sym 997 if s == nil { 998 break 999 } 1000 c.instoffset = 0 // s.b. unused but just in case 1001 return C_LCONADDR 1002 1003 case obj.NAME_AUTO: 1004 if a.Reg == REGSP { 1005 // unset base register for better printing, since 1006 // a.Offset is still relative to pseudo-SP. 1007 a.Reg = obj.REG_NONE 1008 } 1009 c.instoffset = c.autosize + a.Offset 1010 return c.aconsize() 1011 1012 case obj.NAME_PARAM: 1013 if a.Reg == REGSP { 1014 // unset base register for better printing, since 1015 // a.Offset is still relative to pseudo-FP. 1016 a.Reg = obj.REG_NONE 1017 } 1018 c.instoffset = c.autosize + a.Offset + 4 1019 return c.aconsize() 1020 } 1021 1022 return C_GOK 1023 1024 case obj.TYPE_BRANCH: 1025 return C_SBRA 1026 } 1027 1028 return C_GOK 1029 } 1030 1031 func (c *ctxt5) aconsize() int { 1032 if immrot(uint32(c.instoffset)) != 0 { 1033 return C_RACON 1034 } 1035 if immrot(uint32(-c.instoffset)) != 0 { 1036 return C_RACON 1037 } 1038 return C_LACON 1039 } 1040 1041 func (c *ctxt5) oplook(p *obj.Prog) *Optab { 1042 a1 := int(p.Optab) 1043 if a1 != 0 { 1044 return &optab[a1-1] 1045 } 1046 a1 = int(p.From.Class) 1047 if a1 == 0 { 1048 a1 = c.aclass(&p.From) + 1 1049 p.From.Class = int8(a1) 1050 } 1051 1052 a1-- 1053 a3 := int(p.To.Class) 1054 if a3 == 0 { 1055 a3 = c.aclass(&p.To) + 1 1056 p.To.Class = int8(a3) 1057 } 1058 1059 a3-- 1060 a2 := C_NONE 1061 if p.Reg != 0 { 1062 switch { 1063 case REG_F0 <= p.Reg && p.Reg <= REG_F15: 1064 a2 = C_FREG 1065 case REG_R0 <= p.Reg && p.Reg <= REG_R15: 1066 a2 = C_REG 1067 default: 1068 c.ctxt.Diag("invalid register in %v", p) 1069 } 1070 } 1071 1072 // check illegal base register 1073 switch a1 { 1074 case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR: 1075 if p.From.Reg < REG_R0 || REG_R15 < p.From.Reg { 1076 c.ctxt.Diag("illegal base register: %v", p) 1077 } 1078 default: 1079 } 1080 switch a3 { 1081 case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR: 1082 if p.To.Reg < REG_R0 || REG_R15 < p.To.Reg { 1083 c.ctxt.Diag("illegal base register: %v", p) 1084 } 1085 default: 1086 } 1087 1088 // If current instruction has a .S suffix (flags update), 1089 // we must use the constant pool instead of splitting it. 1090 if (a1 == C_RCON2A || a1 == C_RCON2S) && p.Scond&C_SBIT != 0 { 1091 a1 = C_LCON 1092 } 1093 if (a3 == C_RCON2A || a3 == C_RCON2S) && p.Scond&C_SBIT != 0 { 1094 a3 = C_LCON 1095 } 1096 1097 if false { /*debug['O']*/ 1098 fmt.Printf("oplook %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3)) 1099 fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) 1100 } 1101 1102 if (p.As == ASRL || p.As == ASRA) && p.From.Type == obj.TYPE_CONST && p.From.Offset == 0 { 1103 // Right shifts are weird - a shift that looks like "shift by constant 0" actually 1104 // means "shift by constant 32". Use left shift in this situation instead. 1105 // See issue 64715. 1106 // TODO: rotate by 0? Not currently supported, but if we ever do then include it here. 1107 p.As = ASLL 1108 } 1109 if p.As != AMOVB && p.As != AMOVBS && p.As != AMOVBU && p.As != AMOVH && p.As != AMOVHS && p.As != AMOVHU && p.As != AXTAB && p.As != AXTABU && p.As != AXTAH && p.As != AXTAHU { 1110 // Same here, but for shifts encoded in Addrs. 1111 // Don't do it for the extension ops, which 1112 // need to keep their RR shifts. 1113 fixShift := func(a *obj.Addr) { 1114 if a.Type == obj.TYPE_SHIFT { 1115 typ := a.Offset & SHIFT_RR 1116 isConst := a.Offset&(1<<4) == 0 1117 amount := a.Offset >> 7 & 0x1f 1118 if isConst && amount == 0 && (typ == SHIFT_LR || typ == SHIFT_AR || typ == SHIFT_RR) { 1119 a.Offset -= typ 1120 a.Offset += SHIFT_LL 1121 } 1122 } 1123 } 1124 fixShift(&p.From) 1125 fixShift(&p.To) 1126 } 1127 1128 ops := oprange[p.As&obj.AMask] 1129 c1 := &xcmp[a1] 1130 c3 := &xcmp[a3] 1131 for i := range ops { 1132 op := &ops[i] 1133 if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] { 1134 p.Optab = uint16(cap(optab) - cap(ops) + i + 1) 1135 checkSuffix(c, p, op) 1136 return op 1137 } 1138 } 1139 1140 c.ctxt.Diag("illegal combination %v; %v %v %v; from %d %d; to %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.From.Name, p.To.Type, p.To.Name) 1141 if ops == nil { 1142 ops = optab 1143 } 1144 return &ops[0] 1145 } 1146 1147 func cmp(a int, b int) bool { 1148 if a == b { 1149 return true 1150 } 1151 switch a { 1152 case C_LCON: 1153 if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S { 1154 return true 1155 } 1156 1157 case C_LACON: 1158 if b == C_RACON { 1159 return true 1160 } 1161 1162 case C_LFCON: 1163 if b == C_ZFCON || b == C_SFCON { 1164 return true 1165 } 1166 1167 case C_HFAUTO: 1168 return b == C_HAUTO || b == C_FAUTO 1169 1170 case C_FAUTO, C_HAUTO: 1171 return b == C_HFAUTO 1172 1173 case C_SAUTO: 1174 return cmp(C_HFAUTO, b) 1175 1176 case C_LAUTO: 1177 return cmp(C_SAUTO, b) 1178 1179 case C_HFOREG: 1180 return b == C_HOREG || b == C_FOREG 1181 1182 case C_FOREG, C_HOREG: 1183 return b == C_HFOREG 1184 1185 case C_SROREG: 1186 return cmp(C_SOREG, b) || cmp(C_ROREG, b) 1187 1188 case C_SOREG, C_ROREG: 1189 return b == C_SROREG || cmp(C_HFOREG, b) 1190 1191 case C_LOREG: 1192 return cmp(C_SROREG, b) 1193 1194 case C_LBRA: 1195 if b == C_SBRA { 1196 return true 1197 } 1198 1199 case C_HREG: 1200 return cmp(C_SP, b) || cmp(C_PC, b) 1201 } 1202 1203 return false 1204 } 1205 1206 type ocmp []Optab 1207 1208 func (x ocmp) Len() int { 1209 return len(x) 1210 } 1211 1212 func (x ocmp) Swap(i, j int) { 1213 x[i], x[j] = x[j], x[i] 1214 } 1215 1216 func (x ocmp) Less(i, j int) bool { 1217 p1 := &x[i] 1218 p2 := &x[j] 1219 n := int(p1.as) - int(p2.as) 1220 if n != 0 { 1221 return n < 0 1222 } 1223 n = int(p1.a1) - int(p2.a1) 1224 if n != 0 { 1225 return n < 0 1226 } 1227 n = int(p1.a2) - int(p2.a2) 1228 if n != 0 { 1229 return n < 0 1230 } 1231 n = int(p1.a3) - int(p2.a3) 1232 if n != 0 { 1233 return n < 0 1234 } 1235 return false 1236 } 1237 1238 func opset(a, b0 obj.As) { 1239 oprange[a&obj.AMask] = oprange[b0] 1240 } 1241 1242 func buildop(ctxt *obj.Link) { 1243 if oprange[AAND&obj.AMask] != nil { 1244 // Already initialized; stop now. 1245 // This happens in the cmd/asm tests, 1246 // each of which re-initializes the arch. 1247 return 1248 } 1249 1250 symdiv = ctxt.Lookup("runtime._div") 1251 symdivu = ctxt.Lookup("runtime._divu") 1252 symmod = ctxt.Lookup("runtime._mod") 1253 symmodu = ctxt.Lookup("runtime._modu") 1254 1255 var n int 1256 1257 for i := 0; i < C_GOK; i++ { 1258 for n = 0; n < C_GOK; n++ { 1259 if cmp(n, i) { 1260 xcmp[i][n] = true 1261 } 1262 } 1263 } 1264 for n = 0; optab[n].as != obj.AXXX; n++ { 1265 if optab[n].flag&LPCREL != 0 { 1266 if ctxt.Flag_shared { 1267 optab[n].size += int8(optab[n].pcrelsiz) 1268 } else { 1269 optab[n].flag &^= LPCREL 1270 } 1271 } 1272 } 1273 1274 sort.Sort(ocmp(optab[:n])) 1275 for i := 0; i < n; i++ { 1276 r := optab[i].as 1277 r0 := r & obj.AMask 1278 start := i 1279 for optab[i].as == r { 1280 i++ 1281 } 1282 oprange[r0] = optab[start:i] 1283 i-- 1284 1285 switch r { 1286 default: 1287 ctxt.Diag("unknown op in build: %v", r) 1288 ctxt.DiagFlush() 1289 log.Fatalf("bad code") 1290 1291 case AADD: 1292 opset(ASUB, r0) 1293 opset(ARSB, r0) 1294 opset(AADC, r0) 1295 opset(ASBC, r0) 1296 opset(ARSC, r0) 1297 1298 case AORR: 1299 opset(AEOR, r0) 1300 opset(ABIC, r0) 1301 1302 case ACMP: 1303 opset(ATEQ, r0) 1304 opset(ACMN, r0) 1305 opset(ATST, r0) 1306 1307 case AMVN: 1308 break 1309 1310 case ABEQ: 1311 opset(ABNE, r0) 1312 opset(ABCS, r0) 1313 opset(ABHS, r0) 1314 opset(ABCC, r0) 1315 opset(ABLO, r0) 1316 opset(ABMI, r0) 1317 opset(ABPL, r0) 1318 opset(ABVS, r0) 1319 opset(ABVC, r0) 1320 opset(ABHI, r0) 1321 opset(ABLS, r0) 1322 opset(ABGE, r0) 1323 opset(ABLT, r0) 1324 opset(ABGT, r0) 1325 opset(ABLE, r0) 1326 1327 case ASLL: 1328 opset(ASRL, r0) 1329 opset(ASRA, r0) 1330 1331 case AMUL: 1332 opset(AMULU, r0) 1333 1334 case ADIV: 1335 opset(AMOD, r0) 1336 opset(AMODU, r0) 1337 opset(ADIVU, r0) 1338 1339 case ADIVHW: 1340 opset(ADIVUHW, r0) 1341 1342 case AMOVW, 1343 AMOVB, 1344 AMOVBS, 1345 AMOVBU, 1346 AMOVH, 1347 AMOVHS, 1348 AMOVHU: 1349 break 1350 1351 case ASWPW: 1352 opset(ASWPBU, r0) 1353 1354 case AB, 1355 ABL, 1356 ABX, 1357 ABXRET, 1358 obj.ADUFFZERO, 1359 obj.ADUFFCOPY, 1360 ASWI, 1361 AWORD, 1362 AMOVM, 1363 ARFE, 1364 obj.ATEXT: 1365 break 1366 1367 case AADDF: 1368 opset(AADDD, r0) 1369 opset(ASUBF, r0) 1370 opset(ASUBD, r0) 1371 opset(AMULF, r0) 1372 opset(AMULD, r0) 1373 opset(ANMULF, r0) 1374 opset(ANMULD, r0) 1375 opset(AMULAF, r0) 1376 opset(AMULAD, r0) 1377 opset(AMULSF, r0) 1378 opset(AMULSD, r0) 1379 opset(ANMULAF, r0) 1380 opset(ANMULAD, r0) 1381 opset(ANMULSF, r0) 1382 opset(ANMULSD, r0) 1383 opset(AFMULAF, r0) 1384 opset(AFMULAD, r0) 1385 opset(AFMULSF, r0) 1386 opset(AFMULSD, r0) 1387 opset(AFNMULAF, r0) 1388 opset(AFNMULAD, r0) 1389 opset(AFNMULSF, r0) 1390 opset(AFNMULSD, r0) 1391 opset(ADIVF, r0) 1392 opset(ADIVD, r0) 1393 1394 case ANEGF: 1395 opset(ANEGD, r0) 1396 opset(ASQRTF, r0) 1397 opset(ASQRTD, r0) 1398 opset(AMOVFD, r0) 1399 opset(AMOVDF, r0) 1400 opset(AABSF, r0) 1401 opset(AABSD, r0) 1402 1403 case ACMPF: 1404 opset(ACMPD, r0) 1405 1406 case AMOVF: 1407 opset(AMOVD, r0) 1408 1409 case AMOVFW: 1410 opset(AMOVDW, r0) 1411 1412 case AMOVWF: 1413 opset(AMOVWD, r0) 1414 1415 case AMULL: 1416 opset(AMULAL, r0) 1417 opset(AMULLU, r0) 1418 opset(AMULALU, r0) 1419 1420 case AMULWT: 1421 opset(AMULWB, r0) 1422 opset(AMULBB, r0) 1423 opset(AMMUL, r0) 1424 1425 case AMULAWT: 1426 opset(AMULAWB, r0) 1427 opset(AMULABB, r0) 1428 opset(AMULS, r0) 1429 opset(AMMULA, r0) 1430 opset(AMMULS, r0) 1431 1432 case ABFX: 1433 opset(ABFXU, r0) 1434 opset(ABFC, r0) 1435 opset(ABFI, r0) 1436 1437 case ACLZ: 1438 opset(AREV, r0) 1439 opset(AREV16, r0) 1440 opset(AREVSH, r0) 1441 opset(ARBIT, r0) 1442 1443 case AXTAB: 1444 opset(AXTAH, r0) 1445 opset(AXTABU, r0) 1446 opset(AXTAHU, r0) 1447 1448 case ALDREX, 1449 ASTREX, 1450 ALDREXD, 1451 ASTREXD, 1452 ADMB, 1453 APLD, 1454 AAND, 1455 AMULA, 1456 obj.AUNDEF, 1457 obj.AFUNCDATA, 1458 obj.APCDATA, 1459 obj.ANOP: 1460 break 1461 } 1462 } 1463 } 1464 1465 func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) { 1466 c.printp = p 1467 o1 := uint32(0) 1468 o2 := uint32(0) 1469 o3 := uint32(0) 1470 o4 := uint32(0) 1471 o5 := uint32(0) 1472 o6 := uint32(0) 1473 if false { /*debug['P']*/ 1474 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) 1475 } 1476 switch o.type_ { 1477 default: 1478 c.ctxt.Diag("%v: unknown asm %d", p, o.type_) 1479 1480 case 0: /* pseudo ops */ 1481 if false { /*debug['G']*/ 1482 fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name) 1483 } 1484 1485 case 1: /* op R,[R],R */ 1486 o1 = c.oprrr(p, p.As, int(p.Scond)) 1487 1488 rf := int(p.From.Reg) 1489 rt := int(p.To.Reg) 1490 r := int(p.Reg) 1491 if p.To.Type == obj.TYPE_NONE { 1492 rt = 0 1493 } 1494 if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN { 1495 r = 0 1496 } else if r == 0 { 1497 r = rt 1498 } 1499 o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 1500 1501 case 2: /* movbu $I,[R],R */ 1502 c.aclass(&p.From) 1503 1504 o1 = c.oprrr(p, p.As, int(p.Scond)) 1505 o1 |= uint32(immrot(uint32(c.instoffset))) 1506 rt := int(p.To.Reg) 1507 r := int(p.Reg) 1508 if p.To.Type == obj.TYPE_NONE { 1509 rt = 0 1510 } 1511 if p.As == AMOVW || p.As == AMVN { 1512 r = 0 1513 } else if r == 0 { 1514 r = rt 1515 } 1516 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 1517 1518 case 106: /* op $I,R,R where I can be decomposed into 2 immediates */ 1519 c.aclass(&p.From) 1520 r := int(p.Reg) 1521 rt := int(p.To.Reg) 1522 if r == 0 { 1523 r = rt 1524 } 1525 x, y := immrot2a(uint32(c.instoffset)) 1526 var as2 obj.As 1527 switch p.As { 1528 case AADD, ASUB, AORR, AEOR, ABIC: 1529 as2 = p.As // ADD, SUB, ORR, EOR, BIC 1530 case ARSB: 1531 as2 = AADD // RSB -> RSB/ADD pair 1532 case AADC: 1533 as2 = AADD // ADC -> ADC/ADD pair 1534 case ASBC: 1535 as2 = ASUB // SBC -> SBC/SUB pair 1536 case ARSC: 1537 as2 = AADD // RSC -> RSC/ADD pair 1538 default: 1539 c.ctxt.Diag("unknown second op for %v", p) 1540 } 1541 o1 = c.oprrr(p, p.As, int(p.Scond)) 1542 o2 = c.oprrr(p, as2, int(p.Scond)) 1543 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 1544 o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12 1545 o1 |= x 1546 o2 |= y 1547 1548 case 107: /* op $I,R,R where I can be decomposed into 2 immediates */ 1549 c.aclass(&p.From) 1550 r := int(p.Reg) 1551 rt := int(p.To.Reg) 1552 if r == 0 { 1553 r = rt 1554 } 1555 y, x := immrot2s(uint32(c.instoffset)) 1556 var as2 obj.As 1557 switch p.As { 1558 case AADD: 1559 as2 = ASUB // ADD -> ADD/SUB pair 1560 case ASUB: 1561 as2 = AADD // SUB -> SUB/ADD pair 1562 case ARSB: 1563 as2 = ASUB // RSB -> RSB/SUB pair 1564 case AADC: 1565 as2 = ASUB // ADC -> ADC/SUB pair 1566 case ASBC: 1567 as2 = AADD // SBC -> SBC/ADD pair 1568 case ARSC: 1569 as2 = ASUB // RSC -> RSC/SUB pair 1570 default: 1571 c.ctxt.Diag("unknown second op for %v", p) 1572 } 1573 o1 = c.oprrr(p, p.As, int(p.Scond)) 1574 o2 = c.oprrr(p, as2, int(p.Scond)) 1575 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 1576 o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12 1577 o1 |= y 1578 o2 |= x 1579 1580 case 3: /* add R<<[IR],[R],R */ 1581 o1 = c.mov(p) 1582 1583 case 4: /* MOVW $off(R), R -> add $off,[R],R */ 1584 c.aclass(&p.From) 1585 if c.instoffset < 0 { 1586 o1 = c.oprrr(p, ASUB, int(p.Scond)) 1587 o1 |= uint32(immrot(uint32(-c.instoffset))) 1588 } else { 1589 o1 = c.oprrr(p, AADD, int(p.Scond)) 1590 o1 |= uint32(immrot(uint32(c.instoffset))) 1591 } 1592 r := int(p.From.Reg) 1593 if r == 0 { 1594 r = int(o.param) 1595 } 1596 o1 |= (uint32(r) & 15) << 16 1597 o1 |= (uint32(p.To.Reg) & 15) << 12 1598 1599 case 5: /* bra s */ 1600 o1 = c.opbra(p, p.As, int(p.Scond)) 1601 1602 v := int32(-8) 1603 if p.To.Sym != nil { 1604 rel := obj.Addrel(c.cursym) 1605 rel.Off = int32(c.pc) 1606 rel.Siz = 4 1607 rel.Sym = p.To.Sym 1608 v += int32(p.To.Offset) 1609 rel.Add = int64(o1) | (int64(v)>>2)&0xffffff 1610 rel.Type = objabi.R_CALLARM 1611 break 1612 } 1613 1614 if p.To.Target() != nil { 1615 v = int32((p.To.Target().Pc - c.pc) - 8) 1616 } 1617 o1 |= (uint32(v) >> 2) & 0xffffff 1618 1619 case 6: /* b ,O(R) -> add $O,R,PC */ 1620 c.aclass(&p.To) 1621 1622 o1 = c.oprrr(p, AADD, int(p.Scond)) 1623 o1 |= uint32(immrot(uint32(c.instoffset))) 1624 o1 |= (uint32(p.To.Reg) & 15) << 16 1625 o1 |= (REGPC & 15) << 12 1626 1627 case 7: /* bl (R) -> blx R */ 1628 c.aclass(&p.To) 1629 1630 if c.instoffset != 0 { 1631 c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset) 1632 } 1633 o1 = c.oprrr(p, ABL, int(p.Scond)) 1634 o1 |= (uint32(p.To.Reg) & 15) << 0 1635 rel := obj.Addrel(c.cursym) 1636 rel.Off = int32(c.pc) 1637 rel.Siz = 0 1638 rel.Type = objabi.R_CALLIND 1639 1640 case 8: /* sll $c,[R],R -> mov (R<<$c),R */ 1641 c.aclass(&p.From) 1642 1643 o1 = c.oprrr(p, p.As, int(p.Scond)) 1644 r := int(p.Reg) 1645 if r == 0 { 1646 r = int(p.To.Reg) 1647 } 1648 o1 |= (uint32(r) & 15) << 0 1649 o1 |= uint32((c.instoffset & 31) << 7) 1650 o1 |= (uint32(p.To.Reg) & 15) << 12 1651 1652 case 9: /* sll R,[R],R -> mov (R<<R),R */ 1653 o1 = c.oprrr(p, p.As, int(p.Scond)) 1654 1655 r := int(p.Reg) 1656 if r == 0 { 1657 r = int(p.To.Reg) 1658 } 1659 o1 |= (uint32(r) & 15) << 0 1660 o1 |= (uint32(p.From.Reg)&15)<<8 | 1<<4 1661 o1 |= (uint32(p.To.Reg) & 15) << 12 1662 1663 case 10: /* swi [$con] */ 1664 o1 = c.oprrr(p, p.As, int(p.Scond)) 1665 1666 if p.To.Type != obj.TYPE_NONE { 1667 c.aclass(&p.To) 1668 o1 |= uint32(c.instoffset & 0xffffff) 1669 } 1670 1671 case 11: /* word */ 1672 c.aclass(&p.To) 1673 1674 o1 = uint32(c.instoffset) 1675 if p.To.Sym != nil { 1676 // This case happens with words generated 1677 // in the PC stream as part of the literal pool (c.pool). 1678 rel := obj.Addrel(c.cursym) 1679 1680 rel.Off = int32(c.pc) 1681 rel.Siz = 4 1682 rel.Sym = p.To.Sym 1683 rel.Add = p.To.Offset 1684 1685 if c.ctxt.Flag_shared { 1686 if p.To.Name == obj.NAME_GOTREF { 1687 rel.Type = objabi.R_GOTPCREL 1688 } else { 1689 rel.Type = objabi.R_PCREL 1690 } 1691 rel.Add += c.pc - p.Rel.Pc - 8 1692 } else { 1693 rel.Type = objabi.R_ADDR 1694 } 1695 o1 = 0 1696 } 1697 1698 case 12: /* movw $lcon, reg */ 1699 if o.a1 == C_SCON { 1700 o1 = c.omvs(p, &p.From, int(p.To.Reg)) 1701 } else if p.As == AMVN { 1702 o1 = c.omvr(p, &p.From, int(p.To.Reg)) 1703 } else { 1704 o1 = c.omvl(p, &p.From, int(p.To.Reg)) 1705 } 1706 1707 if o.flag&LPCREL != 0 { 1708 o2 = c.oprrr(p, AADD, int(p.Scond)) | (uint32(p.To.Reg)&15)<<0 | (REGPC&15)<<16 | (uint32(p.To.Reg)&15)<<12 1709 } 1710 1711 case 13: /* op $lcon, [R], R */ 1712 if o.a1 == C_SCON { 1713 o1 = c.omvs(p, &p.From, REGTMP) 1714 } else { 1715 o1 = c.omvl(p, &p.From, REGTMP) 1716 } 1717 1718 if o1 == 0 { 1719 break 1720 } 1721 o2 = c.oprrr(p, p.As, int(p.Scond)) 1722 o2 |= REGTMP & 15 1723 r := int(p.Reg) 1724 if p.As == AMVN { 1725 r = 0 1726 } else if r == 0 { 1727 r = int(p.To.Reg) 1728 } 1729 o2 |= (uint32(r) & 15) << 16 1730 if p.To.Type != obj.TYPE_NONE { 1731 o2 |= (uint32(p.To.Reg) & 15) << 12 1732 } 1733 1734 case 14: /* movb/movbu/movh/movhu R,R */ 1735 o1 = c.oprrr(p, ASLL, int(p.Scond)) 1736 1737 if p.As == AMOVBU || p.As == AMOVHU { 1738 o2 = c.oprrr(p, ASRL, int(p.Scond)) 1739 } else { 1740 o2 = c.oprrr(p, ASRA, int(p.Scond)) 1741 } 1742 1743 r := int(p.To.Reg) 1744 o1 |= (uint32(p.From.Reg)&15)<<0 | (uint32(r)&15)<<12 1745 o2 |= uint32(r)&15 | (uint32(r)&15)<<12 1746 if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU { 1747 o1 |= 24 << 7 1748 o2 |= 24 << 7 1749 } else { 1750 o1 |= 16 << 7 1751 o2 |= 16 << 7 1752 } 1753 1754 case 15: /* mul r,[r,]r */ 1755 o1 = c.oprrr(p, p.As, int(p.Scond)) 1756 1757 rf := int(p.From.Reg) 1758 rt := int(p.To.Reg) 1759 r := int(p.Reg) 1760 if r == 0 { 1761 r = rt 1762 } 1763 1764 o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 1765 1766 case 16: /* div r,[r,]r */ 1767 o1 = 0xf << 28 1768 1769 o2 = 0 1770 1771 case 17: 1772 o1 = c.oprrr(p, p.As, int(p.Scond)) 1773 rf := int(p.From.Reg) 1774 rt := int(p.To.Reg) 1775 rt2 := int(p.To.Offset) 1776 r := int(p.Reg) 1777 o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12 1778 1779 case 18: /* BFX/BFXU/BFC/BFI */ 1780 o1 = c.oprrr(p, p.As, int(p.Scond)) 1781 rt := int(p.To.Reg) 1782 r := int(p.Reg) 1783 if r == 0 { 1784 r = rt 1785 } else if p.As == ABFC { // only "BFC $width, $lsb, Reg" is accepted, p.Reg must be 0 1786 c.ctxt.Diag("illegal combination: %v", p) 1787 } 1788 if p.GetFrom3() == nil || p.GetFrom3().Type != obj.TYPE_CONST { 1789 c.ctxt.Diag("%v: missing or wrong LSB", p) 1790 break 1791 } 1792 lsb := p.GetFrom3().Offset 1793 width := p.From.Offset 1794 if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 32 { 1795 c.ctxt.Diag("%v: wrong width or LSB", p) 1796 } 1797 switch p.As { 1798 case ABFX, ABFXU: // (width-1) is encoded 1799 o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16 1800 case ABFC, ABFI: // MSB is encoded 1801 o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(lsb+width-1)<<16 1802 default: 1803 c.ctxt.Diag("illegal combination: %v", p) 1804 } 1805 1806 case 20: /* mov/movb/movbu R,O(R) */ 1807 c.aclass(&p.To) 1808 1809 r := int(p.To.Reg) 1810 if r == 0 { 1811 r = int(o.param) 1812 } 1813 o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond)) 1814 1815 case 21: /* mov/movbu O(R),R -> lr */ 1816 c.aclass(&p.From) 1817 1818 r := int(p.From.Reg) 1819 if r == 0 { 1820 r = int(o.param) 1821 } 1822 o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond)) 1823 if p.As != AMOVW { 1824 o1 |= 1 << 22 1825 } 1826 1827 case 22: /* XTAB R@>i, [R], R */ 1828 o1 = c.oprrr(p, p.As, int(p.Scond)) 1829 switch p.From.Offset &^ 0xf { 1830 // only 0/8/16/24 bits rotation is accepted 1831 case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7: 1832 o1 |= uint32(p.From.Offset) & 0xc0f 1833 default: 1834 c.ctxt.Diag("illegal shift: %v", p) 1835 } 1836 rt := p.To.Reg 1837 r := p.Reg 1838 if r == 0 { 1839 r = rt 1840 } 1841 o1 |= (uint32(rt)&15)<<12 | (uint32(r)&15)<<16 1842 1843 case 23: /* MOVW/MOVB/MOVH R@>i, R */ 1844 switch p.As { 1845 case AMOVW: 1846 o1 = c.mov(p) 1847 case AMOVBU, AMOVBS, AMOVB, AMOVHU, AMOVHS, AMOVH: 1848 o1 = c.movxt(p) 1849 default: 1850 c.ctxt.Diag("illegal combination: %v", p) 1851 } 1852 1853 case 30: /* mov/movb/movbu R,L(R) */ 1854 o1 = c.omvl(p, &p.To, REGTMP) 1855 1856 if o1 == 0 { 1857 break 1858 } 1859 r := int(p.To.Reg) 1860 if r == 0 { 1861 r = int(o.param) 1862 } 1863 o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond)) 1864 if p.As != AMOVW { 1865 o2 |= 1 << 22 1866 } 1867 1868 case 31: /* mov/movbu L(R),R -> lr[b] */ 1869 o1 = c.omvl(p, &p.From, REGTMP) 1870 1871 if o1 == 0 { 1872 break 1873 } 1874 r := int(p.From.Reg) 1875 if r == 0 { 1876 r = int(o.param) 1877 } 1878 o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond)) 1879 if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB { 1880 o2 |= 1 << 22 1881 } 1882 1883 case 34: /* mov $lacon,R */ 1884 o1 = c.omvl(p, &p.From, REGTMP) 1885 1886 if o1 == 0 { 1887 break 1888 } 1889 1890 o2 = c.oprrr(p, AADD, int(p.Scond)) 1891 o2 |= REGTMP & 15 1892 r := int(p.From.Reg) 1893 if r == 0 { 1894 r = int(o.param) 1895 } 1896 o2 |= (uint32(r) & 15) << 16 1897 if p.To.Type != obj.TYPE_NONE { 1898 o2 |= (uint32(p.To.Reg) & 15) << 12 1899 } 1900 1901 case 35: /* mov PSR,R */ 1902 o1 = 2<<23 | 0xf<<16 | 0<<0 1903 1904 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 1905 o1 |= (uint32(p.From.Reg) & 1) << 22 1906 o1 |= (uint32(p.To.Reg) & 15) << 12 1907 1908 case 36: /* mov R,PSR */ 1909 o1 = 2<<23 | 0x2cf<<12 | 0<<4 1910 1911 if p.Scond&C_FBIT != 0 { 1912 o1 ^= 0x010 << 12 1913 } 1914 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 1915 o1 |= (uint32(p.To.Reg) & 1) << 22 1916 o1 |= (uint32(p.From.Reg) & 15) << 0 1917 1918 case 37: /* mov $con,PSR */ 1919 c.aclass(&p.From) 1920 1921 o1 = 2<<23 | 0x2cf<<12 | 0<<4 1922 if p.Scond&C_FBIT != 0 { 1923 o1 ^= 0x010 << 12 1924 } 1925 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 1926 o1 |= uint32(immrot(uint32(c.instoffset))) 1927 o1 |= (uint32(p.To.Reg) & 1) << 22 1928 o1 |= (uint32(p.From.Reg) & 15) << 0 1929 1930 case 38, 39: 1931 switch o.type_ { 1932 case 38: /* movm $con,oreg -> stm */ 1933 o1 = 0x4 << 25 1934 1935 o1 |= uint32(p.From.Offset & 0xffff) 1936 o1 |= (uint32(p.To.Reg) & 15) << 16 1937 c.aclass(&p.To) 1938 1939 case 39: /* movm oreg,$con -> ldm */ 1940 o1 = 0x4<<25 | 1<<20 1941 1942 o1 |= uint32(p.To.Offset & 0xffff) 1943 o1 |= (uint32(p.From.Reg) & 15) << 16 1944 c.aclass(&p.From) 1945 } 1946 1947 if c.instoffset != 0 { 1948 c.ctxt.Diag("offset must be zero in MOVM; %v", p) 1949 } 1950 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 1951 if p.Scond&C_PBIT != 0 { 1952 o1 |= 1 << 24 1953 } 1954 if p.Scond&C_UBIT != 0 { 1955 o1 |= 1 << 23 1956 } 1957 if p.Scond&C_WBIT != 0 { 1958 o1 |= 1 << 21 1959 } 1960 1961 case 40: /* swp oreg,reg,reg */ 1962 c.aclass(&p.From) 1963 1964 if c.instoffset != 0 { 1965 c.ctxt.Diag("offset must be zero in SWP") 1966 } 1967 o1 = 0x2<<23 | 0x9<<4 1968 if p.As != ASWPW { 1969 o1 |= 1 << 22 1970 } 1971 o1 |= (uint32(p.From.Reg) & 15) << 16 1972 o1 |= (uint32(p.Reg) & 15) << 0 1973 o1 |= (uint32(p.To.Reg) & 15) << 12 1974 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 1975 1976 case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */ 1977 o1 = 0xe8fd8000 1978 1979 case 50: /* floating point store */ 1980 v := c.regoff(&p.To) 1981 1982 r := int(p.To.Reg) 1983 if r == 0 { 1984 r = int(o.param) 1985 } 1986 o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p) 1987 1988 case 51: /* floating point load */ 1989 v := c.regoff(&p.From) 1990 1991 r := int(p.From.Reg) 1992 if r == 0 { 1993 r = int(o.param) 1994 } 1995 o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20 1996 1997 case 52: /* floating point store, int32 offset UGLY */ 1998 o1 = c.omvl(p, &p.To, REGTMP) 1999 2000 if o1 == 0 { 2001 break 2002 } 2003 r := int(p.To.Reg) 2004 if r == 0 { 2005 r = int(o.param) 2006 } 2007 o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 2008 o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) 2009 2010 case 53: /* floating point load, int32 offset UGLY */ 2011 o1 = c.omvl(p, &p.From, REGTMP) 2012 2013 if o1 == 0 { 2014 break 2015 } 2016 r := int(p.From.Reg) 2017 if r == 0 { 2018 r = int(o.param) 2019 } 2020 o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 2021 o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 2022 2023 case 54: /* floating point arith */ 2024 o1 = c.oprrr(p, p.As, int(p.Scond)) 2025 2026 rf := int(p.From.Reg) 2027 rt := int(p.To.Reg) 2028 r := int(p.Reg) 2029 if r == 0 { 2030 switch p.As { 2031 case AMULAD, AMULAF, AMULSF, AMULSD, ANMULAF, ANMULAD, ANMULSF, ANMULSD, 2032 AFMULAD, AFMULAF, AFMULSF, AFMULSD, AFNMULAF, AFNMULAD, AFNMULSF, AFNMULSD: 2033 c.ctxt.Diag("illegal combination: %v", p) 2034 default: 2035 r = rt 2036 } 2037 } 2038 2039 o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 2040 2041 case 55: /* negf freg, freg */ 2042 o1 = c.oprrr(p, p.As, int(p.Scond)) 2043 2044 rf := int(p.From.Reg) 2045 rt := int(p.To.Reg) 2046 2047 o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12 2048 2049 case 56: /* move to FP[CS]R */ 2050 o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xee1<<16 | 0xa1<<4 2051 2052 o1 |= (uint32(p.From.Reg) & 15) << 12 2053 2054 case 57: /* move from FP[CS]R */ 2055 o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xef1<<16 | 0xa1<<4 2056 2057 o1 |= (uint32(p.To.Reg) & 15) << 12 2058 2059 case 58: /* movbu R,R */ 2060 o1 = c.oprrr(p, AAND, int(p.Scond)) 2061 2062 o1 |= uint32(immrot(0xff)) 2063 rt := int(p.To.Reg) 2064 r := int(p.From.Reg) 2065 if p.To.Type == obj.TYPE_NONE { 2066 rt = 0 2067 } 2068 if r == 0 { 2069 r = rt 2070 } 2071 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 2072 2073 case 59: /* movw/bu R<<I(R),R -> ldr indexed */ 2074 if p.From.Reg == 0 { 2075 c.ctxt.Diag("source operand is not a memory address: %v", p) 2076 break 2077 } 2078 if p.From.Offset&(1<<4) != 0 { 2079 c.ctxt.Diag("bad shift in LDR") 2080 break 2081 } 2082 o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) 2083 if p.As == AMOVBU { 2084 o1 |= 1 << 22 2085 } 2086 2087 case 60: /* movb R(R),R -> ldrsb indexed */ 2088 if p.From.Reg == 0 { 2089 c.ctxt.Diag("source operand is not a memory address: %v", p) 2090 break 2091 } 2092 if p.From.Offset&(^0xf) != 0 { 2093 c.ctxt.Diag("bad shift: %v", p) 2094 break 2095 } 2096 o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) 2097 switch p.As { 2098 case AMOVB, AMOVBS: 2099 o1 ^= 1<<5 | 1<<6 2100 case AMOVH, AMOVHS: 2101 o1 ^= 1 << 6 2102 default: 2103 } 2104 if p.Scond&C_UBIT != 0 { 2105 o1 &^= 1 << 23 2106 } 2107 2108 case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */ 2109 if p.To.Reg == 0 { 2110 c.ctxt.Diag("MOV to shifter operand") 2111 } 2112 o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond)) 2113 if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU { 2114 o1 |= 1 << 22 2115 } 2116 2117 case 62: /* MOVH/MOVHS/MOVHU Reg, Reg<<0(Reg) -> strh */ 2118 if p.To.Reg == 0 { 2119 c.ctxt.Diag("MOV to shifter operand") 2120 } 2121 if p.To.Offset&(^0xf) != 0 { 2122 c.ctxt.Diag("bad shift: %v", p) 2123 } 2124 o1 = c.olhrr(int(p.To.Offset), int(p.To.Reg), int(p.From.Reg), int(p.Scond)) 2125 o1 ^= 1 << 20 2126 if p.Scond&C_UBIT != 0 { 2127 o1 &^= 1 << 23 2128 } 2129 2130 /* reloc ops */ 2131 case 64: /* mov/movb/movbu R,addr */ 2132 o1 = c.omvl(p, &p.To, REGTMP) 2133 2134 if o1 == 0 { 2135 break 2136 } 2137 o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond)) 2138 if o.flag&LPCREL != 0 { 2139 o3 = o2 2140 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2141 } 2142 2143 case 65: /* mov/movbu addr,R */ 2144 o1 = c.omvl(p, &p.From, REGTMP) 2145 2146 if o1 == 0 { 2147 break 2148 } 2149 o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond)) 2150 if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB { 2151 o2 |= 1 << 22 2152 } 2153 if o.flag&LPCREL != 0 { 2154 o3 = o2 2155 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2156 } 2157 2158 case 101: /* movw tlsvar,R, local exec*/ 2159 o1 = c.omvl(p, &p.From, int(p.To.Reg)) 2160 2161 case 102: /* movw tlsvar,R, initial exec*/ 2162 o1 = c.omvl(p, &p.From, int(p.To.Reg)) 2163 o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond)) 2164 2165 case 103: /* word tlsvar, local exec */ 2166 if p.To.Sym == nil { 2167 c.ctxt.Diag("nil sym in tls %v", p) 2168 } 2169 if p.To.Offset != 0 { 2170 c.ctxt.Diag("offset against tls var in %v", p) 2171 } 2172 // This case happens with words generated in the PC stream as part of 2173 // the literal c.pool. 2174 rel := obj.Addrel(c.cursym) 2175 2176 rel.Off = int32(c.pc) 2177 rel.Siz = 4 2178 rel.Sym = p.To.Sym 2179 rel.Type = objabi.R_TLS_LE 2180 o1 = 0 2181 2182 case 104: /* word tlsvar, initial exec */ 2183 if p.To.Sym == nil { 2184 c.ctxt.Diag("nil sym in tls %v", p) 2185 } 2186 if p.To.Offset != 0 { 2187 c.ctxt.Diag("offset against tls var in %v", p) 2188 } 2189 rel := obj.Addrel(c.cursym) 2190 rel.Off = int32(c.pc) 2191 rel.Siz = 4 2192 rel.Sym = p.To.Sym 2193 rel.Type = objabi.R_TLS_IE 2194 rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz) 2195 2196 case 68: /* floating point store -> ADDR */ 2197 o1 = c.omvl(p, &p.To, REGTMP) 2198 2199 if o1 == 0 { 2200 break 2201 } 2202 o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) 2203 if o.flag&LPCREL != 0 { 2204 o3 = o2 2205 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2206 } 2207 2208 case 69: /* floating point load <- ADDR */ 2209 o1 = c.omvl(p, &p.From, REGTMP) 2210 2211 if o1 == 0 { 2212 break 2213 } 2214 o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 2215 if o.flag&LPCREL != 0 { 2216 o3 = o2 2217 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2218 } 2219 2220 /* ArmV4 ops: */ 2221 case 70: /* movh/movhu R,O(R) -> strh */ 2222 c.aclass(&p.To) 2223 2224 r := int(p.To.Reg) 2225 if r == 0 { 2226 r = int(o.param) 2227 } 2228 o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond)) 2229 2230 case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */ 2231 c.aclass(&p.From) 2232 2233 r := int(p.From.Reg) 2234 if r == 0 { 2235 r = int(o.param) 2236 } 2237 o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond)) 2238 if p.As == AMOVB || p.As == AMOVBS { 2239 o1 ^= 1<<5 | 1<<6 2240 } else if p.As == AMOVH || p.As == AMOVHS { 2241 o1 ^= (1 << 6) 2242 } 2243 2244 case 72: /* movh/movhu R,L(R) -> strh */ 2245 o1 = c.omvl(p, &p.To, REGTMP) 2246 2247 if o1 == 0 { 2248 break 2249 } 2250 r := int(p.To.Reg) 2251 if r == 0 { 2252 r = int(o.param) 2253 } 2254 o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond)) 2255 2256 case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */ 2257 o1 = c.omvl(p, &p.From, REGTMP) 2258 2259 if o1 == 0 { 2260 break 2261 } 2262 r := int(p.From.Reg) 2263 if r == 0 { 2264 r = int(o.param) 2265 } 2266 o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond)) 2267 if p.As == AMOVB || p.As == AMOVBS { 2268 o2 ^= 1<<5 | 1<<6 2269 } else if p.As == AMOVH || p.As == AMOVHS { 2270 o2 ^= (1 << 6) 2271 } 2272 2273 case 74: /* bx $I */ 2274 c.ctxt.Diag("ABX $I") 2275 2276 case 75: /* bx O(R) */ 2277 c.aclass(&p.To) 2278 2279 if c.instoffset != 0 { 2280 c.ctxt.Diag("non-zero offset in ABX") 2281 } 2282 2283 /* 2284 o1 = c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR 2285 o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0); // BX R 2286 */ 2287 // p->to.reg may be REGLINK 2288 o1 = c.oprrr(p, AADD, int(p.Scond)) 2289 2290 o1 |= uint32(immrot(uint32(c.instoffset))) 2291 o1 |= (uint32(p.To.Reg) & 15) << 16 2292 o1 |= (REGTMP & 15) << 12 2293 o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR 2294 o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15 // BX Rtmp 2295 2296 case 76: /* bx O(R) when returning from fn*/ 2297 c.ctxt.Diag("ABXRET") 2298 2299 case 77: /* ldrex oreg,reg */ 2300 c.aclass(&p.From) 2301 2302 if c.instoffset != 0 { 2303 c.ctxt.Diag("offset must be zero in LDREX") 2304 } 2305 o1 = 0x19<<20 | 0xf9f 2306 o1 |= (uint32(p.From.Reg) & 15) << 16 2307 o1 |= (uint32(p.To.Reg) & 15) << 12 2308 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2309 2310 case 78: /* strex reg,oreg,reg */ 2311 c.aclass(&p.From) 2312 2313 if c.instoffset != 0 { 2314 c.ctxt.Diag("offset must be zero in STREX") 2315 } 2316 if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg { 2317 c.ctxt.Diag("cannot use same register as both source and destination: %v", p) 2318 } 2319 o1 = 0x18<<20 | 0xf90 2320 o1 |= (uint32(p.From.Reg) & 15) << 16 2321 o1 |= (uint32(p.Reg) & 15) << 0 2322 o1 |= (uint32(p.To.Reg) & 15) << 12 2323 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2324 2325 case 80: /* fmov zfcon,freg */ 2326 if p.As == AMOVD { 2327 o1 = 0xeeb00b00 // VMOV imm 64 2328 o2 = c.oprrr(p, ASUBD, int(p.Scond)) 2329 } else { 2330 o1 = 0x0eb00a00 // VMOV imm 32 2331 o2 = c.oprrr(p, ASUBF, int(p.Scond)) 2332 } 2333 2334 v := int32(0x70) // 1.0 2335 r := (int(p.To.Reg) & 15) << 0 2336 2337 // movf $1.0, r 2338 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2339 2340 o1 |= (uint32(r) & 15) << 12 2341 o1 |= (uint32(v) & 0xf) << 0 2342 o1 |= (uint32(v) & 0xf0) << 12 2343 2344 // subf r,r,r 2345 o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12 2346 2347 case 81: /* fmov sfcon,freg */ 2348 o1 = 0x0eb00a00 // VMOV imm 32 2349 if p.As == AMOVD { 2350 o1 = 0xeeb00b00 // VMOV imm 64 2351 } 2352 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2353 o1 |= (uint32(p.To.Reg) & 15) << 12 2354 v := int32(c.chipfloat5(p.From.Val.(float64))) 2355 o1 |= (uint32(v) & 0xf) << 0 2356 o1 |= (uint32(v) & 0xf0) << 12 2357 2358 case 82: /* fcmp freg,freg, */ 2359 o1 = c.oprrr(p, p.As, int(p.Scond)) 2360 2361 o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0 2362 o2 = 0x0ef1fa10 // VMRS R15 2363 o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2364 2365 case 83: /* fcmp freg,, */ 2366 o1 = c.oprrr(p, p.As, int(p.Scond)) 2367 2368 o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16 2369 o2 = 0x0ef1fa10 // VMRS R15 2370 o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2371 2372 case 84: /* movfw freg,freg - truncate float-to-fix */ 2373 o1 = c.oprrr(p, p.As, int(p.Scond)) 2374 2375 o1 |= (uint32(p.From.Reg) & 15) << 0 2376 o1 |= (uint32(p.To.Reg) & 15) << 12 2377 2378 case 85: /* movwf freg,freg - fix-to-float */ 2379 o1 = c.oprrr(p, p.As, int(p.Scond)) 2380 2381 o1 |= (uint32(p.From.Reg) & 15) << 0 2382 o1 |= (uint32(p.To.Reg) & 15) << 12 2383 2384 // macro for movfw freg,FTMP; movw FTMP,reg 2385 case 86: /* movfw freg,reg - truncate float-to-fix */ 2386 o1 = c.oprrr(p, p.As, int(p.Scond)) 2387 2388 o1 |= (uint32(p.From.Reg) & 15) << 0 2389 o1 |= (FREGTMP & 15) << 12 2390 o2 = c.oprrr(p, -AMOVFW, int(p.Scond)) 2391 o2 |= (FREGTMP & 15) << 16 2392 o2 |= (uint32(p.To.Reg) & 15) << 12 2393 2394 // macro for movw reg,FTMP; movwf FTMP,freg 2395 case 87: /* movwf reg,freg - fix-to-float */ 2396 o1 = c.oprrr(p, -AMOVWF, int(p.Scond)) 2397 2398 o1 |= (uint32(p.From.Reg) & 15) << 12 2399 o1 |= (FREGTMP & 15) << 16 2400 o2 = c.oprrr(p, p.As, int(p.Scond)) 2401 o2 |= (FREGTMP & 15) << 0 2402 o2 |= (uint32(p.To.Reg) & 15) << 12 2403 2404 case 88: /* movw reg,freg */ 2405 o1 = c.oprrr(p, -AMOVWF, int(p.Scond)) 2406 2407 o1 |= (uint32(p.From.Reg) & 15) << 12 2408 o1 |= (uint32(p.To.Reg) & 15) << 16 2409 2410 case 89: /* movw freg,reg */ 2411 o1 = c.oprrr(p, -AMOVFW, int(p.Scond)) 2412 2413 o1 |= (uint32(p.From.Reg) & 15) << 16 2414 o1 |= (uint32(p.To.Reg) & 15) << 12 2415 2416 case 91: /* ldrexd oreg,reg */ 2417 c.aclass(&p.From) 2418 2419 if c.instoffset != 0 { 2420 c.ctxt.Diag("offset must be zero in LDREX") 2421 } 2422 o1 = 0x1b<<20 | 0xf9f 2423 o1 |= (uint32(p.From.Reg) & 15) << 16 2424 o1 |= (uint32(p.To.Reg) & 15) << 12 2425 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2426 2427 case 92: /* strexd reg,oreg,reg */ 2428 c.aclass(&p.From) 2429 2430 if c.instoffset != 0 { 2431 c.ctxt.Diag("offset must be zero in STREX") 2432 } 2433 if p.Reg&1 != 0 { 2434 c.ctxt.Diag("source register must be even in STREXD: %v", p) 2435 } 2436 if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg || p.To.Reg == p.Reg+1 { 2437 c.ctxt.Diag("cannot use same register as both source and destination: %v", p) 2438 } 2439 o1 = 0x1a<<20 | 0xf90 2440 o1 |= (uint32(p.From.Reg) & 15) << 16 2441 o1 |= (uint32(p.Reg) & 15) << 0 2442 o1 |= (uint32(p.To.Reg) & 15) << 12 2443 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2444 2445 case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */ 2446 o1 = c.omvl(p, &p.From, REGTMP) 2447 2448 if o1 == 0 { 2449 break 2450 } 2451 o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond)) 2452 if p.As == AMOVB || p.As == AMOVBS { 2453 o2 ^= 1<<5 | 1<<6 2454 } else if p.As == AMOVH || p.As == AMOVHS { 2455 o2 ^= (1 << 6) 2456 } 2457 if o.flag&LPCREL != 0 { 2458 o3 = o2 2459 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2460 } 2461 2462 case 94: /* movh/movhu R,addr -> strh */ 2463 o1 = c.omvl(p, &p.To, REGTMP) 2464 2465 if o1 == 0 { 2466 break 2467 } 2468 o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond)) 2469 if o.flag&LPCREL != 0 { 2470 o3 = o2 2471 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2472 } 2473 2474 case 95: /* PLD off(reg) */ 2475 o1 = 0xf5d0f000 2476 2477 o1 |= (uint32(p.From.Reg) & 15) << 16 2478 if p.From.Offset < 0 { 2479 o1 &^= (1 << 23) 2480 o1 |= uint32((-p.From.Offset) & 0xfff) 2481 } else { 2482 o1 |= uint32(p.From.Offset & 0xfff) 2483 } 2484 2485 // This is supposed to be something that stops execution. 2486 // It's not supposed to be reached, ever, but if it is, we'd 2487 // like to be able to tell how we got there. Assemble as 2488 // 0xf7fabcfd which is guaranteed to raise undefined instruction 2489 // exception. 2490 case 96: /* UNDEF */ 2491 o1 = 0xf7fabcfd 2492 2493 case 97: /* CLZ Rm, Rd */ 2494 o1 = c.oprrr(p, p.As, int(p.Scond)) 2495 2496 o1 |= (uint32(p.To.Reg) & 15) << 12 2497 o1 |= (uint32(p.From.Reg) & 15) << 0 2498 2499 case 98: /* MULW{T,B} Rs, Rm, Rd */ 2500 o1 = c.oprrr(p, p.As, int(p.Scond)) 2501 2502 o1 |= (uint32(p.To.Reg) & 15) << 16 2503 o1 |= (uint32(p.From.Reg) & 15) << 8 2504 o1 |= (uint32(p.Reg) & 15) << 0 2505 2506 case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */ 2507 o1 = c.oprrr(p, p.As, int(p.Scond)) 2508 2509 o1 |= (uint32(p.To.Reg) & 15) << 16 2510 o1 |= (uint32(p.From.Reg) & 15) << 8 2511 o1 |= (uint32(p.Reg) & 15) << 0 2512 o1 |= uint32((p.To.Offset & 15) << 12) 2513 2514 case 105: /* divhw r,[r,]r */ 2515 o1 = c.oprrr(p, p.As, int(p.Scond)) 2516 rf := int(p.From.Reg) 2517 rt := int(p.To.Reg) 2518 r := int(p.Reg) 2519 if r == 0 { 2520 r = rt 2521 } 2522 o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 2523 2524 case 110: /* dmb [mbop | $con] */ 2525 o1 = 0xf57ff050 2526 mbop := uint32(0) 2527 2528 switch c.aclass(&p.From) { 2529 case C_SPR: 2530 for _, f := range mbOp { 2531 if f.reg == p.From.Reg { 2532 mbop = f.enc 2533 break 2534 } 2535 } 2536 case C_RCON: 2537 for _, f := range mbOp { 2538 enc := uint32(c.instoffset) 2539 if f.enc == enc { 2540 mbop = enc 2541 break 2542 } 2543 } 2544 case C_NONE: 2545 mbop = 0xf 2546 } 2547 2548 if mbop == 0 { 2549 c.ctxt.Diag("illegal mb option:\n%v", p) 2550 } 2551 o1 |= mbop 2552 } 2553 2554 out[0] = o1 2555 out[1] = o2 2556 out[2] = o3 2557 out[3] = o4 2558 out[4] = o5 2559 out[5] = o6 2560 } 2561 2562 func (c *ctxt5) movxt(p *obj.Prog) uint32 { 2563 o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2564 switch p.As { 2565 case AMOVB, AMOVBS: 2566 o1 |= 0x6af<<16 | 0x7<<4 2567 case AMOVH, AMOVHS: 2568 o1 |= 0x6bf<<16 | 0x7<<4 2569 case AMOVBU: 2570 o1 |= 0x6ef<<16 | 0x7<<4 2571 case AMOVHU: 2572 o1 |= 0x6ff<<16 | 0x7<<4 2573 default: 2574 c.ctxt.Diag("illegal combination: %v", p) 2575 } 2576 switch p.From.Offset &^ 0xf { 2577 // only 0/8/16/24 bits rotation is accepted 2578 case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7: 2579 o1 |= uint32(p.From.Offset) & 0xc0f 2580 default: 2581 c.ctxt.Diag("illegal shift: %v", p) 2582 } 2583 o1 |= (uint32(p.To.Reg) & 15) << 12 2584 return o1 2585 } 2586 2587 func (c *ctxt5) mov(p *obj.Prog) uint32 { 2588 c.aclass(&p.From) 2589 o1 := c.oprrr(p, p.As, int(p.Scond)) 2590 o1 |= uint32(p.From.Offset) 2591 rt := int(p.To.Reg) 2592 if p.To.Type == obj.TYPE_NONE { 2593 rt = 0 2594 } 2595 r := int(p.Reg) 2596 if p.As == AMOVW || p.As == AMVN { 2597 r = 0 2598 } else if r == 0 { 2599 r = rt 2600 } 2601 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 2602 return o1 2603 } 2604 2605 func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 { 2606 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 2607 if sc&C_SBIT != 0 { 2608 o |= 1 << 20 2609 } 2610 switch a { 2611 case ADIVHW: 2612 return o | 0x71<<20 | 0xf<<12 | 0x1<<4 2613 case ADIVUHW: 2614 return o | 0x73<<20 | 0xf<<12 | 0x1<<4 2615 case AMMUL: 2616 return o | 0x75<<20 | 0xf<<12 | 0x1<<4 2617 case AMULS: 2618 return o | 0x6<<20 | 0x9<<4 2619 case AMMULA: 2620 return o | 0x75<<20 | 0x1<<4 2621 case AMMULS: 2622 return o | 0x75<<20 | 0xd<<4 2623 case AMULU, AMUL: 2624 return o | 0x0<<21 | 0x9<<4 2625 case AMULA: 2626 return o | 0x1<<21 | 0x9<<4 2627 case AMULLU: 2628 return o | 0x4<<21 | 0x9<<4 2629 case AMULL: 2630 return o | 0x6<<21 | 0x9<<4 2631 case AMULALU: 2632 return o | 0x5<<21 | 0x9<<4 2633 case AMULAL: 2634 return o | 0x7<<21 | 0x9<<4 2635 case AAND: 2636 return o | 0x0<<21 2637 case AEOR: 2638 return o | 0x1<<21 2639 case ASUB: 2640 return o | 0x2<<21 2641 case ARSB: 2642 return o | 0x3<<21 2643 case AADD: 2644 return o | 0x4<<21 2645 case AADC: 2646 return o | 0x5<<21 2647 case ASBC: 2648 return o | 0x6<<21 2649 case ARSC: 2650 return o | 0x7<<21 2651 case ATST: 2652 return o | 0x8<<21 | 1<<20 2653 case ATEQ: 2654 return o | 0x9<<21 | 1<<20 2655 case ACMP: 2656 return o | 0xa<<21 | 1<<20 2657 case ACMN: 2658 return o | 0xb<<21 | 1<<20 2659 case AORR: 2660 return o | 0xc<<21 2661 2662 case AMOVB, AMOVH, AMOVW: 2663 if sc&(C_PBIT|C_WBIT) != 0 { 2664 c.ctxt.Diag("invalid .P/.W suffix: %v", p) 2665 } 2666 return o | 0xd<<21 2667 case ABIC: 2668 return o | 0xe<<21 2669 case AMVN: 2670 return o | 0xf<<21 2671 case ASLL: 2672 return o | 0xd<<21 | 0<<5 2673 case ASRL: 2674 return o | 0xd<<21 | 1<<5 2675 case ASRA: 2676 return o | 0xd<<21 | 2<<5 2677 case ASWI: 2678 return o | 0xf<<24 2679 2680 case AADDD: 2681 return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4 2682 case AADDF: 2683 return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4 2684 case ASUBD: 2685 return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4 2686 case ASUBF: 2687 return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4 2688 case AMULD: 2689 return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4 2690 case AMULF: 2691 return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4 2692 case ANMULD: 2693 return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0x4<<4 2694 case ANMULF: 2695 return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0x4<<4 2696 case AMULAD: 2697 return o | 0xe<<24 | 0xb<<8 2698 case AMULAF: 2699 return o | 0xe<<24 | 0xa<<8 2700 case AMULSD: 2701 return o | 0xe<<24 | 0xb<<8 | 0x4<<4 2702 case AMULSF: 2703 return o | 0xe<<24 | 0xa<<8 | 0x4<<4 2704 case ANMULAD: 2705 return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 0x4<<4 2706 case ANMULAF: 2707 return o | 0xe<<24 | 0x1<<20 | 0xa<<8 | 0x4<<4 2708 case ANMULSD: 2709 return o | 0xe<<24 | 0x1<<20 | 0xb<<8 2710 case ANMULSF: 2711 return o | 0xe<<24 | 0x1<<20 | 0xa<<8 2712 case AFMULAD: 2713 return o | 0xe<<24 | 0xa<<20 | 0xb<<8 2714 case AFMULAF: 2715 return o | 0xe<<24 | 0xa<<20 | 0xa<<8 2716 case AFMULSD: 2717 return o | 0xe<<24 | 0xa<<20 | 0xb<<8 | 0x4<<4 2718 case AFMULSF: 2719 return o | 0xe<<24 | 0xa<<20 | 0xa<<8 | 0x4<<4 2720 case AFNMULAD: 2721 return o | 0xe<<24 | 0x9<<20 | 0xb<<8 | 0x4<<4 2722 case AFNMULAF: 2723 return o | 0xe<<24 | 0x9<<20 | 0xa<<8 | 0x4<<4 2724 case AFNMULSD: 2725 return o | 0xe<<24 | 0x9<<20 | 0xb<<8 2726 case AFNMULSF: 2727 return o | 0xe<<24 | 0x9<<20 | 0xa<<8 2728 case ADIVD: 2729 return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4 2730 case ADIVF: 2731 return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4 2732 case ASQRTD: 2733 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4 2734 case ASQRTF: 2735 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4 2736 case AABSD: 2737 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4 2738 case AABSF: 2739 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4 2740 case ANEGD: 2741 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4 2742 case ANEGF: 2743 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4 2744 case ACMPD: 2745 return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4 2746 case ACMPF: 2747 return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4 2748 2749 case AMOVF: 2750 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4 2751 case AMOVD: 2752 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4 2753 2754 case AMOVDF: 2755 return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof 2756 case AMOVFD: 2757 return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof 2758 2759 case AMOVWF: 2760 if sc&C_UBIT == 0 { 2761 o |= 1 << 7 /* signed */ 2762 } 2763 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double 2764 2765 case AMOVWD: 2766 if sc&C_UBIT == 0 { 2767 o |= 1 << 7 /* signed */ 2768 } 2769 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double 2770 2771 case AMOVFW: 2772 if sc&C_UBIT == 0 { 2773 o |= 1 << 16 /* signed */ 2774 } 2775 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc 2776 2777 case AMOVDW: 2778 if sc&C_UBIT == 0 { 2779 o |= 1 << 16 /* signed */ 2780 } 2781 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc 2782 2783 case -AMOVWF: // copy WtoF 2784 return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4 2785 2786 case -AMOVFW: // copy FtoW 2787 return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4 2788 2789 case -ACMP: // cmp imm 2790 return o | 0x3<<24 | 0x5<<20 2791 2792 case ABFX: 2793 return o | 0x3d<<21 | 0x5<<4 2794 2795 case ABFXU: 2796 return o | 0x3f<<21 | 0x5<<4 2797 2798 case ABFC: 2799 return o | 0x3e<<21 | 0x1f 2800 2801 case ABFI: 2802 return o | 0x3e<<21 | 0x1<<4 2803 2804 case AXTAB: 2805 return o | 0x6a<<20 | 0x7<<4 2806 2807 case AXTAH: 2808 return o | 0x6b<<20 | 0x7<<4 2809 2810 case AXTABU: 2811 return o | 0x6e<<20 | 0x7<<4 2812 2813 case AXTAHU: 2814 return o | 0x6f<<20 | 0x7<<4 2815 2816 // CLZ doesn't support .nil 2817 case ACLZ: 2818 return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4 2819 2820 case AREV: 2821 return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4 2822 2823 case AREV16: 2824 return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4 2825 2826 case AREVSH: 2827 return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4 2828 2829 case ARBIT: 2830 return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4 2831 2832 case AMULWT: 2833 return o&(0xf<<28) | 0x12<<20 | 0xe<<4 2834 2835 case AMULWB: 2836 return o&(0xf<<28) | 0x12<<20 | 0xa<<4 2837 2838 case AMULBB: 2839 return o&(0xf<<28) | 0x16<<20 | 0x8<<4 2840 2841 case AMULAWT: 2842 return o&(0xf<<28) | 0x12<<20 | 0xc<<4 2843 2844 case AMULAWB: 2845 return o&(0xf<<28) | 0x12<<20 | 0x8<<4 2846 2847 case AMULABB: 2848 return o&(0xf<<28) | 0x10<<20 | 0x8<<4 2849 2850 case ABL: // BLX REG 2851 return o&(0xf<<28) | 0x12fff3<<4 2852 } 2853 2854 c.ctxt.Diag("%v: bad rrr %d", p, a) 2855 return 0 2856 } 2857 2858 func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 { 2859 sc &= C_SCOND 2860 sc ^= C_SCOND_XOR 2861 if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY { 2862 return uint32(sc)<<28 | 0x5<<25 | 0x1<<24 2863 } 2864 if sc != 0xe { 2865 c.ctxt.Diag("%v: .COND on bcond instruction", p) 2866 } 2867 switch a { 2868 case ABEQ: 2869 return 0x0<<28 | 0x5<<25 2870 case ABNE: 2871 return 0x1<<28 | 0x5<<25 2872 case ABCS: 2873 return 0x2<<28 | 0x5<<25 2874 case ABHS: 2875 return 0x2<<28 | 0x5<<25 2876 case ABCC: 2877 return 0x3<<28 | 0x5<<25 2878 case ABLO: 2879 return 0x3<<28 | 0x5<<25 2880 case ABMI: 2881 return 0x4<<28 | 0x5<<25 2882 case ABPL: 2883 return 0x5<<28 | 0x5<<25 2884 case ABVS: 2885 return 0x6<<28 | 0x5<<25 2886 case ABVC: 2887 return 0x7<<28 | 0x5<<25 2888 case ABHI: 2889 return 0x8<<28 | 0x5<<25 2890 case ABLS: 2891 return 0x9<<28 | 0x5<<25 2892 case ABGE: 2893 return 0xa<<28 | 0x5<<25 2894 case ABLT: 2895 return 0xb<<28 | 0x5<<25 2896 case ABGT: 2897 return 0xc<<28 | 0x5<<25 2898 case ABLE: 2899 return 0xd<<28 | 0x5<<25 2900 case AB: 2901 return 0xe<<28 | 0x5<<25 2902 } 2903 2904 c.ctxt.Diag("%v: bad bra %v", p, a) 2905 return 0 2906 } 2907 2908 func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 { 2909 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 2910 if sc&C_PBIT == 0 { 2911 o |= 1 << 24 2912 } 2913 if sc&C_UBIT == 0 { 2914 o |= 1 << 23 2915 } 2916 if sc&C_WBIT != 0 { 2917 o |= 1 << 21 2918 } 2919 o |= 1<<26 | 1<<20 2920 if v < 0 { 2921 if sc&C_UBIT != 0 { 2922 c.ctxt.Diag(".U on neg offset") 2923 } 2924 v = -v 2925 o ^= 1 << 23 2926 } 2927 2928 if v >= 1<<12 || v < 0 { 2929 c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp) 2930 } 2931 o |= uint32(v) 2932 o |= (uint32(b) & 15) << 16 2933 o |= (uint32(r) & 15) << 12 2934 return o 2935 } 2936 2937 func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 { 2938 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 2939 if sc&C_PBIT == 0 { 2940 o |= 1 << 24 2941 } 2942 if sc&C_WBIT != 0 { 2943 o |= 1 << 21 2944 } 2945 o |= 1<<23 | 1<<20 | 0xb<<4 2946 if v < 0 { 2947 v = -v 2948 o ^= 1 << 23 2949 } 2950 2951 if v >= 1<<8 || v < 0 { 2952 c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp) 2953 } 2954 o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22 2955 o |= (uint32(b) & 15) << 16 2956 o |= (uint32(r) & 15) << 12 2957 return o 2958 } 2959 2960 func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 { 2961 o := c.olr(v, b, r, sc) ^ (1 << 20) 2962 if a != AMOVW { 2963 o |= 1 << 22 2964 } 2965 return o 2966 } 2967 2968 func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 { 2969 o := c.olhr(v, b, r, sc) ^ (1 << 20) 2970 return o 2971 } 2972 2973 func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 { 2974 return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20) 2975 } 2976 2977 func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 { 2978 return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20) 2979 } 2980 2981 func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 { 2982 return c.olr(int32(i), b, r, sc) ^ (1 << 25) 2983 } 2984 2985 func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 { 2986 return c.olhr(int32(i), b, r, sc) ^ (1 << 22) 2987 } 2988 2989 func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 { 2990 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 2991 if sc&C_PBIT == 0 { 2992 o |= 1 << 24 2993 } 2994 if sc&C_WBIT != 0 { 2995 o |= 1 << 21 2996 } 2997 o |= 6<<25 | 1<<24 | 1<<23 | 10<<8 2998 if v < 0 { 2999 v = -v 3000 o ^= 1 << 23 3001 } 3002 3003 if v&3 != 0 { 3004 c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p) 3005 } else if v >= 1<<10 || v < 0 { 3006 c.ctxt.Diag("literal span too large: %d\n%v", v, p) 3007 } 3008 o |= (uint32(v) >> 2) & 0xFF 3009 o |= (uint32(b) & 15) << 16 3010 o |= (uint32(r) & 15) << 12 3011 3012 switch a { 3013 default: 3014 c.ctxt.Diag("bad fst %v", a) 3015 fallthrough 3016 3017 case AMOVD: 3018 o |= 1 << 8 3019 fallthrough 3020 3021 case AMOVF: 3022 break 3023 } 3024 3025 return o 3026 } 3027 3028 // MOVW $"lower 16-bit", Reg 3029 func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 { 3030 o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 3031 o1 |= 0x30 << 20 3032 o1 |= (uint32(dr) & 15) << 12 3033 o1 |= uint32(a.Offset) & 0x0fff 3034 o1 |= (uint32(a.Offset) & 0xf000) << 4 3035 return o1 3036 } 3037 3038 // MVN $C_NCON, Reg -> MOVW $C_RCON, Reg 3039 func (c *ctxt5) omvr(p *obj.Prog, a *obj.Addr, dr int) uint32 { 3040 o1 := c.oprrr(p, AMOVW, int(p.Scond)) 3041 o1 |= (uint32(dr) & 15) << 12 3042 v := immrot(^uint32(a.Offset)) 3043 if v == 0 { 3044 c.ctxt.Diag("%v: missing literal", p) 3045 return 0 3046 } 3047 o1 |= uint32(v) 3048 return o1 3049 } 3050 3051 func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 { 3052 var o1 uint32 3053 if p.Pool == nil { 3054 c.aclass(a) 3055 v := immrot(^uint32(c.instoffset)) 3056 if v == 0 { 3057 c.ctxt.Diag("%v: missing literal", p) 3058 return 0 3059 } 3060 3061 o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND) 3062 o1 |= uint32(v) 3063 o1 |= (uint32(dr) & 15) << 12 3064 } else { 3065 v := int32(p.Pool.Pc - p.Pc - 8) 3066 o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND) 3067 } 3068 3069 return o1 3070 } 3071 3072 func (c *ctxt5) chipzero5(e float64) int { 3073 // We use GOARM.Version=7 and !GOARM.SoftFloat to gate the use of VFPv3 vmov (imm) instructions. 3074 if buildcfg.GOARM.Version < 7 || buildcfg.GOARM.SoftFloat || math.Float64bits(e) != 0 { 3075 return -1 3076 } 3077 return 0 3078 } 3079 3080 func (c *ctxt5) chipfloat5(e float64) int { 3081 // We use GOARM.Version=7 and !GOARM.SoftFloat to gate the use of VFPv3 vmov (imm) instructions. 3082 if buildcfg.GOARM.Version < 7 || buildcfg.GOARM.SoftFloat { 3083 return -1 3084 } 3085 3086 ei := math.Float64bits(e) 3087 l := uint32(ei) 3088 h := uint32(ei >> 32) 3089 3090 if l != 0 || h&0xffff != 0 { 3091 return -1 3092 } 3093 h1 := h & 0x7fc00000 3094 if h1 != 0x40000000 && h1 != 0x3fc00000 { 3095 return -1 3096 } 3097 n := 0 3098 3099 // sign bit (a) 3100 if h&0x80000000 != 0 { 3101 n |= 1 << 7 3102 } 3103 3104 // exp sign bit (b) 3105 if h1 == 0x3fc00000 { 3106 n |= 1 << 6 3107 } 3108 3109 // rest of exp and mantissa (cd-efgh) 3110 n |= int((h >> 16) & 0x3f) 3111 3112 //print("match %.8lux %.8lux %d\n", l, h, n); 3113 return n 3114 } 3115 3116 func nocache(p *obj.Prog) { 3117 p.Optab = 0 3118 p.From.Class = 0 3119 if p.GetFrom3() != nil { 3120 p.GetFrom3().Class = 0 3121 } 3122 p.To.Class = 0 3123 }