diff options
Diffstat (limited to 'ARMeilleure/Instructions')
-rw-r--r-- | ARMeilleure/Instructions/InstEmitFlow32.cs | 25 | ||||
-rw-r--r-- | ARMeilleure/Instructions/InstEmitMemory32.cs | 16 | ||||
-rw-r--r-- | ARMeilleure/Instructions/InstEmitMemoryHelper.cs | 42 | ||||
-rw-r--r-- | ARMeilleure/Instructions/InstName.cs | 2 |
4 files changed, 76 insertions, 9 deletions
diff --git a/ARMeilleure/Instructions/InstEmitFlow32.cs b/ARMeilleure/Instructions/InstEmitFlow32.cs index 030713fb..19524b42 100644 --- a/ARMeilleure/Instructions/InstEmitFlow32.cs +++ b/ARMeilleure/Instructions/InstEmitFlow32.cs @@ -107,5 +107,30 @@ namespace ARMeilleure.Instructions context.SetIfThenBlockState(op.IfThenBlockConds); } + + public static void Tbb(ArmEmitterContext context) => EmitTb(context, halfword: false); + public static void Tbh(ArmEmitterContext context) => EmitTb(context, halfword: true); + + private static void EmitTb(ArmEmitterContext context, bool halfword) + { + OpCodeT32Tb op = (OpCodeT32Tb)context.CurrOp; + + Operand halfwords; + + if (halfword) + { + Operand address = context.Add(GetIntA32(context, op.Rn), context.ShiftLeft(GetIntA32(context, op.Rm), Const(1))); + halfwords = InstEmitMemoryHelper.EmitReadInt(context, address, 1); + } + else + { + Operand address = context.Add(GetIntA32(context, op.Rn), GetIntA32(context, op.Rm)); + halfwords = InstEmitMemoryHelper.EmitReadIntAligned(context, address, 0); + } + + Operand targetAddress = context.Add(Const((int)op.GetPc()), context.ShiftLeft(halfwords, Const(1))); + + EmitVirtualJump(context, targetAddress, isReturn: false); + } } }
\ No newline at end of file diff --git a/ARMeilleure/Instructions/InstEmitMemory32.cs b/ARMeilleure/Instructions/InstEmitMemory32.cs index e15f6a5b..17ec97aa 100644 --- a/ARMeilleure/Instructions/InstEmitMemory32.cs +++ b/ARMeilleure/Instructions/InstEmitMemory32.cs @@ -204,15 +204,15 @@ namespace ARMeilleure.Instructions context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag)); - Load(op.Rt, 0, WordSizeLog2); - Load(op.Rt | 1, 4, WordSizeLog2); + Load(op.Rt, 0, WordSizeLog2); + Load(op.Rt2, 4, WordSizeLog2); context.Branch(lblEnd); context.MarkLabel(lblBigEndian); - Load(op.Rt | 1, 0, WordSizeLog2); - Load(op.Rt, 4, WordSizeLog2); + Load(op.Rt2, 0, WordSizeLog2); + Load(op.Rt, 4, WordSizeLog2); context.MarkLabel(lblEnd); } @@ -237,15 +237,15 @@ namespace ARMeilleure.Instructions context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag)); - Store(op.Rt, 0, WordSizeLog2); - Store(op.Rt | 1, 4, WordSizeLog2); + Store(op.Rt, 0, WordSizeLog2); + Store(op.Rt2, 4, WordSizeLog2); context.Branch(lblEnd); context.MarkLabel(lblBigEndian); - Store(op.Rt | 1, 0, WordSizeLog2); - Store(op.Rt, 4, WordSizeLog2); + Store(op.Rt2, 0, WordSizeLog2); + Store(op.Rt, 4, WordSizeLog2); context.MarkLabel(lblEnd); } diff --git a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs index 2877d53e..f97e395c 100644 --- a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs +++ b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs @@ -123,6 +123,41 @@ namespace ARMeilleure.Instructions context.CurrOp is OpCodeSimdMemSs); } + public static Operand EmitReadInt(ArmEmitterContext context, Operand address, int size) + { + Operand temp = context.AllocateLocal(size == 3 ? OperandType.I64 : OperandType.I32); + + Operand lblSlowPath = Label(); + Operand lblEnd = Label(); + + Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath, write: false, size); + + Operand value = default; + + switch (size) + { + case 0: value = context.Load8 (physAddr); break; + case 1: value = context.Load16(physAddr); break; + case 2: value = context.Load (OperandType.I32, physAddr); break; + case 3: value = context.Load (OperandType.I64, physAddr); break; + } + + context.Copy(temp, value); + + if (!context.Memory.Type.IsHostMapped()) + { + context.Branch(lblEnd); + + context.MarkLabel(lblSlowPath, BasicBlockFrequency.Cold); + + context.Copy(temp, EmitReadIntFallback(context, address, size)); + + context.MarkLabel(lblEnd); + } + + return temp; + } + private static void EmitReadInt(ArmEmitterContext context, Operand address, int rt, int size) { Operand lblSlowPath = Label(); @@ -420,6 +455,11 @@ namespace ARMeilleure.Instructions private static void EmitReadIntFallback(ArmEmitterContext context, Operand address, int rt, int size) { + SetInt(context, rt, EmitReadIntFallback(context, address, size)); + } + + private static Operand EmitReadIntFallback(ArmEmitterContext context, Operand address, int size) + { MethodInfo info = null; switch (size) @@ -430,7 +470,7 @@ namespace ARMeilleure.Instructions case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break; } - SetInt(context, rt, context.Call(info, address)); + return context.Call(info, address); } private static void EmitReadVectorFallback( diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs index 0d63820b..f2c95ae9 100644 --- a/ARMeilleure/Instructions/InstName.cs +++ b/ARMeilleure/Instructions/InstName.cs @@ -545,6 +545,8 @@ namespace ARMeilleure.Instructions Strexh, Strh, Sxtb16, + Tbb, + Tbh, Teq, Trap, Tst, |