add B and fix add
This commit is contained in:
@ -27,13 +27,21 @@ namespace ARMeilleure.CodeGen.Loong64
|
||||
}
|
||||
}
|
||||
|
||||
public void B(int imm)
|
||||
{
|
||||
WriteUInt32(0x50000000 | EncodeSImm26_2(imm));
|
||||
}
|
||||
|
||||
public void Addi(Operand rd, Operand rj, int imm)
|
||||
{
|
||||
if (rd.Type == OperandType.I64)
|
||||
{
|
||||
WriteUInt32(0x02c00000u | EncodeReg(rd) | EncodeReg(rj) << 5 | EncodeSImm12(imm) << 10);
|
||||
}
|
||||
WriteUInt32(0x02800000u | EncodeReg(rd) | EncodeReg(rj) << 5 | EncodeSImm12(imm) << 10);
|
||||
else
|
||||
{
|
||||
WriteUInt32(0x02800000u | EncodeReg(rd) | EncodeReg(rj) << 5 | EncodeSImm12(imm) << 10);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddReg(Operand rd, Operand rj, Operand rk)
|
||||
@ -42,7 +50,10 @@ namespace ARMeilleure.CodeGen.Loong64
|
||||
{
|
||||
WriteUInt32(0x00108000u | EncodeReg(rd) | EncodeReg(rj) << 5 | EncodeReg(rk) << 10);
|
||||
}
|
||||
WriteUInt32(0x00100000u | EncodeReg(rd) | EncodeReg(rj) << 5 | EncodeReg(rk) << 10);
|
||||
else
|
||||
{
|
||||
WriteUInt32(0x00100000u | EncodeReg(rd) | EncodeReg(rj) << 5 | EncodeReg(rk) << 10);
|
||||
}
|
||||
}
|
||||
|
||||
private static uint EncodeSImm12(int value)
|
||||
@ -52,6 +63,28 @@ namespace ARMeilleure.CodeGen.Loong64
|
||||
return imm;
|
||||
}
|
||||
|
||||
private static uint EncodeSImm26_2(int value)
|
||||
{
|
||||
int shifted = value >> 2;
|
||||
|
||||
uint immLo = (uint)shifted & 0xFFFF; // imm[15:0]
|
||||
uint immHi = ((uint)shifted >> 16) & 0x3FF; // imm[25:16]
|
||||
|
||||
uint encoded =
|
||||
(immLo << 10) | // inst[25:10]
|
||||
(immHi << 0); // inst[9:0]
|
||||
|
||||
uint recon =
|
||||
((encoded & 0x3FF) << 16) | // inst[9:0] -> imm[25:16]
|
||||
((encoded >> 10) & 0xFFFF); // inst[25:10] -> imm[15:0]
|
||||
|
||||
int decoded = (int)(recon << 6) >> 4;
|
||||
|
||||
Debug.Assert(decoded == value, $"Failed to encode constant 0x{value:X}.");
|
||||
|
||||
return encoded;
|
||||
}
|
||||
|
||||
private static uint EncodeReg(Operand reg)
|
||||
{
|
||||
if (reg.Kind == OperandKind.Constant && reg.Value == 0)
|
||||
|
||||
@ -11,24 +11,186 @@ namespace ARMeilleure.CodeGen.Loong64
|
||||
{
|
||||
class CodeGenContext
|
||||
{
|
||||
private const int BranchInstLength = 4;
|
||||
|
||||
private readonly RecyclableMemoryStream _stream;
|
||||
|
||||
public int StreamOffset => (int)_stream.Length;
|
||||
|
||||
public AllocationResult AllocResult { get; }
|
||||
|
||||
public Assembler Assembler { get; }
|
||||
|
||||
public CodeGenContext(AllocationResult allocResult)
|
||||
public BasicBlock CurrBlock { get; private set; }
|
||||
|
||||
public bool HasCall { get; }
|
||||
|
||||
public int CallArgsRegionSize { get; }
|
||||
|
||||
private readonly Dictionary<BasicBlock, long> _visitedBlocks;
|
||||
private readonly Dictionary<BasicBlock, List<PendingBranch>> _pendingBranches;
|
||||
|
||||
private readonly bool _relocatable;
|
||||
|
||||
private readonly struct PendingBranch
|
||||
{
|
||||
public readonly Comparison ComparisonType;
|
||||
public readonly Operand? Operand1;
|
||||
public readonly Operand? Operand2;
|
||||
public readonly long BranchPosition;
|
||||
|
||||
public PendingBranch(Comparison compType, Operand? op1, Operand? op2, long pos)
|
||||
{
|
||||
ComparisonType = compType;
|
||||
Operand1 = op1;
|
||||
Operand2 = op2;
|
||||
BranchPosition = pos;
|
||||
}
|
||||
}
|
||||
|
||||
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, bool relocatable)
|
||||
{
|
||||
_stream = MemoryStreamManager.Shared.GetStream();
|
||||
|
||||
AllocResult = allocResult;
|
||||
|
||||
Assembler = new Assembler(_stream);
|
||||
|
||||
bool hasCall = maxCallArgs >= 0;
|
||||
|
||||
HasCall = hasCall;
|
||||
|
||||
if (maxCallArgs < 0)
|
||||
{
|
||||
maxCallArgs = 0;
|
||||
}
|
||||
|
||||
CallArgsRegionSize = maxCallArgs * 16;
|
||||
|
||||
_visitedBlocks = new Dictionary<BasicBlock, long>();
|
||||
_pendingBranches = new Dictionary<BasicBlock, List<PendingBranch>>();
|
||||
|
||||
_relocatable = relocatable;
|
||||
}
|
||||
|
||||
public void EnterBlock(BasicBlock block)
|
||||
{
|
||||
CurrBlock = block;
|
||||
|
||||
long target = _stream.Position;
|
||||
|
||||
// 修补所有跳转到此块的待处理分支
|
||||
if (_pendingBranches.TryGetValue(block, out List<PendingBranch> list))
|
||||
{
|
||||
foreach (PendingBranch pending in list)
|
||||
{
|
||||
_stream.Seek(pending.BranchPosition, SeekOrigin.Begin);
|
||||
WriteBranch(pending.ComparisonType, pending.Operand1, pending.Operand2, target);
|
||||
}
|
||||
|
||||
_stream.Seek(target, SeekOrigin.Begin);
|
||||
_pendingBranches.Remove(block);
|
||||
}
|
||||
|
||||
_visitedBlocks.Add(block, target);
|
||||
}
|
||||
|
||||
public void JumpTo(BasicBlock target)
|
||||
{
|
||||
if (_visitedBlocks.TryGetValue(target, out long offset))
|
||||
{
|
||||
// 目标块已生成,直接写入无条件跳转
|
||||
WriteUnconditionalBranch(offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 目标块未生成,记录待修补(使用特殊的无条件标记)
|
||||
if (!_pendingBranches.TryGetValue(target, out List<PendingBranch> list))
|
||||
{
|
||||
list = new List<PendingBranch>();
|
||||
_pendingBranches.Add(target, list);
|
||||
}
|
||||
|
||||
// 使用 Comparison.Equal 和 null 操作数表示无条件跳转
|
||||
list.Add(new PendingBranch(Comparison.Equal, null, null, _stream.Position));
|
||||
|
||||
_stream.Seek(BranchInstLength, SeekOrigin.Current);
|
||||
}
|
||||
}
|
||||
|
||||
public void JumpToIf(Comparison compType, Operand op1, Operand op2, BasicBlock target)
|
||||
{
|
||||
if (_visitedBlocks.TryGetValue(target, out long offset))
|
||||
{
|
||||
// 目标块已生成,直接写入条件分支
|
||||
WriteBranch(compType, op1, op2, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 目标块未生成,记录待修补
|
||||
if (!_pendingBranches.TryGetValue(target, out List<PendingBranch> list))
|
||||
{
|
||||
list = new List<PendingBranch>();
|
||||
_pendingBranches.Add(target, list);
|
||||
}
|
||||
|
||||
list.Add(new PendingBranch(compType, op1, op2, _stream.Position));
|
||||
|
||||
_stream.Seek(BranchInstLength, SeekOrigin.Current);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteBranch(Comparison compType, Operand? op1, Operand? op2, long targetPos)
|
||||
{
|
||||
// 如果操作数为 null,表示无条件跳转
|
||||
if (op1 == null && op2 == null)
|
||||
{
|
||||
WriteUnconditionalBranch(targetPos);
|
||||
return;
|
||||
}
|
||||
|
||||
int offset = checked((int)(targetPos - _stream.Position));
|
||||
|
||||
// TODO: 根据 Comparison 类型调用相应的 Assembler 方法
|
||||
// 这里需要实现 Loong64 的条件分支指令
|
||||
switch (compType)
|
||||
{
|
||||
case Comparison.Equal:
|
||||
// Assembler.Beq(op1, op2, offset);
|
||||
throw new NotImplementedException("Beq not implemented yet");
|
||||
|
||||
case Comparison.NotEqual:
|
||||
// Assembler.Bne(op1, op2, offset);
|
||||
throw new NotImplementedException("Bne not implemented yet");
|
||||
|
||||
case Comparison.Less:
|
||||
// Assembler.Blt(op1, op2, offset);
|
||||
throw new NotImplementedException("Blt not implemented yet");
|
||||
|
||||
case Comparison.LessOrEqual:
|
||||
// Assembler.Ble(op1, op2, offset);
|
||||
throw new NotImplementedException("Ble not implemented yet");
|
||||
|
||||
case Comparison.Greater:
|
||||
// Assembler.Bgt(op1, op2, offset);
|
||||
throw new NotImplementedException("Bgt not implemented yet");
|
||||
|
||||
case Comparison.GreaterOrEqual:
|
||||
// Assembler.Bge(op1, op2, offset);
|
||||
throw new NotImplementedException("Bge not implemented yet");
|
||||
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported comparison type: {compType}");
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteUnconditionalBranch(long targetPos)
|
||||
{
|
||||
int offset = checked((int)(targetPos - _stream.Position));
|
||||
|
||||
// TODO: 实现 Loong64 的无条件跳转指令
|
||||
Assembler.B(offset);
|
||||
throw new NotImplementedException("Unconditional branch not implemented yet");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,7 +95,7 @@ namespace ARMeilleure.CodeGen.Loong64
|
||||
|
||||
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0;
|
||||
|
||||
CodeGenContext context = new(allocResult);
|
||||
CodeGenContext context = new(allocResult, maxCallArgs, relocatable);
|
||||
|
||||
UnwindInfo unwindInfo = WritePrologue(context);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user