github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/liblink/asm9.c (about) 1 // cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova. 2 // 3 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 4 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 5 // Portions Copyright © 1997-1999 Vita Nuova Limited 6 // Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com) 7 // Portions Copyright © 2004,2006 Bruce Ellis 8 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 9 // Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others 10 // Portions Copyright © 2009 The Go Authors. All rights reserved. 11 // 12 // Permission is hereby granted, free of charge, to any person obtaining a copy 13 // of this software and associated documentation files (the "Software"), to deal 14 // in the Software without restriction, including without limitation the rights 15 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 // copies of the Software, and to permit persons to whom the Software is 17 // furnished to do so, subject to the following conditions: 18 // 19 // The above copyright notice and this permission notice shall be included in 20 // all copies or substantial portions of the Software. 21 // 22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 // THE SOFTWARE. 29 30 // Instruction layout. 31 32 #include <u.h> 33 #include <libc.h> 34 #include <bio.h> 35 #include <link.h> 36 #include "../cmd/9l/9.out.h" 37 #include "../runtime/stack.h" 38 39 enum { 40 FuncAlign = 8, 41 }; 42 43 enum { 44 r0iszero = 1, 45 }; 46 47 typedef struct Optab Optab; 48 49 struct Optab 50 { 51 short as; 52 uchar a1; 53 uchar a2; 54 uchar a3; 55 uchar a4; 56 char type; 57 char size; 58 char param; 59 }; 60 61 static Optab optab[] = { 62 { ATEXT, C_LEXT, C_NONE, C_NONE, C_LCON, 0, 0, 0 }, 63 { ATEXT, C_LEXT, C_REG, C_NONE, C_LCON, 0, 0, 0 }, 64 { ATEXT, C_LEXT, C_NONE, C_LCON, C_LCON, 0, 0, 0 }, 65 { ATEXT, C_LEXT, C_REG, C_LCON, C_LCON, 0, 0, 0 }, 66 { ATEXT, C_ADDR, C_NONE, C_NONE, C_LCON, 0, 0, 0 }, 67 { ATEXT, C_ADDR, C_REG, C_NONE, C_LCON, 0, 0, 0 }, 68 { ATEXT, C_ADDR, C_NONE, C_LCON, C_LCON, 0, 0, 0 }, 69 { ATEXT, C_ADDR, C_REG, C_LCON, C_LCON, 0, 0, 0 }, 70 71 /* move register */ 72 { AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0 }, 73 { AMOVB, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0 }, 74 { AMOVBZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0 }, 75 { AMOVW, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0 }, 76 { AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0 }, 77 78 { AADD, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0 }, 79 { AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0 }, 80 { AADD, C_ADDCON,C_REG, C_NONE, C_REG, 4, 4, 0 }, 81 { AADD, C_ADDCON,C_NONE, C_NONE, C_REG, 4, 4, 0 }, 82 { AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 4, 0 }, 83 { AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 4, 0 }, 84 { AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0 }, 85 { AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0 }, 86 87 { AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0 }, 88 { AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0 }, 89 { AADDC, C_ADDCON,C_REG, C_NONE, C_REG, 4, 4, 0 }, 90 { AADDC, C_ADDCON,C_NONE, C_NONE, C_REG, 4, 4, 0 }, 91 { AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0 }, 92 { AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0 }, 93 94 { AAND, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0 }, /* logical, no literal */ 95 { AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0 }, 96 { AANDCC, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0 }, 97 { AANDCC, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0 }, 98 99 { AANDCC, C_ANDCON,C_NONE, C_NONE, C_REG, 58, 4, 0 }, 100 { AANDCC, C_ANDCON,C_REG, C_NONE, C_REG, 58, 4, 0 }, 101 { AANDCC, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0 }, 102 { AANDCC, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0 }, 103 { AANDCC, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0 }, 104 { AANDCC, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0 }, 105 106 { AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0 }, 107 { AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0 }, 108 { AMULLW, C_ADDCON,C_REG, C_NONE, C_REG, 4, 4, 0 }, 109 { AMULLW, C_ADDCON,C_NONE, C_NONE, C_REG, 4, 4, 0 }, 110 { AMULLW, C_ANDCON,C_REG, C_NONE, C_REG, 4, 4, 0 }, 111 { AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 4, 0 }, 112 { AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0}, 113 { AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0}, 114 115 { ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0 }, 116 { ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0 }, 117 { ASUBC, C_REG, C_NONE, C_ADDCON, C_REG, 27, 4, 0 }, 118 { ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 12, 0}, 119 120 { AOR, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0 }, /* logical, literal not cc (or/xor) */ 121 { AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0 }, 122 { AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0 }, 123 { AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0 }, 124 { AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0 }, 125 { AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0 }, 126 { AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0 }, 127 { AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0 }, 128 129 { ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0 }, /* op r1[,r2],r3 */ 130 { ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0 }, 131 { ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0 }, /* op r2[,r1],r3 */ 132 { ASUB, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0 }, 133 134 { ASLW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0 }, 135 { ASLW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0 }, 136 { ASLD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0 }, 137 { ASLD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0 }, 138 { ASLD, C_SCON, C_REG, C_NONE, C_REG, 25, 4, 0 }, 139 { ASLD, C_SCON, C_NONE, C_NONE, C_REG, 25, 4, 0 }, 140 { ASLW, C_SCON, C_REG, C_NONE, C_REG, 57, 4, 0 }, 141 { ASLW, C_SCON, C_NONE, C_NONE, C_REG, 57, 4, 0 }, 142 143 { ASRAW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0 }, 144 { ASRAW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0 }, 145 { ASRAW, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0 }, 146 { ASRAW, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0 }, 147 { ASRAD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0 }, 148 { ASRAD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0 }, 149 { ASRAD, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0 }, 150 { ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0 }, 151 152 { ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0 }, 153 { ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0 }, 154 { ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0 }, 155 156 { ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0 }, 157 { ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0 }, 158 { ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0 }, 159 { ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0 }, 160 161 { AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0 }, 162 { AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 4, 0 }, 163 { AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0 }, 164 { AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 4, 0 }, 165 { AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0 }, 166 167 { AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 4, 0 }, 168 { AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 4, 0 }, 169 { AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 4, 0 }, 170 171 /* store, short offset */ 172 { AMOVD, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO }, 173 { AMOVW, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO }, 174 { AMOVWZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO }, 175 { AMOVBZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO }, 176 { AMOVBZU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO }, 177 { AMOVB, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO }, 178 { AMOVBU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO }, 179 { AMOVD, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB }, 180 { AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB }, 181 { AMOVWZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB }, 182 { AMOVBZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB }, 183 { AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB }, 184 { AMOVD, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP }, 185 { AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP }, 186 { AMOVWZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP }, 187 { AMOVBZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP }, 188 { AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP }, 189 { AMOVD, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO }, 190 { AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO }, 191 { AMOVWZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO }, 192 { AMOVBZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO }, 193 { AMOVBZU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO }, 194 { AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO }, 195 { AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO }, 196 197 /* load, short offset */ 198 { AMOVD, C_ZOREG,C_REG, C_NONE, C_REG, 8, 4, REGZERO }, 199 { AMOVW, C_ZOREG,C_REG, C_NONE, C_REG, 8, 4, REGZERO }, 200 { AMOVWZ, C_ZOREG,C_REG, C_NONE, C_REG, 8, 4, REGZERO }, 201 { AMOVBZ, C_ZOREG,C_REG, C_NONE, C_REG, 8, 4, REGZERO }, 202 { AMOVBZU, C_ZOREG,C_REG, C_NONE, C_REG, 8, 4, REGZERO }, 203 { AMOVB, C_ZOREG,C_REG, C_NONE, C_REG, 9, 8, REGZERO }, 204 { AMOVBU, C_ZOREG,C_REG, C_NONE, C_REG, 9, 8, REGZERO }, 205 { AMOVD, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB }, 206 { AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB }, 207 { AMOVWZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB }, 208 { AMOVBZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB }, 209 { AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, 9, 8, REGSB }, 210 { AMOVD, C_SAUTO,C_NONE, C_NONE, C_REG, 8, 4, REGSP }, 211 { AMOVW, C_SAUTO,C_NONE, C_NONE, C_REG, 8, 4, REGSP }, 212 { AMOVWZ, C_SAUTO,C_NONE, C_NONE, C_REG, 8, 4, REGSP }, 213 { AMOVBZ, C_SAUTO,C_NONE, C_NONE, C_REG, 8, 4, REGSP }, 214 { AMOVB, C_SAUTO,C_NONE, C_NONE, C_REG, 9, 8, REGSP }, 215 { AMOVD, C_SOREG,C_NONE, C_NONE, C_REG, 8, 4, REGZERO }, 216 { AMOVW, C_SOREG,C_NONE, C_NONE, C_REG, 8, 4, REGZERO }, 217 { AMOVWZ, C_SOREG,C_NONE, C_NONE, C_REG, 8, 4, REGZERO }, 218 { AMOVBZ, C_SOREG,C_NONE, C_NONE, C_REG, 8, 4, REGZERO }, 219 { AMOVBZU, C_SOREG,C_NONE, C_NONE, C_REG, 8, 4, REGZERO }, 220 { AMOVB, C_SOREG,C_NONE, C_NONE, C_REG, 9, 8, REGZERO }, 221 { AMOVBU, C_SOREG,C_NONE, C_NONE, C_REG, 9, 8, REGZERO }, 222 223 /* store, long offset */ 224 { AMOVD, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB }, 225 { AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB }, 226 { AMOVWZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB }, 227 { AMOVBZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB }, 228 { AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB }, 229 { AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP }, 230 { AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP }, 231 { AMOVWZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP }, 232 { AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP }, 233 { AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP }, 234 { AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, 235 { AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, 236 { AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, 237 { AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, 238 { AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, 239 { AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0 }, 240 { AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0 }, 241 { AMOVWZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0 }, 242 { AMOVBZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0 }, 243 { AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0 }, 244 245 /* load, long offset */ 246 { AMOVD, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB }, 247 { AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB }, 248 { AMOVWZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB }, 249 { AMOVBZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB }, 250 { AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, 37, 12, REGSB }, 251 { AMOVD, C_LAUTO,C_NONE, C_NONE, C_REG, 36, 8, REGSP }, 252 { AMOVW, C_LAUTO,C_NONE, C_NONE, C_REG, 36, 8, REGSP }, 253 { AMOVWZ, C_LAUTO,C_NONE, C_NONE, C_REG, 36, 8, REGSP }, 254 { AMOVBZ, C_LAUTO,C_NONE, C_NONE, C_REG, 36, 8, REGSP }, 255 { AMOVB, C_LAUTO,C_NONE, C_NONE, C_REG, 37, 12, REGSP }, 256 { AMOVD, C_LOREG,C_NONE, C_NONE, C_REG, 36, 8, REGZERO }, 257 { AMOVW, C_LOREG,C_NONE, C_NONE, C_REG, 36, 8, REGZERO }, 258 { AMOVWZ, C_LOREG,C_NONE, C_NONE, C_REG, 36, 8, REGZERO }, 259 { AMOVBZ, C_LOREG,C_NONE, C_NONE, C_REG, 36, 8, REGZERO }, 260 { AMOVB, C_LOREG,C_NONE, C_NONE, C_REG, 37, 12, REGZERO }, 261 { AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0 }, 262 { AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0 }, 263 { AMOVWZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0 }, 264 { AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0 }, 265 { AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0 }, 266 267 /* load constant */ 268 { AMOVD, C_SECON,C_NONE, C_NONE, C_REG, 3, 4, REGSB }, 269 { AMOVD, C_SACON,C_NONE, C_NONE, C_REG, 3, 4, REGSP }, 270 { AMOVD, C_LECON,C_NONE, C_NONE, C_REG, 26, 8, REGSB }, 271 { AMOVD, C_LACON,C_NONE, C_NONE, C_REG, 26, 8, REGSP }, 272 { AMOVD, C_ADDCON,C_NONE, C_NONE, C_REG, 3, 4, REGZERO }, 273 { AMOVW, C_SECON,C_NONE, C_NONE, C_REG, 3, 4, REGSB }, /* TO DO: check */ 274 { AMOVW, C_SACON,C_NONE, C_NONE, C_REG, 3, 4, REGSP }, 275 { AMOVW, C_LECON,C_NONE, C_NONE, C_REG, 26, 8, REGSB }, 276 { AMOVW, C_LACON,C_NONE, C_NONE, C_REG, 26, 8, REGSP }, 277 { AMOVW, C_ADDCON,C_NONE, C_NONE, C_REG, 3, 4, REGZERO }, 278 { AMOVWZ, C_SECON,C_NONE, C_NONE, C_REG, 3, 4, REGSB }, /* TO DO: check */ 279 { AMOVWZ, C_SACON,C_NONE, C_NONE, C_REG, 3, 4, REGSP }, 280 { AMOVWZ, C_LECON,C_NONE, C_NONE, C_REG, 26, 8, REGSB }, 281 { AMOVWZ, C_LACON,C_NONE, C_NONE, C_REG, 26, 8, REGSP }, 282 { AMOVWZ, C_ADDCON,C_NONE, C_NONE, C_REG, 3, 4, REGZERO }, 283 284 /* load unsigned/long constants (TO DO: check) */ 285 { AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO }, 286 { AMOVD, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0 }, 287 { AMOVW, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO }, 288 { AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0 }, 289 { AMOVWZ, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO }, 290 { AMOVWZ, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0 }, 291 292 { AMOVHBR, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0 }, 293 { AMOVHBR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0 }, 294 { AMOVHBR, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0 }, 295 { AMOVHBR, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0 }, 296 297 { ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0 }, 298 { ASYSCALL, C_REG, C_NONE, C_NONE, C_NONE, 77, 12, 0 }, 299 { ASYSCALL, C_SCON, C_NONE, C_NONE, C_NONE, 77, 12, 0 }, 300 301 { ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0 }, 302 { ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0 }, 303 304 { ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 }, 305 306 { ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0 }, 307 { ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0 }, 308 309 { ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0 }, 310 { ABR, C_NONE, C_NONE, C_NONE, C_CTR, 18, 4, 0 }, 311 { ABR, C_REG, C_NONE, C_NONE, C_CTR, 18, 4, 0 }, 312 { ABR, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0 }, 313 314 { ABC, C_NONE, C_REG, C_NONE, C_LR, 18, 4, 0 }, 315 { ABC, C_NONE, C_REG, C_NONE, C_CTR, 18, 4, 0 }, 316 { ABC, C_SCON, C_REG, C_NONE, C_LR, 18, 4, 0 }, 317 { ABC, C_SCON, C_REG, C_NONE, C_CTR, 18, 4, 0 }, 318 { ABC, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0 }, 319 320 { AFMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, 8, 4, REGSB }, 321 { AFMOVD, C_SAUTO,C_NONE, C_NONE, C_FREG, 8, 4, REGSP }, 322 { AFMOVD, C_SOREG,C_NONE, C_NONE, C_FREG, 8, 4, REGZERO }, 323 324 { AFMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, 36, 8, REGSB }, 325 { AFMOVD, C_LAUTO,C_NONE, C_NONE, C_FREG, 36, 8, REGSP }, 326 { AFMOVD, C_LOREG,C_NONE, C_NONE, C_FREG, 36, 8, REGZERO }, 327 { AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 75, 8, 0 }, 328 329 { AFMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB }, 330 { AFMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP }, 331 { AFMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO }, 332 333 { AFMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB }, 334 { AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP }, 335 { AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO }, 336 { AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0 }, 337 338 { ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0 }, 339 { AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0 }, 340 { ADWORD, C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0 }, 341 { ADWORD, C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0 }, 342 343 { AADDME, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0 }, 344 345 { AEXTSB, C_REG, C_NONE, C_NONE, C_REG, 48, 4, 0 }, 346 { AEXTSB, C_NONE, C_NONE, C_NONE, C_REG, 48, 4, 0 }, 347 348 { ANEG, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0 }, 349 { ANEG, C_NONE, C_NONE, C_NONE, C_REG, 47, 4, 0 }, 350 351 { AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0 }, 352 { AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0 }, 353 { AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0 }, 354 { AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0 }, 355 { AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0 }, 356 { AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0 }, 357 { AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0 }, 358 { AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0 }, 359 360 { AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0 }, 361 { AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0 }, 362 { AMOVFL, C_FREG, C_NONE, C_NONE, C_FPSCR, 64, 4, 0 }, 363 { AMOVFL, C_FREG, C_NONE, C_LCON, C_FPSCR, 64, 4, 0 }, 364 { AMOVFL, C_LCON, C_NONE, C_NONE, C_FPSCR, 65, 4, 0 }, 365 366 { AMOVD, C_MSR, C_NONE, C_NONE, C_REG, 54, 4, 0 }, /* mfmsr */ 367 { AMOVD, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0 }, /* mtmsrd */ 368 { AMOVWZ, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0 }, /* mtmsr */ 369 370 /* 64-bit special registers */ 371 { AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0 }, 372 { AMOVD, C_REG, C_NONE, C_NONE, C_LR, 66, 4, 0 }, 373 { AMOVD, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0 }, 374 { AMOVD, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0 }, 375 { AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0 }, 376 { AMOVD, C_LR, C_NONE, C_NONE, C_REG, 66, 4, 0 }, 377 { AMOVD, C_CTR, C_NONE, C_NONE, C_REG, 66, 4, 0 }, 378 { AMOVD, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0 }, 379 380 /* 32-bit special registers (gloss over sign-extension or not?) */ 381 { AMOVW, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0 }, 382 { AMOVW, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0 }, 383 { AMOVW, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0 }, 384 { AMOVW, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0 }, 385 { AMOVW, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0 }, 386 387 { AMOVWZ, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0 }, 388 { AMOVWZ, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0 }, 389 { AMOVWZ, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0 }, 390 { AMOVWZ, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0 }, 391 { AMOVWZ, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0 }, 392 393 { AMOVFL, C_FPSCR, C_NONE, C_NONE, C_CREG, 73, 4, 0 }, 394 { AMOVFL, C_CREG, C_NONE, C_NONE, C_CREG, 67, 4, 0 }, 395 { AMOVW, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0 }, 396 { AMOVWZ, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0 }, 397 { AMOVFL, C_REG, C_NONE, C_LCON, C_CREG, 69, 4, 0 }, 398 { AMOVFL, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0 }, 399 { AMOVW, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0 }, 400 { AMOVWZ, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0 }, 401 402 { ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0 }, 403 { ACMP, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0 }, 404 { ACMP, C_REG, C_NONE, C_NONE, C_ADDCON, 71, 4, 0 }, 405 { ACMP, C_REG, C_REG, C_NONE, C_ADDCON, 71, 4, 0 }, 406 407 { ACMPU, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0 }, 408 { ACMPU, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0 }, 409 { ACMPU, C_REG, C_NONE, C_NONE, C_ANDCON, 71, 4, 0 }, 410 { ACMPU, C_REG, C_REG, C_NONE, C_ANDCON, 71, 4, 0 }, 411 412 { AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 4, 0 }, 413 { AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 4, 0 }, 414 415 { ATW, C_LCON, C_REG, C_NONE, C_REG, 60, 4, 0 }, 416 { ATW, C_LCON, C_REG, C_NONE, C_ADDCON, 61, 4, 0 }, 417 418 { ADCBF, C_ZOREG, C_NONE, C_NONE, C_NONE, 43, 4, 0 }, 419 { ADCBF, C_ZOREG, C_REG, C_NONE, C_NONE, 43, 4, 0 }, 420 421 { AECOWX, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0 }, 422 { AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0 }, 423 { AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0 }, 424 { AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0 }, 425 426 { AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0 }, 427 { ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0 }, 428 { ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0 }, 429 { ASLBMFEE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0 }, 430 { ASLBMTE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0 }, 431 432 { ASTSW, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0 }, 433 { ASTSW, C_REG, C_NONE, C_LCON, C_ZOREG, 41, 4, 0 }, 434 { ALSW, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0 }, 435 { ALSW, C_ZOREG, C_NONE, C_LCON, C_REG, 42, 4, 0 }, 436 437 { AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0 }, 438 { AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0 }, 439 { APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0 }, 440 { AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0 }, 441 { ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0 }, 442 443 { ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 }, // same as ABR/ABL 444 { ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0 }, // same as ABR/ABL 445 446 { AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0 }, 447 }; 448 449 static int ocmp(const void *, const void *); 450 static int cmp(int, int); 451 static void buildop(Link*); 452 static void prasm(Prog *); 453 static int isint32(vlong); 454 static int isuint32(uvlong); 455 static int aclass(Link*, Addr*); 456 static Optab* oplook(Link*, Prog*); 457 static void asmout(Link*, Prog*, Optab*, int32*); 458 static vlong vregoff(Link*, Addr*); 459 static int32 regoff(Link*, Addr*); 460 static int32 oprrr(Link*, int); 461 static int32 opirr(Link*, int); 462 static int32 opload(Link*, int); 463 static int32 opstore(Link*, int); 464 static int32 oploadx(Link*, int); 465 static int32 opstorex(Link*, int); 466 static int getmask(uchar*, uint32); 467 static void maskgen(Link*, Prog*, uchar*, uint32); 468 static int getmask64(uchar*, uvlong); 469 static void maskgen64(Link*, Prog*, uchar*, uvlong); 470 static uint32 loadu32(int, vlong); 471 static void addaddrreloc(Link*, LSym*, int*, int*); 472 473 static struct 474 { 475 Optab* start; 476 Optab* stop; 477 } oprange[ALAST]; 478 479 static uchar xcmp[C_NCLASS][C_NCLASS]; 480 481 482 void 483 span9(Link *ctxt, LSym *cursym) 484 { 485 Prog *p, *q; 486 Optab *o; 487 int m, bflag; 488 vlong c, otxt; 489 int32 out[6], i, j; 490 uchar *bp, *cast; 491 492 p = cursym->text; 493 if(p == nil || p->link == nil) // handle external functions and ELF section symbols 494 return; 495 ctxt->cursym = cursym; 496 ctxt->autosize = (int32)(p->to.offset & 0xffffffffll) + 8; 497 498 if(oprange[AANDN].start == nil) 499 buildop(ctxt); 500 501 c = 0; 502 p->pc = c; 503 504 for(p = p->link; p != nil; p = p->link) { 505 ctxt->curp = p; 506 p->pc = c; 507 o = oplook(ctxt, p); 508 m = o->size; 509 if(m == 0) { 510 if(p->as != ANOP && p->as != AFUNCDATA && p->as != APCDATA) 511 ctxt->diag("zero-width instruction\n%P", p); 512 continue; 513 } 514 c += m; 515 } 516 cursym->size = c; 517 518 /* 519 * if any procedure is large enough to 520 * generate a large SBRA branch, then 521 * generate extra passes putting branches 522 * around jmps to fix. this is rare. 523 */ 524 bflag = 1; 525 while(bflag) { 526 if(ctxt->debugvlog) 527 Bprint(ctxt->bso, "%5.2f span1\n", cputime()); 528 bflag = 0; 529 c = 0; 530 for(p = cursym->text->link; p != nil; p = p->link) { 531 p->pc = c; 532 o = oplook(ctxt, p); 533 534 // very large conditional branches 535 if((o->type == 16 || o->type == 17) && p->pcond) { 536 otxt = p->pcond->pc - c; 537 if(otxt < -(1L<<15)+10 || otxt >= (1L<<15)-10) { 538 q = ctxt->arch->prg(); 539 q->link = p->link; 540 p->link = q; 541 q->as = ABR; 542 q->to.type = D_BRANCH; 543 q->pcond = p->pcond; 544 p->pcond = q; 545 q = ctxt->arch->prg(); 546 q->link = p->link; 547 p->link = q; 548 q->as = ABR; 549 q->to.type = D_BRANCH; 550 q->pcond = q->link->link; 551 //addnop(p->link); 552 //addnop(p); 553 bflag = 1; 554 } 555 } 556 557 m = o->size; 558 if(m == 0) { 559 if(p->as != ANOP && p->as != AFUNCDATA && p->as != APCDATA) 560 ctxt->diag("zero-width instruction\n%P", p); 561 continue; 562 } 563 c += m; 564 } 565 cursym->size = c; 566 } 567 568 c += -c&(FuncAlign-1); 569 cursym->size = c; 570 571 /* 572 * lay out the code, emitting code and data relocations. 573 */ 574 if(ctxt->tlsg == nil) 575 ctxt->tlsg = linklookup(ctxt, "runtime.tlsg", 0); 576 577 symgrow(ctxt, cursym, cursym->size); 578 579 bp = cursym->p; 580 for(p = cursym->text->link; p != nil; p = p->link) { 581 ctxt->pc = p->pc; 582 ctxt->curp = p; 583 o = oplook(ctxt, p); 584 if(o->size > 4*nelem(out)) 585 sysfatal("out array in span9 is too small, need at least %d for %P", o->size/4, p); 586 asmout(ctxt, p, o, out); 587 for(i=0; i<o->size/4; i++) { 588 cast = (uchar*)&out[i]; 589 for(j=0; j<4; j++) 590 *bp++ = cast[inuxi4[j]]; 591 } 592 } 593 } 594 595 static int 596 isint32(vlong v) 597 { 598 return (int32)v == v; 599 } 600 601 static int 602 isuint32(uvlong v) 603 { 604 return (uint32)v == v; 605 } 606 607 static int 608 aclass(Link *ctxt, Addr *a) 609 { 610 LSym *s; 611 612 switch(a->type) { 613 case D_NONE: 614 return C_NONE; 615 616 case D_REG: 617 return C_REG; 618 619 case D_FREG: 620 return C_FREG; 621 622 case D_CREG: 623 return C_CREG; 624 625 case D_SPR: 626 if(a->offset == D_LR) 627 return C_LR; 628 if(a->offset == D_XER) 629 return C_XER; 630 if(a->offset == D_CTR) 631 return C_CTR; 632 return C_SPR; 633 634 case D_DCR: 635 return C_SPR; 636 637 case D_FPSCR: 638 return C_FPSCR; 639 640 case D_MSR: 641 return C_MSR; 642 643 case D_OREG: 644 switch(a->name) { 645 case D_EXTERN: 646 case D_STATIC: 647 if(a->sym == nil) 648 break; 649 ctxt->instoffset = a->offset; 650 if(a->sym != nil) // use relocation 651 return C_ADDR; 652 return C_LEXT; 653 case D_AUTO: 654 ctxt->instoffset = ctxt->autosize + a->offset; 655 if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) 656 return C_SAUTO; 657 return C_LAUTO; 658 case D_PARAM: 659 ctxt->instoffset = ctxt->autosize + a->offset + 8L; 660 if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) 661 return C_SAUTO; 662 return C_LAUTO; 663 case D_NONE: 664 ctxt->instoffset = a->offset; 665 if(ctxt->instoffset == 0) 666 return C_ZOREG; 667 if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) 668 return C_SOREG; 669 return C_LOREG; 670 } 671 return C_GOK; 672 673 case D_OPT: 674 ctxt->instoffset = a->offset & 31L; 675 if(a->name == D_NONE) 676 return C_SCON; 677 return C_GOK; 678 679 case D_CONST: 680 switch(a->name) { 681 case D_NONE: 682 ctxt->instoffset = a->offset; 683 if(a->reg != NREG) { 684 if(-BIG <= ctxt->instoffset && ctxt->instoffset <= BIG) 685 return C_SACON; 686 return C_LACON; 687 } 688 consize: 689 if(ctxt->instoffset >= 0) { 690 if(ctxt->instoffset == 0) 691 return C_ZCON; 692 if(ctxt->instoffset <= 0x7fff) 693 return C_SCON; 694 if(ctxt->instoffset <= 0xffff) 695 return C_ANDCON; 696 if((ctxt->instoffset & 0xffff) == 0 && isuint32(ctxt->instoffset)) /* && (instoffset & (1<<31)) == 0) */ 697 return C_UCON; 698 if(isint32(ctxt->instoffset) || isuint32(ctxt->instoffset)) 699 return C_LCON; 700 return C_DCON; 701 } 702 if(ctxt->instoffset >= -0x8000) 703 return C_ADDCON; 704 if((ctxt->instoffset & 0xffff) == 0 && isint32(ctxt->instoffset)) 705 return C_UCON; 706 if(isint32(ctxt->instoffset)) 707 return C_LCON; 708 return C_DCON; 709 710 case D_EXTERN: 711 case D_STATIC: 712 s = a->sym; 713 if(s == nil) 714 break; 715 if(s->type == SCONST) { 716 ctxt->instoffset = s->value + a->offset; 717 goto consize; 718 } 719 ctxt->instoffset = s->value + a->offset; 720 /* not sure why this barfs */ 721 return C_LCON; 722 723 case D_AUTO: 724 ctxt->instoffset = ctxt->autosize + a->offset; 725 if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) 726 return C_SACON; 727 return C_LACON; 728 729 case D_PARAM: 730 ctxt->instoffset = ctxt->autosize + a->offset + 8L; 731 if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) 732 return C_SACON; 733 return C_LACON; 734 } 735 return C_GOK; 736 737 case D_BRANCH: 738 return C_SBRA; 739 } 740 return C_GOK; 741 } 742 743 static void 744 prasm(Prog *p) 745 { 746 print("%P\n", p); 747 } 748 749 static Optab* 750 oplook(Link *ctxt, Prog *p) 751 { 752 int a1, a2, a3, a4, r; 753 uchar *c1, *c3, *c4; 754 Optab *o, *e; 755 756 a1 = p->optab; 757 if(a1) 758 return optab+(a1-1); 759 a1 = p->from.class; 760 if(a1 == 0) { 761 a1 = aclass(ctxt, &p->from) + 1; 762 p->from.class = a1; 763 } 764 a1--; 765 a3 = p->from3.class; 766 if(a3 == 0) { 767 a3 = aclass(ctxt, &p->from3) + 1; 768 p->from3.class = a3; 769 } 770 a3--; 771 a4 = p->to.class; 772 if(a4 == 0) { 773 a4 = aclass(ctxt, &p->to) + 1; 774 p->to.class = a4; 775 } 776 a4--; 777 a2 = C_NONE; 778 if(p->reg != NREG) 779 a2 = C_REG; 780 //print("oplook %P %d %d %d %d\n", p, a1, a2, a3, a4); 781 r = p->as; 782 o = oprange[r].start; 783 if(o == 0) 784 o = oprange[r].stop; /* just generate an error */ 785 e = oprange[r].stop; 786 c1 = xcmp[a1]; 787 c3 = xcmp[a3]; 788 c4 = xcmp[a4]; 789 for(; o<e; o++) 790 if(o->a2 == a2) 791 if(c1[o->a1]) 792 if(c3[o->a3]) 793 if(c4[o->a4]) { 794 p->optab = (o-optab)+1; 795 return o; 796 } 797 ctxt->diag("illegal combination %A %^ %^ %^ %^", 798 p->as, a1, a2, a3, a4); 799 prasm(p); 800 if(o == 0) 801 o = optab; 802 return o; 803 } 804 805 static int 806 cmp(int a, int b) 807 { 808 809 if(a == b) 810 return 1; 811 switch(a) { 812 case C_LCON: 813 if(b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON) 814 return 1; 815 break; 816 case C_ADDCON: 817 if(b == C_ZCON || b == C_SCON) 818 return 1; 819 break; 820 case C_ANDCON: 821 if(b == C_ZCON || b == C_SCON) 822 return 1; 823 break; 824 case C_SPR: 825 if(b == C_LR || b == C_XER || b == C_CTR) 826 return 1; 827 break; 828 case C_UCON: 829 if(b == C_ZCON) 830 return 1; 831 break; 832 case C_SCON: 833 if(b == C_ZCON) 834 return 1; 835 break; 836 case C_LACON: 837 if(b == C_SACON) 838 return 1; 839 break; 840 case C_LBRA: 841 if(b == C_SBRA) 842 return 1; 843 break; 844 case C_LEXT: 845 if(b == C_SEXT) 846 return 1; 847 break; 848 case C_LAUTO: 849 if(b == C_SAUTO) 850 return 1; 851 break; 852 case C_REG: 853 if(b == C_ZCON) 854 return r0iszero; 855 break; 856 case C_LOREG: 857 if(b == C_ZOREG || b == C_SOREG) 858 return 1; 859 break; 860 case C_SOREG: 861 if(b == C_ZOREG) 862 return 1; 863 break; 864 865 case C_ANY: 866 return 1; 867 } 868 return 0; 869 } 870 871 static int 872 ocmp(const void *a1, const void *a2) 873 { 874 const Optab *p1, *p2; 875 int n; 876 877 p1 = a1; 878 p2 = a2; 879 n = p1->as - p2->as; 880 if(n) 881 return n; 882 n = p1->a1 - p2->a1; 883 if(n) 884 return n; 885 n = p1->a2 - p2->a2; 886 if(n) 887 return n; 888 n = p1->a3 - p2->a3; 889 if(n) 890 return n; 891 n = p1->a4 - p2->a4; 892 if(n) 893 return n; 894 return 0; 895 } 896 897 static void 898 buildop(Link *ctxt) 899 { 900 int i, n, r; 901 902 for(i=0; i<C_NCLASS; i++) 903 for(n=0; n<C_NCLASS; n++) 904 xcmp[i][n] = cmp(n, i); 905 for(n=0; optab[n].as != AXXX; n++) 906 ; 907 qsort(optab, n, sizeof(optab[0]), ocmp); 908 for(i=0; i<n; i++) { 909 r = optab[i].as; 910 oprange[r].start = optab+i; 911 while(optab[i].as == r) 912 i++; 913 oprange[r].stop = optab+i; 914 i--; 915 916 switch(r) 917 { 918 default: 919 ctxt->diag("unknown op in build: %A", r); 920 sysfatal("bad code"); 921 case ADCBF: /* unary indexed: op (b+a); op (b) */ 922 oprange[ADCBI] = oprange[r]; 923 oprange[ADCBST] = oprange[r]; 924 oprange[ADCBT] = oprange[r]; 925 oprange[ADCBTST] = oprange[r]; 926 oprange[ADCBZ] = oprange[r]; 927 oprange[AICBI] = oprange[r]; 928 break; 929 case AECOWX: /* indexed store: op s,(b+a); op s,(b) */ 930 oprange[ASTWCCC] = oprange[r]; 931 oprange[ASTDCCC] = oprange[r]; 932 break; 933 case AREM: /* macro */ 934 oprange[AREMCC] = oprange[r]; 935 oprange[AREMV] = oprange[r]; 936 oprange[AREMVCC] = oprange[r]; 937 break; 938 case AREMU: 939 oprange[AREMU] = oprange[r]; 940 oprange[AREMUCC] = oprange[r]; 941 oprange[AREMUV] = oprange[r]; 942 oprange[AREMUVCC] = oprange[r]; 943 break; 944 case AREMD: 945 oprange[AREMDCC] = oprange[r]; 946 oprange[AREMDV] = oprange[r]; 947 oprange[AREMDVCC] = oprange[r]; 948 break; 949 case AREMDU: 950 oprange[AREMDU] = oprange[r]; 951 oprange[AREMDUCC] = oprange[r]; 952 oprange[AREMDUV] = oprange[r]; 953 oprange[AREMDUVCC] = oprange[r]; 954 break; 955 case ADIVW: /* op Rb[,Ra],Rd */ 956 oprange[AMULHW] = oprange[r]; 957 oprange[AMULHWCC] = oprange[r]; 958 oprange[AMULHWU] = oprange[r]; 959 oprange[AMULHWUCC] = oprange[r]; 960 oprange[AMULLWCC] = oprange[r]; 961 oprange[AMULLWVCC] = oprange[r]; 962 oprange[AMULLWV] = oprange[r]; 963 oprange[ADIVWCC] = oprange[r]; 964 oprange[ADIVWV] = oprange[r]; 965 oprange[ADIVWVCC] = oprange[r]; 966 oprange[ADIVWU] = oprange[r]; 967 oprange[ADIVWUCC] = oprange[r]; 968 oprange[ADIVWUV] = oprange[r]; 969 oprange[ADIVWUVCC] = oprange[r]; 970 oprange[AADDCC] = oprange[r]; 971 oprange[AADDCV] = oprange[r]; 972 oprange[AADDCVCC] = oprange[r]; 973 oprange[AADDV] = oprange[r]; 974 oprange[AADDVCC] = oprange[r]; 975 oprange[AADDE] = oprange[r]; 976 oprange[AADDECC] = oprange[r]; 977 oprange[AADDEV] = oprange[r]; 978 oprange[AADDEVCC] = oprange[r]; 979 oprange[ACRAND] = oprange[r]; 980 oprange[ACRANDN] = oprange[r]; 981 oprange[ACREQV] = oprange[r]; 982 oprange[ACRNAND] = oprange[r]; 983 oprange[ACRNOR] = oprange[r]; 984 oprange[ACROR] = oprange[r]; 985 oprange[ACRORN] = oprange[r]; 986 oprange[ACRXOR] = oprange[r]; 987 oprange[AMULHD] = oprange[r]; 988 oprange[AMULHDCC] = oprange[r]; 989 oprange[AMULHDU] = oprange[r]; 990 oprange[AMULHDUCC] = oprange[r]; 991 oprange[AMULLD] = oprange[r]; 992 oprange[AMULLDCC] = oprange[r]; 993 oprange[AMULLDVCC] = oprange[r]; 994 oprange[AMULLDV] = oprange[r]; 995 oprange[ADIVD] = oprange[r]; 996 oprange[ADIVDCC] = oprange[r]; 997 oprange[ADIVDVCC] = oprange[r]; 998 oprange[ADIVDV] = oprange[r]; 999 oprange[ADIVDU] = oprange[r]; 1000 oprange[ADIVDUCC] = oprange[r]; 1001 oprange[ADIVDUVCC] = oprange[r]; 1002 oprange[ADIVDUCC] = oprange[r]; 1003 break; 1004 case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */ 1005 oprange[AMOVH] = oprange[r]; 1006 oprange[AMOVHZ] = oprange[r]; 1007 break; 1008 case AMOVBZU: /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */ 1009 oprange[AMOVHU] = oprange[r]; 1010 oprange[AMOVHZU] = oprange[r]; 1011 oprange[AMOVWU] = oprange[r]; 1012 oprange[AMOVWZU] = oprange[r]; 1013 oprange[AMOVDU] = oprange[r]; 1014 oprange[AMOVMW] = oprange[r]; 1015 break; 1016 case AAND: /* logical op Rb,Rs,Ra; no literal */ 1017 oprange[AANDN] = oprange[r]; 1018 oprange[AANDNCC] = oprange[r]; 1019 oprange[AEQV] = oprange[r]; 1020 oprange[AEQVCC] = oprange[r]; 1021 oprange[ANAND] = oprange[r]; 1022 oprange[ANANDCC] = oprange[r]; 1023 oprange[ANOR] = oprange[r]; 1024 oprange[ANORCC] = oprange[r]; 1025 oprange[AORCC] = oprange[r]; 1026 oprange[AORN] = oprange[r]; 1027 oprange[AORNCC] = oprange[r]; 1028 oprange[AXORCC] = oprange[r]; 1029 break; 1030 case AADDME: /* op Ra, Rd */ 1031 oprange[AADDMECC] = oprange[r]; 1032 oprange[AADDMEV] = oprange[r]; 1033 oprange[AADDMEVCC] = oprange[r]; 1034 oprange[AADDZE] = oprange[r]; 1035 oprange[AADDZECC] = oprange[r]; 1036 oprange[AADDZEV] = oprange[r]; 1037 oprange[AADDZEVCC] = oprange[r]; 1038 oprange[ASUBME] = oprange[r]; 1039 oprange[ASUBMECC] = oprange[r]; 1040 oprange[ASUBMEV] = oprange[r]; 1041 oprange[ASUBMEVCC] = oprange[r]; 1042 oprange[ASUBZE] = oprange[r]; 1043 oprange[ASUBZECC] = oprange[r]; 1044 oprange[ASUBZEV] = oprange[r]; 1045 oprange[ASUBZEVCC] = oprange[r]; 1046 break; 1047 case AADDC: 1048 oprange[AADDCCC] = oprange[r]; 1049 break; 1050 case ABEQ: 1051 oprange[ABGE] = oprange[r]; 1052 oprange[ABGT] = oprange[r]; 1053 oprange[ABLE] = oprange[r]; 1054 oprange[ABLT] = oprange[r]; 1055 oprange[ABNE] = oprange[r]; 1056 oprange[ABVC] = oprange[r]; 1057 oprange[ABVS] = oprange[r]; 1058 break; 1059 case ABR: 1060 oprange[ABL] = oprange[r]; 1061 break; 1062 case ABC: 1063 oprange[ABCL] = oprange[r]; 1064 break; 1065 case AEXTSB: /* op Rs, Ra */ 1066 oprange[AEXTSBCC] = oprange[r]; 1067 oprange[AEXTSH] = oprange[r]; 1068 oprange[AEXTSHCC] = oprange[r]; 1069 oprange[ACNTLZW] = oprange[r]; 1070 oprange[ACNTLZWCC] = oprange[r]; 1071 oprange[ACNTLZD] = oprange[r]; 1072 oprange[AEXTSW] = oprange[r]; 1073 oprange[AEXTSWCC] = oprange[r]; 1074 oprange[ACNTLZDCC] = oprange[r]; 1075 break; 1076 case AFABS: /* fop [s,]d */ 1077 oprange[AFABSCC] = oprange[r]; 1078 oprange[AFNABS] = oprange[r]; 1079 oprange[AFNABSCC] = oprange[r]; 1080 oprange[AFNEG] = oprange[r]; 1081 oprange[AFNEGCC] = oprange[r]; 1082 oprange[AFRSP] = oprange[r]; 1083 oprange[AFRSPCC] = oprange[r]; 1084 oprange[AFCTIW] = oprange[r]; 1085 oprange[AFCTIWCC] = oprange[r]; 1086 oprange[AFCTIWZ] = oprange[r]; 1087 oprange[AFCTIWZCC] = oprange[r]; 1088 oprange[AFCTID] = oprange[r]; 1089 oprange[AFCTIDCC] = oprange[r]; 1090 oprange[AFCTIDZ] = oprange[r]; 1091 oprange[AFCTIDZCC] = oprange[r]; 1092 oprange[AFCFID] = oprange[r]; 1093 oprange[AFCFIDCC] = oprange[r]; 1094 oprange[AFRES] = oprange[r]; 1095 oprange[AFRESCC] = oprange[r]; 1096 oprange[AFRSQRTE] = oprange[r]; 1097 oprange[AFRSQRTECC] = oprange[r]; 1098 oprange[AFSQRT] = oprange[r]; 1099 oprange[AFSQRTCC] = oprange[r]; 1100 oprange[AFSQRTS] = oprange[r]; 1101 oprange[AFSQRTSCC] = oprange[r]; 1102 break; 1103 case AFADD: 1104 oprange[AFADDS] = oprange[r]; 1105 oprange[AFADDCC] = oprange[r]; 1106 oprange[AFADDSCC] = oprange[r]; 1107 oprange[AFDIV] = oprange[r]; 1108 oprange[AFDIVS] = oprange[r]; 1109 oprange[AFDIVCC] = oprange[r]; 1110 oprange[AFDIVSCC] = oprange[r]; 1111 oprange[AFSUB] = oprange[r]; 1112 oprange[AFSUBS] = oprange[r]; 1113 oprange[AFSUBCC] = oprange[r]; 1114 oprange[AFSUBSCC] = oprange[r]; 1115 break; 1116 case AFMADD: 1117 oprange[AFMADDCC] = oprange[r]; 1118 oprange[AFMADDS] = oprange[r]; 1119 oprange[AFMADDSCC] = oprange[r]; 1120 oprange[AFMSUB] = oprange[r]; 1121 oprange[AFMSUBCC] = oprange[r]; 1122 oprange[AFMSUBS] = oprange[r]; 1123 oprange[AFMSUBSCC] = oprange[r]; 1124 oprange[AFNMADD] = oprange[r]; 1125 oprange[AFNMADDCC] = oprange[r]; 1126 oprange[AFNMADDS] = oprange[r]; 1127 oprange[AFNMADDSCC] = oprange[r]; 1128 oprange[AFNMSUB] = oprange[r]; 1129 oprange[AFNMSUBCC] = oprange[r]; 1130 oprange[AFNMSUBS] = oprange[r]; 1131 oprange[AFNMSUBSCC] = oprange[r]; 1132 oprange[AFSEL] = oprange[r]; 1133 oprange[AFSELCC] = oprange[r]; 1134 break; 1135 case AFMUL: 1136 oprange[AFMULS] = oprange[r]; 1137 oprange[AFMULCC] = oprange[r]; 1138 oprange[AFMULSCC] = oprange[r]; 1139 break; 1140 case AFCMPO: 1141 oprange[AFCMPU] = oprange[r]; 1142 break; 1143 case AMTFSB0: 1144 oprange[AMTFSB0CC] = oprange[r]; 1145 oprange[AMTFSB1] = oprange[r]; 1146 oprange[AMTFSB1CC] = oprange[r]; 1147 break; 1148 case ANEG: /* op [Ra,] Rd */ 1149 oprange[ANEGCC] = oprange[r]; 1150 oprange[ANEGV] = oprange[r]; 1151 oprange[ANEGVCC] = oprange[r]; 1152 break; 1153 case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */ 1154 oprange[AXOR] = oprange[r]; 1155 break; 1156 case ASLW: 1157 oprange[ASLWCC] = oprange[r]; 1158 oprange[ASRW] = oprange[r]; 1159 oprange[ASRWCC] = oprange[r]; 1160 break; 1161 case ASLD: 1162 oprange[ASLDCC] = oprange[r]; 1163 oprange[ASRD] = oprange[r]; 1164 oprange[ASRDCC] = oprange[r]; 1165 break; 1166 case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */ 1167 oprange[ASRAWCC] = oprange[r]; 1168 break; 1169 case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */ 1170 oprange[ASRADCC] = oprange[r]; 1171 break; 1172 case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */ 1173 oprange[ASUB] = oprange[r]; 1174 oprange[ASUBCC] = oprange[r]; 1175 oprange[ASUBV] = oprange[r]; 1176 oprange[ASUBVCC] = oprange[r]; 1177 oprange[ASUBCCC] = oprange[r]; 1178 oprange[ASUBCV] = oprange[r]; 1179 oprange[ASUBCVCC] = oprange[r]; 1180 oprange[ASUBE] = oprange[r]; 1181 oprange[ASUBECC] = oprange[r]; 1182 oprange[ASUBEV] = oprange[r]; 1183 oprange[ASUBEVCC] = oprange[r]; 1184 break; 1185 case ASYNC: 1186 oprange[AISYNC] = oprange[r]; 1187 oprange[APTESYNC] = oprange[r]; 1188 oprange[ATLBSYNC] = oprange[r]; 1189 break; 1190 case ARLWMI: 1191 oprange[ARLWMICC] = oprange[r]; 1192 oprange[ARLWNM] = oprange[r]; 1193 oprange[ARLWNMCC] = oprange[r]; 1194 break; 1195 case ARLDMI: 1196 oprange[ARLDMICC] = oprange[r]; 1197 break; 1198 case ARLDC: 1199 oprange[ARLDCCC] = oprange[r]; 1200 break; 1201 case ARLDCL: 1202 oprange[ARLDCR] = oprange[r]; 1203 oprange[ARLDCLCC] = oprange[r]; 1204 oprange[ARLDCRCC] = oprange[r]; 1205 break; 1206 case AFMOVD: 1207 oprange[AFMOVDCC] = oprange[r]; 1208 oprange[AFMOVDU] = oprange[r]; 1209 oprange[AFMOVS] = oprange[r]; 1210 oprange[AFMOVSU] = oprange[r]; 1211 break; 1212 case AECIWX: 1213 oprange[ALWAR] = oprange[r]; 1214 oprange[ALDAR] = oprange[r]; 1215 break; 1216 case ASYSCALL: /* just the op; flow of control */ 1217 oprange[ARFI] = oprange[r]; 1218 oprange[ARFCI] = oprange[r]; 1219 oprange[ARFID] = oprange[r]; 1220 oprange[AHRFID] = oprange[r]; 1221 break; 1222 case AMOVHBR: 1223 oprange[AMOVWBR] = oprange[r]; 1224 break; 1225 case ASLBMFEE: 1226 oprange[ASLBMFEV] = oprange[r]; 1227 break; 1228 case ATW: 1229 oprange[ATD] = oprange[r]; 1230 break; 1231 case ATLBIE: 1232 oprange[ASLBIE] = oprange[r]; 1233 oprange[ATLBIEL] = oprange[r]; 1234 break; 1235 case AEIEIO: 1236 oprange[ASLBIA] = oprange[r]; 1237 break; 1238 case ACMP: 1239 oprange[ACMPW] = oprange[r]; 1240 break; 1241 case ACMPU: 1242 oprange[ACMPWU] = oprange[r]; 1243 break; 1244 case AADD: 1245 case AANDCC: /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */ 1246 case ALSW: 1247 case AMOVW: /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */ 1248 case AMOVWZ: /* load/store/move word with zero extension; move 32-bit literals */ 1249 case AMOVD: /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */ 1250 case AMOVB: /* macro: move byte with sign extension */ 1251 case AMOVBU: /* macro: move byte with sign extension & update */ 1252 case AMOVFL: 1253 case AMULLW: /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */ 1254 case ASUBC: /* op r1,$s,r3; op r1[,r2],r3 */ 1255 case ASTSW: 1256 case ASLBMTE: 1257 case AWORD: 1258 case ADWORD: 1259 case ANOP: 1260 case ATEXT: 1261 case AUNDEF: 1262 case AUSEFIELD: 1263 case AFUNCDATA: 1264 case APCDATA: 1265 case ADUFFZERO: 1266 case ADUFFCOPY: 1267 break; 1268 } 1269 } 1270 } 1271 1272 #define OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1)) 1273 #define OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc)) 1274 #define OP(o,xo) OPVCC((o),(xo),0,0) 1275 1276 /* the order is dest, a/s, b/imm for both arithmetic and logical operations */ 1277 #define AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11)) 1278 #define AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF)) 1279 #define LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11)) 1280 #define LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF)) 1281 #define OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1)) 1282 #define OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1)) 1283 #define OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)) 1284 #define OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\ 1285 (((mb)&31L)<<6)|(((me)&31L)<<1)) 1286 1287 #define OP_ADD OPVCC(31,266,0,0) 1288 #define OP_ADDI OPVCC(14,0,0,0) 1289 #define OP_ADDIS OPVCC(15,0,0,0) 1290 #define OP_ANDI OPVCC(28,0,0,0) 1291 #define OP_EXTSB OPVCC(31,954,0,0) 1292 #define OP_EXTSH OPVCC(31,922,0,0) 1293 #define OP_EXTSW OPVCC(31,986,0,0) 1294 #define OP_MCRF OPVCC(19,0,0,0) 1295 #define OP_MCRFS OPVCC(63,64,0,0) 1296 #define OP_MCRXR OPVCC(31,512,0,0) 1297 #define OP_MFCR OPVCC(31,19,0,0) 1298 #define OP_MFFS OPVCC(63,583,0,0) 1299 #define OP_MFMSR OPVCC(31,83,0,0) 1300 #define OP_MFSPR OPVCC(31,339,0,0) 1301 #define OP_MFSR OPVCC(31,595,0,0) 1302 #define OP_MFSRIN OPVCC(31,659,0,0) 1303 #define OP_MTCRF OPVCC(31,144,0,0) 1304 #define OP_MTFSF OPVCC(63,711,0,0) 1305 #define OP_MTFSFI OPVCC(63,134,0,0) 1306 #define OP_MTMSR OPVCC(31,146,0,0) 1307 #define OP_MTMSRD OPVCC(31,178,0,0) 1308 #define OP_MTSPR OPVCC(31,467,0,0) 1309 #define OP_MTSR OPVCC(31,210,0,0) 1310 #define OP_MTSRIN OPVCC(31,242,0,0) 1311 #define OP_MULLW OPVCC(31,235,0,0) 1312 #define OP_MULLD OPVCC(31,233,0,0) 1313 #define OP_OR OPVCC(31,444,0,0) 1314 #define OP_ORI OPVCC(24,0,0,0) 1315 #define OP_ORIS OPVCC(25,0,0,0) 1316 #define OP_RLWINM OPVCC(21,0,0,0) 1317 #define OP_SUBF OPVCC(31,40,0,0) 1318 #define OP_RLDIC OPVCC(30,4,0,0) 1319 #define OP_RLDICR OPVCC(30,2,0,0) 1320 #define OP_RLDICL OPVCC(30,0,0,0) 1321 1322 #define oclass(v) ((v).class-1) 1323 1324 // add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2. 1325 static void 1326 addaddrreloc(Link *ctxt, LSym *s, int *o1, int *o2) 1327 { 1328 Reloc *rel; 1329 1330 rel = addrel(ctxt->cursym); 1331 rel->off = ctxt->pc; 1332 rel->siz = 8; 1333 rel->sym = s; 1334 rel->add = ((uvlong)*o1<<32) | (uint32)*o2; 1335 rel->type = R_ADDRPOWER; 1336 } 1337 1338 /* 1339 * 32-bit masks 1340 */ 1341 static int 1342 getmask(uchar *m, uint32 v) 1343 { 1344 int i; 1345 1346 m[0] = m[1] = 0; 1347 if(v != ~0U && v & (1<<31) && v & 1){ /* MB > ME */ 1348 if(getmask(m, ~v)){ 1349 i = m[0]; m[0] = m[1]+1; m[1] = i-1; 1350 return 1; 1351 } 1352 return 0; 1353 } 1354 for(i=0; i<32; i++) 1355 if(v & (1<<(31-i))){ 1356 m[0] = i; 1357 do { 1358 m[1] = i; 1359 } while(++i<32 && (v & (1<<(31-i))) != 0); 1360 for(; i<32; i++) 1361 if(v & (1<<(31-i))) 1362 return 0; 1363 return 1; 1364 } 1365 return 0; 1366 } 1367 1368 static void 1369 maskgen(Link *ctxt, Prog *p, uchar *m, uint32 v) 1370 { 1371 if(!getmask(m, v)) 1372 ctxt->diag("cannot generate mask #%lux\n%P", v, p); 1373 } 1374 1375 /* 1376 * 64-bit masks (rldic etc) 1377 */ 1378 static int 1379 getmask64(uchar *m, uvlong v) 1380 { 1381 int i; 1382 1383 m[0] = m[1] = 0; 1384 for(i=0; i<64; i++) 1385 if(v & ((uvlong)1<<(63-i))){ 1386 m[0] = i; 1387 do { 1388 m[1] = i; 1389 } while(++i<64 && (v & ((uvlong)1<<(63-i))) != 0); 1390 for(; i<64; i++) 1391 if(v & ((uvlong)1<<(63-i))) 1392 return 0; 1393 return 1; 1394 } 1395 return 0; 1396 } 1397 1398 static void 1399 maskgen64(Link *ctxt, Prog *p, uchar *m, uvlong v) 1400 { 1401 if(!getmask64(m, v)) 1402 ctxt->diag("cannot generate mask #%llux\n%P", v, p); 1403 } 1404 1405 static uint32 1406 loadu32(int r, vlong d) 1407 { 1408 int32 v; 1409 1410 v = d>>16; 1411 if(isuint32(d)) 1412 return LOP_IRR(OP_ORIS, r, REGZERO, v); 1413 return AOP_IRR(OP_ADDIS, r, REGZERO, v); 1414 } 1415 1416 static uint16 1417 high16adjusted(int32 d) 1418 { 1419 if(d & 0x8000) 1420 return (d>>16) + 1; 1421 return d>>16; 1422 } 1423 1424 static void 1425 asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) 1426 { 1427 int32 o1, o2, o3, o4, o5, v, t; 1428 vlong d; 1429 int r, a; 1430 uchar mask[2]; 1431 Reloc *rel; 1432 1433 o1 = 0; 1434 o2 = 0; 1435 o3 = 0; 1436 o4 = 0; 1437 o5 = 0; 1438 1439 //print("%P => case %d\n", p, o->type); 1440 switch(o->type) { 1441 default: 1442 ctxt->diag("unknown type %d", o->type); 1443 prasm(p); 1444 break; 1445 1446 case 0: /* pseudo ops */ 1447 break; 1448 1449 case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */ 1450 if(p->to.reg == REGZERO && p->from.type == D_CONST) { 1451 v = regoff(ctxt, &p->from); 1452 if(r0iszero && v != 0) { 1453 //nerrors--; 1454 ctxt->diag("literal operation on R0\n%P", p); 1455 } 1456 o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v); 1457 break; 1458 } 1459 o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg); 1460 break; 1461 1462 case 2: /* int/cr/fp op Rb,[Ra],Rd */ 1463 r = p->reg; 1464 if(r == NREG) 1465 r = p->to.reg; 1466 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg); 1467 break; 1468 1469 case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */ 1470 d = vregoff(ctxt, &p->from); 1471 v = d; 1472 r = p->from.reg; 1473 if(r == NREG) 1474 r = o->param; 1475 if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0)) 1476 ctxt->diag("literal operation on R0\n%P", p); 1477 a = OP_ADDI; 1478 if(o->a1 == C_UCON) { 1479 if((d&0xffff) != 0) 1480 sysfatal("invalid handling of %P", p); 1481 v >>= 16; 1482 if(r == REGZERO && isuint32(d)){ 1483 o1 = LOP_IRR(OP_ORIS, p->to.reg, REGZERO, v); 1484 break; 1485 } 1486 a = OP_ADDIS; 1487 } else { 1488 if((int16)d != d) 1489 sysfatal("invalid handling of %P", p); 1490 } 1491 o1 = AOP_IRR(a, p->to.reg, r, v); 1492 break; 1493 1494 case 4: /* add/mul $scon,[r1],r2 */ 1495 v = regoff(ctxt, &p->from); 1496 r = p->reg; 1497 if(r == NREG) 1498 r = p->to.reg; 1499 if(r0iszero && p->to.reg == 0) 1500 ctxt->diag("literal operation on R0\n%P", p); 1501 if((int16)v != v) 1502 sysfatal("mishandled instruction %P", p); 1503 o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v); 1504 break; 1505 1506 case 5: /* syscall */ 1507 o1 = oprrr(ctxt, p->as); 1508 break; 1509 1510 case 6: /* logical op Rb,[Rs,]Ra; no literal */ 1511 r = p->reg; 1512 if(r == NREG) 1513 r = p->to.reg; 1514 o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg); 1515 break; 1516 1517 case 7: /* mov r, soreg ==> stw o(r) */ 1518 r = p->to.reg; 1519 if(r == NREG) 1520 r = o->param; 1521 v = regoff(ctxt, &p->to); 1522 if(p->to.type == D_OREG && p->reg != NREG) { 1523 if(v) 1524 ctxt->diag("illegal indexed instruction\n%P", p); 1525 o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, p->reg, r); 1526 } else { 1527 if((int16)v != v) 1528 sysfatal("mishandled instruction %P", p); 1529 o1 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, r, v); 1530 } 1531 break; 1532 1533 case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */ 1534 r = p->from.reg; 1535 if(r == NREG) 1536 r = o->param; 1537 v = regoff(ctxt, &p->from); 1538 if(p->from.type == D_OREG && p->reg != NREG) { 1539 if(v) 1540 ctxt->diag("illegal indexed instruction\n%P", p); 1541 o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r); 1542 } else { 1543 if((int16)v != v) 1544 sysfatal("mishandled instruction %P", p); 1545 o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v); 1546 } 1547 break; 1548 1549 case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */ 1550 r = p->from.reg; 1551 if(r == NREG) 1552 r = o->param; 1553 v = regoff(ctxt, &p->from); 1554 if(p->from.type == D_OREG && p->reg != NREG) { 1555 if(v) 1556 ctxt->diag("illegal indexed instruction\n%P", p); 1557 o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r); 1558 } else 1559 o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v); 1560 o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0); 1561 break; 1562 1563 case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */ 1564 r = p->reg; 1565 if(r == NREG) 1566 r = p->to.reg; 1567 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, r); 1568 break; 1569 1570 case 11: /* br/bl lbra */ 1571 v = 0; 1572 if(p->pcond) { 1573 v = p->pcond->pc - p->pc; 1574 if(v & 03) { 1575 ctxt->diag("odd branch target address\n%P", p); 1576 v &= ~03; 1577 } 1578 if(v < -(1L<<25) || v >= (1L<<24)) 1579 ctxt->diag("branch too far\n%P", p); 1580 } 1581 o1 = OP_BR(opirr(ctxt, p->as), v, 0); 1582 if(p->to.sym != nil) { 1583 rel = addrel(ctxt->cursym); 1584 rel->off = ctxt->pc; 1585 rel->siz = 4; 1586 rel->sym = p->to.sym; 1587 v += p->to.offset; 1588 if(v & 03) { 1589 ctxt->diag("odd branch target address\n%P", p); 1590 v &= ~03; 1591 } 1592 rel->add = v; 1593 rel->type = R_CALLPOWER; 1594 } 1595 break; 1596 1597 case 12: /* movb r,r (extsb); movw r,r (extsw) */ 1598 if(p->to.reg == REGZERO && p->from.type == D_CONST) { 1599 v = regoff(ctxt, &p->from); 1600 if(r0iszero && v != 0) { 1601 ctxt->diag("literal operation on R0\n%P", p); 1602 } 1603 o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v); 1604 break; 1605 } 1606 if(p->as == AMOVW) 1607 o1 = LOP_RRR(OP_EXTSW, p->to.reg, p->from.reg, 0); 1608 else 1609 o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0); 1610 break; 1611 1612 case 13: /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */ 1613 if(p->as == AMOVBZ) 1614 o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31); 1615 else if(p->as == AMOVH) 1616 o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0); 1617 else if(p->as == AMOVHZ) 1618 o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31); 1619 else if(p->as == AMOVWZ) 1620 o1 = OP_RLW(OP_RLDIC, p->to.reg, p->from.reg, 0, 0, 0) | (1<<5); /* MB=32 */ 1621 else 1622 ctxt->diag("internal: bad mov[bhw]z\n%P", p); 1623 break; 1624 1625 case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */ 1626 r = p->reg; 1627 if(r == NREG) 1628 r = p->to.reg; 1629 d = vregoff(ctxt, &p->from3); 1630 maskgen64(ctxt, p, mask, d); 1631 switch(p->as){ 1632 case ARLDCL: case ARLDCLCC: 1633 a = mask[0]; /* MB */ 1634 if(mask[1] != 63) 1635 ctxt->diag("invalid mask for rotate: %llux (end != bit 63)\n%P", d, p); 1636 break; 1637 case ARLDCR: case ARLDCRCC: 1638 a = mask[1]; /* ME */ 1639 if(mask[0] != 0) 1640 ctxt->diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p); 1641 break; 1642 default: 1643 ctxt->diag("unexpected op in rldc case\n%P", p); 1644 a = 0; 1645 } 1646 o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg); 1647 o1 |= (a&31L)<<6; 1648 if(a & 0x20) 1649 o1 |= 1<<5; /* mb[5] is top bit */ 1650 break; 1651 1652 case 17: /* bc bo,bi,lbra (same for now) */ 1653 case 16: /* bc bo,bi,sbra */ 1654 a = 0; 1655 if(p->from.type == D_CONST) 1656 a = regoff(ctxt, &p->from); 1657 r = p->reg; 1658 if(r == NREG) 1659 r = 0; 1660 v = 0; 1661 if(p->pcond) 1662 v = p->pcond->pc - p->pc; 1663 if(v & 03) { 1664 ctxt->diag("odd branch target address\n%P", p); 1665 v &= ~03; 1666 } 1667 if(v < -(1L<<16) || v >= (1L<<15)) 1668 ctxt->diag("branch too far\n%P", p); 1669 o1 = OP_BC(opirr(ctxt, p->as), a, r, v, 0); 1670 break; 1671 1672 case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */ 1673 if(p->as == ABC || p->as == ABCL) 1674 v = regoff(ctxt, &p->to)&31L; 1675 else 1676 v = 20; /* unconditional */ 1677 r = p->reg; 1678 if(r == NREG) 1679 r = 0; 1680 o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11); 1681 o2 = OPVCC(19, 16, 0, 0); 1682 if(p->as == ABL || p->as == ABCL) 1683 o2 |= 1; 1684 o2 = OP_BCR(o2, v, r); 1685 break; 1686 1687 case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */ 1688 if(p->as == ABC || p->as == ABCL) 1689 v = regoff(ctxt, &p->from)&31L; 1690 else 1691 v = 20; /* unconditional */ 1692 r = p->reg; 1693 if(r == NREG) 1694 r = 0; 1695 switch(oclass(p->to)) { 1696 case C_CTR: 1697 o1 = OPVCC(19, 528, 0, 0); 1698 break; 1699 case C_LR: 1700 o1 = OPVCC(19, 16, 0, 0); 1701 break; 1702 default: 1703 ctxt->diag("bad optab entry (18): %d\n%P", p->to.class, p); 1704 v = 0; 1705 } 1706 if(p->as == ABL || p->as == ABCL) 1707 o1 |= 1; 1708 o1 = OP_BCR(o1, v, r); 1709 break; 1710 1711 case 19: /* mov $lcon,r ==> cau+or */ 1712 d = vregoff(ctxt, &p->from); 1713 if(p->from.sym == nil) { 1714 o1 = loadu32(p->to.reg, d); 1715 o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, (int32)d); 1716 } else { 1717 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(d)); 1718 o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, d); 1719 addaddrreloc(ctxt, p->from.sym, &o1, &o2); 1720 } 1721 //if(dlm) reloc(&p->from, p->pc, 0); 1722 break; 1723 1724 case 20: /* add $ucon,,r */ 1725 v = regoff(ctxt, &p->from); 1726 r = p->reg; 1727 if(r == NREG) 1728 r = p->to.reg; 1729 if(p->as == AADD && (!r0iszero && p->reg == 0 || r0iszero && p->to.reg == 0)) 1730 ctxt->diag("literal operation on R0\n%P", p); 1731 o1 = AOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16); 1732 break; 1733 1734 case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */ 1735 if(p->to.reg == REGTMP || p->reg == REGTMP) 1736 ctxt->diag("cant synthesize large constant\n%P", p); 1737 d = vregoff(ctxt, &p->from); 1738 o1 = loadu32(REGTMP, d); 1739 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d); 1740 r = p->reg; 1741 if(r == NREG) 1742 r = p->to.reg; 1743 o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r); 1744 if(p->from.sym != nil) 1745 ctxt->diag("%P is not supported", p); 1746 //if(dlm) reloc(&p->from, p->pc, 0); 1747 break; 1748 1749 case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */ 1750 if(p->to.reg == REGTMP || p->reg == REGTMP) 1751 ctxt->diag("cant synthesize large constant\n%P", p); 1752 d = vregoff(ctxt, &p->from); 1753 o1 = loadu32(REGTMP, d); 1754 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d); 1755 r = p->reg; 1756 if(r == NREG) 1757 r = p->to.reg; 1758 o3 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r); 1759 if(p->from.sym != nil) 1760 ctxt->diag("%P is not supported", p); 1761 //if(dlm) reloc(&p->from, p->pc, 0); 1762 break; 1763 /*24*/ 1764 1765 case 25: /* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */ 1766 v = regoff(ctxt, &p->from); 1767 if(v < 0) 1768 v = 0; 1769 else if(v > 63) 1770 v = 63; 1771 r = p->reg; 1772 if(r == NREG) 1773 r = p->to.reg; 1774 switch(p->as){ 1775 case ASLD: case ASLDCC: 1776 a = 63-v; 1777 o1 = OP_RLDICR; 1778 break; 1779 case ASRD: case ASRDCC: 1780 a = v; 1781 v = 64-v; 1782 o1 = OP_RLDICL; 1783 break; 1784 default: 1785 ctxt->diag("unexpected op in sldi case\n%P", p); 1786 a = 0; 1787 o1 = 0; 1788 } 1789 o1 = AOP_RRR(o1, r, p->to.reg, (v&0x1F)); 1790 o1 |= (a&31L)<<6; 1791 if(v & 0x20) 1792 o1 |= 1<<1; 1793 if(a & 0x20) 1794 o1 |= 1<<5; /* mb[5] is top bit */ 1795 if(p->as == ASLDCC || p->as == ASRDCC) 1796 o1 |= 1; /* Rc */ 1797 break; 1798 1799 case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */ 1800 if(p->to.reg == REGTMP) 1801 ctxt->diag("can't synthesize large constant\n%P", p); 1802 v = regoff(ctxt, &p->from); 1803 if(v & 0x8000L) 1804 v += 0x10000L; 1805 r = p->from.reg; 1806 if(r == NREG) 1807 r = o->param; 1808 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16); 1809 o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, v); 1810 break; 1811 1812 case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */ 1813 v = regoff(ctxt, &p->from3); 1814 r = p->from.reg; 1815 o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v); 1816 break; 1817 1818 case 28: /* subc r1,$lcon,r2 ==> cau+or+subfc */ 1819 if(p->to.reg == REGTMP || p->from.reg == REGTMP) 1820 ctxt->diag("can't synthesize large constant\n%P", p); 1821 v = regoff(ctxt, &p->from3); 1822 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16); 1823 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v); 1824 o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, REGTMP); 1825 if(p->from.sym != nil) 1826 ctxt->diag("%P is not supported", p); 1827 //if(dlm) reloc(&p->from3, p->pc, 0); 1828 break; 1829 1830 case 29: /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */ 1831 v = regoff(ctxt, &p->from); 1832 d = vregoff(ctxt, &p->from3); 1833 maskgen64(ctxt, p, mask, d); 1834 switch(p->as){ 1835 case ARLDC: case ARLDCCC: 1836 a = mask[0]; /* MB */ 1837 if(mask[1] != (63-v)) 1838 ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); 1839 break; 1840 case ARLDCL: case ARLDCLCC: 1841 a = mask[0]; /* MB */ 1842 if(mask[1] != 63) 1843 ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); 1844 break; 1845 case ARLDCR: case ARLDCRCC: 1846 a = mask[1]; /* ME */ 1847 if(mask[0] != 0) 1848 ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); 1849 break; 1850 default: 1851 ctxt->diag("unexpected op in rldic case\n%P", p); 1852 a = 0; 1853 } 1854 o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, (v&0x1F)); 1855 o1 |= (a&31L)<<6; 1856 if(v & 0x20) 1857 o1 |= 1<<1; 1858 if(a & 0x20) 1859 o1 |= 1<<5; /* mb[5] is top bit */ 1860 break; 1861 1862 case 30: /* rldimi $sh,s,$mask,a */ 1863 v = regoff(ctxt, &p->from); 1864 d = vregoff(ctxt, &p->from3); 1865 maskgen64(ctxt, p, mask, d); 1866 if(mask[1] != (63-v)) 1867 ctxt->diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p); 1868 o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, (v&0x1F)); 1869 o1 |= (mask[0]&31L)<<6; 1870 if(v & 0x20) 1871 o1 |= 1<<1; 1872 if(mask[0] & 0x20) 1873 o1 |= 1<<5; /* mb[5] is top bit */ 1874 break; 1875 1876 case 31: /* dword */ 1877 d = vregoff(ctxt, &p->from); 1878 if(ctxt->arch->endian == BigEndian) { 1879 o1 = d>>32; 1880 o2 = d; 1881 } else { 1882 o1 = d; 1883 o2 = d>>32; 1884 } 1885 if(p->from.sym != nil) { 1886 rel = addrel(ctxt->cursym); 1887 rel->off = ctxt->pc; 1888 rel->siz = 8; 1889 rel->sym = p->from.sym; 1890 rel->add = p->from.offset; 1891 rel->type = R_ADDR; 1892 o1 = o2 = 0; 1893 } 1894 break; 1895 1896 case 32: /* fmul frc,fra,frd */ 1897 r = p->reg; 1898 if(r == NREG) 1899 r = p->to.reg; 1900 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6); 1901 break; 1902 1903 case 33: /* fabs [frb,]frd; fmr. frb,frd */ 1904 r = p->from.reg; 1905 if(oclass(p->from) == C_NONE) 1906 r = p->to.reg; 1907 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, r); 1908 break; 1909 1910 case 34: /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */ 1911 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, p->reg)|((p->from3.reg&31L)<<6); 1912 break; 1913 1914 case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */ 1915 v = regoff(ctxt, &p->to); 1916 if(v & 0x8000L) 1917 v += 0x10000L; 1918 r = p->to.reg; 1919 if(r == NREG) 1920 r = o->param; 1921 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16); 1922 o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v); 1923 break; 1924 1925 case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */ 1926 v = regoff(ctxt, &p->from); 1927 if(v & 0x8000L) 1928 v += 0x10000L; 1929 r = p->from.reg; 1930 if(r == NREG) 1931 r = o->param; 1932 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16); 1933 o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v); 1934 break; 1935 1936 case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */ 1937 v = regoff(ctxt, &p->from); 1938 if(v & 0x8000L) 1939 v += 0x10000L; 1940 r = p->from.reg; 1941 if(r == NREG) 1942 r = o->param; 1943 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16); 1944 o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v); 1945 o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0); 1946 break; 1947 1948 case 40: /* word */ 1949 o1 = regoff(ctxt, &p->from); 1950 break; 1951 1952 case 41: /* stswi */ 1953 o1 = AOP_RRR(opirr(ctxt, p->as), p->from.reg, p->to.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11); 1954 break; 1955 1956 case 42: /* lswi */ 1957 o1 = AOP_RRR(opirr(ctxt, p->as), p->to.reg, p->from.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11); 1958 break; 1959 1960 case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */ 1961 r = p->reg; 1962 if(r == NREG) 1963 r = 0; 1964 o1 = AOP_RRR(oprrr(ctxt, p->as), 0, r, p->from.reg); 1965 break; 1966 1967 case 44: /* indexed store */ 1968 r = p->reg; 1969 if(r == NREG) 1970 r = 0; 1971 o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, r, p->to.reg); 1972 break; 1973 case 45: /* indexed load */ 1974 r = p->reg; 1975 if(r == NREG) 1976 r = 0; 1977 o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, r, p->from.reg); 1978 break; 1979 1980 case 46: /* plain op */ 1981 o1 = oprrr(ctxt, p->as); 1982 break; 1983 1984 case 47: /* op Ra, Rd; also op [Ra,] Rd */ 1985 r = p->from.reg; 1986 if(r == NREG) 1987 r = p->to.reg; 1988 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0); 1989 break; 1990 1991 case 48: /* op Rs, Ra */ 1992 r = p->from.reg; 1993 if(r == NREG) 1994 r = p->to.reg; 1995 o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0); 1996 break; 1997 1998 case 49: /* op Rb; op $n, Rb */ 1999 if(p->from.type != D_REG){ /* tlbie $L, rB */ 2000 v = regoff(ctxt, &p->from) & 1; 2001 o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->to.reg) | (v<<21); 2002 }else 2003 o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->from.reg); 2004 break; 2005 2006 case 50: /* rem[u] r1[,r2],r3 */ 2007 r = p->reg; 2008 if(r == NREG) 2009 r = p->to.reg; 2010 v = oprrr(ctxt, p->as); 2011 t = v & ((1<<10)|1); /* OE|Rc */ 2012 o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg); 2013 o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg); 2014 o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r); 2015 if(p->as == AREMU) { 2016 o4 = o3; 2017 /* Clear top 32 bits */ 2018 o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | (1<<5); 2019 } 2020 break; 2021 2022 case 51: /* remd[u] r1[,r2],r3 */ 2023 r = p->reg; 2024 if(r == NREG) 2025 r = p->to.reg; 2026 v = oprrr(ctxt, p->as); 2027 t = v & ((1<<10)|1); /* OE|Rc */ 2028 o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg); 2029 o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, p->from.reg); 2030 o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r); 2031 break; 2032 2033 case 52: /* mtfsbNx cr(n) */ 2034 v = regoff(ctxt, &p->from)&31L; 2035 o1 = AOP_RRR(oprrr(ctxt, p->as), v, 0, 0); 2036 break; 2037 2038 case 53: /* mffsX ,fr1 */ 2039 o1 = AOP_RRR(OP_MFFS, p->to.reg, 0, 0); 2040 break; 2041 2042 case 54: /* mov msr,r1; mov r1, msr*/ 2043 if(oclass(p->from) == C_REG){ 2044 if(p->as == AMOVD) 2045 o1 = AOP_RRR(OP_MTMSRD, p->from.reg, 0, 0); 2046 else 2047 o1 = AOP_RRR(OP_MTMSR, p->from.reg, 0, 0); 2048 }else 2049 o1 = AOP_RRR(OP_MFMSR, p->to.reg, 0, 0); 2050 break; 2051 2052 case 55: /* op Rb, Rd */ 2053 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, p->from.reg); 2054 break; 2055 2056 case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */ 2057 v = regoff(ctxt, &p->from); 2058 r = p->reg; 2059 if(r == NREG) 2060 r = p->to.reg; 2061 o1 = AOP_RRR(opirr(ctxt, p->as), r, p->to.reg, v&31L); 2062 if(p->as == ASRAD && (v&0x20)) 2063 o1 |= 1<<1; /* mb[5] */ 2064 break; 2065 2066 case 57: /* slw $sh,[s,]a -> rlwinm ... */ 2067 v = regoff(ctxt, &p->from); 2068 r = p->reg; 2069 if(r == NREG) 2070 r = p->to.reg; 2071 /* 2072 * Let user (gs) shoot himself in the foot. 2073 * qc has already complained. 2074 * 2075 if(v < 0 || v > 31) 2076 ctxt->diag("illegal shift %ld\n%P", v, p); 2077 */ 2078 if(v < 0) 2079 v = 0; 2080 else if(v > 32) 2081 v = 32; 2082 if(p->as == ASRW || p->as == ASRWCC) { /* shift right */ 2083 mask[0] = v; 2084 mask[1] = 31; 2085 v = 32-v; 2086 } else { 2087 mask[0] = 0; 2088 mask[1] = 31-v; 2089 } 2090 o1 = OP_RLW(OP_RLWINM, p->to.reg, r, v, mask[0], mask[1]); 2091 if(p->as == ASLWCC || p->as == ASRWCC) 2092 o1 |= 1; /* Rc */ 2093 break; 2094 2095 case 58: /* logical $andcon,[s],a */ 2096 v = regoff(ctxt, &p->from); 2097 r = p->reg; 2098 if(r == NREG) 2099 r = p->to.reg; 2100 o1 = LOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v); 2101 break; 2102 2103 case 59: /* or/and $ucon,,r */ 2104 v = regoff(ctxt, &p->from); 2105 r = p->reg; 2106 if(r == NREG) 2107 r = p->to.reg; 2108 o1 = LOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16); /* oris, xoris, andis */ 2109 break; 2110 2111 case 60: /* tw to,a,b */ 2112 r = regoff(ctxt, &p->from)&31L; 2113 o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->reg, p->to.reg); 2114 break; 2115 2116 case 61: /* tw to,a,$simm */ 2117 r = regoff(ctxt, &p->from)&31L; 2118 v = regoff(ctxt, &p->to); 2119 o1 = AOP_IRR(opirr(ctxt, p->as), r, p->reg, v); 2120 break; 2121 2122 case 62: /* rlwmi $sh,s,$mask,a */ 2123 v = regoff(ctxt, &p->from); 2124 maskgen(ctxt, p, mask, regoff(ctxt, &p->from3)); 2125 o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, v); 2126 o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1); 2127 break; 2128 2129 case 63: /* rlwmi b,s,$mask,a */ 2130 maskgen(ctxt, p, mask, regoff(ctxt, &p->from3)); 2131 o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, p->from.reg); 2132 o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1); 2133 break; 2134 2135 case 64: /* mtfsf fr[, $m] {,fpcsr} */ 2136 if(p->from3.type != D_NONE) 2137 v = regoff(ctxt, &p->from3)&255L; 2138 else 2139 v = 255; 2140 o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11); 2141 break; 2142 2143 case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */ 2144 if(p->to.reg == NREG) 2145 ctxt->diag("must specify FPSCR(n)\n%P", p); 2146 o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(ctxt, &p->from)&31L)<<12); 2147 break; 2148 2149 case 66: /* mov spr,r1; mov r1,spr, also dcr */ 2150 if(p->from.type == D_REG) { 2151 r = p->from.reg; 2152 v = p->to.offset; 2153 if(p->to.type == D_DCR) 2154 o1 = OPVCC(31,451,0,0); /* mtdcr */ 2155 else 2156 o1 = OPVCC(31,467,0,0); /* mtspr */ 2157 } else { 2158 r = p->to.reg; 2159 v = p->from.offset; 2160 if(p->from.type == D_DCR) 2161 o1 = OPVCC(31,323,0,0); /* mfdcr */ 2162 else 2163 o1 = OPVCC(31,339,0,0); /* mfspr */ 2164 } 2165 o1 = AOP_RRR(o1, r, 0, 0) | ((v&0x1f)<<16) | (((v>>5)&0x1f)<<11); 2166 break; 2167 2168 case 67: /* mcrf crfD,crfS */ 2169 if(p->from.type != D_CREG || p->from.reg == NREG || 2170 p->to.type != D_CREG || p->to.reg == NREG) 2171 ctxt->diag("illegal CR field number\n%P", p); 2172 o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0); 2173 break; 2174 2175 case 68: /* mfcr rD; mfocrf CRM,rD */ 2176 if(p->from.type == D_CREG && p->from.reg != NREG){ 2177 v = 1<<(7-(p->to.reg&7)); /* CR(n) */ 2178 o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0) | (1<<20) | (v<<12); /* new form, mfocrf */ 2179 }else 2180 o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0); /* old form, whole register */ 2181 break; 2182 2183 case 69: /* mtcrf CRM,rS */ 2184 if(p->from3.type != D_NONE) { 2185 if(p->to.reg != NREG) 2186 ctxt->diag("can't use both mask and CR(n)\n%P", p); 2187 v = regoff(ctxt, &p->from3) & 0xff; 2188 } else { 2189 if(p->to.reg == NREG) 2190 v = 0xff; /* CR */ 2191 else 2192 v = 1<<(7-(p->to.reg&7)); /* CR(n) */ 2193 } 2194 o1 = AOP_RRR(OP_MTCRF, p->from.reg, 0, 0) | (v<<12); 2195 break; 2196 2197 case 70: /* [f]cmp r,r,cr*/ 2198 if(p->reg == NREG) 2199 r = 0; 2200 else 2201 r = (p->reg&7)<<2; 2202 o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->from.reg, p->to.reg); 2203 break; 2204 2205 case 71: /* cmp[l] r,i,cr*/ 2206 if(p->reg == NREG) 2207 r = 0; 2208 else 2209 r = (p->reg&7)<<2; 2210 o1 = AOP_RRR(opirr(ctxt, p->as), r, p->from.reg, 0) | (regoff(ctxt, &p->to)&0xffff); 2211 break; 2212 2213 case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */ 2214 o1 = AOP_RRR(oprrr(ctxt, p->as), p->from.reg, 0, p->to.reg); 2215 break; 2216 2217 case 73: /* mcrfs crfD,crfS */ 2218 if(p->from.type != D_FPSCR || p->from.reg == NREG || 2219 p->to.type != D_CREG || p->to.reg == NREG) 2220 ctxt->diag("illegal FPSCR/CR field number\n%P", p); 2221 o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0); 2222 break; 2223 2224 case 77: /* syscall $scon, syscall Rx */ 2225 if(p->from.type == D_CONST) { 2226 if(p->from.offset > BIG || p->from.offset < -BIG) 2227 ctxt->diag("illegal syscall, sysnum too large: %P", p); 2228 o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, p->from.offset); 2229 } else if(p->from.type == D_REG) { 2230 o1 = LOP_RRR(OP_OR, REGZERO, p->from.reg, p->from.reg); 2231 } else { 2232 ctxt->diag("illegal syscall: %P", p); 2233 o1 = 0x7fe00008; // trap always 2234 } 2235 o2 = oprrr(ctxt, p->as); 2236 o3 = AOP_RRR(oprrr(ctxt, AXOR), REGZERO, REGZERO, REGZERO); // XOR R0, R0 2237 break; 2238 2239 case 78: /* undef */ 2240 o1 = 0; /* "An instruction consisting entirely of binary 0s is guaranteed 2241 always to be an illegal instruction." */ 2242 break; 2243 2244 /* relocation operations */ 2245 2246 case 74: 2247 v = regoff(ctxt, &p->to); 2248 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v)); 2249 o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v); 2250 addaddrreloc(ctxt, p->to.sym, &o1, &o2); 2251 //if(dlm) reloc(&p->to, p->pc, 1); 2252 break; 2253 2254 case 75: 2255 v = regoff(ctxt, &p->from); 2256 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v)); 2257 o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v); 2258 addaddrreloc(ctxt, p->from.sym, &o1, &o2); 2259 //if(dlm) reloc(&p->from, p->pc, 1); 2260 break; 2261 2262 case 76: 2263 v = regoff(ctxt, &p->from); 2264 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v)); 2265 o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v); 2266 addaddrreloc(ctxt, p->from.sym, &o1, &o2); 2267 o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0); 2268 //if(dlm) reloc(&p->from, p->pc, 1); 2269 break; 2270 2271 } 2272 2273 out[0] = o1; 2274 out[1] = o2; 2275 out[2] = o3; 2276 out[3] = o4; 2277 out[4] = o5; 2278 return; 2279 } 2280 2281 static vlong 2282 vregoff(Link *ctxt, Addr *a) 2283 { 2284 2285 ctxt->instoffset = 0; 2286 aclass(ctxt, a); 2287 return ctxt->instoffset; 2288 } 2289 2290 static int32 2291 regoff(Link *ctxt, Addr *a) 2292 { 2293 return vregoff(ctxt, a); 2294 } 2295 2296 static int32 2297 oprrr(Link *ctxt, int a) 2298 { 2299 switch(a) { 2300 case AADD: return OPVCC(31,266,0,0); 2301 case AADDCC: return OPVCC(31,266,0,1); 2302 case AADDV: return OPVCC(31,266,1,0); 2303 case AADDVCC: return OPVCC(31,266,1,1); 2304 case AADDC: return OPVCC(31,10,0,0); 2305 case AADDCCC: return OPVCC(31,10,0,1); 2306 case AADDCV: return OPVCC(31,10,1,0); 2307 case AADDCVCC: return OPVCC(31,10,1,1); 2308 case AADDE: return OPVCC(31,138,0,0); 2309 case AADDECC: return OPVCC(31,138,0,1); 2310 case AADDEV: return OPVCC(31,138,1,0); 2311 case AADDEVCC: return OPVCC(31,138,1,1); 2312 case AADDME: return OPVCC(31,234,0,0); 2313 case AADDMECC: return OPVCC(31,234,0,1); 2314 case AADDMEV: return OPVCC(31,234,1,0); 2315 case AADDMEVCC: return OPVCC(31,234,1,1); 2316 case AADDZE: return OPVCC(31,202,0,0); 2317 case AADDZECC: return OPVCC(31,202,0,1); 2318 case AADDZEV: return OPVCC(31,202,1,0); 2319 case AADDZEVCC: return OPVCC(31,202,1,1); 2320 2321 case AAND: return OPVCC(31,28,0,0); 2322 case AANDCC: return OPVCC(31,28,0,1); 2323 case AANDN: return OPVCC(31,60,0,0); 2324 case AANDNCC: return OPVCC(31,60,0,1); 2325 2326 case ACMP: return OPVCC(31,0,0,0)|(1<<21); /* L=1 */ 2327 case ACMPU: return OPVCC(31,32,0,0)|(1<<21); 2328 case ACMPW: return OPVCC(31,0,0,0); /* L=0 */ 2329 case ACMPWU: return OPVCC(31,32,0,0); 2330 2331 case ACNTLZW: return OPVCC(31,26,0,0); 2332 case ACNTLZWCC: return OPVCC(31,26,0,1); 2333 case ACNTLZD: return OPVCC(31,58,0,0); 2334 case ACNTLZDCC: return OPVCC(31,58,0,1); 2335 2336 case ACRAND: return OPVCC(19,257,0,0); 2337 case ACRANDN: return OPVCC(19,129,0,0); 2338 case ACREQV: return OPVCC(19,289,0,0); 2339 case ACRNAND: return OPVCC(19,225,0,0); 2340 case ACRNOR: return OPVCC(19,33,0,0); 2341 case ACROR: return OPVCC(19,449,0,0); 2342 case ACRORN: return OPVCC(19,417,0,0); 2343 case ACRXOR: return OPVCC(19,193,0,0); 2344 2345 case ADCBF: return OPVCC(31,86,0,0); 2346 case ADCBI: return OPVCC(31,470,0,0); 2347 case ADCBST: return OPVCC(31,54,0,0); 2348 case ADCBT: return OPVCC(31,278,0,0); 2349 case ADCBTST: return OPVCC(31,246,0,0); 2350 case ADCBZ: return OPVCC(31,1014,0,0); 2351 2352 case AREM: 2353 case ADIVW: return OPVCC(31,491,0,0); 2354 case AREMCC: 2355 case ADIVWCC: return OPVCC(31,491,0,1); 2356 case AREMV: 2357 case ADIVWV: return OPVCC(31,491,1,0); 2358 case AREMVCC: 2359 case ADIVWVCC: return OPVCC(31,491,1,1); 2360 case AREMU: 2361 case ADIVWU: return OPVCC(31,459,0,0); 2362 case AREMUCC: 2363 case ADIVWUCC: return OPVCC(31,459,0,1); 2364 case AREMUV: 2365 case ADIVWUV: return OPVCC(31,459,1,0); 2366 case AREMUVCC: 2367 case ADIVWUVCC: return OPVCC(31,459,1,1); 2368 2369 case AREMD: 2370 case ADIVD: return OPVCC(31,489,0,0); 2371 case AREMDCC: 2372 case ADIVDCC: return OPVCC(31,489,0,1); 2373 case AREMDV: 2374 case ADIVDV: return OPVCC(31,489,1,0); 2375 case AREMDVCC: 2376 case ADIVDVCC: return OPVCC(31,489,1,1); 2377 case AREMDU: 2378 case ADIVDU: return OPVCC(31,457,0,0); 2379 case AREMDUCC: 2380 case ADIVDUCC: return OPVCC(31,457,0,1); 2381 case AREMDUV: 2382 case ADIVDUV: return OPVCC(31,457,1,0); 2383 case AREMDUVCC: 2384 case ADIVDUVCC: return OPVCC(31,457,1,1); 2385 2386 case AEIEIO: return OPVCC(31,854,0,0); 2387 2388 case AEQV: return OPVCC(31,284,0,0); 2389 case AEQVCC: return OPVCC(31,284,0,1); 2390 2391 case AEXTSB: return OPVCC(31,954,0,0); 2392 case AEXTSBCC: return OPVCC(31,954,0,1); 2393 case AEXTSH: return OPVCC(31,922,0,0); 2394 case AEXTSHCC: return OPVCC(31,922,0,1); 2395 case AEXTSW: return OPVCC(31,986,0,0); 2396 case AEXTSWCC: return OPVCC(31,986,0,1); 2397 2398 case AFABS: return OPVCC(63,264,0,0); 2399 case AFABSCC: return OPVCC(63,264,0,1); 2400 case AFADD: return OPVCC(63,21,0,0); 2401 case AFADDCC: return OPVCC(63,21,0,1); 2402 case AFADDS: return OPVCC(59,21,0,0); 2403 case AFADDSCC: return OPVCC(59,21,0,1); 2404 case AFCMPO: return OPVCC(63,32,0,0); 2405 case AFCMPU: return OPVCC(63,0,0,0); 2406 case AFCFID: return OPVCC(63,846,0,0); 2407 case AFCFIDCC: return OPVCC(63,846,0,1); 2408 case AFCTIW: return OPVCC(63,14,0,0); 2409 case AFCTIWCC: return OPVCC(63,14,0,1); 2410 case AFCTIWZ: return OPVCC(63,15,0,0); 2411 case AFCTIWZCC: return OPVCC(63,15,0,1); 2412 case AFCTID: return OPVCC(63,814,0,0); 2413 case AFCTIDCC: return OPVCC(63,814,0,1); 2414 case AFCTIDZ: return OPVCC(63,815,0,0); 2415 case AFCTIDZCC: return OPVCC(63,815,0,1); 2416 case AFDIV: return OPVCC(63,18,0,0); 2417 case AFDIVCC: return OPVCC(63,18,0,1); 2418 case AFDIVS: return OPVCC(59,18,0,0); 2419 case AFDIVSCC: return OPVCC(59,18,0,1); 2420 case AFMADD: return OPVCC(63,29,0,0); 2421 case AFMADDCC: return OPVCC(63,29,0,1); 2422 case AFMADDS: return OPVCC(59,29,0,0); 2423 case AFMADDSCC: return OPVCC(59,29,0,1); 2424 case AFMOVS: 2425 case AFMOVD: return OPVCC(63,72,0,0); /* load */ 2426 case AFMOVDCC: return OPVCC(63,72,0,1); 2427 case AFMSUB: return OPVCC(63,28,0,0); 2428 case AFMSUBCC: return OPVCC(63,28,0,1); 2429 case AFMSUBS: return OPVCC(59,28,0,0); 2430 case AFMSUBSCC: return OPVCC(59,28,0,1); 2431 case AFMUL: return OPVCC(63,25,0,0); 2432 case AFMULCC: return OPVCC(63,25,0,1); 2433 case AFMULS: return OPVCC(59,25,0,0); 2434 case AFMULSCC: return OPVCC(59,25,0,1); 2435 case AFNABS: return OPVCC(63,136,0,0); 2436 case AFNABSCC: return OPVCC(63,136,0,1); 2437 case AFNEG: return OPVCC(63,40,0,0); 2438 case AFNEGCC: return OPVCC(63,40,0,1); 2439 case AFNMADD: return OPVCC(63,31,0,0); 2440 case AFNMADDCC: return OPVCC(63,31,0,1); 2441 case AFNMADDS: return OPVCC(59,31,0,0); 2442 case AFNMADDSCC: return OPVCC(59,31,0,1); 2443 case AFNMSUB: return OPVCC(63,30,0,0); 2444 case AFNMSUBCC: return OPVCC(63,30,0,1); 2445 case AFNMSUBS: return OPVCC(59,30,0,0); 2446 case AFNMSUBSCC: return OPVCC(59,30,0,1); 2447 case AFRES: return OPVCC(59,24,0,0); 2448 case AFRESCC: return OPVCC(59,24,0,1); 2449 case AFRSP: return OPVCC(63,12,0,0); 2450 case AFRSPCC: return OPVCC(63,12,0,1); 2451 case AFRSQRTE: return OPVCC(63,26,0,0); 2452 case AFRSQRTECC: return OPVCC(63,26,0,1); 2453 case AFSEL: return OPVCC(63,23,0,0); 2454 case AFSELCC: return OPVCC(63,23,0,1); 2455 case AFSQRT: return OPVCC(63,22,0,0); 2456 case AFSQRTCC: return OPVCC(63,22,0,1); 2457 case AFSQRTS: return OPVCC(59,22,0,0); 2458 case AFSQRTSCC: return OPVCC(59,22,0,1); 2459 case AFSUB: return OPVCC(63,20,0,0); 2460 case AFSUBCC: return OPVCC(63,20,0,1); 2461 case AFSUBS: return OPVCC(59,20,0,0); 2462 case AFSUBSCC: return OPVCC(59,20,0,1); 2463 2464 case AICBI: return OPVCC(31,982,0,0); 2465 case AISYNC: return OPVCC(19,150,0,0); 2466 2467 case AMTFSB0: return OPVCC(63,70,0,0); 2468 case AMTFSB0CC: return OPVCC(63,70,0,1); 2469 case AMTFSB1: return OPVCC(63,38,0,0); 2470 case AMTFSB1CC: return OPVCC(63,38,0,1); 2471 2472 case AMULHW: return OPVCC(31,75,0,0); 2473 case AMULHWCC: return OPVCC(31,75,0,1); 2474 case AMULHWU: return OPVCC(31,11,0,0); 2475 case AMULHWUCC: return OPVCC(31,11,0,1); 2476 case AMULLW: return OPVCC(31,235,0,0); 2477 case AMULLWCC: return OPVCC(31,235,0,1); 2478 case AMULLWV: return OPVCC(31,235,1,0); 2479 case AMULLWVCC: return OPVCC(31,235,1,1); 2480 2481 case AMULHD: return OPVCC(31,73,0,0); 2482 case AMULHDCC: return OPVCC(31,73,0,1); 2483 case AMULHDU: return OPVCC(31,9,0,0); 2484 case AMULHDUCC: return OPVCC(31,9,0,1); 2485 case AMULLD: return OPVCC(31,233,0,0); 2486 case AMULLDCC: return OPVCC(31,233,0,1); 2487 case AMULLDV: return OPVCC(31,233,1,0); 2488 case AMULLDVCC: return OPVCC(31,233,1,1); 2489 2490 case ANAND: return OPVCC(31,476,0,0); 2491 case ANANDCC: return OPVCC(31,476,0,1); 2492 case ANEG: return OPVCC(31,104,0,0); 2493 case ANEGCC: return OPVCC(31,104,0,1); 2494 case ANEGV: return OPVCC(31,104,1,0); 2495 case ANEGVCC: return OPVCC(31,104,1,1); 2496 case ANOR: return OPVCC(31,124,0,0); 2497 case ANORCC: return OPVCC(31,124,0,1); 2498 case AOR: return OPVCC(31,444,0,0); 2499 case AORCC: return OPVCC(31,444,0,1); 2500 case AORN: return OPVCC(31,412,0,0); 2501 case AORNCC: return OPVCC(31,412,0,1); 2502 2503 case ARFI: return OPVCC(19,50,0,0); 2504 case ARFCI: return OPVCC(19,51,0,0); 2505 case ARFID: return OPVCC(19,18,0,0); 2506 case AHRFID: return OPVCC(19,274,0,0); 2507 2508 case ARLWMI: return OPVCC(20,0,0,0); 2509 case ARLWMICC: return OPVCC(20,0,0,1); 2510 case ARLWNM: return OPVCC(23,0,0,0); 2511 case ARLWNMCC: return OPVCC(23,0,0,1); 2512 2513 case ARLDCL: return OPVCC(30,8,0,0); 2514 case ARLDCR: return OPVCC(30,9,0,0); 2515 2516 case ASYSCALL: return OPVCC(17,1,0,0); 2517 2518 case ASLW: return OPVCC(31,24,0,0); 2519 case ASLWCC: return OPVCC(31,24,0,1); 2520 case ASLD: return OPVCC(31,27,0,0); 2521 case ASLDCC: return OPVCC(31,27,0,1); 2522 2523 case ASRAW: return OPVCC(31,792,0,0); 2524 case ASRAWCC: return OPVCC(31,792,0,1); 2525 case ASRAD: return OPVCC(31,794,0,0); 2526 case ASRADCC: return OPVCC(31,794,0,1); 2527 2528 case ASRW: return OPVCC(31,536,0,0); 2529 case ASRWCC: return OPVCC(31,536,0,1); 2530 case ASRD: return OPVCC(31,539,0,0); 2531 case ASRDCC: return OPVCC(31,539,0,1); 2532 2533 case ASUB: return OPVCC(31,40,0,0); 2534 case ASUBCC: return OPVCC(31,40,0,1); 2535 case ASUBV: return OPVCC(31,40,1,0); 2536 case ASUBVCC: return OPVCC(31,40,1,1); 2537 case ASUBC: return OPVCC(31,8,0,0); 2538 case ASUBCCC: return OPVCC(31,8,0,1); 2539 case ASUBCV: return OPVCC(31,8,1,0); 2540 case ASUBCVCC: return OPVCC(31,8,1,1); 2541 case ASUBE: return OPVCC(31,136,0,0); 2542 case ASUBECC: return OPVCC(31,136,0,1); 2543 case ASUBEV: return OPVCC(31,136,1,0); 2544 case ASUBEVCC: return OPVCC(31,136,1,1); 2545 case ASUBME: return OPVCC(31,232,0,0); 2546 case ASUBMECC: return OPVCC(31,232,0,1); 2547 case ASUBMEV: return OPVCC(31,232,1,0); 2548 case ASUBMEVCC: return OPVCC(31,232,1,1); 2549 case ASUBZE: return OPVCC(31,200,0,0); 2550 case ASUBZECC: return OPVCC(31,200,0,1); 2551 case ASUBZEV: return OPVCC(31,200,1,0); 2552 case ASUBZEVCC: return OPVCC(31,200,1,1); 2553 2554 case ASYNC: return OPVCC(31,598,0,0); 2555 case APTESYNC: return OPVCC(31,598,0,0) | (2<<21); 2556 2557 case ATLBIE: return OPVCC(31,306,0,0); 2558 case ATLBIEL: return OPVCC(31,274,0,0); 2559 case ATLBSYNC: return OPVCC(31,566,0,0); 2560 case ASLBIA: return OPVCC(31,498,0,0); 2561 case ASLBIE: return OPVCC(31,434,0,0); 2562 case ASLBMFEE: return OPVCC(31,915,0,0); 2563 case ASLBMFEV: return OPVCC(31,851,0,0); 2564 case ASLBMTE: return OPVCC(31,402,0,0); 2565 2566 case ATW: return OPVCC(31,4,0,0); 2567 case ATD: return OPVCC(31,68,0,0); 2568 2569 case AXOR: return OPVCC(31,316,0,0); 2570 case AXORCC: return OPVCC(31,316,0,1); 2571 } 2572 ctxt->diag("bad r/r opcode %A", a); 2573 return 0; 2574 } 2575 2576 static int32 2577 opirr(Link *ctxt, int a) 2578 { 2579 switch(a) { 2580 case AADD: return OPVCC(14,0,0,0); 2581 case AADDC: return OPVCC(12,0,0,0); 2582 case AADDCCC: return OPVCC(13,0,0,0); 2583 case AADD+AEND: return OPVCC(15,0,0,0); /* ADDIS/CAU */ 2584 2585 case AANDCC: return OPVCC(28,0,0,0); 2586 case AANDCC+AEND: return OPVCC(29,0,0,0); /* ANDIS./ANDIU. */ 2587 2588 case ABR: return OPVCC(18,0,0,0); 2589 case ABL: return OPVCC(18,0,0,0) | 1; 2590 case ADUFFZERO: return OPVCC(18,0,0,0) | 1; 2591 case ADUFFCOPY: return OPVCC(18,0,0,0) | 1; 2592 case ABC: return OPVCC(16,0,0,0); 2593 case ABCL: return OPVCC(16,0,0,0) | 1; 2594 2595 case ABEQ: return AOP_RRR(16<<26,12,2,0); 2596 case ABGE: return AOP_RRR(16<<26,4,0,0); 2597 case ABGT: return AOP_RRR(16<<26,12,1,0); 2598 case ABLE: return AOP_RRR(16<<26,4,1,0); 2599 case ABLT: return AOP_RRR(16<<26,12,0,0); 2600 case ABNE: return AOP_RRR(16<<26,4,2,0); 2601 case ABVC: return AOP_RRR(16<<26,4,3,0); 2602 case ABVS: return AOP_RRR(16<<26,12,3,0); 2603 2604 case ACMP: return OPVCC(11,0,0,0)|(1<<21); /* L=1 */ 2605 case ACMPU: return OPVCC(10,0,0,0)|(1<<21); 2606 case ACMPW: return OPVCC(11,0,0,0); /* L=0 */ 2607 case ACMPWU: return OPVCC(10,0,0,0); 2608 case ALSW: return OPVCC(31,597,0,0); 2609 2610 case AMULLW: return OPVCC(7,0,0,0); 2611 2612 case AOR: return OPVCC(24,0,0,0); 2613 case AOR+AEND: return OPVCC(25,0,0,0); /* ORIS/ORIU */ 2614 2615 case ARLWMI: return OPVCC(20,0,0,0); /* rlwimi */ 2616 case ARLWMICC: return OPVCC(20,0,0,1); 2617 case ARLDMI: return OPVCC(30,0,0,0) | (3<<2); /* rldimi */ 2618 case ARLDMICC: return OPVCC(30,0,0,1) | (3<<2); 2619 2620 case ARLWNM: return OPVCC(21,0,0,0); /* rlwinm */ 2621 case ARLWNMCC: return OPVCC(21,0,0,1); 2622 2623 case ARLDCL: return OPVCC(30,0,0,0); /* rldicl */ 2624 case ARLDCLCC: return OPVCC(30,0,0,1); 2625 case ARLDCR: return OPVCC(30,1,0,0); /* rldicr */ 2626 case ARLDCRCC: return OPVCC(30,1,0,1); 2627 case ARLDC: return OPVCC(30,0,0,0) | (2<<2); 2628 case ARLDCCC: return OPVCC(30,0,0,1) | (2<<2); 2629 2630 case ASRAW: return OPVCC(31,824,0,0); 2631 case ASRAWCC: return OPVCC(31,824,0,1); 2632 case ASRAD: return OPVCC(31,(413<<1),0,0); 2633 case ASRADCC: return OPVCC(31,(413<<1),0,1); 2634 2635 case ASTSW: return OPVCC(31,725,0,0); 2636 2637 case ASUBC: return OPVCC(8,0,0,0); 2638 2639 case ATW: return OPVCC(3,0,0,0); 2640 case ATD: return OPVCC(2,0,0,0); 2641 2642 case AXOR: return OPVCC(26,0,0,0); /* XORIL */ 2643 case AXOR+AEND: return OPVCC(27,0,0,0); /* XORIU */ 2644 } 2645 ctxt->diag("bad opcode i/r %A", a); 2646 return 0; 2647 } 2648 2649 /* 2650 * load o(a),d 2651 */ 2652 static int32 2653 opload(Link *ctxt, int a) 2654 { 2655 switch(a) { 2656 case AMOVD: return OPVCC(58,0,0,0); /* ld */ 2657 case AMOVDU: return OPVCC(58,0,0,1); /* ldu */ 2658 case AMOVWZ: return OPVCC(32,0,0,0); /* lwz */ 2659 case AMOVWZU: return OPVCC(33,0,0,0); /* lwzu */ 2660 case AMOVW: return OPVCC(58,0,0,0)|(1<<1); /* lwa */ 2661 /* no AMOVWU */ 2662 case AMOVB: 2663 case AMOVBZ: return OPVCC(34,0,0,0); /* load */ 2664 case AMOVBU: 2665 case AMOVBZU: return OPVCC(35,0,0,0); 2666 case AFMOVD: return OPVCC(50,0,0,0); 2667 case AFMOVDU: return OPVCC(51,0,0,0); 2668 case AFMOVS: return OPVCC(48,0,0,0); 2669 case AFMOVSU: return OPVCC(49,0,0,0); 2670 case AMOVH: return OPVCC(42,0,0,0); 2671 case AMOVHU: return OPVCC(43,0,0,0); 2672 case AMOVHZ: return OPVCC(40,0,0,0); 2673 case AMOVHZU: return OPVCC(41,0,0,0); 2674 case AMOVMW: return OPVCC(46,0,0,0); /* lmw */ 2675 } 2676 ctxt->diag("bad load opcode %A", a); 2677 return 0; 2678 } 2679 2680 /* 2681 * indexed load a(b),d 2682 */ 2683 static int32 2684 oploadx(Link *ctxt, int a) 2685 { 2686 switch(a) { 2687 case AMOVWZ: return OPVCC(31,23,0,0); /* lwzx */ 2688 case AMOVWZU: return OPVCC(31,55,0,0); /* lwzux */ 2689 case AMOVW: return OPVCC(31,341,0,0); /* lwax */ 2690 case AMOVWU: return OPVCC(31,373,0,0); /* lwaux */ 2691 case AMOVB: 2692 case AMOVBZ: return OPVCC(31,87,0,0); /* lbzx */ 2693 case AMOVBU: 2694 case AMOVBZU: return OPVCC(31,119,0,0); /* lbzux */ 2695 case AFMOVD: return OPVCC(31,599,0,0); /* lfdx */ 2696 case AFMOVDU: return OPVCC(31,631,0,0); /* lfdux */ 2697 case AFMOVS: return OPVCC(31,535,0,0); /* lfsx */ 2698 case AFMOVSU: return OPVCC(31,567,0,0); /* lfsux */ 2699 case AMOVH: return OPVCC(31,343,0,0); /* lhax */ 2700 case AMOVHU: return OPVCC(31,375,0,0); /* lhaux */ 2701 case AMOVHBR: return OPVCC(31,790,0,0); /* lhbrx */ 2702 case AMOVWBR: return OPVCC(31,534,0,0); /* lwbrx */ 2703 case AMOVHZ: return OPVCC(31,279,0,0); /* lhzx */ 2704 case AMOVHZU: return OPVCC(31,311,0,0); /* lhzux */ 2705 case AECIWX: return OPVCC(31,310,0,0); /* eciwx */ 2706 case ALWAR: return OPVCC(31,20,0,0); /* lwarx */ 2707 case ALDAR: return OPVCC(31,84,0,0); 2708 case ALSW: return OPVCC(31,533,0,0); /* lswx */ 2709 case AMOVD: return OPVCC(31,21,0,0); /* ldx */ 2710 case AMOVDU: return OPVCC(31,53,0,0); /* ldux */ 2711 } 2712 ctxt->diag("bad loadx opcode %A", a); 2713 return 0; 2714 } 2715 2716 /* 2717 * store s,o(d) 2718 */ 2719 static int32 2720 opstore(Link *ctxt, int a) 2721 { 2722 switch(a) { 2723 case AMOVB: 2724 case AMOVBZ: return OPVCC(38,0,0,0); /* stb */ 2725 case AMOVBU: 2726 case AMOVBZU: return OPVCC(39,0,0,0); /* stbu */ 2727 case AFMOVD: return OPVCC(54,0,0,0); /* stfd */ 2728 case AFMOVDU: return OPVCC(55,0,0,0); /* stfdu */ 2729 case AFMOVS: return OPVCC(52,0,0,0); /* stfs */ 2730 case AFMOVSU: return OPVCC(53,0,0,0); /* stfsu */ 2731 case AMOVHZ: 2732 case AMOVH: return OPVCC(44,0,0,0); /* sth */ 2733 case AMOVHZU: 2734 case AMOVHU: return OPVCC(45,0,0,0); /* sthu */ 2735 case AMOVMW: return OPVCC(47,0,0,0); /* stmw */ 2736 case ASTSW: return OPVCC(31,725,0,0); /* stswi */ 2737 case AMOVWZ: 2738 case AMOVW: return OPVCC(36,0,0,0); /* stw */ 2739 case AMOVWZU: 2740 case AMOVWU: return OPVCC(37,0,0,0); /* stwu */ 2741 case AMOVD: return OPVCC(62,0,0,0); /* std */ 2742 case AMOVDU: return OPVCC(62,0,0,1); /* stdu */ 2743 } 2744 ctxt->diag("unknown store opcode %A", a); 2745 return 0; 2746 } 2747 2748 /* 2749 * indexed store s,a(b) 2750 */ 2751 static int32 2752 opstorex(Link *ctxt, int a) 2753 { 2754 switch(a) { 2755 case AMOVB: 2756 case AMOVBZ: return OPVCC(31,215,0,0); /* stbx */ 2757 case AMOVBU: 2758 case AMOVBZU: return OPVCC(31,247,0,0); /* stbux */ 2759 case AFMOVD: return OPVCC(31,727,0,0); /* stfdx */ 2760 case AFMOVDU: return OPVCC(31,759,0,0); /* stfdux */ 2761 case AFMOVS: return OPVCC(31,663,0,0); /* stfsx */ 2762 case AFMOVSU: return OPVCC(31,695,0,0); /* stfsux */ 2763 case AMOVHZ: 2764 case AMOVH: return OPVCC(31,407,0,0); /* sthx */ 2765 case AMOVHBR: return OPVCC(31,918,0,0); /* sthbrx */ 2766 case AMOVHZU: 2767 case AMOVHU: return OPVCC(31,439,0,0); /* sthux */ 2768 case AMOVWZ: 2769 case AMOVW: return OPVCC(31,151,0,0); /* stwx */ 2770 case AMOVWZU: 2771 case AMOVWU: return OPVCC(31,183,0,0); /* stwux */ 2772 case ASTSW: return OPVCC(31,661,0,0); /* stswx */ 2773 case AMOVWBR: return OPVCC(31,662,0,0); /* stwbrx */ 2774 case ASTWCCC: return OPVCC(31,150,0,1); /* stwcx. */ 2775 case ASTDCCC: return OPVCC(31,214,0,1); /* stwdx. */ 2776 case AECOWX: return OPVCC(31,438,0,0); /* ecowx */ 2777 case AMOVD: return OPVCC(31,149,0,0); /* stdx */ 2778 case AMOVDU: return OPVCC(31,181,0,0); /* stdux */ 2779 } 2780 ctxt->diag("unknown storex opcode %A", a); 2781 return 0; 2782 } 2783