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