aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Translation/ILOpCodeConst.cs
blob: 5497eba16fd66c3ce7f544ac490a09ad4e97548c (plain) (blame)
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
using System.Reflection.Emit;
using System.Runtime.InteropServices;

namespace ChocolArm64.Translation
{
    class ILOpCodeConst : IILEmit
    {
        [StructLayout(LayoutKind.Explicit, Size = 8)]
        private struct ImmVal
        {
            [FieldOffset(0)] public int    I4;
            [FieldOffset(0)] public long   I8;
            [FieldOffset(0)] public float  R4;
            [FieldOffset(0)] public double R8;
        }

        private ImmVal _value;

        private enum ConstType
        {
            Int32,
            Int64,
            Single,
            Double
        }

        private ConstType _type;

        private ILOpCodeConst(ConstType type)
        {
            _type = type;
        }

        public ILOpCodeConst(int value) : this(ConstType.Int32)
        {
            _value = new ImmVal { I4 = value };
        }

        public ILOpCodeConst(long value) : this(ConstType.Int64)
        {
            _value = new ImmVal { I8 = value };
        }

        public ILOpCodeConst(float value) : this(ConstType.Single)
        {
            _value = new ImmVal { R4 = value };
        }

        public ILOpCodeConst(double value) : this(ConstType.Double)
        {
            _value = new ImmVal { R8 = value };
        }

        public void Emit(ILEmitter context)
        {
            switch (_type)
            {
                case ConstType.Int32:  context.Generator.EmitLdc_I4(_value.I4);           break;
                case ConstType.Int64:  context.Generator.Emit(OpCodes.Ldc_I8, _value.I8); break;
                case ConstType.Single: context.Generator.Emit(OpCodes.Ldc_R4, _value.R4); break;
                case ConstType.Double: context.Generator.Emit(OpCodes.Ldc_R8, _value.R8); break;
            }
        }
    }
}