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