@@ -56,7 +56,71 @@ impl ops::IndexMut<gimli::Register> for Context {
5656 }
5757}
5858
59- macro_rules! ctx_helper {
59+ macro_rules! save_regs {
60+ ( gp$( , $fp: ident) ?) => {
61+ core:: arch:: naked_asm!(
62+ maybe_cfi!( ".cfi_startproc" ) ,
63+ "
64+ move $r12, $r3
65+ addi.d $r3, $r3, -0x210
66+ " ,
67+ maybe_cfi!( ".cfi_def_cfa_offset 0x210" ) ,
68+ "
69+ st.d $r1, $r3, 0x200
70+ " ,
71+ maybe_cfi!( ".cfi_offset 1, -16" ) , // ra
72+ helper!( save_gp) ,
73+ save_regs!( maybe_save_fp( $( $fp) ?) ) ,
74+ "
75+ move $r12, $r4
76+ move $r4, $r3 // argument a0 pointing the ctx base
77+
78+ addi.d $r13, $r3, 0x210
79+ st.d $r13, $r3, 0x18 // save sp
80+
81+ jirl $r1, $r12, 0 // call f
82+
83+ ld.d $r1, $r3, 0x200
84+ addi.d $r3, $r3, 0x210 // restore ra and sp
85+ " ,
86+ maybe_cfi!( ".cfi_def_cfa_offset 0" ) ,
87+ maybe_cfi!( ".cfi_restore 1" ) , // ra
88+ "
89+ ret
90+ " ,
91+ maybe_cfi!( ".cfi_endproc" ) ,
92+ )
93+ } ;
94+ ( maybe_save_fp( fp) ) => {
95+ helper!( save_fp)
96+ } ;
97+ ( maybe_save_fp( ) ) => {
98+ ""
99+ } ;
100+ }
101+
102+ macro_rules! restore_regs {
103+ ( $ctx: expr, gp$( , $fp: ident) ?) => {
104+ core:: arch:: asm!(
105+ restore_regs!( maybe_restore_fp( $( $fp) ?) ) ,
106+ helper!( restore_gp) ,
107+ "
108+ ld.d $r4, $r4, 0x20
109+ ret
110+ " ,
111+ in( "$r4" ) $ctx,
112+ options( noreturn)
113+ )
114+ } ;
115+ ( maybe_restore_fp( fp) ) => {
116+ helper!( restore_fp)
117+ } ;
118+ ( maybe_restore_fp( ) ) => {
119+ ""
120+ } ;
121+ }
122+
123+ macro_rules! helper {
60124 // see https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html for ABI conventions
61125 ( save_gp) => {
62126 "
@@ -94,7 +158,7 @@ macro_rules! ctx_helper {
94158 ld.d $r1, $r4, 0x8 // ra
95159 ld.d $r2, $r4, 0x10 // tp
96160 ld.d $r3, $r4, 0x18 // sp
97- // a0 is restored later
161+ // r4(a0) is restored later
98162 ld.d $r5, $r4, 0x28 // a1
99163 ld.d $r6, $r4, 0x30 // a2
100164 ld.d $r7, $r4, 0x38 // a3
@@ -166,52 +230,18 @@ macro_rules! ctx_helper {
166230pub extern "C-unwind" fn save_context ( f : extern "C" fn ( & mut Context , * mut ( ) ) , ptr : * mut ( ) ) {
167231 #[ allow( unused_unsafe) ]
168232 unsafe {
169- core:: arch:: naked_asm!(
170- maybe_cfi!( ".cfi_startproc" ) ,
171- "
172- move $r12, $r3
173- addi.d $r3, $r3, -0x210
174- " ,
175- maybe_cfi!( ".cfi_def_cfa_offset 0x210" ) ,
176- "
177- st.d $r1, $r3, 0x200
178- " ,
179- maybe_cfi!( ".cfi_offset 1, -16" ) , // ra
180- ctx_helper!( save_gp) ,
181- ctx_helper!( save_fp) ,
182- "
183- move $r12, $r4
184- move $r4, $r3 // argument a0 pointing the ctx base
185-
186- addi.d $r13, $r3, 0x210
187- st.d $r13, $r3, 0x18 // save sp
188-
189- jirl $r1, $r12, 0 // call f
190-
191- ld.d $r1, $r3, 0x200
192- addi.d $r3, $r3, 0x210 // restore ra and sp
193- " ,
194- maybe_cfi!( ".cfi_def_cfa_offset 0" ) ,
195- maybe_cfi!( ".cfi_restore 1" ) , // ra
196- "
197- ret
198- " ,
199- maybe_cfi!( ".cfi_endproc" ) ,
200- )
233+ #[ cfg( target_feature = "d" ) ]
234+ save_regs ! ( gp, fp) ;
235+ #[ cfg( not( target_feature = "d" ) ) ]
236+ save_regs ! ( gp) ;
201237 }
202238}
203239
204240pub unsafe fn restore_context ( ctx : & Context ) -> ! {
205241 unsafe {
206- core:: arch:: asm!(
207- ctx_helper!( restore_gp) ,
208- ctx_helper!( restore_fp) ,
209- "
210- ld.d $r4, $r4, 0x20
211- ret
212- " ,
213- in( "$r4" ) ctx,
214- options( noreturn)
215- ) ;
242+ #[ cfg( target_feature = "d" ) ]
243+ restore_regs ! ( ctx, gp, fp) ;
244+ #[ cfg( not( target_feature = "d" ) ) ]
245+ restore_regs ! ( ctx, gp) ;
216246 }
217247}
0 commit comments