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