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