diff options
| author | Alex Barney <thealexbarney@gmail.com> | 2018-10-30 19:43:02 -0600 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-10-30 22:43:02 -0300 |
| commit | 9cb57fb4bb3bbae0ae052a5af4a96a49fc5d864d (patch) | |
| tree | 0c97425aeb311c142bc92a6fcc503cb2c07d4376 /ChocolArm64/Instructions/InstEmitAluHelper.cs | |
| parent | 5a87e58183578f5b84ca8d01cbb76aed11820f78 (diff) | |
Adjust naming conventions for Ryujinx and ChocolArm64 projects (#484)
* Change naming convention for Ryujinx project
* Change naming convention for ChocolArm64 project
* Fix NaN
* Remove unneeded this. from Ryujinx project
* Adjust naming from new PRs
* Name changes based on feedback
* How did this get removed?
* Rebasing fix
* Change FP enum case
* Remove prefix from ChocolArm64 classes - Part 1
* Remove prefix from ChocolArm64 classes - Part 2
* Fix alignment from last commit's renaming
* Rename namespaces
* Rename stragglers
* Fix alignment
* Rename OpCode class
* Missed a few
* Adjust alignment
Diffstat (limited to 'ChocolArm64/Instructions/InstEmitAluHelper.cs')
| -rw-r--r-- | ChocolArm64/Instructions/InstEmitAluHelper.cs | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/ChocolArm64/Instructions/InstEmitAluHelper.cs b/ChocolArm64/Instructions/InstEmitAluHelper.cs new file mode 100644 index 00000000..613dd234 --- /dev/null +++ b/ChocolArm64/Instructions/InstEmitAluHelper.cs @@ -0,0 +1,212 @@ +using ChocolArm64.Decoders; +using ChocolArm64.State; +using ChocolArm64.Translation; +using System.Reflection.Emit; + +namespace ChocolArm64.Instructions +{ + static class InstEmitAluHelper + { + public static void EmitAdcsCCheck(ILEmitterCtx context) + { + //C = (Rd == Rn && CIn) || Rd < Rn + context.EmitSttmp(); + context.EmitLdtmp(); + context.EmitLdtmp(); + + EmitDataLoadRn(context); + + context.Emit(OpCodes.Ceq); + + context.EmitLdflg((int)PState.CBit); + + context.Emit(OpCodes.And); + + context.EmitLdtmp(); + + EmitDataLoadRn(context); + + context.Emit(OpCodes.Clt_Un); + context.Emit(OpCodes.Or); + + context.EmitStflg((int)PState.CBit); + } + + public static void EmitAddsCCheck(ILEmitterCtx context) + { + //C = Rd < Rn + context.Emit(OpCodes.Dup); + + EmitDataLoadRn(context); + + context.Emit(OpCodes.Clt_Un); + + context.EmitStflg((int)PState.CBit); + } + + public static void EmitAddsVCheck(ILEmitterCtx context) + { + //V = (Rd ^ Rn) & ~(Rn ^ Rm) < 0 + context.Emit(OpCodes.Dup); + + EmitDataLoadRn(context); + + context.Emit(OpCodes.Xor); + + EmitDataLoadOpers(context); + + context.Emit(OpCodes.Xor); + context.Emit(OpCodes.Not); + context.Emit(OpCodes.And); + + context.EmitLdc_I(0); + + context.Emit(OpCodes.Clt); + + context.EmitStflg((int)PState.VBit); + } + + public static void EmitSbcsCCheck(ILEmitterCtx context) + { + //C = (Rn == Rm && CIn) || Rn > Rm + EmitDataLoadOpers(context); + + context.Emit(OpCodes.Ceq); + + context.EmitLdflg((int)PState.CBit); + + context.Emit(OpCodes.And); + + EmitDataLoadOpers(context); + + context.Emit(OpCodes.Cgt_Un); + context.Emit(OpCodes.Or); + + context.EmitStflg((int)PState.CBit); + } + + public static void EmitSubsCCheck(ILEmitterCtx context) + { + //C = Rn == Rm || Rn > Rm = !(Rn < Rm) + EmitDataLoadOpers(context); + + context.Emit(OpCodes.Clt_Un); + + context.EmitLdc_I4(1); + + context.Emit(OpCodes.Xor); + + context.EmitStflg((int)PState.CBit); + } + + public static void EmitSubsVCheck(ILEmitterCtx context) + { + //V = (Rd ^ Rn) & (Rn ^ Rm) < 0 + context.Emit(OpCodes.Dup); + + EmitDataLoadRn(context); + + context.Emit(OpCodes.Xor); + + EmitDataLoadOpers(context); + + context.Emit(OpCodes.Xor); + context.Emit(OpCodes.And); + + context.EmitLdc_I(0); + + context.Emit(OpCodes.Clt); + + context.EmitStflg((int)PState.VBit); + } + + public static void EmitDataLoadRm(ILEmitterCtx context) + { + context.EmitLdintzr(((IOpCodeAluRs64)context.CurrOp).Rm); + } + + public static void EmitDataLoadOpers(ILEmitterCtx context) + { + EmitDataLoadRn(context); + EmitDataLoadOper2(context); + } + + public static void EmitDataLoadRn(ILEmitterCtx context) + { + IOpCodeAlu64 op = (IOpCodeAlu64)context.CurrOp; + + if (op.DataOp == DataOp.Logical || op is IOpCodeAluRs64) + { + context.EmitLdintzr(op.Rn); + } + else + { + context.EmitLdint(op.Rn); + } + } + + public static void EmitDataLoadOper2(ILEmitterCtx context) + { + switch (context.CurrOp) + { + case IOpCodeAluImm64 op: + context.EmitLdc_I(op.Imm); + break; + + case IOpCodeAluRs64 op: + context.EmitLdintzr(op.Rm); + + switch (op.ShiftType) + { + case ShiftType.Lsl: context.EmitLsl(op.Shift); break; + case ShiftType.Lsr: context.EmitLsr(op.Shift); break; + case ShiftType.Asr: context.EmitAsr(op.Shift); break; + case ShiftType.Ror: context.EmitRor(op.Shift); break; + } + break; + + case IOpCodeAluRx64 op: + context.EmitLdintzr(op.Rm); + context.EmitCast(op.IntType); + context.EmitLsl(op.Shift); + break; + } + } + + public static void EmitDataStore(ILEmitterCtx context) => EmitDataStore(context, false); + public static void EmitDataStoreS(ILEmitterCtx context) => EmitDataStore(context, true); + + public static void EmitDataStore(ILEmitterCtx context, bool setFlags) + { + IOpCodeAlu64 op = (IOpCodeAlu64)context.CurrOp; + + if (setFlags || op is IOpCodeAluRs64) + { + context.EmitStintzr(op.Rd); + } + else + { + context.EmitStint(op.Rd); + } + } + + public static void EmitSetNzcv(ILEmitterCtx context, int nzcv) + { + context.EmitLdc_I4((nzcv >> 0) & 1); + + context.EmitStflg((int)PState.VBit); + + context.EmitLdc_I4((nzcv >> 1) & 1); + + context.EmitStflg((int)PState.CBit); + + context.EmitLdc_I4((nzcv >> 2) & 1); + + context.EmitStflg((int)PState.ZBit); + + context.EmitLdc_I4((nzcv >> 3) & 1); + + context.EmitStflg((int)PState.NBit); + } + } +}
\ No newline at end of file |
