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