github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/cmd/internal/obj/mips/asm0.go (about) 1 // cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova. 2 // 3 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 4 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 5 // Portions Copyright © 1997-1999 Vita Nuova Limited 6 // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com) 7 // Portions Copyright © 2004,2006 Bruce Ellis 8 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 9 // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others 10 // Portions Copyright © 2009 The Go Authors. All rights reserved. 11 // 12 // Permission is hereby granted, free of charge, to any person obtaining a copy 13 // of this software and associated documentation files (the "Software"), to deal 14 // in the Software without restriction, including without limitation the rights 15 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 // copies of the Software, and to permit persons to whom the Software is 17 // furnished to do so, subject to the following conditions: 18 // 19 // The above copyright notice and this permission notice shall be included in 20 // all copies or substantial portions of the Software. 21 // 22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 // THE SOFTWARE. 29 30 package mips 31 32 import ( 33 "cmd/internal/obj" 34 "fmt" 35 "log" 36 "sort" 37 ) 38 39 // Instruction layout. 40 41 const ( 42 FuncAlign = 8 43 ) 44 45 const ( 46 r0iszero = 1 47 ) 48 49 type Optab struct { 50 as obj.As 51 a1 uint8 52 a2 uint8 53 a3 uint8 54 type_ int8 55 size int8 56 param int16 57 } 58 59 var optab = []Optab{ 60 {obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0}, 61 {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0}, 62 63 {AMOVW, C_REG, C_NONE, C_REG, 14, 8, 0}, 64 {AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0}, 65 {AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0}, 66 {AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0}, 67 {AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0}, 68 69 {ASUB, C_REG, C_REG, C_REG, 2, 4, 0}, 70 {AADD, C_REG, C_REG, C_REG, 2, 4, 0}, 71 {AAND, C_REG, C_REG, C_REG, 2, 4, 0}, 72 {ASUB, C_REG, C_NONE, C_REG, 2, 4, 0}, 73 {AADD, C_REG, C_NONE, C_REG, 2, 4, 0}, 74 {AAND, C_REG, C_NONE, C_REG, 2, 4, 0}, 75 76 {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0}, 77 {ASLL, C_REG, C_REG, C_REG, 9, 4, 0}, 78 79 {AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0}, 80 {AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0}, 81 {ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0}, 82 {AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0}, 83 {AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0}, 84 {AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0}, 85 86 {AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, 87 {AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, 88 {AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, 89 {AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, 90 {AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, 91 {AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, 92 {AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, 93 {AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, 94 {AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, 95 {AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, 96 {AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, 97 {AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, 98 {AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, 99 {AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, 100 {AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, 101 {AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, 102 {AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, 103 {AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, 104 105 {AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, 106 {AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, 107 {AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, 108 {AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, 109 {AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, 110 {AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB}, 111 {AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, 112 {AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, 113 {AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, 114 {AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, 115 {AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, 116 {AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP}, 117 {AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, 118 {AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, 119 {AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, 120 {AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, 121 {AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, 122 {AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO}, 123 124 {AMOVW, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, 125 {AMOVWU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, 126 {AMOVV, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, 127 {AMOVB, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, 128 {AMOVBU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB}, 129 {AMOVW, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, 130 {AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, 131 {AMOVV, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, 132 {AMOVB, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, 133 {AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP}, 134 {AMOVW, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, 135 {AMOVWU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, 136 {AMOVV, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, 137 {AMOVB, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, 138 {AMOVBU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO}, 139 {AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0}, 140 {AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0}, 141 {AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0}, 142 {AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0}, 143 {AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0}, 144 145 {AMOVW, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, 146 {AMOVWU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, 147 {AMOVV, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, 148 {AMOVB, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, 149 {AMOVBU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB}, 150 {AMOVW, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, 151 {AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, 152 {AMOVV, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, 153 {AMOVB, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, 154 {AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP}, 155 {AMOVW, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, 156 {AMOVWU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, 157 {AMOVV, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, 158 {AMOVB, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, 159 {AMOVBU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO}, 160 {AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0}, 161 {AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0}, 162 {AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0}, 163 {AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0}, 164 {AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0}, 165 166 {AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB}, 167 {AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB}, 168 {AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP}, 169 {AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP}, 170 {AMOVW, C_LECON, C_NONE, C_REG, 26, 12, REGSB}, 171 {AMOVV, C_LECON, C_NONE, C_REG, 26, 12, REGSB}, 172 {AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP}, 173 {AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP}, 174 {AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO}, 175 {AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO}, 176 {AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO}, 177 {AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO}, 178 179 {AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0}, 180 {AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0}, 181 {AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0}, 182 {AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0}, 183 184 {AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0}, 185 {AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0}, 186 {AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0}, 187 {AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0}, 188 {AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0}, 189 {AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0}, 190 {AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0}, 191 {AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0}, 192 193 {AMUL, C_REG, C_REG, C_NONE, 22, 4, 0}, 194 195 {AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0}, 196 {AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0}, 197 {AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0}, 198 {AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0}, 199 200 {AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0}, 201 {AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0}, 202 {AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0}, 203 {AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0}, 204 205 {AADD, C_UCON, C_REG, C_REG, 25, 8, 0}, 206 {AADD, C_UCON, C_NONE, C_REG, 25, 8, 0}, 207 {AAND, C_UCON, C_REG, C_REG, 25, 8, 0}, 208 {AAND, C_UCON, C_NONE, C_REG, 25, 8, 0}, 209 210 {AADD, C_LCON, C_NONE, C_REG, 23, 12, 0}, 211 {AAND, C_LCON, C_NONE, C_REG, 23, 12, 0}, 212 {AADD, C_LCON, C_REG, C_REG, 23, 12, 0}, 213 {AAND, C_LCON, C_REG, C_REG, 23, 12, 0}, 214 215 {ASLL, C_SCON, C_REG, C_REG, 16, 4, 0}, 216 {ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0}, 217 218 {ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0}, 219 220 {ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0}, 221 {ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0}, 222 {ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0}, 223 {ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0}, 224 225 {AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, 226 {AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, 227 228 {AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO}, 229 {AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK}, 230 231 {AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB}, 232 {AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB}, 233 {AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB}, 234 {AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP}, 235 {AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP}, 236 {AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP}, 237 {AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO}, 238 {AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO}, 239 {AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO}, 240 241 {AMOVW, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB}, 242 {AMOVF, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB}, 243 {AMOVD, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB}, 244 {AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP}, 245 {AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP}, 246 {AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP}, 247 {AMOVW, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO}, 248 {AMOVF, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO}, 249 {AMOVD, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO}, 250 {AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0}, 251 {AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0}, 252 253 {AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB}, 254 {AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB}, 255 {AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB}, 256 {AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP}, 257 {AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP}, 258 {AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP}, 259 {AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO}, 260 {AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO}, 261 {AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO}, 262 263 {AMOVW, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB}, 264 {AMOVF, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB}, 265 {AMOVD, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB}, 266 {AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP}, 267 {AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP}, 268 {AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP}, 269 {AMOVW, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO}, 270 {AMOVF, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO}, 271 {AMOVD, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO}, 272 {AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0}, 273 {AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0}, 274 275 {AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0}, 276 {AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0}, 277 {AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0}, 278 {AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0}, 279 280 {AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0}, 281 {AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0}, 282 {AMOVW, C_UCON, C_NONE, C_FREG, 35, 8, 0}, 283 {AMOVW, C_LCON, C_NONE, C_FREG, 36, 12, 0}, 284 285 {AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0}, 286 {AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0}, 287 {AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0}, 288 {AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0}, 289 290 {AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0}, 291 292 {AMOVW, C_REG, C_NONE, C_FCREG, 41, 8, 0}, 293 {AMOVV, C_REG, C_NONE, C_FCREG, 41, 8, 0}, 294 {AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0}, 295 {AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0}, 296 297 {ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, /* really CACHE instruction */ 298 {ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP}, 299 {ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO}, 300 {ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0}, 301 302 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0}, 303 {obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0}, 304 {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0}, 305 {obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0}, 306 {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0}, 307 {obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP 308 {obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP 309 310 {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0}, 311 } 312 313 var oprange [ALAST & obj.AMask][]Optab 314 315 var xcmp [C_NCLASS][C_NCLASS]bool 316 317 func span0(ctxt *obj.Link, cursym *obj.LSym) { 318 p := cursym.Text 319 if p == nil || p.Link == nil { // handle external functions and ELF section symbols 320 return 321 } 322 ctxt.Cursym = cursym 323 ctxt.Autosize = int32(p.To.Offset + 8) 324 325 if oprange[AOR&obj.AMask] == nil { 326 buildop(ctxt) 327 } 328 329 c := int64(0) 330 p.Pc = c 331 332 var m int 333 var o *Optab 334 for p = p.Link; p != nil; p = p.Link { 335 ctxt.Curp = p 336 p.Pc = c 337 o = oplook(ctxt, p) 338 m = int(o.size) 339 if m == 0 { 340 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD { 341 ctxt.Diag("zero-width instruction\n%v", p) 342 } 343 continue 344 } 345 346 c += int64(m) 347 } 348 349 cursym.Size = c 350 351 /* 352 * if any procedure is large enough to 353 * generate a large SBRA branch, then 354 * generate extra passes putting branches 355 * around jmps to fix. this is rare. 356 */ 357 bflag := 1 358 359 var otxt int64 360 var q *obj.Prog 361 for bflag != 0 { 362 if ctxt.Debugvlog != 0 { 363 fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime()) 364 } 365 bflag = 0 366 c = 0 367 for p = cursym.Text.Link; p != nil; p = p.Link { 368 p.Pc = c 369 o = oplook(ctxt, p) 370 371 // very large conditional branches 372 if o.type_ == 6 && p.Pcond != nil { 373 otxt = p.Pcond.Pc - c 374 if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 { 375 q = ctxt.NewProg() 376 q.Link = p.Link 377 p.Link = q 378 q.As = AJMP 379 q.Lineno = p.Lineno 380 q.To.Type = obj.TYPE_BRANCH 381 q.Pcond = p.Pcond 382 p.Pcond = q 383 q = ctxt.NewProg() 384 q.Link = p.Link 385 p.Link = q 386 q.As = AJMP 387 q.Lineno = p.Lineno 388 q.To.Type = obj.TYPE_BRANCH 389 q.Pcond = q.Link.Link 390 391 addnop(ctxt, p.Link) 392 addnop(ctxt, p) 393 bflag = 1 394 } 395 } 396 397 m = int(o.size) 398 if m == 0 { 399 if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD { 400 ctxt.Diag("zero-width instruction\n%v", p) 401 } 402 continue 403 } 404 405 c += int64(m) 406 } 407 408 cursym.Size = c 409 } 410 411 c += -c & (FuncAlign - 1) 412 cursym.Size = c 413 414 /* 415 * lay out the code, emitting code and data relocations. 416 */ 417 418 cursym.Grow(cursym.Size) 419 420 bp := cursym.P 421 var i int32 422 var out [4]uint32 423 for p := cursym.Text.Link; p != nil; p = p.Link { 424 ctxt.Pc = p.Pc 425 ctxt.Curp = p 426 o = oplook(ctxt, p) 427 if int(o.size) > 4*len(out) { 428 log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p) 429 } 430 asmout(ctxt, p, o, out[:]) 431 for i = 0; i < int32(o.size/4); i++ { 432 ctxt.Arch.ByteOrder.PutUint32(bp, out[i]) 433 bp = bp[4:] 434 } 435 } 436 } 437 438 func isint32(v int64) bool { 439 return int64(int32(v)) == v 440 } 441 442 func isuint32(v uint64) bool { 443 return uint64(uint32(v)) == v 444 } 445 446 func aclass(ctxt *obj.Link, a *obj.Addr) int { 447 switch a.Type { 448 case obj.TYPE_NONE: 449 return C_NONE 450 451 case obj.TYPE_REG: 452 if REG_R0 <= a.Reg && a.Reg <= REG_R31 { 453 return C_REG 454 } 455 if REG_F0 <= a.Reg && a.Reg <= REG_F31 { 456 return C_FREG 457 } 458 if REG_M0 <= a.Reg && a.Reg <= REG_M31 { 459 return C_MREG 460 } 461 if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 { 462 return C_FCREG 463 } 464 if a.Reg == REG_LO { 465 return C_LO 466 } 467 if a.Reg == REG_HI { 468 return C_HI 469 } 470 return C_GOK 471 472 case obj.TYPE_MEM: 473 switch a.Name { 474 case obj.NAME_EXTERN, 475 obj.NAME_STATIC: 476 if a.Sym == nil { 477 break 478 } 479 ctxt.Instoffset = a.Offset 480 if a.Sym != nil { // use relocation 481 return C_ADDR 482 } 483 return C_LEXT 484 485 case obj.NAME_AUTO: 486 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset 487 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG { 488 return C_SAUTO 489 } 490 return C_LAUTO 491 492 case obj.NAME_PARAM: 493 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8 494 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG { 495 return C_SAUTO 496 } 497 return C_LAUTO 498 499 case obj.NAME_NONE: 500 ctxt.Instoffset = a.Offset 501 if ctxt.Instoffset == 0 { 502 return C_ZOREG 503 } 504 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG { 505 return C_SOREG 506 } 507 return C_LOREG 508 } 509 510 return C_GOK 511 512 case obj.TYPE_TEXTSIZE: 513 return C_TEXTSIZE 514 515 case obj.TYPE_CONST, 516 obj.TYPE_ADDR: 517 switch a.Name { 518 case obj.NAME_NONE: 519 ctxt.Instoffset = a.Offset 520 if a.Reg != 0 { 521 if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG { 522 return C_SACON 523 } 524 if isint32(ctxt.Instoffset) { 525 return C_LACON 526 } 527 return C_DACON 528 } 529 530 goto consize 531 532 case obj.NAME_EXTERN, 533 obj.NAME_STATIC: 534 s := a.Sym 535 if s == nil { 536 break 537 } 538 if s.Type == obj.SCONST { 539 ctxt.Instoffset = a.Offset 540 goto consize 541 } 542 543 ctxt.Instoffset = a.Offset 544 545 /* not sure why this barfs */ 546 return C_LCON 547 548 case obj.NAME_AUTO: 549 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset 550 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG { 551 return C_SACON 552 } 553 return C_LACON 554 555 case obj.NAME_PARAM: 556 ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8 557 if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG { 558 return C_SACON 559 } 560 return C_LACON 561 } 562 563 return C_GOK 564 565 consize: 566 if ctxt.Instoffset >= 0 { 567 if ctxt.Instoffset == 0 { 568 return C_ZCON 569 } 570 if ctxt.Instoffset <= 0x7fff { 571 return C_SCON 572 } 573 if ctxt.Instoffset <= 0xffff { 574 return C_ANDCON 575 } 576 if ctxt.Instoffset&0xffff == 0 && isuint32(uint64(ctxt.Instoffset)) { /* && (instoffset & (1<<31)) == 0) */ 577 return C_UCON 578 } 579 if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) { 580 return C_LCON 581 } 582 return C_LCON // C_DCON 583 } 584 585 if ctxt.Instoffset >= -0x8000 { 586 return C_ADDCON 587 } 588 if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) { 589 return C_UCON 590 } 591 if isint32(ctxt.Instoffset) { 592 return C_LCON 593 } 594 return C_LCON // C_DCON 595 596 case obj.TYPE_BRANCH: 597 return C_SBRA 598 } 599 600 return C_GOK 601 } 602 603 func prasm(p *obj.Prog) { 604 fmt.Printf("%v\n", p) 605 } 606 607 func oplook(ctxt *obj.Link, p *obj.Prog) *Optab { 608 if oprange[AOR&obj.AMask] == nil { 609 buildop(ctxt) 610 } 611 612 a1 := int(p.Optab) 613 if a1 != 0 { 614 return &optab[a1-1:][0] 615 } 616 a1 = int(p.From.Class) 617 if a1 == 0 { 618 a1 = aclass(ctxt, &p.From) + 1 619 p.From.Class = int8(a1) 620 } 621 622 a1-- 623 a3 := int(p.To.Class) 624 if a3 == 0 { 625 a3 = aclass(ctxt, &p.To) + 1 626 p.To.Class = int8(a3) 627 } 628 629 a3-- 630 a2 := C_NONE 631 if p.Reg != 0 { 632 a2 = C_REG 633 } 634 635 //print("oplook %P %d %d %d\n", p, a1, a2, a3); 636 637 ops := oprange[p.As&obj.AMask] 638 c1 := &xcmp[a1] 639 c3 := &xcmp[a3] 640 for i := range ops { 641 op := &ops[i] 642 if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] { 643 p.Optab = uint16(cap(optab) - cap(ops) + i + 1) 644 return op 645 } 646 } 647 648 ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(p.As), DRconv(a1), DRconv(a2), DRconv(a3)) 649 prasm(p) 650 if ops == nil { 651 ops = optab 652 } 653 return &ops[0] 654 } 655 656 func cmp(a int, b int) bool { 657 if a == b { 658 return true 659 } 660 switch a { 661 case C_LCON: 662 if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON { 663 return true 664 } 665 666 case C_ADD0CON: 667 if b == C_ADDCON { 668 return true 669 } 670 fallthrough 671 672 case C_ADDCON: 673 if b == C_ZCON || b == C_SCON { 674 return true 675 } 676 677 case C_AND0CON: 678 if b == C_ANDCON { 679 return true 680 } 681 fallthrough 682 683 case C_ANDCON: 684 if b == C_ZCON || b == C_SCON { 685 return true 686 } 687 688 case C_UCON: 689 if b == C_ZCON { 690 return true 691 } 692 693 case C_SCON: 694 if b == C_ZCON { 695 return true 696 } 697 698 case C_LACON: 699 if b == C_SACON { 700 return true 701 } 702 703 case C_LBRA: 704 if b == C_SBRA { 705 return true 706 } 707 708 case C_LEXT: 709 if b == C_SEXT { 710 return true 711 } 712 713 case C_LAUTO: 714 if b == C_SAUTO { 715 return true 716 } 717 718 case C_REG: 719 if b == C_ZCON { 720 return r0iszero != 0 /*TypeKind(100016)*/ 721 } 722 723 case C_LOREG: 724 if b == C_ZOREG || b == C_SOREG { 725 return true 726 } 727 728 case C_SOREG: 729 if b == C_ZOREG { 730 return true 731 } 732 } 733 734 return false 735 } 736 737 type ocmp []Optab 738 739 func (x ocmp) Len() int { 740 return len(x) 741 } 742 743 func (x ocmp) Swap(i, j int) { 744 x[i], x[j] = x[j], x[i] 745 } 746 747 func (x ocmp) Less(i, j int) bool { 748 p1 := &x[i] 749 p2 := &x[j] 750 n := int(p1.as) - int(p2.as) 751 if n != 0 { 752 return n < 0 753 } 754 n = int(p1.a1) - int(p2.a1) 755 if n != 0 { 756 return n < 0 757 } 758 n = int(p1.a2) - int(p2.a2) 759 if n != 0 { 760 return n < 0 761 } 762 n = int(p1.a3) - int(p2.a3) 763 if n != 0 { 764 return n < 0 765 } 766 return false 767 } 768 func opset(a, b0 obj.As) { 769 oprange[a&obj.AMask] = oprange[b0] 770 } 771 772 func buildop(ctxt *obj.Link) { 773 var n int 774 775 for i := 0; i < C_NCLASS; i++ { 776 for n = 0; n < C_NCLASS; n++ { 777 if cmp(n, i) { 778 xcmp[i][n] = true 779 } 780 } 781 } 782 for n = 0; optab[n].as != obj.AXXX; n++ { 783 } 784 sort.Sort(ocmp(optab[:n])) 785 for i := 0; i < n; i++ { 786 r := optab[i].as 787 r0 := r & obj.AMask 788 start := i 789 for optab[i].as == r { 790 i++ 791 } 792 oprange[r0] = optab[start:i] 793 i-- 794 795 switch r { 796 default: 797 ctxt.Diag("unknown op in build: %v", obj.Aconv(r)) 798 log.Fatalf("bad code") 799 800 case AABSF: 801 opset(AMOVFD, r0) 802 opset(AMOVDF, r0) 803 opset(AMOVWF, r0) 804 opset(AMOVFW, r0) 805 opset(AMOVWD, r0) 806 opset(AMOVDW, r0) 807 opset(ANEGF, r0) 808 opset(ANEGD, r0) 809 opset(AABSD, r0) 810 opset(ATRUNCDW, r0) 811 opset(ATRUNCFW, r0) 812 opset(ATRUNCDV, r0) 813 opset(ATRUNCFV, r0) 814 opset(AMOVVF, r0) 815 opset(AMOVFV, r0) 816 opset(AMOVVD, r0) 817 opset(AMOVDV, r0) 818 819 case AADD: 820 opset(ASGT, r0) 821 opset(ASGTU, r0) 822 opset(AADDU, r0) 823 opset(AADDV, r0) 824 opset(AADDVU, r0) 825 826 case AADDF: 827 opset(ADIVF, r0) 828 opset(ADIVD, r0) 829 opset(AMULF, r0) 830 opset(AMULD, r0) 831 opset(ASUBF, r0) 832 opset(ASUBD, r0) 833 opset(AADDD, r0) 834 835 case AAND: 836 opset(AOR, r0) 837 opset(AXOR, r0) 838 839 case ABEQ: 840 opset(ABNE, r0) 841 842 case ABLEZ: 843 opset(ABGEZ, r0) 844 opset(ABGEZAL, r0) 845 opset(ABLTZ, r0) 846 opset(ABLTZAL, r0) 847 opset(ABGTZ, r0) 848 849 case AMOVB: 850 opset(AMOVH, r0) 851 852 case AMOVBU: 853 opset(AMOVHU, r0) 854 855 case AMUL: 856 opset(AREM, r0) 857 opset(AREMU, r0) 858 opset(ADIVU, r0) 859 opset(AMULU, r0) 860 opset(ADIV, r0) 861 opset(ADIVV, r0) 862 opset(ADIVVU, r0) 863 opset(AMULV, r0) 864 opset(AMULVU, r0) 865 opset(AREMV, r0) 866 opset(AREMVU, r0) 867 868 case ASLL: 869 opset(ASRL, r0) 870 opset(ASRA, r0) 871 opset(ASLLV, r0) 872 opset(ASRAV, r0) 873 opset(ASRLV, r0) 874 875 case ASUB: 876 opset(ASUBU, r0) 877 opset(ASUBV, r0) 878 opset(ASUBVU, r0) 879 opset(ANOR, r0) 880 881 case ASYSCALL: 882 opset(ATLBP, r0) 883 opset(ATLBR, r0) 884 opset(ATLBWI, r0) 885 opset(ATLBWR, r0) 886 887 case ACMPEQF: 888 opset(ACMPGTF, r0) 889 opset(ACMPGTD, r0) 890 opset(ACMPGEF, r0) 891 opset(ACMPGED, r0) 892 opset(ACMPEQD, r0) 893 894 case ABFPT: 895 opset(ABFPF, r0) 896 897 case AMOVWL: 898 opset(AMOVWR, r0) 899 opset(AMOVVR, r0) 900 opset(AMOVVL, r0) 901 902 case AMOVW, 903 AMOVD, 904 AMOVF, 905 AMOVV, 906 ABREAK, 907 ARFE, 908 AJAL, 909 AJMP, 910 AMOVWU, 911 AWORD, 912 obj.ANOP, 913 obj.ATEXT, 914 obj.AUNDEF, 915 obj.AUSEFIELD, 916 obj.AFUNCDATA, 917 obj.APCDATA, 918 obj.ADUFFZERO, 919 obj.ADUFFCOPY: 920 break 921 } 922 } 923 } 924 925 func OP(x uint32, y uint32) uint32 { 926 return x<<3 | y<<0 927 } 928 929 func SP(x uint32, y uint32) uint32 { 930 return x<<29 | y<<26 931 } 932 933 func BCOND(x uint32, y uint32) uint32 { 934 return x<<19 | y<<16 935 } 936 937 func MMU(x uint32, y uint32) uint32 { 938 return SP(2, 0) | 16<<21 | x<<3 | y<<0 939 } 940 941 func FPF(x uint32, y uint32) uint32 { 942 return SP(2, 1) | 16<<21 | x<<3 | y<<0 943 } 944 945 func FPD(x uint32, y uint32) uint32 { 946 return SP(2, 1) | 17<<21 | x<<3 | y<<0 947 } 948 949 func FPW(x uint32, y uint32) uint32 { 950 return SP(2, 1) | 20<<21 | x<<3 | y<<0 951 } 952 953 func FPV(x uint32, y uint32) uint32 { 954 return SP(2, 1) | 21<<21 | x<<3 | y<<0 955 } 956 957 func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 { 958 return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11 959 } 960 961 func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 { 962 return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16 963 } 964 965 func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 { 966 return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11 967 } 968 969 func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 { 970 return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6 971 } 972 973 func OP_JMP(op uint32, i uint32) uint32 { 974 return op | i&0x3FFFFFF 975 } 976 977 func oclass(a *obj.Addr) int { 978 return int(a.Class) - 1 979 } 980 981 func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { 982 o1 := uint32(0) 983 o2 := uint32(0) 984 o3 := uint32(0) 985 o4 := uint32(0) 986 987 switch o.type_ { 988 default: 989 ctxt.Diag("unknown type %d %v", o.type_) 990 prasm(p) 991 992 case 0: /* pseudo ops */ 993 break 994 995 case 1: /* mov r1,r2 ==> OR r1,r0,r2 */ 996 o1 = OP_RRR(oprrr(ctxt, AOR), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg)) 997 998 case 2: /* add/sub r1,[r2],r3 */ 999 r := int(p.Reg) 1000 1001 if r == 0 { 1002 r = int(p.To.Reg) 1003 } 1004 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) 1005 1006 case 3: /* mov $soreg, r ==> or/add $i,o,r */ 1007 v := regoff(ctxt, &p.From) 1008 1009 r := int(p.From.Reg) 1010 if r == 0 { 1011 r = int(o.param) 1012 } 1013 a := AADDVU 1014 if o.a1 == C_ANDCON { 1015 a = AOR 1016 } 1017 1018 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg)) 1019 1020 case 4: /* add $scon,[r1],r2 */ 1021 v := regoff(ctxt, &p.From) 1022 1023 r := int(p.Reg) 1024 if r == 0 { 1025 r = int(p.To.Reg) 1026 } 1027 1028 o1 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.To.Reg)) 1029 1030 case 5: /* syscall */ 1031 o1 = uint32(oprrr(ctxt, p.As)) 1032 1033 case 6: /* beq r1,[r2],sbra */ 1034 v := int32(0) 1035 if p.Pcond == nil { 1036 v = int32(-4) >> 2 1037 } else { 1038 v = int32(p.Pcond.Pc-p.Pc-4) >> 2 1039 } 1040 if (v<<16)>>16 != v { 1041 ctxt.Diag("short branch too far\n%v", p) 1042 } 1043 o1 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg)) 1044 // for ABFPT and ABFPF only: always fill delay slot with 0 1045 // see comments in func preprocess for details. 1046 o2 = 0 1047 1048 case 7: /* mov r, soreg ==> sw o(r) */ 1049 r := int(p.To.Reg) 1050 if r == 0 { 1051 r = int(o.param) 1052 } 1053 v := regoff(ctxt, &p.To) 1054 o1 = OP_IRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.From.Reg)) 1055 1056 case 8: /* mov soreg, r ==> lw o(r) */ 1057 r := int(p.From.Reg) 1058 if r == 0 { 1059 r = int(o.param) 1060 } 1061 v := regoff(ctxt, &p.From) 1062 o1 = OP_IRR(opirr(ctxt, -p.As), uint32(v), uint32(r), uint32(p.To.Reg)) 1063 1064 case 9: /* sll r1,[r2],r3 */ 1065 r := int(p.Reg) 1066 1067 if r == 0 { 1068 r = int(p.To.Reg) 1069 } 1070 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg)) 1071 1072 case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */ 1073 v := regoff(ctxt, &p.From) 1074 a := AOR 1075 if v < 0 { 1076 a = AADDU 1077 } 1078 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP)) 1079 r := int(p.Reg) 1080 if r == 0 { 1081 r = int(p.To.Reg) 1082 } 1083 o2 = OP_RRR(oprrr(ctxt, p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1084 1085 case 11: /* jmp lbra */ 1086 v := int32(0) 1087 if aclass(ctxt, &p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP { 1088 // use PC-relative branch for short branches 1089 // BEQ R0, R0, sbra 1090 if p.Pcond == nil { 1091 v = int32(-4) >> 2 1092 } else { 1093 v = int32(p.Pcond.Pc-p.Pc-4) >> 2 1094 } 1095 if (v<<16)>>16 == v { 1096 o1 = OP_IRR(opirr(ctxt, ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO)) 1097 break 1098 } 1099 } 1100 if p.Pcond == nil { 1101 v = int32(p.Pc) >> 2 1102 } else { 1103 v = int32(p.Pcond.Pc) >> 2 1104 } 1105 o1 = OP_JMP(opirr(ctxt, p.As), uint32(v)) 1106 if p.To.Sym == nil { 1107 p.To.Sym = ctxt.Cursym.Text.From.Sym 1108 p.To.Offset = p.Pcond.Pc 1109 } 1110 rel := obj.Addrel(ctxt.Cursym) 1111 rel.Off = int32(ctxt.Pc) 1112 rel.Siz = 4 1113 rel.Sym = p.To.Sym 1114 rel.Add = p.To.Offset 1115 if p.As == AJAL { 1116 rel.Type = obj.R_CALLMIPS 1117 } else { 1118 rel.Type = obj.R_JMPMIPS 1119 } 1120 1121 case 12: /* movbs r,r */ 1122 v := 16 1123 if p.As == AMOVB { 1124 v = 24 1125 } 1126 o1 = OP_SRR(opirr(ctxt, ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg)) 1127 o2 = OP_SRR(opirr(ctxt, ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg)) 1128 1129 case 13: /* movbu r,r */ 1130 if p.As == AMOVBU { 1131 o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg)) 1132 } else { 1133 o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg)) 1134 } 1135 1136 case 14: /* movwu r,r */ 1137 o1 = OP_SRR(opirr(ctxt, -ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg)) 1138 if p.As == AMOVWU { 1139 o2 = OP_SRR(opirr(ctxt, -ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) 1140 } else { 1141 o2 = OP_SRR(opirr(ctxt, -ASRAV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) 1142 } 1143 1144 case 16: /* sll $c,[r1],r2 */ 1145 v := regoff(ctxt, &p.From) 1146 r := int(p.Reg) 1147 if r == 0 { 1148 r = int(p.To.Reg) 1149 } 1150 1151 /* OP_SRR will use only the low 5 bits of the shift value */ 1152 if v >= 32 && vshift(p.As) { 1153 o1 = OP_SRR(opirr(ctxt, -p.As), uint32(v-32), uint32(r), uint32(p.To.Reg)) 1154 } else { 1155 o1 = OP_SRR(opirr(ctxt, p.As), uint32(v), uint32(r), uint32(p.To.Reg)) 1156 } 1157 1158 case 18: /* jmp [r1],0(r2) */ 1159 r := int(p.Reg) 1160 if r == 0 { 1161 r = int(o.param) 1162 } 1163 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(0), uint32(p.To.Reg), uint32(r)) 1164 rel := obj.Addrel(ctxt.Cursym) 1165 rel.Off = int32(ctxt.Pc) 1166 rel.Siz = 0 1167 rel.Type = obj.R_CALLIND 1168 1169 case 19: /* mov $lcon,r ==> lu+or */ 1170 v := regoff(ctxt, &p.From) 1171 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg)) 1172 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg)) 1173 if p.From.Sym != nil { 1174 rel := obj.Addrel(ctxt.Cursym) 1175 rel.Off = int32(ctxt.Pc) 1176 rel.Siz = 8 1177 rel.Sym = p.From.Sym 1178 rel.Add = p.From.Offset 1179 rel.Type = obj.R_ADDRMIPS 1180 } 1181 1182 case 20: /* mov lo/hi,r */ 1183 a := OP(2, 0) /* mfhi */ 1184 if p.From.Reg == REG_LO { 1185 a = OP(2, 2) /* mflo */ 1186 } 1187 o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg)) 1188 1189 case 21: /* mov r,lo/hi */ 1190 a := OP(2, 1) /* mthi */ 1191 if p.To.Reg == REG_LO { 1192 a = OP(2, 3) /* mtlo */ 1193 } 1194 o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO)) 1195 1196 case 22: /* mul r1,r2 */ 1197 o1 = OP_RRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO)) 1198 1199 case 23: /* add $lcon,r1,r2 ==> lu+or+add */ 1200 v := regoff(ctxt, &p.From) 1201 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1202 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1203 r := int(p.Reg) 1204 if r == 0 { 1205 r = int(p.To.Reg) 1206 } 1207 o3 = OP_RRR(oprrr(ctxt, p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1208 1209 case 24: /* mov $ucon,r ==> lu r */ 1210 v := regoff(ctxt, &p.From) 1211 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg)) 1212 1213 case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */ 1214 v := regoff(ctxt, &p.From) 1215 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1216 r := int(p.Reg) 1217 if r == 0 { 1218 r = int(p.To.Reg) 1219 } 1220 o2 = OP_RRR(oprrr(ctxt, p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1221 1222 case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */ 1223 v := regoff(ctxt, &p.From) 1224 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1225 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1226 r := int(p.From.Reg) 1227 if r == 0 { 1228 r = int(o.param) 1229 } 1230 o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1231 1232 case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */ 1233 v := regoff(ctxt, &p.From) 1234 r := int(p.From.Reg) 1235 if r == 0 { 1236 r = int(o.param) 1237 } 1238 a := -AMOVF 1239 if p.As == AMOVD { 1240 a = -AMOVD 1241 } 1242 switch o.size { 1243 case 16: 1244 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1245 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1246 o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1247 o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(r), uint32(p.To.Reg)) 1248 1249 case 4: 1250 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg)) 1251 } 1252 1253 case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */ 1254 v := regoff(ctxt, &p.To) 1255 r := int(p.To.Reg) 1256 if r == 0 { 1257 r = int(o.param) 1258 } 1259 a := AMOVF 1260 if p.As == AMOVD { 1261 a = AMOVD 1262 } 1263 switch o.size { 1264 case 16: 1265 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1266 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1267 o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1268 o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(REGTMP), uint32(p.From.Reg)) 1269 1270 case 4: 1271 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.From.Reg)) 1272 } 1273 1274 case 30: /* movw r,fr */ 1275 a := SP(2, 1) | (4 << 21) /* mtc1 */ 1276 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) 1277 1278 case 31: /* movw fr,r */ 1279 a := SP(2, 1) | (0 << 21) /* mtc1 */ 1280 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) 1281 1282 case 32: /* fadd fr1,[fr2],fr3 */ 1283 r := int(p.Reg) 1284 if r == 0 { 1285 r = int(p.To.Reg) 1286 } 1287 o1 = OP_FRRR(oprrr(ctxt, p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) 1288 1289 case 33: /* fabs fr1, fr3 */ 1290 o1 = OP_FRRR(oprrr(ctxt, p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg)) 1291 1292 case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */ 1293 v := regoff(ctxt, &p.From) 1294 a := AADDU 1295 if o.a1 == C_ANDCON { 1296 a = AOR 1297 } 1298 o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP)) 1299 o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */ 1300 1301 case 35: /* mov r,lext/auto/oreg ==> sw o(r) */ 1302 v := regoff(ctxt, &p.To) 1303 r := int(p.To.Reg) 1304 if r == 0 { 1305 r = int(o.param) 1306 } 1307 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1308 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1309 o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1310 o4 = OP_IRR(opirr(ctxt, p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg)) 1311 1312 case 36: /* mov lext/auto/oreg,r ==> lw o(r30) */ 1313 v := regoff(ctxt, &p.From) 1314 r := int(p.From.Reg) 1315 if r == 0 { 1316 r = int(o.param) 1317 } 1318 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1319 o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1320 o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1321 o4 = OP_IRR(opirr(ctxt, -p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg)) 1322 1323 case 37: /* movw r,mr */ 1324 a := SP(2, 0) | (4 << 21) /* mtc0 */ 1325 if p.As == AMOVV { 1326 a = SP(2, 0) | (5 << 21) /* dmtc0 */ 1327 } 1328 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) 1329 1330 case 38: /* movw mr,r */ 1331 a := SP(2, 0) | (0 << 21) /* mfc0 */ 1332 if p.As == AMOVV { 1333 a = SP(2, 0) | (1 << 21) /* dmfc0 */ 1334 } 1335 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) 1336 1337 case 40: /* word */ 1338 o1 = uint32(regoff(ctxt, &p.From)) 1339 1340 case 41: /* movw f,fcr */ 1341 o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(REGZERO), uint32(0), uint32(p.To.Reg)) /* mfcc1 */ 1342 o2 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */ 1343 1344 case 42: /* movw fcr,r */ 1345 o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */ 1346 1347 case 47: /* movv r,fr */ 1348 a := SP(2, 1) | (5 << 21) /* dmtc1 */ 1349 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) 1350 1351 case 48: /* movv fr,r */ 1352 a := SP(2, 1) | (1 << 21) /* dmtc1 */ 1353 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) 1354 1355 case 49: /* undef */ 1356 o1 = 8 /* JMP (R0) */ 1357 1358 /* relocation operations */ 1359 case 50: /* mov r,addr ==> lu + or + sw (REGTMP) */ 1360 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP)) 1361 o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP)) 1362 rel := obj.Addrel(ctxt.Cursym) 1363 rel.Off = int32(ctxt.Pc) 1364 rel.Siz = 8 1365 rel.Sym = p.To.Sym 1366 rel.Add = p.To.Offset 1367 rel.Type = obj.R_ADDRMIPS 1368 o3 = OP_IRR(opirr(ctxt, p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg)) 1369 1370 case 51: /* mov addr,r ==> lu + or + lw (REGTMP) */ 1371 o1 = OP_IRR(opirr(ctxt, ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP)) 1372 o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP)) 1373 rel := obj.Addrel(ctxt.Cursym) 1374 rel.Off = int32(ctxt.Pc) 1375 rel.Siz = 8 1376 rel.Sym = p.From.Sym 1377 rel.Add = p.From.Offset 1378 rel.Type = obj.R_ADDRMIPS 1379 o3 = OP_IRR(opirr(ctxt, -p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg)) 1380 } 1381 1382 out[0] = o1 1383 out[1] = o2 1384 out[2] = o3 1385 out[3] = o4 1386 return 1387 } 1388 1389 func vregoff(ctxt *obj.Link, a *obj.Addr) int64 { 1390 ctxt.Instoffset = 0 1391 aclass(ctxt, a) 1392 return ctxt.Instoffset 1393 } 1394 1395 func regoff(ctxt *obj.Link, a *obj.Addr) int32 { 1396 return int32(vregoff(ctxt, a)) 1397 } 1398 1399 func oprrr(ctxt *obj.Link, a obj.As) uint32 { 1400 switch a { 1401 case AADD: 1402 return OP(4, 0) 1403 case AADDU: 1404 return OP(4, 1) 1405 case ASGT: 1406 return OP(5, 2) 1407 case ASGTU: 1408 return OP(5, 3) 1409 case AAND: 1410 return OP(4, 4) 1411 case AOR: 1412 return OP(4, 5) 1413 case AXOR: 1414 return OP(4, 6) 1415 case ASUB: 1416 return OP(4, 2) 1417 case ASUBU: 1418 return OP(4, 3) 1419 case ANOR: 1420 return OP(4, 7) 1421 case ASLL: 1422 return OP(0, 4) 1423 case ASRL: 1424 return OP(0, 6) 1425 case ASRA: 1426 return OP(0, 7) 1427 case ASLLV: 1428 return OP(2, 4) 1429 case ASRLV: 1430 return OP(2, 6) 1431 case ASRAV: 1432 return OP(2, 7) 1433 case AADDV: 1434 return OP(5, 4) 1435 case AADDVU: 1436 return OP(5, 5) 1437 case ASUBV: 1438 return OP(5, 6) 1439 case ASUBVU: 1440 return OP(5, 7) 1441 case AREM, 1442 ADIV: 1443 return OP(3, 2) 1444 case AREMU, 1445 ADIVU: 1446 return OP(3, 3) 1447 case AMUL: 1448 return OP(3, 0) 1449 case AMULU: 1450 return OP(3, 1) 1451 case AREMV, 1452 ADIVV: 1453 return OP(3, 6) 1454 case AREMVU, 1455 ADIVVU: 1456 return OP(3, 7) 1457 case AMULV: 1458 return OP(3, 4) 1459 case AMULVU: 1460 return OP(3, 5) 1461 1462 case AJMP: 1463 return OP(1, 0) 1464 case AJAL: 1465 return OP(1, 1) 1466 1467 case ABREAK: 1468 return OP(1, 5) 1469 case ASYSCALL: 1470 return OP(1, 4) 1471 case ATLBP: 1472 return MMU(1, 0) 1473 case ATLBR: 1474 return MMU(0, 1) 1475 case ATLBWI: 1476 return MMU(0, 2) 1477 case ATLBWR: 1478 return MMU(0, 6) 1479 case ARFE: 1480 return MMU(2, 0) 1481 1482 case ADIVF: 1483 return FPF(0, 3) 1484 case ADIVD: 1485 return FPD(0, 3) 1486 case AMULF: 1487 return FPF(0, 2) 1488 case AMULD: 1489 return FPD(0, 2) 1490 case ASUBF: 1491 return FPF(0, 1) 1492 case ASUBD: 1493 return FPD(0, 1) 1494 case AADDF: 1495 return FPF(0, 0) 1496 case AADDD: 1497 return FPD(0, 0) 1498 case ATRUNCFV: 1499 return FPF(1, 1) 1500 case ATRUNCDV: 1501 return FPD(1, 1) 1502 case ATRUNCFW: 1503 return FPF(1, 5) 1504 case ATRUNCDW: 1505 return FPD(1, 5) 1506 case AMOVFV: 1507 return FPF(4, 5) 1508 case AMOVDV: 1509 return FPD(4, 5) 1510 case AMOVVF: 1511 return FPV(4, 0) 1512 case AMOVVD: 1513 return FPV(4, 1) 1514 case AMOVFW: 1515 return FPF(4, 4) 1516 case AMOVDW: 1517 return FPD(4, 4) 1518 case AMOVWF: 1519 return FPW(4, 0) 1520 case AMOVDF: 1521 return FPD(4, 0) 1522 case AMOVWD: 1523 return FPW(4, 1) 1524 case AMOVFD: 1525 return FPF(4, 1) 1526 case AABSF: 1527 return FPF(0, 5) 1528 case AABSD: 1529 return FPD(0, 5) 1530 case AMOVF: 1531 return FPF(0, 6) 1532 case AMOVD: 1533 return FPD(0, 6) 1534 case ANEGF: 1535 return FPF(0, 7) 1536 case ANEGD: 1537 return FPD(0, 7) 1538 case ACMPEQF: 1539 return FPF(6, 2) 1540 case ACMPEQD: 1541 return FPD(6, 2) 1542 case ACMPGTF: 1543 return FPF(7, 4) 1544 case ACMPGTD: 1545 return FPD(7, 4) 1546 case ACMPGEF: 1547 return FPF(7, 6) 1548 case ACMPGED: 1549 return FPD(7, 6) 1550 } 1551 1552 if a < 0 { 1553 ctxt.Diag("bad rrr opcode -%v", obj.Aconv(-a)) 1554 } else { 1555 ctxt.Diag("bad rrr opcode %v", obj.Aconv(a)) 1556 } 1557 return 0 1558 } 1559 1560 func opirr(ctxt *obj.Link, a obj.As) uint32 { 1561 switch a { 1562 case AADD: 1563 return SP(1, 0) 1564 case AADDU: 1565 return SP(1, 1) 1566 case ASGT: 1567 return SP(1, 2) 1568 case ASGTU: 1569 return SP(1, 3) 1570 case AAND: 1571 return SP(1, 4) 1572 case AOR: 1573 return SP(1, 5) 1574 case AXOR: 1575 return SP(1, 6) 1576 case ALUI: 1577 return SP(1, 7) 1578 case ASLL: 1579 return OP(0, 0) 1580 case ASRL: 1581 return OP(0, 2) 1582 case ASRA: 1583 return OP(0, 3) 1584 case AADDV: 1585 return SP(3, 0) 1586 case AADDVU: 1587 return SP(3, 1) 1588 1589 case AJMP: 1590 return SP(0, 2) 1591 case AJAL, 1592 obj.ADUFFZERO, 1593 obj.ADUFFCOPY: 1594 return SP(0, 3) 1595 case ABEQ: 1596 return SP(0, 4) 1597 case -ABEQ: 1598 return SP(2, 4) /* likely */ 1599 case ABNE: 1600 return SP(0, 5) 1601 case -ABNE: 1602 return SP(2, 5) /* likely */ 1603 case ABGEZ: 1604 return SP(0, 1) | BCOND(0, 1) 1605 case -ABGEZ: 1606 return SP(0, 1) | BCOND(0, 3) /* likely */ 1607 case ABGEZAL: 1608 return SP(0, 1) | BCOND(2, 1) 1609 case -ABGEZAL: 1610 return SP(0, 1) | BCOND(2, 3) /* likely */ 1611 case ABGTZ: 1612 return SP(0, 7) 1613 case -ABGTZ: 1614 return SP(2, 7) /* likely */ 1615 case ABLEZ: 1616 return SP(0, 6) 1617 case -ABLEZ: 1618 return SP(2, 6) /* likely */ 1619 case ABLTZ: 1620 return SP(0, 1) | BCOND(0, 0) 1621 case -ABLTZ: 1622 return SP(0, 1) | BCOND(0, 2) /* likely */ 1623 case ABLTZAL: 1624 return SP(0, 1) | BCOND(2, 0) 1625 case -ABLTZAL: 1626 return SP(0, 1) | BCOND(2, 2) /* likely */ 1627 case ABFPT: 1628 return SP(2, 1) | (257 << 16) 1629 case -ABFPT: 1630 return SP(2, 1) | (259 << 16) /* likely */ 1631 case ABFPF: 1632 return SP(2, 1) | (256 << 16) 1633 case -ABFPF: 1634 return SP(2, 1) | (258 << 16) /* likely */ 1635 1636 case AMOVB, 1637 AMOVBU: 1638 return SP(5, 0) 1639 case AMOVH, 1640 AMOVHU: 1641 return SP(5, 1) 1642 case AMOVW, 1643 AMOVWU: 1644 return SP(5, 3) 1645 case AMOVV: 1646 return SP(7, 7) 1647 case AMOVF: 1648 return SP(7, 1) 1649 case AMOVD: 1650 return SP(7, 5) 1651 case AMOVWL: 1652 return SP(5, 2) 1653 case AMOVWR: 1654 return SP(5, 6) 1655 case AMOVVL: 1656 return SP(5, 4) 1657 case AMOVVR: 1658 return SP(5, 5) 1659 1660 case ABREAK: 1661 return SP(5, 7) 1662 1663 case -AMOVWL: 1664 return SP(4, 2) 1665 case -AMOVWR: 1666 return SP(4, 6) 1667 case -AMOVVL: 1668 return SP(3, 2) 1669 case -AMOVVR: 1670 return SP(3, 3) 1671 case -AMOVB: 1672 return SP(4, 0) 1673 case -AMOVBU: 1674 return SP(4, 4) 1675 case -AMOVH: 1676 return SP(4, 1) 1677 case -AMOVHU: 1678 return SP(4, 5) 1679 case -AMOVW: 1680 return SP(4, 3) 1681 case -AMOVWU: 1682 return SP(4, 7) 1683 case -AMOVV: 1684 return SP(6, 7) 1685 case -AMOVF: 1686 return SP(6, 1) 1687 case -AMOVD: 1688 return SP(6, 5) 1689 1690 case ASLLV: 1691 return OP(7, 0) 1692 case ASRLV: 1693 return OP(7, 2) 1694 case ASRAV: 1695 return OP(7, 3) 1696 case -ASLLV: 1697 return OP(7, 4) 1698 case -ASRLV: 1699 return OP(7, 6) 1700 case -ASRAV: 1701 return OP(7, 7) 1702 } 1703 1704 if a < 0 { 1705 ctxt.Diag("bad irr opcode -%v", obj.Aconv(-a)) 1706 } else { 1707 ctxt.Diag("bad irr opcode %v", obj.Aconv(a)) 1708 } 1709 return 0 1710 } 1711 1712 func vshift(a obj.As) bool { 1713 switch a { 1714 case ASLLV, 1715 ASRLV, 1716 ASRAV: 1717 return true 1718 } 1719 return false 1720 }