aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Translation/AILOpCodeLoad.cs
blob: d60ce539f7d5fedbbb9d5476a186568147618cb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using ChocolArm64.State;
using System.Reflection.Emit;

namespace ChocolArm64.Translation
{
    struct AILOpCodeLoad : IAILEmit
    {
        public int Index { get; private set; }

        public AIoType IoType { get; private set; }

        public ARegisterSize RegisterSize { get; private set; }

        public AILOpCodeLoad(int Index, AIoType IoType, ARegisterSize RegisterSize = 0)
        {
            this.Index        = Index;
            this.IoType       = IoType;
            this.RegisterSize = RegisterSize;
        }

        public void Emit(AILEmitter Context)
        {
            switch (IoType)
            {
                case AIoType.Arg: Context.Generator.EmitLdarg(Index); break;

                case AIoType.Fields:
                {
                    long IntInputs = Context.LocalAlloc.GetIntInputs(Context.GetILBlock(Index));
                    long VecInputs = Context.LocalAlloc.GetVecInputs(Context.GetILBlock(Index));

                    LoadLocals(Context, IntInputs, ARegisterType.Int);
                    LoadLocals(Context, VecInputs, ARegisterType.Vector);

                    break;
                }

                case AIoType.Flag:   EmitLdloc(Context, Index, ARegisterType.Flag);   break;
                case AIoType.Int:    EmitLdloc(Context, Index, ARegisterType.Int);    break;
                case AIoType.Vector: EmitLdloc(Context, Index, ARegisterType.Vector); break;
            }
        }

        private void LoadLocals(AILEmitter Context, long Inputs, ARegisterType BaseType)
        {
            for (int Bit = 0; Bit < 64; Bit++)
            {
                long Mask = 1L << Bit;

                if ((Inputs & Mask) != 0)
                {
                    ARegister Reg = AILEmitter.GetRegFromBit(Bit, BaseType);

                    Context.Generator.EmitLdarg(ATranslatedSub.StateArgIdx);
                    Context.Generator.Emit(OpCodes.Ldfld, Reg.GetField());

                    Context.Generator.EmitStloc(Context.GetLocalIndex(Reg));
                }
            }
        }

        private void EmitLdloc(AILEmitter Context, int Index, ARegisterType RegisterType)
        {
            ARegister Reg = new ARegister(Index, RegisterType);

            Context.Generator.EmitLdloc(Context.GetLocalIndex(Reg));

            if (RegisterType == ARegisterType.Int &&
                RegisterSize == ARegisterSize.Int32)
            {
                Context.Generator.Emit(OpCodes.Conv_U4);
            }
        }
    }
}