aboutsummaryrefslogtreecommitdiff
path: root/src/ARMeilleure/CodeGen/Arm64/CallingConvention.cs
blob: a487c2ed33ede9e9414b824df5f535462ec60a48 (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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
using System;

namespace ARMeilleure.CodeGen.Arm64
{
    static class CallingConvention
    {
        private const int RegistersMask = unchecked((int)0xffffffff);

        // Some of those register have specific roles and can't be used as general purpose registers.
        // X18 - Reserved for platform specific usage.
        // X29 - Frame pointer.
        // X30 - Return address.
        // X31 - Not an actual register, in some cases maps to SP, and in others to ZR.
        private const int ReservedRegsMask = (1 << CodeGenCommon.ReservedRegister) | (1 << 18) | (1 << 29) | (1 << 30) | (1 << 31);

        public static int GetIntAvailableRegisters()
        {
            return RegistersMask & ~ReservedRegsMask;
        }

        public static int GetVecAvailableRegisters()
        {
            return RegistersMask;
        }

        public static int GetIntCallerSavedRegisters()
        {
            return (GetIntCalleeSavedRegisters() ^ RegistersMask) & ~ReservedRegsMask;
        }

        public static int GetFpCallerSavedRegisters()
        {
            return GetFpCalleeSavedRegisters() ^ RegistersMask;
        }

        public static int GetVecCallerSavedRegisters()
        {
            return GetVecCalleeSavedRegisters() ^ RegistersMask;
        }

        public static int GetIntCalleeSavedRegisters()
        {
            return 0x1ff80000; // X19 to X28
        }

        public static int GetFpCalleeSavedRegisters()
        {
            return 0xff00; // D8 to D15
        }

        public static int GetVecCalleeSavedRegisters()
        {
            return 0;
        }

        public static int GetArgumentsOnRegsCount()
        {
            return 8;
        }

        public static int GetIntArgumentRegister(int index)
        {
            if ((uint)index < (uint)GetArgumentsOnRegsCount())
            {
                return index;
            }

            throw new ArgumentOutOfRangeException(nameof(index));
        }

        public static int GetVecArgumentRegister(int index)
        {
            if ((uint)index < (uint)GetArgumentsOnRegsCount())
            {
                return index;
            }

            throw new ArgumentOutOfRangeException(nameof(index));
        }

        public static int GetIntReturnRegister()
        {
            return 0;
        }

        public static int GetIntReturnRegisterHigh()
        {
            return 1;
        }

        public static int GetVecReturnRegister()
        {
            return 0;
        }
    }
}