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