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