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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [config/] [mips/] [mips16.S] - Blame information for rev 816

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

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

powered by: WebSVN 2.1.0

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