Skip to content

Commit

Permalink
- ARM32 WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
tgiphil committed Nov 23, 2023
1 parent 9d4873a commit 0164e00
Show file tree
Hide file tree
Showing 53 changed files with 392 additions and 103 deletions.
1 change: 1 addition & 0 deletions Source/Mosa.Compiler.ARM32/Architecture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ public override void ExtendMethodCompilerPipeline(Pipeline<BaseMethodCompilerSta
pipeline.InsertAfterLast<PlatformIntrinsicStage>(
new BaseMethodCompilerStage[]
{
new FloatingTweakTransform(),
new IRTransformStage(),
mosaSettings.PlatformOptimizations ? new Stages.OptimizationStage() : null,
new PlatformTransformStage(),
Expand Down
20 changes: 20 additions & 0 deletions Source/Mosa.Compiler.ARM32/Stages/FloatingTweakTransform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using Mosa.Compiler.ARM32.Transforms.FloatingTweaks;

namespace Mosa.Compiler.ARM32.Stages;

/// <summary>
/// ARM32 IR Transformation Stage
/// </summary>
/// <seealso cref="Mosa.Compiler.Framework.Stages.BaseTransformStage" />
public sealed class FloatingTweakTransform : Compiler.Framework.Stages.BaseTransformStage
{
public override string Name => "ARM32." + GetType().Name;

public FloatingTweakTransform()
: base()
{
AddTranforms(FloatingTweakTransforms.List);
}
}
157 changes: 98 additions & 59 deletions Source/Mosa.Compiler.ARM32/Transforms/BaseARM32Transform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,79 +55,57 @@ public static void Translate(Transform transform, Context context, BaseInstructi
}
}

public static void MoveConstantRight(Transform transform, Context context)
{
Debug.Assert(context.OperandCount == 2);
Debug.Assert(context.Instruction.IsCommutative);

var operand1 = context.Operand1;

if (operand1.IsConstant && context.Instruction.IsCommutative)
{
var operand2 = context.Operand2;

context.Operand1 = operand2;
context.Operand2 = operand1;
}
}

public static void TransformLoad(Transform transform, Context context, BaseInstruction loadInstruction, Operand result, Operand baseOperand, Operand offsetOperand)
{
baseOperand = MoveConstantToRegister(transform, context, baseOperand);
var upDirection = true;

if (offsetOperand.IsResolvedConstant)
{
if (offsetOperand.ConstantUnsigned64 >= 0 && offsetOperand.ConstantSigned32 <= 0xFFF)
{
// Nothing
}
else if (offsetOperand.ConstantUnsigned64 < 0 && -offsetOperand.ConstantSigned32 <= 0xFFF)
{
upDirection = false;
offsetOperand = Operand.CreateConstant32(-offsetOperand.ConstantSigned32);
}
else
{
offsetOperand = MoveConstantToRegister(transform, context, offsetOperand);
}
}
else if (offsetOperand.IsUnresolvedConstant)
{
offsetOperand = MoveConstantToRegister(transform, context, offsetOperand);
}
offsetOperand = LimitOffsetToRange(transform, context, offsetOperand, 12, out var upDirection);

context.SetInstruction(loadInstruction, upDirection ? StatusRegister.UpDirection : StatusRegister.DownDirection, result, baseOperand, offsetOperand);
}

public static void TransformStore(Transform transform, Context context, BaseInstruction storeInstruction, Operand baseOperand, Operand offsetOperand, Operand sourceOperand)
{
baseOperand = MoveConstantToRegister(transform, context, baseOperand);
sourceOperand = MoveConstantToRegister(transform, context, sourceOperand);
baseOperand = MoveConstantToRegister(transform, context, baseOperand);
offsetOperand = LimitOffsetToRange(transform, context, offsetOperand, 12, out var upDirection);

var upDirection = true;
context.SetInstruction(storeInstruction, upDirection ? StatusRegister.UpDirection : StatusRegister.DownDirection, null, baseOperand, offsetOperand, sourceOperand);
}

if (offsetOperand.IsResolvedConstant)
public static void TransformFloatingPointLoad(Transform transform, Context context, BaseInstruction loadInstruction, Operand result, Operand baseOperand, Operand offsetOperand)
{
if (baseOperand.IsConstant && offsetOperand.IsVirtualRegister)
{
if (offsetOperand.ConstantUnsigned64 >= 0 && offsetOperand.ConstantSigned32 <= 0xFFF)
{
// Nothing
}
else if (offsetOperand.ConstantUnsigned64 < 0 && -offsetOperand.ConstantSigned32 <= 0xFFF)
{
offsetOperand = Operand.CreateConstant32(-offsetOperand.ConstantSigned32);
}
else
{
upDirection = false;
offsetOperand = MoveConstantToRegister(transform, context, offsetOperand);
}
// swap
var tmp = baseOperand;
baseOperand = offsetOperand;
offsetOperand = tmp;
}
else if (offsetOperand.IsUnresolvedConstant)

baseOperand = MoveConstantToRegister(transform, context, baseOperand);
offsetOperand = LimitOffsetToRange(transform, context, offsetOperand, 8, out var upDirection);

ConformBaseOffsetToContant(transform, context, ref baseOperand, ref offsetOperand);

context.SetInstruction(loadInstruction, upDirection ? StatusRegister.UpDirection : StatusRegister.DownDirection, result, baseOperand, offsetOperand);
}

public static void TransformFloatingPointStore(Transform transform, Context context, BaseInstruction storeInstruction, Operand baseOperand, Operand offsetOperand, Operand sourceOperand)
{
if (baseOperand.IsConstant && offsetOperand.IsVirtualRegister)
{
offsetOperand = MoveConstantToRegister(transform, context, offsetOperand);
// swap
var tmp = baseOperand;
baseOperand = offsetOperand;
offsetOperand = tmp;
}

sourceOperand = MoveConstantToFloatRegister(transform, context, sourceOperand);
baseOperand = MoveConstantToRegister(transform, context, baseOperand);
offsetOperand = LimitOffsetToRange(transform, context, offsetOperand, 8, out var upDirection);

ConformBaseOffsetToContant(transform, context, ref baseOperand, ref offsetOperand);

context.SetInstruction(storeInstruction, upDirection ? StatusRegister.UpDirection : StatusRegister.DownDirection, null, baseOperand, offsetOperand, sourceOperand);
}

Expand Down Expand Up @@ -236,14 +214,14 @@ public static Operand MoveConstantToFloatRegisterOrImmediate(Transform transform
: transform.VirtualRegisters.AllocateR8();

var symbol = operand.IsR4
? transform.Linker.GetConstantSymbol((float)operand.ConstantUnsigned64)
: transform.Linker.GetConstantSymbol((double)operand.ConstantUnsigned64);
? transform.Linker.GetConstantSymbol(operand.ConstantFloat)
: transform.Linker.GetConstantSymbol(operand.ConstantDouble);

var label = operand.IsR4
? Operand.CreateLabelR4(symbol.Name)
: Operand.CreateLabelR8(symbol.Name);

var source = MoveConstantToRegisterOrImmediate(transform, context, label, true);
var source = MoveConstantToRegister(transform, context, label);

context.InsertBefore().SetInstruction(ARM32.Ldf, v1, source, Operand.Constant32_0);

Expand Down Expand Up @@ -291,6 +269,67 @@ public static Operand ConvertFloatToImm(Transform transform, Operand operand)
return null;
}

public static void MoveConstantRight(Transform transform, Context context)
{
Debug.Assert(context.OperandCount == 2);
Debug.Assert(context.Instruction.IsCommutative);

var operand1 = context.Operand1;

if (operand1.IsConstant && context.Instruction.IsCommutative)
{
var operand2 = context.Operand2;

context.Operand1 = operand2;
context.Operand2 = operand1;
}
}

private static Operand LimitOffsetToRange(Transform transform, Context context, Operand offsetOperand, int bits, out bool upDirection)
{
var mask = 1 << (bits + 1) - 1;

// bits == 4 then mask == 0xFFF

upDirection = true;

if (offsetOperand.IsResolvedConstant)
{
if (offsetOperand.ConstantUnsigned64 >= 0 && offsetOperand.ConstantSigned32 <= mask)
{
// Nothing
}
else if (offsetOperand.ConstantUnsigned64 < 0 && -offsetOperand.ConstantSigned32 <= mask)
{
offsetOperand = Operand.CreateConstant32(-offsetOperand.ConstantSigned32);
}
else
{
upDirection = false;
offsetOperand = MoveConstantToRegister(transform, context, offsetOperand);
}
}
else if (offsetOperand.IsUnresolvedConstant)
{
offsetOperand = MoveConstantToRegister(transform, context, offsetOperand);
}

return offsetOperand;
}

private static void ConformBaseOffsetToContant(Transform transform, Context context, ref Operand baseOperand, ref Operand offsetOperand)
{
if (offsetOperand.IsVirtualRegister)
{
var before = context.InsertBefore();
var v1 = transform.VirtualRegisters.Allocate32();
before.SetInstruction(ARM32.Add, v1, baseOperand, offsetOperand);

baseOperand = v1;
offsetOperand = Operand.Constant32_0;
}
}

#endregion Helpers
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Mosa.Compiler.ARM32.Transforms.BaseIR;
/// </summary>
public static class IRTransforms
{
public static readonly List<BaseTransform> List = new List<BaseTransform>
public static readonly List<BaseTransform> List = new()
{
new Add32(),
new AddCarryIn32(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ public override void Transform(Context context, Transform transform)
{
Debug.Assert(context.Operand1.IsConstant);

TransformLoad(transform, context, ARM32.Ldf, context.Result, transform.StackFrame, context.Operand1);
TransformFloatingPointLoad(transform, context, ARM32.Ldf, context.Result, transform.StackFrame, context.Operand1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ public override void Transform(Context context, Transform transform)
{
Debug.Assert(context.Operand1.IsConstant);

TransformLoad(transform, context, ARM32.Ldf, context.Result, transform.StackFrame, context.Operand1);
TransformFloatingPointLoad(transform, context, ARM32.Ldf, context.Result, transform.StackFrame, context.Operand1);
}
}
2 changes: 1 addition & 1 deletion Source/Mosa.Compiler.ARM32/Transforms/BaseIR/LoadR4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ public override void Transform(Context context, Transform transform)
{
transform.OrderLoadStoreOperands(context);

TransformLoad(transform, context, ARM32.Ldf, context.Result, context.Operand1, context.Operand2);
TransformFloatingPointLoad(transform, context, ARM32.Ldf, context.Result, context.Operand1, context.Operand2);
}
}
2 changes: 1 addition & 1 deletion Source/Mosa.Compiler.ARM32/Transforms/BaseIR/LoadR8.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ public override void Transform(Context context, Transform transform)
{
transform.OrderLoadStoreOperands(context);

TransformLoad(transform, context, ARM32.Ldf, context.Result, context.Operand1, context.Operand2);
TransformFloatingPointLoad(transform, context, ARM32.Ldf, context.Result, context.Operand1, context.Operand2);
}
}
4 changes: 3 additions & 1 deletion Source/Mosa.Compiler.ARM32/Transforms/BaseIR/StoreParamR4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public StoreParamR4() : base(IR.StoreParamR4, TransformType.Manual | TransformTy

public override void Transform(Context context, Transform transform)
{
TransformStore(transform, context, ARM32.Stf, transform.StackFrame, context.Operand1, context.Operand2);
//operand1 = MoveConstantToRegister(transform, context, operand1);

TransformFloatingPointStore(transform, context, ARM32.Stf, transform.StackFrame, context.Operand1, context.Operand2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public StoreParamR8() : base(IR.StoreParamR8, TransformType.Manual | TransformTy

public override void Transform(Context context, Transform transform)
{
TransformStore(transform, context, ARM32.Stf, transform.StackFrame, context.Operand1, context.Operand2);
TransformFloatingPointStore(transform, context, ARM32.Stf, transform.StackFrame, context.Operand1, context.Operand2);
}
}
2 changes: 1 addition & 1 deletion Source/Mosa.Compiler.ARM32/Transforms/BaseIR/StoreR4.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public StoreR4() : base(IR.StoreR4, TransformType.Manual | TransformType.Transfo

public override void Transform(Context context, Transform transform)
{
TransformStore(transform, context, ARM32.Stf, context.Operand1, context.Operand2, context.Operand3);
TransformFloatingPointStore(transform, context, ARM32.Stf, context.Operand1, context.Operand2, context.Operand3);
}
}
2 changes: 1 addition & 1 deletion Source/Mosa.Compiler.ARM32/Transforms/BaseIR/StoreR8.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public StoreR8() : base(IR.StoreR8, TransformType.Manual | TransformType.Transfo

public override void Transform(Context context, Transform transform)
{
TransformStore(transform, context, ARM32.Stf, context.Operand1, context.Operand2, context.Operand3);
TransformFloatingPointStore(transform, context, ARM32.Stf, context.Operand1, context.Operand2, context.Operand3);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Mosa.Compiler.ARM32.Transforms.FixedRegisters;
/// </summary>
public static class FixedRegistersTransforms
{
public static readonly List<BaseTransform> List = new List<BaseTransform>
public static readonly List<BaseTransform> List = new()
{
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using Mosa.Compiler.Framework;

namespace Mosa.Compiler.ARM32.Transforms.FloatingTweaks;

/// <summary>
/// ConvertI3ConvertI64ToR42ToR4
/// </summary>
public sealed class ConvertI64ToR4 : BaseTransform
{
public ConvertI64ToR4() : base(IR.ConvertI64ToR4, TransformType.Manual | TransformType.Transform)
{
}

public override bool Match(Context context, Transform transform)
{
return true;
}

public override void Transform(Context context, Transform transform)
{
var result = context.Result;
var operand1 = context.Operand1;

transform.SplitOperand(operand1, out _, out _);

var v1 = transform.VirtualRegisters.Allocate32();
var v2 = transform.VirtualRegisters.AllocateR8();

var multiply = Operand.CreateConstant((float)uint.MaxValue);

context.SetInstruction(IR.GetHigh32, v1, operand1);
context.AppendInstruction(IR.ConvertI32ToR4, v2, v1);
context.AppendInstruction(IR.MulR4, result, v2, multiply);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using Mosa.Compiler.Framework;

namespace Mosa.Compiler.ARM32.Transforms.FloatingTweaks;

/// <summary>
/// ConvertI64ToR8
/// </summary>
public sealed class ConvertI64ToR8 : BaseTransform
{
public ConvertI64ToR8() : base(IR.ConvertI64ToR8, TransformType.Manual | TransformType.Transform)
{
}

public override bool Match(Context context, Transform transform)
{
return true;
}

public override void Transform(Context context, Transform transform)
{
var result = context.Result;
var operand1 = context.Operand1;

transform.SplitOperand(operand1, out _, out _);

var v1 = transform.VirtualRegisters.Allocate32();
var v2 = transform.VirtualRegisters.AllocateR8();

var multiply = Operand.CreateConstant((double)uint.MaxValue);

context.SetInstruction(IR.GetHigh32, v1, operand1);
context.AppendInstruction(IR.ConvertI32ToR8, v2, v1);
context.AppendInstruction(IR.MulR8, result, v2, multiply);
}
}
Loading

0 comments on commit 0164e00

Please sign in to comment.