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