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