github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/src/cmd/internal/obj/arm/asm5.go (about) 1 // Inferno utils/5l/span.c 2 // https://bitbucket.org/inferno-os/inferno-os/src/default/utils/5l/span.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 package arm 32 33 import ( 34 "cmd/internal/obj" 35 "cmd/internal/objabi" 36 "fmt" 37 "log" 38 "math" 39 "sort" 40 ) 41 42 // ctxt5 holds state while assembling a single function. 43 // Each function gets a fresh ctxt5. 44 // This allows for multiple functions to be safely concurrently assembled. 45 type ctxt5 struct { 46 ctxt *obj.Link 47 newprog obj.ProgAlloc 48 cursym *obj.LSym 49 printp *obj.Prog 50 blitrl *obj.Prog 51 elitrl *obj.Prog 52 autosize int64 53 instoffset int64 54 pc int64 55 pool struct { 56 start uint32 57 size uint32 58 extra uint32 59 } 60 } 61 62 type Optab struct { 63 as obj.As 64 a1 uint8 65 a2 int8 66 a3 uint8 67 type_ uint8 68 size int8 69 param int16 70 flag int8 71 pcrelsiz uint8 72 } 73 74 type Opcross [32][2][32]uint8 75 76 const ( 77 LFROM = 1 << 0 78 LTO = 1 << 1 79 LPOOL = 1 << 2 80 LPCREL = 1 << 3 81 ) 82 83 var optab = []Optab{ 84 /* struct Optab: 85 OPCODE, from, prog->reg, to, type,size,param,flag */ 86 {obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0}, 87 {AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 88 {AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 89 {AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 90 {AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 91 {AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0}, 92 {AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 93 {AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 94 {AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 95 {ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0}, 96 {AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0}, 97 {AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0}, 98 {AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0}, 99 {AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0}, 100 {AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0}, 101 {AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0}, 102 {AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0}, 103 {AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0}, 104 {ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0}, 105 {AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0}, 106 {AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 107 {AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0}, 108 {AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 109 {AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0}, 110 {AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 111 {AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0}, 112 {ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0}, 113 {AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0}, 114 {AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0}, 115 {ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 116 {ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0}, 117 {ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, 118 {ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // prediction hinted form, hint ignored 119 120 {AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0}, 121 {ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0}, 122 {ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0}, 123 {ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0}, 124 {ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0}, 125 {ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0}, 126 {ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0}, 127 {ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0}, 128 {ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0}, 129 {ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0}, 130 {ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0}, 131 {AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0}, 132 {AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0}, 133 {AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0}, 134 {AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0}, 135 {AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0}, 136 {AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0}, 137 {AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0}, 138 {AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0}, 139 {AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4}, 140 {AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0}, 141 {AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0}, 142 {AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0}, 143 {AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0}, 144 {AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0}, 145 {AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0}, 146 {AMVN, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0}, 147 {ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0}, 148 {AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0}, 149 {AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0}, 150 {AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0}, 151 {AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0}, 152 {AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0}, 153 {AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0}, 154 {AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0}, 155 {ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0}, 156 {AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0}, 157 {AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0}, 158 {AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0}, 159 {AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0}, 160 {AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0}, 161 {AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0}, 162 {AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0}, 163 {AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0}, 164 {AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0}, 165 {AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0}, 166 {AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0}, 167 {AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0}, 168 {AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0}, 169 {ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0}, 170 {AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 171 {AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0}, 172 {AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0}, 173 {AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0}, 174 {AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0}, 175 {AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0}, 176 {AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0}, 177 {AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0}, 178 {ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0}, 179 {ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0}, 180 {ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0}, 181 {ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0}, 182 {AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0}, 183 {AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0}, 184 {AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0}, 185 {AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0}, 186 {AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0}, 187 {AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0}, 188 {AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0}, 189 {AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0}, 190 {AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0}, 191 {AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 192 {AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 193 {AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0}, 194 {AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0}, 195 {AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 196 {AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 197 {AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4}, 198 {AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 199 {AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 200 {AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4}, 201 {AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 202 {AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 203 {AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4}, 204 {AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0}, 205 {AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0}, 206 {AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4}, 207 {AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0}, 208 {AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0}, 209 {AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 210 {AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 211 {AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4}, 212 {AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0}, 213 {AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0}, 214 {AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4}, 215 {AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0}, 216 {AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0}, 217 {AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0}, 218 {AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0}, 219 {AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0}, 220 {AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0}, 221 {ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0}, 222 {ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0}, 223 {AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0}, 224 {AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0}, 225 {AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0}, 226 {AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0}, 227 {AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0}, 228 {AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0}, 229 {AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0}, 230 {AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0}, 231 {AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4}, 232 {AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4}, 233 {AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0}, 234 {AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0}, 235 {AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0}, 236 {ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0}, 237 {AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0}, 238 {AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0}, 239 {AMOVW, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0}, 240 {AMOVBU, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0}, 241 {AMOVB, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0}, 242 {AMOVBS, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0}, 243 {AMOVW, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0}, 244 {AMOVB, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0}, 245 {AMOVBS, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0}, 246 {AMOVBU, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0}, 247 {AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0}, 248 {AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0}, 249 {AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0}, 250 {AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0}, 251 {AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0}, 252 {AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0}, 253 {AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0}, 254 {AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0}, 255 {AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0}, 256 {AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0}, 257 {AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0}, 258 {AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0}, 259 {AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0}, 260 {AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0}, 261 {AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0}, 262 {AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0}, 263 {AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0}, 264 {AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0}, 265 {AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4}, 266 {AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0}, 267 {AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0}, 268 {AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4}, 269 {AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0}, 270 {AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0}, 271 {AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4}, 272 {AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0}, 273 {AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0}, 274 {AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4}, 275 {AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0}, 276 {AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0}, 277 {AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4}, 278 {AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0}, 279 {AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0}, 280 {AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4}, 281 {AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0}, 282 {AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0}, 283 {AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4}, 284 {AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0}, 285 {AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0}, 286 {AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4}, 287 {ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0}, 288 {ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0}, 289 {AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0}, 290 {AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0}, 291 {ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0}, 292 {ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0}, 293 {AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0}, 294 {AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0}, 295 {AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0}, 296 {AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0}, 297 {AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0}, 298 {AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0}, 299 {ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0}, 300 {ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0}, 301 {APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0}, 302 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0}, 303 {ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0}, 304 {AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0}, 305 {AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0}, 306 {obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0}, 307 {obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0}, 308 {obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, 309 {obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL 310 {obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL 311 312 {ADATABUNDLE, C_NONE, C_NONE, C_NONE, 100, 4, 0, 0, 0}, 313 {ADATABUNDLEEND, C_NONE, C_NONE, C_NONE, 100, 0, 0, 0, 0}, 314 {obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0}, 315 } 316 317 var oprange [ALAST & obj.AMask][]Optab 318 319 var xcmp [C_GOK + 1][C_GOK + 1]bool 320 321 var ( 322 deferreturn *obj.LSym 323 symdiv *obj.LSym 324 symdivu *obj.LSym 325 symmod *obj.LSym 326 symmodu *obj.LSym 327 ) 328 329 // Note about encoding: Prog.scond holds the condition encoding, 330 // but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0. 331 // The code that shifts the value << 28 has the responsibility 332 // for XORing with C_SCOND_XOR too. 333 334 // asmoutnacl assembles the instruction p. It replaces asmout for NaCl. 335 // It returns the total number of bytes put in out, and it can change 336 // p->pc if extra padding is necessary. 337 // In rare cases, asmoutnacl might split p into two instructions. 338 // origPC is the PC for this Prog (no padding is taken into account). 339 func (c *ctxt5) asmoutnacl(origPC int32, p *obj.Prog, o *Optab, out []uint32) int { 340 size := int(o.size) 341 342 // instruction specific 343 switch p.As { 344 default: 345 if out != nil { 346 c.asmout(p, o, out) 347 } 348 349 case ADATABUNDLE, // align to 16-byte boundary 350 ADATABUNDLEEND: // zero width instruction, just to align next instruction to 16-byte boundary 351 p.Pc = (p.Pc + 15) &^ 15 352 353 if out != nil { 354 c.asmout(p, o, out) 355 } 356 357 case obj.AUNDEF, 358 APLD: 359 size = 4 360 if out != nil { 361 switch p.As { 362 case obj.AUNDEF: 363 out[0] = 0xe7fedef0 // NACL_INSTR_ARM_ABORT_NOW (UDF #0xEDE0) 364 365 case APLD: 366 out[0] = 0xe1a01001 // (MOVW R1, R1) 367 } 368 } 369 370 case AB, ABL: 371 if p.To.Type != obj.TYPE_MEM { 372 if out != nil { 373 c.asmout(p, o, out) 374 } 375 } else { 376 if p.To.Offset != 0 || size != 4 || p.To.Reg > REG_R15 || p.To.Reg < REG_R0 { 377 c.ctxt.Diag("unsupported instruction: %v", p) 378 } 379 if p.Pc&15 == 12 { 380 p.Pc += 4 381 } 382 if out != nil { 383 out[0] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03c0013f | (uint32(p.To.Reg)&15)<<12 | (uint32(p.To.Reg)&15)<<16 // BIC $0xc000000f, Rx 384 if p.As == AB { 385 out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff10 | (uint32(p.To.Reg)&15)<<0 // BX Rx 386 } else { // ABL 387 out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff30 | (uint32(p.To.Reg)&15)<<0 // BLX Rx 388 } 389 } 390 391 size = 8 392 } 393 394 // align the last instruction (the actual BL) to the last instruction in a bundle 395 if p.As == ABL { 396 if p.To.Sym == deferreturn { 397 p.Pc = ((int64(origPC) + 15) &^ 15) + 16 - int64(size) 398 } else { 399 p.Pc += (16 - ((p.Pc + int64(size)) & 15)) & 15 400 } 401 } 402 403 case ALDREX, 404 ALDREXD, 405 AMOVB, 406 AMOVBS, 407 AMOVBU, 408 AMOVD, 409 AMOVF, 410 AMOVH, 411 AMOVHS, 412 AMOVHU, 413 AMOVM, 414 AMOVW, 415 ASTREX, 416 ASTREXD: 417 if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_R15 && p.From.Reg == REG_R13 { // MOVW.W x(R13), PC 418 if out != nil { 419 c.asmout(p, o, out) 420 } 421 if size == 4 { 422 if out != nil { 423 // Note: 5c and 5g reg.c know that DIV/MOD smashes R12 424 // so that this return instruction expansion is valid. 425 out[0] = out[0] &^ 0x3000 // change PC to R12 426 out[1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03ccc13f // BIC $0xc000000f, R12 427 out[2] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff1c // BX R12 428 } 429 430 size += 8 431 if (p.Pc+int64(size))&15 == 4 { 432 p.Pc += 4 433 } 434 break 435 } else { 436 // if the instruction used more than 4 bytes, then it must have used a very large 437 // offset to update R13, so we need to additionally mask R13. 438 if out != nil { 439 out[size/4-1] &^= 0x3000 // change PC to R12 440 out[size/4] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03cdd103 // BIC $0xc0000000, R13 441 out[size/4+1] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03ccc13f // BIC $0xc000000f, R12 442 out[size/4+2] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x012fff1c // BX R12 443 } 444 445 // p->pc+size is only ok at 4 or 12 mod 16. 446 if (p.Pc+int64(size))%8 == 0 { 447 p.Pc += 4 448 } 449 size += 12 450 break 451 } 452 } 453 454 if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_R15 { 455 c.ctxt.Diag("unsupported instruction (move to another register and use indirect jump instead): %v", p) 456 } 457 458 if p.To.Type == obj.TYPE_MEM && p.To.Reg == REG_R13 && (p.Scond&C_WBIT != 0) && size > 4 { 459 // function prolog with very large frame size: MOVW.W R14,-100004(R13) 460 // split it into two instructions: 461 // ADD $-100004, R13 462 // MOVW R14, 0(R13) 463 q := c.newprog() 464 465 p.Scond &^= C_WBIT 466 *q = *p 467 a := &p.To 468 var a2 *obj.Addr 469 if p.To.Type == obj.TYPE_MEM { 470 a2 = &q.To 471 } else { 472 a2 = &q.From 473 } 474 nocache(q) 475 nocache(p) 476 477 // insert q after p 478 q.Link = p.Link 479 480 p.Link = q 481 q.Pcond = nil 482 483 // make p into ADD $X, R13 484 p.As = AADD 485 486 p.From = *a 487 p.From.Reg = 0 488 p.From.Type = obj.TYPE_CONST 489 p.To = obj.Addr{} 490 p.To.Type = obj.TYPE_REG 491 p.To.Reg = REG_R13 492 493 // make q into p but load/store from 0(R13) 494 q.Spadj = 0 495 496 *a2 = obj.Addr{} 497 a2.Type = obj.TYPE_MEM 498 a2.Reg = REG_R13 499 a2.Sym = nil 500 a2.Offset = 0 501 size = int(c.oplook(p).size) 502 break 503 } 504 505 if (p.To.Type == obj.TYPE_MEM && p.To.Reg != REG_R9) || // MOVW Rx, X(Ry), y != 9 506 (p.From.Type == obj.TYPE_MEM && p.From.Reg != REG_R9) { // MOVW X(Rx), Ry, x != 9 507 var a *obj.Addr 508 if p.To.Type == obj.TYPE_MEM { 509 a = &p.To 510 } else { 511 a = &p.From 512 } 513 reg := int(a.Reg) 514 if size == 4 { 515 // if addr.reg == 0, then it is probably load from x(FP) with small x, no need to modify. 516 if reg == 0 { 517 if out != nil { 518 c.asmout(p, o, out) 519 } 520 } else { 521 if out != nil { 522 out[0] = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x03c00103 | (uint32(reg)&15)<<16 | (uint32(reg)&15)<<12 // BIC $0xc0000000, Rx 523 } 524 if p.Pc&15 == 12 { 525 p.Pc += 4 526 } 527 size += 4 528 if out != nil { 529 c.asmout(p, o, out[1:]) 530 } 531 } 532 533 break 534 } else { 535 // if a load/store instruction takes more than 1 word to implement, then 536 // we need to separate the instruction into two: 537 // 1. explicitly load the address into R11. 538 // 2. load/store from R11. 539 // This won't handle .W/.P, so we should reject such code. 540 if p.Scond&(C_PBIT|C_WBIT) != 0 { 541 c.ctxt.Diag("unsupported instruction (.P/.W): %v", p) 542 } 543 q := c.newprog() 544 *q = *p 545 var a2 *obj.Addr 546 if p.To.Type == obj.TYPE_MEM { 547 a2 = &q.To 548 } else { 549 a2 = &q.From 550 } 551 nocache(q) 552 nocache(p) 553 554 // insert q after p 555 q.Link = p.Link 556 557 p.Link = q 558 q.Pcond = nil 559 560 // make p into MOVW $X(R), R11 561 p.As = AMOVW 562 563 p.From = *a 564 p.From.Type = obj.TYPE_ADDR 565 p.To = obj.Addr{} 566 p.To.Type = obj.TYPE_REG 567 p.To.Reg = REG_R11 568 569 // make q into p but load/store from 0(R11) 570 *a2 = obj.Addr{} 571 572 a2.Type = obj.TYPE_MEM 573 a2.Reg = REG_R11 574 a2.Sym = nil 575 a2.Offset = 0 576 size = int(c.oplook(p).size) 577 break 578 } 579 } else if out != nil { 580 c.asmout(p, o, out) 581 } 582 } 583 584 // destination register specific 585 if p.To.Type == obj.TYPE_REG { 586 switch p.To.Reg { 587 case REG_R9: 588 c.ctxt.Diag("invalid instruction, cannot write to R9: %v", p) 589 590 case REG_R13: 591 if out != nil { 592 out[size/4] = 0xe3cdd103 // BIC $0xc0000000, R13 593 } 594 if (p.Pc+int64(size))&15 == 0 { 595 p.Pc += 4 596 } 597 size += 4 598 } 599 } 600 601 return size 602 } 603 604 const ( 605 T_SBIT = 1 << 0 606 T_PBIT = 1 << 1 607 T_WBIT = 1 << 2 608 ) 609 610 var mayHaveSuffix = map[obj.As]uint8{ 611 // bit logic 612 AAND: T_SBIT, 613 AEOR: T_SBIT, 614 AORR: T_SBIT, 615 ABIC: T_SBIT, 616 // arithmatic 617 ASUB: T_SBIT, 618 AADD: T_SBIT, 619 ASBC: T_SBIT, 620 AADC: T_SBIT, 621 ARSB: T_SBIT, 622 ARSC: T_SBIT, 623 // mov 624 AMVN: T_SBIT, 625 AMOVW: T_SBIT | T_PBIT | T_WBIT, 626 AMOVB: T_SBIT | T_PBIT | T_WBIT, 627 AMOVBS: T_SBIT | T_PBIT | T_WBIT, 628 AMOVBU: T_SBIT | T_PBIT | T_WBIT, 629 AMOVH: T_SBIT | T_PBIT | T_WBIT, 630 AMOVHS: T_SBIT | T_PBIT | T_WBIT, 631 AMOVHU: T_SBIT | T_PBIT | T_WBIT, 632 AMOVM: T_PBIT | T_WBIT, 633 // shift 634 ASRL: T_SBIT, 635 ASRA: T_SBIT, 636 ASLL: T_SBIT, 637 // mul 638 AMUL: T_SBIT, 639 AMULU: T_SBIT, 640 AMULL: T_SBIT, 641 AMULLU: T_SBIT, 642 // mula 643 AMULA: T_SBIT, 644 AMULAL: T_SBIT, 645 AMULALU: T_SBIT, 646 // MRC/MCR 647 AMRC: T_SBIT, 648 } 649 650 func checkBits(ctxt *obj.Link, p *obj.Prog) { 651 if p.Scond&C_SBIT != 0 && mayHaveSuffix[p.As]&T_SBIT == 0 { 652 ctxt.Diag("invalid .S suffix: %v", p) 653 } 654 if p.Scond&C_PBIT != 0 && mayHaveSuffix[p.As]&T_PBIT == 0 { 655 ctxt.Diag("invalid .P suffix: %v", p) 656 } 657 if p.Scond&C_WBIT != 0 && mayHaveSuffix[p.As]&T_WBIT == 0 { 658 ctxt.Diag("invalid .W suffix: %v", p) 659 } 660 } 661 662 func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { 663 var p *obj.Prog 664 var op *obj.Prog 665 666 p = cursym.Func.Text 667 if p == nil || p.Link == nil { // handle external functions and ELF section symbols 668 return 669 } 670 671 if oprange[AAND&obj.AMask] == nil { 672 ctxt.Diag("arm ops not initialized, call arm.buildop first") 673 } 674 675 c := ctxt5{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: p.To.Offset + 4} 676 pc := int32(0) 677 678 op = p 679 p = p.Link 680 var i int 681 var m int 682 var o *Optab 683 for ; p != nil || c.blitrl != nil; op, p = p, p.Link { 684 if p == nil { 685 if c.checkpool(op, 0) { 686 p = op 687 continue 688 } 689 690 // can't happen: blitrl is not nil, but checkpool didn't flushpool 691 ctxt.Diag("internal inconsistency") 692 693 break 694 } 695 696 p.Pc = int64(pc) 697 o = c.oplook(p) 698 if ctxt.Headtype != objabi.Hnacl { 699 m = int(o.size) 700 } else { 701 m = c.asmoutnacl(pc, p, o, nil) 702 pc = int32(p.Pc) // asmoutnacl might change pc for alignment 703 o = c.oplook(p) // asmoutnacl might change p in rare cases 704 } 705 706 if m%4 != 0 || p.Pc%4 != 0 { 707 ctxt.Diag("!pc invalid: %v size=%d", p, m) 708 } 709 710 // must check literal pool here in case p generates many instructions 711 if c.blitrl != nil { 712 i = m 713 if c.checkpool(op, i) { 714 p = op 715 continue 716 } 717 } 718 719 if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != ADATABUNDLEEND && p.As != obj.ANOP) { 720 ctxt.Diag("zero-width instruction\n%v", p) 721 continue 722 } 723 724 switch o.flag & (LFROM | LTO | LPOOL) { 725 case LFROM: 726 c.addpool(p, &p.From) 727 728 case LTO: 729 c.addpool(p, &p.To) 730 731 case LPOOL: 732 if p.Scond&C_SCOND == C_SCOND_NONE { 733 c.flushpool(p, 0, 0) 734 } 735 } 736 737 if p.As == AMOVW && p.To.Type == obj.TYPE_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE { 738 c.flushpool(p, 0, 0) 739 } 740 741 checkBits(ctxt, p) 742 743 pc += int32(m) 744 } 745 746 c.cursym.Size = int64(pc) 747 748 /* 749 * if any procedure is large enough to 750 * generate a large SBRA branch, then 751 * generate extra passes putting branches 752 * around jmps to fix. this is rare. 753 */ 754 times := 0 755 756 var bflag int 757 var opc int32 758 var out [6 + 3]uint32 759 for { 760 bflag = 0 761 pc = 0 762 times++ 763 c.cursym.Func.Text.Pc = 0 // force re-layout the code. 764 for p = c.cursym.Func.Text; p != nil; p = p.Link { 765 o = c.oplook(p) 766 if int64(pc) > p.Pc { 767 p.Pc = int64(pc) 768 } 769 770 /* very large branches 771 if(o->type == 6 && p->pcond) { 772 otxt = p->pcond->pc - c; 773 if(otxt < 0) 774 otxt = -otxt; 775 if(otxt >= (1L<<17) - 10) { 776 q = emallocz(sizeof(Prog)); 777 q->link = p->link; 778 p->link = q; 779 q->as = AB; 780 q->to.type = TYPE_BRANCH; 781 q->pcond = p->pcond; 782 p->pcond = q; 783 q = emallocz(sizeof(Prog)); 784 q->link = p->link; 785 p->link = q; 786 q->as = AB; 787 q->to.type = TYPE_BRANCH; 788 q->pcond = q->link->link; 789 bflag = 1; 790 } 791 } 792 */ 793 opc = int32(p.Pc) 794 795 if ctxt.Headtype != objabi.Hnacl { 796 m = int(o.size) 797 } else { 798 m = c.asmoutnacl(pc, p, o, nil) 799 } 800 if p.Pc != int64(opc) { 801 bflag = 1 802 } 803 804 //print("%v pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times); 805 pc = int32(p.Pc + int64(m)) 806 807 if m%4 != 0 || p.Pc%4 != 0 { 808 ctxt.Diag("pc invalid: %v size=%d", p, m) 809 } 810 811 if m/4 > len(out) { 812 ctxt.Diag("instruction size too large: %d > %d", m/4, len(out)) 813 } 814 if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != ADATABUNDLEEND && p.As != obj.ANOP) { 815 if p.As == obj.ATEXT { 816 c.autosize = p.To.Offset + 4 817 continue 818 } 819 820 ctxt.Diag("zero-width instruction\n%v", p) 821 continue 822 } 823 } 824 825 c.cursym.Size = int64(pc) 826 if bflag == 0 { 827 break 828 } 829 } 830 831 if pc%4 != 0 { 832 ctxt.Diag("sym->size=%d, invalid", pc) 833 } 834 835 /* 836 * lay out the code. all the pc-relative code references, 837 * even cross-function, are resolved now; 838 * only data references need to be relocated. 839 * with more work we could leave cross-function 840 * code references to be relocated too, and then 841 * perhaps we'd be able to parallelize the span loop above. 842 */ 843 844 p = c.cursym.Func.Text 845 c.autosize = p.To.Offset + 4 846 c.cursym.Grow(c.cursym.Size) 847 848 bp := c.cursym.P 849 pc = int32(p.Pc) // even p->link might need extra padding 850 var v int 851 for p = p.Link; p != nil; p = p.Link { 852 c.pc = p.Pc 853 o = c.oplook(p) 854 opc = int32(p.Pc) 855 if ctxt.Headtype != objabi.Hnacl { 856 c.asmout(p, o, out[:]) 857 m = int(o.size) 858 } else { 859 m = c.asmoutnacl(pc, p, o, out[:]) 860 if int64(opc) != p.Pc { 861 ctxt.Diag("asmoutnacl broken: pc changed (%d->%d) in last stage: %v", opc, int32(p.Pc), p) 862 } 863 } 864 865 if m%4 != 0 || p.Pc%4 != 0 { 866 ctxt.Diag("final stage: pc invalid: %v size=%d", p, m) 867 } 868 869 if int64(pc) > p.Pc { 870 ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, pc, p) 871 } 872 for int64(pc) != p.Pc { 873 // emit 0xe1a00000 (MOVW R0, R0) 874 bp[0] = 0x00 875 bp = bp[1:] 876 877 bp[0] = 0x00 878 bp = bp[1:] 879 bp[0] = 0xa0 880 bp = bp[1:] 881 bp[0] = 0xe1 882 bp = bp[1:] 883 pc += 4 884 } 885 886 for i = 0; i < m/4; i++ { 887 v = int(out[i]) 888 bp[0] = byte(v) 889 bp = bp[1:] 890 bp[0] = byte(v >> 8) 891 bp = bp[1:] 892 bp[0] = byte(v >> 16) 893 bp = bp[1:] 894 bp[0] = byte(v >> 24) 895 bp = bp[1:] 896 } 897 898 pc += int32(m) 899 } 900 } 901 902 /* 903 * when the first reference to the literal pool threatens 904 * to go out of range of a 12-bit PC-relative offset, 905 * drop the pool now, and branch round it. 906 * this happens only in extended basic blocks that exceed 4k. 907 */ 908 func (c *ctxt5) checkpool(p *obj.Prog, sz int) bool { 909 if c.pool.size >= 0xff0 || immaddr(int32((p.Pc+int64(sz)+4)+4+int64(12+c.pool.size)-int64(c.pool.start+8))) == 0 { 910 return c.flushpool(p, 1, 0) 911 } else if p.Link == nil { 912 return c.flushpool(p, 2, 0) 913 } 914 return false 915 } 916 917 func (c *ctxt5) flushpool(p *obj.Prog, skip int, force int) bool { 918 if c.blitrl != nil { 919 if skip != 0 { 920 if false && skip == 1 { 921 fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start) 922 } 923 q := c.newprog() 924 q.As = AB 925 q.To.Type = obj.TYPE_BRANCH 926 q.Pcond = p.Link 927 q.Link = c.blitrl 928 q.Pos = p.Pos 929 c.blitrl = q 930 } else if force == 0 && (p.Pc+int64(12+c.pool.size)-int64(c.pool.start) < 2048) { // 12 take into account the maximum nacl literal pool alignment padding size 931 return false 932 } 933 if c.ctxt.Headtype == objabi.Hnacl && c.pool.size%16 != 0 { 934 // if pool is not multiple of 16 bytes, add an alignment marker 935 q := c.newprog() 936 937 q.As = ADATABUNDLEEND 938 c.elitrl.Link = q 939 c.elitrl = q 940 } 941 942 // The line number for constant pool entries doesn't really matter. 943 // We set it to the line number of the preceding instruction so that 944 // there are no deltas to encode in the pc-line tables. 945 for q := c.blitrl; q != nil; q = q.Link { 946 q.Pos = p.Pos 947 } 948 949 c.elitrl.Link = p.Link 950 p.Link = c.blitrl 951 952 c.blitrl = nil /* BUG: should refer back to values until out-of-range */ 953 c.elitrl = nil 954 c.pool.size = 0 955 c.pool.start = 0 956 c.pool.extra = 0 957 return true 958 } 959 960 return false 961 } 962 963 func (c *ctxt5) addpool(p *obj.Prog, a *obj.Addr) { 964 t := c.newprog() 965 t.As = AWORD 966 967 switch c.aclass(a) { 968 default: 969 t.To.Offset = a.Offset 970 t.To.Sym = a.Sym 971 t.To.Type = a.Type 972 t.To.Name = a.Name 973 974 if c.ctxt.Flag_shared && t.To.Sym != nil { 975 t.Rel = p 976 } 977 978 case C_SROREG, 979 C_LOREG, 980 C_ROREG, 981 C_FOREG, 982 C_SOREG, 983 C_HOREG, 984 C_FAUTO, 985 C_SAUTO, 986 C_LAUTO, 987 C_LACON: 988 t.To.Type = obj.TYPE_CONST 989 t.To.Offset = c.instoffset 990 } 991 992 if t.Rel == nil { 993 for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */ 994 if q.Rel == nil && q.To == t.To { 995 p.Pcond = q 996 return 997 } 998 } 999 } 1000 1001 if c.ctxt.Headtype == objabi.Hnacl && c.pool.size%16 == 0 { 1002 // start a new data bundle 1003 q := c.newprog() 1004 q.As = ADATABUNDLE 1005 q.Pc = int64(c.pool.size) 1006 c.pool.size += 4 1007 if c.blitrl == nil { 1008 c.blitrl = q 1009 c.pool.start = uint32(p.Pc) 1010 } else { 1011 c.elitrl.Link = q 1012 } 1013 1014 c.elitrl = q 1015 } 1016 1017 q := c.newprog() 1018 *q = *t 1019 q.Pc = int64(c.pool.size) 1020 1021 if c.blitrl == nil { 1022 c.blitrl = q 1023 c.pool.start = uint32(p.Pc) 1024 } else { 1025 c.elitrl.Link = q 1026 } 1027 c.elitrl = q 1028 c.pool.size += 4 1029 1030 p.Pcond = q 1031 } 1032 1033 func (c *ctxt5) regoff(a *obj.Addr) int32 { 1034 c.instoffset = 0 1035 c.aclass(a) 1036 return int32(c.instoffset) 1037 } 1038 1039 func immrot(v uint32) int32 { 1040 for i := 0; i < 16; i++ { 1041 if v&^0xff == 0 { 1042 return int32(uint32(int32(i)<<8) | v | 1<<25) 1043 } 1044 v = v<<2 | v>>30 1045 } 1046 1047 return 0 1048 } 1049 1050 // immrot2a returns bits encoding the immediate constant fields of two instructions, 1051 // such that the encoded constants x, y satisfy x|y==v, x&y==0. 1052 // Returns 0,0 if no such decomposition of v exists. 1053 func immrot2a(v uint32) (uint32, uint32) { 1054 for i := uint(1); i < 32; i++ { 1055 m := uint32(1<<i - 1) 1056 if x, y := immrot(v&m), immrot(v&^m); x != 0 && y != 0 { 1057 return uint32(x), uint32(y) 1058 } 1059 } 1060 // TODO: handle some more cases, like where 1061 // the wraparound from the rotate could help. 1062 return 0, 0 1063 } 1064 1065 // immrot2s returns bits encoding the immediate constant fields of two instructions, 1066 // such that the encoded constants y, x satisfy y-x==v, y&x==0. 1067 // Returns 0,0 if no such decomposition of v exists. 1068 func immrot2s(v uint32) (uint32, uint32) { 1069 if immrot(v) != 0 { 1070 return v, 0 1071 } 1072 // suppose v in the form of {leading 00, upper effective bits, lower 8 effective bits, trailing 00} 1073 // omit trailing 00 1074 var i uint32 1075 for i = 2; i < 32; i += 2 { 1076 if v&(1<<i-1) != 0 { 1077 break 1078 } 1079 } 1080 // i must be <= 24, then adjust i just above lower 8 effective bits of v 1081 i += 6 1082 // let x = {the complement of lower 8 effective bits, trailing 00}, y = x + v 1083 x := 1<<i - v&(1<<i-1) 1084 y := v + x 1085 if y, x = uint32(immrot(y)), uint32(immrot(x)); y != 0 && x != 0 { 1086 return y, x 1087 } 1088 return 0, 0 1089 } 1090 1091 func immaddr(v int32) int32 { 1092 if v >= 0 && v <= 0xfff { 1093 return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */ 1094 } 1095 if v >= -0xfff && v < 0 { 1096 return -v&0xfff | 1<<24 /* pre indexing */ 1097 } 1098 return 0 1099 } 1100 1101 func immfloat(v int32) bool { 1102 return v&0xC03 == 0 /* offset will fit in floating-point load/store */ 1103 } 1104 1105 func immhalf(v int32) bool { 1106 if v >= 0 && v <= 0xff { 1107 return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */ 1108 } 1109 if v >= -0xff && v < 0 { 1110 return -v&0xff|1<<24 != 0 /* pre indexing */ 1111 } 1112 return false 1113 } 1114 1115 func (c *ctxt5) aclass(a *obj.Addr) int { 1116 switch a.Type { 1117 case obj.TYPE_NONE: 1118 return C_NONE 1119 1120 case obj.TYPE_REG: 1121 c.instoffset = 0 1122 if REG_R0 <= a.Reg && a.Reg <= REG_R15 { 1123 return C_REG 1124 } 1125 if REG_F0 <= a.Reg && a.Reg <= REG_F15 { 1126 return C_FREG 1127 } 1128 if a.Reg == REG_FPSR || a.Reg == REG_FPCR { 1129 return C_FCR 1130 } 1131 if a.Reg == REG_CPSR || a.Reg == REG_SPSR { 1132 return C_PSR 1133 } 1134 return C_GOK 1135 1136 case obj.TYPE_REGREG: 1137 return C_REGREG 1138 1139 case obj.TYPE_REGREG2: 1140 return C_REGREG2 1141 1142 case obj.TYPE_REGLIST: 1143 return C_REGLIST 1144 1145 case obj.TYPE_SHIFT: 1146 return C_SHIFT 1147 1148 case obj.TYPE_MEM: 1149 switch a.Name { 1150 case obj.NAME_EXTERN, 1151 obj.NAME_GOTREF, 1152 obj.NAME_STATIC: 1153 if a.Sym == nil || a.Sym.Name == "" { 1154 fmt.Printf("null sym external\n") 1155 return C_GOK 1156 } 1157 1158 c.instoffset = 0 // s.b. unused but just in case 1159 if a.Sym.Type == objabi.STLSBSS { 1160 if c.ctxt.Flag_shared { 1161 return C_TLS_IE 1162 } else { 1163 return C_TLS_LE 1164 } 1165 } 1166 1167 return C_ADDR 1168 1169 case obj.NAME_AUTO: 1170 c.instoffset = c.autosize + a.Offset 1171 if t := immaddr(int32(c.instoffset)); t != 0 { 1172 if immhalf(int32(c.instoffset)) { 1173 if immfloat(t) { 1174 return C_HFAUTO 1175 } 1176 return C_HAUTO 1177 } 1178 1179 if immfloat(t) { 1180 return C_FAUTO 1181 } 1182 return C_SAUTO 1183 } 1184 1185 return C_LAUTO 1186 1187 case obj.NAME_PARAM: 1188 c.instoffset = c.autosize + a.Offset + 4 1189 if t := immaddr(int32(c.instoffset)); t != 0 { 1190 if immhalf(int32(c.instoffset)) { 1191 if immfloat(t) { 1192 return C_HFAUTO 1193 } 1194 return C_HAUTO 1195 } 1196 1197 if immfloat(t) { 1198 return C_FAUTO 1199 } 1200 return C_SAUTO 1201 } 1202 1203 return C_LAUTO 1204 1205 case obj.NAME_NONE: 1206 c.instoffset = a.Offset 1207 if t := immaddr(int32(c.instoffset)); t != 0 { 1208 if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */ 1209 if immfloat(t) { 1210 return C_HFOREG 1211 } 1212 return C_HOREG 1213 } 1214 1215 if immfloat(t) { 1216 return C_FOREG /* n.b. that it will also satisfy immrot */ 1217 } 1218 if immrot(uint32(c.instoffset)) != 0 { 1219 return C_SROREG 1220 } 1221 if immhalf(int32(c.instoffset)) { 1222 return C_HOREG 1223 } 1224 return C_SOREG 1225 } 1226 1227 if immrot(uint32(c.instoffset)) != 0 { 1228 return C_ROREG 1229 } 1230 return C_LOREG 1231 } 1232 1233 return C_GOK 1234 1235 case obj.TYPE_FCONST: 1236 if c.chipzero5(a.Val.(float64)) >= 0 { 1237 return C_ZFCON 1238 } 1239 if c.chipfloat5(a.Val.(float64)) >= 0 { 1240 return C_SFCON 1241 } 1242 return C_LFCON 1243 1244 case obj.TYPE_TEXTSIZE: 1245 return C_TEXTSIZE 1246 1247 case obj.TYPE_CONST, 1248 obj.TYPE_ADDR: 1249 switch a.Name { 1250 case obj.NAME_NONE: 1251 c.instoffset = a.Offset 1252 if a.Reg != 0 { 1253 return c.aconsize() 1254 } 1255 1256 if immrot(uint32(c.instoffset)) != 0 { 1257 return C_RCON 1258 } 1259 if immrot(^uint32(c.instoffset)) != 0 { 1260 return C_NCON 1261 } 1262 if uint32(c.instoffset) <= 0xffff && objabi.GOARM == 7 { 1263 return C_SCON 1264 } 1265 if x, y := immrot2a(uint32(c.instoffset)); x != 0 && y != 0 { 1266 return C_RCON2A 1267 } 1268 if y, x := immrot2s(uint32(c.instoffset)); x != 0 && y != 0 { 1269 return C_RCON2S 1270 } 1271 return C_LCON 1272 1273 case obj.NAME_EXTERN, 1274 obj.NAME_GOTREF, 1275 obj.NAME_STATIC: 1276 s := a.Sym 1277 if s == nil { 1278 break 1279 } 1280 c.instoffset = 0 // s.b. unused but just in case 1281 return C_LCONADDR 1282 1283 case obj.NAME_AUTO: 1284 c.instoffset = c.autosize + a.Offset 1285 return c.aconsize() 1286 1287 case obj.NAME_PARAM: 1288 c.instoffset = c.autosize + a.Offset + 4 1289 return c.aconsize() 1290 } 1291 1292 return C_GOK 1293 1294 case obj.TYPE_BRANCH: 1295 return C_SBRA 1296 } 1297 1298 return C_GOK 1299 } 1300 1301 func (c *ctxt5) aconsize() int { 1302 if immrot(uint32(c.instoffset)) != 0 { 1303 return C_RACON 1304 } 1305 if immrot(uint32(-c.instoffset)) != 0 { 1306 return C_RACON 1307 } 1308 return C_LACON 1309 } 1310 1311 func (c *ctxt5) oplook(p *obj.Prog) *Optab { 1312 a1 := int(p.Optab) 1313 if a1 != 0 { 1314 return &optab[a1-1] 1315 } 1316 a1 = int(p.From.Class) 1317 if a1 == 0 { 1318 a1 = c.aclass(&p.From) + 1 1319 p.From.Class = int8(a1) 1320 } 1321 1322 a1-- 1323 a3 := int(p.To.Class) 1324 if a3 == 0 { 1325 a3 = c.aclass(&p.To) + 1 1326 p.To.Class = int8(a3) 1327 } 1328 1329 a3-- 1330 a2 := C_NONE 1331 if p.Reg != 0 { 1332 switch { 1333 case REG_F0 <= p.Reg && p.Reg <= REG_F15: 1334 a2 = C_FREG 1335 case REG_R0 <= p.Reg && p.Reg <= REG_R15: 1336 a2 = C_REG 1337 default: 1338 c.ctxt.Diag("invalid register in %v", p) 1339 } 1340 } 1341 1342 // If current instruction has a .S suffix (flags update), 1343 // we must use the constant pool instead of splitting it. 1344 if (a1 == C_RCON2A || a1 == C_RCON2S) && p.Scond&C_SBIT != 0 { 1345 a1 = C_LCON 1346 } 1347 if (a3 == C_RCON2A || a3 == C_RCON2S) && p.Scond&C_SBIT != 0 { 1348 a3 = C_LCON 1349 } 1350 1351 if false { /*debug['O']*/ 1352 fmt.Printf("oplook %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3)) 1353 fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type) 1354 } 1355 1356 ops := oprange[p.As&obj.AMask] 1357 c1 := &xcmp[a1] 1358 c3 := &xcmp[a3] 1359 for i := range ops { 1360 op := &ops[i] 1361 if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] { 1362 p.Optab = uint16(cap(optab) - cap(ops) + i + 1) 1363 return op 1364 } 1365 } 1366 1367 c.ctxt.Diag("illegal combination %v; %v %v %v; from %d %d; to %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.From.Name, p.To.Type, p.To.Name) 1368 if ops == nil { 1369 ops = optab 1370 } 1371 return &ops[0] 1372 } 1373 1374 func cmp(a int, b int) bool { 1375 if a == b { 1376 return true 1377 } 1378 switch a { 1379 case C_LCON: 1380 if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S { 1381 return true 1382 } 1383 1384 case C_LACON: 1385 if b == C_RACON { 1386 return true 1387 } 1388 1389 case C_LFCON: 1390 if b == C_ZFCON || b == C_SFCON { 1391 return true 1392 } 1393 1394 case C_HFAUTO: 1395 return b == C_HAUTO || b == C_FAUTO 1396 1397 case C_FAUTO, C_HAUTO: 1398 return b == C_HFAUTO 1399 1400 case C_SAUTO: 1401 return cmp(C_HFAUTO, b) 1402 1403 case C_LAUTO: 1404 return cmp(C_SAUTO, b) 1405 1406 case C_HFOREG: 1407 return b == C_HOREG || b == C_FOREG 1408 1409 case C_FOREG, C_HOREG: 1410 return b == C_HFOREG 1411 1412 case C_SROREG: 1413 return cmp(C_SOREG, b) || cmp(C_ROREG, b) 1414 1415 case C_SOREG, C_ROREG: 1416 return b == C_SROREG || cmp(C_HFOREG, b) 1417 1418 case C_LOREG: 1419 return cmp(C_SROREG, b) 1420 1421 case C_LBRA: 1422 if b == C_SBRA { 1423 return true 1424 } 1425 1426 case C_HREG: 1427 return cmp(C_SP, b) || cmp(C_PC, b) 1428 } 1429 1430 return false 1431 } 1432 1433 type ocmp []Optab 1434 1435 func (x ocmp) Len() int { 1436 return len(x) 1437 } 1438 1439 func (x ocmp) Swap(i, j int) { 1440 x[i], x[j] = x[j], x[i] 1441 } 1442 1443 func (x ocmp) Less(i, j int) bool { 1444 p1 := &x[i] 1445 p2 := &x[j] 1446 n := int(p1.as) - int(p2.as) 1447 if n != 0 { 1448 return n < 0 1449 } 1450 n = int(p1.a1) - int(p2.a1) 1451 if n != 0 { 1452 return n < 0 1453 } 1454 n = int(p1.a2) - int(p2.a2) 1455 if n != 0 { 1456 return n < 0 1457 } 1458 n = int(p1.a3) - int(p2.a3) 1459 if n != 0 { 1460 return n < 0 1461 } 1462 return false 1463 } 1464 1465 func opset(a, b0 obj.As) { 1466 oprange[a&obj.AMask] = oprange[b0] 1467 } 1468 1469 func buildop(ctxt *obj.Link) { 1470 if oprange[AAND&obj.AMask] != nil { 1471 // Already initialized; stop now. 1472 // This happens in the cmd/asm tests, 1473 // each of which re-initializes the arch. 1474 return 1475 } 1476 1477 deferreturn = ctxt.Lookup("runtime.deferreturn") 1478 1479 symdiv = ctxt.Lookup("_div") 1480 symdivu = ctxt.Lookup("_divu") 1481 symmod = ctxt.Lookup("_mod") 1482 symmodu = ctxt.Lookup("_modu") 1483 1484 var n int 1485 1486 for i := 0; i < C_GOK; i++ { 1487 for n = 0; n < C_GOK; n++ { 1488 if cmp(n, i) { 1489 xcmp[i][n] = true 1490 } 1491 } 1492 } 1493 for n = 0; optab[n].as != obj.AXXX; n++ { 1494 if optab[n].flag&LPCREL != 0 { 1495 if ctxt.Flag_shared { 1496 optab[n].size += int8(optab[n].pcrelsiz) 1497 } else { 1498 optab[n].flag &^= LPCREL 1499 } 1500 } 1501 } 1502 1503 sort.Sort(ocmp(optab[:n])) 1504 for i := 0; i < n; i++ { 1505 r := optab[i].as 1506 r0 := r & obj.AMask 1507 start := i 1508 for optab[i].as == r { 1509 i++ 1510 } 1511 oprange[r0] = optab[start:i] 1512 i-- 1513 1514 switch r { 1515 default: 1516 ctxt.Diag("unknown op in build: %v", r) 1517 log.Fatalf("bad code") 1518 1519 case AADD: 1520 opset(ASUB, r0) 1521 opset(ARSB, r0) 1522 opset(AADC, r0) 1523 opset(ASBC, r0) 1524 opset(ARSC, r0) 1525 1526 case AORR: 1527 opset(AEOR, r0) 1528 opset(ABIC, r0) 1529 1530 case ACMP: 1531 opset(ATEQ, r0) 1532 opset(ACMN, r0) 1533 opset(ATST, r0) 1534 1535 case AMVN: 1536 break 1537 1538 case ABEQ: 1539 opset(ABNE, r0) 1540 opset(ABCS, r0) 1541 opset(ABHS, r0) 1542 opset(ABCC, r0) 1543 opset(ABLO, r0) 1544 opset(ABMI, r0) 1545 opset(ABPL, r0) 1546 opset(ABVS, r0) 1547 opset(ABVC, r0) 1548 opset(ABHI, r0) 1549 opset(ABLS, r0) 1550 opset(ABGE, r0) 1551 opset(ABLT, r0) 1552 opset(ABGT, r0) 1553 opset(ABLE, r0) 1554 1555 case ASLL: 1556 opset(ASRL, r0) 1557 opset(ASRA, r0) 1558 1559 case AMUL: 1560 opset(AMULU, r0) 1561 1562 case ADIV: 1563 opset(AMOD, r0) 1564 opset(AMODU, r0) 1565 opset(ADIVU, r0) 1566 1567 case ADIVHW: 1568 opset(ADIVUHW, r0) 1569 1570 case AMOVW, 1571 AMOVB, 1572 AMOVBS, 1573 AMOVBU, 1574 AMOVH, 1575 AMOVHS, 1576 AMOVHU: 1577 break 1578 1579 case ASWPW: 1580 opset(ASWPBU, r0) 1581 1582 case AB, 1583 ABL, 1584 ABX, 1585 ABXRET, 1586 obj.ADUFFZERO, 1587 obj.ADUFFCOPY, 1588 ASWI, 1589 AWORD, 1590 AMOVM, 1591 ARFE, 1592 obj.ATEXT: 1593 break 1594 1595 case AADDF: 1596 opset(AADDD, r0) 1597 opset(ASUBF, r0) 1598 opset(ASUBD, r0) 1599 opset(AMULF, r0) 1600 opset(AMULD, r0) 1601 opset(ADIVF, r0) 1602 opset(ADIVD, r0) 1603 1604 case ANEGF: 1605 opset(ANEGD, r0) 1606 opset(ASQRTF, r0) 1607 opset(ASQRTD, r0) 1608 opset(AMOVFD, r0) 1609 opset(AMOVDF, r0) 1610 opset(AABSF, r0) 1611 opset(AABSD, r0) 1612 1613 case ACMPF: 1614 opset(ACMPD, r0) 1615 1616 case AMOVF: 1617 opset(AMOVD, r0) 1618 1619 case AMOVFW: 1620 opset(AMOVDW, r0) 1621 1622 case AMOVWF: 1623 opset(AMOVWD, r0) 1624 1625 case AMULL: 1626 opset(AMULAL, r0) 1627 opset(AMULLU, r0) 1628 opset(AMULALU, r0) 1629 1630 case AMULWT: 1631 opset(AMULWB, r0) 1632 opset(AMULBB, r0) 1633 opset(AMMUL, r0) 1634 1635 case AMULAWT: 1636 opset(AMULAWB, r0) 1637 opset(AMULABB, r0) 1638 opset(AMULA, r0) 1639 opset(AMULS, r0) 1640 opset(AMMULA, r0) 1641 opset(AMMULS, r0) 1642 1643 case ACLZ: 1644 opset(AREV, r0) 1645 opset(AREV16, r0) 1646 opset(AREVSH, r0) 1647 opset(ARBIT, r0) 1648 1649 case ALDREX, 1650 ASTREX, 1651 ALDREXD, 1652 ASTREXD, 1653 APLD, 1654 AAND, 1655 obj.AUNDEF, 1656 obj.AFUNCDATA, 1657 obj.APCDATA, 1658 obj.ANOP, 1659 ADATABUNDLE, 1660 ADATABUNDLEEND: 1661 break 1662 } 1663 } 1664 } 1665 1666 func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) { 1667 c.printp = p 1668 o1 := uint32(0) 1669 o2 := uint32(0) 1670 o3 := uint32(0) 1671 o4 := uint32(0) 1672 o5 := uint32(0) 1673 o6 := uint32(0) 1674 if false { /*debug['P']*/ 1675 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_) 1676 } 1677 switch o.type_ { 1678 default: 1679 c.ctxt.Diag("%v: unknown asm %d", p, o.type_) 1680 1681 case 0: /* pseudo ops */ 1682 if false { /*debug['G']*/ 1683 fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name) 1684 } 1685 1686 case 1: /* op R,[R],R */ 1687 o1 = c.oprrr(p, p.As, int(p.Scond)) 1688 1689 rf := int(p.From.Reg) 1690 rt := int(p.To.Reg) 1691 r := int(p.Reg) 1692 if p.To.Type == obj.TYPE_NONE { 1693 rt = 0 1694 } 1695 if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN { 1696 r = 0 1697 } else if r == 0 { 1698 r = rt 1699 } 1700 o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 1701 1702 case 2: /* movbu $I,[R],R */ 1703 c.aclass(&p.From) 1704 1705 o1 = c.oprrr(p, p.As, int(p.Scond)) 1706 o1 |= uint32(immrot(uint32(c.instoffset))) 1707 rt := int(p.To.Reg) 1708 r := int(p.Reg) 1709 if p.To.Type == obj.TYPE_NONE { 1710 rt = 0 1711 } 1712 if p.As == AMOVW || p.As == AMVN { 1713 r = 0 1714 } else if r == 0 { 1715 r = rt 1716 } 1717 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 1718 1719 case 106: /* op $I,R,R where I can be decomposed into 2 immediates */ 1720 c.aclass(&p.From) 1721 r := int(p.Reg) 1722 rt := int(p.To.Reg) 1723 if r == 0 { 1724 r = rt 1725 } 1726 x, y := immrot2a(uint32(c.instoffset)) 1727 var as2 obj.As 1728 switch p.As { 1729 case AADD, ASUB, AORR, AEOR, ABIC: 1730 as2 = p.As // ADD, SUB, ORR, EOR, BIC 1731 case ARSB: 1732 as2 = AADD // RSB -> RSB/ADD pair 1733 case AADC: 1734 as2 = AADD // ADC -> ADC/ADD pair 1735 case ASBC: 1736 as2 = ASUB // SBC -> SBC/SUB pair 1737 case ARSC: 1738 as2 = AADD // RSC -> RSC/ADD pair 1739 default: 1740 c.ctxt.Diag("unknown second op for %v", p) 1741 } 1742 o1 = c.oprrr(p, p.As, int(p.Scond)) 1743 o2 = c.oprrr(p, as2, int(p.Scond)) 1744 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 1745 o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12 1746 o1 |= x 1747 o2 |= y 1748 1749 case 107: /* op $I,R,R where I can be decomposed into 2 immediates */ 1750 c.aclass(&p.From) 1751 r := int(p.Reg) 1752 rt := int(p.To.Reg) 1753 if r == 0 { 1754 r = rt 1755 } 1756 y, x := immrot2s(uint32(c.instoffset)) 1757 var as2 obj.As 1758 switch p.As { 1759 case AADD: 1760 as2 = ASUB // ADD -> ADD/SUB pair 1761 case ASUB: 1762 as2 = AADD // SUB -> SUB/ADD pair 1763 case ARSB: 1764 as2 = ASUB // RSB -> RSB/SUB pair 1765 case AADC: 1766 as2 = ASUB // ADC -> ADC/SUB pair 1767 case ASBC: 1768 as2 = AADD // SBC -> SBC/ADD pair 1769 case ARSC: 1770 as2 = ASUB // RSC -> RSC/SUB pair 1771 default: 1772 c.ctxt.Diag("unknown second op for %v", p) 1773 } 1774 o1 = c.oprrr(p, p.As, int(p.Scond)) 1775 o2 = c.oprrr(p, as2, int(p.Scond)) 1776 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 1777 o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12 1778 o1 |= y 1779 o2 |= x 1780 1781 case 3: /* add R<<[IR],[R],R */ 1782 o1 = c.mov(p) 1783 1784 case 4: /* MOVW $off(R), R -> add $off,[R],R */ 1785 c.aclass(&p.From) 1786 if c.instoffset < 0 { 1787 o1 = c.oprrr(p, ASUB, int(p.Scond)) 1788 o1 |= uint32(immrot(uint32(-c.instoffset))) 1789 } else { 1790 o1 = c.oprrr(p, AADD, int(p.Scond)) 1791 o1 |= uint32(immrot(uint32(c.instoffset))) 1792 } 1793 r := int(p.From.Reg) 1794 if r == 0 { 1795 r = int(o.param) 1796 } 1797 o1 |= (uint32(r) & 15) << 16 1798 o1 |= (uint32(p.To.Reg) & 15) << 12 1799 1800 case 5: /* bra s */ 1801 o1 = c.opbra(p, p.As, int(p.Scond)) 1802 1803 v := int32(-8) 1804 if p.To.Sym != nil { 1805 rel := obj.Addrel(c.cursym) 1806 rel.Off = int32(c.pc) 1807 rel.Siz = 4 1808 rel.Sym = p.To.Sym 1809 v += int32(p.To.Offset) 1810 rel.Add = int64(o1) | (int64(v)>>2)&0xffffff 1811 rel.Type = objabi.R_CALLARM 1812 break 1813 } 1814 1815 if p.Pcond != nil { 1816 v = int32((p.Pcond.Pc - c.pc) - 8) 1817 } 1818 o1 |= (uint32(v) >> 2) & 0xffffff 1819 1820 case 6: /* b ,O(R) -> add $O,R,PC */ 1821 c.aclass(&p.To) 1822 1823 o1 = c.oprrr(p, AADD, int(p.Scond)) 1824 o1 |= uint32(immrot(uint32(c.instoffset))) 1825 o1 |= (uint32(p.To.Reg) & 15) << 16 1826 o1 |= (REGPC & 15) << 12 1827 1828 case 7: /* bl (R) -> blx R */ 1829 c.aclass(&p.To) 1830 1831 if c.instoffset != 0 { 1832 c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset) 1833 } 1834 o1 = c.oprrr(p, ABL, int(p.Scond)) 1835 o1 |= (uint32(p.To.Reg) & 15) << 0 1836 rel := obj.Addrel(c.cursym) 1837 rel.Off = int32(c.pc) 1838 rel.Siz = 0 1839 rel.Type = objabi.R_CALLIND 1840 1841 case 8: /* sll $c,[R],R -> mov (R<<$c),R */ 1842 c.aclass(&p.From) 1843 1844 o1 = c.oprrr(p, p.As, int(p.Scond)) 1845 r := int(p.Reg) 1846 if r == 0 { 1847 r = int(p.To.Reg) 1848 } 1849 o1 |= (uint32(r) & 15) << 0 1850 o1 |= uint32((c.instoffset & 31) << 7) 1851 o1 |= (uint32(p.To.Reg) & 15) << 12 1852 1853 case 9: /* sll R,[R],R -> mov (R<<R),R */ 1854 o1 = c.oprrr(p, p.As, int(p.Scond)) 1855 1856 r := int(p.Reg) 1857 if r == 0 { 1858 r = int(p.To.Reg) 1859 } 1860 o1 |= (uint32(r) & 15) << 0 1861 o1 |= (uint32(p.From.Reg)&15)<<8 | 1<<4 1862 o1 |= (uint32(p.To.Reg) & 15) << 12 1863 1864 case 10: /* swi [$con] */ 1865 o1 = c.oprrr(p, p.As, int(p.Scond)) 1866 1867 if p.To.Type != obj.TYPE_NONE { 1868 c.aclass(&p.To) 1869 o1 |= uint32(c.instoffset & 0xffffff) 1870 } 1871 1872 case 11: /* word */ 1873 c.aclass(&p.To) 1874 1875 o1 = uint32(c.instoffset) 1876 if p.To.Sym != nil { 1877 // This case happens with words generated 1878 // in the PC stream as part of the literal pool (c.pool). 1879 rel := obj.Addrel(c.cursym) 1880 1881 rel.Off = int32(c.pc) 1882 rel.Siz = 4 1883 rel.Sym = p.To.Sym 1884 rel.Add = p.To.Offset 1885 1886 if c.ctxt.Flag_shared { 1887 if p.To.Name == obj.NAME_GOTREF { 1888 rel.Type = objabi.R_GOTPCREL 1889 } else { 1890 rel.Type = objabi.R_PCREL 1891 } 1892 rel.Add += c.pc - p.Rel.Pc - 8 1893 } else { 1894 rel.Type = objabi.R_ADDR 1895 } 1896 o1 = 0 1897 } 1898 1899 case 12: /* movw $lcon, reg */ 1900 if o.a1 == C_SCON { 1901 o1 = c.omvs(p, &p.From, int(p.To.Reg)) 1902 } else { 1903 o1 = c.omvl(p, &p.From, int(p.To.Reg)) 1904 } 1905 1906 if o.flag&LPCREL != 0 { 1907 o2 = c.oprrr(p, AADD, int(p.Scond)) | (uint32(p.To.Reg)&15)<<0 | (REGPC&15)<<16 | (uint32(p.To.Reg)&15)<<12 1908 } 1909 1910 case 13: /* op $lcon, [R], R */ 1911 if o.a1 == C_SCON { 1912 o1 = c.omvs(p, &p.From, REGTMP) 1913 } else { 1914 o1 = c.omvl(p, &p.From, REGTMP) 1915 } 1916 1917 if o1 == 0 { 1918 break 1919 } 1920 o2 = c.oprrr(p, p.As, int(p.Scond)) 1921 o2 |= REGTMP & 15 1922 r := int(p.Reg) 1923 if p.As == AMOVW || p.As == AMVN { 1924 r = 0 1925 } else if r == 0 { 1926 r = int(p.To.Reg) 1927 } 1928 o2 |= (uint32(r) & 15) << 16 1929 if p.To.Type != obj.TYPE_NONE { 1930 o2 |= (uint32(p.To.Reg) & 15) << 12 1931 } 1932 1933 case 14: /* movb/movbu/movh/movhu R,R */ 1934 o1 = c.oprrr(p, ASLL, int(p.Scond)) 1935 1936 if p.As == AMOVBU || p.As == AMOVHU { 1937 o2 = c.oprrr(p, ASRL, int(p.Scond)) 1938 } else { 1939 o2 = c.oprrr(p, ASRA, int(p.Scond)) 1940 } 1941 1942 r := int(p.To.Reg) 1943 o1 |= (uint32(p.From.Reg)&15)<<0 | (uint32(r)&15)<<12 1944 o2 |= uint32(r)&15 | (uint32(r)&15)<<12 1945 if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU { 1946 o1 |= 24 << 7 1947 o2 |= 24 << 7 1948 } else { 1949 o1 |= 16 << 7 1950 o2 |= 16 << 7 1951 } 1952 1953 case 15: /* mul r,[r,]r */ 1954 o1 = c.oprrr(p, p.As, int(p.Scond)) 1955 1956 rf := int(p.From.Reg) 1957 rt := int(p.To.Reg) 1958 r := int(p.Reg) 1959 if r == 0 { 1960 r = rt 1961 } 1962 if rt == r { 1963 r = rf 1964 rf = rt 1965 } 1966 1967 if false { 1968 if rt == r || rf == REGPC&15 || r == REGPC&15 || rt == REGPC&15 { 1969 c.ctxt.Diag("%v: bad registers in MUL", p) 1970 } 1971 } 1972 1973 o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 1974 1975 case 16: /* div r,[r,]r */ 1976 o1 = 0xf << 28 1977 1978 o2 = 0 1979 1980 case 17: 1981 o1 = c.oprrr(p, p.As, int(p.Scond)) 1982 rf := int(p.From.Reg) 1983 rt := int(p.To.Reg) 1984 rt2 := int(p.To.Offset) 1985 r := int(p.Reg) 1986 o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12 1987 1988 case 20: /* mov/movb/movbu R,O(R) */ 1989 c.aclass(&p.To) 1990 1991 r := int(p.To.Reg) 1992 if r == 0 { 1993 r = int(o.param) 1994 } 1995 o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond)) 1996 1997 case 21: /* mov/movbu O(R),R -> lr */ 1998 c.aclass(&p.From) 1999 2000 r := int(p.From.Reg) 2001 if r == 0 { 2002 r = int(o.param) 2003 } 2004 o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond)) 2005 if p.As != AMOVW { 2006 o1 |= 1 << 22 2007 } 2008 2009 case 30: /* mov/movb/movbu R,L(R) */ 2010 o1 = c.omvl(p, &p.To, REGTMP) 2011 2012 if o1 == 0 { 2013 break 2014 } 2015 r := int(p.To.Reg) 2016 if r == 0 { 2017 r = int(o.param) 2018 } 2019 o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond)) 2020 if p.As != AMOVW { 2021 o2 |= 1 << 22 2022 } 2023 2024 case 31: /* mov/movbu L(R),R -> lr[b] */ 2025 o1 = c.omvl(p, &p.From, REGTMP) 2026 2027 if o1 == 0 { 2028 break 2029 } 2030 r := int(p.From.Reg) 2031 if r == 0 { 2032 r = int(o.param) 2033 } 2034 o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond)) 2035 if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB { 2036 o2 |= 1 << 22 2037 } 2038 2039 case 34: /* mov $lacon,R */ 2040 o1 = c.omvl(p, &p.From, REGTMP) 2041 2042 if o1 == 0 { 2043 break 2044 } 2045 2046 o2 = c.oprrr(p, AADD, int(p.Scond)) 2047 o2 |= REGTMP & 15 2048 r := int(p.From.Reg) 2049 if r == 0 { 2050 r = int(o.param) 2051 } 2052 o2 |= (uint32(r) & 15) << 16 2053 if p.To.Type != obj.TYPE_NONE { 2054 o2 |= (uint32(p.To.Reg) & 15) << 12 2055 } 2056 2057 case 35: /* mov PSR,R */ 2058 o1 = 2<<23 | 0xf<<16 | 0<<0 2059 2060 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2061 o1 |= (uint32(p.From.Reg) & 1) << 22 2062 o1 |= (uint32(p.To.Reg) & 15) << 12 2063 2064 case 36: /* mov R,PSR */ 2065 o1 = 2<<23 | 0x29f<<12 | 0<<4 2066 2067 if p.Scond&C_FBIT != 0 { 2068 o1 ^= 0x010 << 12 2069 } 2070 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2071 o1 |= (uint32(p.To.Reg) & 1) << 22 2072 o1 |= (uint32(p.From.Reg) & 15) << 0 2073 2074 case 37: /* mov $con,PSR */ 2075 c.aclass(&p.From) 2076 2077 o1 = 2<<23 | 0x29f<<12 | 0<<4 2078 if p.Scond&C_FBIT != 0 { 2079 o1 ^= 0x010 << 12 2080 } 2081 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2082 o1 |= uint32(immrot(uint32(c.instoffset))) 2083 o1 |= (uint32(p.To.Reg) & 1) << 22 2084 o1 |= (uint32(p.From.Reg) & 15) << 0 2085 2086 case 38, 39: 2087 switch o.type_ { 2088 case 38: /* movm $con,oreg -> stm */ 2089 o1 = 0x4 << 25 2090 2091 o1 |= uint32(p.From.Offset & 0xffff) 2092 o1 |= (uint32(p.To.Reg) & 15) << 16 2093 c.aclass(&p.To) 2094 2095 case 39: /* movm oreg,$con -> ldm */ 2096 o1 = 0x4<<25 | 1<<20 2097 2098 o1 |= uint32(p.To.Offset & 0xffff) 2099 o1 |= (uint32(p.From.Reg) & 15) << 16 2100 c.aclass(&p.From) 2101 } 2102 2103 if c.instoffset != 0 { 2104 c.ctxt.Diag("offset must be zero in MOVM; %v", p) 2105 } 2106 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2107 if p.Scond&C_PBIT != 0 { 2108 o1 |= 1 << 24 2109 } 2110 if p.Scond&C_UBIT != 0 { 2111 o1 |= 1 << 23 2112 } 2113 if p.Scond&C_WBIT != 0 { 2114 o1 |= 1 << 21 2115 } 2116 2117 case 40: /* swp oreg,reg,reg */ 2118 c.aclass(&p.From) 2119 2120 if c.instoffset != 0 { 2121 c.ctxt.Diag("offset must be zero in SWP") 2122 } 2123 o1 = 0x2<<23 | 0x9<<4 2124 if p.As != ASWPW { 2125 o1 |= 1 << 22 2126 } 2127 o1 |= (uint32(p.From.Reg) & 15) << 16 2128 o1 |= (uint32(p.Reg) & 15) << 0 2129 o1 |= (uint32(p.To.Reg) & 15) << 12 2130 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2131 2132 case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */ 2133 o1 = 0xe8fd8000 2134 2135 case 50: /* floating point store */ 2136 v := c.regoff(&p.To) 2137 2138 r := int(p.To.Reg) 2139 if r == 0 { 2140 r = int(o.param) 2141 } 2142 o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p) 2143 2144 case 51: /* floating point load */ 2145 v := c.regoff(&p.From) 2146 2147 r := int(p.From.Reg) 2148 if r == 0 { 2149 r = int(o.param) 2150 } 2151 o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20 2152 2153 case 52: /* floating point store, int32 offset UGLY */ 2154 o1 = c.omvl(p, &p.To, REGTMP) 2155 2156 if o1 == 0 { 2157 break 2158 } 2159 r := int(p.To.Reg) 2160 if r == 0 { 2161 r = int(o.param) 2162 } 2163 o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 2164 o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) 2165 2166 case 53: /* floating point load, int32 offset UGLY */ 2167 o1 = c.omvl(p, &p.From, REGTMP) 2168 2169 if o1 == 0 { 2170 break 2171 } 2172 r := int(p.From.Reg) 2173 if r == 0 { 2174 r = int(o.param) 2175 } 2176 o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0 2177 o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 2178 2179 case 54: /* floating point arith */ 2180 o1 = c.oprrr(p, p.As, int(p.Scond)) 2181 2182 rf := int(p.From.Reg) 2183 rt := int(p.To.Reg) 2184 r := int(p.Reg) 2185 if r == 0 { 2186 r = rt 2187 } 2188 2189 o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 2190 2191 case 55: /* negf freg, freg */ 2192 o1 = c.oprrr(p, p.As, int(p.Scond)) 2193 2194 rf := int(p.From.Reg) 2195 rt := int(p.To.Reg) 2196 2197 o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12 2198 2199 case 56: /* move to FP[CS]R */ 2200 o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xe<<24 | 1<<8 | 1<<4 2201 2202 o1 |= ((uint32(p.To.Reg)&1)+1)<<21 | (uint32(p.From.Reg)&15)<<12 2203 2204 case 57: /* move from FP[CS]R */ 2205 o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xe<<24 | 1<<8 | 1<<4 2206 2207 o1 |= ((uint32(p.From.Reg)&1)+1)<<21 | (uint32(p.To.Reg)&15)<<12 | 1<<20 2208 2209 case 58: /* movbu R,R */ 2210 o1 = c.oprrr(p, AAND, int(p.Scond)) 2211 2212 o1 |= uint32(immrot(0xff)) 2213 rt := int(p.To.Reg) 2214 r := int(p.From.Reg) 2215 if p.To.Type == obj.TYPE_NONE { 2216 rt = 0 2217 } 2218 if r == 0 { 2219 r = rt 2220 } 2221 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 2222 2223 case 59: /* movw/bu R<<I(R),R -> ldr indexed */ 2224 if p.From.Reg == 0 { 2225 if p.As != AMOVW { 2226 c.ctxt.Diag("byte MOV from shifter operand") 2227 } 2228 o1 = c.mov(p) 2229 break 2230 } 2231 2232 if p.From.Offset&(1<<4) != 0 { 2233 c.ctxt.Diag("bad shift in LDR") 2234 } 2235 o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) 2236 if p.As == AMOVBU { 2237 o1 |= 1 << 22 2238 } 2239 2240 case 60: /* movb R(R),R -> ldrsb indexed */ 2241 if p.From.Reg == 0 { 2242 c.ctxt.Diag("byte MOV from shifter operand") 2243 o1 = c.mov(p) 2244 break 2245 } 2246 2247 if p.From.Offset&(^0xf) != 0 { 2248 c.ctxt.Diag("bad shift in LDRSB") 2249 } 2250 o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond)) 2251 o1 ^= 1<<5 | 1<<6 2252 2253 case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */ 2254 if p.To.Reg == 0 { 2255 c.ctxt.Diag("MOV to shifter operand") 2256 } 2257 o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond)) 2258 if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU { 2259 o1 |= 1 << 22 2260 } 2261 2262 /* reloc ops */ 2263 case 64: /* mov/movb/movbu R,addr */ 2264 o1 = c.omvl(p, &p.To, REGTMP) 2265 2266 if o1 == 0 { 2267 break 2268 } 2269 o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond)) 2270 if o.flag&LPCREL != 0 { 2271 o3 = o2 2272 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2273 } 2274 2275 case 65: /* mov/movbu addr,R */ 2276 o1 = c.omvl(p, &p.From, REGTMP) 2277 2278 if o1 == 0 { 2279 break 2280 } 2281 o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond)) 2282 if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB { 2283 o2 |= 1 << 22 2284 } 2285 if o.flag&LPCREL != 0 { 2286 o3 = o2 2287 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2288 } 2289 2290 case 101: /* movw tlsvar,R, local exec*/ 2291 if p.Scond&C_SCOND != C_SCOND_NONE { 2292 c.ctxt.Diag("conditional tls") 2293 } 2294 o1 = c.omvl(p, &p.From, int(p.To.Reg)) 2295 2296 case 102: /* movw tlsvar,R, initial exec*/ 2297 if p.Scond&C_SCOND != C_SCOND_NONE { 2298 c.ctxt.Diag("conditional tls") 2299 } 2300 o1 = c.omvl(p, &p.From, int(p.To.Reg)) 2301 o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond)) 2302 2303 case 103: /* word tlsvar, local exec */ 2304 if p.To.Sym == nil { 2305 c.ctxt.Diag("nil sym in tls %v", p) 2306 } 2307 if p.To.Offset != 0 { 2308 c.ctxt.Diag("offset against tls var in %v", p) 2309 } 2310 // This case happens with words generated in the PC stream as part of 2311 // the literal c.pool. 2312 rel := obj.Addrel(c.cursym) 2313 2314 rel.Off = int32(c.pc) 2315 rel.Siz = 4 2316 rel.Sym = p.To.Sym 2317 rel.Type = objabi.R_TLS_LE 2318 o1 = 0 2319 2320 case 104: /* word tlsvar, initial exec */ 2321 if p.To.Sym == nil { 2322 c.ctxt.Diag("nil sym in tls %v", p) 2323 } 2324 if p.To.Offset != 0 { 2325 c.ctxt.Diag("offset against tls var in %v", p) 2326 } 2327 rel := obj.Addrel(c.cursym) 2328 rel.Off = int32(c.pc) 2329 rel.Siz = 4 2330 rel.Sym = p.To.Sym 2331 rel.Type = objabi.R_TLS_IE 2332 rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz) 2333 2334 case 68: /* floating point store -> ADDR */ 2335 o1 = c.omvl(p, &p.To, REGTMP) 2336 2337 if o1 == 0 { 2338 break 2339 } 2340 o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p) 2341 if o.flag&LPCREL != 0 { 2342 o3 = o2 2343 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2344 } 2345 2346 case 69: /* floating point load <- ADDR */ 2347 o1 = c.omvl(p, &p.From, REGTMP) 2348 2349 if o1 == 0 { 2350 break 2351 } 2352 o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20 2353 if o.flag&LPCREL != 0 { 2354 o3 = o2 2355 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2356 } 2357 2358 /* ArmV4 ops: */ 2359 case 70: /* movh/movhu R,O(R) -> strh */ 2360 c.aclass(&p.To) 2361 2362 r := int(p.To.Reg) 2363 if r == 0 { 2364 r = int(o.param) 2365 } 2366 o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond)) 2367 2368 case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */ 2369 c.aclass(&p.From) 2370 2371 r := int(p.From.Reg) 2372 if r == 0 { 2373 r = int(o.param) 2374 } 2375 o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond)) 2376 if p.As == AMOVB || p.As == AMOVBS { 2377 o1 ^= 1<<5 | 1<<6 2378 } else if p.As == AMOVH || p.As == AMOVHS { 2379 o1 ^= (1 << 6) 2380 } 2381 2382 case 72: /* movh/movhu R,L(R) -> strh */ 2383 o1 = c.omvl(p, &p.To, REGTMP) 2384 2385 if o1 == 0 { 2386 break 2387 } 2388 r := int(p.To.Reg) 2389 if r == 0 { 2390 r = int(o.param) 2391 } 2392 o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond)) 2393 2394 case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */ 2395 o1 = c.omvl(p, &p.From, REGTMP) 2396 2397 if o1 == 0 { 2398 break 2399 } 2400 r := int(p.From.Reg) 2401 if r == 0 { 2402 r = int(o.param) 2403 } 2404 o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond)) 2405 if p.As == AMOVB || p.As == AMOVBS { 2406 o2 ^= 1<<5 | 1<<6 2407 } else if p.As == AMOVH || p.As == AMOVHS { 2408 o2 ^= (1 << 6) 2409 } 2410 2411 case 74: /* bx $I */ 2412 c.ctxt.Diag("ABX $I") 2413 2414 case 75: /* bx O(R) */ 2415 c.aclass(&p.To) 2416 2417 if c.instoffset != 0 { 2418 c.ctxt.Diag("non-zero offset in ABX") 2419 } 2420 2421 /* 2422 o1 = c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12); // mov PC, LR 2423 o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0); // BX R 2424 */ 2425 // p->to.reg may be REGLINK 2426 o1 = c.oprrr(p, AADD, int(p.Scond)) 2427 2428 o1 |= uint32(immrot(uint32(c.instoffset))) 2429 o1 |= (uint32(p.To.Reg) & 15) << 16 2430 o1 |= (REGTMP & 15) << 12 2431 o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR 2432 o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15 // BX Rtmp 2433 2434 case 76: /* bx O(R) when returning from fn*/ 2435 c.ctxt.Diag("ABXRET") 2436 2437 case 77: /* ldrex oreg,reg */ 2438 c.aclass(&p.From) 2439 2440 if c.instoffset != 0 { 2441 c.ctxt.Diag("offset must be zero in LDREX") 2442 } 2443 o1 = 0x19<<20 | 0xf9f 2444 o1 |= (uint32(p.From.Reg) & 15) << 16 2445 o1 |= (uint32(p.To.Reg) & 15) << 12 2446 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2447 2448 case 78: /* strex reg,oreg,reg */ 2449 c.aclass(&p.From) 2450 2451 if c.instoffset != 0 { 2452 c.ctxt.Diag("offset must be zero in STREX") 2453 } 2454 o1 = 0x18<<20 | 0xf90 2455 o1 |= (uint32(p.From.Reg) & 15) << 16 2456 o1 |= (uint32(p.Reg) & 15) << 0 2457 o1 |= (uint32(p.To.Reg) & 15) << 12 2458 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2459 2460 case 80: /* fmov zfcon,freg */ 2461 if p.As == AMOVD { 2462 o1 = 0xeeb00b00 // VMOV imm 64 2463 o2 = c.oprrr(p, ASUBD, int(p.Scond)) 2464 } else { 2465 o1 = 0x0eb00a00 // VMOV imm 32 2466 o2 = c.oprrr(p, ASUBF, int(p.Scond)) 2467 } 2468 2469 v := int32(0x70) // 1.0 2470 r := (int(p.To.Reg) & 15) << 0 2471 2472 // movf $1.0, r 2473 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2474 2475 o1 |= (uint32(r) & 15) << 12 2476 o1 |= (uint32(v) & 0xf) << 0 2477 o1 |= (uint32(v) & 0xf0) << 12 2478 2479 // subf r,r,r 2480 o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12 2481 2482 case 81: /* fmov sfcon,freg */ 2483 o1 = 0x0eb00a00 // VMOV imm 32 2484 if p.As == AMOVD { 2485 o1 = 0xeeb00b00 // VMOV imm 64 2486 } 2487 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2488 o1 |= (uint32(p.To.Reg) & 15) << 12 2489 v := int32(c.chipfloat5(p.From.Val.(float64))) 2490 o1 |= (uint32(v) & 0xf) << 0 2491 o1 |= (uint32(v) & 0xf0) << 12 2492 2493 case 82: /* fcmp freg,freg, */ 2494 o1 = c.oprrr(p, p.As, int(p.Scond)) 2495 2496 o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0 2497 o2 = 0x0ef1fa10 // VMRS R15 2498 o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2499 2500 case 83: /* fcmp freg,, */ 2501 o1 = c.oprrr(p, p.As, int(p.Scond)) 2502 2503 o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16 2504 o2 = 0x0ef1fa10 // VMRS R15 2505 o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2506 2507 case 84: /* movfw freg,freg - truncate float-to-fix */ 2508 o1 = c.oprrr(p, p.As, int(p.Scond)) 2509 2510 o1 |= (uint32(p.From.Reg) & 15) << 0 2511 o1 |= (uint32(p.To.Reg) & 15) << 12 2512 2513 case 85: /* movwf freg,freg - fix-to-float */ 2514 o1 = c.oprrr(p, p.As, int(p.Scond)) 2515 2516 o1 |= (uint32(p.From.Reg) & 15) << 0 2517 o1 |= (uint32(p.To.Reg) & 15) << 12 2518 2519 // macro for movfw freg,FTMP; movw FTMP,reg 2520 case 86: /* movfw freg,reg - truncate float-to-fix */ 2521 o1 = c.oprrr(p, p.As, int(p.Scond)) 2522 2523 o1 |= (uint32(p.From.Reg) & 15) << 0 2524 o1 |= (FREGTMP & 15) << 12 2525 o2 = c.oprrr(p, -AMOVFW, int(p.Scond)) 2526 o2 |= (FREGTMP & 15) << 16 2527 o2 |= (uint32(p.To.Reg) & 15) << 12 2528 2529 // macro for movw reg,FTMP; movwf FTMP,freg 2530 case 87: /* movwf reg,freg - fix-to-float */ 2531 o1 = c.oprrr(p, -AMOVWF, int(p.Scond)) 2532 2533 o1 |= (uint32(p.From.Reg) & 15) << 12 2534 o1 |= (FREGTMP & 15) << 16 2535 o2 = c.oprrr(p, p.As, int(p.Scond)) 2536 o2 |= (FREGTMP & 15) << 0 2537 o2 |= (uint32(p.To.Reg) & 15) << 12 2538 2539 case 88: /* movw reg,freg */ 2540 o1 = c.oprrr(p, -AMOVWF, int(p.Scond)) 2541 2542 o1 |= (uint32(p.From.Reg) & 15) << 12 2543 o1 |= (uint32(p.To.Reg) & 15) << 16 2544 2545 case 89: /* movw freg,reg */ 2546 o1 = c.oprrr(p, -AMOVFW, int(p.Scond)) 2547 2548 o1 |= (uint32(p.From.Reg) & 15) << 16 2549 o1 |= (uint32(p.To.Reg) & 15) << 12 2550 2551 case 91: /* ldrexd oreg,reg */ 2552 c.aclass(&p.From) 2553 2554 if c.instoffset != 0 { 2555 c.ctxt.Diag("offset must be zero in LDREX") 2556 } 2557 o1 = 0x1b<<20 | 0xf9f 2558 o1 |= (uint32(p.From.Reg) & 15) << 16 2559 o1 |= (uint32(p.To.Reg) & 15) << 12 2560 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2561 2562 case 92: /* strexd reg,oreg,reg */ 2563 c.aclass(&p.From) 2564 2565 if c.instoffset != 0 { 2566 c.ctxt.Diag("offset must be zero in STREX") 2567 } 2568 o1 = 0x1a<<20 | 0xf90 2569 o1 |= (uint32(p.From.Reg) & 15) << 16 2570 o1 |= (uint32(p.Reg) & 15) << 0 2571 o1 |= (uint32(p.To.Reg) & 15) << 12 2572 o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 2573 2574 case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */ 2575 o1 = c.omvl(p, &p.From, REGTMP) 2576 2577 if o1 == 0 { 2578 break 2579 } 2580 o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond)) 2581 if p.As == AMOVB || p.As == AMOVBS { 2582 o2 ^= 1<<5 | 1<<6 2583 } else if p.As == AMOVH || p.As == AMOVHS { 2584 o2 ^= (1 << 6) 2585 } 2586 if o.flag&LPCREL != 0 { 2587 o3 = o2 2588 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2589 } 2590 2591 case 94: /* movh/movhu R,addr -> strh */ 2592 o1 = c.omvl(p, &p.To, REGTMP) 2593 2594 if o1 == 0 { 2595 break 2596 } 2597 o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond)) 2598 if o.flag&LPCREL != 0 { 2599 o3 = o2 2600 o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12 2601 } 2602 2603 case 95: /* PLD off(reg) */ 2604 o1 = 0xf5d0f000 2605 2606 o1 |= (uint32(p.From.Reg) & 15) << 16 2607 if p.From.Offset < 0 { 2608 o1 &^= (1 << 23) 2609 o1 |= uint32((-p.From.Offset) & 0xfff) 2610 } else { 2611 o1 |= uint32(p.From.Offset & 0xfff) 2612 } 2613 2614 // This is supposed to be something that stops execution. 2615 // It's not supposed to be reached, ever, but if it is, we'd 2616 // like to be able to tell how we got there. Assemble as 2617 // 0xf7fabcfd which is guaranteed to raise undefined instruction 2618 // exception. 2619 case 96: /* UNDEF */ 2620 o1 = 0xf7fabcfd 2621 2622 case 97: /* CLZ Rm, Rd */ 2623 o1 = c.oprrr(p, p.As, int(p.Scond)) 2624 2625 o1 |= (uint32(p.To.Reg) & 15) << 12 2626 o1 |= (uint32(p.From.Reg) & 15) << 0 2627 2628 case 98: /* MULW{T,B} Rs, Rm, Rd */ 2629 o1 = c.oprrr(p, p.As, int(p.Scond)) 2630 2631 o1 |= (uint32(p.To.Reg) & 15) << 16 2632 o1 |= (uint32(p.From.Reg) & 15) << 8 2633 o1 |= (uint32(p.Reg) & 15) << 0 2634 2635 case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */ 2636 o1 = c.oprrr(p, p.As, int(p.Scond)) 2637 2638 o1 |= (uint32(p.To.Reg) & 15) << 16 2639 o1 |= (uint32(p.From.Reg) & 15) << 8 2640 o1 |= (uint32(p.Reg) & 15) << 0 2641 o1 |= uint32((p.To.Offset & 15) << 12) 2642 2643 // DATABUNDLE: BKPT $0x5be0, signify the start of NaCl data bundle; 2644 // DATABUNDLEEND: zero width alignment marker 2645 case 100: 2646 if p.As == ADATABUNDLE { 2647 o1 = 0xe125be70 2648 } 2649 2650 case 105: /* divhw r,[r,]r */ 2651 o1 = c.oprrr(p, p.As, int(p.Scond)) 2652 rf := int(p.From.Reg) 2653 rt := int(p.To.Reg) 2654 r := int(p.Reg) 2655 if r == 0 { 2656 r = rt 2657 } 2658 o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 2659 } 2660 2661 out[0] = o1 2662 out[1] = o2 2663 out[2] = o3 2664 out[3] = o4 2665 out[4] = o5 2666 out[5] = o6 2667 return 2668 } 2669 2670 func (c *ctxt5) mov(p *obj.Prog) uint32 { 2671 c.aclass(&p.From) 2672 o1 := c.oprrr(p, p.As, int(p.Scond)) 2673 o1 |= uint32(p.From.Offset) 2674 rt := int(p.To.Reg) 2675 if p.To.Type == obj.TYPE_NONE { 2676 rt = 0 2677 } 2678 r := int(p.Reg) 2679 if p.As == AMOVW || p.As == AMVN { 2680 r = 0 2681 } else if r == 0 { 2682 r = rt 2683 } 2684 o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12 2685 return o1 2686 } 2687 2688 func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 { 2689 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 2690 if sc&C_SBIT != 0 { 2691 o |= 1 << 20 2692 } 2693 switch a { 2694 case ADIVHW: 2695 return o | 0x71<<20 | 0xf<<12 | 0x1<<4 2696 case ADIVUHW: 2697 return o | 0x73<<20 | 0xf<<12 | 0x1<<4 2698 case AMMUL: 2699 return o | 0x75<<20 | 0xf<<12 | 0x1<<4 2700 case AMULS: 2701 return o | 0x6<<20 | 0x9<<4 2702 case AMMULA: 2703 return o | 0x75<<20 | 0x1<<4 2704 case AMMULS: 2705 return o | 0x75<<20 | 0xd<<4 2706 case AMULU, AMUL: 2707 return o | 0x0<<21 | 0x9<<4 2708 case AMULA: 2709 return o | 0x1<<21 | 0x9<<4 2710 case AMULLU: 2711 return o | 0x4<<21 | 0x9<<4 2712 case AMULL: 2713 return o | 0x6<<21 | 0x9<<4 2714 case AMULALU: 2715 return o | 0x5<<21 | 0x9<<4 2716 case AMULAL: 2717 return o | 0x7<<21 | 0x9<<4 2718 case AAND: 2719 return o | 0x0<<21 2720 case AEOR: 2721 return o | 0x1<<21 2722 case ASUB: 2723 return o | 0x2<<21 2724 case ARSB: 2725 return o | 0x3<<21 2726 case AADD: 2727 return o | 0x4<<21 2728 case AADC: 2729 return o | 0x5<<21 2730 case ASBC: 2731 return o | 0x6<<21 2732 case ARSC: 2733 return o | 0x7<<21 2734 case ATST: 2735 return o | 0x8<<21 | 1<<20 2736 case ATEQ: 2737 return o | 0x9<<21 | 1<<20 2738 case ACMP: 2739 return o | 0xa<<21 | 1<<20 2740 case ACMN: 2741 return o | 0xb<<21 | 1<<20 2742 case AORR: 2743 return o | 0xc<<21 2744 2745 case AMOVB, AMOVH, AMOVW: 2746 if sc&(C_PBIT|C_WBIT) != 0 { 2747 c.ctxt.Diag("invalid .P/.W suffix: %v", p) 2748 } 2749 return o | 0xd<<21 2750 case ABIC: 2751 return o | 0xe<<21 2752 case AMVN: 2753 return o | 0xf<<21 2754 case ASLL: 2755 return o | 0xd<<21 | 0<<5 2756 case ASRL: 2757 return o | 0xd<<21 | 1<<5 2758 case ASRA: 2759 return o | 0xd<<21 | 2<<5 2760 case ASWI: 2761 return o | 0xf<<24 2762 2763 case AADDD: 2764 return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4 2765 case AADDF: 2766 return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4 2767 case ASUBD: 2768 return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4 2769 case ASUBF: 2770 return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4 2771 case AMULD: 2772 return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4 2773 case AMULF: 2774 return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4 2775 case ADIVD: 2776 return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4 2777 case ADIVF: 2778 return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4 2779 case ASQRTD: 2780 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4 2781 case ASQRTF: 2782 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4 2783 case AABSD: 2784 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4 2785 case AABSF: 2786 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4 2787 case ANEGD: 2788 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4 2789 case ANEGF: 2790 return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4 2791 case ACMPD: 2792 return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4 2793 case ACMPF: 2794 return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4 2795 2796 case AMOVF: 2797 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4 2798 case AMOVD: 2799 return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4 2800 2801 case AMOVDF: 2802 return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof 2803 case AMOVFD: 2804 return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof 2805 2806 case AMOVWF: 2807 if sc&C_UBIT == 0 { 2808 o |= 1 << 7 /* signed */ 2809 } 2810 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double 2811 2812 case AMOVWD: 2813 if sc&C_UBIT == 0 { 2814 o |= 1 << 7 /* signed */ 2815 } 2816 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double 2817 2818 case AMOVFW: 2819 if sc&C_UBIT == 0 { 2820 o |= 1 << 16 /* signed */ 2821 } 2822 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc 2823 2824 case AMOVDW: 2825 if sc&C_UBIT == 0 { 2826 o |= 1 << 16 /* signed */ 2827 } 2828 return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc 2829 2830 case -AMOVWF: // copy WtoF 2831 return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4 2832 2833 case -AMOVFW: // copy FtoW 2834 return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4 2835 2836 case -ACMP: // cmp imm 2837 return o | 0x3<<24 | 0x5<<20 2838 2839 // CLZ doesn't support .nil 2840 case ACLZ: 2841 return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4 2842 2843 case AREV: 2844 return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4 2845 2846 case AREV16: 2847 return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4 2848 2849 case AREVSH: 2850 return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4 2851 2852 case ARBIT: 2853 return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4 2854 2855 case AMULWT: 2856 return o&(0xf<<28) | 0x12<<20 | 0xe<<4 2857 2858 case AMULWB: 2859 return o&(0xf<<28) | 0x12<<20 | 0xa<<4 2860 2861 case AMULBB: 2862 return o&(0xf<<28) | 0x16<<20 | 0xf<<12 | 0x8<<4 2863 2864 case AMULAWT: 2865 return o&(0xf<<28) | 0x12<<20 | 0xc<<4 2866 2867 case AMULAWB: 2868 return o&(0xf<<28) | 0x12<<20 | 0x8<<4 2869 2870 case AMULABB: 2871 return o&(0xf<<28) | 0x10<<20 | 0x8<<4 2872 2873 case ABL: // BLX REG 2874 return o&(0xf<<28) | 0x12fff3<<4 2875 } 2876 2877 c.ctxt.Diag("%v: bad rrr %d", p, a) 2878 return 0 2879 } 2880 2881 func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 { 2882 sc &= C_SCOND 2883 sc ^= C_SCOND_XOR 2884 if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY { 2885 return uint32(sc)<<28 | 0x5<<25 | 0x1<<24 2886 } 2887 if sc != 0xe { 2888 c.ctxt.Diag("%v: .COND on bcond instruction", p) 2889 } 2890 switch a { 2891 case ABEQ: 2892 return 0x0<<28 | 0x5<<25 2893 case ABNE: 2894 return 0x1<<28 | 0x5<<25 2895 case ABCS: 2896 return 0x2<<28 | 0x5<<25 2897 case ABHS: 2898 return 0x2<<28 | 0x5<<25 2899 case ABCC: 2900 return 0x3<<28 | 0x5<<25 2901 case ABLO: 2902 return 0x3<<28 | 0x5<<25 2903 case ABMI: 2904 return 0x4<<28 | 0x5<<25 2905 case ABPL: 2906 return 0x5<<28 | 0x5<<25 2907 case ABVS: 2908 return 0x6<<28 | 0x5<<25 2909 case ABVC: 2910 return 0x7<<28 | 0x5<<25 2911 case ABHI: 2912 return 0x8<<28 | 0x5<<25 2913 case ABLS: 2914 return 0x9<<28 | 0x5<<25 2915 case ABGE: 2916 return 0xa<<28 | 0x5<<25 2917 case ABLT: 2918 return 0xb<<28 | 0x5<<25 2919 case ABGT: 2920 return 0xc<<28 | 0x5<<25 2921 case ABLE: 2922 return 0xd<<28 | 0x5<<25 2923 case AB: 2924 return 0xe<<28 | 0x5<<25 2925 } 2926 2927 c.ctxt.Diag("%v: bad bra %v", p, a) 2928 return 0 2929 } 2930 2931 func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 { 2932 if sc&C_SBIT != 0 { 2933 c.ctxt.Diag(".nil on LDR/STR instruction") 2934 } 2935 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 2936 if sc&C_PBIT == 0 { 2937 o |= 1 << 24 2938 } 2939 if sc&C_UBIT == 0 { 2940 o |= 1 << 23 2941 } 2942 if sc&C_WBIT != 0 { 2943 o |= 1 << 21 2944 } 2945 o |= 1<<26 | 1<<20 2946 if v < 0 { 2947 if sc&C_UBIT != 0 { 2948 c.ctxt.Diag(".U on neg offset") 2949 } 2950 v = -v 2951 o ^= 1 << 23 2952 } 2953 2954 if v >= 1<<12 || v < 0 { 2955 c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp) 2956 } 2957 o |= uint32(v) 2958 o |= (uint32(b) & 15) << 16 2959 o |= (uint32(r) & 15) << 12 2960 return o 2961 } 2962 2963 func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 { 2964 if sc&C_SBIT != 0 { 2965 c.ctxt.Diag(".nil on LDRH/STRH instruction") 2966 } 2967 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 2968 if sc&C_PBIT == 0 { 2969 o |= 1 << 24 2970 } 2971 if sc&C_WBIT != 0 { 2972 o |= 1 << 21 2973 } 2974 o |= 1<<23 | 1<<20 | 0xb<<4 2975 if v < 0 { 2976 v = -v 2977 o ^= 1 << 23 2978 } 2979 2980 if v >= 1<<8 || v < 0 { 2981 c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp) 2982 } 2983 o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22 2984 o |= (uint32(b) & 15) << 16 2985 o |= (uint32(r) & 15) << 12 2986 return o 2987 } 2988 2989 func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 { 2990 o := c.olr(v, b, r, sc) ^ (1 << 20) 2991 if a != AMOVW { 2992 o |= 1 << 22 2993 } 2994 return o 2995 } 2996 2997 func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 { 2998 o := c.olhr(v, b, r, sc) ^ (1 << 20) 2999 return o 3000 } 3001 3002 func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 { 3003 return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20) 3004 } 3005 3006 func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 { 3007 return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20) 3008 } 3009 3010 func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 { 3011 return c.olr(int32(i), b, r, sc) ^ (1 << 25) 3012 } 3013 3014 func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 { 3015 return c.olhr(int32(i), b, r, sc) ^ (1 << 22) 3016 } 3017 3018 func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 { 3019 o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28 3020 if sc&C_PBIT == 0 { 3021 o |= 1 << 24 3022 } 3023 if sc&C_WBIT != 0 { 3024 o |= 1 << 21 3025 } 3026 o |= 6<<25 | 1<<24 | 1<<23 | 10<<8 3027 if v < 0 { 3028 v = -v 3029 o ^= 1 << 23 3030 } 3031 3032 if v&3 != 0 { 3033 c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p) 3034 } else if v >= 1<<10 || v < 0 { 3035 c.ctxt.Diag("literal span too large: %d\n%v", v, p) 3036 } 3037 o |= (uint32(v) >> 2) & 0xFF 3038 o |= (uint32(b) & 15) << 16 3039 o |= (uint32(r) & 15) << 12 3040 3041 switch a { 3042 default: 3043 c.ctxt.Diag("bad fst %v", a) 3044 fallthrough 3045 3046 case AMOVD: 3047 o |= 1 << 8 3048 fallthrough 3049 3050 case AMOVF: 3051 break 3052 } 3053 3054 return o 3055 } 3056 3057 // MOVW $"lower 16-bit", Reg 3058 func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 { 3059 var o1 uint32 3060 o1 = ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28 3061 o1 |= 0x30 << 20 3062 o1 |= (uint32(dr) & 15) << 12 3063 o1 |= uint32(a.Offset) & 0x0fff 3064 o1 |= (uint32(a.Offset) & 0xf000) << 4 3065 return o1 3066 } 3067 3068 func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 { 3069 var o1 uint32 3070 if p.Pcond == nil { 3071 c.aclass(a) 3072 v := immrot(^uint32(c.instoffset)) 3073 if v == 0 { 3074 c.ctxt.Diag("%v: missing literal", p) 3075 return 0 3076 } 3077 3078 o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND) 3079 o1 |= uint32(v) 3080 o1 |= (uint32(dr) & 15) << 12 3081 } else { 3082 v := int32(p.Pcond.Pc - p.Pc - 8) 3083 o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND) 3084 } 3085 3086 return o1 3087 } 3088 3089 func (c *ctxt5) chipzero5(e float64) int { 3090 // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions. 3091 if objabi.GOARM < 7 || e != 0 { 3092 return -1 3093 } 3094 return 0 3095 } 3096 3097 func (c *ctxt5) chipfloat5(e float64) int { 3098 // We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions. 3099 if objabi.GOARM < 7 { 3100 return -1 3101 } 3102 3103 ei := math.Float64bits(e) 3104 l := uint32(ei) 3105 h := uint32(ei >> 32) 3106 3107 if l != 0 || h&0xffff != 0 { 3108 return -1 3109 } 3110 h1 := h & 0x7fc00000 3111 if h1 != 0x40000000 && h1 != 0x3fc00000 { 3112 return -1 3113 } 3114 n := 0 3115 3116 // sign bit (a) 3117 if h&0x80000000 != 0 { 3118 n |= 1 << 7 3119 } 3120 3121 // exp sign bit (b) 3122 if h1 == 0x3fc00000 { 3123 n |= 1 << 6 3124 } 3125 3126 // rest of exp and mantissa (cd-efgh) 3127 n |= int((h >> 16) & 0x3f) 3128 3129 //print("match %.8lux %.8lux %d\n", l, h, n); 3130 return n 3131 } 3132 3133 func nocache(p *obj.Prog) { 3134 p.Optab = 0 3135 p.From.Class = 0 3136 if p.From3 != nil { 3137 p.From3.Class = 0 3138 } 3139 p.To.Class = 0 3140 }