OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgcc/] [config/] [mips/] [mips16.S] - Blame information for rev 818

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 734 jeremybenn
/* mips16 floating point support code
2
   Copyright (C) 1996, 1997, 1998, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
   Contributed by Cygnus Support
5
 
6
This file is free software; you can redistribute it and/or modify it
7
under the terms of the GNU General Public License as published by the
8
Free Software Foundation; either version 3, or (at your option) any
9
later version.
10
 
11
This file is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
Under Section 7 of GPL version 3, you are granted additional
17
permissions described in the GCC Runtime Library Exception, version
18
3.1, as published by the Free Software Foundation.
19
 
20
You should have received a copy of the GNU General Public License and
21
a copy of the GCC Runtime Library Exception along with this program;
22
see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23
.  */
24
 
25
/* This file contains mips16 floating point support functions.  These
26
   functions are called by mips16 code to handle floating point when
27
   -msoft-float is not used.  They accept the arguments and return
28
   values using the soft-float calling convention, but do the actual
29
   operation using the hard floating point instructions.  */
30
 
31
#if defined _MIPS_SIM && (_MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIO64)
32
 
33
/* This file contains 32-bit assembly code.  */
34
        .set nomips16
35
 
36
/* Start a function.  */
37
 
38
#define STARTFN(NAME) .globl NAME; .ent NAME; NAME:
39
 
40
/* Finish a function.  */
41
 
42
#define ENDFN(NAME) .end NAME
43
 
44
/* ARG1
45
        The FPR that holds the first floating-point argument.
46
 
47
   ARG2
48
        The FPR that holds the second floating-point argument.
49
 
50
   RET
51
        The FPR that holds a floating-point return value.  */
52
 
53
#define RET $f0
54
#define ARG1 $f12
55
#ifdef __mips64
56
#define ARG2 $f13
57
#else
58
#define ARG2 $f14
59
#endif
60
 
61
/* Set 64-bit register GPR so that its high 32 bits contain HIGH_FPR
62
   and so that its low 32 bits contain LOW_FPR.  */
63
#define MERGE_GPRf(GPR, HIGH_FPR, LOW_FPR)      \
64
        .set    noat;                           \
65
        mfc1    $1, LOW_FPR;                    \
66
        mfc1    GPR, HIGH_FPR;                  \
67
        dsll    $1, $1, 32;                     \
68
        dsll    GPR, GPR, 32;                   \
69
        dsrl    $1, $1, 32;                     \
70
        or      GPR, GPR, $1;                   \
71
        .set    at
72
 
73
/* Move the high 32 bits of GPR to HIGH_FPR and the low 32 bits of
74
   GPR to LOW_FPR.  */
75
#define MERGE_GPRt(GPR, HIGH_FPR, LOW_FPR)      \
76
        .set    noat;                           \
77
        dsrl    $1, GPR, 32;                    \
78
        mtc1    GPR, LOW_FPR;                   \
79
        mtc1    $1, HIGH_FPR;                   \
80
        .set    at
81
 
82
/* Jump to T, and use "OPCODE, OP2" to implement a delayed move.  */
83
#define DELAYt(T, OPCODE, OP2)                  \
84
        .set    noreorder;                      \
85
        jr      T;                              \
86
        OPCODE, OP2;                            \
87
        .set    reorder
88
 
89
/* Use "OPCODE. OP2" and jump to T.  */
90
#define DELAYf(T, OPCODE, OP2) OPCODE, OP2; jr T
91
 
92
/* MOVE_SF_BYTE0(D)
93
        Move the first single-precision floating-point argument between
94
        GPRs and FPRs.
95
 
96
   MOVE_SI_BYTE0(D)
97
        Likewise the first single-precision integer argument.
98
 
99
   MOVE_SF_BYTE4(D)
100
        Move the second single-precision floating-point argument between
101
        GPRs and FPRs, given that the first argument occupies 4 bytes.
102
 
103
   MOVE_SF_BYTE8(D)
104
        Move the second single-precision floating-point argument between
105
        GPRs and FPRs, given that the first argument occupies 8 bytes.
106
 
107
   MOVE_DF_BYTE0(D)
108
        Move the first double-precision floating-point argument between
109
        GPRs and FPRs.
110
 
111
   MOVE_DF_BYTE8(D)
112
        Likewise the second double-precision floating-point argument.
113
 
114
   MOVE_SF_RET(D, T)
115
        Likewise a single-precision floating-point return value,
116
        then jump to T.
117
 
118
   MOVE_SC_RET(D, T)
119
        Likewise a complex single-precision floating-point return value.
120
 
121
   MOVE_DF_RET(D, T)
122
        Likewise a double-precision floating-point return value.
123
 
124
   MOVE_DC_RET(D, T)
125
        Likewise a complex double-precision floating-point return value.
126
 
127
   MOVE_SI_RET(D, T)
128
        Likewise a single-precision integer return value.
129
 
130
   The D argument is "t" to move to FPRs and "f" to move from FPRs.
131
   The return macros may assume that the target of the jump does not
132
   use a floating-point register.  */
133
 
134
#define MOVE_SF_RET(D, T) DELAY##D (T, m##D##c1 $2,$f0)
135
#define MOVE_SI_RET(D, T) DELAY##D (T, m##D##c1 $2,$f0)
136
 
137
#if defined(__mips64) && defined(__MIPSEB__)
138
#define MOVE_SC_RET(D, T) MERGE_GPR##D ($2, $f0, $f1); jr T
139
#elif defined(__mips64)
140
/* The high 32 bits of $2 correspond to the second word in memory;
141
   i.e. the imaginary part.  */
142
#define MOVE_SC_RET(D, T) MERGE_GPR##D ($2, $f1, $f0); jr T
143
#elif __mips_fpr == 64
144
#define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f1)
145
#else
146
#define MOVE_SC_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f2)
147
#endif
148
 
149
#if defined(__mips64)
150
#define MOVE_SF_BYTE0(D) m##D##c1 $4,$f12
151
#define MOVE_SF_BYTE4(D) m##D##c1 $5,$f13
152
#define MOVE_SF_BYTE8(D) m##D##c1 $5,$f13
153
#else
154
#define MOVE_SF_BYTE0(D) m##D##c1 $4,$f12
155
#define MOVE_SF_BYTE4(D) m##D##c1 $5,$f14
156
#define MOVE_SF_BYTE8(D) m##D##c1 $6,$f14
157
#endif
158
#define MOVE_SI_BYTE0(D) MOVE_SF_BYTE0(D)
159
 
160
#if defined(__mips64)
161
#define MOVE_DF_BYTE0(D) dm##D##c1 $4,$f12
162
#define MOVE_DF_BYTE8(D) dm##D##c1 $5,$f13
163
#define MOVE_DF_RET(D, T) DELAY##D (T, dm##D##c1 $2,$f0)
164
#define MOVE_DC_RET(D, T) dm##D##c1 $3,$f1; MOVE_DF_RET (D, T)
165
#elif __mips_fpr == 64 && defined(__MIPSEB__)
166
#define MOVE_DF_BYTE0(D) m##D##c1 $5,$f12; m##D##hc1 $4,$f12
167
#define MOVE_DF_BYTE8(D) m##D##c1 $7,$f14; m##D##hc1 $6,$f14
168
#define MOVE_DF_RET(D, T) m##D##c1 $3,$f0; DELAY##D (T, m##D##hc1 $2,$f0)
169
#define MOVE_DC_RET(D, T) m##D##c1 $5,$f1; m##D##hc1 $4,$f1; MOVE_DF_RET (D, T)
170
#elif __mips_fpr == 64
171
#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f12; m##D##hc1 $5,$f12
172
#define MOVE_DF_BYTE8(D) m##D##c1 $6,$f14; m##D##hc1 $7,$f14
173
#define MOVE_DF_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##hc1 $3,$f0)
174
#define MOVE_DC_RET(D, T) m##D##c1 $4,$f1; m##D##hc1 $5,$f1; MOVE_DF_RET (D, T)
175
#elif defined(__MIPSEB__)
176
/* FPRs are little-endian.  */
177
#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f13; m##D##c1 $5,$f12
178
#define MOVE_DF_BYTE8(D) m##D##c1 $6,$f15; m##D##c1 $7,$f14
179
#define MOVE_DF_RET(D, T) m##D##c1 $2,$f1; DELAY##D (T, m##D##c1 $3,$f0)
180
#define MOVE_DC_RET(D, T) m##D##c1 $4,$f3; m##D##c1 $5,$f2; MOVE_DF_RET (D, T)
181
#else
182
#define MOVE_DF_BYTE0(D) m##D##c1 $4,$f12; m##D##c1 $5,$f13
183
#define MOVE_DF_BYTE8(D) m##D##c1 $6,$f14; m##D##c1 $7,$f15
184
#define MOVE_DF_RET(D, T) m##D##c1 $2,$f0; DELAY##D (T, m##D##c1 $3,$f1)
185
#define MOVE_DC_RET(D, T) m##D##c1 $4,$f2; m##D##c1 $5,$f3; MOVE_DF_RET (D, T)
186
#endif
187
 
188
/* Single-precision math.  */
189
 
190
/* Define a function NAME that loads two single-precision values,
191
   performs FPU operation OPCODE on them, and returns the single-
192
   precision result.  */
193
 
194
#define OPSF3(NAME, OPCODE)     \
195
STARTFN (NAME);                 \
196
        MOVE_SF_BYTE0 (t);      \
197
        MOVE_SF_BYTE4 (t);      \
198
        OPCODE  RET,ARG1,ARG2;  \
199
        MOVE_SF_RET (f, $31);   \
200
        ENDFN (NAME)
201
 
202
#ifdef L_m16addsf3
203
OPSF3 (__mips16_addsf3, add.s)
204
#endif
205
#ifdef L_m16subsf3
206
OPSF3 (__mips16_subsf3, sub.s)
207
#endif
208
#ifdef L_m16mulsf3
209
OPSF3 (__mips16_mulsf3, mul.s)
210
#endif
211
#ifdef L_m16divsf3
212
OPSF3 (__mips16_divsf3, div.s)
213
#endif
214
 
215
/* Define a function NAME that loads a single-precision value,
216
   performs FPU operation OPCODE on it, and returns the single-
217
   precision result.  */
218
 
219
#define OPSF2(NAME, OPCODE)     \
220
STARTFN (NAME);                 \
221
        MOVE_SF_BYTE0 (t);      \
222
        OPCODE  RET,ARG1;       \
223
        MOVE_SF_RET (f, $31);   \
224
        ENDFN (NAME)
225
 
226
#ifdef L_m16negsf2
227
OPSF2 (__mips16_negsf2, neg.s)
228
#endif
229
#ifdef L_m16abssf2
230
OPSF2 (__mips16_abssf2, abs.s)
231
#endif
232
 
233
/* Single-precision comparisons.  */
234
 
235
/* Define a function NAME that loads two single-precision values,
236
   performs floating point comparison OPCODE, and returns TRUE or
237
   FALSE depending on the result.  */
238
 
239
#define CMPSF(NAME, OPCODE, TRUE, FALSE)        \
240
STARTFN (NAME);                                 \
241
        MOVE_SF_BYTE0 (t);                      \
242
        MOVE_SF_BYTE4 (t);                      \
243
        OPCODE  ARG1,ARG2;                      \
244
        li      $2,TRUE;                        \
245
        bc1t    1f;                             \
246
        li      $2,FALSE;                       \
247
1:;                                             \
248
        j       $31;                            \
249
        ENDFN (NAME)
250
 
251
/* Like CMPSF, but reverse the comparison operands.  */
252
 
253
#define REVCMPSF(NAME, OPCODE, TRUE, FALSE)     \
254
STARTFN (NAME);                                 \
255
        MOVE_SF_BYTE0 (t);                      \
256
        MOVE_SF_BYTE4 (t);                      \
257
        OPCODE  ARG2,ARG1;                      \
258
        li      $2,TRUE;                        \
259
        bc1t    1f;                             \
260
        li      $2,FALSE;                       \
261
1:;                                             \
262
        j       $31;                            \
263
        ENDFN (NAME)
264
 
265
#ifdef L_m16eqsf2
266
CMPSF (__mips16_eqsf2, c.eq.s, 0, 1)
267
#endif
268
#ifdef L_m16nesf2
269
CMPSF (__mips16_nesf2, c.eq.s, 0, 1)
270
#endif
271
#ifdef L_m16gtsf2
272
REVCMPSF (__mips16_gtsf2, c.lt.s, 1, 0)
273
#endif
274
#ifdef L_m16gesf2
275
REVCMPSF (__mips16_gesf2, c.le.s, 0, -1)
276
#endif
277
#ifdef L_m16lesf2
278
CMPSF (__mips16_lesf2, c.le.s, 0, 1)
279
#endif
280
#ifdef L_m16ltsf2
281
CMPSF (__mips16_ltsf2, c.lt.s, -1, 0)
282
#endif
283
#ifdef L_m16unordsf2
284
CMPSF(__mips16_unordsf2, c.un.s, 1, 0)
285
#endif
286
 
287
 
288
/* Single-precision conversions.  */
289
 
290
#ifdef L_m16fltsisf
291
STARTFN (__mips16_floatsisf)
292
        MOVE_SF_BYTE0 (t)
293
        cvt.s.w RET,ARG1
294
        MOVE_SF_RET (f, $31)
295
        ENDFN (__mips16_floatsisf)
296
#endif
297
 
298
#ifdef L_m16fltunsisf
299
STARTFN (__mips16_floatunsisf)
300
        .set    noreorder
301
        bltz    $4,1f
302
        MOVE_SF_BYTE0 (t)
303
        .set    reorder
304
        cvt.s.w RET,ARG1
305
        MOVE_SF_RET (f, $31)
306
1:
307
        and     $2,$4,1
308
        srl     $3,$4,1
309
        or      $2,$2,$3
310
        mtc1    $2,RET
311
        cvt.s.w RET,RET
312
        add.s   RET,RET,RET
313
        MOVE_SF_RET (f, $31)
314
        ENDFN (__mips16_floatunsisf)
315
#endif
316
 
317
#ifdef L_m16fix_truncsfsi
318
STARTFN (__mips16_fix_truncsfsi)
319
        MOVE_SF_BYTE0 (t)
320
        trunc.w.s RET,ARG1,$4
321
        MOVE_SI_RET (f, $31)
322
        ENDFN (__mips16_fix_truncsfsi)
323
#endif
324
 
325
#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
326
 
327
/* Double-precision math.  */
328
 
329
/* Define a function NAME that loads two double-precision values,
330
   performs FPU operation OPCODE on them, and returns the double-
331
   precision result.  */
332
 
333
#define OPDF3(NAME, OPCODE)     \
334
STARTFN (NAME);                 \
335
        MOVE_DF_BYTE0 (t);      \
336
        MOVE_DF_BYTE8 (t);      \
337
        OPCODE RET,ARG1,ARG2;   \
338
        MOVE_DF_RET (f, $31);   \
339
        ENDFN (NAME)
340
 
341
#ifdef L_m16adddf3
342
OPDF3 (__mips16_adddf3, add.d)
343
#endif
344
#ifdef L_m16subdf3
345
OPDF3 (__mips16_subdf3, sub.d)
346
#endif
347
#ifdef L_m16muldf3
348
OPDF3 (__mips16_muldf3, mul.d)
349
#endif
350
#ifdef L_m16divdf3
351
OPDF3 (__mips16_divdf3, div.d)
352
#endif
353
 
354
/* Define a function NAME that loads a double-precision value,
355
   performs FPU operation OPCODE on it, and returns the double-
356
   precision result.  */
357
 
358
#define OPDF2(NAME, OPCODE)     \
359
STARTFN (NAME);                 \
360
        MOVE_DF_BYTE0 (t);      \
361
        OPCODE RET,ARG1;        \
362
        MOVE_DF_RET (f, $31);   \
363
        ENDFN (NAME)
364
 
365
#ifdef L_m16negdf2
366
OPDF2 (__mips16_negdf2, neg.d)
367
#endif
368
#ifdef L_m16absdf2
369
OPDF2 (__mips16_absdf2, abs.d)
370
#endif
371
 
372
/* Conversions between single and double precision.  */
373
 
374
#ifdef L_m16extsfdf2
375
STARTFN (__mips16_extendsfdf2)
376
        MOVE_SF_BYTE0 (t)
377
        cvt.d.s RET,ARG1
378
        MOVE_DF_RET (f, $31)
379
        ENDFN (__mips16_extendsfdf2)
380
#endif
381
 
382
#ifdef L_m16trdfsf2
383
STARTFN (__mips16_truncdfsf2)
384
        MOVE_DF_BYTE0 (t)
385
        cvt.s.d RET,ARG1
386
        MOVE_SF_RET (f, $31)
387
        ENDFN (__mips16_truncdfsf2)
388
#endif
389
 
390
/* Double-precision comparisons.  */
391
 
392
/* Define a function NAME that loads two double-precision values,
393
   performs floating point comparison OPCODE, and returns TRUE or
394
   FALSE depending on the result.  */
395
 
396
#define CMPDF(NAME, OPCODE, TRUE, FALSE)        \
397
STARTFN (NAME);                                 \
398
        MOVE_DF_BYTE0 (t);                      \
399
        MOVE_DF_BYTE8 (t);                      \
400
        OPCODE  ARG1,ARG2;                      \
401
        li      $2,TRUE;                        \
402
        bc1t    1f;                             \
403
        li      $2,FALSE;                       \
404
1:;                                             \
405
        j       $31;                            \
406
        ENDFN (NAME)
407
 
408
/* Like CMPDF, but reverse the comparison operands.  */
409
 
410
#define REVCMPDF(NAME, OPCODE, TRUE, FALSE)     \
411
STARTFN (NAME);                                 \
412
        MOVE_DF_BYTE0 (t);                      \
413
        MOVE_DF_BYTE8 (t);                      \
414
        OPCODE  ARG2,ARG1;                      \
415
        li      $2,TRUE;                        \
416
        bc1t    1f;                             \
417
        li      $2,FALSE;                       \
418
1:;                                             \
419
        j       $31;                            \
420
        ENDFN (NAME)
421
 
422
#ifdef L_m16eqdf2
423
CMPDF (__mips16_eqdf2, c.eq.d, 0, 1)
424
#endif
425
#ifdef L_m16nedf2
426
CMPDF (__mips16_nedf2, c.eq.d, 0, 1)
427
#endif
428
#ifdef L_m16gtdf2
429
REVCMPDF (__mips16_gtdf2, c.lt.d, 1, 0)
430
#endif
431
#ifdef L_m16gedf2
432
REVCMPDF (__mips16_gedf2, c.le.d, 0, -1)
433
#endif
434
#ifdef L_m16ledf2
435
CMPDF (__mips16_ledf2, c.le.d, 0, 1)
436
#endif
437
#ifdef L_m16ltdf2
438
CMPDF (__mips16_ltdf2, c.lt.d, -1, 0)
439
#endif
440
#ifdef L_m16unorddf2
441
CMPDF(__mips16_unorddf2, c.un.d, 1, 0)
442
#endif
443
 
444
/* Double-precision conversions.  */
445
 
446
#ifdef L_m16fltsidf
447
STARTFN (__mips16_floatsidf)
448
        MOVE_SI_BYTE0 (t)
449
        cvt.d.w RET,ARG1
450
        MOVE_DF_RET (f, $31)
451
        ENDFN (__mips16_floatsidf)
452
#endif
453
 
454
#ifdef L_m16fltunsidf
455
STARTFN (__mips16_floatunsidf)
456
        MOVE_SI_BYTE0 (t)
457
        cvt.d.w RET,ARG1
458
        bgez    $4,1f
459
        li.d    ARG1, 4.294967296e+9
460
        add.d   RET, RET, ARG1
461
1:      MOVE_DF_RET (f, $31)
462
        ENDFN (__mips16_floatunsidf)
463
#endif
464
 
465
#ifdef L_m16fix_truncdfsi
466
STARTFN (__mips16_fix_truncdfsi)
467
        MOVE_DF_BYTE0 (t)
468
        trunc.w.d RET,ARG1,$4
469
        MOVE_SI_RET (f, $31)
470
        ENDFN (__mips16_fix_truncdfsi)
471
#endif
472
#endif /* !__mips_single_float */
473
 
474
/* Define a function NAME that moves a return value of mode MODE from
475
   FPRs to GPRs.  */
476
 
477
#define RET_FUNCTION(NAME, MODE)        \
478
STARTFN (NAME);                         \
479
        MOVE_##MODE##_RET (t, $31);     \
480
        ENDFN (NAME)
481
 
482
#ifdef L_m16retsf
483
RET_FUNCTION (__mips16_ret_sf, SF)
484
#endif
485
 
486
#ifdef L_m16retsc
487
RET_FUNCTION (__mips16_ret_sc, SC)
488
#endif
489
 
490
#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
491
#ifdef L_m16retdf
492
RET_FUNCTION (__mips16_ret_df, DF)
493
#endif
494
 
495
#ifdef L_m16retdc
496
RET_FUNCTION (__mips16_ret_dc, DC)
497
#endif
498
#endif /* !__mips_single_float */
499
 
500
/* STUB_ARGS_X copies the arguments from GPRs to FPRs for argument
501
   code X.  X is calculated as ARG1 + ARG2 * 4, where ARG1 and ARG2
502
   classify the first and second arguments as follows:
503
 
504
        1: a single-precision argument
505
        2: a double-precision argument
506
        0: no argument, or not one of the above.  */
507
 
508
#define STUB_ARGS_0                                             /* () */
509
#define STUB_ARGS_1 MOVE_SF_BYTE0 (t)                           /* (sf) */
510
#define STUB_ARGS_5 MOVE_SF_BYTE0 (t); MOVE_SF_BYTE4 (t)        /* (sf, sf) */
511
#define STUB_ARGS_9 MOVE_SF_BYTE0 (t); MOVE_DF_BYTE8 (t)        /* (sf, df) */
512
#define STUB_ARGS_2 MOVE_DF_BYTE0 (t)                           /* (df) */
513
#define STUB_ARGS_6 MOVE_DF_BYTE0 (t); MOVE_SF_BYTE8 (t)        /* (df, sf) */
514
#define STUB_ARGS_10 MOVE_DF_BYTE0 (t); MOVE_DF_BYTE8 (t)       /* (df, df) */
515
 
516
/* These functions are used by 16-bit code when calling via a function
517
   pointer.  They must copy the floating point arguments from the GPRs
518
   to FPRs and then call function $2.  */
519
 
520
#define CALL_STUB_NO_RET(NAME, CODE)    \
521
STARTFN (NAME);                         \
522
        STUB_ARGS_##CODE;               \
523
        .set    noreorder;              \
524
        jr      $2;                     \
525
        move    $25,$2;                 \
526
        .set    reorder;                \
527
        ENDFN (NAME)
528
 
529
#ifdef L_m16stub1
530
CALL_STUB_NO_RET (__mips16_call_stub_1, 1)
531
#endif
532
 
533
#ifdef L_m16stub5
534
CALL_STUB_NO_RET (__mips16_call_stub_5, 5)
535
#endif
536
 
537
#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
538
 
539
#ifdef L_m16stub2
540
CALL_STUB_NO_RET (__mips16_call_stub_2, 2)
541
#endif
542
 
543
#ifdef L_m16stub6
544
CALL_STUB_NO_RET (__mips16_call_stub_6, 6)
545
#endif
546
 
547
#ifdef L_m16stub9
548
CALL_STUB_NO_RET (__mips16_call_stub_9, 9)
549
#endif
550
 
551
#ifdef L_m16stub10
552
CALL_STUB_NO_RET (__mips16_call_stub_10, 10)
553
#endif
554
#endif /* !__mips_single_float */
555
 
556
/* Now we have the same set of functions, except that this time the
557
   function being called returns an SFmode, SCmode, DFmode or DCmode
558
   value; we need to instantiate a set for each case.  The calling
559
   function will arrange to preserve $18, so these functions are free
560
   to use it to hold the return address.
561
 
562
   Note that we do not know whether the function we are calling is 16
563
   bit or 32 bit.  However, it does not matter, because 16-bit
564
   functions always return floating point values in both the gp and
565
   the fp regs.  It would be possible to check whether the function
566
   being called is 16 bits, in which case the copy is unnecessary;
567
   however, it's faster to always do the copy.  */
568
 
569
#define CALL_STUB_RET(NAME, CODE, MODE)                                 \
570
STARTFN (NAME);                                                         \
571
        .cfi_startproc;                                                 \
572
        /* Create a fake CFA 4 bytes below the stack pointer.  */       \
573
        .cfi_def_cfa 29,-4;                                             \
574
        /* "Save" $sp in itself so we don't use the fake CFA.           \
575
           This is: DW_CFA_val_expression r29, { DW_OP_reg29 }.  */     \
576
        .cfi_escape 0x16,29,1,0x6d;                                     \
577
        move    $18,$31;                                                \
578
        .cfi_register 31,18;                                            \
579
        STUB_ARGS_##CODE;                                               \
580
        .set    noreorder;                                              \
581
        jalr    $2;                                                     \
582
        move    $25,$2;                                                 \
583
        .set    reorder;                                                \
584
        MOVE_##MODE##_RET (f, $18);                                     \
585
        .cfi_endproc;                                                   \
586
        ENDFN (NAME)
587
 
588
/* First, instantiate the single-float set.  */
589
 
590
#ifdef L_m16stubsf0
591
CALL_STUB_RET (__mips16_call_stub_sf_0, 0, SF)
592
#endif
593
 
594
#ifdef L_m16stubsf1
595
CALL_STUB_RET (__mips16_call_stub_sf_1, 1, SF)
596
#endif
597
 
598
#ifdef L_m16stubsf5
599
CALL_STUB_RET (__mips16_call_stub_sf_5, 5, SF)
600
#endif
601
 
602
#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
603
#ifdef L_m16stubsf2
604
CALL_STUB_RET (__mips16_call_stub_sf_2, 2, SF)
605
#endif
606
 
607
#ifdef L_m16stubsf6
608
CALL_STUB_RET (__mips16_call_stub_sf_6, 6, SF)
609
#endif
610
 
611
#ifdef L_m16stubsf9
612
CALL_STUB_RET (__mips16_call_stub_sf_9, 9, SF)
613
#endif
614
 
615
#ifdef L_m16stubsf10
616
CALL_STUB_RET (__mips16_call_stub_sf_10, 10, SF)
617
#endif
618
#endif /* !__mips_single_float */
619
 
620
 
621
/* Now we have the same set of functions again, except that this time
622
   the function being called returns an DFmode value.  */
623
 
624
#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
625
#ifdef L_m16stubdf0
626
CALL_STUB_RET (__mips16_call_stub_df_0, 0, DF)
627
#endif
628
 
629
#ifdef L_m16stubdf1
630
CALL_STUB_RET (__mips16_call_stub_df_1, 1, DF)
631
#endif
632
 
633
#ifdef L_m16stubdf5
634
CALL_STUB_RET (__mips16_call_stub_df_5, 5, DF)
635
#endif
636
 
637
#ifdef L_m16stubdf2
638
CALL_STUB_RET (__mips16_call_stub_df_2, 2, DF)
639
#endif
640
 
641
#ifdef L_m16stubdf6
642
CALL_STUB_RET (__mips16_call_stub_df_6, 6, DF)
643
#endif
644
 
645
#ifdef L_m16stubdf9
646
CALL_STUB_RET (__mips16_call_stub_df_9, 9, DF)
647
#endif
648
 
649
#ifdef L_m16stubdf10
650
CALL_STUB_RET (__mips16_call_stub_df_10, 10, DF)
651
#endif
652
#endif /* !__mips_single_float */
653
 
654
 
655
/* Ho hum.  Here we have the same set of functions again, this time
656
   for when the function being called returns an SCmode value.  */
657
 
658
#ifdef L_m16stubsc0
659
CALL_STUB_RET (__mips16_call_stub_sc_0, 0, SC)
660
#endif
661
 
662
#ifdef L_m16stubsc1
663
CALL_STUB_RET (__mips16_call_stub_sc_1, 1, SC)
664
#endif
665
 
666
#ifdef L_m16stubsc5
667
CALL_STUB_RET (__mips16_call_stub_sc_5, 5, SC)
668
#endif
669
 
670
#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
671
#ifdef L_m16stubsc2
672
CALL_STUB_RET (__mips16_call_stub_sc_2, 2, SC)
673
#endif
674
 
675
#ifdef L_m16stubsc6
676
CALL_STUB_RET (__mips16_call_stub_sc_6, 6, SC)
677
#endif
678
 
679
#ifdef L_m16stubsc9
680
CALL_STUB_RET (__mips16_call_stub_sc_9, 9, SC)
681
#endif
682
 
683
#ifdef L_m16stubsc10
684
CALL_STUB_RET (__mips16_call_stub_sc_10, 10, SC)
685
#endif
686
#endif /* !__mips_single_float */
687
 
688
 
689
/* Finally, another set of functions for DCmode.  */
690
 
691
#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
692
#ifdef L_m16stubdc0
693
CALL_STUB_RET (__mips16_call_stub_dc_0, 0, DC)
694
#endif
695
 
696
#ifdef L_m16stubdc1
697
CALL_STUB_RET (__mips16_call_stub_dc_1, 1, DC)
698
#endif
699
 
700
#ifdef L_m16stubdc5
701
CALL_STUB_RET (__mips16_call_stub_dc_5, 5, DC)
702
#endif
703
 
704
#ifdef L_m16stubdc2
705
CALL_STUB_RET (__mips16_call_stub_dc_2, 2, DC)
706
#endif
707
 
708
#ifdef L_m16stubdc6
709
CALL_STUB_RET (__mips16_call_stub_dc_6, 6, DC)
710
#endif
711
 
712
#ifdef L_m16stubdc9
713
CALL_STUB_RET (__mips16_call_stub_dc_9, 9, DC)
714
#endif
715
 
716
#ifdef L_m16stubdc10
717
CALL_STUB_RET (__mips16_call_stub_dc_10, 10, DC)
718
#endif
719
#endif /* !__mips_single_float */
720
 
721
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.