diff options
author | Ian Lance Taylor <ian@cygnus.com> | 1997-12-19 16:55:53 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1997-12-19 09:55:53 -0700 |
commit | afba61d1421cd6bc16d20fb4e5d8a10bf48a0b79 (patch) | |
tree | e59a4ee5e3633c77e27680db1fc5687b3a1a6205 /gcc | |
parent | 6003a6bf7579b9e600e5ec539fad7a8122f98fac (diff) | |
download | gcc-afba61d1421cd6bc16d20fb4e5d8a10bf48a0b79.zip gcc-afba61d1421cd6bc16d20fb4e5d8a10bf48a0b79.tar.gz gcc-afba61d1421cd6bc16d20fb4e5d8a10bf48a0b79.tar.bz2 |
* mips16.S: New file.
From-SVN: r17157
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/config/mips/mips16.S | 685 |
2 files changed, 689 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 505d84b..aed4461 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ Fri Dec 19 17:31:11 1997 Ian Lance Taylor <ian@cygnus.com> + * mips16.S: New file. + + * libgcc2.c (varargs): Handle mips16. + * expr.c (do_tablejump): Let CASE_VECTOR_PC_RELATIVE be an expression. * stmt.c (expand_end_case): Likewise. diff --git a/gcc/config/mips/mips16.S b/gcc/config/mips/mips16.S new file mode 100644 index 0000000..eb4fe37 --- /dev/null +++ b/gcc/config/mips/mips16.S @@ -0,0 +1,685 @@ +/* mips16 floating point support code + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Cygnus Support + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file with other programs, and to distribute +those programs without any restriction coming from the use of this +file. (The General Public License restrictions do apply in other +respects; for example, they cover modification of the file, and +distribution when not linked into another program.) + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with other files, + some of which are compiled with GCC, to produce an executable, + this library does not by itself cause the resulting executable + to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* This file contains mips16 floating point support functions. These + functions are called by mips16 code to handle floating point when + -msoft-float is not used. They accept the arguments and return + values using the soft-float calling convention, but do the actual + operation using the hard floating point instructions. */ + +/* This file contains 32 bit assembly code. */ + .set nomips16 + +/* Start a function. */ + +#define STARTFN(NAME) .globl NAME; .ent NAME; NAME: + +/* Finish a function. */ + +#define ENDFN(NAME) .end NAME + +/* Single precision math. */ + +/* This macro defines a function which loads two single precision + values, performs an operation, and returns the single precision + result. */ + +#define SFOP(NAME, OPCODE) \ +STARTFN (NAME); \ + .set noreorder; \ + mtc1 $4,$f0; \ + mtc1 $5,$f2; \ + nop; \ + OPCODE $f0,$f0,$f2; \ + mfc1 $2,$f0; \ + j $31; \ + nop; \ + .set reorder; \ + ENDFN (NAME) + +#ifdef L_m16addsf3 +SFOP(__mips16_addsf3, add.s) +#endif +#ifdef L_m16subsf3 +SFOP(__mips16_subsf3, sub.s) +#endif +#ifdef L_m16mulsf3 +SFOP(__mips16_mulsf3, mul.s) +#endif +#ifdef L_m16divsf3 +SFOP(__mips16_divsf3, div.s) +#endif + +/* Single precision comparisons. */ + +/* This macro defines a function which loads two single precision + values, performs a floating point comparison, and returns the + specified values according to whether the comparison is true or + false. */ + +#define SFCMP(NAME, OPCODE, TRUE, FALSE) \ +STARTFN (NAME); \ + mtc1 $4,$f0; \ + mtc1 $5,$f2; \ + OPCODE $f0,$f2; \ + li $2,TRUE; \ + bc1t 1f; \ + li $2,FALSE; \ +1:; \ + j $31; \ + ENDFN (NAME) + +/* This macro is like SFCMP, but it reverses the comparison. */ + +#define SFREVCMP(NAME, OPCODE, TRUE, FALSE) \ +STARTFN (NAME); \ + mtc1 $4,$f0; \ + mtc1 $5,$f2; \ + OPCODE $f2,$f0; \ + li $2,TRUE; \ + bc1t 1f; \ + li $2,FALSE; \ +1:; \ + j $31; \ + ENDFN (NAME) + +#ifdef L_m16eqsf2 +SFCMP(__mips16_eqsf2, c.eq.s, 0, 1) +#endif +#ifdef L_m16nesf2 +SFCMP(__mips16_nesf2, c.eq.s, 0, 1) +#endif +#ifdef L_m16gtsf2 +SFREVCMP(__mips16_gtsf2, c.lt.s, 1, 0) +#endif +#ifdef L_m16gesf2 +SFREVCMP(__mips16_gesf2, c.le.s, 0, -1) +#endif +#ifdef L_m16lesf2 +SFCMP(__mips16_lesf2, c.le.s, 0, 1) +#endif +#ifdef L_m16ltsf2 +SFCMP(__mips16_ltsf2, c.lt.s, -1, 0) +#endif + +/* Single precision conversions. */ + +#ifdef L_m16fltsisf +STARTFN (__mips16_floatsisf) + .set noreorder + mtc1 $4,$f0 + nop + cvt.s.w $f0,$f0 + mfc1 $2,$f0 + j $31 + nop + .set reorder + ENDFN (__mips16_floatsisf) +#endif + +#ifdef L_m16fixsfsi +STARTFN (__mips16_fixsfsi) + .set noreorder + mtc1 $4,$f0 + nop + trunc.w.s $f0,$f0,$4 + mfc1 $2,$f0 + j $31 + nop + .set reorder + ENDFN (__mips16_fixsfsi) +#endif + +/* The double precision operations. We need to use different code + based on the preprocessor symbol __mips64, because the way in which + double precision values will change. Without __mips64, the value + is passed in two 32 bit registers. With __mips64, the value is + passed in a single 64 bit register. */ + +/* Load the first double precision operand. */ + +#ifdef __mips64 +#define LDDBL1 dmtc1 $4,$f0 +#else +#define LDDBL1 mtc1 $4,$f1; mtc1 $5,$f0 +#endif + +/* Load the second double precision operand. */ + +#ifdef __mips64 +#define LDDBL2 dmtc1 $5,$f2 +#else +#define LDDBL2 mtc1 $6,$f3; mtc1 $7,$f2 +#endif + +/* Move the double precision return value to the right place. */ + +#ifdef __mips64 +#define RETDBL dmfc1 $2,$f0 +#else +#define RETDBL mfc1 $2,$f1; mfc1 $3,$f0 +#endif + +/* Double precision math. */ + +/* This macro defines a function which loads two double precision + values, performs an operation, and returns the double precision + result. */ + +#define DFOP(NAME, OPCODE) \ +STARTFN (NAME); \ + .set noreorder; \ + LDDBL1; \ + LDDBL2; \ + nop; \ + OPCODE $f0,$f0,$f2; \ + RETDBL; \ + j $31; \ + nop; \ + .set reorder; \ + ENDFN (NAME) + +#ifdef L_m16adddf3 +DFOP(__mips16_adddf3, add.d) +#endif +#ifdef L_m16subdf3 +DFOP(__mips16_subdf3, sub.d) +#endif +#ifdef L_m16muldf3 +DFOP(__mips16_muldf3, mul.d) +#endif +#ifdef L_m16divdf3 +DFOP(__mips16_divdf3, div.d) +#endif + +/* Conversions between single and double precision. */ + +#ifdef L_m16extsfdf2 +STARTFN (__mips16_extendsfdf2) + .set noreorder + mtc1 $4,$f0 + nop + cvt.d.s $f0,$f0 + RETDBL + j $31 + nop + .set reorder + ENDFN (__mips16_extendsfdf2) +#endif + +#ifdef L_m16trdfsf2 +STARTFN (__mips16_truncdfsf2) + .set noreorder + LDDBL1 + nop + cvt.s.d $f0,$f0 + mfc1 $2,$f0 + j $31 + nop + .set reorder + ENDFN (__mips16_truncdfsf2) +#endif + +/* Double precision comparisons. */ + +/* This macro defines a function which loads two double precision + values, performs a floating point comparison, and returns the + specified values according to whether the comparison is true or + false. */ + +#define DFCMP(NAME, OPCODE, TRUE, FALSE) \ +STARTFN (NAME); \ + LDDBL1; \ + LDDBL2; \ + OPCODE $f0,$f2; \ + li $2,TRUE; \ + bc1t 1f; \ + li $2,FALSE; \ +1:; \ + j $31; \ + ENDFN (NAME) + +/* This macro is like DFCMP, but it reverses the comparison. */ + +#define DFREVCMP(NAME, OPCODE, TRUE, FALSE) \ +STARTFN (NAME); \ + LDDBL1; \ + LDDBL2; \ + OPCODE $f2,$f0; \ + li $2,TRUE; \ + bc1t 1f; \ + li $2,FALSE; \ +1:; \ + j $31; \ + ENDFN (NAME) + +#ifdef L_m16eqdf2 +DFCMP(__mips16_eqdf2, c.eq.d, 0, 1) +#endif +#ifdef L_m16nedf2 +DFCMP(__mips16_nedf2, c.eq.d, 0, 1) +#endif +#ifdef L_m16gtdf2 +DFREVCMP(__mips16_gtdf2, c.lt.d, 1, 0) +#endif +#ifdef L_m16gedf2 +DFREVCMP(__mips16_gedf2, c.le.d, 0, -1) +#endif +#ifdef L_m16ledf2 +DFCMP(__mips16_ledf2, c.le.d, 0, 1) +#endif +#ifdef L_m16ltdf2 +DFCMP(__mips16_ltdf2, c.lt.d, -1, 0) +#endif + +/* Double precision conversions. */ + +#ifdef L_m16fltsidf +STARTFN (__mips16_floatsidf) + .set noreorder + mtc1 $4,$f0 + nop + cvt.d.w $f0,$f0 + RETDBL + j $31 + nop + .set reorder + ENDFN (__mips16_floatsidf) +#endif + +#ifdef L_m16fixdfsi +STARTFN (__mips16_fixdfsi) + .set noreorder + LDDBL1 + nop + trunc.w.d $f0,$f0,$4 + mfc1 $2,$f0 + j $31 + nop + .set reorder + ENDFN (__mips16_fixdfsi) +#endif + +/* These functions are used to return floating point values from + mips16 functions which do not use -mentry. In this case we can + put mtc1 in a jump delay slot, because we know that the next + instruction will not refer to a floating point register. */ + +#ifdef L_m16retsf +STARTFN (__mips16_ret_sf) + .set noreorder + j $31 + mtc1 $2,$f0 + .set reorder + ENDFN (__mips16_ret_sf) +#endif + +#ifdef L_m16retdf +STARTFN (__mips16_ret_df) + .set noreorder + mtc1 $2,$f1 + j $31 + mtc1 $3,$f0 + ENDFN (__mips16_ret_df) +#endif + +/* These functions are used by 16 bit code when calling via a function + pointer. They must copy the floating point arguments from the gp + regs into the fp regs. The function to call will be in $2. The + exact set of floating point arguments to copy is encoded in the + function name; the final number is an fp_code, as described in + mips.h in the comment about CUMULATIVE_ARGS. */ + +#ifdef L_m16stub1 +/* (float) */ +STARTFN (__mips16_call_stub_1) + .set noreorder + mtc1 $4,$f12 + j $2 + nop + .set reorder + ENDFN (__mips16_call_stub_1) +#endif + +#ifdef L_m16stub2 +/* (double) */ +STARTFN (__mips16_call_stub_2) + .set noreorder + mtc1 $5,$f12 + mtc1 $4,$f13 + j $2 + nop + .set reorder + ENDFN (__mips16_call_stub_2) +#endif + +#ifdef L_m16stub5 +/* (float, float) */ +STARTFN (__mips16_call_stub_5) + .set noreorder + mtc1 $4,$f12 + mtc1 $5,$f14 + j $2 + nop + .set reorder + ENDFN (__mips16_call_stub_5) +#endif + +#ifdef L_m16stub6 +/* (double, float) */ +STARTFN (__mips16_call_stub_6) + .set noreorder + mtc1 $5,$f12 + mtc1 $4,$f13 + mtc1 $6,$f14 + j $2 + nop + .set reorder + ENDFN (__mips16_call_stub_6) +#endif + +#ifdef L_m16stub9 +/* (float, double) */ +STARTFN (__mips16_call_stub_9) + .set noreorder + mtc1 $4,$f12 + mtc1 $7,$f14 + mtc1 $6,$f15 + j $2 + nop + .set reorder + ENDFN (__mips16_call_stub_9) +#endif + +#ifdef L_m16stub10 +/* (double, double) */ +STARTFN (__mips16_call_stub_10) + .set noreorder + mtc1 $5,$f12 + mtc1 $4,$f13 + mtc1 $7,$f14 + mtc1 $6,$f15 + j $2 + nop + .set reorder + ENDFN (__mips16_call_stub_10) +#endif + +/* Now we have the same set of functions, except that this time the + function being called returns an SFmode value. The calling + function will arrange to preserve $18, so these functions are free + to use it to hold the return address. + + Note that we do not know whether the function we are calling is 16 + bit or 32 bit. However, it does not matter, because 16 bit + functions always return floating point values in both the gp and + the fp regs. It would be possible to check whether the function + being called is 16 bits, in which case the copy is unnecessary; + however, it's faster to always do the copy. */ + +#ifdef L_m16stubsf0 +/* () */ +STARTFN (__mips16_call_stub_sf_0) + .set noreorder + move $18,$31 + jal $2 + nop + mfc1 $4,$f0 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_sf_0) +#endif + +#ifdef L_m16stubsf1 +/* (float) */ +STARTFN (__mips16_call_stub_sf_1) + .set noreorder + mtc1 $4,$f12 + move $18,$31 + jal $2 + nop + mfc1 $4,$f0 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_sf_1) +#endif + +#ifdef L_m16stubsf2 +/* (double) */ +STARTFN (__mips16_call_stub_sf_2) + .set noreorder + mtc1 $5,$f12 + mtc1 $4,$f13 + move $18,$31 + jal $2 + nop + mfc1 $4,$f0 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_sf_2) +#endif + +#ifdef L_m16stubsf5 +/* (float, float) */ +STARTFN (__mips16_call_stub_sf_5) + .set noreorder + mtc1 $4,$f12 + mtc1 $5,$f14 + move $18,$31 + jal $2 + nop + mfc1 $4,$f0 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_sf_5) +#endif + +#ifdef L_m16stubsf6 +/* (double, float) */ +STARTFN (__mips16_call_stub_sf_6) + .set noreorder + mtc1 $5,$f12 + mtc1 $4,$f13 + mtc1 $6,$f14 + move $18,$31 + jal $2 + nop + mfc1 $4,$f0 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_sf_6) +#endif + +#ifdef L_m16stubsf9 +/* (float, double) */ +STARTFN (__mips16_call_stub_sf_9) + .set noreorder + mtc1 $4,$f12 + mtc1 $7,$f14 + mtc1 $6,$f15 + move $18,$31 + jal $2 + nop + mfc1 $4,$f0 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_sf_9) +#endif + +#ifdef L_m16stubsf10 +/* (double, double) */ +STARTFN (__mips16_call_stub_sf_10) + .set noreorder + mtc1 $5,$f12 + mtc1 $4,$f13 + mtc1 $7,$f14 + mtc1 $6,$f15 + move $18,$31 + jal $2 + nop + mfc1 $4,$f0 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_sf_10) +#endif + +/* Now we have the same set of functions again, except that this time + the function being called returns an DFmode value. */ + +#ifdef L_m16stubdf0 +/* () */ +STARTFN (__mips16_call_stub_df_0) + .set noreorder + move $18,$31 + jal $2 + nop + mfc1 $5,$f0 + mfc1 $4,$f1 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_df_0) +#endif + +#ifdef L_m16stubdf1 +/* (float) */ +STARTFN (__mips16_call_stub_df_1) + .set noreorder + mtc1 $4,$f12 + move $18,$31 + jal $2 + nop + mfc1 $5,$f0 + mfc1 $4,$f1 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_df_1) +#endif + +#ifdef L_m16stubdf2 +/* (double) */ +STARTFN (__mips16_call_stub_df_2) + .set noreorder + mtc1 $5,$f12 + mtc1 $4,$f13 + move $18,$31 + jal $2 + nop + mfc1 $5,$f0 + mfc1 $4,$f1 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_df_2) +#endif + +#ifdef L_m16stubdf5 +/* (float, float) */ +STARTFN (__mips16_call_stub_df_5) + .set noreorder + mtc1 $4,$f12 + mtc1 $5,$f14 + move $18,$31 + jal $2 + nop + mfc1 $5,$f0 + mfc1 $4,$f1 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_df_5) +#endif + +#ifdef L_m16stubdf6 +/* (double, float) */ +STARTFN (__mips16_call_stub_df_6) + .set noreorder + mtc1 $5,$f12 + mtc1 $4,$f13 + mtc1 $6,$f14 + move $18,$31 + jal $2 + nop + mfc1 $5,$f0 + mfc1 $4,$f1 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_df_6) +#endif + +#ifdef L_m16stubdf9 +/* (float, double) */ +STARTFN (__mips16_call_stub_df_9) + .set noreorder + mtc1 $4,$f12 + mtc1 $7,$f14 + mtc1 $6,$f15 + move $18,$31 + jal $2 + nop + mfc1 $5,$f0 + mfc1 $4,$f1 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_df_9) +#endif + +#ifdef L_m16stubdf10 +/* (double, double) */ +STARTFN (__mips16_call_stub_df_10) + .set noreorder + mtc1 $5,$f12 + mtc1 $4,$f13 + mtc1 $7,$f14 + mtc1 $6,$f15 + move $18,$31 + jal $2 + nop + mfc1 $5,$f0 + mfc1 $4,$f1 + j $18 + nop + .set reorder + ENDFN (__mips16_call_stub_df_10) +#endif |