optabs.h revision 132718
190075Sobrien/* Definitions for code generation pass of GNU compiler.
2132718Skan   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
390075Sobrien
490075SobrienThis file is part of GCC.
590075Sobrien
690075SobrienGCC is free software; you can redistribute it and/or modify
790075Sobrienit under the terms of the GNU General Public License as published by
890075Sobrienthe Free Software Foundation; either version 2, or (at your option)
990075Sobrienany later version.
1090075Sobrien
1190075SobrienGCC is distributed in the hope that it will be useful,
1290075Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1390075SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1490075SobrienGNU General Public License for more details.
1590075Sobrien
1690075SobrienYou should have received a copy of the GNU General Public License
1790075Sobrienalong with GCC; see the file COPYING.  If not, write to
1890075Sobrienthe Free Software Foundation, 59 Temple Place - Suite 330,
1990075SobrienBoston, MA 02111-1307, USA.  */
2090075Sobrien
2190075Sobrien#ifndef GCC_OPTABS_H
2290075Sobrien#define GCC_OPTABS_H
2390075Sobrien
2490075Sobrien#include "insn-codes.h"
2590075Sobrien
2690075Sobrien/* Optabs are tables saying how to generate insn bodies
2790075Sobrien   for various machine modes and numbers of operands.
2890075Sobrien   Each optab applies to one operation.
2990075Sobrien   For example, add_optab applies to addition.
3090075Sobrien
3190075Sobrien   The insn_code slot is the enum insn_code that says how to
3290075Sobrien   generate an insn for this operation on a particular machine mode.
3390075Sobrien   It is CODE_FOR_nothing if there is no such insn on the target machine.
3490075Sobrien
3590075Sobrien   The `lib_call' slot is the name of the library function that
3690075Sobrien   can be used to perform the operation.
3790075Sobrien
3890075Sobrien   A few optabs, such as move_optab and cmp_optab, are used
3990075Sobrien   by special code.  */
4090075Sobrien
41132718Skanstruct optab_handlers GTY(())
42132718Skan{
43132718Skan  enum insn_code insn_code;
44132718Skan  rtx libfunc;
45132718Skan};
46132718Skan
47117395Skanstruct optab GTY(())
4890075Sobrien{
4990075Sobrien  enum rtx_code code;
50132718Skan  struct optab_handlers handlers[NUM_MACHINE_MODES];
51117395Skan};
52117395Skantypedef struct optab * optab;
5390075Sobrien
54132718Skan/* A convert_optab is for some sort of conversion operation between
55132718Skan   modes.  The first array index is the destination mode, the second
56132718Skan   is the source mode.  */
57132718Skanstruct convert_optab GTY(())
58132718Skan{
59132718Skan  enum rtx_code code;
60132718Skan  struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
61132718Skan};
62132718Skantypedef struct convert_optab *convert_optab;
63132718Skan
6490075Sobrien/* Given an enum insn_code, access the function to construct
6590075Sobrien   the body of that kind of insn.  */
66132718Skan#define GEN_FCN(CODE) (insn_data[CODE].genfun)
6790075Sobrien
6890075Sobrien/* Enumeration of valid indexes into optab_table.  */
6990075Sobrienenum optab_index
7090075Sobrien{
7190075Sobrien  OTI_add,
7290075Sobrien  OTI_addv,
7390075Sobrien  OTI_sub,
7490075Sobrien  OTI_subv,
7590075Sobrien
7690075Sobrien  /* Signed and fp multiply */
7790075Sobrien  OTI_smul,
7890075Sobrien  OTI_smulv,
7990075Sobrien  /* Signed multiply, return high word */
8090075Sobrien  OTI_smul_highpart,
8190075Sobrien  OTI_umul_highpart,
8290075Sobrien  /* Signed multiply with result one machine mode wider than args */
8390075Sobrien  OTI_smul_widen,
8490075Sobrien  OTI_umul_widen,
8590075Sobrien
8690075Sobrien  /* Signed divide */
8790075Sobrien  OTI_sdiv,
8890075Sobrien  OTI_sdivv,
8990075Sobrien  /* Signed divide-and-remainder in one */
9090075Sobrien  OTI_sdivmod,
9190075Sobrien  OTI_udiv,
9290075Sobrien  OTI_udivmod,
9390075Sobrien  /* Signed remainder */
9490075Sobrien  OTI_smod,
9590075Sobrien  OTI_umod,
9690075Sobrien  /* Convert float to integer in float fmt */
9790075Sobrien  OTI_ftrunc,
9890075Sobrien
9990075Sobrien  /* Logical and */
10090075Sobrien  OTI_and,
10190075Sobrien  /* Logical or */
10290075Sobrien  OTI_ior,
10390075Sobrien  /* Logical xor */
10490075Sobrien  OTI_xor,
10590075Sobrien
10690075Sobrien  /* Arithmetic shift left */
10790075Sobrien  OTI_ashl,
10890075Sobrien  /* Logical shift right */
109132718Skan  OTI_lshr,
11090075Sobrien  /* Arithmetic shift right */
11190075Sobrien  OTI_ashr,
11290075Sobrien  /* Rotate left */
11390075Sobrien  OTI_rotl,
11490075Sobrien  /* Rotate right */
11590075Sobrien  OTI_rotr,
11690075Sobrien  /* Signed and floating-point minimum value */
11790075Sobrien  OTI_smin,
11890075Sobrien  /* Signed and floating-point maximum value */
11990075Sobrien  OTI_smax,
12090075Sobrien  /* Unsigned minimum value */
12190075Sobrien  OTI_umin,
12290075Sobrien  /* Unsigned maximum value */
12390075Sobrien  OTI_umax,
124132718Skan  /* Power */
125132718Skan  OTI_pow,
126132718Skan  /* Arc tangent of y/x */
127132718Skan  OTI_atan2,
12890075Sobrien
12990075Sobrien  /* Move instruction.  */
13090075Sobrien  OTI_mov,
13190075Sobrien  /* Move, preserving high part of register.  */
13290075Sobrien  OTI_movstrict,
13390075Sobrien
13490075Sobrien  /* Unary operations */
13590075Sobrien  /* Negation */
13690075Sobrien  OTI_neg,
13790075Sobrien  OTI_negv,
13890075Sobrien  /* Abs value */
13990075Sobrien  OTI_abs,
14090075Sobrien  OTI_absv,
14190075Sobrien  /* Bitwise not */
14290075Sobrien  OTI_one_cmpl,
143132718Skan  /* Bit scanning and counting */
14490075Sobrien  OTI_ffs,
145132718Skan  OTI_clz,
146132718Skan  OTI_ctz,
147132718Skan  OTI_popcount,
148132718Skan  OTI_parity,
14990075Sobrien  /* Square root */
15090075Sobrien  OTI_sqrt,
15190075Sobrien  /* Sine */
15290075Sobrien  OTI_sin,
15390075Sobrien  /* Cosine */
15490075Sobrien  OTI_cos,
155117395Skan  /* Exponential */
156117395Skan  OTI_exp,
157117395Skan  /* Natural Logarithm */
158117395Skan  OTI_log,
159132718Skan  /* Rounding functions */
160132718Skan  OTI_floor,
161132718Skan  OTI_ceil,
162132718Skan  OTI_trunc,
163132718Skan  OTI_round,
164132718Skan  OTI_nearbyint,
165132718Skan  /* Tangent */
166132718Skan  OTI_tan,
167132718Skan  /* Inverse tangent */
168132718Skan  OTI_atan,
16990075Sobrien
17090075Sobrien  /* Compare insn; two operands.  */
17190075Sobrien  OTI_cmp,
17290075Sobrien  /* Used only for libcalls for unsigned comparisons.  */
17390075Sobrien  OTI_ucmp,
17490075Sobrien  /* tst insn; compare one operand against 0 */
17590075Sobrien  OTI_tst,
17690075Sobrien
177132718Skan  /* Floating point comparison optabs - used primarily for libfuncs */
178132718Skan  OTI_eq,
179132718Skan  OTI_ne,
180132718Skan  OTI_gt,
181132718Skan  OTI_ge,
182132718Skan  OTI_lt,
183132718Skan  OTI_le,
184132718Skan  OTI_unord,
185132718Skan
18690075Sobrien  /* String length */
18790075Sobrien  OTI_strlen,
18890075Sobrien
18990075Sobrien  /* Combined compare & jump/store flags/move operations.  */
19090075Sobrien  OTI_cbranch,
19190075Sobrien  OTI_cmov,
19290075Sobrien  OTI_cstore,
193132718Skan
19490075Sobrien  /* Push instruction.  */
19590075Sobrien  OTI_push,
19690075Sobrien
197132718Skan  /* Conditional add instruction.  */
198132718Skan  OTI_addcc,
199132718Skan
200132718Skan  /* Set specified field of vector operand.  */
201132718Skan  OTI_vec_set,
202132718Skan  /* Extract specified field of vector operand.  */
203132718Skan  OTI_vec_extract,
204132718Skan  /* Initialize vector operand.  */
205132718Skan  OTI_vec_init,
206132718Skan
20790075Sobrien  OTI_MAX
20890075Sobrien};
20990075Sobrien
210117395Skanextern GTY(()) optab optab_table[OTI_MAX];
21190075Sobrien
21290075Sobrien#define add_optab (optab_table[OTI_add])
21390075Sobrien#define sub_optab (optab_table[OTI_sub])
21490075Sobrien#define smul_optab (optab_table[OTI_smul])
21590075Sobrien#define addv_optab (optab_table[OTI_addv])
21690075Sobrien#define subv_optab (optab_table[OTI_subv])
21790075Sobrien#define smul_highpart_optab (optab_table[OTI_smul_highpart])
21890075Sobrien#define umul_highpart_optab (optab_table[OTI_umul_highpart])
21990075Sobrien#define smul_widen_optab (optab_table[OTI_smul_widen])
22090075Sobrien#define umul_widen_optab (optab_table[OTI_umul_widen])
22190075Sobrien#define sdiv_optab (optab_table[OTI_sdiv])
22290075Sobrien#define smulv_optab (optab_table[OTI_smulv])
22390075Sobrien#define sdivv_optab (optab_table[OTI_sdivv])
22490075Sobrien#define sdivmod_optab (optab_table[OTI_sdivmod])
22590075Sobrien#define udiv_optab (optab_table[OTI_udiv])
22690075Sobrien#define udivmod_optab (optab_table[OTI_udivmod])
22790075Sobrien#define smod_optab (optab_table[OTI_smod])
22890075Sobrien#define umod_optab (optab_table[OTI_umod])
22990075Sobrien#define ftrunc_optab (optab_table[OTI_ftrunc])
23090075Sobrien#define and_optab (optab_table[OTI_and])
23190075Sobrien#define ior_optab (optab_table[OTI_ior])
23290075Sobrien#define xor_optab (optab_table[OTI_xor])
23390075Sobrien#define ashl_optab (optab_table[OTI_ashl])
23490075Sobrien#define lshr_optab (optab_table[OTI_lshr])
23590075Sobrien#define ashr_optab (optab_table[OTI_ashr])
23690075Sobrien#define rotl_optab (optab_table[OTI_rotl])
23790075Sobrien#define rotr_optab (optab_table[OTI_rotr])
23890075Sobrien#define smin_optab (optab_table[OTI_smin])
23990075Sobrien#define smax_optab (optab_table[OTI_smax])
24090075Sobrien#define umin_optab (optab_table[OTI_umin])
24190075Sobrien#define umax_optab (optab_table[OTI_umax])
242132718Skan#define pow_optab (optab_table[OTI_pow])
243132718Skan#define atan2_optab (optab_table[OTI_atan2])
24490075Sobrien
24590075Sobrien#define mov_optab (optab_table[OTI_mov])
24690075Sobrien#define movstrict_optab (optab_table[OTI_movstrict])
24790075Sobrien
24890075Sobrien#define neg_optab (optab_table[OTI_neg])
24990075Sobrien#define negv_optab (optab_table[OTI_negv])
25090075Sobrien#define abs_optab (optab_table[OTI_abs])
25190075Sobrien#define absv_optab (optab_table[OTI_absv])
25290075Sobrien#define one_cmpl_optab (optab_table[OTI_one_cmpl])
25390075Sobrien#define ffs_optab (optab_table[OTI_ffs])
254132718Skan#define clz_optab (optab_table[OTI_clz])
255132718Skan#define ctz_optab (optab_table[OTI_ctz])
256132718Skan#define popcount_optab (optab_table[OTI_popcount])
257132718Skan#define parity_optab (optab_table[OTI_parity])
25890075Sobrien#define sqrt_optab (optab_table[OTI_sqrt])
25990075Sobrien#define sin_optab (optab_table[OTI_sin])
26090075Sobrien#define cos_optab (optab_table[OTI_cos])
261117395Skan#define exp_optab (optab_table[OTI_exp])
262117395Skan#define log_optab (optab_table[OTI_log])
263132718Skan#define floor_optab (optab_table[OTI_floor])
264132718Skan#define ceil_optab (optab_table[OTI_ceil])
265132718Skan#define btrunc_optab (optab_table[OTI_trunc])
266132718Skan#define round_optab (optab_table[OTI_round])
267132718Skan#define nearbyint_optab (optab_table[OTI_nearbyint])
268132718Skan#define tan_optab (optab_table[OTI_tan])
269132718Skan#define atan_optab (optab_table[OTI_atan])
27090075Sobrien
27190075Sobrien#define cmp_optab (optab_table[OTI_cmp])
27290075Sobrien#define ucmp_optab (optab_table[OTI_ucmp])
27390075Sobrien#define tst_optab (optab_table[OTI_tst])
27490075Sobrien
275132718Skan#define eq_optab (optab_table[OTI_eq])
276132718Skan#define ne_optab (optab_table[OTI_ne])
277132718Skan#define gt_optab (optab_table[OTI_gt])
278132718Skan#define ge_optab (optab_table[OTI_ge])
279132718Skan#define lt_optab (optab_table[OTI_lt])
280132718Skan#define le_optab (optab_table[OTI_le])
281132718Skan#define unord_optab (optab_table[OTI_unord])
282132718Skan
28390075Sobrien#define strlen_optab (optab_table[OTI_strlen])
28490075Sobrien
28590075Sobrien#define cbranch_optab (optab_table[OTI_cbranch])
28690075Sobrien#define cmov_optab (optab_table[OTI_cmov])
28790075Sobrien#define cstore_optab (optab_table[OTI_cstore])
28890075Sobrien#define push_optab (optab_table[OTI_push])
289132718Skan#define addcc_optab (optab_table[OTI_addcc])
29090075Sobrien
291132718Skan#define vec_set_optab (optab_table[OTI_vec_set])
292132718Skan#define vec_extract_optab (optab_table[OTI_vec_extract])
293132718Skan#define vec_init_optab (optab_table[OTI_vec_init])
29490075Sobrien
295132718Skan/* Conversion optabs have their own table and indexes.  */
296132718Skanenum convert_optab_index
297132718Skan{
298132718Skan  CTI_sext,
299132718Skan  CTI_zext,
300132718Skan  CTI_trunc,
30190075Sobrien
302132718Skan  CTI_sfix,
303132718Skan  CTI_ufix,
304132718Skan
305132718Skan  CTI_sfixtrunc,
306132718Skan  CTI_ufixtrunc,
307132718Skan
308132718Skan  CTI_sfloat,
309132718Skan  CTI_ufloat,
310132718Skan
311132718Skan  CTI_MAX
312132718Skan};
313132718Skan
314132718Skanextern GTY(()) convert_optab convert_optab_table[CTI_MAX];
315132718Skan
316132718Skan#define sext_optab (convert_optab_table[CTI_sext])
317132718Skan#define zext_optab (convert_optab_table[CTI_zext])
318132718Skan#define trunc_optab (convert_optab_table[CTI_trunc])
319132718Skan#define sfix_optab (convert_optab_table[CTI_sfix])
320132718Skan#define ufix_optab (convert_optab_table[CTI_ufix])
321132718Skan#define sfixtrunc_optab (convert_optab_table[CTI_sfixtrunc])
322132718Skan#define ufixtrunc_optab (convert_optab_table[CTI_ufixtrunc])
323132718Skan#define sfloat_optab (convert_optab_table[CTI_sfloat])
324132718Skan#define ufloat_optab (convert_optab_table[CTI_ufloat])
325132718Skan
32690075Sobrien/* These arrays record the insn_code of insns that may be needed to
32790075Sobrien   perform input and output reloads of special objects.  They provide a
32890075Sobrien   place to pass a scratch register.  */
32990075Sobrienextern enum insn_code reload_in_optab[NUM_MACHINE_MODES];
33090075Sobrienextern enum insn_code reload_out_optab[NUM_MACHINE_MODES];
33190075Sobrien
33290075Sobrien/* Contains the optab used for each rtx code.  */
333132718Skanextern GTY(()) optab code_to_optab[NUM_RTX_CODE + 1];
33490075Sobrien
33590075Sobrien
336132718Skantypedef rtx (*rtxfun) (rtx);
33790075Sobrien
33890075Sobrien/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
33990075Sobrien   gives the gen_function to make a branch to test that condition.  */
34090075Sobrien
34190075Sobrienextern rtxfun bcc_gen_fctn[NUM_RTX_CODE];
34290075Sobrien
34390075Sobrien/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
34490075Sobrien   gives the insn code to make a store-condition insn
34590075Sobrien   to test that condition.  */
34690075Sobrien
34790075Sobrienextern enum insn_code setcc_gen_code[NUM_RTX_CODE];
34890075Sobrien
34990075Sobrien#ifdef HAVE_conditional_move
35090075Sobrien/* Indexed by the machine mode, gives the insn code to make a conditional
35190075Sobrien   move insn.  */
35290075Sobrien
35390075Sobrienextern enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
35490075Sobrien#endif
35590075Sobrien
35690075Sobrien/* This array records the insn_code of insns to perform block moves.  */
35790075Sobrienextern enum insn_code movstr_optab[NUM_MACHINE_MODES];
35890075Sobrien
35990075Sobrien/* This array records the insn_code of insns to perform block clears.  */
36090075Sobrienextern enum insn_code clrstr_optab[NUM_MACHINE_MODES];
36190075Sobrien
362132718Skan/* These arrays record the insn_code of two different kinds of insns
363132718Skan   to perform block compares.  */
364132718Skanextern enum insn_code cmpstr_optab[NUM_MACHINE_MODES];
365132718Skanextern enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
366132718Skan
36790075Sobrien/* Define functions given in optabs.c.  */
36890075Sobrien
36990075Sobrien/* Expand a binary operation given optab and rtx operands.  */
370132718Skanextern rtx expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
371132718Skan			 enum optab_methods);
37290075Sobrien
37390075Sobrien/* Expand a binary operation with both signed and unsigned forms.  */
374132718Skanextern rtx sign_expand_binop (enum machine_mode, optab, optab, rtx, rtx,
375132718Skan			      rtx, int, enum optab_methods);
37690075Sobrien
37790075Sobrien/* Generate code to perform an operation on two operands with two results.  */
378132718Skanextern int expand_twoval_binop (optab, rtx, rtx, rtx, rtx, int);
37990075Sobrien
38090075Sobrien/* Expand a unary arithmetic operation given optab rtx operand.  */
381132718Skanextern rtx expand_unop (enum machine_mode, optab, rtx, rtx, int);
38290075Sobrien
38390075Sobrien/* Expand the absolute value operation.  */
384132718Skanextern rtx expand_abs_nojump (enum machine_mode, rtx, rtx, int);
385132718Skanextern rtx expand_abs (enum machine_mode, rtx, rtx, int, int);
38690075Sobrien
38790075Sobrien/* Expand the complex absolute value operation.  */
388132718Skanextern rtx expand_complex_abs (enum machine_mode, rtx, rtx, int);
38990075Sobrien
39090075Sobrien/* Generate an instruction with a given INSN_CODE with an output and
39190075Sobrien   an input.  */
392132718Skanextern void emit_unop_insn (int, rtx, rtx, enum rtx_code);
39390075Sobrien
39490075Sobrien/* Emit code to perform a series of operations on a multi-word quantity, one
39590075Sobrien   word at a time.  */
396132718Skanextern rtx emit_no_conflict_block (rtx, rtx, rtx, rtx, rtx);
39790075Sobrien
39890075Sobrien/* Emit one rtl instruction to store zero in specified rtx.  */
399132718Skanextern void emit_clr_insn (rtx);
40090075Sobrien
40190075Sobrien/* Emit one rtl insn to store 1 in specified rtx assuming it contains 0.  */
402132718Skanextern void emit_0_to_1_insn (rtx);
40390075Sobrien
40490075Sobrien/* Emit one rtl insn to compare two rtx's.  */
405132718Skanextern void emit_cmp_insn (rtx, rtx, enum rtx_code, rtx, enum machine_mode,
406132718Skan			   int);
40790075Sobrien
40890075Sobrien/* The various uses that a comparison can have; used by can_compare_p:
40990075Sobrien   jumps, conditional moves, store flag operations.  */
41090075Sobrienenum can_compare_purpose
41190075Sobrien{
41290075Sobrien  ccp_jump,
41390075Sobrien  ccp_cmov,
41490075Sobrien  ccp_store_flag
41590075Sobrien};
41690075Sobrien
41790075Sobrien/* Nonzero if a compare of mode MODE can be done straightforwardly
41890075Sobrien   (without splitting it into pieces).  */
419132718Skanextern int can_compare_p (enum rtx_code, enum machine_mode,
420132718Skan			  enum can_compare_purpose);
42190075Sobrien
422132718Skanextern rtx prepare_operand (int, rtx, int, enum machine_mode,
423132718Skan			    enum machine_mode, int);
42490075Sobrien
42590075Sobrien/* Return the INSN_CODE to use for an extend operation.  */
426132718Skanextern enum insn_code can_extend_p (enum machine_mode, enum machine_mode, int);
42790075Sobrien
42890075Sobrien/* Generate the body of an insn to extend Y (with mode MFROM)
42990075Sobrien   into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */
430132718Skanextern rtx gen_extend_insn (rtx, rtx, enum machine_mode,
431132718Skan			    enum machine_mode, int);
43290075Sobrien
43390075Sobrien/* Initialize the tables that control conversion between fixed and
43490075Sobrien   floating values.  */
435132718Skanextern void init_fixtab (void);
436132718Skanextern void init_floattab (void);
43790075Sobrien
438132718Skan/* Call this to reset the function entry for one optab.  */
439132718Skanextern void set_optab_libfunc (optab, enum machine_mode, const char *);
440132718Skanextern void set_conv_libfunc (convert_optab, enum machine_mode,
441132718Skan			      enum machine_mode, const char *);
442132718Skan
44390075Sobrien/* Generate code for a FLOAT_EXPR.  */
444132718Skanextern void expand_float (rtx, rtx, int);
44590075Sobrien
44690075Sobrien/* Generate code for a FIX_EXPR.  */
447132718Skanextern void expand_fix (rtx, rtx, int);
44890075Sobrien
44990075Sobrien#endif /* GCC_OPTABS_H */
450