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