github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/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 if(isint32(ctxt->instoffset)) 687 return C_LACON; 688 return C_DACON; 689 } 690 consize: 691 if(ctxt->instoffset >= 0) { 692 if(ctxt->instoffset == 0) 693 return C_ZCON; 694 if(ctxt->instoffset <= 0x7fff) 695 return C_SCON; 696 if(ctxt->instoffset <= 0xffff) 697 return C_ANDCON; 698 if((ctxt->instoffset & 0xffff) == 0 && isuint32(ctxt->instoffset)) /* && (instoffset & (1<<31)) == 0) */ 699 return C_UCON; 700 if(isint32(ctxt->instoffset) || isuint32(ctxt->instoffset)) 701 return C_LCON; 702 return C_DCON; 703 } 704 if(ctxt->instoffset >= -0x8000) 705 return C_ADDCON; 706 if((ctxt->instoffset & 0xffff) == 0 && isint32(ctxt->instoffset)) 707 return C_UCON; 708 if(isint32(ctxt->instoffset)) 709 return C_LCON; 710 return C_DCON; 711 712 case D_EXTERN: 713 case D_STATIC: 714 s = a->sym; 715 if(s == nil) 716 break; 717 if(s->type == SCONST) { 718 ctxt->instoffset = s->value + a->offset; 719 goto consize; 720 } 721 ctxt->instoffset = s->value + a->offset; 722 /* not sure why this barfs */ 723 return C_LCON; 724 725 case D_AUTO: 726 ctxt->instoffset = ctxt->autosize + a->offset; 727 if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) 728 return C_SACON; 729 return C_LACON; 730 731 case D_PARAM: 732 ctxt->instoffset = ctxt->autosize + a->offset + 8L; 733 if(ctxt->instoffset >= -BIG && ctxt->instoffset < BIG) 734 return C_SACON; 735 return C_LACON; 736 } 737 return C_GOK; 738 739 case D_BRANCH: 740 return C_SBRA; 741 } 742 return C_GOK; 743 } 744 745 static void 746 prasm(Prog *p) 747 { 748 print("%P\n", p); 749 } 750 751 static Optab* 752 oplook(Link *ctxt, Prog *p) 753 { 754 int a1, a2, a3, a4, r; 755 uchar *c1, *c3, *c4; 756 Optab *o, *e; 757 758 a1 = p->optab; 759 if(a1) 760 return optab+(a1-1); 761 a1 = p->from.class; 762 if(a1 == 0) { 763 a1 = aclass(ctxt, &p->from) + 1; 764 p->from.class = a1; 765 } 766 a1--; 767 a3 = p->from3.class; 768 if(a3 == 0) { 769 a3 = aclass(ctxt, &p->from3) + 1; 770 p->from3.class = a3; 771 } 772 a3--; 773 a4 = p->to.class; 774 if(a4 == 0) { 775 a4 = aclass(ctxt, &p->to) + 1; 776 p->to.class = a4; 777 } 778 a4--; 779 a2 = C_NONE; 780 if(p->reg != NREG) 781 a2 = C_REG; 782 //print("oplook %P %d %d %d %d\n", p, a1, a2, a3, a4); 783 r = p->as; 784 o = oprange[r].start; 785 if(o == 0) 786 o = oprange[r].stop; /* just generate an error */ 787 e = oprange[r].stop; 788 c1 = xcmp[a1]; 789 c3 = xcmp[a3]; 790 c4 = xcmp[a4]; 791 for(; o<e; o++) 792 if(o->a2 == a2) 793 if(c1[o->a1]) 794 if(c3[o->a3]) 795 if(c4[o->a4]) { 796 p->optab = (o-optab)+1; 797 return o; 798 } 799 ctxt->diag("illegal combination %A %^ %^ %^ %^", 800 p->as, a1, a2, a3, a4); 801 prasm(p); 802 if(o == 0) 803 o = optab; 804 return o; 805 } 806 807 static int 808 cmp(int a, int b) 809 { 810 811 if(a == b) 812 return 1; 813 switch(a) { 814 case C_LCON: 815 if(b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON) 816 return 1; 817 break; 818 case C_ADDCON: 819 if(b == C_ZCON || b == C_SCON) 820 return 1; 821 break; 822 case C_ANDCON: 823 if(b == C_ZCON || b == C_SCON) 824 return 1; 825 break; 826 case C_SPR: 827 if(b == C_LR || b == C_XER || b == C_CTR) 828 return 1; 829 break; 830 case C_UCON: 831 if(b == C_ZCON) 832 return 1; 833 break; 834 case C_SCON: 835 if(b == C_ZCON) 836 return 1; 837 break; 838 case C_LACON: 839 if(b == C_SACON) 840 return 1; 841 break; 842 case C_LBRA: 843 if(b == C_SBRA) 844 return 1; 845 break; 846 case C_LEXT: 847 if(b == C_SEXT) 848 return 1; 849 break; 850 case C_LAUTO: 851 if(b == C_SAUTO) 852 return 1; 853 break; 854 case C_REG: 855 if(b == C_ZCON) 856 return r0iszero; 857 break; 858 case C_LOREG: 859 if(b == C_ZOREG || b == C_SOREG) 860 return 1; 861 break; 862 case C_SOREG: 863 if(b == C_ZOREG) 864 return 1; 865 break; 866 867 case C_ANY: 868 return 1; 869 } 870 return 0; 871 } 872 873 static int 874 ocmp(const void *a1, const void *a2) 875 { 876 const Optab *p1, *p2; 877 int n; 878 879 p1 = a1; 880 p2 = a2; 881 n = p1->as - p2->as; 882 if(n) 883 return n; 884 n = p1->a1 - p2->a1; 885 if(n) 886 return n; 887 n = p1->a2 - p2->a2; 888 if(n) 889 return n; 890 n = p1->a3 - p2->a3; 891 if(n) 892 return n; 893 n = p1->a4 - p2->a4; 894 if(n) 895 return n; 896 return 0; 897 } 898 899 static void 900 buildop(Link *ctxt) 901 { 902 int i, n, r; 903 904 for(i=0; i<C_NCLASS; i++) 905 for(n=0; n<C_NCLASS; n++) 906 xcmp[i][n] = cmp(n, i); 907 for(n=0; optab[n].as != AXXX; n++) 908 ; 909 qsort(optab, n, sizeof(optab[0]), ocmp); 910 for(i=0; i<n; i++) { 911 r = optab[i].as; 912 oprange[r].start = optab+i; 913 while(optab[i].as == r) 914 i++; 915 oprange[r].stop = optab+i; 916 i--; 917 918 switch(r) 919 { 920 default: 921 ctxt->diag("unknown op in build: %A", r); 922 sysfatal("bad code"); 923 case ADCBF: /* unary indexed: op (b+a); op (b) */ 924 oprange[ADCBI] = oprange[r]; 925 oprange[ADCBST] = oprange[r]; 926 oprange[ADCBT] = oprange[r]; 927 oprange[ADCBTST] = oprange[r]; 928 oprange[ADCBZ] = oprange[r]; 929 oprange[AICBI] = oprange[r]; 930 break; 931 case AECOWX: /* indexed store: op s,(b+a); op s,(b) */ 932 oprange[ASTWCCC] = oprange[r]; 933 oprange[ASTDCCC] = oprange[r]; 934 break; 935 case AREM: /* macro */ 936 oprange[AREMCC] = oprange[r]; 937 oprange[AREMV] = oprange[r]; 938 oprange[AREMVCC] = oprange[r]; 939 break; 940 case AREMU: 941 oprange[AREMU] = oprange[r]; 942 oprange[AREMUCC] = oprange[r]; 943 oprange[AREMUV] = oprange[r]; 944 oprange[AREMUVCC] = oprange[r]; 945 break; 946 case AREMD: 947 oprange[AREMDCC] = oprange[r]; 948 oprange[AREMDV] = oprange[r]; 949 oprange[AREMDVCC] = oprange[r]; 950 break; 951 case AREMDU: 952 oprange[AREMDU] = oprange[r]; 953 oprange[AREMDUCC] = oprange[r]; 954 oprange[AREMDUV] = oprange[r]; 955 oprange[AREMDUVCC] = oprange[r]; 956 break; 957 case ADIVW: /* op Rb[,Ra],Rd */ 958 oprange[AMULHW] = oprange[r]; 959 oprange[AMULHWCC] = oprange[r]; 960 oprange[AMULHWU] = oprange[r]; 961 oprange[AMULHWUCC] = oprange[r]; 962 oprange[AMULLWCC] = oprange[r]; 963 oprange[AMULLWVCC] = oprange[r]; 964 oprange[AMULLWV] = oprange[r]; 965 oprange[ADIVWCC] = oprange[r]; 966 oprange[ADIVWV] = oprange[r]; 967 oprange[ADIVWVCC] = oprange[r]; 968 oprange[ADIVWU] = oprange[r]; 969 oprange[ADIVWUCC] = oprange[r]; 970 oprange[ADIVWUV] = oprange[r]; 971 oprange[ADIVWUVCC] = oprange[r]; 972 oprange[AADDCC] = oprange[r]; 973 oprange[AADDCV] = oprange[r]; 974 oprange[AADDCVCC] = oprange[r]; 975 oprange[AADDV] = oprange[r]; 976 oprange[AADDVCC] = oprange[r]; 977 oprange[AADDE] = oprange[r]; 978 oprange[AADDECC] = oprange[r]; 979 oprange[AADDEV] = oprange[r]; 980 oprange[AADDEVCC] = oprange[r]; 981 oprange[ACRAND] = oprange[r]; 982 oprange[ACRANDN] = oprange[r]; 983 oprange[ACREQV] = oprange[r]; 984 oprange[ACRNAND] = oprange[r]; 985 oprange[ACRNOR] = oprange[r]; 986 oprange[ACROR] = oprange[r]; 987 oprange[ACRORN] = oprange[r]; 988 oprange[ACRXOR] = oprange[r]; 989 oprange[AMULHD] = oprange[r]; 990 oprange[AMULHDCC] = oprange[r]; 991 oprange[AMULHDU] = oprange[r]; 992 oprange[AMULHDUCC] = oprange[r]; 993 oprange[AMULLD] = oprange[r]; 994 oprange[AMULLDCC] = oprange[r]; 995 oprange[AMULLDVCC] = oprange[r]; 996 oprange[AMULLDV] = oprange[r]; 997 oprange[ADIVD] = oprange[r]; 998 oprange[ADIVDCC] = oprange[r]; 999 oprange[ADIVDVCC] = oprange[r]; 1000 oprange[ADIVDV] = oprange[r]; 1001 oprange[ADIVDU] = oprange[r]; 1002 oprange[ADIVDUCC] = oprange[r]; 1003 oprange[ADIVDUVCC] = oprange[r]; 1004 oprange[ADIVDUCC] = oprange[r]; 1005 break; 1006 case AMOVBZ: /* lbz, stz, rlwm(r/r), lhz, lha, stz, and x variants */ 1007 oprange[AMOVH] = oprange[r]; 1008 oprange[AMOVHZ] = oprange[r]; 1009 break; 1010 case AMOVBZU: /* lbz[x]u, stb[x]u, lhz[x]u, lha[x]u, sth[u]x, ld[x]u, std[u]x */ 1011 oprange[AMOVHU] = oprange[r]; 1012 oprange[AMOVHZU] = oprange[r]; 1013 oprange[AMOVWU] = oprange[r]; 1014 oprange[AMOVWZU] = oprange[r]; 1015 oprange[AMOVDU] = oprange[r]; 1016 oprange[AMOVMW] = oprange[r]; 1017 break; 1018 case AAND: /* logical op Rb,Rs,Ra; no literal */ 1019 oprange[AANDN] = oprange[r]; 1020 oprange[AANDNCC] = oprange[r]; 1021 oprange[AEQV] = oprange[r]; 1022 oprange[AEQVCC] = oprange[r]; 1023 oprange[ANAND] = oprange[r]; 1024 oprange[ANANDCC] = oprange[r]; 1025 oprange[ANOR] = oprange[r]; 1026 oprange[ANORCC] = oprange[r]; 1027 oprange[AORCC] = oprange[r]; 1028 oprange[AORN] = oprange[r]; 1029 oprange[AORNCC] = oprange[r]; 1030 oprange[AXORCC] = oprange[r]; 1031 break; 1032 case AADDME: /* op Ra, Rd */ 1033 oprange[AADDMECC] = oprange[r]; 1034 oprange[AADDMEV] = oprange[r]; 1035 oprange[AADDMEVCC] = oprange[r]; 1036 oprange[AADDZE] = oprange[r]; 1037 oprange[AADDZECC] = oprange[r]; 1038 oprange[AADDZEV] = oprange[r]; 1039 oprange[AADDZEVCC] = oprange[r]; 1040 oprange[ASUBME] = oprange[r]; 1041 oprange[ASUBMECC] = oprange[r]; 1042 oprange[ASUBMEV] = oprange[r]; 1043 oprange[ASUBMEVCC] = oprange[r]; 1044 oprange[ASUBZE] = oprange[r]; 1045 oprange[ASUBZECC] = oprange[r]; 1046 oprange[ASUBZEV] = oprange[r]; 1047 oprange[ASUBZEVCC] = oprange[r]; 1048 break; 1049 case AADDC: 1050 oprange[AADDCCC] = oprange[r]; 1051 break; 1052 case ABEQ: 1053 oprange[ABGE] = oprange[r]; 1054 oprange[ABGT] = oprange[r]; 1055 oprange[ABLE] = oprange[r]; 1056 oprange[ABLT] = oprange[r]; 1057 oprange[ABNE] = oprange[r]; 1058 oprange[ABVC] = oprange[r]; 1059 oprange[ABVS] = oprange[r]; 1060 break; 1061 case ABR: 1062 oprange[ABL] = oprange[r]; 1063 break; 1064 case ABC: 1065 oprange[ABCL] = oprange[r]; 1066 break; 1067 case AEXTSB: /* op Rs, Ra */ 1068 oprange[AEXTSBCC] = oprange[r]; 1069 oprange[AEXTSH] = oprange[r]; 1070 oprange[AEXTSHCC] = oprange[r]; 1071 oprange[ACNTLZW] = oprange[r]; 1072 oprange[ACNTLZWCC] = oprange[r]; 1073 oprange[ACNTLZD] = oprange[r]; 1074 oprange[AEXTSW] = oprange[r]; 1075 oprange[AEXTSWCC] = oprange[r]; 1076 oprange[ACNTLZDCC] = oprange[r]; 1077 break; 1078 case AFABS: /* fop [s,]d */ 1079 oprange[AFABSCC] = oprange[r]; 1080 oprange[AFNABS] = oprange[r]; 1081 oprange[AFNABSCC] = oprange[r]; 1082 oprange[AFNEG] = oprange[r]; 1083 oprange[AFNEGCC] = oprange[r]; 1084 oprange[AFRSP] = oprange[r]; 1085 oprange[AFRSPCC] = oprange[r]; 1086 oprange[AFCTIW] = oprange[r]; 1087 oprange[AFCTIWCC] = oprange[r]; 1088 oprange[AFCTIWZ] = oprange[r]; 1089 oprange[AFCTIWZCC] = oprange[r]; 1090 oprange[AFCTID] = oprange[r]; 1091 oprange[AFCTIDCC] = oprange[r]; 1092 oprange[AFCTIDZ] = oprange[r]; 1093 oprange[AFCTIDZCC] = oprange[r]; 1094 oprange[AFCFID] = oprange[r]; 1095 oprange[AFCFIDCC] = oprange[r]; 1096 oprange[AFRES] = oprange[r]; 1097 oprange[AFRESCC] = oprange[r]; 1098 oprange[AFRSQRTE] = oprange[r]; 1099 oprange[AFRSQRTECC] = oprange[r]; 1100 oprange[AFSQRT] = oprange[r]; 1101 oprange[AFSQRTCC] = oprange[r]; 1102 oprange[AFSQRTS] = oprange[r]; 1103 oprange[AFSQRTSCC] = oprange[r]; 1104 break; 1105 case AFADD: 1106 oprange[AFADDS] = oprange[r]; 1107 oprange[AFADDCC] = oprange[r]; 1108 oprange[AFADDSCC] = oprange[r]; 1109 oprange[AFDIV] = oprange[r]; 1110 oprange[AFDIVS] = oprange[r]; 1111 oprange[AFDIVCC] = oprange[r]; 1112 oprange[AFDIVSCC] = oprange[r]; 1113 oprange[AFSUB] = oprange[r]; 1114 oprange[AFSUBS] = oprange[r]; 1115 oprange[AFSUBCC] = oprange[r]; 1116 oprange[AFSUBSCC] = oprange[r]; 1117 break; 1118 case AFMADD: 1119 oprange[AFMADDCC] = oprange[r]; 1120 oprange[AFMADDS] = oprange[r]; 1121 oprange[AFMADDSCC] = oprange[r]; 1122 oprange[AFMSUB] = oprange[r]; 1123 oprange[AFMSUBCC] = oprange[r]; 1124 oprange[AFMSUBS] = oprange[r]; 1125 oprange[AFMSUBSCC] = oprange[r]; 1126 oprange[AFNMADD] = oprange[r]; 1127 oprange[AFNMADDCC] = oprange[r]; 1128 oprange[AFNMADDS] = oprange[r]; 1129 oprange[AFNMADDSCC] = oprange[r]; 1130 oprange[AFNMSUB] = oprange[r]; 1131 oprange[AFNMSUBCC] = oprange[r]; 1132 oprange[AFNMSUBS] = oprange[r]; 1133 oprange[AFNMSUBSCC] = oprange[r]; 1134 oprange[AFSEL] = oprange[r]; 1135 oprange[AFSELCC] = oprange[r]; 1136 break; 1137 case AFMUL: 1138 oprange[AFMULS] = oprange[r]; 1139 oprange[AFMULCC] = oprange[r]; 1140 oprange[AFMULSCC] = oprange[r]; 1141 break; 1142 case AFCMPO: 1143 oprange[AFCMPU] = oprange[r]; 1144 break; 1145 case AMTFSB0: 1146 oprange[AMTFSB0CC] = oprange[r]; 1147 oprange[AMTFSB1] = oprange[r]; 1148 oprange[AMTFSB1CC] = oprange[r]; 1149 break; 1150 case ANEG: /* op [Ra,] Rd */ 1151 oprange[ANEGCC] = oprange[r]; 1152 oprange[ANEGV] = oprange[r]; 1153 oprange[ANEGVCC] = oprange[r]; 1154 break; 1155 case AOR: /* or/xor Rb,Rs,Ra; ori/xori $uimm,Rs,Ra; oris/xoris $uimm,Rs,Ra */ 1156 oprange[AXOR] = oprange[r]; 1157 break; 1158 case ASLW: 1159 oprange[ASLWCC] = oprange[r]; 1160 oprange[ASRW] = oprange[r]; 1161 oprange[ASRWCC] = oprange[r]; 1162 break; 1163 case ASLD: 1164 oprange[ASLDCC] = oprange[r]; 1165 oprange[ASRD] = oprange[r]; 1166 oprange[ASRDCC] = oprange[r]; 1167 break; 1168 case ASRAW: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */ 1169 oprange[ASRAWCC] = oprange[r]; 1170 break; 1171 case ASRAD: /* sraw Rb,Rs,Ra; srawi sh,Rs,Ra */ 1172 oprange[ASRADCC] = oprange[r]; 1173 break; 1174 case ASUB: /* SUB Ra,Rb,Rd => subf Rd,ra,rb */ 1175 oprange[ASUB] = oprange[r]; 1176 oprange[ASUBCC] = oprange[r]; 1177 oprange[ASUBV] = oprange[r]; 1178 oprange[ASUBVCC] = oprange[r]; 1179 oprange[ASUBCCC] = oprange[r]; 1180 oprange[ASUBCV] = oprange[r]; 1181 oprange[ASUBCVCC] = oprange[r]; 1182 oprange[ASUBE] = oprange[r]; 1183 oprange[ASUBECC] = oprange[r]; 1184 oprange[ASUBEV] = oprange[r]; 1185 oprange[ASUBEVCC] = oprange[r]; 1186 break; 1187 case ASYNC: 1188 oprange[AISYNC] = oprange[r]; 1189 oprange[APTESYNC] = oprange[r]; 1190 oprange[ATLBSYNC] = oprange[r]; 1191 break; 1192 case ARLWMI: 1193 oprange[ARLWMICC] = oprange[r]; 1194 oprange[ARLWNM] = oprange[r]; 1195 oprange[ARLWNMCC] = oprange[r]; 1196 break; 1197 case ARLDMI: 1198 oprange[ARLDMICC] = oprange[r]; 1199 break; 1200 case ARLDC: 1201 oprange[ARLDCCC] = oprange[r]; 1202 break; 1203 case ARLDCL: 1204 oprange[ARLDCR] = oprange[r]; 1205 oprange[ARLDCLCC] = oprange[r]; 1206 oprange[ARLDCRCC] = oprange[r]; 1207 break; 1208 case AFMOVD: 1209 oprange[AFMOVDCC] = oprange[r]; 1210 oprange[AFMOVDU] = oprange[r]; 1211 oprange[AFMOVS] = oprange[r]; 1212 oprange[AFMOVSU] = oprange[r]; 1213 break; 1214 case AECIWX: 1215 oprange[ALWAR] = oprange[r]; 1216 oprange[ALDAR] = oprange[r]; 1217 break; 1218 case ASYSCALL: /* just the op; flow of control */ 1219 oprange[ARFI] = oprange[r]; 1220 oprange[ARFCI] = oprange[r]; 1221 oprange[ARFID] = oprange[r]; 1222 oprange[AHRFID] = oprange[r]; 1223 break; 1224 case AMOVHBR: 1225 oprange[AMOVWBR] = oprange[r]; 1226 break; 1227 case ASLBMFEE: 1228 oprange[ASLBMFEV] = oprange[r]; 1229 break; 1230 case ATW: 1231 oprange[ATD] = oprange[r]; 1232 break; 1233 case ATLBIE: 1234 oprange[ASLBIE] = oprange[r]; 1235 oprange[ATLBIEL] = oprange[r]; 1236 break; 1237 case AEIEIO: 1238 oprange[ASLBIA] = oprange[r]; 1239 break; 1240 case ACMP: 1241 oprange[ACMPW] = oprange[r]; 1242 break; 1243 case ACMPU: 1244 oprange[ACMPWU] = oprange[r]; 1245 break; 1246 case AADD: 1247 case AANDCC: /* and. Rb,Rs,Ra; andi. $uimm,Rs,Ra; andis. $uimm,Rs,Ra */ 1248 case ALSW: 1249 case AMOVW: /* load/store/move word with sign extension; special 32-bit move; move 32-bit literals */ 1250 case AMOVWZ: /* load/store/move word with zero extension; move 32-bit literals */ 1251 case AMOVD: /* load/store/move 64-bit values, including 32-bit literals with/without sign-extension */ 1252 case AMOVB: /* macro: move byte with sign extension */ 1253 case AMOVBU: /* macro: move byte with sign extension & update */ 1254 case AMOVFL: 1255 case AMULLW: /* op $s[,r2],r3; op r1[,r2],r3; no cc/v */ 1256 case ASUBC: /* op r1,$s,r3; op r1[,r2],r3 */ 1257 case ASTSW: 1258 case ASLBMTE: 1259 case AWORD: 1260 case ADWORD: 1261 case ANOP: 1262 case ATEXT: 1263 case AUNDEF: 1264 case AUSEFIELD: 1265 case AFUNCDATA: 1266 case APCDATA: 1267 case ADUFFZERO: 1268 case ADUFFCOPY: 1269 break; 1270 } 1271 } 1272 } 1273 1274 #define OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1)) 1275 #define OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc)) 1276 #define OP(o,xo) OPVCC((o),(xo),0,0) 1277 1278 /* the order is dest, a/s, b/imm for both arithmetic and logical operations */ 1279 #define AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11)) 1280 #define AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF)) 1281 #define LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11)) 1282 #define LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF)) 1283 #define OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1)) 1284 #define OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1)) 1285 #define OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)) 1286 #define OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\ 1287 (((mb)&31L)<<6)|(((me)&31L)<<1)) 1288 1289 #define OP_ADD OPVCC(31,266,0,0) 1290 #define OP_ADDI OPVCC(14,0,0,0) 1291 #define OP_ADDIS OPVCC(15,0,0,0) 1292 #define OP_ANDI OPVCC(28,0,0,0) 1293 #define OP_EXTSB OPVCC(31,954,0,0) 1294 #define OP_EXTSH OPVCC(31,922,0,0) 1295 #define OP_EXTSW OPVCC(31,986,0,0) 1296 #define OP_MCRF OPVCC(19,0,0,0) 1297 #define OP_MCRFS OPVCC(63,64,0,0) 1298 #define OP_MCRXR OPVCC(31,512,0,0) 1299 #define OP_MFCR OPVCC(31,19,0,0) 1300 #define OP_MFFS OPVCC(63,583,0,0) 1301 #define OP_MFMSR OPVCC(31,83,0,0) 1302 #define OP_MFSPR OPVCC(31,339,0,0) 1303 #define OP_MFSR OPVCC(31,595,0,0) 1304 #define OP_MFSRIN OPVCC(31,659,0,0) 1305 #define OP_MTCRF OPVCC(31,144,0,0) 1306 #define OP_MTFSF OPVCC(63,711,0,0) 1307 #define OP_MTFSFI OPVCC(63,134,0,0) 1308 #define OP_MTMSR OPVCC(31,146,0,0) 1309 #define OP_MTMSRD OPVCC(31,178,0,0) 1310 #define OP_MTSPR OPVCC(31,467,0,0) 1311 #define OP_MTSR OPVCC(31,210,0,0) 1312 #define OP_MTSRIN OPVCC(31,242,0,0) 1313 #define OP_MULLW OPVCC(31,235,0,0) 1314 #define OP_MULLD OPVCC(31,233,0,0) 1315 #define OP_OR OPVCC(31,444,0,0) 1316 #define OP_ORI OPVCC(24,0,0,0) 1317 #define OP_ORIS OPVCC(25,0,0,0) 1318 #define OP_RLWINM OPVCC(21,0,0,0) 1319 #define OP_SUBF OPVCC(31,40,0,0) 1320 #define OP_RLDIC OPVCC(30,4,0,0) 1321 #define OP_RLDICR OPVCC(30,2,0,0) 1322 #define OP_RLDICL OPVCC(30,0,0,0) 1323 1324 #define oclass(v) ((v).class-1) 1325 1326 // add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2. 1327 static void 1328 addaddrreloc(Link *ctxt, LSym *s, int *o1, int *o2) 1329 { 1330 Reloc *rel; 1331 1332 rel = addrel(ctxt->cursym); 1333 rel->off = ctxt->pc; 1334 rel->siz = 8; 1335 rel->sym = s; 1336 rel->add = ((uvlong)*o1<<32) | (uint32)*o2; 1337 rel->type = R_ADDRPOWER; 1338 } 1339 1340 /* 1341 * 32-bit masks 1342 */ 1343 static int 1344 getmask(uchar *m, uint32 v) 1345 { 1346 int i; 1347 1348 m[0] = m[1] = 0; 1349 if(v != ~0U && v & (1<<31) && v & 1){ /* MB > ME */ 1350 if(getmask(m, ~v)){ 1351 i = m[0]; m[0] = m[1]+1; m[1] = i-1; 1352 return 1; 1353 } 1354 return 0; 1355 } 1356 for(i=0; i<32; i++) 1357 if(v & (1<<(31-i))){ 1358 m[0] = i; 1359 do { 1360 m[1] = i; 1361 } while(++i<32 && (v & (1<<(31-i))) != 0); 1362 for(; i<32; i++) 1363 if(v & (1<<(31-i))) 1364 return 0; 1365 return 1; 1366 } 1367 return 0; 1368 } 1369 1370 static void 1371 maskgen(Link *ctxt, Prog *p, uchar *m, uint32 v) 1372 { 1373 if(!getmask(m, v)) 1374 ctxt->diag("cannot generate mask #%lux\n%P", v, p); 1375 } 1376 1377 /* 1378 * 64-bit masks (rldic etc) 1379 */ 1380 static int 1381 getmask64(uchar *m, uvlong v) 1382 { 1383 int i; 1384 1385 m[0] = m[1] = 0; 1386 for(i=0; i<64; i++) 1387 if(v & ((uvlong)1<<(63-i))){ 1388 m[0] = i; 1389 do { 1390 m[1] = i; 1391 } while(++i<64 && (v & ((uvlong)1<<(63-i))) != 0); 1392 for(; i<64; i++) 1393 if(v & ((uvlong)1<<(63-i))) 1394 return 0; 1395 return 1; 1396 } 1397 return 0; 1398 } 1399 1400 static void 1401 maskgen64(Link *ctxt, Prog *p, uchar *m, uvlong v) 1402 { 1403 if(!getmask64(m, v)) 1404 ctxt->diag("cannot generate mask #%llux\n%P", v, p); 1405 } 1406 1407 static uint32 1408 loadu32(int r, vlong d) 1409 { 1410 int32 v; 1411 1412 v = d>>16; 1413 if(isuint32(d)) 1414 return LOP_IRR(OP_ORIS, r, REGZERO, v); 1415 return AOP_IRR(OP_ADDIS, r, REGZERO, v); 1416 } 1417 1418 static uint16 1419 high16adjusted(int32 d) 1420 { 1421 if(d & 0x8000) 1422 return (d>>16) + 1; 1423 return d>>16; 1424 } 1425 1426 static void 1427 asmout(Link *ctxt, Prog *p, Optab *o, int32 *out) 1428 { 1429 int32 o1, o2, o3, o4, o5, v, t; 1430 vlong d; 1431 int r, a; 1432 uchar mask[2]; 1433 Reloc *rel; 1434 1435 o1 = 0; 1436 o2 = 0; 1437 o3 = 0; 1438 o4 = 0; 1439 o5 = 0; 1440 1441 //print("%P => case %d\n", p, o->type); 1442 switch(o->type) { 1443 default: 1444 ctxt->diag("unknown type %d", o->type); 1445 prasm(p); 1446 break; 1447 1448 case 0: /* pseudo ops */ 1449 break; 1450 1451 case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */ 1452 if(p->to.reg == REGZERO && p->from.type == D_CONST) { 1453 v = regoff(ctxt, &p->from); 1454 if(r0iszero && v != 0) { 1455 //nerrors--; 1456 ctxt->diag("literal operation on R0\n%P", p); 1457 } 1458 o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v); 1459 break; 1460 } 1461 o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg); 1462 break; 1463 1464 case 2: /* int/cr/fp op Rb,[Ra],Rd */ 1465 r = p->reg; 1466 if(r == NREG) 1467 r = p->to.reg; 1468 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg); 1469 break; 1470 1471 case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */ 1472 d = vregoff(ctxt, &p->from); 1473 v = d; 1474 r = p->from.reg; 1475 if(r == NREG) 1476 r = o->param; 1477 if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0)) 1478 ctxt->diag("literal operation on R0\n%P", p); 1479 a = OP_ADDI; 1480 if(o->a1 == C_UCON) { 1481 if((d&0xffff) != 0) 1482 sysfatal("invalid handling of %P", p); 1483 v >>= 16; 1484 if(r == REGZERO && isuint32(d)){ 1485 o1 = LOP_IRR(OP_ORIS, p->to.reg, REGZERO, v); 1486 break; 1487 } 1488 a = OP_ADDIS; 1489 } else { 1490 if((int16)d != d) 1491 sysfatal("invalid handling of %P", p); 1492 } 1493 o1 = AOP_IRR(a, p->to.reg, r, v); 1494 break; 1495 1496 case 4: /* add/mul $scon,[r1],r2 */ 1497 v = regoff(ctxt, &p->from); 1498 r = p->reg; 1499 if(r == NREG) 1500 r = p->to.reg; 1501 if(r0iszero && p->to.reg == 0) 1502 ctxt->diag("literal operation on R0\n%P", p); 1503 if((int16)v != v) 1504 sysfatal("mishandled instruction %P", p); 1505 o1 = AOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v); 1506 break; 1507 1508 case 5: /* syscall */ 1509 o1 = oprrr(ctxt, p->as); 1510 break; 1511 1512 case 6: /* logical op Rb,[Rs,]Ra; no literal */ 1513 r = p->reg; 1514 if(r == NREG) 1515 r = p->to.reg; 1516 o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg); 1517 break; 1518 1519 case 7: /* mov r, soreg ==> stw o(r) */ 1520 r = p->to.reg; 1521 if(r == NREG) 1522 r = o->param; 1523 v = regoff(ctxt, &p->to); 1524 if(p->to.type == D_OREG && p->reg != NREG) { 1525 if(v) 1526 ctxt->diag("illegal indexed instruction\n%P", p); 1527 o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, p->reg, r); 1528 } else { 1529 if((int16)v != v) 1530 sysfatal("mishandled instruction %P", p); 1531 o1 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, r, v); 1532 } 1533 break; 1534 1535 case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */ 1536 r = p->from.reg; 1537 if(r == NREG) 1538 r = o->param; 1539 v = regoff(ctxt, &p->from); 1540 if(p->from.type == D_OREG && p->reg != NREG) { 1541 if(v) 1542 ctxt->diag("illegal indexed instruction\n%P", p); 1543 o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r); 1544 } else { 1545 if((int16)v != v) 1546 sysfatal("mishandled instruction %P", p); 1547 o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v); 1548 } 1549 break; 1550 1551 case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */ 1552 r = p->from.reg; 1553 if(r == NREG) 1554 r = o->param; 1555 v = regoff(ctxt, &p->from); 1556 if(p->from.type == D_OREG && p->reg != NREG) { 1557 if(v) 1558 ctxt->diag("illegal indexed instruction\n%P", p); 1559 o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, p->reg, r); 1560 } else 1561 o1 = AOP_IRR(opload(ctxt, p->as), p->to.reg, r, v); 1562 o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0); 1563 break; 1564 1565 case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */ 1566 r = p->reg; 1567 if(r == NREG) 1568 r = p->to.reg; 1569 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, p->from.reg, r); 1570 break; 1571 1572 case 11: /* br/bl lbra */ 1573 v = 0; 1574 if(p->pcond) { 1575 v = p->pcond->pc - p->pc; 1576 if(v & 03) { 1577 ctxt->diag("odd branch target address\n%P", p); 1578 v &= ~03; 1579 } 1580 if(v < -(1L<<25) || v >= (1L<<24)) 1581 ctxt->diag("branch too far\n%P", p); 1582 } 1583 o1 = OP_BR(opirr(ctxt, p->as), v, 0); 1584 if(p->to.sym != nil) { 1585 rel = addrel(ctxt->cursym); 1586 rel->off = ctxt->pc; 1587 rel->siz = 4; 1588 rel->sym = p->to.sym; 1589 v += p->to.offset; 1590 if(v & 03) { 1591 ctxt->diag("odd branch target address\n%P", p); 1592 v &= ~03; 1593 } 1594 rel->add = v; 1595 rel->type = R_CALLPOWER; 1596 } 1597 break; 1598 1599 case 12: /* movb r,r (extsb); movw r,r (extsw) */ 1600 if(p->to.reg == REGZERO && p->from.type == D_CONST) { 1601 v = regoff(ctxt, &p->from); 1602 if(r0iszero && v != 0) { 1603 ctxt->diag("literal operation on R0\n%P", p); 1604 } 1605 o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v); 1606 break; 1607 } 1608 if(p->as == AMOVW) 1609 o1 = LOP_RRR(OP_EXTSW, p->to.reg, p->from.reg, 0); 1610 else 1611 o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0); 1612 break; 1613 1614 case 13: /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */ 1615 if(p->as == AMOVBZ) 1616 o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31); 1617 else if(p->as == AMOVH) 1618 o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0); 1619 else if(p->as == AMOVHZ) 1620 o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31); 1621 else if(p->as == AMOVWZ) 1622 o1 = OP_RLW(OP_RLDIC, p->to.reg, p->from.reg, 0, 0, 0) | (1<<5); /* MB=32 */ 1623 else 1624 ctxt->diag("internal: bad mov[bhw]z\n%P", p); 1625 break; 1626 1627 case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */ 1628 r = p->reg; 1629 if(r == NREG) 1630 r = p->to.reg; 1631 d = vregoff(ctxt, &p->from3); 1632 maskgen64(ctxt, p, mask, d); 1633 switch(p->as){ 1634 case ARLDCL: case ARLDCLCC: 1635 a = mask[0]; /* MB */ 1636 if(mask[1] != 63) 1637 ctxt->diag("invalid mask for rotate: %llux (end != bit 63)\n%P", d, p); 1638 break; 1639 case ARLDCR: case ARLDCRCC: 1640 a = mask[1]; /* ME */ 1641 if(mask[0] != 0) 1642 ctxt->diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p); 1643 break; 1644 default: 1645 ctxt->diag("unexpected op in rldc case\n%P", p); 1646 a = 0; 1647 } 1648 o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, p->from.reg); 1649 o1 |= (a&31L)<<6; 1650 if(a & 0x20) 1651 o1 |= 1<<5; /* mb[5] is top bit */ 1652 break; 1653 1654 case 17: /* bc bo,bi,lbra (same for now) */ 1655 case 16: /* bc bo,bi,sbra */ 1656 a = 0; 1657 if(p->from.type == D_CONST) 1658 a = regoff(ctxt, &p->from); 1659 r = p->reg; 1660 if(r == NREG) 1661 r = 0; 1662 v = 0; 1663 if(p->pcond) 1664 v = p->pcond->pc - p->pc; 1665 if(v & 03) { 1666 ctxt->diag("odd branch target address\n%P", p); 1667 v &= ~03; 1668 } 1669 if(v < -(1L<<16) || v >= (1L<<15)) 1670 ctxt->diag("branch too far\n%P", p); 1671 o1 = OP_BC(opirr(ctxt, p->as), a, r, v, 0); 1672 break; 1673 1674 case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */ 1675 if(p->as == ABC || p->as == ABCL) 1676 v = regoff(ctxt, &p->to)&31L; 1677 else 1678 v = 20; /* unconditional */ 1679 r = p->reg; 1680 if(r == NREG) 1681 r = 0; 1682 o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11); 1683 o2 = OPVCC(19, 16, 0, 0); 1684 if(p->as == ABL || p->as == ABCL) 1685 o2 |= 1; 1686 o2 = OP_BCR(o2, v, r); 1687 break; 1688 1689 case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */ 1690 if(p->as == ABC || p->as == ABCL) 1691 v = regoff(ctxt, &p->from)&31L; 1692 else 1693 v = 20; /* unconditional */ 1694 r = p->reg; 1695 if(r == NREG) 1696 r = 0; 1697 switch(oclass(p->to)) { 1698 case C_CTR: 1699 o1 = OPVCC(19, 528, 0, 0); 1700 break; 1701 case C_LR: 1702 o1 = OPVCC(19, 16, 0, 0); 1703 break; 1704 default: 1705 ctxt->diag("bad optab entry (18): %d\n%P", p->to.class, p); 1706 v = 0; 1707 } 1708 if(p->as == ABL || p->as == ABCL) 1709 o1 |= 1; 1710 o1 = OP_BCR(o1, v, r); 1711 break; 1712 1713 case 19: /* mov $lcon,r ==> cau+or */ 1714 d = vregoff(ctxt, &p->from); 1715 if(p->from.sym == nil) { 1716 o1 = loadu32(p->to.reg, d); 1717 o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, (int32)d); 1718 } else { 1719 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(d)); 1720 o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, d); 1721 addaddrreloc(ctxt, p->from.sym, &o1, &o2); 1722 } 1723 //if(dlm) reloc(&p->from, p->pc, 0); 1724 break; 1725 1726 case 20: /* add $ucon,,r */ 1727 v = regoff(ctxt, &p->from); 1728 r = p->reg; 1729 if(r == NREG) 1730 r = p->to.reg; 1731 if(p->as == AADD && (!r0iszero && p->reg == 0 || r0iszero && p->to.reg == 0)) 1732 ctxt->diag("literal operation on R0\n%P", p); 1733 o1 = AOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16); 1734 break; 1735 1736 case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */ 1737 if(p->to.reg == REGTMP || p->reg == REGTMP) 1738 ctxt->diag("cant synthesize large constant\n%P", p); 1739 d = vregoff(ctxt, &p->from); 1740 o1 = loadu32(REGTMP, d); 1741 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d); 1742 r = p->reg; 1743 if(r == NREG) 1744 r = p->to.reg; 1745 o3 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r); 1746 if(p->from.sym != nil) 1747 ctxt->diag("%P is not supported", p); 1748 //if(dlm) reloc(&p->from, p->pc, 0); 1749 break; 1750 1751 case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */ 1752 if(p->to.reg == REGTMP || p->reg == REGTMP) 1753 ctxt->diag("cant synthesize large constant\n%P", p); 1754 d = vregoff(ctxt, &p->from); 1755 o1 = loadu32(REGTMP, d); 1756 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (int32)d); 1757 r = p->reg; 1758 if(r == NREG) 1759 r = p->to.reg; 1760 o3 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, REGTMP, r); 1761 if(p->from.sym != nil) 1762 ctxt->diag("%P is not supported", p); 1763 //if(dlm) reloc(&p->from, p->pc, 0); 1764 break; 1765 /*24*/ 1766 1767 case 25: /* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */ 1768 v = regoff(ctxt, &p->from); 1769 if(v < 0) 1770 v = 0; 1771 else if(v > 63) 1772 v = 63; 1773 r = p->reg; 1774 if(r == NREG) 1775 r = p->to.reg; 1776 switch(p->as){ 1777 case ASLD: case ASLDCC: 1778 a = 63-v; 1779 o1 = OP_RLDICR; 1780 break; 1781 case ASRD: case ASRDCC: 1782 a = v; 1783 v = 64-v; 1784 o1 = OP_RLDICL; 1785 break; 1786 default: 1787 ctxt->diag("unexpected op in sldi case\n%P", p); 1788 a = 0; 1789 o1 = 0; 1790 } 1791 o1 = AOP_RRR(o1, r, p->to.reg, (v&0x1F)); 1792 o1 |= (a&31L)<<6; 1793 if(v & 0x20) 1794 o1 |= 1<<1; 1795 if(a & 0x20) 1796 o1 |= 1<<5; /* mb[5] is top bit */ 1797 if(p->as == ASLDCC || p->as == ASRDCC) 1798 o1 |= 1; /* Rc */ 1799 break; 1800 1801 case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */ 1802 if(p->to.reg == REGTMP) 1803 ctxt->diag("can't synthesize large constant\n%P", p); 1804 v = regoff(ctxt, &p->from); 1805 r = p->from.reg; 1806 if(r == NREG) 1807 r = o->param; 1808 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v)); 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 r = p->to.reg; 1917 if(r == NREG) 1918 r = o->param; 1919 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v)); 1920 o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v); 1921 break; 1922 1923 case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */ 1924 v = regoff(ctxt, &p->from); 1925 r = p->from.reg; 1926 if(r == NREG) 1927 r = o->param; 1928 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v)); 1929 o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v); 1930 break; 1931 1932 case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */ 1933 v = regoff(ctxt, &p->from); 1934 r = p->from.reg; 1935 if(r == NREG) 1936 r = o->param; 1937 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, high16adjusted(v)); 1938 o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v); 1939 o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0); 1940 break; 1941 1942 case 40: /* word */ 1943 o1 = regoff(ctxt, &p->from); 1944 break; 1945 1946 case 41: /* stswi */ 1947 o1 = AOP_RRR(opirr(ctxt, p->as), p->from.reg, p->to.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11); 1948 break; 1949 1950 case 42: /* lswi */ 1951 o1 = AOP_RRR(opirr(ctxt, p->as), p->to.reg, p->from.reg, 0) | ((regoff(ctxt, &p->from3)&0x7F)<<11); 1952 break; 1953 1954 case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */ 1955 r = p->reg; 1956 if(r == NREG) 1957 r = 0; 1958 o1 = AOP_RRR(oprrr(ctxt, p->as), 0, r, p->from.reg); 1959 break; 1960 1961 case 44: /* indexed store */ 1962 r = p->reg; 1963 if(r == NREG) 1964 r = 0; 1965 o1 = AOP_RRR(opstorex(ctxt, p->as), p->from.reg, r, p->to.reg); 1966 break; 1967 case 45: /* indexed load */ 1968 r = p->reg; 1969 if(r == NREG) 1970 r = 0; 1971 o1 = AOP_RRR(oploadx(ctxt, p->as), p->to.reg, r, p->from.reg); 1972 break; 1973 1974 case 46: /* plain op */ 1975 o1 = oprrr(ctxt, p->as); 1976 break; 1977 1978 case 47: /* op Ra, Rd; also op [Ra,] Rd */ 1979 r = p->from.reg; 1980 if(r == NREG) 1981 r = p->to.reg; 1982 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0); 1983 break; 1984 1985 case 48: /* op Rs, Ra */ 1986 r = p->from.reg; 1987 if(r == NREG) 1988 r = p->to.reg; 1989 o1 = LOP_RRR(oprrr(ctxt, p->as), p->to.reg, r, 0); 1990 break; 1991 1992 case 49: /* op Rb; op $n, Rb */ 1993 if(p->from.type != D_REG){ /* tlbie $L, rB */ 1994 v = regoff(ctxt, &p->from) & 1; 1995 o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->to.reg) | (v<<21); 1996 }else 1997 o1 = AOP_RRR(oprrr(ctxt, p->as), 0, 0, p->from.reg); 1998 break; 1999 2000 case 50: /* rem[u] r1[,r2],r3 */ 2001 r = p->reg; 2002 if(r == NREG) 2003 r = p->to.reg; 2004 v = oprrr(ctxt, p->as); 2005 t = v & ((1<<10)|1); /* OE|Rc */ 2006 o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg); 2007 o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg); 2008 o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r); 2009 if(p->as == AREMU) { 2010 o4 = o3; 2011 /* Clear top 32 bits */ 2012 o3 = OP_RLW(OP_RLDIC, REGTMP, REGTMP, 0, 0, 0) | (1<<5); 2013 } 2014 break; 2015 2016 case 51: /* remd[u] r1[,r2],r3 */ 2017 r = p->reg; 2018 if(r == NREG) 2019 r = p->to.reg; 2020 v = oprrr(ctxt, p->as); 2021 t = v & ((1<<10)|1); /* OE|Rc */ 2022 o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg); 2023 o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, p->from.reg); 2024 o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r); 2025 break; 2026 2027 case 52: /* mtfsbNx cr(n) */ 2028 v = regoff(ctxt, &p->from)&31L; 2029 o1 = AOP_RRR(oprrr(ctxt, p->as), v, 0, 0); 2030 break; 2031 2032 case 53: /* mffsX ,fr1 */ 2033 o1 = AOP_RRR(OP_MFFS, p->to.reg, 0, 0); 2034 break; 2035 2036 case 54: /* mov msr,r1; mov r1, msr*/ 2037 if(oclass(p->from) == C_REG){ 2038 if(p->as == AMOVD) 2039 o1 = AOP_RRR(OP_MTMSRD, p->from.reg, 0, 0); 2040 else 2041 o1 = AOP_RRR(OP_MTMSR, p->from.reg, 0, 0); 2042 }else 2043 o1 = AOP_RRR(OP_MFMSR, p->to.reg, 0, 0); 2044 break; 2045 2046 case 55: /* op Rb, Rd */ 2047 o1 = AOP_RRR(oprrr(ctxt, p->as), p->to.reg, 0, p->from.reg); 2048 break; 2049 2050 case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */ 2051 v = regoff(ctxt, &p->from); 2052 r = p->reg; 2053 if(r == NREG) 2054 r = p->to.reg; 2055 o1 = AOP_RRR(opirr(ctxt, p->as), r, p->to.reg, v&31L); 2056 if(p->as == ASRAD && (v&0x20)) 2057 o1 |= 1<<1; /* mb[5] */ 2058 break; 2059 2060 case 57: /* slw $sh,[s,]a -> rlwinm ... */ 2061 v = regoff(ctxt, &p->from); 2062 r = p->reg; 2063 if(r == NREG) 2064 r = p->to.reg; 2065 /* 2066 * Let user (gs) shoot himself in the foot. 2067 * qc has already complained. 2068 * 2069 if(v < 0 || v > 31) 2070 ctxt->diag("illegal shift %ld\n%P", v, p); 2071 */ 2072 if(v < 0) 2073 v = 0; 2074 else if(v > 32) 2075 v = 32; 2076 if(p->as == ASRW || p->as == ASRWCC) { /* shift right */ 2077 mask[0] = v; 2078 mask[1] = 31; 2079 v = 32-v; 2080 } else { 2081 mask[0] = 0; 2082 mask[1] = 31-v; 2083 } 2084 o1 = OP_RLW(OP_RLWINM, p->to.reg, r, v, mask[0], mask[1]); 2085 if(p->as == ASLWCC || p->as == ASRWCC) 2086 o1 |= 1; /* Rc */ 2087 break; 2088 2089 case 58: /* logical $andcon,[s],a */ 2090 v = regoff(ctxt, &p->from); 2091 r = p->reg; 2092 if(r == NREG) 2093 r = p->to.reg; 2094 o1 = LOP_IRR(opirr(ctxt, p->as), p->to.reg, r, v); 2095 break; 2096 2097 case 59: /* or/and $ucon,,r */ 2098 v = regoff(ctxt, &p->from); 2099 r = p->reg; 2100 if(r == NREG) 2101 r = p->to.reg; 2102 o1 = LOP_IRR(opirr(ctxt, p->as+AEND), p->to.reg, r, v>>16); /* oris, xoris, andis */ 2103 break; 2104 2105 case 60: /* tw to,a,b */ 2106 r = regoff(ctxt, &p->from)&31L; 2107 o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->reg, p->to.reg); 2108 break; 2109 2110 case 61: /* tw to,a,$simm */ 2111 r = regoff(ctxt, &p->from)&31L; 2112 v = regoff(ctxt, &p->to); 2113 o1 = AOP_IRR(opirr(ctxt, p->as), r, p->reg, v); 2114 break; 2115 2116 case 62: /* rlwmi $sh,s,$mask,a */ 2117 v = regoff(ctxt, &p->from); 2118 maskgen(ctxt, p, mask, regoff(ctxt, &p->from3)); 2119 o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, v); 2120 o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1); 2121 break; 2122 2123 case 63: /* rlwmi b,s,$mask,a */ 2124 maskgen(ctxt, p, mask, regoff(ctxt, &p->from3)); 2125 o1 = AOP_RRR(opirr(ctxt, p->as), p->reg, p->to.reg, p->from.reg); 2126 o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1); 2127 break; 2128 2129 case 64: /* mtfsf fr[, $m] {,fpcsr} */ 2130 if(p->from3.type != D_NONE) 2131 v = regoff(ctxt, &p->from3)&255L; 2132 else 2133 v = 255; 2134 o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11); 2135 break; 2136 2137 case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */ 2138 if(p->to.reg == NREG) 2139 ctxt->diag("must specify FPSCR(n)\n%P", p); 2140 o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(ctxt, &p->from)&31L)<<12); 2141 break; 2142 2143 case 66: /* mov spr,r1; mov r1,spr, also dcr */ 2144 if(p->from.type == D_REG) { 2145 r = p->from.reg; 2146 v = p->to.offset; 2147 if(p->to.type == D_DCR) 2148 o1 = OPVCC(31,451,0,0); /* mtdcr */ 2149 else 2150 o1 = OPVCC(31,467,0,0); /* mtspr */ 2151 } else { 2152 r = p->to.reg; 2153 v = p->from.offset; 2154 if(p->from.type == D_DCR) 2155 o1 = OPVCC(31,323,0,0); /* mfdcr */ 2156 else 2157 o1 = OPVCC(31,339,0,0); /* mfspr */ 2158 } 2159 o1 = AOP_RRR(o1, r, 0, 0) | ((v&0x1f)<<16) | (((v>>5)&0x1f)<<11); 2160 break; 2161 2162 case 67: /* mcrf crfD,crfS */ 2163 if(p->from.type != D_CREG || p->from.reg == NREG || 2164 p->to.type != D_CREG || p->to.reg == NREG) 2165 ctxt->diag("illegal CR field number\n%P", p); 2166 o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0); 2167 break; 2168 2169 case 68: /* mfcr rD; mfocrf CRM,rD */ 2170 if(p->from.type == D_CREG && p->from.reg != NREG){ 2171 v = 1<<(7-(p->to.reg&7)); /* CR(n) */ 2172 o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0) | (1<<20) | (v<<12); /* new form, mfocrf */ 2173 }else 2174 o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0); /* old form, whole register */ 2175 break; 2176 2177 case 69: /* mtcrf CRM,rS */ 2178 if(p->from3.type != D_NONE) { 2179 if(p->to.reg != NREG) 2180 ctxt->diag("can't use both mask and CR(n)\n%P", p); 2181 v = regoff(ctxt, &p->from3) & 0xff; 2182 } else { 2183 if(p->to.reg == NREG) 2184 v = 0xff; /* CR */ 2185 else 2186 v = 1<<(7-(p->to.reg&7)); /* CR(n) */ 2187 } 2188 o1 = AOP_RRR(OP_MTCRF, p->from.reg, 0, 0) | (v<<12); 2189 break; 2190 2191 case 70: /* [f]cmp r,r,cr*/ 2192 if(p->reg == NREG) 2193 r = 0; 2194 else 2195 r = (p->reg&7)<<2; 2196 o1 = AOP_RRR(oprrr(ctxt, p->as), r, p->from.reg, p->to.reg); 2197 break; 2198 2199 case 71: /* cmp[l] r,i,cr*/ 2200 if(p->reg == NREG) 2201 r = 0; 2202 else 2203 r = (p->reg&7)<<2; 2204 o1 = AOP_RRR(opirr(ctxt, p->as), r, p->from.reg, 0) | (regoff(ctxt, &p->to)&0xffff); 2205 break; 2206 2207 case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */ 2208 o1 = AOP_RRR(oprrr(ctxt, p->as), p->from.reg, 0, p->to.reg); 2209 break; 2210 2211 case 73: /* mcrfs crfD,crfS */ 2212 if(p->from.type != D_FPSCR || p->from.reg == NREG || 2213 p->to.type != D_CREG || p->to.reg == NREG) 2214 ctxt->diag("illegal FPSCR/CR field number\n%P", p); 2215 o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0); 2216 break; 2217 2218 case 77: /* syscall $scon, syscall Rx */ 2219 if(p->from.type == D_CONST) { 2220 if(p->from.offset > BIG || p->from.offset < -BIG) 2221 ctxt->diag("illegal syscall, sysnum too large: %P", p); 2222 o1 = AOP_IRR(OP_ADDI, REGZERO, REGZERO, p->from.offset); 2223 } else if(p->from.type == D_REG) { 2224 o1 = LOP_RRR(OP_OR, REGZERO, p->from.reg, p->from.reg); 2225 } else { 2226 ctxt->diag("illegal syscall: %P", p); 2227 o1 = 0x7fe00008; // trap always 2228 } 2229 o2 = oprrr(ctxt, p->as); 2230 o3 = AOP_RRR(oprrr(ctxt, AXOR), REGZERO, REGZERO, REGZERO); // XOR R0, R0 2231 break; 2232 2233 case 78: /* undef */ 2234 o1 = 0; /* "An instruction consisting entirely of binary 0s is guaranteed 2235 always to be an illegal instruction." */ 2236 break; 2237 2238 /* relocation operations */ 2239 2240 case 74: 2241 v = regoff(ctxt, &p->to); 2242 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v)); 2243 o2 = AOP_IRR(opstore(ctxt, p->as), p->from.reg, REGTMP, v); 2244 addaddrreloc(ctxt, p->to.sym, &o1, &o2); 2245 //if(dlm) reloc(&p->to, p->pc, 1); 2246 break; 2247 2248 case 75: 2249 v = regoff(ctxt, &p->from); 2250 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v)); 2251 o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v); 2252 addaddrreloc(ctxt, p->from.sym, &o1, &o2); 2253 //if(dlm) reloc(&p->from, p->pc, 1); 2254 break; 2255 2256 case 76: 2257 v = regoff(ctxt, &p->from); 2258 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, high16adjusted(v)); 2259 o2 = AOP_IRR(opload(ctxt, p->as), p->to.reg, REGTMP, v); 2260 addaddrreloc(ctxt, p->from.sym, &o1, &o2); 2261 o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0); 2262 //if(dlm) reloc(&p->from, p->pc, 1); 2263 break; 2264 2265 } 2266 2267 out[0] = o1; 2268 out[1] = o2; 2269 out[2] = o3; 2270 out[3] = o4; 2271 out[4] = o5; 2272 return; 2273 } 2274 2275 static vlong 2276 vregoff(Link *ctxt, Addr *a) 2277 { 2278 2279 ctxt->instoffset = 0; 2280 aclass(ctxt, a); 2281 return ctxt->instoffset; 2282 } 2283 2284 static int32 2285 regoff(Link *ctxt, Addr *a) 2286 { 2287 return vregoff(ctxt, a); 2288 } 2289 2290 static int32 2291 oprrr(Link *ctxt, int a) 2292 { 2293 switch(a) { 2294 case AADD: return OPVCC(31,266,0,0); 2295 case AADDCC: return OPVCC(31,266,0,1); 2296 case AADDV: return OPVCC(31,266,1,0); 2297 case AADDVCC: return OPVCC(31,266,1,1); 2298 case AADDC: return OPVCC(31,10,0,0); 2299 case AADDCCC: return OPVCC(31,10,0,1); 2300 case AADDCV: return OPVCC(31,10,1,0); 2301 case AADDCVCC: return OPVCC(31,10,1,1); 2302 case AADDE: return OPVCC(31,138,0,0); 2303 case AADDECC: return OPVCC(31,138,0,1); 2304 case AADDEV: return OPVCC(31,138,1,0); 2305 case AADDEVCC: return OPVCC(31,138,1,1); 2306 case AADDME: return OPVCC(31,234,0,0); 2307 case AADDMECC: return OPVCC(31,234,0,1); 2308 case AADDMEV: return OPVCC(31,234,1,0); 2309 case AADDMEVCC: return OPVCC(31,234,1,1); 2310 case AADDZE: return OPVCC(31,202,0,0); 2311 case AADDZECC: return OPVCC(31,202,0,1); 2312 case AADDZEV: return OPVCC(31,202,1,0); 2313 case AADDZEVCC: return OPVCC(31,202,1,1); 2314 2315 case AAND: return OPVCC(31,28,0,0); 2316 case AANDCC: return OPVCC(31,28,0,1); 2317 case AANDN: return OPVCC(31,60,0,0); 2318 case AANDNCC: return OPVCC(31,60,0,1); 2319 2320 case ACMP: return OPVCC(31,0,0,0)|(1<<21); /* L=1 */ 2321 case ACMPU: return OPVCC(31,32,0,0)|(1<<21); 2322 case ACMPW: return OPVCC(31,0,0,0); /* L=0 */ 2323 case ACMPWU: return OPVCC(31,32,0,0); 2324 2325 case ACNTLZW: return OPVCC(31,26,0,0); 2326 case ACNTLZWCC: return OPVCC(31,26,0,1); 2327 case ACNTLZD: return OPVCC(31,58,0,0); 2328 case ACNTLZDCC: return OPVCC(31,58,0,1); 2329 2330 case ACRAND: return OPVCC(19,257,0,0); 2331 case ACRANDN: return OPVCC(19,129,0,0); 2332 case ACREQV: return OPVCC(19,289,0,0); 2333 case ACRNAND: return OPVCC(19,225,0,0); 2334 case ACRNOR: return OPVCC(19,33,0,0); 2335 case ACROR: return OPVCC(19,449,0,0); 2336 case ACRORN: return OPVCC(19,417,0,0); 2337 case ACRXOR: return OPVCC(19,193,0,0); 2338 2339 case ADCBF: return OPVCC(31,86,0,0); 2340 case ADCBI: return OPVCC(31,470,0,0); 2341 case ADCBST: return OPVCC(31,54,0,0); 2342 case ADCBT: return OPVCC(31,278,0,0); 2343 case ADCBTST: return OPVCC(31,246,0,0); 2344 case ADCBZ: return OPVCC(31,1014,0,0); 2345 2346 case AREM: 2347 case ADIVW: return OPVCC(31,491,0,0); 2348 case AREMCC: 2349 case ADIVWCC: return OPVCC(31,491,0,1); 2350 case AREMV: 2351 case ADIVWV: return OPVCC(31,491,1,0); 2352 case AREMVCC: 2353 case ADIVWVCC: return OPVCC(31,491,1,1); 2354 case AREMU: 2355 case ADIVWU: return OPVCC(31,459,0,0); 2356 case AREMUCC: 2357 case ADIVWUCC: return OPVCC(31,459,0,1); 2358 case AREMUV: 2359 case ADIVWUV: return OPVCC(31,459,1,0); 2360 case AREMUVCC: 2361 case ADIVWUVCC: return OPVCC(31,459,1,1); 2362 2363 case AREMD: 2364 case ADIVD: return OPVCC(31,489,0,0); 2365 case AREMDCC: 2366 case ADIVDCC: return OPVCC(31,489,0,1); 2367 case AREMDV: 2368 case ADIVDV: return OPVCC(31,489,1,0); 2369 case AREMDVCC: 2370 case ADIVDVCC: return OPVCC(31,489,1,1); 2371 case AREMDU: 2372 case ADIVDU: return OPVCC(31,457,0,0); 2373 case AREMDUCC: 2374 case ADIVDUCC: return OPVCC(31,457,0,1); 2375 case AREMDUV: 2376 case ADIVDUV: return OPVCC(31,457,1,0); 2377 case AREMDUVCC: 2378 case ADIVDUVCC: return OPVCC(31,457,1,1); 2379 2380 case AEIEIO: return OPVCC(31,854,0,0); 2381 2382 case AEQV: return OPVCC(31,284,0,0); 2383 case AEQVCC: return OPVCC(31,284,0,1); 2384 2385 case AEXTSB: return OPVCC(31,954,0,0); 2386 case AEXTSBCC: return OPVCC(31,954,0,1); 2387 case AEXTSH: return OPVCC(31,922,0,0); 2388 case AEXTSHCC: return OPVCC(31,922,0,1); 2389 case AEXTSW: return OPVCC(31,986,0,0); 2390 case AEXTSWCC: return OPVCC(31,986,0,1); 2391 2392 case AFABS: return OPVCC(63,264,0,0); 2393 case AFABSCC: return OPVCC(63,264,0,1); 2394 case AFADD: return OPVCC(63,21,0,0); 2395 case AFADDCC: return OPVCC(63,21,0,1); 2396 case AFADDS: return OPVCC(59,21,0,0); 2397 case AFADDSCC: return OPVCC(59,21,0,1); 2398 case AFCMPO: return OPVCC(63,32,0,0); 2399 case AFCMPU: return OPVCC(63,0,0,0); 2400 case AFCFID: return OPVCC(63,846,0,0); 2401 case AFCFIDCC: return OPVCC(63,846,0,1); 2402 case AFCTIW: return OPVCC(63,14,0,0); 2403 case AFCTIWCC: return OPVCC(63,14,0,1); 2404 case AFCTIWZ: return OPVCC(63,15,0,0); 2405 case AFCTIWZCC: return OPVCC(63,15,0,1); 2406 case AFCTID: return OPVCC(63,814,0,0); 2407 case AFCTIDCC: return OPVCC(63,814,0,1); 2408 case AFCTIDZ: return OPVCC(63,815,0,0); 2409 case AFCTIDZCC: return OPVCC(63,815,0,1); 2410 case AFDIV: return OPVCC(63,18,0,0); 2411 case AFDIVCC: return OPVCC(63,18,0,1); 2412 case AFDIVS: return OPVCC(59,18,0,0); 2413 case AFDIVSCC: return OPVCC(59,18,0,1); 2414 case AFMADD: return OPVCC(63,29,0,0); 2415 case AFMADDCC: return OPVCC(63,29,0,1); 2416 case AFMADDS: return OPVCC(59,29,0,0); 2417 case AFMADDSCC: return OPVCC(59,29,0,1); 2418 case AFMOVS: 2419 case AFMOVD: return OPVCC(63,72,0,0); /* load */ 2420 case AFMOVDCC: return OPVCC(63,72,0,1); 2421 case AFMSUB: return OPVCC(63,28,0,0); 2422 case AFMSUBCC: return OPVCC(63,28,0,1); 2423 case AFMSUBS: return OPVCC(59,28,0,0); 2424 case AFMSUBSCC: return OPVCC(59,28,0,1); 2425 case AFMUL: return OPVCC(63,25,0,0); 2426 case AFMULCC: return OPVCC(63,25,0,1); 2427 case AFMULS: return OPVCC(59,25,0,0); 2428 case AFMULSCC: return OPVCC(59,25,0,1); 2429 case AFNABS: return OPVCC(63,136,0,0); 2430 case AFNABSCC: return OPVCC(63,136,0,1); 2431 case AFNEG: return OPVCC(63,40,0,0); 2432 case AFNEGCC: return OPVCC(63,40,0,1); 2433 case AFNMADD: return OPVCC(63,31,0,0); 2434 case AFNMADDCC: return OPVCC(63,31,0,1); 2435 case AFNMADDS: return OPVCC(59,31,0,0); 2436 case AFNMADDSCC: return OPVCC(59,31,0,1); 2437 case AFNMSUB: return OPVCC(63,30,0,0); 2438 case AFNMSUBCC: return OPVCC(63,30,0,1); 2439 case AFNMSUBS: return OPVCC(59,30,0,0); 2440 case AFNMSUBSCC: return OPVCC(59,30,0,1); 2441 case AFRES: return OPVCC(59,24,0,0); 2442 case AFRESCC: return OPVCC(59,24,0,1); 2443 case AFRSP: return OPVCC(63,12,0,0); 2444 case AFRSPCC: return OPVCC(63,12,0,1); 2445 case AFRSQRTE: return OPVCC(63,26,0,0); 2446 case AFRSQRTECC: return OPVCC(63,26,0,1); 2447 case AFSEL: return OPVCC(63,23,0,0); 2448 case AFSELCC: return OPVCC(63,23,0,1); 2449 case AFSQRT: return OPVCC(63,22,0,0); 2450 case AFSQRTCC: return OPVCC(63,22,0,1); 2451 case AFSQRTS: return OPVCC(59,22,0,0); 2452 case AFSQRTSCC: return OPVCC(59,22,0,1); 2453 case AFSUB: return OPVCC(63,20,0,0); 2454 case AFSUBCC: return OPVCC(63,20,0,1); 2455 case AFSUBS: return OPVCC(59,20,0,0); 2456 case AFSUBSCC: return OPVCC(59,20,0,1); 2457 2458 case AICBI: return OPVCC(31,982,0,0); 2459 case AISYNC: return OPVCC(19,150,0,0); 2460 2461 case AMTFSB0: return OPVCC(63,70,0,0); 2462 case AMTFSB0CC: return OPVCC(63,70,0,1); 2463 case AMTFSB1: return OPVCC(63,38,0,0); 2464 case AMTFSB1CC: return OPVCC(63,38,0,1); 2465 2466 case AMULHW: return OPVCC(31,75,0,0); 2467 case AMULHWCC: return OPVCC(31,75,0,1); 2468 case AMULHWU: return OPVCC(31,11,0,0); 2469 case AMULHWUCC: return OPVCC(31,11,0,1); 2470 case AMULLW: return OPVCC(31,235,0,0); 2471 case AMULLWCC: return OPVCC(31,235,0,1); 2472 case AMULLWV: return OPVCC(31,235,1,0); 2473 case AMULLWVCC: return OPVCC(31,235,1,1); 2474 2475 case AMULHD: return OPVCC(31,73,0,0); 2476 case AMULHDCC: return OPVCC(31,73,0,1); 2477 case AMULHDU: return OPVCC(31,9,0,0); 2478 case AMULHDUCC: return OPVCC(31,9,0,1); 2479 case AMULLD: return OPVCC(31,233,0,0); 2480 case AMULLDCC: return OPVCC(31,233,0,1); 2481 case AMULLDV: return OPVCC(31,233,1,0); 2482 case AMULLDVCC: return OPVCC(31,233,1,1); 2483 2484 case ANAND: return OPVCC(31,476,0,0); 2485 case ANANDCC: return OPVCC(31,476,0,1); 2486 case ANEG: return OPVCC(31,104,0,0); 2487 case ANEGCC: return OPVCC(31,104,0,1); 2488 case ANEGV: return OPVCC(31,104,1,0); 2489 case ANEGVCC: return OPVCC(31,104,1,1); 2490 case ANOR: return OPVCC(31,124,0,0); 2491 case ANORCC: return OPVCC(31,124,0,1); 2492 case AOR: return OPVCC(31,444,0,0); 2493 case AORCC: return OPVCC(31,444,0,1); 2494 case AORN: return OPVCC(31,412,0,0); 2495 case AORNCC: return OPVCC(31,412,0,1); 2496 2497 case ARFI: return OPVCC(19,50,0,0); 2498 case ARFCI: return OPVCC(19,51,0,0); 2499 case ARFID: return OPVCC(19,18,0,0); 2500 case AHRFID: return OPVCC(19,274,0,0); 2501 2502 case ARLWMI: return OPVCC(20,0,0,0); 2503 case ARLWMICC: return OPVCC(20,0,0,1); 2504 case ARLWNM: return OPVCC(23,0,0,0); 2505 case ARLWNMCC: return OPVCC(23,0,0,1); 2506 2507 case ARLDCL: return OPVCC(30,8,0,0); 2508 case ARLDCR: return OPVCC(30,9,0,0); 2509 2510 case ASYSCALL: return OPVCC(17,1,0,0); 2511 2512 case ASLW: return OPVCC(31,24,0,0); 2513 case ASLWCC: return OPVCC(31,24,0,1); 2514 case ASLD: return OPVCC(31,27,0,0); 2515 case ASLDCC: return OPVCC(31,27,0,1); 2516 2517 case ASRAW: return OPVCC(31,792,0,0); 2518 case ASRAWCC: return OPVCC(31,792,0,1); 2519 case ASRAD: return OPVCC(31,794,0,0); 2520 case ASRADCC: return OPVCC(31,794,0,1); 2521 2522 case ASRW: return OPVCC(31,536,0,0); 2523 case ASRWCC: return OPVCC(31,536,0,1); 2524 case ASRD: return OPVCC(31,539,0,0); 2525 case ASRDCC: return OPVCC(31,539,0,1); 2526 2527 case ASUB: return OPVCC(31,40,0,0); 2528 case ASUBCC: return OPVCC(31,40,0,1); 2529 case ASUBV: return OPVCC(31,40,1,0); 2530 case ASUBVCC: return OPVCC(31,40,1,1); 2531 case ASUBC: return OPVCC(31,8,0,0); 2532 case ASUBCCC: return OPVCC(31,8,0,1); 2533 case ASUBCV: return OPVCC(31,8,1,0); 2534 case ASUBCVCC: return OPVCC(31,8,1,1); 2535 case ASUBE: return OPVCC(31,136,0,0); 2536 case ASUBECC: return OPVCC(31,136,0,1); 2537 case ASUBEV: return OPVCC(31,136,1,0); 2538 case ASUBEVCC: return OPVCC(31,136,1,1); 2539 case ASUBME: return OPVCC(31,232,0,0); 2540 case ASUBMECC: return OPVCC(31,232,0,1); 2541 case ASUBMEV: return OPVCC(31,232,1,0); 2542 case ASUBMEVCC: return OPVCC(31,232,1,1); 2543 case ASUBZE: return OPVCC(31,200,0,0); 2544 case ASUBZECC: return OPVCC(31,200,0,1); 2545 case ASUBZEV: return OPVCC(31,200,1,0); 2546 case ASUBZEVCC: return OPVCC(31,200,1,1); 2547 2548 case ASYNC: return OPVCC(31,598,0,0); 2549 case APTESYNC: return OPVCC(31,598,0,0) | (2<<21); 2550 2551 case ATLBIE: return OPVCC(31,306,0,0); 2552 case ATLBIEL: return OPVCC(31,274,0,0); 2553 case ATLBSYNC: return OPVCC(31,566,0,0); 2554 case ASLBIA: return OPVCC(31,498,0,0); 2555 case ASLBIE: return OPVCC(31,434,0,0); 2556 case ASLBMFEE: return OPVCC(31,915,0,0); 2557 case ASLBMFEV: return OPVCC(31,851,0,0); 2558 case ASLBMTE: return OPVCC(31,402,0,0); 2559 2560 case ATW: return OPVCC(31,4,0,0); 2561 case ATD: return OPVCC(31,68,0,0); 2562 2563 case AXOR: return OPVCC(31,316,0,0); 2564 case AXORCC: return OPVCC(31,316,0,1); 2565 } 2566 ctxt->diag("bad r/r opcode %A", a); 2567 return 0; 2568 } 2569 2570 static int32 2571 opirr(Link *ctxt, int a) 2572 { 2573 switch(a) { 2574 case AADD: return OPVCC(14,0,0,0); 2575 case AADDC: return OPVCC(12,0,0,0); 2576 case AADDCCC: return OPVCC(13,0,0,0); 2577 case AADD+AEND: return OPVCC(15,0,0,0); /* ADDIS/CAU */ 2578 2579 case AANDCC: return OPVCC(28,0,0,0); 2580 case AANDCC+AEND: return OPVCC(29,0,0,0); /* ANDIS./ANDIU. */ 2581 2582 case ABR: return OPVCC(18,0,0,0); 2583 case ABL: return OPVCC(18,0,0,0) | 1; 2584 case ADUFFZERO: return OPVCC(18,0,0,0) | 1; 2585 case ADUFFCOPY: return OPVCC(18,0,0,0) | 1; 2586 case ABC: return OPVCC(16,0,0,0); 2587 case ABCL: return OPVCC(16,0,0,0) | 1; 2588 2589 case ABEQ: return AOP_RRR(16<<26,12,2,0); 2590 case ABGE: return AOP_RRR(16<<26,4,0,0); 2591 case ABGT: return AOP_RRR(16<<26,12,1,0); 2592 case ABLE: return AOP_RRR(16<<26,4,1,0); 2593 case ABLT: return AOP_RRR(16<<26,12,0,0); 2594 case ABNE: return AOP_RRR(16<<26,4,2,0); 2595 case ABVC: return AOP_RRR(16<<26,4,3,0); 2596 case ABVS: return AOP_RRR(16<<26,12,3,0); 2597 2598 case ACMP: return OPVCC(11,0,0,0)|(1<<21); /* L=1 */ 2599 case ACMPU: return OPVCC(10,0,0,0)|(1<<21); 2600 case ACMPW: return OPVCC(11,0,0,0); /* L=0 */ 2601 case ACMPWU: return OPVCC(10,0,0,0); 2602 case ALSW: return OPVCC(31,597,0,0); 2603 2604 case AMULLW: return OPVCC(7,0,0,0); 2605 2606 case AOR: return OPVCC(24,0,0,0); 2607 case AOR+AEND: return OPVCC(25,0,0,0); /* ORIS/ORIU */ 2608 2609 case ARLWMI: return OPVCC(20,0,0,0); /* rlwimi */ 2610 case ARLWMICC: return OPVCC(20,0,0,1); 2611 case ARLDMI: return OPVCC(30,0,0,0) | (3<<2); /* rldimi */ 2612 case ARLDMICC: return OPVCC(30,0,0,1) | (3<<2); 2613 2614 case ARLWNM: return OPVCC(21,0,0,0); /* rlwinm */ 2615 case ARLWNMCC: return OPVCC(21,0,0,1); 2616 2617 case ARLDCL: return OPVCC(30,0,0,0); /* rldicl */ 2618 case ARLDCLCC: return OPVCC(30,0,0,1); 2619 case ARLDCR: return OPVCC(30,1,0,0); /* rldicr */ 2620 case ARLDCRCC: return OPVCC(30,1,0,1); 2621 case ARLDC: return OPVCC(30,0,0,0) | (2<<2); 2622 case ARLDCCC: return OPVCC(30,0,0,1) | (2<<2); 2623 2624 case ASRAW: return OPVCC(31,824,0,0); 2625 case ASRAWCC: return OPVCC(31,824,0,1); 2626 case ASRAD: return OPVCC(31,(413<<1),0,0); 2627 case ASRADCC: return OPVCC(31,(413<<1),0,1); 2628 2629 case ASTSW: return OPVCC(31,725,0,0); 2630 2631 case ASUBC: return OPVCC(8,0,0,0); 2632 2633 case ATW: return OPVCC(3,0,0,0); 2634 case ATD: return OPVCC(2,0,0,0); 2635 2636 case AXOR: return OPVCC(26,0,0,0); /* XORIL */ 2637 case AXOR+AEND: return OPVCC(27,0,0,0); /* XORIU */ 2638 } 2639 ctxt->diag("bad opcode i/r %A", a); 2640 return 0; 2641 } 2642 2643 /* 2644 * load o(a),d 2645 */ 2646 static int32 2647 opload(Link *ctxt, int a) 2648 { 2649 switch(a) { 2650 case AMOVD: return OPVCC(58,0,0,0); /* ld */ 2651 case AMOVDU: return OPVCC(58,0,0,1); /* ldu */ 2652 case AMOVWZ: return OPVCC(32,0,0,0); /* lwz */ 2653 case AMOVWZU: return OPVCC(33,0,0,0); /* lwzu */ 2654 case AMOVW: return OPVCC(58,0,0,0)|(1<<1); /* lwa */ 2655 /* no AMOVWU */ 2656 case AMOVB: 2657 case AMOVBZ: return OPVCC(34,0,0,0); /* load */ 2658 case AMOVBU: 2659 case AMOVBZU: return OPVCC(35,0,0,0); 2660 case AFMOVD: return OPVCC(50,0,0,0); 2661 case AFMOVDU: return OPVCC(51,0,0,0); 2662 case AFMOVS: return OPVCC(48,0,0,0); 2663 case AFMOVSU: return OPVCC(49,0,0,0); 2664 case AMOVH: return OPVCC(42,0,0,0); 2665 case AMOVHU: return OPVCC(43,0,0,0); 2666 case AMOVHZ: return OPVCC(40,0,0,0); 2667 case AMOVHZU: return OPVCC(41,0,0,0); 2668 case AMOVMW: return OPVCC(46,0,0,0); /* lmw */ 2669 } 2670 ctxt->diag("bad load opcode %A", a); 2671 return 0; 2672 } 2673 2674 /* 2675 * indexed load a(b),d 2676 */ 2677 static int32 2678 oploadx(Link *ctxt, int a) 2679 { 2680 switch(a) { 2681 case AMOVWZ: return OPVCC(31,23,0,0); /* lwzx */ 2682 case AMOVWZU: return OPVCC(31,55,0,0); /* lwzux */ 2683 case AMOVW: return OPVCC(31,341,0,0); /* lwax */ 2684 case AMOVWU: return OPVCC(31,373,0,0); /* lwaux */ 2685 case AMOVB: 2686 case AMOVBZ: return OPVCC(31,87,0,0); /* lbzx */ 2687 case AMOVBU: 2688 case AMOVBZU: return OPVCC(31,119,0,0); /* lbzux */ 2689 case AFMOVD: return OPVCC(31,599,0,0); /* lfdx */ 2690 case AFMOVDU: return OPVCC(31,631,0,0); /* lfdux */ 2691 case AFMOVS: return OPVCC(31,535,0,0); /* lfsx */ 2692 case AFMOVSU: return OPVCC(31,567,0,0); /* lfsux */ 2693 case AMOVH: return OPVCC(31,343,0,0); /* lhax */ 2694 case AMOVHU: return OPVCC(31,375,0,0); /* lhaux */ 2695 case AMOVHBR: return OPVCC(31,790,0,0); /* lhbrx */ 2696 case AMOVWBR: return OPVCC(31,534,0,0); /* lwbrx */ 2697 case AMOVHZ: return OPVCC(31,279,0,0); /* lhzx */ 2698 case AMOVHZU: return OPVCC(31,311,0,0); /* lhzux */ 2699 case AECIWX: return OPVCC(31,310,0,0); /* eciwx */ 2700 case ALWAR: return OPVCC(31,20,0,0); /* lwarx */ 2701 case ALDAR: return OPVCC(31,84,0,0); 2702 case ALSW: return OPVCC(31,533,0,0); /* lswx */ 2703 case AMOVD: return OPVCC(31,21,0,0); /* ldx */ 2704 case AMOVDU: return OPVCC(31,53,0,0); /* ldux */ 2705 } 2706 ctxt->diag("bad loadx opcode %A", a); 2707 return 0; 2708 } 2709 2710 /* 2711 * store s,o(d) 2712 */ 2713 static int32 2714 opstore(Link *ctxt, int a) 2715 { 2716 switch(a) { 2717 case AMOVB: 2718 case AMOVBZ: return OPVCC(38,0,0,0); /* stb */ 2719 case AMOVBU: 2720 case AMOVBZU: return OPVCC(39,0,0,0); /* stbu */ 2721 case AFMOVD: return OPVCC(54,0,0,0); /* stfd */ 2722 case AFMOVDU: return OPVCC(55,0,0,0); /* stfdu */ 2723 case AFMOVS: return OPVCC(52,0,0,0); /* stfs */ 2724 case AFMOVSU: return OPVCC(53,0,0,0); /* stfsu */ 2725 case AMOVHZ: 2726 case AMOVH: return OPVCC(44,0,0,0); /* sth */ 2727 case AMOVHZU: 2728 case AMOVHU: return OPVCC(45,0,0,0); /* sthu */ 2729 case AMOVMW: return OPVCC(47,0,0,0); /* stmw */ 2730 case ASTSW: return OPVCC(31,725,0,0); /* stswi */ 2731 case AMOVWZ: 2732 case AMOVW: return OPVCC(36,0,0,0); /* stw */ 2733 case AMOVWZU: 2734 case AMOVWU: return OPVCC(37,0,0,0); /* stwu */ 2735 case AMOVD: return OPVCC(62,0,0,0); /* std */ 2736 case AMOVDU: return OPVCC(62,0,0,1); /* stdu */ 2737 } 2738 ctxt->diag("unknown store opcode %A", a); 2739 return 0; 2740 } 2741 2742 /* 2743 * indexed store s,a(b) 2744 */ 2745 static int32 2746 opstorex(Link *ctxt, int a) 2747 { 2748 switch(a) { 2749 case AMOVB: 2750 case AMOVBZ: return OPVCC(31,215,0,0); /* stbx */ 2751 case AMOVBU: 2752 case AMOVBZU: return OPVCC(31,247,0,0); /* stbux */ 2753 case AFMOVD: return OPVCC(31,727,0,0); /* stfdx */ 2754 case AFMOVDU: return OPVCC(31,759,0,0); /* stfdux */ 2755 case AFMOVS: return OPVCC(31,663,0,0); /* stfsx */ 2756 case AFMOVSU: return OPVCC(31,695,0,0); /* stfsux */ 2757 case AMOVHZ: 2758 case AMOVH: return OPVCC(31,407,0,0); /* sthx */ 2759 case AMOVHBR: return OPVCC(31,918,0,0); /* sthbrx */ 2760 case AMOVHZU: 2761 case AMOVHU: return OPVCC(31,439,0,0); /* sthux */ 2762 case AMOVWZ: 2763 case AMOVW: return OPVCC(31,151,0,0); /* stwx */ 2764 case AMOVWZU: 2765 case AMOVWU: return OPVCC(31,183,0,0); /* stwux */ 2766 case ASTSW: return OPVCC(31,661,0,0); /* stswx */ 2767 case AMOVWBR: return OPVCC(31,662,0,0); /* stwbrx */ 2768 case ASTWCCC: return OPVCC(31,150,0,1); /* stwcx. */ 2769 case ASTDCCC: return OPVCC(31,214,0,1); /* stwdx. */ 2770 case AECOWX: return OPVCC(31,438,0,0); /* ecowx */ 2771 case AMOVD: return OPVCC(31,149,0,0); /* stdx */ 2772 case AMOVDU: return OPVCC(31,181,0,0); /* stdux */ 2773 } 2774 ctxt->diag("unknown storex opcode %A", a); 2775 return 0; 2776 } 2777