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