64,65c64
< // Remember that writeback adds a uop or two and the temp register adds one
< numMicroops = ones + (writeback ? (load ? 2 : 1) : 0) + 1;
---
> uint32_t mem_ops = ones;
67,68c66,73
< // It's technically legal to do a lot of nothing
< if (!ones)
---
> // Copy the base address register if we overwrite it, or if this instruction
> // is basically a no-op (we have to do something)
> bool copy_base = (bits(reglist, rn) && load) || !ones;
> bool force_user = user & !bits(reglist, 15);
> bool exception_ret = user & bits(reglist, 15);
> bool pc_temp = load && writeback && bits(reglist, 15);
>
> if (!ones) {
69a75,83
> } else if (load) {
> numMicroops = ((ones + 1) / 2)
> + ((ones % 2 == 0 && exception_ret) ? 1 : 0)
> + (copy_base ? 1 : 0)
> + (writeback? 1 : 0)
> + (pc_temp ? 1 : 0);
> } else {
> numMicroops = ones + (writeback ? 1 : 0);
> }
71a86
>
84c99,100
< *uop = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0);
---
> if (copy_base)
> *uop++ = new MicroAddiUop(machInst, INTREG_UREG0, rn, 0);
87,89c103,110
< unsigned regIdx = 0;
< bool force_user = user & !bits(reglist, 15);
< bool exception_ret = user & bits(reglist, 15);
---
> while (mem_ops != 0) {
> // Do load operations in pairs if possible
> if (load && mem_ops >= 2 &&
> !(mem_ops == 2 && bits(regs,INTREG_PC) && exception_ret)) {
> // 64-bit memory operation
> // Find 2 set register bits (clear them after finding)
> unsigned reg_idx1;
> unsigned reg_idx2;
91,95c112,115
< for (int i = 0; i < ones; i++) {
< // Find the next register.
< while (!bits(regs, reg))
< reg++;
< replaceBits(regs, reg, 0);
---
> // Find the first register
> while (!bits(regs, reg)) reg++;
> replaceBits(regs, reg, 0);
> reg_idx1 = force_user ? intRegInMode(MODE_USER, reg) : reg;
97,100c117,120
< regIdx = reg;
< if (force_user) {
< regIdx = intRegInMode(MODE_USER, regIdx);
< }
---
> // Find the second register
> while (!bits(regs, reg)) reg++;
> replaceBits(regs, reg, 0);
> reg_idx2 = force_user ? intRegInMode(MODE_USER, reg) : reg;
102,114c122,173
< if (load) {
< if (writeback && i == ones - 1) {
< // If it's a writeback and this is the last register
< // do the load into a temporary register which we'll move
< // into the final one later
< *++uop = new MicroLdrUop(machInst, INTREG_UREG1, INTREG_UREG0,
< up, addr);
< } else {
< // Otherwise just do it normally
< if (reg == INTREG_PC && exception_ret) {
< // This must be the exception return form of ldm.
< *++uop = new MicroLdrRetUop(machInst, regIdx,
< INTREG_UREG0, up, addr);
---
> // Load into temp reg if necessary
> if (reg_idx2 == INTREG_PC && pc_temp)
> reg_idx2 = INTREG_UREG1;
>
> // Actually load both registers from memory
> *uop = new MicroLdr2Uop(machInst, reg_idx1, reg_idx2,
> copy_base ? INTREG_UREG0 : rn, up, addr);
>
> if (!writeback && reg_idx2 == INTREG_PC) {
> // No writeback if idx==pc, set appropriate flags
> (*uop)->setFlag(StaticInst::IsControl);
> (*uop)->setFlag(StaticInst::IsIndirectControl);
>
> if (!(condCode == COND_AL || condCode == COND_UC))
> (*uop)->setFlag(StaticInst::IsCondControl);
> else
> (*uop)->setFlag(StaticInst::IsUncondControl);
> }
>
> if (up) addr += 8;
> else addr -= 8;
> mem_ops -= 2;
> } else {
> // 32-bit memory operation
> // Find register for operation
> unsigned reg_idx;
> while(!bits(regs, reg)) reg++;
> replaceBits(regs, reg, 0);
> reg_idx = force_user ? intRegInMode(MODE_USER, reg) : reg;
>
> if (load) {
> if (writeback && reg_idx == INTREG_PC) {
> // If this instruction changes the PC and performs a
> // writeback, ensure the pc load/branch is the last uop.
> // Load into a temp reg here.
> *uop = new MicroLdrUop(machInst, INTREG_UREG1,
> copy_base ? INTREG_UREG0 : rn, up, addr);
> } else if (reg_idx == INTREG_PC && exception_ret) {
> // Special handling for exception return
> *uop = new MicroLdrRetUop(machInst, reg_idx,
> copy_base ? INTREG_UREG0 : rn, up, addr);
> } else {
> // standard single load uop
> *uop = new MicroLdrUop(machInst, reg_idx,
> copy_base ? INTREG_UREG0 : rn, up, addr);
> }
>
> // Loading pc as last operation? Set appropriate flags.
> if (!writeback && reg_idx == INTREG_PC) {
> (*uop)->setFlag(StaticInst::IsControl);
> (*uop)->setFlag(StaticInst::IsIndirectControl);
>
119,129d177
< } else {
< *++uop = new MicroLdrUop(machInst, regIdx,
< INTREG_UREG0, up, addr);
< if (reg == INTREG_PC) {
< (*uop)->setFlag(StaticInst::IsControl);
< if (!(condCode == COND_AL || condCode == COND_UC))
< (*uop)->setFlag(StaticInst::IsCondControl);
< else
< (*uop)->setFlag(StaticInst::IsUncondControl);
< (*uop)->setFlag(StaticInst::IsIndirectControl);
< }
130a179,180
> } else {
> *uop = new MicroStrUop(machInst, reg_idx, rn, up, addr);
132,133c182,185
< } else {
< *++uop = new MicroStrUop(machInst, regIdx, INTREG_UREG0, up, addr);
---
>
> if (up) addr += 4;
> else addr -= 4;
> --mem_ops;
136,139c188,189
< if (up)
< addr += 4;
< else
< addr -= 4;
---
> // Load/store micro-op generated, go to next uop
> ++uop;
143c193
< // put the register update after we're done all loading
---
> // Perform writeback uop operation
145c195
< *++uop = new MicroAddiUop(machInst, rn, rn, ones * 4);
---
> *uop++ = new MicroAddiUop(machInst, rn, rn, ones * 4);
147c197
< *++uop = new MicroSubiUop(machInst, rn, rn, ones * 4);
---
> *uop++ = new MicroSubiUop(machInst, rn, rn, ones * 4);
149,153c199,208
< // If this was a load move the last temporary value into place
< // this way we can't take an exception after we update the base
< // register.
< if (load && reg == INTREG_PC && exception_ret) {
< *++uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1);
---
> // Write PC after address writeback?
> if (pc_temp) {
> if (exception_ret) {
> *uop = new MicroUopRegMovRet(machInst, 0, INTREG_UREG1);
> } else {
> *uop = new MicroUopRegMov(machInst, INTREG_PC, INTREG_UREG1);
> }
> (*uop)->setFlag(StaticInst::IsControl);
> (*uop)->setFlag(StaticInst::IsIndirectControl);
>
158,166d212
< } else if (load) {
< *++uop = new MicroUopRegMov(machInst, regIdx, INTREG_UREG1);
< if (reg == INTREG_PC) {
< (*uop)->setFlag(StaticInst::IsControl);
< (*uop)->setFlag(StaticInst::IsCondControl);
< (*uop)->setFlag(StaticInst::IsIndirectControl);
< // This is created as a RAS POP
< if (rn == INTREG_SP)
< (*uop)->setFlag(StaticInst::IsReturn);
168c214,217
< }
---
> if (rn == INTREG_SP)
> (*uop)->setFlag(StaticInst::IsReturn);
>
> ++uop;
171a221
> --uop;
178a229,230
> if ((*uop)->isUncondCtrl())
> setFlag(StaticInst::IsUncondControl);
184,188c236,237
< for (StaticInstPtr *curUop = microOps;
< !(*curUop)->isLastMicroop(); curUop++) {
< MicroOp * uopPtr = dynamic_cast<MicroOp *>(curUop->get());
< assert(uopPtr);
< uopPtr->setDelayedCommit();
---
> for (StaticInstPtr *uop = microOps; !(*uop)->isLastMicroop(); uop++) {
> (*uop)->setDelayedCommit();
198a248
> bool post = (mode == AddrMd_PostIndex);
200c250,256
< numMicroops = 1 + (size / 4) + (writeback ? 1 : 0);
---
>
> if (load) {
> // Use integer rounding to round up loads of size 4
> numMicroops = (post ? 0 : 1) + ((size + 4) / 8) + (writeback ? 1 : 0);
> } else {
> numMicroops = (post ? 0 : 1) + (size / 4) + (writeback ? 1 : 0);
> }
205,206d260
< bool post = (mode == AddrMd_PostIndex);
<
209c263,266
< *uop = new MicroAddXiSpAlignUop(machInst, INTREG_UREG0, rn, post ? 0 : imm);
---
> if (!post) {
> *uop++ = new MicroAddXiSpAlignUop(machInst, INTREG_UREG0, rn,
> post ? 0 : imm);
> }
214,221c271,274
< *++uop = new MicroLdrQBFpXImmUop(machInst, rt,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
< *++uop = new MicroLdrQTFpXImmUop(machInst, rt,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
< *++uop = new MicroLdrQBFpXImmUop(machInst, rt2,
< INTREG_UREG0, 16, noAlloc, exclusive, acrel);
< *++uop = new MicroLdrQTFpXImmUop(machInst, rt2,
< INTREG_UREG0, 16, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroLdFp16Uop(machInst, rt,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
> *uop++ = new MicroLdFp16Uop(machInst, rt2,
> post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel);
223,230c276,283
< *++uop = new MicroStrQBFpXImmUop(machInst, rt,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
< *++uop = new MicroStrQTFpXImmUop(machInst, rt,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
< *++uop = new MicroStrQBFpXImmUop(machInst, rt2,
< INTREG_UREG0, 16, noAlloc, exclusive, acrel);
< *++uop = new MicroStrQTFpXImmUop(machInst, rt2,
< INTREG_UREG0, 16, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroStrQBFpXImmUop(machInst, rt,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
> *uop++ = new MicroStrQTFpXImmUop(machInst, rt,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
> *uop++ = new MicroStrQBFpXImmUop(machInst, rt2,
> post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel);
> *uop++ = new MicroStrQTFpXImmUop(machInst, rt2,
> post ? rn : INTREG_UREG0, 16, noAlloc, exclusive, acrel);
234,237c287,288
< *++uop = new MicroLdrFpXImmUop(machInst, rt,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
< *++uop = new MicroLdrFpXImmUop(machInst, rt2,
< INTREG_UREG0, 8, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroLdPairFp8Uop(machInst, rt, rt2,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
239,242c290,293
< *++uop = new MicroStrFpXImmUop(machInst, rt,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
< *++uop = new MicroStrFpXImmUop(machInst, rt2,
< INTREG_UREG0, 8, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroStrFpXImmUop(machInst, rt,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
> *uop++ = new MicroStrFpXImmUop(machInst, rt2,
> post ? rn : INTREG_UREG0, 8, noAlloc, exclusive, acrel);
246,247c297,298
< *++uop = new MicroLdrDFpXImmUop(machInst, rt, rt2,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroLdrDFpXImmUop(machInst, rt, rt2,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
249,250c300,301
< *++uop = new MicroStrDFpXImmUop(machInst, rt, rt2,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroStrDFpXImmUop(machInst, rt, rt2,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
256,259c307,308
< *++uop = new MicroLdrXImmUop(machInst, rt, INTREG_UREG0,
< 0, noAlloc, exclusive, acrel);
< *++uop = new MicroLdrXImmUop(machInst, rt2, INTREG_UREG0,
< size, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroLdPairUop(machInst, rt, rt2,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
261c310
< *++uop = new MicroStrXImmUop(machInst, rt, INTREG_UREG0,
---
> *uop++ = new MicroStrXImmUop(machInst, rt, post ? rn : INTREG_UREG0,
263c312
< *++uop = new MicroStrXImmUop(machInst, rt2, INTREG_UREG0,
---
> *uop++ = new MicroStrXImmUop(machInst, rt2, post ? rn : INTREG_UREG0,
269,270c318,319
< *++uop = new MicroLdrDSXImmUop(machInst, rt, rt2,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroLdrDSXImmUop(machInst, rt, rt2,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
272,273c321,322
< *++uop = new MicroLdrDUXImmUop(machInst, rt, rt2,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroLdrDUXImmUop(machInst, rt, rt2,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
276,277c325,326
< *++uop = new MicroStrDXImmUop(machInst, rt, rt2,
< INTREG_UREG0, 0, noAlloc, exclusive, acrel);
---
> *uop++ = new MicroStrDXImmUop(machInst, rt, rt2,
> post ? rn : INTREG_UREG0, 0, noAlloc, exclusive, acrel);
283c332
< *++uop = new MicroAddXiUop(machInst, rn, INTREG_UREG0,
---
> *uop++ = new MicroAddXiUop(machInst, rn, post ? rn : INTREG_UREG0,
287c336,337
< (*uop)->setLastMicroop();
---
> assert(uop == &microOps[numMicroops]);
> (*--uop)->setLastMicroop();
300c350
< numMicroops = 2;
---
> numMicroops = load ? 1 : 2;
302a353,354
> StaticInstPtr *uop = microOps;
>
304,305c356
< microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
< microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
---
> *uop = new MicroLdFp16Uop(machInst, dest, base, imm);
307,308c358,360
< microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
< microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
---
> *uop = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
> (*uop)->setDelayedCommit();
> *++uop = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
310,311c362
< microOps[0]->setDelayedCommit();
< microOps[1]->setLastMicroop();
---
> (*uop)->setLastMicroop();
319c370
< numMicroops = 3;
---
> numMicroops = load ? 2 : 3;
321a373,374
> StaticInstPtr *uop = microOps;
>
323,324c376
< microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, 0);
< microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, 0);
---
> *uop++ = new MicroLdFp16Uop(machInst, dest, base, 0);
326,327c378,379
< microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, 0);
< microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, 0);
---
> *uop++= new MicroStrQBFpXImmUop(machInst, dest, base, 0);
> *uop++ = new MicroStrQTFpXImmUop(machInst, dest, base, 0);
329c381,382
< microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
---
> *uop = new MicroAddXiUop(machInst, base, base, imm);
> (*uop)->setLastMicroop();
331,333c384,387
< microOps[0]->setDelayedCommit();
< microOps[1]->setDelayedCommit();
< microOps[2]->setLastMicroop();
---
> for (StaticInstPtr *curUop = microOps;
> !(*curUop)->isLastMicroop(); curUop++) {
> (*curUop)->setDelayedCommit();
> }
341c395
< numMicroops = 3;
---
> numMicroops = load ? 2 : 3;
343a398,399
> StaticInstPtr *uop = microOps;
>
345,346c401
< microOps[0] = new MicroLdrQBFpXImmUop(machInst, dest, base, imm);
< microOps[1] = new MicroLdrQTFpXImmUop(machInst, dest, base, imm);
---
> *uop++ = new MicroLdFp16Uop(machInst, dest, base, imm);
348,349c403,404
< microOps[0] = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
< microOps[1] = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
---
> *uop++ = new MicroStrQBFpXImmUop(machInst, dest, base, imm);
> *uop++ = new MicroStrQTFpXImmUop(machInst, dest, base, imm);
351c406,407
< microOps[2] = new MicroAddXiUop(machInst, base, base, imm);
---
> *uop = new MicroAddXiUop(machInst, base, base, imm);
> (*uop)->setLastMicroop();
353,355c409,412
< microOps[0]->setDelayedCommit();
< microOps[1]->setDelayedCommit();
< microOps[2]->setLastMicroop();
---
> for (StaticInstPtr *curUop = microOps;
> !(*curUop)->isLastMicroop(); curUop++) {
> (*curUop)->setDelayedCommit();
> }
364c421
< numMicroops = 2;
---
> numMicroops = load ? 1 : 2;
366a424,425
> StaticInstPtr *uop = microOps;
>
368,371c427,428
< microOps[0] = new MicroLdrQBFpXRegUop(machInst, dest, base,
< offset, type, imm);
< microOps[1] = new MicroLdrQTFpXRegUop(machInst, dest, base,
< offset, type, imm);
---
> *uop = new MicroLdFp16RegUop(machInst, dest, base,
> offset, type, imm);
373,376c430,434
< microOps[0] = new MicroStrQBFpXRegUop(machInst, dest, base,
< offset, type, imm);
< microOps[1] = new MicroStrQTFpXRegUop(machInst, dest, base,
< offset, type, imm);
---
> *uop = new MicroStrQBFpXRegUop(machInst, dest, base,
> offset, type, imm);
> (*uop)->setDelayedCommit();
> *++uop = new MicroStrQTFpXRegUop(machInst, dest, base,
> offset, type, imm);
379,380c437
< microOps[0]->setDelayedCommit();
< microOps[1]->setLastMicroop();
---
> (*uop)->setLastMicroop();
388c445
< numMicroops = 2;
---
> numMicroops = 1;
391,395c448,449
< microOps[0] = new MicroLdrQBFpXLitUop(machInst, dest, imm);
< microOps[1] = new MicroLdrQTFpXLitUop(machInst, dest, imm);
<
< microOps[0]->setDelayedCommit();
< microOps[1]->setLastMicroop();
---
> microOps[0] = new MicroLdFp16LitUop(machInst, dest, imm);
> microOps[0]->setLastMicroop();
1540a1595,1608
> std::string
> MicroMemPairOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const
> {
> std::stringstream ss;
> printMnemonic(ss);
> printReg(ss, dest);
> ss << ",";
> printReg(ss, dest2);
> ss << ", [";
> printReg(ss, urb);
> ss << ", ";
> ccprintf(ss, "#%d", imm);
> ss << "]";
> return ss.str();
1541a1610,1611
>
> }