summaryrefslogtreecommitdiff
path: root/asmrun/mips.s
blob: 80de0d7001c9e1d4b76c548827b9a43310bfe225 (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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
/***********************************************************************/
/*                                                                     */
/*                           Objective Caml                            */
/*                                                                     */
/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
/*                                                                     */
/*  Copyright 1996 Institut National de Recherche en Informatique et   */
/*  en Automatique.  All rights reserved.  This file is distributed    */
/*  under the terms of the GNU Library General Public License.         */
/*                                                                     */
/***********************************************************************/

/* $Id$ */

/* Asm part of the runtime system, Mips processor, IRIX n32 conventions */

/* Allocation */

        .text

        .globl  caml_call_gc
        .ent    caml_call_gc

caml_call_gc:
    /* Reserve stack space for registers and saved $gp */
    /* 32 * 8 = 0x100 for float regs
       22 * 4 = 0x58  for integer regs
            8 = 0x8   for saved $gp ====> 0x160 total */
        subu    $sp, $sp, 0x160
    /* Reinit $gp */
        .cpsetup $25, 0x158, caml_call_gc
    /* Record return address */
        sw      $31, caml_last_return_address
    /* Record lowest stack address */
        addu    $24, $sp, 0x160
        sw      $24, caml_bottom_of_stack
    /* Save pointer to register array */
        addu    $24, $sp, 0x100
        sw      $24, caml_gc_regs
    /* Save current allocation pointer for debugging purposes */
        sw      $22, young_ptr
    /* Save the exception handler (if e.g. a sighandler raises) */
        sw      $30, caml_exception_pointer
    /* Save all regs used by the code generator on the stack */
        sw      $2, 2 * 4($24)
        sw      $3, 3 * 4($24)
        sw      $4, 4 * 4($24)
        sw      $5, 5 * 4($24)
        sw      $6, 6 * 4($24)
        sw      $7, 7 * 4($24)
        sw      $8, 8 * 4($24)
        sw      $9, 9 * 4($24)
        sw      $10, 10 * 4($24)
        sw      $11, 11 * 4($24)
        sw      $12, 12 * 4($24)
        sw      $13, 13 * 4($24)
        sw      $14, 14 * 4($24)
        sw      $15, 15 * 4($24)
        sw      $16, 16 * 4($24)
        sw      $17, 17 * 4($24)
        sw      $18, 18 * 4($24)
        sw      $19, 19 * 4($24)
        sw      $20, 20 * 4($24)
        sw      $21, 21 * 4($24)
        s.d     $f0, 0 * 8($sp)
        s.d     $f1, 1 * 8($sp)
        s.d     $f2, 2 * 8($sp)
        s.d     $f3, 3 * 8($sp)
        s.d     $f4, 4 * 8($sp)
        s.d     $f5, 5 * 8($sp)
        s.d     $f6, 6 * 8($sp)
        s.d     $f7, 7 * 8($sp)
        s.d     $f8, 8 * 8($sp)
        s.d     $f9, 9 * 8($sp)
        s.d     $f10, 10 * 8($sp)
        s.d     $f11, 11 * 8($sp)
        s.d     $f12, 12 * 8($sp)
        s.d     $f13, 13 * 8($sp)
        s.d     $f14, 14 * 8($sp)
        s.d     $f15, 15 * 8($sp)
        s.d     $f16, 16 * 8($sp)
        s.d     $f17, 17 * 8($sp)
        s.d     $f18, 18 * 8($sp)
        s.d     $f19, 19 * 8($sp)
        s.d     $f20, 20 * 8($sp)
        s.d     $f21, 21 * 8($sp)
        s.d     $f22, 22 * 8($sp)
        s.d     $f23, 23 * 8($sp)
        s.d     $f24, 24 * 8($sp)
        s.d     $f25, 25 * 8($sp)
        s.d     $f26, 26 * 8($sp)
        s.d     $f27, 27 * 8($sp)
        s.d     $f28, 28 * 8($sp)
        s.d     $f29, 29 * 8($sp)
        s.d     $f30, 30 * 8($sp)
        s.d     $f31, 31 * 8($sp)
    /* Call the garbage collector */
        jal     garbage_collection
    /* Restore all regs used by the code generator */
        addu    $24, $sp, 0x100
        lw      $2, 2 * 4($24)
        lw      $3, 3 * 4($24)
        lw      $4, 4 * 4($24)
        lw      $5, 5 * 4($24)
        lw      $6, 6 * 4($24)
        lw      $7, 7 * 4($24)
        lw      $8, 8 * 4($24)
        lw      $9, 9 * 4($24)
        lw      $10, 10 * 4($24)
        lw      $11, 11 * 4($24)
        lw      $12, 12 * 4($24)
        lw      $13, 13 * 4($24)
        lw      $14, 14 * 4($24)
        lw      $15, 15 * 4($24)
        lw      $16, 16 * 4($24)
        lw      $17, 17 * 4($24)
        lw      $18, 18 * 4($24)
        lw      $19, 19 * 4($24)
        lw      $20, 20 * 4($24)
        lw      $21, 21 * 4($24)
        l.d     $f0, 0 * 8($sp)
        l.d     $f1, 1 * 8($sp)
        l.d     $f2, 2 * 8($sp)
        l.d     $f3, 3 * 8($sp)
        l.d     $f4, 4 * 8($sp)
        l.d     $f5, 5 * 8($sp)
        l.d     $f6, 6 * 8($sp)
        l.d     $f7, 7 * 8($sp)
        l.d     $f8, 8 * 8($sp)
        l.d     $f9, 9 * 8($sp)
        l.d     $f10, 10 * 8($sp)
        l.d     $f11, 11 * 8($sp)
        l.d     $f12, 12 * 8($sp)
        l.d     $f13, 13 * 8($sp)
        l.d     $f14, 14 * 8($sp)
        l.d     $f15, 15 * 8($sp)
        l.d     $f16, 16 * 8($sp)
        l.d     $f17, 17 * 8($sp)
        l.d     $f18, 18 * 8($sp)
        l.d     $f19, 19 * 8($sp)
        l.d     $f20, 20 * 8($sp)
        l.d     $f21, 21 * 8($sp)
        l.d     $f22, 22 * 8($sp)
        l.d     $f23, 23 * 8($sp)
        l.d     $f24, 24 * 8($sp)
        l.d     $f25, 25 * 8($sp)
        l.d     $f26, 26 * 8($sp)
        l.d     $f27, 27 * 8($sp)
        l.d     $f28, 28 * 8($sp)
        l.d     $f29, 29 * 8($sp)
        l.d     $f30, 30 * 8($sp)
        l.d     $f31, 31 * 8($sp)
    /* Reload new allocation pointer and allocation limit */
        lw      $22, young_ptr
        lw      $23, young_limit
    /* Reload return address */
        lw      $31, caml_last_return_address
    /* Say that we are back into Caml code */
        sw      $0, caml_last_return_address
    /* Adjust return address to restart the allocation sequence */
        subu    $31, $31, 16
    /* Return */
        .cpreturn
        addu    $sp, $sp, 0x160
        j       $31

        .end    caml_call_gc

/* Call a C function from Caml */

        .globl  caml_c_call
        .ent    caml_c_call

caml_c_call:
    /* Function to call is in $24 */
    /* Set up $gp, saving caller's $gp in callee-save register $19 */
        .cpsetup $25, $19, caml_c_call
    /* Preload addresses of interesting global variables
       in callee-save registers */
        la      $16, caml_last_return_address
        la      $17, young_ptr
    /* Save return address, bottom of stack, alloc ptr, exn ptr */
        sw      $31, 0($16)     /* caml_last_return_address */
        sw      $sp, caml_bottom_of_stack
        sw      $22, 0($17)     /* young_ptr */
        sw      $30, caml_exception_pointer
    /* Call C function */
        move    $25, $24
        jal     $24
    /* Reload return address, alloc ptr, alloc limit */
        lw      $31, 0($16)     /* caml_last_return_address */
        lw      $22, 0($17)     /* young_ptr */
        lw      $23, young_limit /* young_limit */
    /* Zero caml_last_return_address, indicating we're back in Caml code */
        sw      $0, 0($16)      /* caml_last_return_address */
    /* Restore $gp and return */
        move    $gp, $19
        j       $31
        .end    caml_c_call

/* Start the Caml program */

        .globl  caml_start_program
        .globl  stray_exn_handler
        .ent    caml_start_program
caml_start_program:
    /* Reserve space for callee-save registers */
        subu    $sp, $sp, 0x90
    /* Setup $gp */
        .cpsetup $25, 0x80, caml_start_program
    /* Load in $24 the code address to call */
        la      $24, caml_program
    /* Code shared with callback* */
$103:
    /* Save return address */
        sd      $31, 0x88($sp)
    /* Save all callee-save registers */
        sd      $16, 0x0($sp)
        sd      $17, 0x8($sp)
        sd      $18, 0x10($sp)
        sd      $19, 0x18($sp)
        sd      $20, 0x20($sp)
        sd      $21, 0x28($sp)
        sd      $22, 0x30($sp)
        sd      $23, 0x38($sp)
        sd      $30, 0x40($sp)
        s.d     $f20, 0x48($sp)
        s.d     $f22, 0x50($sp)
        s.d     $f24, 0x58($sp)
        s.d     $f26, 0x60($sp)
        s.d     $f28, 0x68($sp)
        s.d     $f30, 0x70($sp)
    /* Set up a callback link on the stack. */
        subu    $sp, $sp, 16
        lw      $2, caml_bottom_of_stack
        sw      $2, 0($sp)
        lw      $3, caml_last_return_address
        sw      $3, 4($sp)
        lw      $4, caml_gc_regs
        sw      $4, 8($sp)
    /* Set up a trap frame to catch exceptions escaping the Caml code */
        subu    $sp, $sp, 16
        lw      $30, caml_exception_pointer
        sw      $30, 0($sp)
        la      $2, $105
        sw      $2, 4($sp)
        sw      $gp, 8($sp)
        move    $30, $sp
    /* Reload allocation pointers */
        lw      $22, young_ptr
        lw      $23, young_limit
    /* Say that we are back into Caml code */
        sw      $0, caml_last_return_address
    /* Call the Caml code */
        move    $25, $24
        jal     $24
$104:
    /* Pop the trap frame, restoring caml_exception_pointer */
        lw      $24, 0($sp)
        sw      $24, caml_exception_pointer
        addu    $sp, $sp, 16
$106:
    /* Pop the callback link, restoring the global variables */
        lw      $24, 0($sp)
        sw      $24, caml_bottom_of_stack
        lw      $25, 4($sp)
        sw      $25, caml_last_return_address
        lw      $24, 8($sp)
        sw      $24, caml_gc_regs
        addu    $sp, $sp, 16
    /* Update allocation pointer */
        sw      $22, young_ptr
    /* Reload callee-save registers and return */
        ld      $31, 0x88($sp)
        ld      $16, 0x0($sp)
        ld      $17, 0x8($sp)
        ld      $18, 0x10($sp)
        ld      $19, 0x18($sp)
        ld      $20, 0x20($sp)
        ld      $21, 0x28($sp)
        ld      $22, 0x30($sp)
        ld      $23, 0x38($sp)
        ld      $30, 0x40($sp)
        l.d     $f20, 0x48($sp)
        l.d     $f22, 0x50($sp)
        l.d     $f24, 0x58($sp)
        l.d     $f26, 0x60($sp)
        l.d     $f28, 0x68($sp)
        l.d     $f30, 0x70($sp)
        .cpreturn
        addu    $sp, $sp, 0x90
        j       $31

    /* The trap handler: encode exception bucket as an exception result
       and return it */
$105:
        sw      $30, caml_exception_pointer
        or      $2, $2, 2
        b       $106

        .end    caml_start_program

/* Raise an exception from C */

        .globl  raise_caml_exception
        .ent    raise_caml_exception
raise_caml_exception:
    /* Setup $gp, discarding caller's $gp (we won't return) */
        .cpsetup $25, $24, raise_caml_exception
    /* Branch to exn handler */
        move    $2, $4
        lw      $22, young_ptr
        lw      $23, young_limit
        lw      $sp, caml_exception_pointer
        lw      $30, 0($sp)
        lw      $24, 4($sp)
        lw      $gp, 8($sp)
        addu    $sp, $sp, 16
        j       $24

        .end    raise_caml_exception

/* Callback from C to Caml */

        .globl  callback_exn
        .ent    callback_exn
callback_exn:
        subu    $sp, $sp, 0x90
        .cpsetup $25, 0x80, callback_exn
    /* Initial shuffling of arguments */
        move    $9, $4          /* closure */
        move    $8, $5          /* argument */
        lw      $24, 0($4)      /* code pointer */
        b       $103
        .end    callback_exn

        .globl  callback2_exn
        .ent    callback2_exn
callback2_exn:
        subu    $sp, $sp, 0x90
        .cpsetup $25, 0x80, callback2_exn
    /* Initial shuffling of arguments */
        move    $10, $4                 /* closure */
        move    $8, $5                  /* first argument */
        move    $9, $6                  /* second argument */
        la      $24, caml_apply2        /* code pointer */
        b       $103

        .end    callback2_exn

        .globl  callback3_exn
        .ent    callback3_exn
callback3_exn:
        subu    $sp, $sp, 0x90
        .cpsetup $25, 0x80, callback3_exn
    /* Initial shuffling of arguments */
        move    $11, $4                 /* closure */
        move    $8, $5                  /* first argument */
        move    $9, $6                  /* second argument */
        move    $10, $7                 /* third argument */
        la      $24, caml_apply3        /* code pointer */
        b       $103

        .end    callback3

/* Glue code to call array_bound_error */

        .globl  caml_array_bound_error
        .ent    caml_array_bound_error

caml_array_bound_error:
    /* Setup $gp, discarding caller's $gp (we won't return) */
        .cpsetup $25, $24, caml_array_bound_error
        la      $24, array_bound_error
        jal     caml_c_call             /* never returns */

        .end    caml_array_bound_error

        .rdata
        .globl  system_frametable
system_frametable:
        .word   1               /* one descriptor */
        .word   $104            /* return address into callback */
        .half   -1              /* negative frame size => use callback link */
        .half   0               /* no roots here */