diff --git a/ARMeilleure/Instructions/InstEmitFlow32.cs b/ARMeilleure/Instructions/InstEmitFlow32.cs index cbb9ad5b26..f8487205b6 100644 --- a/ARMeilleure/Instructions/InstEmitFlow32.cs +++ b/ARMeilleure/Instructions/InstEmitFlow32.cs @@ -5,6 +5,7 @@ using ARMeilleure.Translation; using static ARMeilleure.Instructions.InstEmitFlowHelper; using static ARMeilleure.Instructions.InstEmitHelper; +using static ARMeilleure.Instructions.InstEmitFlowHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper; namespace ARMeilleure.Instructions @@ -21,7 +22,6 @@ namespace ARMeilleure.Instructions } else { - context.StoreToContext(); context.Return(Const(op.Immediate)); } } @@ -57,7 +57,7 @@ namespace ARMeilleure.Instructions SetFlag(context, PState.TFlag, Const(isThumb ? 0 : 1)); } - InstEmitFlowHelper.EmitCall(context, (ulong)op.Immediate); + EmitJumpTableCall(context, Const((int)op.Immediate)); } public static void Blxr(ArmEmitterContext context) @@ -66,9 +66,8 @@ namespace ARMeilleure.Instructions uint pc = op.GetPc(); - Operand addr = GetIntA32(context, op.Rm); + Operand addr = context.Copy(GetIntA32(context, op.Rm)); Operand bitOne = context.BitwiseAnd(addr, Const(1)); - addr = context.BitwiseOr(addr, Const((int)CallFlag)); // Set call flag. bool isThumb = IsThumb(context.CurrOp); @@ -80,15 +79,13 @@ namespace ARMeilleure.Instructions SetFlag(context, PState.TFlag, bitOne); - context.Return(addr); // Call. + EmitJumpTableCall(context, addr); } public static void Bx(ArmEmitterContext context) { IOpCode32BReg op = (IOpCode32BReg)context.CurrOp; - context.StoreToContext(); - EmitBxWritePc(context, GetIntA32(context, op.Rm)); } } diff --git a/ARMeilleure/Instructions/InstEmitHelper.cs b/ARMeilleure/Instructions/InstEmitHelper.cs index f5495c6600..64fe7f153d 100644 --- a/ARMeilleure/Instructions/InstEmitHelper.cs +++ b/ARMeilleure/Instructions/InstEmitHelper.cs @@ -144,22 +144,33 @@ namespace ARMeilleure.Instructions } } - public static void EmitBxWritePc(ArmEmitterContext context, Operand pc) + public static void EmitBxWritePc(ArmEmitterContext context, Operand pc, int sourceRegister = 0) { + bool allowRejit = sourceRegister != RegisterAlias.Aarch32Lr && context.CurrOp.Instruction.Name != InstName.Ldm; Operand mode = context.BitwiseAnd(pc, Const(1)); SetFlag(context, PState.TFlag, mode); Operand lblArmMode = Label(); - context.BranchIfTrue(lblArmMode, mode); + context.BranchIfFalse(lblArmMode, mode); - // Make this count as a call, the translator will ignore the low bit for the address. - context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(pc, Const((int)InstEmitFlowHelper.CallFlag)))); + Operand thumbAddr = allowRejit ? context.BitwiseOr(pc, Const((int)InstEmitFlowHelper.CallFlag)) : pc; + // Make this count for rejit, the translator will ignore the low bit for the address. + context.Return(context.ZeroExtend32(OperandType.I64, thumbAddr)); context.MarkLabel(lblArmMode); - context.Return(context.ZeroExtend32(OperandType.I64, context.BitwiseOr(context.BitwiseAnd(pc, Const(~3)), Const((int)InstEmitFlowHelper.CallFlag)))); + Operand a32Addr = context.BitwiseAnd(pc, Const(~3)); + + if (allowRejit) + { + InstEmitFlowHelper.EmitJumpTableCall(context, a32Addr, true); + } + else + { + context.Return(context.ZeroExtend32(OperandType.I64, a32Addr)); + } } public static Operand GetIntOrZR(ArmEmitterContext context, int regIndex) diff --git a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs index 70861d1634..e1dec3313a 100644 --- a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs +++ b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs @@ -51,7 +51,7 @@ namespace ARMeilleure.Instructions EmitReadInt(context, address, rt, size); } - if (!isSimd) + if (!isSimd && !(context.CurrOp is OpCode32 && rt == State.RegisterAlias.Aarch32Pc)) { Operand value = GetInt(context, rt);