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