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