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 30package mips 31 32import ( 33 "cmd/internal/obj" 34 "cmd/internal/objabi" 35 "cmd/internal/sys" 36 "fmt" 37 "log" 38 "sort" 39) 40 41// ctxt0 holds state while assembling a single function. 42// Each function gets a fresh ctxt0. 43// This allows for multiple functions to be safely concurrently assembled. 44type 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 55const ( 56 mips64FuncAlign = 8 57) 58 59const ( 60 r0iszero = 1 61) 62 63type 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 75const ( 76 // Optab.flag 77 NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP 78) 79 80var 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 403var oprange [ALAST & obj.AMask][]Optab 404 405var xcmp [C_NCLASS][C_NCLASS]bool 406 407func 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. 536func (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. 544func (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 559func isint32(v int64) bool { 560 return int64(int32(v)) == v 561} 562 563func isuint32(v uint64) bool { 564 return uint64(uint32(v)) == v 565} 566 567func (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 745func prasm(p *obj.Prog) { 746 fmt.Printf("%v\n", p) 747} 748 749func (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 794func 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 875type ocmp []Optab 876 877func (x ocmp) Len() int { 878 return len(x) 879} 880 881func (x ocmp) Swap(i, j int) { 882 x[i], x[j] = x[j], x[i] 883} 884 885func (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 907func opset(a, b0 obj.As) { 908 oprange[a&obj.AMask] = oprange[b0] 909} 910 911func 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 opset(AROTR, r0) 1026 1027 case ASLLV: 1028 opset(ASRAV, r0) 1029 opset(ASRLV, r0) 1030 opset(AROTRV, r0) 1031 1032 case ASUB: 1033 opset(ASUBU, r0) 1034 opset(ANOR, r0) 1035 1036 case ASUBV: 1037 opset(ASUBVU, r0) 1038 1039 case ASYSCALL: 1040 opset(ASYNC, r0) 1041 opset(ANOOP, r0) 1042 opset(ATLBP, r0) 1043 opset(ATLBR, r0) 1044 opset(ATLBWI, r0) 1045 opset(ATLBWR, r0) 1046 1047 case ACMPEQF: 1048 opset(ACMPGTF, r0) 1049 opset(ACMPGTD, r0) 1050 opset(ACMPGEF, r0) 1051 opset(ACMPGED, r0) 1052 opset(ACMPEQD, r0) 1053 1054 case ABFPT: 1055 opset(ABFPF, r0) 1056 1057 case AMOVWL: 1058 opset(AMOVWR, r0) 1059 1060 case AMOVVL: 1061 opset(AMOVVR, r0) 1062 1063 case AVMOVB: 1064 opset(AVMOVH, r0) 1065 opset(AVMOVW, r0) 1066 opset(AVMOVD, r0) 1067 1068 case AMOVW, 1069 AMOVD, 1070 AMOVF, 1071 AMOVV, 1072 ABREAK, 1073 ARFE, 1074 AJAL, 1075 AJMP, 1076 AMOVWU, 1077 ALL, 1078 ALLV, 1079 ASC, 1080 ASCV, 1081 ANEGW, 1082 ANEGV, 1083 AWORD, 1084 obj.ANOP, 1085 obj.ATEXT, 1086 obj.AUNDEF, 1087 obj.AFUNCDATA, 1088 obj.APCDATA, 1089 obj.ADUFFZERO, 1090 obj.ADUFFCOPY: 1091 break 1092 1093 case ACMOVN: 1094 opset(ACMOVZ, r0) 1095 1096 case ACMOVT: 1097 opset(ACMOVF, r0) 1098 1099 case ACLO: 1100 opset(ACLZ, r0) 1101 1102 case ATEQ: 1103 opset(ATNE, r0) 1104 } 1105 } 1106} 1107 1108func OP(x uint32, y uint32) uint32 { 1109 return x<<3 | y<<0 1110} 1111 1112func SP(x uint32, y uint32) uint32 { 1113 return x<<29 | y<<26 1114} 1115 1116func BCOND(x uint32, y uint32) uint32 { 1117 return x<<19 | y<<16 1118} 1119 1120func MMU(x uint32, y uint32) uint32 { 1121 return SP(2, 0) | 16<<21 | x<<3 | y<<0 1122} 1123 1124func FPF(x uint32, y uint32) uint32 { 1125 return SP(2, 1) | 16<<21 | x<<3 | y<<0 1126} 1127 1128func FPD(x uint32, y uint32) uint32 { 1129 return SP(2, 1) | 17<<21 | x<<3 | y<<0 1130} 1131 1132func FPW(x uint32, y uint32) uint32 { 1133 return SP(2, 1) | 20<<21 | x<<3 | y<<0 1134} 1135 1136func FPV(x uint32, y uint32) uint32 { 1137 return SP(2, 1) | 21<<21 | x<<3 | y<<0 1138} 1139 1140func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 { 1141 return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11 1142} 1143 1144func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 { 1145 return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16 1146} 1147 1148func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 { 1149 return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11 1150} 1151 1152func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 { 1153 return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6 1154} 1155 1156func OP_JMP(op uint32, i uint32) uint32 { 1157 return op | i&0x3FFFFFF 1158} 1159 1160func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 { 1161 return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F 1162} 1163 1164func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 { 1165 return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3 1166} 1167 1168func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) { 1169 o1 := uint32(0) 1170 o2 := uint32(0) 1171 o3 := uint32(0) 1172 o4 := uint32(0) 1173 1174 add := AADDU 1175 1176 if c.ctxt.Arch.Family == sys.MIPS64 { 1177 add = AADDVU 1178 } 1179 switch o.type_ { 1180 default: 1181 c.ctxt.Diag("unknown type %d %v", o.type_) 1182 prasm(p) 1183 1184 case 0: /* pseudo ops */ 1185 break 1186 1187 case 1: /* mov r1,r2 ==> OR r1,r0,r2 */ 1188 a := AOR 1189 if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 { 1190 // on MIPS64, most of the 32-bit instructions have unpredictable behavior, 1191 // but SLL is special that the result is always sign-extended to 64-bit. 1192 a = ASLL 1193 } 1194 o1 = OP_RRR(c.oprrr(a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg)) 1195 1196 case 2: /* add/sub r1,[r2],r3 */ 1197 r := int(p.Reg) 1198 if p.As == ANEGW || p.As == ANEGV { 1199 r = REGZERO 1200 } 1201 if r == 0 { 1202 r = int(p.To.Reg) 1203 } 1204 o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) 1205 1206 case 3: /* mov $soreg, r ==> or/add $i,o,r */ 1207 v := c.regoff(&p.From) 1208 1209 r := int(p.From.Reg) 1210 if r == 0 { 1211 r = int(o.param) 1212 } 1213 a := add 1214 if o.a1 == C_ANDCON { 1215 a = AOR 1216 } 1217 1218 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg)) 1219 1220 case 4: /* add $scon,[r1],r2 */ 1221 v := c.regoff(&p.From) 1222 1223 r := int(p.Reg) 1224 if r == 0 { 1225 r = int(p.To.Reg) 1226 } 1227 1228 o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg)) 1229 1230 case 5: /* syscall */ 1231 o1 = c.oprrr(p.As) 1232 1233 case 6: /* beq r1,[r2],sbra */ 1234 v := int32(0) 1235 if p.To.Target() == nil { 1236 v = int32(-4) >> 2 1237 } else { 1238 v = int32(p.To.Target().Pc-p.Pc-4) >> 2 1239 } 1240 if (v<<16)>>16 != v { 1241 c.ctxt.Diag("short branch too far\n%v", p) 1242 } 1243 o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg)) 1244 // for ABFPT and ABFPF only: always fill delay slot with 0 1245 // see comments in func preprocess for details. 1246 o2 = 0 1247 1248 case 7: /* mov r, soreg ==> sw o(r) */ 1249 r := int(p.To.Reg) 1250 if r == 0 { 1251 r = int(o.param) 1252 } 1253 v := c.regoff(&p.To) 1254 o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg)) 1255 1256 case 8: /* mov soreg, r ==> lw o(r) */ 1257 r := int(p.From.Reg) 1258 if r == 0 { 1259 r = int(o.param) 1260 } 1261 v := c.regoff(&p.From) 1262 o1 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg)) 1263 1264 case 9: /* sll r1,[r2],r3 */ 1265 r := int(p.Reg) 1266 1267 if r == 0 { 1268 r = int(p.To.Reg) 1269 } 1270 o1 = OP_RRR(c.oprrr(p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg)) 1271 1272 case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */ 1273 v := c.regoff(&p.From) 1274 a := AOR 1275 if v < 0 { 1276 a = AADDU 1277 } 1278 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP)) 1279 r := int(p.Reg) 1280 if r == 0 { 1281 r = int(p.To.Reg) 1282 } 1283 o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1284 1285 case 11: /* jmp lbra */ 1286 v := int32(0) 1287 if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP { 1288 // use PC-relative branch for short branches 1289 // BEQ R0, R0, sbra 1290 if p.To.Target() == nil { 1291 v = int32(-4) >> 2 1292 } else { 1293 v = int32(p.To.Target().Pc-p.Pc-4) >> 2 1294 } 1295 if (v<<16)>>16 == v { 1296 o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO)) 1297 break 1298 } 1299 } 1300 if p.To.Target() == nil { 1301 v = int32(p.Pc) >> 2 1302 } else { 1303 v = int32(p.To.Target().Pc) >> 2 1304 } 1305 o1 = OP_JMP(c.opirr(p.As), uint32(v)) 1306 if p.To.Sym == nil { 1307 p.To.Sym = c.cursym.Func().Text.From.Sym 1308 p.To.Offset = p.To.Target().Pc 1309 } 1310 rel := obj.Addrel(c.cursym) 1311 rel.Off = int32(c.pc) 1312 rel.Siz = 4 1313 rel.Sym = p.To.Sym 1314 rel.Add = p.To.Offset 1315 if p.As == AJAL { 1316 rel.Type = objabi.R_CALLMIPS 1317 } else { 1318 rel.Type = objabi.R_JMPMIPS 1319 } 1320 1321 case 12: /* movbs r,r */ 1322 // NOTE: this case does not use REGTMP. If it ever does, 1323 // remove the NOTUSETMP flag in optab. 1324 v := 16 1325 if p.As == AMOVB { 1326 v = 24 1327 } 1328 o1 = OP_SRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg)) 1329 o2 = OP_SRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg)) 1330 1331 case 13: /* movbu r,r */ 1332 if p.As == AMOVBU { 1333 o1 = OP_IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg)) 1334 } else { 1335 o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg)) 1336 } 1337 1338 case 14: /* movwu r,r */ 1339 // NOTE: this case does not use REGTMP. If it ever does, 1340 // remove the NOTUSETMP flag in optab. 1341 o1 = OP_SRR(c.opirr(-ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg)) 1342 o2 = OP_SRR(c.opirr(-ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) 1343 1344 case 15: /* teq $c r,r */ 1345 v := c.regoff(&p.From) 1346 r := int(p.Reg) 1347 if r == 0 { 1348 r = REGZERO 1349 } 1350 /* only use 10 bits of trap code */ 1351 o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, uint32(r), uint32(p.To.Reg)) 1352 1353 case 16: /* sll $c,[r1],r2 */ 1354 v := c.regoff(&p.From) 1355 r := int(p.Reg) 1356 if r == 0 { 1357 r = int(p.To.Reg) 1358 } 1359 1360 /* OP_SRR will use only the low 5 bits of the shift value */ 1361 if v >= 32 && vshift(p.As) { 1362 o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), uint32(r), uint32(p.To.Reg)) 1363 } else { 1364 o1 = OP_SRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg)) 1365 } 1366 1367 case 17: 1368 o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg)) 1369 1370 case 18: /* jmp [r1],0(r2) */ 1371 r := int(p.Reg) 1372 if r == 0 { 1373 r = int(o.param) 1374 } 1375 o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r)) 1376 if p.As == obj.ACALL { 1377 rel := obj.Addrel(c.cursym) 1378 rel.Off = int32(c.pc) 1379 rel.Siz = 0 1380 rel.Type = objabi.R_CALLIND 1381 } 1382 1383 case 19: /* mov $lcon,r ==> lu+or */ 1384 // NOTE: this case does not use REGTMP. If it ever does, 1385 // remove the NOTUSETMP flag in optab. 1386 v := c.regoff(&p.From) 1387 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg)) 1388 o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg)) 1389 1390 case 20: /* mov lo/hi,r */ 1391 a := OP(2, 0) /* mfhi */ 1392 if p.From.Reg == REG_LO { 1393 a = OP(2, 2) /* mflo */ 1394 } 1395 o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg)) 1396 1397 case 21: /* mov r,lo/hi */ 1398 a := OP(2, 1) /* mthi */ 1399 if p.To.Reg == REG_LO { 1400 a = OP(2, 3) /* mtlo */ 1401 } 1402 o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO)) 1403 1404 case 22: /* mul r1,r2 [r3]*/ 1405 if p.To.Reg != 0 { 1406 r := int(p.Reg) 1407 if r == 0 { 1408 r = int(p.To.Reg) 1409 } 1410 a := SP(3, 4) | 2 /* mul */ 1411 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) 1412 } else { 1413 o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO)) 1414 } 1415 1416 case 23: /* add $lcon,r1,r2 ==> lu+or+add */ 1417 v := c.regoff(&p.From) 1418 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1419 o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1420 r := int(p.Reg) 1421 if r == 0 { 1422 r = int(p.To.Reg) 1423 } 1424 o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1425 1426 case 24: /* mov $ucon,r ==> lu r */ 1427 v := c.regoff(&p.From) 1428 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg)) 1429 1430 case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */ 1431 v := c.regoff(&p.From) 1432 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1433 r := int(p.Reg) 1434 if r == 0 { 1435 r = int(p.To.Reg) 1436 } 1437 o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1438 1439 case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */ 1440 v := c.regoff(&p.From) 1441 o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP)) 1442 o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP)) 1443 r := int(p.From.Reg) 1444 if r == 0 { 1445 r = int(o.param) 1446 } 1447 o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg)) 1448 1449 case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */ 1450 v := c.regoff(&p.From) 1451 r := int(p.From.Reg) 1452 if r == 0 { 1453 r = int(o.param) 1454 } 1455 a := -AMOVF 1456 if p.As == AMOVD { 1457 a = -AMOVD 1458 } 1459 switch o.size { 1460 case 12: 1461 o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP)) 1462 o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1463 o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg)) 1464 1465 case 4: 1466 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg)) 1467 } 1468 1469 case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */ 1470 v := c.regoff(&p.To) 1471 r := int(p.To.Reg) 1472 if r == 0 { 1473 r = int(o.param) 1474 } 1475 a := AMOVF 1476 if p.As == AMOVD { 1477 a = AMOVD 1478 } 1479 switch o.size { 1480 case 12: 1481 o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP)) 1482 o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1483 o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg)) 1484 1485 case 4: 1486 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg)) 1487 } 1488 1489 case 30: /* movw r,fr */ 1490 a := SP(2, 1) | (4 << 21) /* mtc1 */ 1491 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) 1492 1493 case 31: /* movw fr,r */ 1494 a := SP(2, 1) | (0 << 21) /* mtc1 */ 1495 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) 1496 1497 case 32: /* fadd fr1,[fr2],fr3 */ 1498 r := int(p.Reg) 1499 if r == 0 { 1500 r = int(p.To.Reg) 1501 } 1502 o1 = OP_FRRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg)) 1503 1504 case 33: /* fabs fr1, fr3 */ 1505 o1 = OP_FRRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg)) 1506 1507 case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */ 1508 v := c.regoff(&p.From) 1509 a := AADDU 1510 if o.a1 == C_ANDCON { 1511 a = AOR 1512 } 1513 o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP)) 1514 o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */ 1515 1516 case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */ 1517 v := c.regoff(&p.To) 1518 r := int(p.To.Reg) 1519 if r == 0 { 1520 r = int(o.param) 1521 } 1522 o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP)) 1523 o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1524 o3 = OP_IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg)) 1525 1526 case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */ 1527 v := c.regoff(&p.From) 1528 r := int(p.From.Reg) 1529 if r == 0 { 1530 r = int(o.param) 1531 } 1532 o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP)) 1533 o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP)) 1534 o3 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg)) 1535 1536 case 37: /* movw r,mr */ 1537 a := SP(2, 0) | (4 << 21) /* mtc0 */ 1538 if p.As == AMOVV { 1539 a = SP(2, 0) | (5 << 21) /* dmtc0 */ 1540 } 1541 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) 1542 1543 case 38: /* movw mr,r */ 1544 a := SP(2, 0) | (0 << 21) /* mfc0 */ 1545 if p.As == AMOVV { 1546 a = SP(2, 0) | (1 << 21) /* dmfc0 */ 1547 } 1548 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) 1549 1550 case 40: /* word */ 1551 o1 = uint32(c.regoff(&p.From)) 1552 1553 case 41: /* movw f,fcr */ 1554 o1 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */ 1555 1556 case 42: /* movw fcr,r */ 1557 o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */ 1558 1559 case 47: /* movv r,fr */ 1560 a := SP(2, 1) | (5 << 21) /* dmtc1 */ 1561 o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) 1562 1563 case 48: /* movv fr,r */ 1564 a := SP(2, 1) | (1 << 21) /* dmtc1 */ 1565 o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) 1566 1567 case 49: /* undef */ 1568 o1 = 52 /* trap -- teq r0, r0 */ 1569 1570 /* relocation operations */ 1571 case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */ 1572 o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP)) 1573 rel := obj.Addrel(c.cursym) 1574 rel.Off = int32(c.pc) 1575 rel.Siz = 4 1576 rel.Sym = p.To.Sym 1577 rel.Add = p.To.Offset 1578 rel.Type = objabi.R_ADDRMIPSU 1579 o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg)) 1580 rel2 := obj.Addrel(c.cursym) 1581 rel2.Off = int32(c.pc + 4) 1582 rel2.Siz = 4 1583 rel2.Sym = p.To.Sym 1584 rel2.Add = p.To.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(REGTMP), uint32(REGTMP)) 1590 rel2.Off += 4 1591 } 1592 1593 case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */ 1594 o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP)) 1595 rel := obj.Addrel(c.cursym) 1596 rel.Off = int32(c.pc) 1597 rel.Siz = 4 1598 rel.Sym = p.From.Sym 1599 rel.Add = p.From.Offset 1600 rel.Type = objabi.R_ADDRMIPSU 1601 o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg)) 1602 rel2 := obj.Addrel(c.cursym) 1603 rel2.Off = int32(c.pc + 4) 1604 rel2.Siz = 4 1605 rel2.Sym = p.From.Sym 1606 rel2.Add = p.From.Offset 1607 rel2.Type = objabi.R_ADDRMIPS 1608 1609 if o.size == 12 { 1610 o3 = o2 1611 o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP)) 1612 rel2.Off += 4 1613 } 1614 1615 case 52: /* mov $lext, r ==> lu + add REGSB, r + add */ 1616 // NOTE: this case does not use REGTMP. If it ever does, 1617 // remove the NOTUSETMP flag in optab. 1618 o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg)) 1619 rel := obj.Addrel(c.cursym) 1620 rel.Off = int32(c.pc) 1621 rel.Siz = 4 1622 rel.Sym = p.From.Sym 1623 rel.Add = p.From.Offset 1624 rel.Type = objabi.R_ADDRMIPSU 1625 o2 = OP_IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg)) 1626 rel2 := obj.Addrel(c.cursym) 1627 rel2.Off = int32(c.pc + 4) 1628 rel2.Siz = 4 1629 rel2.Sym = p.From.Sym 1630 rel2.Add = p.From.Offset 1631 rel2.Type = objabi.R_ADDRMIPS 1632 1633 if o.size == 12 { 1634 o3 = o2 1635 o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg)) 1636 rel2.Off += 4 1637 } 1638 1639 case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */ 1640 // clobbers R3 ! 1641 // load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux 1642 // NOTE: this case does not use REGTMP. If it ever does, 1643 // remove the NOTUSETMP flag in optab. 1644 o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3 1645 o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg)) 1646 rel := obj.Addrel(c.cursym) 1647 rel.Off = int32(c.pc + 4) 1648 rel.Siz = 4 1649 rel.Sym = p.To.Sym 1650 rel.Add = p.To.Offset 1651 rel.Type = objabi.R_ADDRMIPSTLS 1652 1653 case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */ 1654 // clobbers R3 ! 1655 // NOTE: this case does not use REGTMP. If it ever does, 1656 // remove the NOTUSETMP flag in optab. 1657 o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3 1658 o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg)) 1659 rel := obj.Addrel(c.cursym) 1660 rel.Off = int32(c.pc + 4) 1661 rel.Siz = 4 1662 rel.Sym = p.From.Sym 1663 rel.Add = p.From.Offset 1664 rel.Type = objabi.R_ADDRMIPSTLS 1665 1666 case 55: /* mov $tlsvar, r ==> rdhwr + add */ 1667 // clobbers R3 ! 1668 // NOTE: this case does not use REGTMP. If it ever does, 1669 // remove the NOTUSETMP flag in optab. 1670 o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3 1671 o2 = OP_IRR(c.opirr(add), uint32(0), uint32(REG_R3), uint32(p.To.Reg)) 1672 rel := obj.Addrel(c.cursym) 1673 rel.Off = int32(c.pc + 4) 1674 rel.Siz = 4 1675 rel.Sym = p.From.Sym 1676 rel.Add = p.From.Offset 1677 rel.Type = objabi.R_ADDRMIPSTLS 1678 1679 case 56: /* vmov{b,h,w,d} $scon, wr */ 1680 1681 v := c.regoff(&p.From) 1682 o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7) 1683 1684 case 57: /* vld $soreg, wr */ 1685 v := c.lsoffset(p.As, c.regoff(&p.From)) 1686 o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As)) 1687 1688 case 58: /* vst wr, $soreg */ 1689 v := c.lsoffset(p.As, c.regoff(&p.To)) 1690 o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As)) 1691 } 1692 1693 out[0] = o1 1694 out[1] = o2 1695 out[2] = o3 1696 out[3] = o4 1697} 1698 1699func (c *ctxt0) vregoff(a *obj.Addr) int64 { 1700 c.instoffset = 0 1701 c.aclass(a) 1702 return c.instoffset 1703} 1704 1705func (c *ctxt0) regoff(a *obj.Addr) int32 { 1706 return int32(c.vregoff(a)) 1707} 1708 1709func (c *ctxt0) oprrr(a obj.As) uint32 { 1710 switch a { 1711 case AADD: 1712 return OP(4, 0) 1713 case AADDU: 1714 return OP(4, 1) 1715 case ASGT: 1716 return OP(5, 2) 1717 case ASGTU: 1718 return OP(5, 3) 1719 case AAND: 1720 return OP(4, 4) 1721 case AOR: 1722 return OP(4, 5) 1723 case AXOR: 1724 return OP(4, 6) 1725 case ASUB: 1726 return OP(4, 2) 1727 case ASUBU, ANEGW: 1728 return OP(4, 3) 1729 case ANOR: 1730 return OP(4, 7) 1731 case ASLL: 1732 return OP(0, 4) 1733 case ASRL: 1734 return OP(0, 6) 1735 case ASRA: 1736 return OP(0, 7) 1737 case AROTR: 1738 return OP(8, 6) 1739 case ASLLV: 1740 return OP(2, 4) 1741 case ASRLV: 1742 return OP(2, 6) 1743 case ASRAV: 1744 return OP(2, 7) 1745 case AROTRV: 1746 return OP(10, 6) 1747 case AADDV: 1748 return OP(5, 4) 1749 case AADDVU: 1750 return OP(5, 5) 1751 case ASUBV: 1752 return OP(5, 6) 1753 case ASUBVU, ANEGV: 1754 return OP(5, 7) 1755 case AREM, 1756 ADIV: 1757 return OP(3, 2) 1758 case AREMU, 1759 ADIVU: 1760 return OP(3, 3) 1761 case AMUL: 1762 return OP(3, 0) 1763 case AMULU: 1764 return OP(3, 1) 1765 case AREMV, 1766 ADIVV: 1767 return OP(3, 6) 1768 case AREMVU, 1769 ADIVVU: 1770 return OP(3, 7) 1771 case AMULV: 1772 return OP(3, 4) 1773 case AMULVU: 1774 return OP(3, 5) 1775 1776 case AJMP: 1777 return OP(1, 0) 1778 case AJAL: 1779 return OP(1, 1) 1780 1781 case ABREAK: 1782 return OP(1, 5) 1783 case ASYSCALL: 1784 return OP(1, 4) 1785 case ATLBP: 1786 return MMU(1, 0) 1787 case ATLBR: 1788 return MMU(0, 1) 1789 case ATLBWI: 1790 return MMU(0, 2) 1791 case ATLBWR: 1792 return MMU(0, 6) 1793 case ARFE: 1794 return MMU(2, 0) 1795 1796 case ADIVF: 1797 return FPF(0, 3) 1798 case ADIVD: 1799 return FPD(0, 3) 1800 case AMULF: 1801 return FPF(0, 2) 1802 case AMULD: 1803 return FPD(0, 2) 1804 case ASUBF: 1805 return FPF(0, 1) 1806 case ASUBD: 1807 return FPD(0, 1) 1808 case AADDF: 1809 return FPF(0, 0) 1810 case AADDD: 1811 return FPD(0, 0) 1812 case ATRUNCFV: 1813 return FPF(1, 1) 1814 case ATRUNCDV: 1815 return FPD(1, 1) 1816 case ATRUNCFW: 1817 return FPF(1, 5) 1818 case ATRUNCDW: 1819 return FPD(1, 5) 1820 case AMOVFV: 1821 return FPF(4, 5) 1822 case AMOVDV: 1823 return FPD(4, 5) 1824 case AMOVVF: 1825 return FPV(4, 0) 1826 case AMOVVD: 1827 return FPV(4, 1) 1828 case AMOVFW: 1829 return FPF(4, 4) 1830 case AMOVDW: 1831 return FPD(4, 4) 1832 case AMOVWF: 1833 return FPW(4, 0) 1834 case AMOVDF: 1835 return FPD(4, 0) 1836 case AMOVWD: 1837 return FPW(4, 1) 1838 case AMOVFD: 1839 return FPF(4, 1) 1840 case AABSF: 1841 return FPF(0, 5) 1842 case AABSD: 1843 return FPD(0, 5) 1844 case AMOVF: 1845 return FPF(0, 6) 1846 case AMOVD: 1847 return FPD(0, 6) 1848 case ANEGF: 1849 return FPF(0, 7) 1850 case ANEGD: 1851 return FPD(0, 7) 1852 case ACMPEQF: 1853 return FPF(6, 2) 1854 case ACMPEQD: 1855 return FPD(6, 2) 1856 case ACMPGTF: 1857 return FPF(7, 4) 1858 case ACMPGTD: 1859 return FPD(7, 4) 1860 case ACMPGEF: 1861 return FPF(7, 6) 1862 case ACMPGED: 1863 return FPD(7, 6) 1864 1865 case ASQRTF: 1866 return FPF(0, 4) 1867 case ASQRTD: 1868 return FPD(0, 4) 1869 1870 case ASYNC: 1871 return OP(1, 7) 1872 case ANOOP: 1873 return 0 1874 1875 case ACMOVN: 1876 return OP(1, 3) 1877 case ACMOVZ: 1878 return OP(1, 2) 1879 case ACMOVT: 1880 return OP(0, 1) | (1 << 16) 1881 case ACMOVF: 1882 return OP(0, 1) | (0 << 16) 1883 case ACLO: 1884 return SP(3, 4) | OP(4, 1) 1885 case ACLZ: 1886 return SP(3, 4) | OP(4, 0) 1887 case AMADD: 1888 return SP(3, 4) | OP(0, 0) 1889 case AMSUB: 1890 return SP(3, 4) | OP(0, 4) 1891 } 1892 1893 if a < 0 { 1894 c.ctxt.Diag("bad rrr opcode -%v", -a) 1895 } else { 1896 c.ctxt.Diag("bad rrr opcode %v", a) 1897 } 1898 return 0 1899} 1900 1901func (c *ctxt0) opirr(a obj.As) uint32 { 1902 switch a { 1903 case AADD: 1904 return SP(1, 0) 1905 case AADDU: 1906 return SP(1, 1) 1907 case ASGT: 1908 return SP(1, 2) 1909 case ASGTU: 1910 return SP(1, 3) 1911 case AAND: 1912 return SP(1, 4) 1913 case AOR: 1914 return SP(1, 5) 1915 case AXOR: 1916 return SP(1, 6) 1917 case ALUI: 1918 return SP(1, 7) 1919 case ASLL: 1920 return OP(0, 0) 1921 case ASRL: 1922 return OP(0, 2) 1923 case ASRA: 1924 return OP(0, 3) 1925 case AROTR: 1926 return OP(0, 2) | 1<<21 1927 case AADDV: 1928 return SP(3, 0) 1929 case AADDVU: 1930 return SP(3, 1) 1931 1932 case AJMP: 1933 return SP(0, 2) 1934 case AJAL, 1935 obj.ADUFFZERO, 1936 obj.ADUFFCOPY: 1937 return SP(0, 3) 1938 case ABEQ: 1939 return SP(0, 4) 1940 case -ABEQ: 1941 return SP(2, 4) /* likely */ 1942 case ABNE: 1943 return SP(0, 5) 1944 case -ABNE: 1945 return SP(2, 5) /* likely */ 1946 case ABGEZ: 1947 return SP(0, 1) | BCOND(0, 1) 1948 case -ABGEZ: 1949 return SP(0, 1) | BCOND(0, 3) /* likely */ 1950 case ABGEZAL: 1951 return SP(0, 1) | BCOND(2, 1) 1952 case -ABGEZAL: 1953 return SP(0, 1) | BCOND(2, 3) /* likely */ 1954 case ABGTZ: 1955 return SP(0, 7) 1956 case -ABGTZ: 1957 return SP(2, 7) /* likely */ 1958 case ABLEZ: 1959 return SP(0, 6) 1960 case -ABLEZ: 1961 return SP(2, 6) /* likely */ 1962 case ABLTZ: 1963 return SP(0, 1) | BCOND(0, 0) 1964 case -ABLTZ: 1965 return SP(0, 1) | BCOND(0, 2) /* likely */ 1966 case ABLTZAL: 1967 return SP(0, 1) | BCOND(2, 0) 1968 case -ABLTZAL: 1969 return SP(0, 1) | BCOND(2, 2) /* likely */ 1970 case ABFPT: 1971 return SP(2, 1) | (257 << 16) 1972 case -ABFPT: 1973 return SP(2, 1) | (259 << 16) /* likely */ 1974 case ABFPF: 1975 return SP(2, 1) | (256 << 16) 1976 case -ABFPF: 1977 return SP(2, 1) | (258 << 16) /* likely */ 1978 1979 case AMOVB, 1980 AMOVBU: 1981 return SP(5, 0) 1982 case AMOVH, 1983 AMOVHU: 1984 return SP(5, 1) 1985 case AMOVW, 1986 AMOVWU: 1987 return SP(5, 3) 1988 case AMOVV: 1989 return SP(7, 7) 1990 case AMOVF: 1991 return SP(7, 1) 1992 case AMOVD: 1993 return SP(7, 5) 1994 case AMOVWL: 1995 return SP(5, 2) 1996 case AMOVWR: 1997 return SP(5, 6) 1998 case AMOVVL: 1999 return SP(5, 4) 2000 case AMOVVR: 2001 return SP(5, 5) 2002 2003 case ABREAK: 2004 return SP(5, 7) 2005 2006 case -AMOVWL: 2007 return SP(4, 2) 2008 case -AMOVWR: 2009 return SP(4, 6) 2010 case -AMOVVL: 2011 return SP(3, 2) 2012 case -AMOVVR: 2013 return SP(3, 3) 2014 case -AMOVB: 2015 return SP(4, 0) 2016 case -AMOVBU: 2017 return SP(4, 4) 2018 case -AMOVH: 2019 return SP(4, 1) 2020 case -AMOVHU: 2021 return SP(4, 5) 2022 case -AMOVW: 2023 return SP(4, 3) 2024 case -AMOVWU: 2025 return SP(4, 7) 2026 case -AMOVV: 2027 return SP(6, 7) 2028 case -AMOVF: 2029 return SP(6, 1) 2030 case -AMOVD: 2031 return SP(6, 5) 2032 2033 case ASLLV: 2034 return OP(7, 0) 2035 case ASRLV: 2036 return OP(7, 2) 2037 case ASRAV: 2038 return OP(7, 3) 2039 case AROTRV: 2040 return OP(7, 2) | 1<<21 2041 case -ASLLV: 2042 return OP(7, 4) 2043 case -ASRLV: 2044 return OP(7, 6) 2045 case -ASRAV: 2046 return OP(7, 7) 2047 case -AROTRV: 2048 return OP(7, 6) | 1<<21 2049 2050 case ATEQ: 2051 return OP(6, 4) 2052 case ATNE: 2053 return OP(6, 6) 2054 case -ALL: 2055 return SP(6, 0) 2056 case -ALLV: 2057 return SP(6, 4) 2058 case ASC: 2059 return SP(7, 0) 2060 case ASCV: 2061 return SP(7, 4) 2062 } 2063 2064 if a < 0 { 2065 c.ctxt.Diag("bad irr opcode -%v", -a) 2066 } else { 2067 c.ctxt.Diag("bad irr opcode %v", a) 2068 } 2069 return 0 2070} 2071 2072func vshift(a obj.As) bool { 2073 switch a { 2074 case ASLLV, 2075 ASRLV, 2076 ASRAV, 2077 AROTRV: 2078 return true 2079 } 2080 return false 2081} 2082 2083// MSA Two-bit Data Format Field Encoding 2084func (c *ctxt0) twobitdf(a obj.As) uint32 { 2085 switch a { 2086 case AVMOVB: 2087 return 0 2088 case AVMOVH: 2089 return 1 2090 case AVMOVW: 2091 return 2 2092 case AVMOVD: 2093 return 3 2094 default: 2095 c.ctxt.Diag("unsupported data format %v", a) 2096 } 2097 return 0 2098} 2099 2100// MSA Load/Store offset have to be multiple of size of data format 2101func (c *ctxt0) lsoffset(a obj.As, o int32) int32 { 2102 var mod int32 2103 switch a { 2104 case AVMOVB: 2105 mod = 1 2106 case AVMOVH: 2107 mod = 2 2108 case AVMOVW: 2109 mod = 4 2110 case AVMOVD: 2111 mod = 8 2112 default: 2113 c.ctxt.Diag("unsupported instruction:%v", a) 2114 } 2115 2116 if o%mod != 0 { 2117 c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod) 2118 } 2119 2120 return o / mod 2121} 2122