summaryrefslogtreecommitdiff
path: root/emu/Linux/asm-arm.S
blob: d13bcd0e832f0e5a24d2e3417366e8b190bbe957 (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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
	.file	"asm-Linux-arm.S"
#include "syscall.h"
	.text

/*
 * void executeonnewstack(void *tos, void (*tramp)(void *arg), void *arg)
 */

        .align  2
        .global executeonnewstack
        .type   executeonnewstack, %function
executeonnewstack:
        @ args = 0, pretend = 0, frame = 12
        @ frame_needed = 1, uses_anonymous_args = 0
        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     sp, sp, #12
        str     r0, [fp, #-16] /* store tos */
        str     r1, [fp, #-20] /* store tramp */
        str     r2, [fp, #-24] /* store arg */
        ldr     r0, [fp, #-24] /* get arg */
        ldr     r2, [fp, #-16] /* get tos */
        mov     sp, r2         /* set new stack */
        mov     lr, pc
        blx     r1             /* call tramp*/

        /* if we return here, tramp didn't do it's job */
        swi     SYS_exit
        ldmea   fp, {fp, sp, pc}
        .size   executeonnewstack, .-executeonnewstack

/*
 * void unlockandexit(int *key)
 *
 * NB: the return status may be garbaged if the stack is reused
 *	between the unlock and the system call, but this should
 *	not matter since no task is waiting for the result
 */

        .align  2
        .global unlockandexit
        .type   unlockandexit, %function
unlockandexit:
        @ args = 0, pretend = 0, frame = 4
        @ frame_needed = 1, uses_anonymous_args = 0
        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     sp, sp, #4
        mov     r1, #0
        str     r1, [r0]
        swi     SYS_exit
        ldmea   fp, {fp, sp, pc}
        .size   unlockandexit, .-unlockandexit

/*
 * ulong umult(ulong m1, ulong m2, ulong *hi)
 */

        .align  2
        .global umult
        .type   umult, %function
umult:
        @ args = 0, pretend = 0, frame = 12
        @ frame_needed = 1, uses_anonymous_args = 0
        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     sp, sp, #12
        str     r0, [fp, #-16]
        str     r1, [fp, #-20]
        str     r2, [fp, #-24]
        ldr     r1, [fp, #-16]
        ldr     r2, [fp, #-20]
        umull   r0, r3, r1, r2
        ldr     r1, [fp, #-24]
        str     r3, [r1]
        ldmea   fp, {fp, sp, pc}
        .size   umult, .-umult

/*
 *  void		FPsave(void*);
 */

        .align  2
        .global FPsave
        .type   FPsave, %function
FPsave:
        @ args = 0, pretend = 0, frame = 4
        @ frame_needed = 1, uses_anonymous_args = 0
        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     sp, sp, #4
        str     r0, [fp, #-16]
        ldmea   fp, {fp, sp, pc}
        .size   FPsave, .-FPsave

/*
 * void		FPrestore(void*);
 */
        .align  2
        .global FPrestore
        .type   FPrestore, %function
FPrestore:
        @ args = 0, pretend = 0, frame = 4
        @ frame_needed = 1, uses_anonymous_args = 0
        mov     ip, sp
        stmfd   sp!, {fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     sp, sp, #4
        str     r0, [fp, #-16]
        ldmea   fp, {fp, sp, pc}
        .size   FPrestore, .-FPrestore

/*
 * ulong _tas(ulong*);
 */
	.align	2
	.global	_tas
	.type	_tas, %function
_tas:
	@ args = 0, pretend = 0, frame = 0
	@ frame_needed = 0, uses_anonymous_args = 0
	@ link register save eliminated.
	@ lr needed for prologue
	mov	r3, #1
	mov	r1, r0
	swp	r0, r3, [r1]
	mov	pc, lr
	.size	_tas, .-_tas