Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arm64 Support #2

Merged
merged 21 commits into from
Aug 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a8d26b2
CoreRT-ARM64: Helper node asm code generation
RalfKornmannEnvision Jul 20, 2020
6c4b87b
CoreRT ARM64: Add additional relocation support
RalfKornmannEnvision Jul 21, 2020
404f4ed
CoreRT ARM64: Use alternative functions for write Barriers
RalfKornmannEnvision Jul 21, 2020
9d4c4cb
ARM64 code generation
RalfKornmannEnvision Aug 3, 2020
20021cb
unwind use only the dwarf index option
RalfKornmannEnvision Aug 3, 2020
39c6ceb
ARM64 runtime assembler functions
RalfKornmannEnvision Aug 3, 2020
6c9e235
ARM64 unix stack walk
RalfKornmannEnvision Aug 4, 2020
aba22ac
ARM64 Exception Handling
RalfKornmannEnvision Aug 4, 2020
5b6bea5
ARM64: Fix EH data decodeing
RalfKornmannEnvision Aug 6, 2020
86a4b8b
Move nattive layout signature from read only to data section on non W…
RalfKornmannEnvision Aug 14, 2020
f98ba02
Fix exception handling macro call
RalfKornmannEnvision Aug 14, 2020
f289d85
ARM64 thunk helpers
RalfKornmannEnvision Aug 14, 2020
986f61a
ARM64 process cfi data for elf
RalfKornmannEnvision Aug 17, 2020
b1481d6
ARM64 missing assembler macro
RalfKornmannEnvision Aug 17, 2020
5f3bb34
ARM64 port more assembler helpers
RalfKornmannEnvision Aug 17, 2020
2fe1f65
ARM64: Add missing case for the gemeric helper node
RalfKornmannEnvision Aug 17, 2020
11817b2
ARM64 intrinsic support
RalfKornmannEnvision Aug 18, 2020
08e0d52
ARM64 object writer for ELF object files
RalfKornmannEnvision Aug 18, 2020
083ee8c
ARM64 llvm patches for object writer
RalfKornmannEnvision Aug 18, 2020
b8d0123
ARM64 include untested helper code with debug break
RalfKornmannEnvision Aug 18, 2020
e70d94e
ARM64 reenable scanning fail exception
RalfKornmannEnvision Aug 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,16 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)

public int Offset => 0;
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
public override ObjectNodeSection Section => ObjectNodeSection.ReadOnlyDataSection;
public override ObjectNodeSection Section
{
get
{
if (_identity.Context.Target.IsWindows)
return ObjectNodeSection.ReadOnlyDataSection;
else
return ObjectNodeSection.DataSection;
}
}
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0)
case RelocType.IMAGE_REL_BASED_THUMB_MOV32:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
// Do not vacate space for this kind of relocation, because
// the space is embedded in the instruction.
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,8 @@ public void EmitSymbolDefinition(int currentOffset)
{
foreach (var name in nodes)
{


_sb.Clear();
AppendExternCPrefix(_sb);
name.AppendMangledName(_nodeFactory.NameMangler, _sb);
Expand Down Expand Up @@ -1043,7 +1045,7 @@ public static void EmitObject(string objectFilePath, IEnumerable<DependencyNode>
// The DWARF CFI unwind is implemented for AMD64 & ARM32 only.
TargetArchitecture tarch = factory.Target.Architecture;
if (!factory.Target.IsWindows &&
(tarch == TargetArchitecture.X64 || tarch == TargetArchitecture.ARM))
(tarch == TargetArchitecture.X64 || tarch == TargetArchitecture.ARM || tarch == TargetArchitecture.ARM64))
objectWriter.BuildCFIMap(factory, node);

// Build debug location map
Expand Down Expand Up @@ -1089,17 +1091,24 @@ public static void EmitObject(string objectFilePath, IEnumerable<DependencyNode>
}
int size = objectWriter.EmitSymbolReference(reloc.Target, (int)delta, reloc.RelocType);

// Emit a copy of original Thumb2 instruction that came from RyuJIT
if (reloc.RelocType == RelocType.IMAGE_REL_BASED_THUMB_MOV32 ||
reloc.RelocType == RelocType.IMAGE_REL_BASED_THUMB_BRANCH24)
// Emit a copy of original Thumb2/ARM64 instruction that came from RyuJIT

switch (reloc.RelocType)
{
unsafe
{
fixed (void* location = &nodeContents.Data[i])
case RelocType.IMAGE_REL_BASED_THUMB_MOV32:
case RelocType.IMAGE_REL_BASED_THUMB_BRANCH24:
case RelocType.IMAGE_REL_BASED_ARM64_BRANCH26:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L:
unsafe
{
objectWriter.EmitBytes((IntPtr)location, size);
fixed (void* location = &nodeContents.Data[i])
{
objectWriter.EmitBytes((IntPtr)location, size);
}
}
}
break;
}

// Update nextRelocIndex/Offset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,45 @@ private static unsafe void PutArm64Rel12(uint* pCode, int imm12)
Debug.Assert(GetArm64Rel12(pCode) == imm12);
}

private static unsafe int GetArm64Rel28(uint* pCode)
{
uint branchInstr = *pCode;

// first shift 6 bits left to set the sign bit,
// then arithmetic shift right by 4 bits
int imm28 = (((int)(branchInstr & 0x03FFFFFF)) << 6) >> 4;

return imm28;
}

private static bool FitsInArm64Rel28(long imm28)
{
return (imm28 >= -0x08000000L) && (imm28 < 0x08000000L);
}

private static unsafe void PutArm64Rel28(uint* pCode, long imm28)
{
// Verify that we got a valid offset
Debug.Assert(FitsInArm64Rel28(imm28));

Debug.Assert((imm28 & 0x3) == 0); // the low two bits must be zero

uint branchInstr = *pCode;

branchInstr &= 0xFC000000; // keep bits 31-26

Debug.Assert((branchInstr & 0x7FFFFFFF) == 0x14000000); // Must be B or BL

// Assemble the pc-relative delta 'imm28' into the branch instruction
branchInstr |= (uint)(((imm28 >> 2) & 0x03FFFFFFU));

*pCode = branchInstr; // write the assembled instruction

Debug.Assert(GetArm64Rel28(pCode) == imm28);
}



public Relocation(RelocType relocType, int offset, ISymbolNode target)
{
RelocType = relocType;
Expand Down Expand Up @@ -286,6 +325,9 @@ public static unsafe void WriteValue(RelocType relocType, void* location, long v
case RelocType.IMAGE_REL_BASED_THUMB_BRANCH24:
PutThumb2BlRel24((ushort*)location, (uint)value);
break;
case RelocType.IMAGE_REL_BASED_ARM64_BRANCH26:
PutArm64Rel28((uint*)location, value);
break;
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
PutArm64Rel21((uint*)location, (int)value);
break;
Expand Down Expand Up @@ -318,6 +360,8 @@ public static unsafe long ReadValue(RelocType relocType, void* location)
return (long)GetThumb2Mov32((ushort*)location);
case RelocType.IMAGE_REL_BASED_THUMB_BRANCH24:
return (long)GetThumb2BlRel24((ushort*)location);
case RelocType.IMAGE_REL_BASED_ARM64_BRANCH26:
return (long)GetArm64Rel28((uint*)location);
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
return GetArm64Rel21((uint*)location);
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void EmitMOV(Register regDst, ref AddrMode memory)

public void EmitMOV(Register regDst, Register regSrc)
{
throw new NotImplementedException();
Builder.EmitUInt((uint)(0b1_0_1_01010_000_00000_000000_11111_00000u | ((uint)regSrc << 16) | (uint)regDst));
}

public void EmitMOV(Register regDst, ushort imm16)
Expand All @@ -35,6 +35,17 @@ public void EmitMOV(Register regDst, ushort imm16)
Builder.EmitUInt(instruction);
}

public void EmitMOV(Register regDst, ISymbolNode symbol)
{
// ADRP regDst, [symbol (21bit ADRP thing)]
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21);
Builder.EmitUInt(0x90000000u | (byte)regDst);

// Add regDst, (12bit LDR page offset reloc)
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A);
Builder.EmitUInt((uint)(0b1_0_0_100010_0_000000000000_00000_00000 | ((byte)regDst << 5) | (byte)regDst));
}

// ldr regDst, [PC + imm19]
public void EmitLDR(Register regDst, short offset)
{
Expand All @@ -54,6 +65,25 @@ public void EmitLDR(Register regDst, Register regAddr)
Builder.EmitUInt(instruction);
}

public void EmitLDR(Register regDst, Register regSrc, int offset)
{
Debug.Assert(offset >= -255 && offset <= 4095);
if (offset >= 0)
{
Debug.Assert(offset % 8 == 0);

offset /= 8;

Builder.EmitUInt((uint)(0b11_1110_0_1_0_1_000000000000_00000_00000u | ((uint)offset << 10) | ((uint)regSrc << 5) | (uint)regDst));
}
else
{
uint o = (uint)offset & 0x1FF;

Builder.EmitUInt((uint)(0b11_1110_0_0_010_000000000_1_1_00000_00000u | (o << 12) | ((uint)regSrc << 5) | (uint)regDst));
}
}

public void EmitLEAQ(Register reg, ISymbolNode symbol, int delta = 0)
{
throw new NotImplementedException();
Expand All @@ -69,12 +99,38 @@ public void EmitCMP(ref AddrMode addrMode, sbyte immediate)
throw new NotImplementedException();
}

public void EmitCMP(Register reg, sbyte immediate)
{
if (immediate >= 0)
{
Builder.EmitUInt((uint)(0b1_1_1_100010_0_000000000000_00000_11111u | immediate << 10) | ((uint)reg << 5));
}
else
{
throw new NotImplementedException();
}
}

// add reg, immediate
public void EmitADD(Register reg, byte immediate)
{
Builder.EmitInt((int)(0x91 << 24) | (immediate << 10) | ((byte)reg << 5) | (byte) reg);
}

public void EmitSUB(Register reg, int immediate)
{
if (immediate >= 0)
{
Debug.Assert(immediate % 4 == 0);

Builder.EmitUInt((uint)(0b1_1_0_100010_0_000000000000_00000_00000u | immediate << 10) | ((uint)reg << 5) | (uint)reg);
}
else
{
throw new NotImplementedException();
}
}

public void EmitJMP(ISymbolNode symbol)
{
if (symbol.RepresentsIndirectionCell)
Expand All @@ -100,24 +156,40 @@ public void EmitJMP(ISymbolNode symbol)
}
}

public void EmitJMP(Register reg)
{
Builder.EmitUInt((uint)(0b11010110_0_0_0_11111_00000_0_00000_00000u | ((uint)reg << 5)));
}

public void EmitINT3()
{
throw new NotImplementedException();
Builder.EmitUInt(0b11010100_001_1111111111111111_000_0_0);
}

public void EmitINT3(uint id)
{
Builder.EmitUInt(0b11010100_001_1111111111111111_000_0_0);
Builder.EmitUInt((uint)(0b0_00101_00000000000000000000000000u | ((uint)4)));
Builder.EmitUInt(0xdeadc0de);
Builder.EmitUInt(id);
Builder.EmitUInt(0xdeadc0de);
}


public void EmitJmpToAddrMode(ref AddrMode addrMode)
{
throw new NotImplementedException();
}

public void EmitRET()
{
throw new NotImplementedException();
Builder.EmitUInt(0b11010110_0_1_0_11111_00000_0_11110_00000);
}

public void EmitRETIfEqual()
{
throw new NotImplementedException();
Builder.EmitUInt(0b01010100_0000000000000000010_0_0001u);
EmitRET();
}

private bool InSignedByteRange(int i)
Expand Down
Loading