1/* 2 * Copyright (c) 2010-2014 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 47 unchanged lines hidden (view full) --- 56MacroMemOp::MacroMemOp(const char *mnem, ExtMachInst machInst, 57 OpClass __opClass, IntRegIndex rn, 58 bool index, bool up, bool user, bool writeback, 59 bool load, uint32_t reglist) : 60 PredMacroOp(mnem, machInst, __opClass) 61{ 62 uint32_t regs = reglist; 63 uint32_t ones = number_of_ones(reglist); |
64 uint32_t mem_ops = ones; |
65 |
66 // Copy the base address register if we overwrite it, or if this instruction 67 // is basically a no-op (we have to do something) 68 bool copy_base = (bits(reglist, rn) && load) || !ones; 69 bool force_user = user & !bits(reglist, 15); 70 bool exception_ret = user & bits(reglist, 15); 71 bool pc_temp = load && writeback && bits(reglist, 15); 72 73 if (!ones) { |
74 numMicroops = 1; |
75 } else if (load) { 76 numMicroops = ((ones + 1) / 2) 77 + ((ones % 2 == 0 && exception_ret) ? 1 : 0) 78 + (copy_base ? 1 : 0) 79 + (writeback? 1 : 0) 80 + (pc_temp ? 1 : 0); 81 } else { 82 numMicroops = ones + (writeback ? 1 : 0); 83 } |
84 85 microOps = new StaticInstPtr[numMicroops]; |
86 |
87 uint32_t addr = 0; 88 89 if (!up) 90 addr = (ones << 2) - 4; 91 92 if (!index) 93 addr += 4; 94 95 StaticInstPtr *uop = microOps; 96 97 // Add 0 to Rn and stick it in ureg0. 98 // This is equivalent to a move. |
99 if (copy_base) 100 *uop++ = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0); |
101 102 unsigned reg = 0; |
103 while (mem_ops != 0) { 104 // Do load operations in pairs if possible 105 if (load && mem_ops >= 2 && 106 !(mem_ops == 2 && bits(regs,INTREG_PC) && exception_ret)) { 107 // 64-bit memory operation 108 // Find 2 set register bits (clear them after finding) 109 unsigned reg_idx1; 110 unsigned reg_idx2; |
111 |
112 // Find the first register 113 while (!bits(regs, reg)) reg++; 114 replaceBits(regs, reg, 0); 115 reg_idx1 = force_user ? intRegInMode(MODE_USER, reg) : reg; |
116 |
117 // Find the second register 118 while (!bits(regs, reg)) reg++; 119 replaceBits(regs, reg, 0); 120 reg_idx2 = force_user ? intRegInMode(MODE_USER, reg) : reg; |
121 |
122 // Load into temp reg if necessary 123 if (reg_idx2 == INTREG_PC && pc_temp) 124 reg_idx2 = INTREG_UREG1; 125 126 // Actually load both registers from memory 127 *uop = new MicroLdr2Uop(machInst, reg_idx1, reg_idx2, 128 copy_base ? INTREG_UREG0 : rn, up, addr); 129 130 if (!writeback && reg_idx2 == INTREG_PC) { 131 // No writeback if idx==pc, set appropriate flags 132 (*uop)->setFlag(StaticInst::IsControl); 133 (*uop)->setFlag(StaticInst::IsIndirectControl); 134 135 if (!(condCode == COND_AL || condCode == COND_UC)) 136 (*uop)->setFlag(StaticInst::IsCondControl); 137 else 138 (*uop)->setFlag(StaticInst::IsUncondControl); 139 } 140 141 if (up) addr += 8; 142 else addr -= 8; 143 mem_ops -= 2; 144 } else { 145 // 32-bit memory operation 146 // Find register for operation 147 unsigned reg_idx; 148 while(!bits(regs, reg)) reg++; 149 replaceBits(regs, reg, 0); 150 reg_idx = force_user ? intRegInMode(MODE_USER, reg) : reg; 151 152 if (load) { 153 if (writeback && reg_idx == INTREG_PC) { 154 // If this instruction changes the PC and performs a 155 // writeback, ensure the pc load/branch is the last uop. 156 // Load into a temp reg here. 157 *uop = new MicroLdrUop(machInst, INTREG_UREG1, 158 copy_base ? INTREG_UREG0 : rn, up, addr); 159 } else if (reg_idx == INTREG_PC && exception_ret) { 160 // Special handling for exception return 161 *uop = new MicroLdrRetUop(machInst, reg_idx, 162 copy_base ? INTREG_UREG0 : rn, up, addr); 163 } else { 164 // standard single load uop 165 *uop = new MicroLdrUop(machInst, reg_idx, 166 copy_base ? INTREG_UREG0 : rn, up, addr); 167 } 168 169 // Loading pc as last operation? Set appropriate flags. 170 if (!writeback && reg_idx == INTREG_PC) { 171 (*uop)->setFlag(StaticInst::IsControl); 172 (*uop)->setFlag(StaticInst::IsIndirectControl); 173 |
174 if (!(condCode == COND_AL || condCode == COND_UC)) 175 (*uop)->setFlag(StaticInst::IsCondControl); 176 else 177 (*uop)->setFlag(StaticInst::IsUncondControl); |
178 } |
179 } else { 180 *uop = new MicroStrUop(machInst, reg_idx, rn, up, addr); |
181 } |
182 183 if (up) addr += 4; 184 else addr -= 4; 185 --mem_ops; |
186 } 187 |
188 // Load/store micro-op generated, go to next uop 189 ++uop; |
190 } 191 192 if (writeback && ones) { |
193 // Perform writeback uop operation |
194 if (up) |
195 *uop++ = new MicroAddiUop(machInst, rn, rn, ones * 4); |
196 else |
197 *uop++ = new MicroSubiUop(machInst, rn, rn, ones * 4); |
198 |
199 // Write PC after address writeback? 200 if (pc_temp) { 201 if (exception_ret) { 202 *uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1); 203 } else { 204 *uop = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG1); 205 } 206 (*uop)->setFlag(StaticInst::IsControl); 207 (*uop)->setFlag(StaticInst::IsIndirectControl); 208 |
209 if (!(condCode == COND_AL || condCode == COND_UC)) 210 (*uop)->setFlag(StaticInst::IsCondControl); 211 else 212 (*uop)->setFlag(StaticInst::IsUncondControl); |
213 |
214 if (rn == INTREG_SP) 215 (*uop)->setFlag(StaticInst::IsReturn); 216 217 ++uop; |
218 } 219 } 220 |
221 --uop; |
222 (*uop)->setLastMicroop(); 223 224 /* Take the control flags from the last microop for the macroop */ 225 if ((*uop)->isControl()) 226 setFlag(StaticInst::IsControl); 227 if ((*uop)->isCondCtrl()) 228 setFlag(StaticInst::IsCondControl); |
229 if ((*uop)->isUncondCtrl()) 230 setFlag(StaticInst::IsUncondControl); |
231 if ((*uop)->isIndirectCtrl()) 232 setFlag(StaticInst::IsIndirectControl); 233 if ((*uop)->isReturn()) 234 setFlag(StaticInst::IsReturn); 235 |
236 for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) { 237 (*uop)->setDelayedCommit(); |
238 } 239} 240 241PairMemOp::PairMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 242 uint32_t size, bool fp, bool load, bool noAlloc, 243 bool signExt, bool exclusive, bool acrel, 244 int64_t imm, AddrMode mode, 245 IntRegIndex rn, IntRegIndex rt, IntRegIndex rt2) : 246 PredMacroOp(mnem, machInst, __opClass) 247{ |
248 bool post = (mode == AddrMd_PostIndex); |
249 bool writeback = (mode != AddrMd_Offset); |
250 251 if (load) { 252 // Use integer rounding to round up loads of size 4 253 numMicroops = (post ? 0 : 1) + ((size + 4) / 8) + (writeback ? 1 : 0); 254 } else { 255 numMicroops = (post ? 0 : 1) + (size / 4) + (writeback ? 1 : 0); 256 } |
257 microOps = new StaticInstPtr[numMicroops]; 258 259 StaticInstPtr *uop = microOps; 260 |
261 rn = makeSP(rn); 262 |
263 if (!post) { 264 *uop++ = new MicroAddXiSpAlignUop(machInst, INTREG_UREG0, rn, 265 post ? 0 : imm); 266 } |
267 268 if (fp) { 269 if (size == 16) { 270 if (load) { |
271 *uop++ = new MicroLdFp16Uop(machInst, rt, 272 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 273 *uop++ = new MicroLdFp16Uop(machInst, rt2, 274 post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel); |
275 } else { |
276 *uop++ = new MicroStrQBFpXImmUop(machInst, rt, 277 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 278 *uop++ = new MicroStrQTFpXImmUop(machInst, rt, 279 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 280 *uop++ = new MicroStrQBFpXImmUop(machInst, rt2, 281 post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel); 282 *uop++ = new MicroStrQTFpXImmUop(machInst, rt2, 283 post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel); |
284 } 285 } else if (size == 8) { 286 if (load) { |
287 *uop++ = new MicroLdPairFp8Uop(machInst, rt, rt2, 288 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); |
289 } else { |
290 *uop++ = new MicroStrFpXImmUop(machInst, rt, 291 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); 292 *uop++ = new MicroStrFpXImmUop(machInst, rt2, 293 post ? rn : INTREG_UREG0, 8, noAlloc, exclusive, acrel); |
294 } 295 } else if (size == 4) { 296 if (load) { |
297 *uop++ = new MicroLdrDFpXImmUop(machInst, rt, rt2, 298 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); |
299 } else { |
300 *uop++ = new MicroStrDFpXImmUop(machInst, rt, rt2, 301 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); |
302 } 303 } 304 } else { 305 if (size == 8) { 306 if (load) { |
307 *uop++ = new MicroLdPairUop(machInst, rt, rt2, 308 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); |
309 } else { |
310 *uop++ = new MicroStrXImmUop(machInst, rt, post ? rn : INTREG_UREG0, |
311 0, noAlloc, exclusive, acrel); |
312 *uop++ = new MicroStrXImmUop(machInst, rt2, post ? rn : INTREG_UREG0, |
313 size, noAlloc, exclusive, acrel); 314 } 315 } else if (size == 4) { 316 if (load) { 317 if (signExt) { |
318 *uop++ = new MicroLdrDSXImmUop(machInst, rt, rt2, 319 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); |
320 } else { |
321 *uop++ = new MicroLdrDUXImmUop(machInst, rt, rt2, 322 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); |
323 } 324 } else { |
325 *uop++ = new MicroStrDXImmUop(machInst, rt, rt2, 326 post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel); |
327 } 328 } 329 } 330 331 if (writeback) { |
332 *uop++ = new MicroAddXiUop(machInst, rn, post ? rn : INTREG_UREG0, |
333 post ? imm : 0); 334 } 335 |
336 assert(uop == µOps[numMicroops]); 337 (*--uop)->setLastMicroop(); |
338 339 for (StaticInstPtr *curUop = microOps; 340 !(*curUop)->isLastMicroop(); curUop++) { 341 (*curUop)->setDelayedCommit(); 342 } 343} 344 345BigFpMemImmOp::BigFpMemImmOp(const char *mnem, ExtMachInst machInst, 346 OpClass __opClass, bool load, IntRegIndex dest, 347 IntRegIndex base, int64_t imm) : 348 PredMacroOp(mnem, machInst, __opClass) 349{ |
350 numMicroops = load ? 1 : 2; |
351 microOps = new StaticInstPtr[numMicroops]; 352 |
353 StaticInstPtr *uop = microOps; 354 |
355 if (load) { |
356 *uop = new MicroLdFp16Uop(machInst, dest, base, imm); |
357 } else { |
358 *uop = new MicroStrQBFpXImmUop(machInst, dest, base, imm); 359 (*uop)->setDelayedCommit(); 360 *++uop = new MicroStrQTFpXImmUop(machInst, dest, base, imm); |
361 } |
362 (*uop)->setLastMicroop(); |
363} 364 365BigFpMemPostOp::BigFpMemPostOp(const char *mnem, ExtMachInst machInst, 366 OpClass __opClass, bool load, IntRegIndex dest, 367 IntRegIndex base, int64_t imm) : 368 PredMacroOp(mnem, machInst, __opClass) 369{ |
370 numMicroops = load ? 2 : 3; |
371 microOps = new StaticInstPtr[numMicroops]; 372 |
373 StaticInstPtr *uop = microOps; 374 |
375 if (load) { |
376 *uop++ = new MicroLdFp16Uop(machInst, dest, base, 0); |
377 } else { |
378 *uop++= new MicroStrQBFpXImmUop(machInst, dest, base, 0); 379 *uop++ = new MicroStrQTFpXImmUop(machInst, dest, base, 0); |
380 } |
381 *uop = new MicroAddXiUop(machInst, base, base, imm); 382 (*uop)->setLastMicroop(); |
383 |
384 for (StaticInstPtr *curUop = microOps; 385 !(*curUop)->isLastMicroop(); curUop++) { 386 (*curUop)->setDelayedCommit(); 387 } |
388} 389 390BigFpMemPreOp::BigFpMemPreOp(const char *mnem, ExtMachInst machInst, 391 OpClass __opClass, bool load, IntRegIndex dest, 392 IntRegIndex base, int64_t imm) : 393 PredMacroOp(mnem, machInst, __opClass) 394{ |
395 numMicroops = load ? 2 : 3; |
396 microOps = new StaticInstPtr[numMicroops]; 397 |
398 StaticInstPtr *uop = microOps; 399 |
400 if (load) { |
401 *uop++ = new MicroLdFp16Uop(machInst, dest, base, imm); |
402 } else { |
403 *uop++ = new MicroStrQBFpXImmUop(machInst, dest, base, imm); 404 *uop++ = new MicroStrQTFpXImmUop(machInst, dest, base, imm); |
405 } |
406 *uop = new MicroAddXiUop(machInst, base, base, imm); 407 (*uop)->setLastMicroop(); |
408 |
409 for (StaticInstPtr *curUop = microOps; 410 !(*curUop)->isLastMicroop(); curUop++) { 411 (*curUop)->setDelayedCommit(); 412 } |
413} 414 415BigFpMemRegOp::BigFpMemRegOp(const char *mnem, ExtMachInst machInst, 416 OpClass __opClass, bool load, IntRegIndex dest, 417 IntRegIndex base, IntRegIndex offset, 418 ArmExtendType type, int64_t imm) : 419 PredMacroOp(mnem, machInst, __opClass) 420{ |
421 numMicroops = load ? 1 : 2; |
422 microOps = new StaticInstPtr[numMicroops]; 423 |
424 StaticInstPtr *uop = microOps; 425 |
426 if (load) { |
427 *uop = new MicroLdFp16RegUop(machInst, dest, base, 428 offset, type, imm); |
429 } else { |
430 *uop = new MicroStrQBFpXRegUop(machInst, dest, base, 431 offset, type, imm); 432 (*uop)->setDelayedCommit(); 433 *++uop = new MicroStrQTFpXRegUop(machInst, dest, base, 434 offset, type, imm); |
435 } 436 |
437 (*uop)->setLastMicroop(); |
438} 439 440BigFpMemLitOp::BigFpMemLitOp(const char *mnem, ExtMachInst machInst, 441 OpClass __opClass, IntRegIndex dest, 442 int64_t imm) : 443 PredMacroOp(mnem, machInst, __opClass) 444{ |
445 numMicroops = 1; |
446 microOps = new StaticInstPtr[numMicroops]; 447 |
448 microOps[0] = new MicroLdFp16LitUop(machInst, dest, imm); 449 microOps[0]->setLastMicroop(); |
450} 451 452VldMultOp::VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, 453 unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, 454 unsigned inc, uint32_t size, uint32_t align, RegIndex rm) : 455 PredMacroOp(mnem, machInst, __opClass) 456{ 457 assert(regs > 0 && regs <= 4); --- 1129 unchanged lines hidden (view full) --- 1587 ss << ", ["; 1588 printReg(ss, urb); 1589 ss << ", "; 1590 ccprintf(ss, "#%d", imm); 1591 ss << "]"; 1592 return ss.str(); 1593} 1594 |
1595std::string 1596MicroMemPairOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 1597{ 1598 std::stringstream ss; 1599 printMnemonic(ss); 1600 printReg(ss, dest); 1601 ss << ","; 1602 printReg(ss, dest2); 1603 ss << ", ["; 1604 printReg(ss, urb); 1605 ss << ", "; 1606 ccprintf(ss, "#%d", imm); 1607 ss << "]"; 1608 return ss.str(); |
1609} |
1610 1611} |