[TestCase(X64Register.R14)] // Never allocated in this method without a requirement public void Register_requirement_is_respected(X64Register required) { var method = new LowMethod <X64Register>(); method.Locals.Add(new LowLocal <X64Register>(SimpleType.Bool)); method.Locals.Add(new LowLocal <X64Register>(SimpleType.Bool, required)); method.Blocks.Add(new LowBlock { Instructions = { new LowInstruction(LowOp.LoadInt, 0, 0, 0, 1), // Load 1 -> #0 new LowInstruction(LowOp.Move, 1, 0, 0, 0), // Move #0 -> #1 new LowInstruction(LowOp.Compare, 0, 1, 0, 0), // Compare #1, #0 new LowInstruction(LowOp.Return, 0, 0, 0, 0) // Return #0 }, Predecessors = Array.Empty <int>(), Successors = Array.Empty <int>() }); var(rewritten, allocationMap) = X64RegisterAllocator.Allocate(method); AssertDump(rewritten, @" LB_0: LoadInt 0 0 1 -> 0 Move 0 0 0 -> 1 Compare 1 0 0 -> 0 Return 0 0 0 -> 0"); Assert.That(allocationMap.Get(0).localIndex, Is.EqualTo(0)); Assert.That(allocationMap.Get(1).localIndex, Is.EqualTo(1)); Assert.That(allocationMap.Get(0).location.IsSet, Is.True); Assert.That(allocationMap.Get(1).location.IsSet, Is.True); Assert.That(allocationMap.Get(1).location.Register, Is.EqualTo(required)); }
/// <summary> /// Emits a full-width pop instruction with the specified destination register. /// </summary> public void EmitPop(X64Register dest) { if (dest >= X64Register.Xmm0) { throw new InvalidOperationException("Pop on XMM register"); } _disassemblyWriter?.WriteLine($"{Indent}pop {GetRegisterName(dest, 8)}"); var(encodedReg, needB) = GetRegisterEncoding(dest); // The opcode is encoded exactly as push, except for the 0x8 bit if (needB) { _outputStream.WriteByte(0x41); } _outputStream.WriteByte((byte)(0x58 | encodedReg)); }
/// <summary> /// Emits a full-width push instruction with the specified source register. /// </summary> public void EmitPush(X64Register src) { if (src >= X64Register.Xmm0) { throw new InvalidOperationException("Push on XMM register"); } _disassemblyWriter?.WriteLine($"{Indent}push {GetRegisterName(src, 8)}"); var(encodedReg, needB) = GetRegisterEncoding(src); if (needB) { // New registers need a REX.B prefix _outputStream.WriteByte(0x41); } _outputStream.WriteByte((byte)(0x50 | encodedReg)); }