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