1// Copyright 2019 The Marl Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#if defined(__powerpc64__)
16
17#define MARL_BUILD_ASM 1
18#include "osfiber_asm_ppc64.h"
19
20// void marl_fiber_swap(marl_fiber_context* from, const marl_fiber_context* to)
21// r3: from
22// r4: to
23.text
24.global marl_fiber_swap
25.align 4
26.type marl_fiber_swap @function
27marl_fiber_swap:
28
29    // Store non-volatile registers
30    std 1, MARL_REG_R1(3)
31    std 2, MARL_REG_R2(3)
32    std 13, MARL_REG_R13(3)
33    std 14, MARL_REG_R14(3)
34    std 15, MARL_REG_R15(3)
35    std 16, MARL_REG_R16(3)
36    std 17, MARL_REG_R17(3)
37    std 18, MARL_REG_R18(3)
38    std 19, MARL_REG_R19(3)
39    std 20, MARL_REG_R20(3)
40    std 21, MARL_REG_R21(3)
41    std 22, MARL_REG_R22(3)
42    std 23, MARL_REG_R23(3)
43    std 24, MARL_REG_R24(3)
44    std 25, MARL_REG_R25(3)
45    std 26, MARL_REG_R26(3)
46    std 27, MARL_REG_R27(3)
47    std 28, MARL_REG_R28(3)
48    std 29, MARL_REG_R29(3)
49    std 30, MARL_REG_R30(3)
50    std 31, MARL_REG_R31(3)
51
52    // Store special registers
53    mflr 5
54    std 5, MARL_REG_LR(3)
55    mfcr 5
56    std 5, MARL_REG_CCR(3)
57
58    // Store non-volatile floating point registers
59    stfd 14, MARL_REG_FPR14(3)
60    stfd 15, MARL_REG_FPR15(3)
61    stfd 16, MARL_REG_FPR16(3)
62    stfd 17, MARL_REG_FPR17(3)
63    stfd 18, MARL_REG_FPR18(3)
64    stfd 19, MARL_REG_FPR19(3)
65    stfd 20, MARL_REG_FPR20(3)
66    stfd 21, MARL_REG_FPR21(3)
67    stfd 22, MARL_REG_FPR22(3)
68    stfd 23, MARL_REG_FPR23(3)
69    stfd 24, MARL_REG_FPR24(3)
70    stfd 25, MARL_REG_FPR25(3)
71    stfd 26, MARL_REG_FPR26(3)
72    stfd 27, MARL_REG_FPR27(3)
73    stfd 28, MARL_REG_FPR28(3)
74    stfd 29, MARL_REG_FPR29(3)
75    stfd 30, MARL_REG_FPR30(3)
76    stfd 31, MARL_REG_FPR31(3)
77
78    // Store non-volatile altivec registers
79#ifdef __ALTIVEC__
80    li 5, MARL_REG_VMX
81    stvxl 20, 3, 5
82    addi 5, 5, 16
83    stvxl 21, 3, 5
84    addi 5, 5, 16
85    stvxl 22, 3, 5
86    addi 5, 5, 16
87    stvxl 23, 3, 5
88    addi 5, 5, 16
89    stvxl 24, 3, 5
90    addi 5, 5, 16
91    stvxl 25, 3, 5
92    addi 5, 5, 16
93    stvxl 26, 3, 5
94    addi 5, 5, 16
95    stvxl 27, 3, 5
96    addi 5, 5, 16
97    stvxl 28, 3, 5
98    addi 5, 5, 16
99    stvxl 29, 3, 5
100    addi 5, 5, 16
101    stvxl 30, 3, 5
102    addi 5, 5, 16
103    stvxl 31, 3, 5
104
105    mfvrsave 5
106    stw 5, MARL_REG_VRSAVE(3)
107#endif // __ALTIVEC__
108
109    // Load non-volatile registers
110    ld 1, MARL_REG_R1(4)
111    ld 2, MARL_REG_R2(4)
112    ld 13, MARL_REG_R13(4)
113    ld 14, MARL_REG_R14(4)
114    ld 15, MARL_REG_R15(4)
115    ld 16, MARL_REG_R16(4)
116    ld 17, MARL_REG_R17(4)
117    ld 18, MARL_REG_R18(4)
118    ld 19, MARL_REG_R19(4)
119    ld 20, MARL_REG_R20(4)
120    ld 21, MARL_REG_R21(4)
121    ld 22, MARL_REG_R22(4)
122    ld 23, MARL_REG_R23(4)
123    ld 24, MARL_REG_R24(4)
124    ld 25, MARL_REG_R25(4)
125    ld 26, MARL_REG_R26(4)
126    ld 27, MARL_REG_R27(4)
127    ld 28, MARL_REG_R28(4)
128    ld 29, MARL_REG_R29(4)
129    ld 30, MARL_REG_R30(4)
130    ld 31, MARL_REG_R31(4)
131
132    // Load non-volatile floating point registers
133    lfd 14, MARL_REG_FPR14(4)
134    lfd 15, MARL_REG_FPR15(4)
135    lfd 16, MARL_REG_FPR16(4)
136    lfd 17, MARL_REG_FPR17(4)
137    lfd 18, MARL_REG_FPR18(4)
138    lfd 19, MARL_REG_FPR19(4)
139    lfd 20, MARL_REG_FPR20(4)
140    lfd 21, MARL_REG_FPR21(4)
141    lfd 22, MARL_REG_FPR22(4)
142    lfd 23, MARL_REG_FPR23(4)
143    lfd 24, MARL_REG_FPR24(4)
144    lfd 25, MARL_REG_FPR25(4)
145    lfd 26, MARL_REG_FPR26(4)
146    lfd 27, MARL_REG_FPR27(4)
147    lfd 28, MARL_REG_FPR28(4)
148    lfd 29, MARL_REG_FPR29(4)
149    lfd 30, MARL_REG_FPR30(4)
150    lfd 31, MARL_REG_FPR31(4)
151
152    // Load non-volatile altivec registers
153#ifdef __ALTIVEC__
154    li 5, MARL_REG_VMX
155    lvxl 20, 4, 5
156    addi 5, 5, 16
157    lvxl 21, 4, 5
158    addi 5, 5, 16
159    lvxl 22, 4, 5
160    addi 5, 5, 16
161    lvxl 23, 4, 5
162    addi 5, 5, 16
163    lvxl 24, 4, 5
164    addi 5, 5, 16
165    lvxl 25, 4, 5
166    addi 5, 5, 16
167    lvxl 26, 4, 5
168    addi 5, 5, 16
169    lvxl 27, 4, 5
170    addi 5, 5, 16
171    lvxl 28, 4, 5
172    addi 5, 5, 16
173    lvxl 29, 4, 5
174    addi 5, 5, 16
175    lvxl 30, 4, 5
176    addi 5, 5, 16
177    lvxl 31, 4, 5
178
179    lwz 5, MARL_REG_VRSAVE(4)
180    mtvrsave 5
181#endif // __ALTIVEC__
182
183    // Load parameters and entrypoint
184    ld 12, MARL_REG_LR(4)
185    ld 3, MARL_REG_R3(4)
186    ld 4, MARL_REG_R4(4)
187    mtlr 12
188
189    // Branch to entrypoint
190    blr
191
192#endif // defined(__powerpc64__)
193