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