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