github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/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 ctxt.DiagFlush() 897 log.Fatalf("bad code") 898 899 case AABSF: 900 opset(AMOVFD, r0) 901 opset(AMOVDF, r0) 902 opset(AMOVWF, r0) 903 opset(AMOVFW, r0) 904 opset(AMOVWD, r0) 905 opset(AMOVDW, r0) 906 opset(ANEGF, r0) 907 opset(ANEGD, r0) 908 opset(AABSD, r0) 909 opset(ATRUNCDW, r0) 910 opset(ATRUNCFW, r0) 911 opset(ASQRTF, r0) 912 opset(ASQRTD, r0) 913 914 case AMOVVF: 915 opset(AMOVVD, r0) 916 opset(AMOVFV, r0) 917 opset(AMOVDV, r0) 918 opset(ATRUNCDV, r0) 919 opset(ATRUNCFV, r0) 920 921 case AADD: 922 opset(ASGT, r0) 923 opset(ASGTU, r0) 924 opset(AADDU, r0) 925 926 case AADDV: 927 opset(AADDVU, r0) 928 929 case AADDF: 930 opset(ADIVF, r0) 931 opset(ADIVD, r0) 932 opset(AMULF, r0) 933 opset(AMULD, r0) 934 opset(ASUBF, r0) 935 opset(ASUBD, r0) 936 opset(AADDD, r0) 937 938 case AAND: 939 opset(AOR, r0) 940 opset(AXOR, r0) 941 942 case ABEQ: 943 opset(ABNE, r0) 944 945 case ABLEZ: 946 opset(ABGEZ, r0) 947 opset(ABGEZAL, r0) 948 opset(ABLTZ, r0) 949 opset(ABLTZAL, r0) 950 opset(ABGTZ, r0) 951 952 case AMOVB: 953 opset(AMOVH, r0) 954 955 case AMOVBU: 956 opset(AMOVHU, r0) 957 958 case AMUL: 959 opset(AREM, r0) 960 opset(AREMU, r0) 961 opset(ADIVU, r0) 962 opset(AMULU, r0) 963 opset(ADIV, r0) 964 965 case AMULV: 966 opset(ADIVV, r0) 967 opset(ADIVVU, r0) 968 opset(AMULVU, r0) 969 opset(AREMV, r0) 970 opset(AREMVU, r0) 971 972 case ASLL: 973 opset(ASRL, r0) 974 opset(ASRA, r0) 975 976 case ASLLV: 977 opset(ASRAV, r0) 978 opset(ASRLV, r0) 979 980 case ASUB: 981 opset(ASUBU, r0) 982 opset(ANOR, r0) 983 984 case ASUBV: 985 opset(ASUBVU, r0) 986 987 case ASYSCALL: 988 opset(ASYNC, r0) 989 opset(ANOOP, r0) 990 opset(ATLBP, r0) 991 opset(ATLBR, r0) 992 opset(ATLBWI, r0) 993 opset(ATLBWR, r0) 994 995 case ACMPEQF: 996 opset(ACMPGTF, r0) 997 opset(ACMPGTD, r0) 998 opset(ACMPGEF, r0) 999 opset(ACMPGED, r0) 1000 opset(ACMPEQD, r0) 1001 1002 case ABFPT: 1003 opset(ABFPF, r0) 1004 1005 case AMOVWL: 1006 opset(AMOVWR, r0) 1007 1008 case AMOVVL: 1009 opset(AMOVVR, r0) 1010 1011 case AMOVW, 1012 AMOVD, 1013 AMOVF, 1014 AMOVV, 1015 ABREAK, 1016 ARFE, 1017 AJAL, 1018 AJMP, 1019 AMOVWU, 1020 ALL, 1021 ALLV, 1022 ASC, 1023 ASCV, 1024 AWORD, 1025 obj.ANOP, 1026 obj.ATEXT, 1027 obj.AUNDEF, 1028 obj.AFUNCDATA, 1029 obj.APCDATA, 1030 obj.ADUFFZERO, 1031 obj.ADUFFCOPY: 1032 break 1033 1034 case ACMOVN: 1035 opset(ACMOVZ, r0) 1036 1037 case ACMOVT: 1038 opset(ACMOVF, r0) 1039 1040 case ACLO: 1041 opset(ACLZ, r0) 1042 1043 case ATEQ: 1044 opset(ATNE, r0) 1045 } 1046 } 1047 } 1048 1049 func OP(x uint32, y uint32) uint32 { 1050 return x<<3 | y<<0 1051 } 1052 1053 func SP(x uint32, y uint32) uint32 { 1054 return x<<29 | y<<26 1055 } 1056 1057 func BCOND(x uint32, y uint32) uint32 { 1058 return x<<19 | y<<16 1059 } 1060 1061 func MMU(x uint32, y uint32) uint32 { 1062 return SP(2, 0) | 16<<21 | x<<3 | y<<0 1063 } 1064 1065 func FPF(x uint32, y uint32) uint32 { 1066 return SP(2, 1) | 16<<21 | x<<3 | y<<0 1067 } 1068 1069 func FPD(x uint32, y uint32) uint32 { 1070 return SP(2, 1) | 17<<21 | x<<3 | y<<0 1071 } 1072 1073 func FPW(x uint32, y uint32) uint32 { 1074 return SP(2, 1) | 20<<21 | x<<3 | y<<0 1075 } 1076 1077 func FPV(x uint32, y uint32) uint32 { 1078 return SP(2, 1) | 21<<21 | x<<3 | y<<0 1079 } 1080 1081 func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 { 1082 return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11 1083 } 1084 1085 func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 { 1086 return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16 1087 } 1088 1089 func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 { 1090 return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11 1091 } 1092 1093 func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 { 1094 return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6 1095 } 1096 1097 func OP_JMP(op uint32, i uint32) uint32 { 1098 return op | i&0x3FFFFFF 1099 } 1100 1101 func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) { 1102 o1 := uint32(0) 1103 o2 := uint32(0) 1104 o3 := uint32(0) 1105 o4 := uint32(0) 1106 1107 add := AADDU 1108 1109 if c.ctxt.Arch.Family == sys.MIPS64 { 1110 add = AADDVU 1111 } 1112 switch o.type_ { 1113 default: 1114 c.ctxt.Diag("unknown type %d %v", o.type_) 1115 prasm(p) 1116 1117 case 0: /* pseudo ops */ 1118 break 1119 1120 case 1: /* mov r1,r2 ==> OR r1,r0,r2 */ 1121 a := AOR 1122 if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 { 1123 a = AADDU // sign-extended to high 32 bits 1124 } 1125 o1 = OP_RRR(c.oprrr(a), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg)) 1126 1127 case 2: /* add/sub r1,[r2],r3 */ 1128 r := int(p.Reg) 1129 1130 if r == 0 { 1131 r = int(p.To.Reg) 1132 } 1133 o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) 1134 1135 case 3: /* mov $soreg, r ==> or/add $i,o,r */ 1136 v := c.regoff(&p.From) 1137 1138 r := int(p.From.Reg) 1139 if r == 0 { 1140 r = int(o.param) 1141 } 1142 a := add 1143 if o.a1 == C_ANDCON { 1144 a = AOR 1145 } 1146 1147 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg)) 1148 1149 case 4: /* add $scon,[r1],r2 */ 1150 v := c.regoff(&p.From) 1151 1152 r := int(p.Reg) 1153 if r == 0 { 1154 r = int(p.To.Reg) 1155 } 1156 1157 o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg)) 1158 1159 case 5: /* syscall */ 1160 o1 = c.oprrr(p.As) 1161 1162 case 6: /* beq r1,[r2],sbra */ 1163 v := int32(0) 1164 if p.Pcond == nil { 1165 v = int32(-4) >> 2 1166 } else { 1167 v = int32(p.Pcond.Pc-p.Pc-4) >> 2 1168 } 1169 if (v<<16)>>16 != v { 1170 c.ctxt.Diag("short branch too far\n%v", p) 1171 } 1172 o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg)) 1173 // for ABFPT and ABFPF only: always fill delay slot with 0 1174 // see comments in func preprocess for details. 1175 o2 = 0 1176 1177 case 7: /* mov r, soreg ==> sw o(r) */ 1178 r := int(p.To.Reg) 1179 if r == 0 { 1180 r = int(o.param) 1181 } 1182 v := c.regoff(&p.To) 1183 o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg)) 1184 1185 case 8: /* mov soreg, r ==> lw o(r) */ 1186 r := int(p.From.Reg) 1187 if r == 0 { 1188 r = int(o.param) 1189 } 1190 v := c.regoff(&p.From) 1191 o1 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg)) 1192 1193 case 9: /* sll r1,[r2],r3 */ 1194 r := int(p.Reg) 1195 1196 if r == 0 { 1197 r = int(p.To.Reg) 1198 } 1199 o1 = OP_RRR(c.oprrr(p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg)) 1200 1201 case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */ 1202 v := c.regoff(&p.From) 1203 a := AOR 1204 if v < 0 { 1205 a = AADDU 1206 } 1207 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP)) 1208 r := int(p.Reg) 1209 if r == 0 { 1210 r = int(p.To.Reg) 1211 } 1212 o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1213 1214 case 11: /* jmp lbra */ 1215 v := int32(0) 1216 if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP { 1217 // use PC-relative branch for short branches 1218 // BEQ R0, R0, sbra 1219 if p.Pcond == nil { 1220 v = int32(-4) >> 2 1221 } else { 1222 v = int32(p.Pcond.Pc-p.Pc-4) >> 2 1223 } 1224 if (v<<16)>>16 == v { 1225 o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO)) 1226 break 1227 } 1228 } 1229 if p.Pcond == nil { 1230 v = int32(p.Pc) >> 2 1231 } else { 1232 v = int32(p.Pcond.Pc) >> 2 1233 } 1234 o1 = OP_JMP(c.opirr(p.As), uint32(v)) 1235 if p.To.Sym == nil { 1236 p.To.Sym = c.cursym.Func.Text.From.Sym 1237 p.To.Offset = p.Pcond.Pc 1238 } 1239 rel := obj.Addrel(c.cursym) 1240 rel.Off = int32(c.pc) 1241 rel.Siz = 4 1242 rel.Sym = p.To.Sym 1243 rel.Add = p.To.Offset 1244 if p.As == AJAL { 1245 rel.Type = objabi.R_CALLMIPS 1246 } else { 1247 rel.Type = objabi.R_JMPMIPS 1248 } 1249 1250 case 12: /* movbs r,r */ 1251 v := 16 1252 if p.As == AMOVB { 1253 v = 24 1254 } 1255 o1 = OP_SRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg)) 1256 o2 = OP_SRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg)) 1257 1258 case 13: /* movbu r,r */ 1259 if p.As == AMOVBU { 1260 o1 = OP_IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg)) 1261 } else { 1262 o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg)) 1263 } 1264 1265 case 14: /* movwu r,r */ 1266 o1 = OP_SRR(c.opirr(-ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg)) 1267 o2 = OP_SRR(c.opirr(-ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) 1268 1269 case 15: /* teq $c r,r */ 1270 v := c.regoff(&p.From) 1271 r := int(p.Reg) 1272 if r == 0 { 1273 r = REGZERO 1274 } 1275 /* only use 10 bits of trap code */ 1276 o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, uint32(p.Reg), uint32(p.To.Reg)) 1277 1278 case 16: /* sll $c,[r1],r2 */ 1279 v := c.regoff(&p.From) 1280 r := int(p.Reg) 1281 if r == 0 { 1282 r = int(p.To.Reg) 1283 } 1284 1285 /* OP_SRR will use only the low 5 bits of the shift value */ 1286 if v >= 32 && vshift(p.As) { 1287 o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), uint32(r), uint32(p.To.Reg)) 1288 } else { 1289 o1 = OP_SRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg)) 1290 } 1291 1292 case 17: 1293 o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg)) 1294 1295 case 18: /* jmp [r1],0(r2) */ 1296 r := int(p.Reg) 1297 if r == 0 { 1298 r = int(o.param) 1299 } 1300 o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r)) 1301 rel := obj.Addrel(c.cursym) 1302 rel.Off = int32(c.pc) 1303 rel.Siz = 0 1304 rel.Type = objabi.R_CALLIND 1305 1306 case 19: /* mov $lcon,r ==> lu+or */ 1307 v := c.regoff(&p.From) 1308 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg)) 1309 o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg)) 1310 1311 case 20: /* mov lo/hi,r */ 1312 a := OP(2, 0) /* mfhi */ 1313 if p.From.Reg == REG_LO { 1314 a = OP(2, 2) /* mflo */ 1315 } 1316 o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg)) 1317 1318 case 21: /* mov r,lo/hi */ 1319 a := OP(2, 1) /* mthi */ 1320 if p.To.Reg == REG_LO { 1321 a = OP(2, 3) /* mtlo */ 1322 } 1323 o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO)) 1324 1325 case 22: /* mul r1,r2 [r3]*/ 1326 if p.To.Reg != 0 { 1327 r := int(p.Reg) 1328 if r == 0 { 1329 r = int(p.To.Reg) 1330 } 1331 a := SP(3, 4) | 2 /* mul */ 1332 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) 1333 } else { 1334 o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO)) 1335 } 1336 1337 case 23: /* add $lcon,r1,r2 ==> lu+or+add */ 1338 v := c.regoff(&p.From) 1339 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1340 o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1341 r := int(p.Reg) 1342 if r == 0 { 1343 r = int(p.To.Reg) 1344 } 1345 o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1346 1347 case 24: /* mov $ucon,r ==> lu r */ 1348 v := c.regoff(&p.From) 1349 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg)) 1350 1351 case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */ 1352 v := c.regoff(&p.From) 1353 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1354 r := int(p.Reg) 1355 if r == 0 { 1356 r = int(p.To.Reg) 1357 } 1358 o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1359 1360 case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */ 1361 v := c.regoff(&p.From) 1362 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1363 o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1364 r := int(p.From.Reg) 1365 if r == 0 { 1366 r = int(o.param) 1367 } 1368 o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1369 1370 case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */ 1371 v := c.regoff(&p.From) 1372 r := int(p.From.Reg) 1373 if r == 0 { 1374 r = int(o.param) 1375 } 1376 a := -AMOVF 1377 if p.As == AMOVD { 1378 a = -AMOVD 1379 } 1380 switch o.size { 1381 case 12: 1382 o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP)) 1383 o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1384 o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg)) 1385 1386 case 4: 1387 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg)) 1388 } 1389 1390 case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */ 1391 v := c.regoff(&p.To) 1392 r := int(p.To.Reg) 1393 if r == 0 { 1394 r = int(o.param) 1395 } 1396 a := AMOVF 1397 if p.As == AMOVD { 1398 a = AMOVD 1399 } 1400 switch o.size { 1401 case 12: 1402 o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP)) 1403 o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1404 o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg)) 1405 1406 case 4: 1407 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg)) 1408 } 1409 1410 case 30: /* movw r,fr */ 1411 a := SP(2, 1) | (4 << 21) /* mtc1 */ 1412 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) 1413 1414 case 31: /* movw fr,r */ 1415 a := SP(2, 1) | (0 << 21) /* mtc1 */ 1416 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) 1417 1418 case 32: /* fadd fr1,[fr2],fr3 */ 1419 r := int(p.Reg) 1420 if r == 0 { 1421 r = int(p.To.Reg) 1422 } 1423 o1 = OP_FRRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) 1424 1425 case 33: /* fabs fr1, fr3 */ 1426 o1 = OP_FRRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg)) 1427 1428 case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */ 1429 v := c.regoff(&p.From) 1430 a := AADDU 1431 if o.a1 == C_ANDCON { 1432 a = AOR 1433 } 1434 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP)) 1435 o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */ 1436 1437 case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */ 1438 v := c.regoff(&p.To) 1439 r := int(p.To.Reg) 1440 if r == 0 { 1441 r = int(o.param) 1442 } 1443 o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP)) 1444 o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1445 o3 = OP_IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg)) 1446 1447 case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */ 1448 v := c.regoff(&p.From) 1449 r := int(p.From.Reg) 1450 if r == 0 { 1451 r = int(o.param) 1452 } 1453 o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP)) 1454 o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1455 o3 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg)) 1456 1457 case 37: /* movw r,mr */ 1458 a := SP(2, 0) | (4 << 21) /* mtc0 */ 1459 if p.As == AMOVV { 1460 a = SP(2, 0) | (5 << 21) /* dmtc0 */ 1461 } 1462 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) 1463 1464 case 38: /* movw mr,r */ 1465 a := SP(2, 0) | (0 << 21) /* mfc0 */ 1466 if p.As == AMOVV { 1467 a = SP(2, 0) | (1 << 21) /* dmfc0 */ 1468 } 1469 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) 1470 1471 case 40: /* word */ 1472 o1 = uint32(c.regoff(&p.From)) 1473 1474 case 41: /* movw f,fcr */ 1475 o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(REGZERO), uint32(0), uint32(p.To.Reg)) /* mfcc1 */ 1476 o2 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */ 1477 1478 case 42: /* movw fcr,r */ 1479 o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */ 1480 1481 case 47: /* movv r,fr */ 1482 a := SP(2, 1) | (5 << 21) /* dmtc1 */ 1483 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) 1484 1485 case 48: /* movv fr,r */ 1486 a := SP(2, 1) | (1 << 21) /* dmtc1 */ 1487 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) 1488 1489 case 49: /* undef */ 1490 o1 = 52 /* trap -- teq r0, r0 */ 1491 1492 /* relocation operations */ 1493 case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */ 1494 o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP)) 1495 rel := obj.Addrel(c.cursym) 1496 rel.Off = int32(c.pc) 1497 rel.Siz = 4 1498 rel.Sym = p.To.Sym 1499 rel.Add = p.To.Offset 1500 rel.Type = objabi.R_ADDRMIPSU 1501 o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg)) 1502 rel2 := obj.Addrel(c.cursym) 1503 rel2.Off = int32(c.pc + 4) 1504 rel2.Siz = 4 1505 rel2.Sym = p.To.Sym 1506 rel2.Add = p.To.Offset 1507 rel2.Type = objabi.R_ADDRMIPS 1508 1509 if o.size == 12 { 1510 o3 = o2 1511 o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP)) 1512 rel2.Off += 4 1513 } 1514 1515 case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */ 1516 o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP)) 1517 rel := obj.Addrel(c.cursym) 1518 rel.Off = int32(c.pc) 1519 rel.Siz = 4 1520 rel.Sym = p.From.Sym 1521 rel.Add = p.From.Offset 1522 rel.Type = objabi.R_ADDRMIPSU 1523 o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg)) 1524 rel2 := obj.Addrel(c.cursym) 1525 rel2.Off = int32(c.pc + 4) 1526 rel2.Siz = 4 1527 rel2.Sym = p.From.Sym 1528 rel2.Add = p.From.Offset 1529 rel2.Type = objabi.R_ADDRMIPS 1530 1531 if o.size == 12 { 1532 o3 = o2 1533 o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP)) 1534 rel2.Off += 4 1535 } 1536 1537 case 52: /* mov $lext, r ==> lu + add REGSB, r + add */ 1538 o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg)) 1539 rel := obj.Addrel(c.cursym) 1540 rel.Off = int32(c.pc) 1541 rel.Siz = 4 1542 rel.Sym = p.From.Sym 1543 rel.Add = p.From.Offset 1544 rel.Type = objabi.R_ADDRMIPSU 1545 o2 = OP_IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) 1546 rel2 := obj.Addrel(c.cursym) 1547 rel2.Off = int32(c.pc + 4) 1548 rel2.Siz = 4 1549 rel2.Sym = p.From.Sym 1550 rel2.Add = p.From.Offset 1551 rel2.Type = objabi.R_ADDRMIPS 1552 1553 if o.size == 12 { 1554 o3 = o2 1555 o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg)) 1556 rel2.Off += 4 1557 } 1558 1559 case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */ 1560 // clobbers R3 ! 1561 // load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux 1562 o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3 1563 o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg)) 1564 rel := obj.Addrel(c.cursym) 1565 rel.Off = int32(c.pc + 4) 1566 rel.Siz = 4 1567 rel.Sym = p.To.Sym 1568 rel.Add = p.To.Offset 1569 rel.Type = objabi.R_ADDRMIPSTLS 1570 1571 case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */ 1572 // clobbers R3 ! 1573 o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3 1574 o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg)) 1575 rel := obj.Addrel(c.cursym) 1576 rel.Off = int32(c.pc + 4) 1577 rel.Siz = 4 1578 rel.Sym = p.From.Sym 1579 rel.Add = p.From.Offset 1580 rel.Type = objabi.R_ADDRMIPSTLS 1581 1582 case 55: /* mov $tlsvar, r ==> rdhwr + add */ 1583 // clobbers R3 ! 1584 o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3 1585 o2 = OP_IRR(c.opirr(add), uint32(0), uint32(REG_R3), uint32(p.To.Reg)) 1586 rel := obj.Addrel(c.cursym) 1587 rel.Off = int32(c.pc + 4) 1588 rel.Siz = 4 1589 rel.Sym = p.From.Sym 1590 rel.Add = p.From.Offset 1591 rel.Type = objabi.R_ADDRMIPSTLS 1592 } 1593 1594 out[0] = o1 1595 out[1] = o2 1596 out[2] = o3 1597 out[3] = o4 1598 return 1599 } 1600 1601 func (c *ctxt0) vregoff(a *obj.Addr) int64 { 1602 c.instoffset = 0 1603 c.aclass(a) 1604 return c.instoffset 1605 } 1606 1607 func (c *ctxt0) regoff(a *obj.Addr) int32 { 1608 return int32(c.vregoff(a)) 1609 } 1610 1611 func (c *ctxt0) oprrr(a obj.As) uint32 { 1612 switch a { 1613 case AADD: 1614 return OP(4, 0) 1615 case AADDU: 1616 return OP(4, 1) 1617 case ASGT: 1618 return OP(5, 2) 1619 case ASGTU: 1620 return OP(5, 3) 1621 case AAND: 1622 return OP(4, 4) 1623 case AOR: 1624 return OP(4, 5) 1625 case AXOR: 1626 return OP(4, 6) 1627 case ASUB: 1628 return OP(4, 2) 1629 case ASUBU: 1630 return OP(4, 3) 1631 case ANOR: 1632 return OP(4, 7) 1633 case ASLL: 1634 return OP(0, 4) 1635 case ASRL: 1636 return OP(0, 6) 1637 case ASRA: 1638 return OP(0, 7) 1639 case ASLLV: 1640 return OP(2, 4) 1641 case ASRLV: 1642 return OP(2, 6) 1643 case ASRAV: 1644 return OP(2, 7) 1645 case AADDV: 1646 return OP(5, 4) 1647 case AADDVU: 1648 return OP(5, 5) 1649 case ASUBV: 1650 return OP(5, 6) 1651 case ASUBVU: 1652 return OP(5, 7) 1653 case AREM, 1654 ADIV: 1655 return OP(3, 2) 1656 case AREMU, 1657 ADIVU: 1658 return OP(3, 3) 1659 case AMUL: 1660 return OP(3, 0) 1661 case AMULU: 1662 return OP(3, 1) 1663 case AREMV, 1664 ADIVV: 1665 return OP(3, 6) 1666 case AREMVU, 1667 ADIVVU: 1668 return OP(3, 7) 1669 case AMULV: 1670 return OP(3, 4) 1671 case AMULVU: 1672 return OP(3, 5) 1673 1674 case AJMP: 1675 return OP(1, 0) 1676 case AJAL: 1677 return OP(1, 1) 1678 1679 case ABREAK: 1680 return OP(1, 5) 1681 case ASYSCALL: 1682 return OP(1, 4) 1683 case ATLBP: 1684 return MMU(1, 0) 1685 case ATLBR: 1686 return MMU(0, 1) 1687 case ATLBWI: 1688 return MMU(0, 2) 1689 case ATLBWR: 1690 return MMU(0, 6) 1691 case ARFE: 1692 return MMU(2, 0) 1693 1694 case ADIVF: 1695 return FPF(0, 3) 1696 case ADIVD: 1697 return FPD(0, 3) 1698 case AMULF: 1699 return FPF(0, 2) 1700 case AMULD: 1701 return FPD(0, 2) 1702 case ASUBF: 1703 return FPF(0, 1) 1704 case ASUBD: 1705 return FPD(0, 1) 1706 case AADDF: 1707 return FPF(0, 0) 1708 case AADDD: 1709 return FPD(0, 0) 1710 case ATRUNCFV: 1711 return FPF(1, 1) 1712 case ATRUNCDV: 1713 return FPD(1, 1) 1714 case ATRUNCFW: 1715 return FPF(1, 5) 1716 case ATRUNCDW: 1717 return FPD(1, 5) 1718 case AMOVFV: 1719 return FPF(4, 5) 1720 case AMOVDV: 1721 return FPD(4, 5) 1722 case AMOVVF: 1723 return FPV(4, 0) 1724 case AMOVVD: 1725 return FPV(4, 1) 1726 case AMOVFW: 1727 return FPF(4, 4) 1728 case AMOVDW: 1729 return FPD(4, 4) 1730 case AMOVWF: 1731 return FPW(4, 0) 1732 case AMOVDF: 1733 return FPD(4, 0) 1734 case AMOVWD: 1735 return FPW(4, 1) 1736 case AMOVFD: 1737 return FPF(4, 1) 1738 case AABSF: 1739 return FPF(0, 5) 1740 case AABSD: 1741 return FPD(0, 5) 1742 case AMOVF: 1743 return FPF(0, 6) 1744 case AMOVD: 1745 return FPD(0, 6) 1746 case ANEGF: 1747 return FPF(0, 7) 1748 case ANEGD: 1749 return FPD(0, 7) 1750 case ACMPEQF: 1751 return FPF(6, 2) 1752 case ACMPEQD: 1753 return FPD(6, 2) 1754 case ACMPGTF: 1755 return FPF(7, 4) 1756 case ACMPGTD: 1757 return FPD(7, 4) 1758 case ACMPGEF: 1759 return FPF(7, 6) 1760 case ACMPGED: 1761 return FPD(7, 6) 1762 1763 case ASQRTF: 1764 return FPF(0, 4) 1765 case ASQRTD: 1766 return FPD(0, 4) 1767 1768 case ASYNC: 1769 return OP(1, 7) 1770 case ANOOP: 1771 return 0 1772 1773 case ACMOVN: 1774 return OP(1, 3) 1775 case ACMOVZ: 1776 return OP(1, 2) 1777 case ACMOVT: 1778 return OP(0, 1) | (1 << 16) 1779 case ACMOVF: 1780 return OP(0, 1) | (0 << 16) 1781 case ACLO: 1782 return SP(3, 4) | OP(4, 1) 1783 case ACLZ: 1784 return SP(3, 4) | OP(4, 0) 1785 } 1786 1787 if a < 0 { 1788 c.ctxt.Diag("bad rrr opcode -%v", -a) 1789 } else { 1790 c.ctxt.Diag("bad rrr opcode %v", a) 1791 } 1792 return 0 1793 } 1794 1795 func (c *ctxt0) opirr(a obj.As) uint32 { 1796 switch a { 1797 case AADD: 1798 return SP(1, 0) 1799 case AADDU: 1800 return SP(1, 1) 1801 case ASGT: 1802 return SP(1, 2) 1803 case ASGTU: 1804 return SP(1, 3) 1805 case AAND: 1806 return SP(1, 4) 1807 case AOR: 1808 return SP(1, 5) 1809 case AXOR: 1810 return SP(1, 6) 1811 case ALUI: 1812 return SP(1, 7) 1813 case ASLL: 1814 return OP(0, 0) 1815 case ASRL: 1816 return OP(0, 2) 1817 case ASRA: 1818 return OP(0, 3) 1819 case AADDV: 1820 return SP(3, 0) 1821 case AADDVU: 1822 return SP(3, 1) 1823 1824 case AJMP: 1825 return SP(0, 2) 1826 case AJAL, 1827 obj.ADUFFZERO, 1828 obj.ADUFFCOPY: 1829 return SP(0, 3) 1830 case ABEQ: 1831 return SP(0, 4) 1832 case -ABEQ: 1833 return SP(2, 4) /* likely */ 1834 case ABNE: 1835 return SP(0, 5) 1836 case -ABNE: 1837 return SP(2, 5) /* likely */ 1838 case ABGEZ: 1839 return SP(0, 1) | BCOND(0, 1) 1840 case -ABGEZ: 1841 return SP(0, 1) | BCOND(0, 3) /* likely */ 1842 case ABGEZAL: 1843 return SP(0, 1) | BCOND(2, 1) 1844 case -ABGEZAL: 1845 return SP(0, 1) | BCOND(2, 3) /* likely */ 1846 case ABGTZ: 1847 return SP(0, 7) 1848 case -ABGTZ: 1849 return SP(2, 7) /* likely */ 1850 case ABLEZ: 1851 return SP(0, 6) 1852 case -ABLEZ: 1853 return SP(2, 6) /* likely */ 1854 case ABLTZ: 1855 return SP(0, 1) | BCOND(0, 0) 1856 case -ABLTZ: 1857 return SP(0, 1) | BCOND(0, 2) /* likely */ 1858 case ABLTZAL: 1859 return SP(0, 1) | BCOND(2, 0) 1860 case -ABLTZAL: 1861 return SP(0, 1) | BCOND(2, 2) /* likely */ 1862 case ABFPT: 1863 return SP(2, 1) | (257 << 16) 1864 case -ABFPT: 1865 return SP(2, 1) | (259 << 16) /* likely */ 1866 case ABFPF: 1867 return SP(2, 1) | (256 << 16) 1868 case -ABFPF: 1869 return SP(2, 1) | (258 << 16) /* likely */ 1870 1871 case AMOVB, 1872 AMOVBU: 1873 return SP(5, 0) 1874 case AMOVH, 1875 AMOVHU: 1876 return SP(5, 1) 1877 case AMOVW, 1878 AMOVWU: 1879 return SP(5, 3) 1880 case AMOVV: 1881 return SP(7, 7) 1882 case AMOVF: 1883 return SP(7, 1) 1884 case AMOVD: 1885 return SP(7, 5) 1886 case AMOVWL: 1887 return SP(5, 2) 1888 case AMOVWR: 1889 return SP(5, 6) 1890 case AMOVVL: 1891 return SP(5, 4) 1892 case AMOVVR: 1893 return SP(5, 5) 1894 1895 case ABREAK: 1896 return SP(5, 7) 1897 1898 case -AMOVWL: 1899 return SP(4, 2) 1900 case -AMOVWR: 1901 return SP(4, 6) 1902 case -AMOVVL: 1903 return SP(3, 2) 1904 case -AMOVVR: 1905 return SP(3, 3) 1906 case -AMOVB: 1907 return SP(4, 0) 1908 case -AMOVBU: 1909 return SP(4, 4) 1910 case -AMOVH: 1911 return SP(4, 1) 1912 case -AMOVHU: 1913 return SP(4, 5) 1914 case -AMOVW: 1915 return SP(4, 3) 1916 case -AMOVWU: 1917 return SP(4, 7) 1918 case -AMOVV: 1919 return SP(6, 7) 1920 case -AMOVF: 1921 return SP(6, 1) 1922 case -AMOVD: 1923 return SP(6, 5) 1924 1925 case ASLLV: 1926 return OP(7, 0) 1927 case ASRLV: 1928 return OP(7, 2) 1929 case ASRAV: 1930 return OP(7, 3) 1931 case -ASLLV: 1932 return OP(7, 4) 1933 case -ASRLV: 1934 return OP(7, 6) 1935 case -ASRAV: 1936 return OP(7, 7) 1937 1938 case ATEQ: 1939 return OP(6, 4) 1940 case ATNE: 1941 return OP(6, 6) 1942 case -ALL: 1943 return SP(6, 0) 1944 case -ALLV: 1945 return SP(6, 4) 1946 case ASC: 1947 return SP(7, 0) 1948 case ASCV: 1949 return SP(7, 4) 1950 } 1951 1952 if a < 0 { 1953 c.ctxt.Diag("bad irr opcode -%v", -a) 1954 } else { 1955 c.ctxt.Diag("bad irr opcode %v", a) 1956 } 1957 return 0 1958 } 1959 1960 func vshift(a obj.As) bool { 1961 switch a { 1962 case ASLLV, 1963 ASRLV, 1964 ASRAV: 1965 return true 1966 } 1967 return false 1968 }