optabs.c 165 KB
Newer Older
Richard Kenner committed
1
/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
Jeff Law committed
2
   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3
   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Richard Kenner committed
4

5
This file is part of GCC.
Richard Kenner committed
6

7 8 9 10
GCC 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.
Richard Kenner committed
11

12 13 14 15
GCC 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.
Richard Kenner committed
16 17

You should have received a copy of the GNU General Public License
18 19 20
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */
Richard Kenner committed
21 22 23


#include "config.h"
24
#include "system.h"
25 26
#include "coretypes.h"
#include "tm.h"
27
#include "toplev.h"
28 29

/* Include insn-config.h before expr.h so that HAVE_conditional_move
30
   is properly defined.  */
31
#include "insn-config.h"
Richard Kenner committed
32 33
#include "rtl.h"
#include "tree.h"
34
#include "tm_p.h"
Richard Kenner committed
35
#include "flags.h"
36
#include "function.h"
37
#include "except.h"
Richard Kenner committed
38
#include "expr.h"
39 40
#include "optabs.h"
#include "libfuncs.h"
Richard Kenner committed
41
#include "recog.h"
Richard Kenner committed
42
#include "reload.h"
43
#include "ggc.h"
44
#include "real.h"
45
#include "basic-block.h"
46
#include "target.h"
Richard Kenner committed
47 48 49 50 51 52 53 54 55 56

/* Each optab contains info on how this target machine
   can perform a particular operation
   for all sizes and kinds of operands.

   The operation to be performed is often specified
   by passing one of these optabs as an argument.

   See expr.h for documentation of these optabs.  */

57 58 59
optab optab_table[OTI_MAX];

rtx libfunc_table[LTI_MAX];
60

61 62
/* Tables of patterns for converting one mode to another.  */
convert_optab convert_optab_table[CTI_MAX];
63

64 65 66
/* Contains the optab used for each rtx code.  */
optab code_to_optab[NUM_RTX_CODE + 1];

Richard Kenner committed
67 68 69 70 71 72 73 74 75 76 77
/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
   gives the gen_function to make a branch to test that condition.  */

rtxfun bcc_gen_fctn[NUM_RTX_CODE];

/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
   gives the insn code to make a store-condition insn
   to test that condition.  */

enum insn_code setcc_gen_code[NUM_RTX_CODE];

78 79 80 81 82 83 84 85 86
#ifdef HAVE_conditional_move
/* Indexed by the machine mode, gives the insn code to make a conditional
   move insn.  This is not indexed by the rtx-code like bcc_gen_fctn and
   setcc_gen_code to cut down on the number of named patterns.  Consider a day
   when a lot more rtx codes are conditional (eg: for the ARM).  */

enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
#endif

87 88 89 90 91
/* The insn generating function can not take an rtx_code argument.
   TRAP_RTX is used as an rtx argument.  Its code is replaced with
   the code to be used in the trap insn and all other fields are ignored.  */
static GTY(()) rtx trap_rtx;

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
static int add_equal_note (rtx, rtx, enum rtx_code, rtx, rtx);
static rtx widen_operand (rtx, enum machine_mode, enum machine_mode, int,
			  int);
static int expand_cmplxdiv_straight (rtx, rtx, rtx, rtx, rtx, rtx,
				     enum machine_mode, int,
				     enum optab_methods, enum mode_class,
				     optab);
static int expand_cmplxdiv_wide (rtx, rtx, rtx, rtx, rtx, rtx,
				 enum machine_mode, int, enum optab_methods,
				 enum mode_class, optab);
static void prepare_cmp_insn (rtx *, rtx *, enum rtx_code *, rtx,
			      enum machine_mode *, int *,
			      enum can_compare_purpose);
static enum insn_code can_fix_p (enum machine_mode, enum machine_mode, int,
				 int *);
static enum insn_code can_float_p (enum machine_mode, enum machine_mode, int);
static optab new_optab (void);
109
static convert_optab new_convert_optab (void);
110 111
static inline optab init_optab (enum rtx_code);
static inline optab init_optabv (enum rtx_code);
112
static inline convert_optab init_convert_optab (enum rtx_code);
113 114 115
static void init_libfuncs (optab, int, int, const char *, int);
static void init_integral_libfuncs (optab, const char *, int);
static void init_floating_libfuncs (optab, const char *, int);
116 117 118 119
static void init_interclass_conv_libfuncs (convert_optab, const char *,
					   enum mode_class, enum mode_class);
static void init_intraclass_conv_libfuncs (convert_optab, const char *,
					   enum mode_class, bool);
120 121 122 123 124 125 126 127 128
static void emit_cmp_and_jump_insn_1 (rtx, rtx, enum machine_mode,
				      enum rtx_code, int, rtx);
static void prepare_float_lib_cmp (rtx *, rtx *, enum rtx_code *,
				   enum machine_mode *, int *);
static rtx expand_vector_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
				enum optab_methods);
static rtx expand_vector_unop (enum machine_mode, optab, rtx, rtx, int);
static rtx widen_clz (enum machine_mode, rtx, rtx);
static rtx expand_parity (enum machine_mode, rtx, rtx);
129 130 131 132 133

#ifndef HAVE_conditional_trap
#define HAVE_conditional_trap 0
#define gen_conditional_trap(a,b) (abort (), NULL_RTX)
#endif
Richard Kenner committed
134

135
/* Add a REG_EQUAL note to the last insn in INSNS.  TARGET is being set to
Richard Kenner committed
136 137 138 139 140 141 142 143 144 145
   the result of operation CODE applied to OP0 (and OP1 if it is a binary
   operation).

   If the last insn does not set TARGET, don't do anything, but return 1.

   If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
   don't add the REG_EQUAL note but return 0.  Our caller can then try
   again, ensuring that TARGET is not one of the operands.  */

static int
146
add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
Richard Kenner committed
147
{
148
  rtx last_insn, insn, set;
Richard Kenner committed
149 150
  rtx note;

151 152 153 154 155
  if (! insns
      || ! INSN_P (insns)
      || NEXT_INSN (insns) == NULL_RTX)
    abort ();

156 157 158 159 160
  if (GET_RTX_CLASS (code) != RTX_COMM_ARITH
      && GET_RTX_CLASS (code) != RTX_BIN_ARITH
      && GET_RTX_CLASS (code) != RTX_COMM_COMPARE
      && GET_RTX_CLASS (code) != RTX_COMPARE
      && GET_RTX_CLASS (code) != RTX_UNARY)
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
    return 1;

  if (GET_CODE (target) == ZERO_EXTRACT)
    return 1;

  for (last_insn = insns;
       NEXT_INSN (last_insn) != NULL_RTX;
       last_insn = NEXT_INSN (last_insn))
    ;

  set = single_set (last_insn);
  if (set == NULL_RTX)
    return 1;

  if (! rtx_equal_p (SET_DEST (set), target)
176
      /* For a STRICT_LOW_PART, the REG_NOTE applies to what is inside it.  */
177
      && (GET_CODE (SET_DEST (set)) != STRICT_LOW_PART
178
	  || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
Richard Kenner committed
179 180 181 182 183 184
    return 1;

  /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
     besides the last insn.  */
  if (reg_overlap_mentioned_p (target, op0)
      || (op1 && reg_overlap_mentioned_p (target, op1)))
185 186 187 188 189 190 191 192 193 194
    {
      insn = PREV_INSN (last_insn);
      while (insn != NULL_RTX)
	{
	  if (reg_set_p (target, insn))
	    return 0;

	  insn = PREV_INSN (insn);
	}
    }
Richard Kenner committed
195

196
  if (GET_RTX_CLASS (code) == RTX_UNARY)
197
    note = gen_rtx_fmt_e (code, GET_MODE (target), copy_rtx (op0));
Richard Kenner committed
198
  else
199
    note = gen_rtx_fmt_ee (code, GET_MODE (target), copy_rtx (op0), copy_rtx (op1));
Richard Kenner committed
200

201
  set_unique_reg_note (last_insn, REG_EQUAL, note);
Richard Kenner committed
202 203 204 205

  return 1;
}

206 207
/* Widen OP to MODE and return the rtx for the widened operand.  UNSIGNEDP
   says whether OP is signed or unsigned.  NO_EXTEND is nonzero if we need
208
   not actually do a sign-extend or zero-extend, but can leave the
209 210 211 212
   higher-order bits of the result rtx undefined, for example, in the case
   of logical operations, but not right shifts.  */

static rtx
213 214
widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode,
	       int unsignedp, int no_extend)
215 216 217
{
  rtx result;

218 219 220 221 222 223 224
  /* If we don't have to extend and this is a constant, return it.  */
  if (no_extend && GET_MODE (op) == VOIDmode)
    return op;

  /* If we must extend do so.  If OP is a SUBREG for a promoted object, also
     extend since it will be more efficient to do so unless the signedness of
     a promoted object differs from our extension.  */
225
  if (! no_extend
226 227
      || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op)
	  && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp))
228
    return convert_modes (mode, oldmode, op, unsignedp);
229 230 231 232

  /* If MODE is no wider than a single word, we return a paradoxical
     SUBREG.  */
  if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
233
    return gen_rtx_SUBREG (mode, force_reg (GET_MODE (op), op), 0);
234 235 236 237 238

  /* Otherwise, get an object of MODE, clobber it, and set the low-order
     part to OP.  */

  result = gen_reg_rtx (mode);
239
  emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
240 241 242 243
  emit_move_insn (gen_lowpart (GET_MODE (op), result), op);
  return result;
}

244 245 246
/* Generate code to perform a straightforward complex divide.  */

static int
247 248 249 250
expand_cmplxdiv_straight (rtx real0, rtx real1, rtx imag0, rtx imag1,
			  rtx realr, rtx imagr, enum machine_mode submode,
			  int unsignedp, enum optab_methods methods,
			  enum mode_class class, optab binoptab)
251 252 253 254 255
{
  rtx divisor;
  rtx real_t, imag_t;
  rtx temp1, temp2;
  rtx res;
256 257 258 259
  optab this_add_optab = add_optab;
  optab this_sub_optab = sub_optab;
  optab this_neg_optab = neg_optab;
  optab this_mul_optab = smul_optab;
260

261 262 263 264 265 266 267 268
  if (binoptab == sdivv_optab)
    {
      this_add_optab = addv_optab;
      this_sub_optab = subv_optab;
      this_neg_optab = negv_optab;
      this_mul_optab = smulv_optab;
    }

269 270 271 272 273 274 275 276 277 278
  /* Don't fetch these from memory more than once.  */
  real0 = force_reg (submode, real0);
  real1 = force_reg (submode, real1);

  if (imag0 != 0)
    imag0 = force_reg (submode, imag0);

  imag1 = force_reg (submode, imag1);

  /* Divisor: c*c + d*d.  */
279
  temp1 = expand_binop (submode, this_mul_optab, real1, real1,
280 281
			NULL_RTX, unsignedp, methods);

282
  temp2 = expand_binop (submode, this_mul_optab, imag1, imag1,
283 284 285 286 287
			NULL_RTX, unsignedp, methods);

  if (temp1 == 0 || temp2 == 0)
    return 0;

288
  divisor = expand_binop (submode, this_add_optab, temp1, temp2,
289 290 291 292
			  NULL_RTX, unsignedp, methods);
  if (divisor == 0)
    return 0;

293
  if (imag0 == 0)
294 295 296 297 298
    {
      /* Mathematically, ((a)(c-id))/divisor.  */
      /* Computationally, (a+i0) / (c+id) = (ac/(cc+dd)) + i(-ad/(cc+dd)).  */

      /* Calculate the dividend.  */
299
      real_t = expand_binop (submode, this_mul_optab, real0, real1,
300
			     NULL_RTX, unsignedp, methods);
301

302
      imag_t = expand_binop (submode, this_mul_optab, real0, imag1,
303 304 305 306 307
			     NULL_RTX, unsignedp, methods);

      if (real_t == 0 || imag_t == 0)
	return 0;

308
      imag_t = expand_unop (submode, this_neg_optab, imag_t,
309 310 311 312 313 314
			    NULL_RTX, unsignedp);
    }
  else
    {
      /* Mathematically, ((a+ib)(c-id))/divider.  */
      /* Calculate the dividend.  */
315
      temp1 = expand_binop (submode, this_mul_optab, real0, real1,
316 317
			    NULL_RTX, unsignedp, methods);

318
      temp2 = expand_binop (submode, this_mul_optab, imag0, imag1,
319 320 321 322 323
			    NULL_RTX, unsignedp, methods);

      if (temp1 == 0 || temp2 == 0)
	return 0;

324
      real_t = expand_binop (submode, this_add_optab, temp1, temp2,
325
			     NULL_RTX, unsignedp, methods);
326

327
      temp1 = expand_binop (submode, this_mul_optab, imag0, real1,
328 329
			    NULL_RTX, unsignedp, methods);

330
      temp2 = expand_binop (submode, this_mul_optab, real0, imag1,
331 332 333 334 335
			    NULL_RTX, unsignedp, methods);

      if (temp1 == 0 || temp2 == 0)
	return 0;

336
      imag_t = expand_binop (submode, this_sub_optab, temp1, temp2,
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
			     NULL_RTX, unsignedp, methods);

      if (real_t == 0 || imag_t == 0)
	return 0;
    }

  if (class == MODE_COMPLEX_FLOAT)
    res = expand_binop (submode, binoptab, real_t, divisor,
			realr, unsignedp, methods);
  else
    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
			 real_t, divisor, realr, unsignedp);

  if (res == 0)
    return 0;

  if (res != realr)
    emit_move_insn (realr, res);

  if (class == MODE_COMPLEX_FLOAT)
    res = expand_binop (submode, binoptab, imag_t, divisor,
			imagr, unsignedp, methods);
  else
    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
			 imag_t, divisor, imagr, unsignedp);

  if (res == 0)
    return 0;

  if (res != imagr)
    emit_move_insn (imagr, res);

  return 1;
}

/* Generate code to perform a wide-input-range-acceptable complex divide.  */

static int
375 376 377 378
expand_cmplxdiv_wide (rtx real0, rtx real1, rtx imag0, rtx imag1, rtx realr,
		      rtx imagr, enum machine_mode submode, int unsignedp,
		      enum optab_methods methods, enum mode_class class,
		      optab binoptab)
379 380 381 382 383 384
{
  rtx ratio, divisor;
  rtx real_t, imag_t;
  rtx temp1, temp2, lab1, lab2;
  enum machine_mode mode;
  rtx res;
385 386 387 388 389 390 391 392 393 394 395 396
  optab this_add_optab = add_optab;
  optab this_sub_optab = sub_optab;
  optab this_neg_optab = neg_optab;
  optab this_mul_optab = smul_optab;

  if (binoptab == sdivv_optab)
    {
      this_add_optab = addv_optab;
      this_sub_optab = subv_optab;
      this_neg_optab = negv_optab;
      this_mul_optab = smulv_optab;
    }
397

398 399 400 401 402 403 404 405 406
  /* Don't fetch these from memory more than once.  */
  real0 = force_reg (submode, real0);
  real1 = force_reg (submode, real1);

  if (imag0 != 0)
    imag0 = force_reg (submode, imag0);

  imag1 = force_reg (submode, imag1);

407 408 409 410 411 412 413 414
  /* XXX What's an "unsigned" complex number?  */
  if (unsignedp)
    {
      temp1 = real1;
      temp2 = imag1;
    }
  else
    {
415 416
      temp1 = expand_abs (submode, real1, NULL_RTX, unsignedp, 1);
      temp2 = expand_abs (submode, imag1, NULL_RTX, unsignedp, 1);
417
    }
418 419 420 421 422 423 424

  if (temp1 == 0 || temp2 == 0)
    return 0;

  mode = GET_MODE (temp1);
  lab1 = gen_label_rtx ();
  emit_cmp_and_jump_insns (temp1, temp2, LT, NULL_RTX,
425
			   mode, unsignedp, lab1);
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440

  /* |c| >= |d|; use ratio d/c to scale dividend and divisor.  */

  if (class == MODE_COMPLEX_FLOAT)
    ratio = expand_binop (submode, binoptab, imag1, real1,
			  NULL_RTX, unsignedp, methods);
  else
    ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
			   imag1, real1, NULL_RTX, unsignedp);

  if (ratio == 0)
    return 0;

  /* Calculate divisor.  */

441
  temp1 = expand_binop (submode, this_mul_optab, imag1, ratio,
442 443 444 445 446
			NULL_RTX, unsignedp, methods);

  if (temp1 == 0)
    return 0;

447
  divisor = expand_binop (submode, this_add_optab, temp1, real1,
448 449 450 451 452 453 454
			  NULL_RTX, unsignedp, methods);

  if (divisor == 0)
    return 0;

  /* Calculate dividend.  */

455
  if (imag0 == 0)
456 457 458 459 460
    {
      real_t = real0;

      /* Compute a / (c+id) as a / (c+d(d/c)) + i (-a(d/c)) / (c+d(d/c)).  */

461
      imag_t = expand_binop (submode, this_mul_optab, real0, ratio,
462 463 464 465 466
			     NULL_RTX, unsignedp, methods);

      if (imag_t == 0)
	return 0;

467
      imag_t = expand_unop (submode, this_neg_optab, imag_t,
468 469 470 471 472 473 474 475 476 477
			    NULL_RTX, unsignedp);

      if (real_t == 0 || imag_t == 0)
	return 0;
    }
  else
    {
      /* Compute (a+ib)/(c+id) as
	 (a+b(d/c))/(c+d(d/c) + i(b-a(d/c))/(c+d(d/c)).  */

478
      temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
479 480 481 482 483
			    NULL_RTX, unsignedp, methods);

      if (temp1 == 0)
	return 0;

484
      real_t = expand_binop (submode, this_add_optab, temp1, real0,
485 486
			     NULL_RTX, unsignedp, methods);

487
      temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
488 489 490 491 492
			    NULL_RTX, unsignedp, methods);

      if (temp1 == 0)
	return 0;

493
      imag_t = expand_binop (submode, this_sub_optab, imag0, temp1,
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
			     NULL_RTX, unsignedp, methods);

      if (real_t == 0 || imag_t == 0)
	return 0;
    }

  if (class == MODE_COMPLEX_FLOAT)
    res = expand_binop (submode, binoptab, real_t, divisor,
			realr, unsignedp, methods);
  else
    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
			 real_t, divisor, realr, unsignedp);

  if (res == 0)
    return 0;

  if (res != realr)
    emit_move_insn (realr, res);

  if (class == MODE_COMPLEX_FLOAT)
    res = expand_binop (submode, binoptab, imag_t, divisor,
			imagr, unsignedp, methods);
  else
    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
			 imag_t, divisor, imagr, unsignedp);

  if (res == 0)
    return 0;

  if (res != imagr)
    emit_move_insn (imagr, res);

  lab2 = gen_label_rtx ();
  emit_jump_insn (gen_jump (lab2));
  emit_barrier ();

  emit_label (lab1);

  /* |d| > |c|; use ratio c/d to scale dividend and divisor.  */

  if (class == MODE_COMPLEX_FLOAT)
    ratio = expand_binop (submode, binoptab, real1, imag1,
			  NULL_RTX, unsignedp, methods);
  else
    ratio = expand_divmod (0, TRUNC_DIV_EXPR, submode,
			   real1, imag1, NULL_RTX, unsignedp);

  if (ratio == 0)
    return 0;

  /* Calculate divisor.  */

546
  temp1 = expand_binop (submode, this_mul_optab, real1, ratio,
547 548 549 550 551
			NULL_RTX, unsignedp, methods);

  if (temp1 == 0)
    return 0;

552
  divisor = expand_binop (submode, this_add_optab, temp1, imag1,
553 554 555 556 557 558 559
			  NULL_RTX, unsignedp, methods);

  if (divisor == 0)
    return 0;

  /* Calculate dividend.  */

560
  if (imag0 == 0)
561 562 563
    {
      /* Compute a / (c+id) as a(c/d) / (c(c/d)+d) + i (-a) / (c(c/d)+d).  */

564
      real_t = expand_binop (submode, this_mul_optab, real0, ratio,
565 566
			     NULL_RTX, unsignedp, methods);

567
      imag_t = expand_unop (submode, this_neg_optab, real0,
568 569 570 571 572 573 574 575 576 577
			    NULL_RTX, unsignedp);

      if (real_t == 0 || imag_t == 0)
	return 0;
    }
  else
    {
      /* Compute (a+ib)/(c+id) as
	 (a(c/d)+b)/(c(c/d)+d) + i (b(c/d)-a)/(c(c/d)+d).  */

578
      temp1 = expand_binop (submode, this_mul_optab, real0, ratio,
579 580 581 582 583
			    NULL_RTX, unsignedp, methods);

      if (temp1 == 0)
	return 0;

584
      real_t = expand_binop (submode, this_add_optab, temp1, imag0,
585 586
			     NULL_RTX, unsignedp, methods);

587
      temp1 = expand_binop (submode, this_mul_optab, imag0, ratio,
588 589 590 591 592
			    NULL_RTX, unsignedp, methods);

      if (temp1 == 0)
	return 0;

593
      imag_t = expand_binop (submode, this_sub_optab, temp1, real0,
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
			     NULL_RTX, unsignedp, methods);

      if (real_t == 0 || imag_t == 0)
	return 0;
    }

  if (class == MODE_COMPLEX_FLOAT)
    res = expand_binop (submode, binoptab, real_t, divisor,
			realr, unsignedp, methods);
  else
    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
			 real_t, divisor, realr, unsignedp);

  if (res == 0)
    return 0;

  if (res != realr)
    emit_move_insn (realr, res);

  if (class == MODE_COMPLEX_FLOAT)
    res = expand_binop (submode, binoptab, imag_t, divisor,
			imagr, unsignedp, methods);
  else
    res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
			 imag_t, divisor, imagr, unsignedp);

  if (res == 0)
    return 0;

  if (res != imagr)
    emit_move_insn (imagr, res);

  emit_label (lab2);

  return 1;
}

631 632 633 634
/* Wrapper around expand_binop which takes an rtx code to specify
   the operation to perform, not an optab pointer.  All other
   arguments are the same.  */
rtx
635 636 637
expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0,
		     rtx op1, rtx target, int unsignedp,
		     enum optab_methods methods)
638
{
639
  optab binop = code_to_optab[(int) code];
640 641 642 643 644 645
  if (binop == 0)
    abort ();

  return expand_binop (mode, binop, op0, op1, target, unsignedp, methods);
}

Richard Kenner committed
646 647 648 649 650 651 652 653 654 655 656 657
/* Generate code to perform an operation specified by BINOPTAB
   on operands OP0 and OP1, with result having machine-mode MODE.

   UNSIGNEDP is for the case where we have to widen the operands
   to perform the operation.  It says to use zero-extension.

   If TARGET is nonzero, the value
   is generated there, if it is convenient to do so.
   In all cases an rtx is returned for the locus of the value;
   this may or may not be TARGET.  */

rtx
658 659
expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
	      rtx target, int unsignedp, enum optab_methods methods)
Richard Kenner committed
660
{
661 662 663
  enum optab_methods next_methods
    = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN
       ? OPTAB_WIDEN : methods);
Richard Kenner committed
664 665
  enum mode_class class;
  enum machine_mode wider_mode;
666
  rtx temp;
Richard Kenner committed
667
  int commutative_op = 0;
668
  int shift_op = (binoptab->code == ASHIFT
Richard Kenner committed
669 670 671 672
		  || binoptab->code == ASHIFTRT
		  || binoptab->code == LSHIFTRT
		  || binoptab->code == ROTATE
		  || binoptab->code == ROTATERT);
673
  rtx entry_last = get_last_insn ();
Richard Kenner committed
674 675 676 677 678 679 680 681 682 683 684
  rtx last;

  class = GET_MODE_CLASS (mode);

  op0 = protect_from_queue (op0, 0);
  op1 = protect_from_queue (op1, 0);
  if (target)
    target = protect_from_queue (target, 1);

  if (flag_force_mem)
    {
685 686 687 688 689 690 691 692 693 694 695
      /* Load duplicate non-volatile operands once.  */
      if (rtx_equal_p (op0, op1) && ! volatile_refs_p (op0))
	{
	  op0 = force_not_mem (op0);
	  op1 = op0;
	}
      else
	{
	  op0 = force_not_mem (op0);
	  op1 = force_not_mem (op1);
	}
Richard Kenner committed
696 697
    }

698 699 700 701 702 703 704 705 706
  /* If subtracting an integer constant, convert this into an addition of
     the negated constant.  */

  if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
    {
      op1 = negate_rtx (mode, op1);
      binoptab = add_optab;
    }

Richard Kenner committed
707 708
  /* If we are inside an appropriately-short loop and one operand is an
     expensive constant, force it into a register.  */
709
  if (CONSTANT_P (op0) && preserve_subexpressions_p ()
710
      && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
Richard Kenner committed
711 712
    op0 = force_reg (mode, op0);

713
  if (CONSTANT_P (op1) && preserve_subexpressions_p ()
714
      && ! shift_op && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
715
    op1 = force_reg (mode, op1);
Richard Kenner committed
716 717 718 719 720 721 722 723

  /* Record where to delete back to if we backtrack.  */
  last = get_last_insn ();

  /* If operation is commutative,
     try to make the first operand a register.
     Even better, try to make it the same as the target.
     Also try to make the last operand a constant.  */
724
  if (GET_RTX_CLASS (binoptab->code) == RTX_COMM_ARITH
Richard Kenner committed
725
      || binoptab == smul_widen_optab
726 727 728
      || binoptab == umul_widen_optab
      || binoptab == smul_highpart_optab
      || binoptab == umul_highpart_optab)
Richard Kenner committed
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
    {
      commutative_op = 1;

      if (((target == 0 || GET_CODE (target) == REG)
	   ? ((GET_CODE (op1) == REG
	       && GET_CODE (op0) != REG)
	      || target == op1)
	   : rtx_equal_p (op1, target))
	  || GET_CODE (op0) == CONST_INT)
	{
	  temp = op1;
	  op1 = op0;
	  op0 = temp;
	}
    }

  /* If we can do it with a three-operand insn, do so.  */

  if (methods != OPTAB_MUST_WIDEN
      && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
    {
      int icode = (int) binoptab->handlers[(int) mode].insn_code;
751 752
      enum machine_mode mode0 = insn_data[icode].operand[1].mode;
      enum machine_mode mode1 = insn_data[icode].operand[2].mode;
Richard Kenner committed
753 754 755 756 757 758 759 760 761
      rtx pat;
      rtx xop0 = op0, xop1 = op1;

      if (target)
	temp = target;
      else
	temp = gen_reg_rtx (mode);

      /* If it is a commutative operator and the modes would match
Mike Stump committed
762
	 if we would swap the operands, we can save the conversions.  */
Richard Kenner committed
763 764 765 766 767
      if (commutative_op)
	{
	  if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
	      && GET_MODE (op0) == mode1 && GET_MODE (op1) == mode0)
	    {
768
	      rtx tmp;
Richard Kenner committed
769 770 771 772 773 774 775

	      tmp = op0; op0 = op1; op1 = tmp;
	      tmp = xop0; xop0 = xop1; xop1 = tmp;
	    }
	}

      /* In case the insn wants input operands in modes different from
776 777
	 those of the actual operands, convert the operands.  It would
	 seem that we don't need to convert CONST_INTs, but we do, so
778 779
	 that they're properly zero-extended, sign-extended or truncated
	 for their mode.  */
Richard Kenner committed
780

781
      if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
782 783 784
	xop0 = convert_modes (mode0,
			      GET_MODE (op0) != VOIDmode
			      ? GET_MODE (op0)
785
			      : mode,
786
			      xop0, unsignedp);
Richard Kenner committed
787

788
      if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
789 790 791
	xop1 = convert_modes (mode1,
			      GET_MODE (op1) != VOIDmode
			      ? GET_MODE (op1)
792
			      : mode,
793
			      xop1, unsignedp);
Richard Kenner committed
794 795 796 797

      /* Now, if insn's predicates don't allow our operands, put them into
	 pseudo regs.  */

798
      if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0)
799
	  && mode0 != VOIDmode)
Richard Kenner committed
800 801
	xop0 = copy_to_mode_reg (mode0, xop0);

802
      if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1)
803
	  && mode1 != VOIDmode)
Richard Kenner committed
804 805
	xop1 = copy_to_mode_reg (mode1, xop1);

806
      if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
Richard Kenner committed
807 808 809 810 811
	temp = gen_reg_rtx (mode);

      pat = GEN_FCN (icode) (temp, xop0, xop1);
      if (pat)
	{
812
	  /* If PAT is composed of more than one insn, try to add an appropriate
Richard Kenner committed
813 814
	     REG_EQUAL note to it.  If we can't because TEMP conflicts with an
	     operand, call ourselves again, this time without a target.  */
815
	  if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
Richard Kenner committed
816 817 818
	      && ! add_equal_note (pat, temp, binoptab->code, xop0, xop1))
	    {
	      delete_insns_since (last);
Charles Hannum committed
819 820
	      return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
				   unsignedp, methods);
Richard Kenner committed
821 822 823 824 825 826 827 828 829
	    }

	  emit_insn (pat);
	  return temp;
	}
      else
	delete_insns_since (last);
    }

830 831 832 833 834 835 836 837 838 839
  /* If this is a multiply, see if we can do a widening operation that
     takes operands of this mode and makes a wider mode.  */

  if (binoptab == smul_optab && GET_MODE_WIDER_MODE (mode) != VOIDmode
      && (((unsignedp ? umul_widen_optab : smul_widen_optab)
	   ->handlers[(int) GET_MODE_WIDER_MODE (mode)].insn_code)
	  != CODE_FOR_nothing))
    {
      temp = expand_binop (GET_MODE_WIDER_MODE (mode),
			   unsignedp ? umul_widen_optab : smul_widen_optab,
840
			   op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
841

842 843 844 845 846 847 848
      if (temp != 0)
	{
	  if (GET_MODE_CLASS (mode) == MODE_INT)
	    return gen_lowpart (mode, temp);
	  else
	    return convert_to_mode (mode, temp, unsignedp);
	}
849 850
    }

851
  /* Look for a wider mode of the same class for which we think we
852 853
     can open-code the operation.  Check for a widening multiply at the
     wider mode as well.  */
854 855

  if ((class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
856
      && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
857 858 859
    for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
	 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
      {
860 861 862 863 864 865
	if (binoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing
	    || (binoptab == smul_optab
		&& GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
		&& (((unsignedp ? umul_widen_optab : smul_widen_optab)
		     ->handlers[(int) GET_MODE_WIDER_MODE (wider_mode)].insn_code)
		    != CODE_FOR_nothing)))
866 867 868 869 870 871
	  {
	    rtx xop0 = op0, xop1 = op1;
	    int no_extend = 0;

	    /* For certain integer operations, we need not actually extend
	       the narrow operands, as long as we will truncate
Kazu Hirata committed
872
	       the results to the same narrowness.  */
873 874 875 876

	    if ((binoptab == ior_optab || binoptab == and_optab
		 || binoptab == xor_optab
		 || binoptab == add_optab || binoptab == sub_optab
Richard Kenner committed
877
		 || binoptab == smul_optab || binoptab == ashl_optab)
878
		&& class == MODE_INT)
879 880
	      no_extend = 1;

881
	    xop0 = widen_operand (xop0, wider_mode, mode, unsignedp, no_extend);
882 883

	    /* The second operand of a shift must always be extended.  */
884
	    xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
Richard Kenner committed
885
				  no_extend && binoptab != ashl_optab);
886

Charles Hannum committed
887
	    temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
				 unsignedp, OPTAB_DIRECT);
	    if (temp)
	      {
		if (class != MODE_INT)
		  {
		    if (target == 0)
		      target = gen_reg_rtx (mode);
		    convert_move (target, temp, 0);
		    return target;
		  }
		else
		  return gen_lowpart (mode, temp);
	      }
	    else
	      delete_insns_since (last);
	  }
      }

Richard Kenner committed
906 907 908 909
  /* These can be done a word at a time.  */
  if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab)
      && class == MODE_INT
      && GET_MODE_SIZE (mode) > UNITS_PER_WORD
910
      && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
Richard Kenner committed
911
    {
912
      int i;
Richard Kenner committed
913 914 915 916 917 918 919 920 921 922 923 924 925 926
      rtx insns;
      rtx equiv_value;

      /* If TARGET is the same as one of the operands, the REG_EQUAL note
	 won't be accurate, so use a new target.  */
      if (target == 0 || target == op0 || target == op1)
	target = gen_reg_rtx (mode);

      start_sequence ();

      /* Do the actual arithmetic.  */
      for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
	{
	  rtx target_piece = operand_subword (target, i, 1, mode);
927
	  rtx x = expand_binop (word_mode, binoptab,
Richard Kenner committed
928 929
				operand_subword_force (op0, i, mode),
				operand_subword_force (op1, i, mode),
930 931 932 933 934
				target_piece, unsignedp, next_methods);

	  if (x == 0)
	    break;

Richard Kenner committed
935 936 937 938 939 940 941
	  if (target_piece != x)
	    emit_move_insn (target_piece, x);
	}

      insns = get_insns ();
      end_sequence ();

942 943 944 945
      if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
	{
	  if (binoptab->code != UNKNOWN)
	    equiv_value
946 947
	      = gen_rtx_fmt_ee (binoptab->code, mode,
				copy_rtx (op0), copy_rtx (op1));
948 949
	  else
	    equiv_value = 0;
Richard Kenner committed
950

951 952 953
	  emit_no_conflict_block (insns, target, op0, op1, equiv_value);
	  return target;
	}
Richard Kenner committed
954 955
    }

956
  /* Synthesize double word shifts from single word shifts.  */
Richard Kenner committed
957 958
  if ((binoptab == lshr_optab || binoptab == ashl_optab
       || binoptab == ashr_optab)
959 960 961 962 963 964 965
      && class == MODE_INT
      && GET_CODE (op1) == CONST_INT
      && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
      && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
      && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
      && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
    {
966
      rtx insns, inter, equiv_value;
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
      rtx into_target, outof_target;
      rtx into_input, outof_input;
      int shift_count, left_shift, outof_word;

      /* If TARGET is the same as one of the operands, the REG_EQUAL note
	 won't be accurate, so use a new target.  */
      if (target == 0 || target == op0 || target == op1)
	target = gen_reg_rtx (mode);

      start_sequence ();

      shift_count = INTVAL (op1);

      /* OUTOF_* is the word we are shifting bits away from, and
	 INTO_* is the word that we are shifting bits towards, thus
	 they differ depending on the direction of the shift and
	 WORDS_BIG_ENDIAN.  */

Richard Kenner committed
985
      left_shift = binoptab == ashl_optab;
986 987 988 989 990 991 992 993 994 995
      outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;

      outof_target = operand_subword (target, outof_word, 1, mode);
      into_target = operand_subword (target, 1 - outof_word, 1, mode);

      outof_input = operand_subword_force (op0, outof_word, mode);
      into_input = operand_subword_force (op0, 1 - outof_word, mode);

      if (shift_count >= BITS_PER_WORD)
	{
996 997 998 999 1000
	  inter = expand_binop (word_mode, binoptab,
			       outof_input,
			       GEN_INT (shift_count - BITS_PER_WORD),
			       into_target, unsignedp, next_methods);

1001
	  if (inter != 0 && inter != into_target)
1002
	    emit_move_insn (into_target, inter);
1003 1004 1005

	  /* For a signed right shift, we must fill the word we are shifting
	     out of with copies of the sign bit.  Otherwise it is zeroed.  */
1006 1007
	  if (inter != 0 && binoptab != ashr_optab)
	    inter = CONST0_RTX (word_mode);
1008 1009 1010 1011 1012 1013
	  else if (inter != 0)
	    inter = expand_binop (word_mode, binoptab,
				  outof_input,
				  GEN_INT (BITS_PER_WORD - 1),
				  outof_target, unsignedp, next_methods);

1014
	  if (inter != 0 && inter != outof_target)
1015
	    emit_move_insn (outof_target, inter);
1016 1017 1018
	}
      else
	{
1019
	  rtx carries;
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
	  optab reverse_unsigned_shift, unsigned_shift;

	  /* For a shift of less then BITS_PER_WORD, to compute the carry,
	     we must do a logical shift in the opposite direction of the
	     desired shift.  */

	  reverse_unsigned_shift = (left_shift ? lshr_optab : ashl_optab);

	  /* For a shift of less than BITS_PER_WORD, to compute the word
	     shifted towards, we need to unsigned shift the orig value of
	     that word.  */

	  unsigned_shift = (left_shift ? ashl_optab : lshr_optab);

	  carries = expand_binop (word_mode, reverse_unsigned_shift,
				  outof_input,
				  GEN_INT (BITS_PER_WORD - shift_count),
1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048
				  0, unsignedp, next_methods);

	  if (carries == 0)
	    inter = 0;
	  else
	    inter = expand_binop (word_mode, unsigned_shift, into_input,
				  op1, 0, unsignedp, next_methods);

	  if (inter != 0)
	    inter = expand_binop (word_mode, ior_optab, carries, inter,
				  into_target, unsignedp, next_methods);

1049
	  if (inter != 0 && inter != into_target)
1050
	    emit_move_insn (into_target, inter);
1051 1052 1053 1054

	  if (inter != 0)
	    inter = expand_binop (word_mode, binoptab, outof_input,
				  op1, outof_target, unsignedp, next_methods);
1055

1056 1057
	  if (inter != 0 && inter != outof_target)
	    emit_move_insn (outof_target, inter);
1058 1059 1060 1061 1062
	}

      insns = get_insns ();
      end_sequence ();

1063 1064 1065
      if (inter != 0)
	{
	  if (binoptab->code != UNKNOWN)
1066
	    equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1067 1068
	  else
	    equiv_value = 0;
1069

1070 1071 1072
	  emit_no_conflict_block (insns, target, op0, op1, equiv_value);
	  return target;
	}
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
    }

  /* Synthesize double word rotates from single word shifts.  */
  if ((binoptab == rotl_optab || binoptab == rotr_optab)
      && class == MODE_INT
      && GET_CODE (op1) == CONST_INT
      && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
      && ashl_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
      && lshr_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
    {
      rtx insns, equiv_value;
      rtx into_target, outof_target;
      rtx into_input, outof_input;
1086
      rtx inter;
1087 1088 1089
      int shift_count, left_shift, outof_word;

      /* If TARGET is the same as one of the operands, the REG_EQUAL note
1090 1091 1092 1093 1094 1095
	 won't be accurate, so use a new target. Do this also if target is not
	 a REG, first because having a register instead may open optimization
	 oportunities, and second because if target and op0 happen to be MEMs
	 designating the same location, we would risk clobbering it too early
	 in the code sequence we generate below.  */
      if (target == 0 || target == op0 || target == op1 || ! REG_P (target))
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
	target = gen_reg_rtx (mode);

      start_sequence ();

      shift_count = INTVAL (op1);

      /* OUTOF_* is the word we are shifting bits away from, and
	 INTO_* is the word that we are shifting bits towards, thus
	 they differ depending on the direction of the shift and
	 WORDS_BIG_ENDIAN.  */

      left_shift = (binoptab == rotl_optab);
      outof_word = left_shift ^ ! WORDS_BIG_ENDIAN;

      outof_target = operand_subword (target, outof_word, 1, mode);
      into_target = operand_subword (target, 1 - outof_word, 1, mode);

      outof_input = operand_subword_force (op0, outof_word, mode);
      into_input = operand_subword_force (op0, 1 - outof_word, mode);

      if (shift_count == BITS_PER_WORD)
	{
	  /* This is just a word swap.  */
	  emit_move_insn (outof_target, into_input);
	  emit_move_insn (into_target, outof_input);
1121
	  inter = const0_rtx;
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
	}
      else
	{
	  rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
	  rtx first_shift_count, second_shift_count;
	  optab reverse_unsigned_shift, unsigned_shift;

	  reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
				    ? lshr_optab : ashl_optab);

	  unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD)
			    ? ashl_optab : lshr_optab);

	  if (shift_count > BITS_PER_WORD)
	    {
	      first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
1138
	      second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
1139 1140 1141 1142 1143 1144 1145 1146 1147
	    }
	  else
	    {
	      first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
	      second_shift_count = GEN_INT (shift_count);
	    }

	  into_temp1 = expand_binop (word_mode, unsigned_shift,
				     outof_input, first_shift_count,
1148
				     NULL_RTX, unsignedp, next_methods);
1149 1150
	  into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
				     into_input, second_shift_count,
1151
				     NULL_RTX, unsignedp, next_methods);
1152 1153 1154 1155 1156 1157 1158

	  if (into_temp1 != 0 && into_temp2 != 0)
	    inter = expand_binop (word_mode, ior_optab, into_temp1, into_temp2,
				  into_target, unsignedp, next_methods);
	  else
	    inter = 0;

1159
	  if (inter != 0 && inter != into_target)
1160
	    emit_move_insn (into_target, inter);
1161 1162 1163

	  outof_temp1 = expand_binop (word_mode, unsigned_shift,
				      into_input, first_shift_count,
1164
				      NULL_RTX, unsignedp, next_methods);
1165 1166
	  outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
				      outof_input, second_shift_count,
1167
				      NULL_RTX, unsignedp, next_methods);
1168 1169 1170 1171 1172 1173

	  if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
	    inter = expand_binop (word_mode, ior_optab,
				  outof_temp1, outof_temp2,
				  outof_target, unsignedp, next_methods);

1174
	  if (inter != 0 && inter != outof_target)
1175
	    emit_move_insn (outof_target, inter);
1176 1177 1178 1179 1180
	}

      insns = get_insns ();
      end_sequence ();

1181 1182 1183
      if (inter != 0)
	{
	  if (binoptab->code != UNKNOWN)
1184
	    equiv_value = gen_rtx_fmt_ee (binoptab->code, mode, op0, op1);
1185 1186
	  else
	    equiv_value = 0;
1187

1188 1189 1190 1191 1192 1193
	  /* We can't make this a no conflict block if this is a word swap,
	     because the word swap case fails if the input and output values
	     are in the same register.  */
	  if (shift_count != BITS_PER_WORD)
	    emit_no_conflict_block (insns, target, op0, op1, equiv_value);
	  else
1194
	    emit_insn (insns);
1195 1196 1197 1198


	  return target;
	}
1199 1200
    }

Richard Kenner committed
1201 1202 1203 1204
  /* These can be done a word at a time by propagating carries.  */
  if ((binoptab == add_optab || binoptab == sub_optab)
      && class == MODE_INT
      && GET_MODE_SIZE (mode) >= 2 * UNITS_PER_WORD
1205
      && binoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
Richard Kenner committed
1206
    {
1207
      unsigned int i;
Richard Kenner committed
1208
      optab otheroptab = binoptab == add_optab ? sub_optab : add_optab;
1209
      const unsigned int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
1210
      rtx carry_in = NULL_RTX, carry_out = NULL_RTX;
1211
      rtx xop0, xop1, xtarget;
Richard Kenner committed
1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222

      /* We can handle either a 1 or -1 value for the carry.  If STORE_FLAG
	 value is one of those, use it.  Otherwise, use 1 since it is the
	 one easiest to get.  */
#if STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1
      int normalizep = STORE_FLAG_VALUE;
#else
      int normalizep = 1;
#endif

      /* Prepare the operands.  */
1223 1224
      xop0 = force_reg (mode, op0);
      xop1 = force_reg (mode, op1);
Richard Kenner committed
1225

1226 1227 1228 1229
      xtarget = gen_reg_rtx (mode);

      if (target == 0 || GET_CODE (target) != REG)
	target = xtarget;
Richard Kenner committed
1230

1231 1232
      /* Indicate for flow that the entire target reg is being set.  */
      if (GET_CODE (target) == REG)
1233
	emit_insn (gen_rtx_CLOBBER (VOIDmode, xtarget));
1234

Richard Kenner committed
1235 1236 1237 1238
      /* Do the actual arithmetic.  */
      for (i = 0; i < nwords; i++)
	{
	  int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
1239
	  rtx target_piece = operand_subword (xtarget, index, 1, mode);
1240 1241
	  rtx op0_piece = operand_subword_force (xop0, index, mode);
	  rtx op1_piece = operand_subword_force (xop1, index, mode);
Richard Kenner committed
1242 1243 1244
	  rtx x;

	  /* Main add/subtract of the input operands.  */
1245
	  x = expand_binop (word_mode, binoptab,
Richard Kenner committed
1246
			    op0_piece, op1_piece,
1247
			    target_piece, unsignedp, next_methods);
Richard Kenner committed
1248 1249 1250 1251 1252 1253
	  if (x == 0)
	    break;

	  if (i + 1 < nwords)
	    {
	      /* Store carry from main add/subtract.  */
1254
	      carry_out = gen_reg_rtx (word_mode);
1255 1256
	      carry_out = emit_store_flag_force (carry_out,
						 (binoptab == add_optab
1257
						  ? LT : GT),
1258 1259
						 x, op0_piece,
						 word_mode, 1, normalizep);
Richard Kenner committed
1260 1261 1262 1263
	    }

	  if (i > 0)
	    {
1264
	      rtx newx;
1265

Richard Kenner committed
1266
	      /* Add/subtract previous carry to main result.  */
1267 1268 1269 1270
	      newx = expand_binop (word_mode,
				   normalizep == 1 ? binoptab : otheroptab,
				   x, carry_in,
				   NULL_RTX, 1, next_methods);
Richard Kenner committed
1271 1272 1273 1274

	      if (i + 1 < nwords)
		{
		  /* Get out carry from adding/subtracting carry in.  */
1275
		  rtx carry_tmp = gen_reg_rtx (word_mode);
1276
		  carry_tmp = emit_store_flag_force (carry_tmp,
1277 1278 1279
						     (binoptab == add_optab
						      ? LT : GT),
						     newx, x,
1280
						     word_mode, 1, normalizep);
1281

Richard Kenner committed
1282
		  /* Logical-ior the two poss. carry together.  */
1283
		  carry_out = expand_binop (word_mode, ior_optab,
Richard Kenner committed
1284
					    carry_out, carry_tmp,
1285 1286
					    carry_out, 0, next_methods);
		  if (carry_out == 0)
Richard Kenner committed
1287 1288
		    break;
		}
1289
	      emit_move_insn (target_piece, newx);
Richard Kenner committed
1290 1291 1292
	    }

	  carry_in = carry_out;
1293
	}
Richard Kenner committed
1294

1295
      if (i == GET_MODE_BITSIZE (mode) / (unsigned) BITS_PER_WORD)
Richard Kenner committed
1296
	{
1297 1298
	  if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
	      || ! rtx_equal_p (target, xtarget))
1299
	    {
1300
	      rtx temp = emit_move_insn (target, xtarget);
1301

1302
	      set_unique_reg_note (temp,
1303
				   REG_EQUAL,
1304 1305 1306
				   gen_rtx_fmt_ee (binoptab->code, mode,
						   copy_rtx (xop0),
						   copy_rtx (xop1)));
1307
	    }
1308 1309
	  else
	    target = xtarget;
Jeff Law committed
1310

Richard Kenner committed
1311 1312
	  return target;
	}
Jeff Law committed
1313

Richard Kenner committed
1314 1315 1316 1317 1318 1319 1320
      else
	delete_insns_since (last);
    }

  /* If we want to multiply two two-word values and have normal and widening
     multiplies of single-word values, we can do this with three smaller
     multiplications.  Note that we do not make a REG_NO_CONFLICT block here
1321
     because we are not operating on one word at a time.
Richard Kenner committed
1322 1323

     The multiplication proceeds as follows:
1324 1325 1326
			         _______________________
			        [__op0_high_|__op0_low__]
			         _______________________
1327
        *			[__op1_high_|__op1_low__]
1328 1329
        _______________________________________________
			         _______________________
1330
    (1)				[__op0_low__*__op1_low__]
1331
		     _______________________
1332
    (2a)	    [__op0_low__*__op1_high_]
1333
		     _______________________
1334
    (2b)	    [__op0_high_*__op1_low__]
1335 1336
         _______________________
    (3) [__op0_high_*__op1_high_]
Richard Kenner committed
1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370


    This gives a 4-word result.  Since we are only interested in the
    lower 2 words, partial result (3) and the upper words of (2a) and
    (2b) don't need to be calculated.  Hence (2a) and (2b) can be
    calculated using non-widening multiplication.

    (1), however, needs to be calculated with an unsigned widening
    multiplication.  If this operation is not directly supported we
    try using a signed widening multiplication and adjust the result.
    This adjustment works as follows:

      If both operands are positive then no adjustment is needed.

      If the operands have different signs, for example op0_low < 0 and
      op1_low >= 0, the instruction treats the most significant bit of
      op0_low as a sign bit instead of a bit with significance
      2**(BITS_PER_WORD-1), i.e. the instruction multiplies op1_low
      with 2**BITS_PER_WORD - op0_low, and two's complements the
      result.  Conclusion: We need to add op1_low * 2**BITS_PER_WORD to
      the result.

      Similarly, if both operands are negative, we need to add
      (op0_low + op1_low) * 2**BITS_PER_WORD.

      We use a trick to adjust quickly.  We logically shift op0_low right
      (op1_low) BITS_PER_WORD-1 steps to get 0 or 1, and add this to
      op0_high (op1_high) before it is used to calculate 2b (2a).  If no
      logical shift exists, we do an arithmetic right shift and subtract
      the 0 or -1.  */

  if (binoptab == smul_optab
      && class == MODE_INT
      && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
1371 1372
      && smul_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
      && add_optab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing
Richard Kenner committed
1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384
      && ((umul_widen_optab->handlers[(int) mode].insn_code
	   != CODE_FOR_nothing)
	  || (smul_widen_optab->handlers[(int) mode].insn_code
	      != CODE_FOR_nothing)))
    {
      int low = (WORDS_BIG_ENDIAN ? 1 : 0);
      int high = (WORDS_BIG_ENDIAN ? 0 : 1);
      rtx op0_high = operand_subword_force (op0, high, mode);
      rtx op0_low = operand_subword_force (op0, low, mode);
      rtx op1_high = operand_subword_force (op1, high, mode);
      rtx op1_low = operand_subword_force (op1, low, mode);
      rtx product = 0;
1385 1386
      rtx op0_xhigh = NULL_RTX;
      rtx op1_xhigh = NULL_RTX;
Richard Kenner committed
1387 1388 1389

      /* If the target is the same as one of the inputs, don't use it.  This
	 prevents problems with the REG_EQUAL note.  */
1390 1391
      if (target == op0 || target == op1
	  || (target != 0 && GET_CODE (target) != REG))
Richard Kenner committed
1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
	target = 0;

      /* Multiply the two lower words to get a double-word product.
	 If unsigned widening multiplication is available, use that;
	 otherwise use the signed form and compensate.  */

      if (umul_widen_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
	{
	  product = expand_binop (mode, umul_widen_optab, op0_low, op1_low,
				  target, 1, OPTAB_DIRECT);

	  /* If we didn't succeed, delete everything we did so far.  */
	  if (product == 0)
	    delete_insns_since (last);
	  else
	    op0_xhigh = op0_high, op1_xhigh = op1_high;
	}

      if (product == 0
	  && smul_widen_optab->handlers[(int) mode].insn_code
	       != CODE_FOR_nothing)
	{
Charles Hannum committed
1414
	  rtx wordm1 = GEN_INT (BITS_PER_WORD - 1);
Richard Kenner committed
1415 1416
	  product = expand_binop (mode, smul_widen_optab, op0_low, op1_low,
				  target, 1, OPTAB_DIRECT);
1417
	  op0_xhigh = expand_binop (word_mode, lshr_optab, op0_low, wordm1,
1418
				    NULL_RTX, 1, next_methods);
Richard Kenner committed
1419
	  if (op0_xhigh)
1420
	    op0_xhigh = expand_binop (word_mode, add_optab, op0_high,
1421
				      op0_xhigh, op0_xhigh, 0, next_methods);
Richard Kenner committed
1422 1423
	  else
	    {
1424
	      op0_xhigh = expand_binop (word_mode, ashr_optab, op0_low, wordm1,
1425
					NULL_RTX, 0, next_methods);
Richard Kenner committed
1426
	      if (op0_xhigh)
1427
		op0_xhigh = expand_binop (word_mode, sub_optab, op0_high,
Richard Kenner committed
1428
					  op0_xhigh, op0_xhigh, 0,
1429
					  next_methods);
Richard Kenner committed
1430 1431
	    }

1432
	  op1_xhigh = expand_binop (word_mode, lshr_optab, op1_low, wordm1,
1433
				    NULL_RTX, 1, next_methods);
Richard Kenner committed
1434
	  if (op1_xhigh)
1435
	    op1_xhigh = expand_binop (word_mode, add_optab, op1_high,
1436
				      op1_xhigh, op1_xhigh, 0, next_methods);
Richard Kenner committed
1437 1438
	  else
	    {
1439
	      op1_xhigh = expand_binop (word_mode, ashr_optab, op1_low, wordm1,
1440
					NULL_RTX, 0, next_methods);
Richard Kenner committed
1441
	      if (op1_xhigh)
1442
		op1_xhigh = expand_binop (word_mode, sub_optab, op1_high,
Richard Kenner committed
1443
					  op1_xhigh, op1_xhigh, 0,
1444
					  next_methods);
Richard Kenner committed
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460
	    }
	}

      /* If we have been able to directly compute the product of the
	 low-order words of the operands and perform any required adjustments
	 of the operands, we proceed by trying two more multiplications
	 and then computing the appropriate sum.

	 We have checked above that the required addition is provided.
	 Full-word addition will normally always succeed, especially if
	 it is provided at all, so we don't worry about its failure.  The
	 multiplication may well fail, however, so we do handle that.  */

      if (product && op0_xhigh && op1_xhigh)
	{
	  rtx product_high = operand_subword (product, high, 1, mode);
Charles Hannum committed
1461 1462
	  rtx temp = expand_binop (word_mode, binoptab, op0_low, op1_xhigh,
				   NULL_RTX, 0, OPTAB_DIRECT);
Richard Kenner committed
1463

1464 1465 1466
	  if (!REG_P (product_high))
	    product_high = force_reg (word_mode, product_high);

1467 1468 1469
	  if (temp != 0)
	    temp = expand_binop (word_mode, add_optab, temp, product_high,
				 product_high, 0, next_methods);
Richard Kenner committed
1470

1471 1472 1473 1474
	  if (temp != 0 && temp != product_high)
	    emit_move_insn (product_high, temp);

	  if (temp != 0)
1475
	    temp = expand_binop (word_mode, binoptab, op1_low, op0_xhigh,
1476 1477 1478 1479 1480 1481
				 NULL_RTX, 0, OPTAB_DIRECT);

	  if (temp != 0)
	    temp = expand_binop (word_mode, add_optab, temp,
				 product_high, product_high,
				 0, next_methods);
Richard Kenner committed
1482

1483 1484
	  if (temp != 0 && temp != product_high)
	    emit_move_insn (product_high, temp);
Richard Kenner committed
1485

1486 1487
	  emit_move_insn (operand_subword (product, high, 1, mode), product_high);

1488 1489
	  if (temp != 0)
	    {
1490 1491 1492
	      if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
		{
		  temp = emit_move_insn (product, product);
1493
		  set_unique_reg_note (temp,
1494
				       REG_EQUAL,
1495 1496 1497
				       gen_rtx_fmt_ee (MULT, mode,
						       copy_rtx (op0),
						       copy_rtx (op1)));
1498
		}
Jeff Law committed
1499

Richard Kenner committed
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510
	      return product;
	    }
	}

      /* If we get here, we couldn't do it for some reason even though we
	 originally thought we could.  Delete anything we've emitted in
	 trying to do it.  */

      delete_insns_since (last);
    }

Aldy Hernandez committed
1511 1512 1513 1514 1515 1516
  /* Open-code the vector operations if we have no hardware support
     for them.  */
  if (class == MODE_VECTOR_INT || class == MODE_VECTOR_FLOAT)
    return expand_vector_binop (mode, binoptab, op0, op1, target,
				unsignedp, methods);

1517 1518 1519 1520 1521 1522
  /* We need to open-code the complex type operations: '+, -, * and /' */

  /* At this point we allow operations between two similar complex
     numbers, and also if one of the operands is not a complex number
     but rather of MODE_FLOAT or MODE_INT. However, the caller
     must make sure that the MODE of the non-complex operand matches
1523
     the SUBMODE of the complex operand.  */
1524 1525

  if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
1526
    {
1527 1528 1529
      rtx real0 = 0, imag0 = 0;
      rtx real1 = 0, imag1 = 0;
      rtx realr, imagr, res;
1530
      rtx seq, result;
1531
      int ok = 0;
1532

1533
      /* Find the correct mode for the real and imaginary parts.  */
1534
      enum machine_mode submode = GET_MODE_INNER (mode);
1535 1536 1537 1538 1539 1540 1541 1542

      if (submode == BLKmode)
	abort ();

      start_sequence ();

      if (GET_MODE (op0) == mode)
	{
1543
	  real0 = gen_realpart (submode, op0);
1544
	  imag0 = gen_imagpart (submode, op0);
1545 1546 1547 1548 1549 1550
	}
      else
	real0 = op0;

      if (GET_MODE (op1) == mode)
	{
1551
	  real1 = gen_realpart (submode, op1);
1552
	  imag1 = gen_imagpart (submode, op1);
1553 1554 1555 1556
	}
      else
	real1 = op1;

1557
      if (real0 == 0 || real1 == 0 || ! (imag0 != 0 || imag1 != 0))
1558 1559
	abort ();

1560 1561 1562 1563
      result = gen_reg_rtx (mode);
      realr = gen_realpart (submode, result);
      imagr = gen_imagpart (submode, result);

1564 1565 1566
      switch (binoptab->code)
	{
	case PLUS:
1567
	  /* (a+ib) + (c+id) = (a+c) + i(b+d) */
1568
	case MINUS:
1569
	  /* (a+ib) - (c+id) = (a-c) + i(b-d) */
1570 1571
	  res = expand_binop (submode, binoptab, real0, real1,
			      realr, unsignedp, methods);
1572 1573 1574 1575

	  if (res == 0)
	    break;
	  else if (res != realr)
1576 1577
	    emit_move_insn (realr, res);

1578
	  if (imag0 != 0 && imag1 != 0)
1579 1580
	    res = expand_binop (submode, binoptab, imag0, imag1,
				imagr, unsignedp, methods);
1581
	  else if (imag0 != 0)
1582 1583
	    res = imag0;
	  else if (binoptab->code == MINUS)
1584 1585 1586
            res = expand_unop (submode,
                                binoptab == subv_optab ? negv_optab : neg_optab,
                                imag1, imagr, unsignedp);
1587 1588 1589
	  else
	    res = imag1;

1590 1591 1592
	  if (res == 0)
	    break;
	  else if (res != imagr)
1593
	    emit_move_insn (imagr, res);
1594 1595

	  ok = 1;
1596
	  break;
1597 1598

	case MULT:
1599 1600
	  /* (a+ib) * (c+id) = (ac-bd) + i(ad+cb) */

1601
	  if (imag0 != 0 && imag1 != 0)
1602
	    {
1603 1604
	      rtx temp1, temp2;

1605 1606 1607 1608 1609 1610
	      /* Don't fetch these from memory more than once.  */
	      real0 = force_reg (submode, real0);
	      real1 = force_reg (submode, real1);
	      imag0 = force_reg (submode, imag0);
	      imag1 = force_reg (submode, imag1);

1611 1612 1613 1614 1615 1616 1617 1618 1619
	      temp1 = expand_binop (submode, binoptab, real0, real1, NULL_RTX,
				    unsignedp, methods);

	      temp2 = expand_binop (submode, binoptab, imag0, imag1, NULL_RTX,
				    unsignedp, methods);

	      if (temp1 == 0 || temp2 == 0)
		break;

1620 1621 1622 1623
	      res = (expand_binop
                     (submode,
                      binoptab == smulv_optab ? subv_optab : sub_optab,
                      temp1, temp2, realr, unsignedp, methods));
1624

1625 1626 1627
	      if (res == 0)
		break;
	      else if (res != realr)
1628
		emit_move_insn (realr, res);
1629

1630 1631 1632
	      temp1 = expand_binop (submode, binoptab, real0, imag1,
				    NULL_RTX, unsignedp, methods);

1633 1634 1635 1636 1637 1638 1639
	      /* Avoid expanding redundant multiplication for the common
		 case of squaring a complex number.  */
	      if (rtx_equal_p (real0, real1) && rtx_equal_p (imag0, imag1))
		temp2 = temp1;
	      else
		temp2 = expand_binop (submode, binoptab, real1, imag0,
				      NULL_RTX, unsignedp, methods);
1640 1641

	      if (temp1 == 0 || temp2 == 0)
1642
		break;
1643

1644 1645 1646 1647
	      res = (expand_binop
                     (submode,
                      binoptab == smulv_optab ? addv_optab : add_optab,
                      temp1, temp2, imagr, unsignedp, methods));
1648 1649 1650 1651

	      if (res == 0)
		break;
	      else if (res != imagr)
1652
		emit_move_insn (imagr, res);
1653 1654

	      ok = 1;
1655 1656 1657
	    }
	  else
	    {
1658 1659 1660 1661
	      /* Don't fetch these from memory more than once.  */
	      real0 = force_reg (submode, real0);
	      real1 = force_reg (submode, real1);

1662 1663
	      res = expand_binop (submode, binoptab, real0, real1,
				  realr, unsignedp, methods);
1664 1665 1666
	      if (res == 0)
		break;
	      else if (res != realr)
1667 1668
		emit_move_insn (realr, res);

1669
	      if (imag0 != 0)
1670 1671 1672 1673 1674
		res = expand_binop (submode, binoptab,
				    real1, imag0, imagr, unsignedp, methods);
	      else
		res = expand_binop (submode, binoptab,
				    real0, imag1, imagr, unsignedp, methods);
1675 1676 1677 1678

	      if (res == 0)
		break;
	      else if (res != imagr)
1679
		emit_move_insn (imagr, res);
1680 1681

	      ok = 1;
1682 1683
	    }
	  break;
1684 1685

	case DIV:
1686
	  /* (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) */
1687

1688
	  if (imag1 == 0)
1689 1690
	    {
	      /* (a+ib) / (c+i0) = (a/c) + i(b/c) */
1691 1692 1693 1694

	      /* Don't fetch these from memory more than once.  */
	      real1 = force_reg (submode, real1);

1695
	      /* Simply divide the real and imaginary parts by `c' */
1696 1697 1698 1699 1700 1701 1702
	      if (class == MODE_COMPLEX_FLOAT)
		res = expand_binop (submode, binoptab, real0, real1,
				    realr, unsignedp, methods);
	      else
		res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
				     real0, real1, realr, unsignedp);

1703 1704 1705
	      if (res == 0)
		break;
	      else if (res != realr)
1706 1707
		emit_move_insn (realr, res);

1708 1709 1710 1711 1712 1713 1714
	      if (class == MODE_COMPLEX_FLOAT)
		res = expand_binop (submode, binoptab, imag0, real1,
				    imagr, unsignedp, methods);
	      else
		res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
				     imag0, real1, imagr, unsignedp);

1715 1716 1717
	      if (res == 0)
		break;
	      else if (res != imagr)
1718 1719
		emit_move_insn (imagr, res);

1720 1721 1722 1723
	      ok = 1;
	    }
	  else
	    {
1724
	      switch (flag_complex_divide_method)
1725
		{
1726 1727 1728 1729 1730 1731
		case 0:
		  ok = expand_cmplxdiv_straight (real0, real1, imag0, imag1,
						 realr, imagr, submode,
						 unsignedp, methods,
						 class, binoptab);
		  break;
1732

1733 1734 1735 1736 1737 1738
		case 1:
		  ok = expand_cmplxdiv_wide (real0, real1, imag0, imag1,
					     realr, imagr, submode,
					     unsignedp, methods,
					     class, binoptab);
		  break;
1739

1740 1741
		default:
		  abort ();
1742 1743 1744
		}
	    }
	  break;
1745

1746 1747 1748 1749
	default:
	  abort ();
	}

1750
      seq = get_insns ();
1751 1752
      end_sequence ();

1753 1754
      if (ok)
	{
1755 1756 1757 1758
	  rtx equiv = gen_rtx_fmt_ee (binoptab->code, mode,
				      copy_rtx (op0), copy_rtx (op1));
	  emit_no_conflict_block (seq, result, op0, op1, equiv);
	  return result;
1759
	}
1760 1761
    }

Richard Kenner committed
1762 1763 1764 1765 1766 1767 1768
  /* It can't be open-coded in this mode.
     Use a library call if one is available and caller says that's ok.  */

  if (binoptab->handlers[(int) mode].libfunc
      && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
    {
      rtx insns;
1769 1770
      rtx op1x = op1;
      enum machine_mode op1_mode = mode;
1771
      rtx value;
Richard Kenner committed
1772 1773 1774

      start_sequence ();

1775 1776 1777 1778 1779 1780 1781 1782
      if (shift_op)
	{
	  op1_mode = word_mode;
	  /* Specify unsigned here,
	     since negative shift counts are meaningless.  */
	  op1x = convert_to_mode (word_mode, op1, 1);
	}

1783 1784
      if (GET_MODE (op0) != VOIDmode
	  && GET_MODE (op0) != mode)
1785 1786
	op0 = convert_to_mode (mode, op0, unsignedp);

Richard Kenner committed
1787 1788
      /* Pass 1 for NO_QUEUE so we don't lose any increments
	 if the libcall is cse'd or moved.  */
1789
      value = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
1790
				       NULL_RTX, LCT_CONST, mode, 2,
1791
				       op0, mode, op1x, op1_mode);
Richard Kenner committed
1792 1793 1794 1795 1796

      insns = get_insns ();
      end_sequence ();

      target = gen_reg_rtx (mode);
1797
      emit_libcall_block (insns, target, value,
1798
			  gen_rtx_fmt_ee (binoptab->code, mode, op0, op1));
Richard Kenner committed
1799 1800 1801 1802 1803 1804 1805 1806 1807 1808

      return target;
    }

  delete_insns_since (last);

  /* It can't be done in this mode.  Can we do it in a wider mode?  */

  if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
	 || methods == OPTAB_MUST_WIDEN))
1809 1810 1811 1812 1813
    {
      /* Caller says, don't even try.  */
      delete_insns_since (entry_last);
      return 0;
    }
Richard Kenner committed
1814 1815 1816 1817 1818 1819

  /* Compute the value of METHODS to pass to recursive calls.
     Don't allow widening to be tried recursively.  */

  methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);

1820 1821
  /* Look for a wider mode of the same class for which it appears we can do
     the operation.  */
Richard Kenner committed
1822 1823 1824

  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
    {
1825
      for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
Richard Kenner committed
1826 1827 1828 1829 1830 1831 1832 1833 1834 1835
	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
	{
	  if ((binoptab->handlers[(int) wider_mode].insn_code
	       != CODE_FOR_nothing)
	      || (methods == OPTAB_LIB
		  && binoptab->handlers[(int) wider_mode].libfunc))
	    {
	      rtx xop0 = op0, xop1 = op1;
	      int no_extend = 0;

1836
	      /* For certain integer operations, we need not actually extend
Richard Kenner committed
1837
		 the narrow operands, as long as we will truncate
1838
		 the results to the same narrowness.  */
Richard Kenner committed
1839

1840 1841 1842
	      if ((binoptab == ior_optab || binoptab == and_optab
		   || binoptab == xor_optab
		   || binoptab == add_optab || binoptab == sub_optab
Richard Kenner committed
1843
		   || binoptab == smul_optab || binoptab == ashl_optab)
1844
		  && class == MODE_INT)
Richard Kenner committed
1845 1846
		no_extend = 1;

1847 1848
	      xop0 = widen_operand (xop0, wider_mode, mode,
				    unsignedp, no_extend);
1849 1850

	      /* The second operand of a shift must always be extended.  */
1851
	      xop1 = widen_operand (xop1, wider_mode, mode, unsignedp,
Richard Kenner committed
1852
				    no_extend && binoptab != ashl_optab);
Richard Kenner committed
1853

Charles Hannum committed
1854
	      temp = expand_binop (wider_mode, binoptab, xop0, xop1, NULL_RTX,
Richard Kenner committed
1855 1856 1857
				   unsignedp, methods);
	      if (temp)
		{
1858
		  if (class != MODE_INT)
Richard Kenner committed
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
		    {
		      if (target == 0)
			target = gen_reg_rtx (mode);
		      convert_move (target, temp, 0);
		      return target;
		    }
		  else
		    return gen_lowpart (mode, temp);
		}
	      else
		delete_insns_since (last);
	    }
	}
    }

1874
  delete_insns_since (entry_last);
Richard Kenner committed
1875 1876
  return 0;
}
Aldy Hernandez committed
1877 1878 1879 1880

/* Like expand_binop, but for open-coding vectors binops.  */

static rtx
1881 1882 1883
expand_vector_binop (enum machine_mode mode, optab binoptab, rtx op0,
		     rtx op1, rtx target, int unsignedp,
		     enum optab_methods methods)
Aldy Hernandez committed
1884
{
1885 1886
  enum machine_mode submode, tmode;
  int size, elts, subsize, subbitsize, i;
Aldy Hernandez committed
1887 1888 1889 1890 1891
  rtx t, a, b, res, seq;
  enum mode_class class;

  class = GET_MODE_CLASS (mode);

1892
  size = GET_MODE_SIZE (mode);
Aldy Hernandez committed
1893 1894
  submode = GET_MODE_INNER (mode);

1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906
  /* Search for the widest vector mode with the same inner mode that is
     still narrower than MODE and that allows to open-code this operator.
     Note, if we find such a mode and the handler later decides it can't
     do the expansion, we'll be called recursively with the narrower mode.  */
  for (tmode = GET_CLASS_NARROWEST_MODE (class);
       GET_MODE_SIZE (tmode) < GET_MODE_SIZE (mode);
       tmode = GET_MODE_WIDER_MODE (tmode))
    {
      if (GET_MODE_INNER (tmode) == GET_MODE_INNER (mode)
	  && binoptab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
	submode = tmode;
    }
Aldy Hernandez committed
1907 1908 1909

  switch (binoptab->code)
    {
1910 1911 1912 1913 1914 1915
    case AND:
    case IOR:
    case XOR:
      tmode = int_mode_for_mode (mode);
      if (tmode != BLKmode)
	submode = tmode;
Aldy Hernandez committed
1916 1917 1918 1919
    case PLUS:
    case MINUS:
    case MULT:
    case DIV:
1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939
      subsize = GET_MODE_SIZE (submode);
      subbitsize = GET_MODE_BITSIZE (submode);
      elts = size / subsize;

      /* If METHODS is OPTAB_DIRECT, we don't insist on the exact mode,
	 but that we operate on more than one element at a time.  */
      if (subsize == GET_MODE_UNIT_SIZE (mode) && methods == OPTAB_DIRECT)
	return 0;

      start_sequence ();

      /* Errors can leave us with a const0_rtx as operand.  */
      if (GET_MODE (op0) != mode)
	op0 = copy_to_mode_reg (mode, op0);
      if (GET_MODE (op1) != mode)
	op1 = copy_to_mode_reg (mode, op1);

      if (!target)
	target = gen_reg_rtx (mode);

Aldy Hernandez committed
1940 1941
      for (i = 0; i < elts; ++i)
	{
1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964
	  /* If this is part of a register, and not the first item in the
	     word, we can't store using a SUBREG - that would clobber
	     previous results.
	     And storing with a SUBREG is only possible for the least
	     significant part, hence we can't do it for big endian
	     (unless we want to permute the evaluation order.  */
	  if (GET_CODE (target) == REG
	      && (BYTES_BIG_ENDIAN
		  ? subsize < UNITS_PER_WORD
		  : ((i * subsize) % UNITS_PER_WORD) != 0))
	    t = NULL_RTX;
	  else
	    t = simplify_gen_subreg (submode, target, mode, i * subsize);
	  if (CONSTANT_P (op0))
	    a = simplify_gen_subreg (submode, op0, mode, i * subsize);
	  else
	    a = extract_bit_field (op0, subbitsize, i * subbitsize, unsignedp,
				   NULL_RTX, submode, submode, size);
	  if (CONSTANT_P (op1))
	    b = simplify_gen_subreg (submode, op1, mode, i * subsize);
	  else
	    b = extract_bit_field (op1, subbitsize, i * subbitsize, unsignedp,
				   NULL_RTX, submode, submode, size);
Aldy Hernandez committed
1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981

	  if (binoptab->code == DIV)
	    {
	      if (class == MODE_VECTOR_FLOAT)
		res = expand_binop (submode, binoptab, a, b, t,
				    unsignedp, methods);
	      else
		res = expand_divmod (0, TRUNC_DIV_EXPR, submode,
				     a, b, t, unsignedp);
	    }
	  else
	    res = expand_binop (submode, binoptab, a, b, t,
				unsignedp, methods);

	  if (res == 0)
	    break;

1982 1983 1984 1985 1986
	  if (t)
	    emit_move_insn (t, res);
	  else
	    store_bit_field (target, subbitsize, i * subbitsize, submode, res,
			     size);
Aldy Hernandez committed
1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003
	}
      break;

    default:
      abort ();
    }

  seq = get_insns ();
  end_sequence ();
  emit_insn (seq);

  return target;
}

/* Like expand_unop but for open-coding vector unops.  */

static rtx
2004 2005
expand_vector_unop (enum machine_mode mode, optab unoptab, rtx op0,
		    rtx target, int unsignedp)
Aldy Hernandez committed
2006
{
2007 2008
  enum machine_mode submode, tmode;
  int size, elts, subsize, subbitsize, i;
Aldy Hernandez committed
2009 2010
  rtx t, a, res, seq;

2011
  size = GET_MODE_SIZE (mode);
Aldy Hernandez committed
2012
  submode = GET_MODE_INNER (mode);
2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026

  /* Search for the widest vector mode with the same inner mode that is
     still narrower than MODE and that allows to open-code this operator.
     Note, if we find such a mode and the handler later decides it can't
     do the expansion, we'll be called recursively with the narrower mode.  */
  for (tmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (mode));
       GET_MODE_SIZE (tmode) < GET_MODE_SIZE (mode);
       tmode = GET_MODE_WIDER_MODE (tmode))
    {
      if (GET_MODE_INNER (tmode) == GET_MODE_INNER (mode)
	  && unoptab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
	submode = tmode;
    }
  /* If there is no negate operation, try doing a subtract from zero.  */
2027 2028 2029 2030
  if (unoptab == neg_optab && GET_MODE_CLASS (submode) == MODE_INT
      /* Avoid infinite recursion when an
	 error has left us with the wrong mode.  */
      && GET_MODE (op0) == mode)
2031
    {
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052
      rtx temp;
      temp = expand_binop (mode, sub_optab, CONST0_RTX (mode), op0,
                           target, unsignedp, OPTAB_DIRECT);
      if (temp)
	return temp;
    }

  if (unoptab == one_cmpl_optab)
    {
      tmode = int_mode_for_mode (mode);
      if (tmode != BLKmode)
	submode = tmode;
    }

  subsize = GET_MODE_SIZE (submode);
  subbitsize = GET_MODE_BITSIZE (submode);
  elts = size / subsize;

  /* Errors can leave us with a const0_rtx as operand.  */
  if (GET_MODE (op0) != mode)
    op0 = copy_to_mode_reg (mode, op0);
Aldy Hernandez committed
2053 2054 2055 2056 2057 2058 2059 2060

  if (!target)
    target = gen_reg_rtx (mode);

  start_sequence ();

  for (i = 0; i < elts; ++i)
    {
2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078
      /* If this is part of a register, and not the first item in the
	 word, we can't store using a SUBREG - that would clobber
	 previous results.
	 And storing with a SUBREG is only possible for the least
	 significant part, hence we can't do it for big endian
	 (unless we want to permute the evaluation order.  */
      if (GET_CODE (target) == REG
	  && (BYTES_BIG_ENDIAN
	      ?  subsize < UNITS_PER_WORD
	      : ((i * subsize) % UNITS_PER_WORD) != 0))
	t = NULL_RTX;
      else
	t = simplify_gen_subreg (submode, target, mode, i * subsize);
      if (CONSTANT_P (op0))
	a = simplify_gen_subreg (submode, op0, mode, i * subsize);
      else
	a = extract_bit_field (op0, subbitsize, i * subbitsize, unsignedp,
			       t, submode, submode, size);
Aldy Hernandez committed
2079 2080 2081

      res = expand_unop (submode, unoptab, a, t, unsignedp);

2082 2083 2084 2085 2086
      if (t)
	emit_move_insn (t, res);
      else
	store_bit_field (target, subbitsize, i * subbitsize, submode, res,
			 size);
Aldy Hernandez committed
2087 2088 2089 2090 2091 2092 2093 2094
    }

  seq = get_insns ();
  end_sequence ();
  emit_insn (seq);

  return target;
}
Richard Kenner committed
2095 2096 2097 2098 2099 2100 2101 2102 2103

/* Expand a binary operator which has both signed and unsigned forms.
   UOPTAB is the optab for unsigned operations, and SOPTAB is for
   signed operations.

   If we widen unsigned operands, we may use a signed wider operation instead
   of an unsigned wider operation, since the result would be the same.  */

rtx
2104 2105 2106
sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab,
		   rtx op0, rtx op1, rtx target, int unsignedp,
		   enum optab_methods methods)
Richard Kenner committed
2107
{
2108
  rtx temp;
Richard Kenner committed
2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149
  optab direct_optab = unsignedp ? uoptab : soptab;
  struct optab wide_soptab;

  /* Do it without widening, if possible.  */
  temp = expand_binop (mode, direct_optab, op0, op1, target,
		       unsignedp, OPTAB_DIRECT);
  if (temp || methods == OPTAB_DIRECT)
    return temp;

  /* Try widening to a signed int.  Make a fake signed optab that
     hides any signed insn for direct use.  */
  wide_soptab = *soptab;
  wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
  wide_soptab.handlers[(int) mode].libfunc = 0;

  temp = expand_binop (mode, &wide_soptab, op0, op1, target,
		       unsignedp, OPTAB_WIDEN);

  /* For unsigned operands, try widening to an unsigned int.  */
  if (temp == 0 && unsignedp)
    temp = expand_binop (mode, uoptab, op0, op1, target,
			 unsignedp, OPTAB_WIDEN);
  if (temp || methods == OPTAB_WIDEN)
    return temp;

  /* Use the right width lib call if that exists.  */
  temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
  if (temp || methods == OPTAB_LIB)
    return temp;

  /* Must widen and use a lib call, use either signed or unsigned.  */
  temp = expand_binop (mode, &wide_soptab, op0, op1, target,
		       unsignedp, methods);
  if (temp != 0)
    return temp;
  if (unsignedp)
    return expand_binop (mode, uoptab, op0, op1, target,
			 unsignedp, methods);
  return 0;
}

2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161
/* Generate code to perform an operation specified by UNOPPTAB
   on operand OP0, with two results to TARG0 and TARG1.
   We assume that the order of the operands for the instruction
   is TARG0, TARG1, OP0.

   Either TARG0 or TARG1 may be zero, but what that means is that
   the result is not actually wanted.  We will generate it into
   a dummy pseudo-reg and discard it.  They may not both be zero.

   Returns 1 if this operation can be performed; 0 if not.  */

int
2162
expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1,
2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236
		    int unsignedp)
{
  enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
  enum mode_class class;
  enum machine_mode wider_mode;
  rtx entry_last = get_last_insn ();
  rtx last;

  class = GET_MODE_CLASS (mode);

  op0 = protect_from_queue (op0, 0);

  if (flag_force_mem)
    {
      op0 = force_not_mem (op0);
    }

  if (targ0)
    targ0 = protect_from_queue (targ0, 1);
  else
    targ0 = gen_reg_rtx (mode);
  if (targ1)
    targ1 = protect_from_queue (targ1, 1);
  else
    targ1 = gen_reg_rtx (mode);

  /* Record where to go back to if we fail.  */
  last = get_last_insn ();

  if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
    {
      int icode = (int) unoptab->handlers[(int) mode].insn_code;
      enum machine_mode mode0 = insn_data[icode].operand[2].mode;
      rtx pat;
      rtx xop0 = op0;

      if (GET_MODE (xop0) != VOIDmode
	  && GET_MODE (xop0) != mode0)
	xop0 = convert_to_mode (mode0, xop0, unsignedp);

      /* Now, if insn doesn't accept these operands, put them into pseudos.  */
      if (! (*insn_data[icode].operand[2].predicate) (xop0, mode0))
	xop0 = copy_to_mode_reg (mode0, xop0);

      /* We could handle this, but we should always be called with a pseudo
	 for our targets and all insns should take them as outputs.  */
      if (! (*insn_data[icode].operand[0].predicate) (targ0, mode)
	  || ! (*insn_data[icode].operand[1].predicate) (targ1, mode))
	abort ();

      pat = GEN_FCN (icode) (targ0, targ1, xop0);
      if (pat)
	{
	  emit_insn (pat);
	  return 1;
	}
      else
	delete_insns_since (last);
    }

  /* It can't be done in this mode.  Can we do it in a wider mode?  */

  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
    {
      for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
	{
	  if (unoptab->handlers[(int) wider_mode].insn_code
	      != CODE_FOR_nothing)
	    {
	      rtx t0 = gen_reg_rtx (wider_mode);
	      rtx t1 = gen_reg_rtx (wider_mode);
	      rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);

2237
	      if (expand_twoval_unop (unoptab, cop0, t0, t1, unsignedp))
2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252
		{
		  convert_move (targ0, t0, unsignedp);
		  convert_move (targ1, t1, unsignedp);
		  return 1;
		}
	      else
		delete_insns_since (last);
	    }
	}
    }

  delete_insns_since (entry_last);
  return 0;
}

Richard Kenner committed
2253 2254 2255 2256 2257 2258 2259
/* Generate code to perform an operation specified by BINOPTAB
   on operands OP0 and OP1, with two results to TARG1 and TARG2.
   We assume that the order of the operands for the instruction
   is TARG0, OP0, OP1, TARG1, which would fit a pattern like
   [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].

   Either TARG0 or TARG1 may be zero, but what that means is that
Jeff Law committed
2260
   the result is not actually wanted.  We will generate it into
Richard Kenner committed
2261 2262 2263 2264 2265
   a dummy pseudo-reg and discard it.  They may not both be zero.

   Returns 1 if this operation can be performed; 0 if not.  */

int
2266 2267
expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1,
		     int unsignedp)
Richard Kenner committed
2268 2269 2270 2271
{
  enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
  enum mode_class class;
  enum machine_mode wider_mode;
2272
  rtx entry_last = get_last_insn ();
Richard Kenner committed
2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287
  rtx last;

  class = GET_MODE_CLASS (mode);

  op0 = protect_from_queue (op0, 0);
  op1 = protect_from_queue (op1, 0);

  if (flag_force_mem)
    {
      op0 = force_not_mem (op0);
      op1 = force_not_mem (op1);
    }

  /* If we are inside an appropriately-short loop and one operand is an
     expensive constant, force it into a register.  */
2288
  if (CONSTANT_P (op0) && preserve_subexpressions_p ()
2289
      && rtx_cost (op0, binoptab->code) > COSTS_N_INSNS (1))
Richard Kenner committed
2290 2291
    op0 = force_reg (mode, op0);

2292
  if (CONSTANT_P (op1) && preserve_subexpressions_p ()
2293
      && rtx_cost (op1, binoptab->code) > COSTS_N_INSNS (1))
Richard Kenner committed
2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310
    op1 = force_reg (mode, op1);

  if (targ0)
    targ0 = protect_from_queue (targ0, 1);
  else
    targ0 = gen_reg_rtx (mode);
  if (targ1)
    targ1 = protect_from_queue (targ1, 1);
  else
    targ1 = gen_reg_rtx (mode);

  /* Record where to go back to if we fail.  */
  last = get_last_insn ();

  if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
    {
      int icode = (int) binoptab->handlers[(int) mode].insn_code;
2311 2312
      enum machine_mode mode0 = insn_data[icode].operand[1].mode;
      enum machine_mode mode1 = insn_data[icode].operand[2].mode;
Richard Kenner committed
2313 2314 2315
      rtx pat;
      rtx xop0 = op0, xop1 = op1;

2316 2317 2318
      /* In case the insn wants input operands in modes different from
	 those of the actual operands, convert the operands.  It would
	 seem that we don't need to convert CONST_INTs, but we do, so
2319 2320
	 that they're properly zero-extended, sign-extended or truncated
	 for their mode.  */
Richard Kenner committed
2321

2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334
      if (GET_MODE (op0) != mode0 && mode0 != VOIDmode)
	xop0 = convert_modes (mode0,
			      GET_MODE (op0) != VOIDmode
			      ? GET_MODE (op0)
			      : mode,
			      xop0, unsignedp);

      if (GET_MODE (op1) != mode1 && mode1 != VOIDmode)
	xop1 = convert_modes (mode1,
			      GET_MODE (op1) != VOIDmode
			      ? GET_MODE (op1)
			      : mode,
			      xop1, unsignedp);
Richard Kenner committed
2335 2336

      /* Now, if insn doesn't accept these operands, put them into pseudos.  */
2337
      if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
Richard Kenner committed
2338 2339
	xop0 = copy_to_mode_reg (mode0, xop0);

2340
      if (! (*insn_data[icode].operand[2].predicate) (xop1, mode1))
Richard Kenner committed
2341 2342 2343 2344
	xop1 = copy_to_mode_reg (mode1, xop1);

      /* We could handle this, but we should always be called with a pseudo
	 for our targets and all insns should take them as outputs.  */
2345 2346
      if (! (*insn_data[icode].operand[0].predicate) (targ0, mode)
	  || ! (*insn_data[icode].operand[3].predicate) (targ1, mode))
Richard Kenner committed
2347
	abort ();
2348

Richard Kenner committed
2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362
      pat = GEN_FCN (icode) (targ0, xop0, xop1, targ1);
      if (pat)
	{
	  emit_insn (pat);
	  return 1;
	}
      else
	delete_insns_since (last);
    }

  /* It can't be done in this mode.  Can we do it in a wider mode?  */

  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
    {
2363
      for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
Richard Kenner committed
2364 2365 2366 2367 2368
	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
	{
	  if (binoptab->handlers[(int) wider_mode].insn_code
	      != CODE_FOR_nothing)
	    {
2369 2370
	      rtx t0 = gen_reg_rtx (wider_mode);
	      rtx t1 = gen_reg_rtx (wider_mode);
2371 2372
	      rtx cop0 = convert_modes (wider_mode, mode, op0, unsignedp);
	      rtx cop1 = convert_modes (wider_mode, mode, op1, unsignedp);
Richard Kenner committed
2373

2374
	      if (expand_twoval_binop (binoptab, cop0, cop1,
Richard Kenner committed
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386
				       t0, t1, unsignedp))
		{
		  convert_move (targ0, t0, unsignedp);
		  convert_move (targ1, t1, unsignedp);
		  return 1;
		}
	      else
		delete_insns_since (last);
	    }
	}
    }

2387
  delete_insns_since (entry_last);
Richard Kenner committed
2388 2389 2390
  return 0;
}

2391 2392 2393 2394
/* Wrapper around expand_unop which takes an rtx code to specify
   the operation to perform, not an optab pointer.  All other
   arguments are the same.  */
rtx
2395 2396
expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0,
		    rtx target, int unsignedp)
2397
{
2398
  optab unop = code_to_optab[(int) code];
2399 2400 2401 2402 2403 2404
  if (unop == 0)
    abort ();

  return expand_unop (mode, unop, op0, target, unsignedp);
}

Richard Henderson committed
2405 2406 2407 2408 2409
/* Try calculating
	(clz:narrow x)
   as
	(clz:wide (zero_extend:wide x)) - ((width wide) - (width narrow)).  */
static rtx
2410
widen_clz (enum machine_mode mode, rtx op0, rtx target)
Richard Henderson committed
2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447
{
  enum mode_class class = GET_MODE_CLASS (mode);
  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
    {
      enum machine_mode wider_mode;
      for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
	{
	  if (clz_optab->handlers[(int) wider_mode].insn_code
	      != CODE_FOR_nothing)
	    {
	      rtx xop0, temp, last;

	      last = get_last_insn ();

	      if (target == 0)
		target = gen_reg_rtx (mode);
	      xop0 = widen_operand (op0, wider_mode, mode, true, false);
	      temp = expand_unop (wider_mode, clz_optab, xop0, NULL_RTX, true);
	      if (temp != 0)
		temp = expand_binop (wider_mode, sub_optab, temp,
				     GEN_INT (GET_MODE_BITSIZE (wider_mode)
					      - GET_MODE_BITSIZE (mode)),
				     target, true, OPTAB_DIRECT);
	      if (temp == 0)
		delete_insns_since (last);

	      return temp;
	    }
	}
    }
  return 0;
}

/* Try calculating (parity x) as (and (popcount x) 1), where
   popcount can also be done in a wider mode.  */
static rtx
2448
expand_parity (enum machine_mode mode, rtx op0, rtx target)
Richard Henderson committed
2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469
{
  enum mode_class class = GET_MODE_CLASS (mode);
  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
    {
      enum machine_mode wider_mode;
      for (wider_mode = mode; wider_mode != VOIDmode;
	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
	{
	  if (popcount_optab->handlers[(int) wider_mode].insn_code
	      != CODE_FOR_nothing)
	    {
	      rtx xop0, temp, last;

	      last = get_last_insn ();

	      if (target == 0)
		target = gen_reg_rtx (mode);
	      xop0 = widen_operand (op0, wider_mode, mode, true, false);
	      temp = expand_unop (wider_mode, popcount_optab, xop0, NULL_RTX,
				  true);
	      if (temp != 0)
2470
		temp = expand_binop (wider_mode, and_optab, temp, const1_rtx,
Richard Henderson committed
2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481
				     target, true, OPTAB_DIRECT);
	      if (temp == 0)
		delete_insns_since (last);

	      return temp;
	    }
	}
    }
  return 0;
}

Richard Kenner committed
2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493
/* Generate code to perform an operation specified by UNOPTAB
   on operand OP0, with result having machine-mode MODE.

   UNSIGNEDP is for the case where we have to widen the operands
   to perform the operation.  It says to use zero-extension.

   If TARGET is nonzero, the value
   is generated there, if it is convenient to do so.
   In all cases an rtx is returned for the locus of the value;
   this may or may not be TARGET.  */

rtx
2494 2495
expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target,
	     int unsignedp)
Richard Kenner committed
2496 2497 2498
{
  enum mode_class class;
  enum machine_mode wider_mode;
2499
  rtx temp;
Richard Kenner committed
2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517
  rtx last = get_last_insn ();
  rtx pat;

  class = GET_MODE_CLASS (mode);

  op0 = protect_from_queue (op0, 0);

  if (flag_force_mem)
    {
      op0 = force_not_mem (op0);
    }

  if (target)
    target = protect_from_queue (target, 1);

  if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
    {
      int icode = (int) unoptab->handlers[(int) mode].insn_code;
2518
      enum machine_mode mode0 = insn_data[icode].operand[1].mode;
Richard Kenner committed
2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531
      rtx xop0 = op0;

      if (target)
	temp = target;
      else
	temp = gen_reg_rtx (mode);

      if (GET_MODE (xop0) != VOIDmode
	  && GET_MODE (xop0) != mode0)
	xop0 = convert_to_mode (mode0, xop0, unsignedp);

      /* Now, if insn doesn't accept our operand, put it into a pseudo.  */

2532
      if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
Richard Kenner committed
2533 2534
	xop0 = copy_to_mode_reg (mode0, xop0);

2535
      if (! (*insn_data[icode].operand[0].predicate) (temp, mode))
Richard Kenner committed
2536 2537 2538 2539 2540
	temp = gen_reg_rtx (mode);

      pat = GEN_FCN (icode) (temp, xop0);
      if (pat)
	{
2541
	  if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
Charles Hannum committed
2542
	      && ! add_equal_note (pat, temp, unoptab->code, xop0, NULL_RTX))
Richard Kenner committed
2543 2544
	    {
	      delete_insns_since (last);
Charles Hannum committed
2545
	      return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
Richard Kenner committed
2546 2547 2548
	    }

	  emit_insn (pat);
2549

Richard Kenner committed
2550 2551 2552 2553 2554 2555
	  return temp;
	}
      else
	delete_insns_since (last);
    }

2556 2557
  /* It can't be done in this mode.  Can we open-code it in a wider mode?  */

Richard Henderson committed
2558 2559 2560 2561 2562 2563 2564 2565 2566 2567
  /* Widening clz needs special treatment.  */
  if (unoptab == clz_optab)
    {
      temp = widen_clz (mode, op0, target);
      if (temp)
	return temp;
      else
	goto try_libcall;
    }

2568 2569 2570 2571 2572 2573 2574 2575 2576 2577
  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
    for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
	 wider_mode = GET_MODE_WIDER_MODE (wider_mode))
      {
	if (unoptab->handlers[(int) wider_mode].insn_code != CODE_FOR_nothing)
	  {
	    rtx xop0 = op0;

	    /* For certain operations, we need not actually extend
	       the narrow operand, as long as we will truncate the
2578 2579
	       results to the same narrowness.  */

2580
	    xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2581 2582 2583
				  (unoptab == neg_optab
				   || unoptab == one_cmpl_optab)
				  && class == MODE_INT);
2584

Charles Hannum committed
2585 2586
	    temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
				unsignedp);
2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604

	    if (temp)
	      {
		if (class != MODE_INT)
		  {
		    if (target == 0)
		      target = gen_reg_rtx (mode);
		    convert_move (target, temp, 0);
		    return target;
		  }
		else
		  return gen_lowpart (mode, temp);
	      }
	    else
	      delete_insns_since (last);
	  }
      }

Richard Kenner committed
2605 2606 2607 2608
  /* These can be done a word at a time.  */
  if (unoptab == one_cmpl_optab
      && class == MODE_INT
      && GET_MODE_SIZE (mode) > UNITS_PER_WORD
2609
      && unoptab->handlers[(int) word_mode].insn_code != CODE_FOR_nothing)
Richard Kenner committed
2610
    {
2611
      int i;
Richard Kenner committed
2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622
      rtx insns;

      if (target == 0 || target == op0)
	target = gen_reg_rtx (mode);

      start_sequence ();

      /* Do the actual arithmetic.  */
      for (i = 0; i < GET_MODE_BITSIZE (mode) / BITS_PER_WORD; i++)
	{
	  rtx target_piece = operand_subword (target, i, 1, mode);
2623
	  rtx x = expand_unop (word_mode, unoptab,
Richard Kenner committed
2624 2625
			       operand_subword_force (op0, i, mode),
			       target_piece, unsignedp);
2626

Richard Kenner committed
2627 2628 2629 2630 2631 2632 2633
	  if (target_piece != x)
	    emit_move_insn (target_piece, x);
	}

      insns = get_insns ();
      end_sequence ();

Charles Hannum committed
2634
      emit_no_conflict_block (insns, target, op0, NULL_RTX,
2635 2636
			      gen_rtx_fmt_e (unoptab->code, mode,
					     copy_rtx (op0)));
Richard Kenner committed
2637 2638 2639
      return target;
    }

2640
  /* Open-code the complex negation operation.  */
2641
  else if (unoptab->code == NEG
2642 2643 2644 2645 2646 2647
	   && (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT))
    {
      rtx target_piece;
      rtx x;
      rtx seq;

2648
      /* Find the correct mode for the real and imaginary parts.  */
2649
      enum machine_mode submode = GET_MODE_INNER (mode);
2650 2651 2652 2653 2654 2655

      if (submode == BLKmode)
	abort ();

      if (target == 0)
	target = gen_reg_rtx (mode);
2656

2657 2658
      start_sequence ();

2659
      target_piece = gen_imagpart (submode, target);
2660
      x = expand_unop (submode, unoptab,
2661
		       gen_imagpart (submode, op0),
2662 2663 2664 2665
		       target_piece, unsignedp);
      if (target_piece != x)
	emit_move_insn (target_piece, x);

2666
      target_piece = gen_realpart (submode, target);
2667
      x = expand_unop (submode, unoptab,
2668
		       gen_realpart (submode, op0),
2669 2670 2671 2672
		       target_piece, unsignedp);
      if (target_piece != x)
	emit_move_insn (target_piece, x);

2673
      seq = get_insns ();
2674 2675 2676
      end_sequence ();

      emit_no_conflict_block (seq, target, op0, 0,
2677 2678
			      gen_rtx_fmt_e (unoptab->code, mode,
					     copy_rtx (op0)));
2679 2680 2681
      return target;
    }

2682 2683 2684 2685
  /* Try negating floating point values by flipping the sign bit.  */
  if (unoptab->code == NEG && class == MODE_FLOAT
      && GET_MODE_BITSIZE (mode) <= 2 * HOST_BITS_PER_WIDE_INT)
    {
2686
      const struct real_format *fmt = REAL_MODE_FORMAT (mode);
2687 2688 2689 2690 2691 2692 2693 2694
      enum machine_mode imode = int_mode_for_mode (mode);
      int bitpos = (fmt != 0) ? fmt->signbit : -1;

      if (imode != BLKmode && bitpos >= 0 && fmt->has_signed_zero)
	{
	  HOST_WIDE_INT hi, lo;
	  rtx last = get_last_insn ();

2695 2696 2697 2698 2699 2700 2701 2702
	  /* Handle targets with different FP word orders.  */
	  if (FLOAT_WORDS_BIG_ENDIAN != WORDS_BIG_ENDIAN)
	    {
	      int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
	      int word = nwords - (bitpos / BITS_PER_WORD) - 1;
	      bitpos = word * BITS_PER_WORD + bitpos % BITS_PER_WORD;
	    }

2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717
	  if (bitpos < HOST_BITS_PER_WIDE_INT)
	    {
	      hi = 0;
	      lo = (HOST_WIDE_INT) 1 << bitpos;
	    }
	  else
	    {
	      hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
	      lo = 0;
	    }
	  temp = expand_binop (imode, xor_optab,
			       gen_lowpart (imode, op0),
			       immed_double_const (lo, hi, imode),
			       NULL_RTX, 1, OPTAB_LIB_WIDEN);
	  if (temp != 0)
2718 2719 2720 2721 2722 2723 2724 2725 2726 2727
	    {
	      rtx insn;
	      if (target == 0)
		target = gen_reg_rtx (mode);
	      insn = emit_move_insn (target, gen_lowpart (mode, temp));
	      set_unique_reg_note (insn, REG_EQUAL,
				   gen_rtx_fmt_e (NEG, mode,
						  copy_rtx (op0)));
	      return target;
	    }
2728 2729 2730 2731
	  delete_insns_since (last);
        }
    }

Richard Henderson committed
2732 2733 2734 2735 2736 2737 2738 2739 2740
  /* Try calculating parity (x) as popcount (x) % 2.  */
  if (unoptab == parity_optab)
    {
      temp = expand_parity (mode, op0, target);
      if (temp)
	return temp;
    }

 try_libcall:
2741
  /* Now try a library call in this mode.  */
Richard Kenner committed
2742 2743 2744
  if (unoptab->handlers[(int) mode].libfunc)
    {
      rtx insns;
2745
      rtx value;
Richard Henderson committed
2746 2747 2748 2749 2750 2751
      enum machine_mode outmode = mode;

      /* All of these functions return small values.  Thus we choose to
	 have them return something that isn't a double-word.  */
      if (unoptab == ffs_optab || unoptab == clz_optab || unoptab == ctz_optab
	  || unoptab == popcount_optab || unoptab == parity_optab)
2752 2753
	outmode
	    = GET_MODE (hard_libcall_value (TYPE_MODE (integer_type_node)));
Richard Kenner committed
2754 2755 2756 2757 2758

      start_sequence ();

      /* Pass 1 for NO_QUEUE so we don't lose any increments
	 if the libcall is cse'd or moved.  */
2759
      value = emit_library_call_value (unoptab->handlers[(int) mode].libfunc,
Richard Henderson committed
2760 2761
				       NULL_RTX, LCT_CONST, outmode,
				       1, op0, mode);
Richard Kenner committed
2762 2763 2764
      insns = get_insns ();
      end_sequence ();

Richard Henderson committed
2765
      target = gen_reg_rtx (outmode);
2766
      emit_libcall_block (insns, target, value,
2767
			  gen_rtx_fmt_e (unoptab->code, mode, op0));
Richard Kenner committed
2768 2769 2770 2771

      return target;
    }

Aldy Hernandez committed
2772 2773 2774
  if (class == MODE_VECTOR_FLOAT || class == MODE_VECTOR_INT)
    return expand_vector_unop (mode, unoptab, op0, target, unsignedp);

Richard Kenner committed
2775 2776 2777 2778
  /* It can't be done in this mode.  Can we do it in a wider mode?  */

  if (class == MODE_INT || class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT)
    {
2779
      for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
Richard Kenner committed
2780 2781 2782 2783 2784 2785
	   wider_mode = GET_MODE_WIDER_MODE (wider_mode))
	{
	  if ((unoptab->handlers[(int) wider_mode].insn_code
	       != CODE_FOR_nothing)
	      || unoptab->handlers[(int) wider_mode].libfunc)
	    {
2786 2787 2788 2789 2790 2791
	      rtx xop0 = op0;

	      /* For certain operations, we need not actually extend
		 the narrow operand, as long as we will truncate the
		 results to the same narrowness.  */

2792
	      xop0 = widen_operand (xop0, wider_mode, mode, unsignedp,
2793 2794 2795
				    (unoptab == neg_optab
				     || unoptab == one_cmpl_optab)
				    && class == MODE_INT);
2796

Charles Hannum committed
2797 2798
	      temp = expand_unop (wider_mode, unoptab, xop0, NULL_RTX,
				  unsignedp);
2799

2800 2801 2802 2803 2804 2805 2806 2807
	      /* If we are generating clz using wider mode, adjust the
		 result.  */
	      if (unoptab == clz_optab && temp != 0)
		temp = expand_binop (wider_mode, sub_optab, temp,
				     GEN_INT (GET_MODE_BITSIZE (wider_mode)
					      - GET_MODE_BITSIZE (mode)),
				     target, true, OPTAB_DIRECT);

2808
	      if (temp)
Richard Kenner committed
2809
		{
2810 2811 2812 2813 2814 2815 2816 2817 2818
		  if (class != MODE_INT)
		    {
		      if (target == 0)
			target = gen_reg_rtx (mode);
		      convert_move (target, temp, 0);
		      return target;
		    }
		  else
		    return gen_lowpart (mode, temp);
Richard Kenner committed
2819 2820
		}
	      else
2821
		delete_insns_since (last);
Richard Kenner committed
2822 2823 2824 2825
	    }
	}
    }

2826 2827
  /* If there is no negate operation, try doing a subtract from zero.
     The US Software GOFAST library needs this.  */
2828
  if (unoptab->code == NEG)
2829
    {
2830
      rtx temp;
2831 2832 2833 2834
      temp = expand_binop (mode,
                           unoptab == negv_optab ? subv_optab : sub_optab,
                           CONST0_RTX (mode), op0,
                           target, unsignedp, OPTAB_LIB_WIDEN);
2835 2836 2837
      if (temp)
	return temp;
    }
2838

Richard Kenner committed
2839 2840 2841
  return 0;
}

2842 2843 2844 2845 2846 2847 2848
/* Emit code to compute the absolute value of OP0, with result to
   TARGET if convenient.  (TARGET may be 0.)  The return value says
   where the result actually is to be found.

   MODE is the mode of the operand; the mode of the result is
   different but can be deduced from MODE.

Kaveh R. Ghazi committed
2849
 */
2850 2851

rtx
2852 2853
expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target,
		   int result_unsignedp)
2854
{
2855
  rtx temp;
2856

2857 2858 2859
  if (! flag_trapv)
    result_unsignedp = 1;

2860
  /* First try to do it with a special abs instruction.  */
2861 2862
  temp = expand_unop (mode, result_unsignedp ? abs_optab : absv_optab,
                      op0, target, 0);
2863 2864 2865
  if (temp != 0)
    return temp;

2866 2867 2868 2869
  /* For floating point modes, try clearing the sign bit.  */
  if (GET_MODE_CLASS (mode) == MODE_FLOAT
      && GET_MODE_BITSIZE (mode) <= 2 * HOST_BITS_PER_WIDE_INT)
    {
2870
      const struct real_format *fmt = REAL_MODE_FORMAT (mode);
2871 2872 2873 2874 2875 2876 2877 2878
      enum machine_mode imode = int_mode_for_mode (mode);
      int bitpos = (fmt != 0) ? fmt->signbit : -1;

      if (imode != BLKmode && bitpos >= 0)
	{
	  HOST_WIDE_INT hi, lo;
	  rtx last = get_last_insn ();

2879 2880 2881 2882 2883 2884 2885 2886
	  /* Handle targets with different FP word orders.  */
	  if (FLOAT_WORDS_BIG_ENDIAN != WORDS_BIG_ENDIAN)
	    {
	      int nwords = GET_MODE_BITSIZE (mode) / BITS_PER_WORD;
	      int word = nwords - (bitpos / BITS_PER_WORD) - 1;
	      bitpos = word * BITS_PER_WORD + bitpos % BITS_PER_WORD;
	    }

2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901
	  if (bitpos < HOST_BITS_PER_WIDE_INT)
	    {
	      hi = 0;
	      lo = (HOST_WIDE_INT) 1 << bitpos;
	    }
	  else
	    {
	      hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
	      lo = 0;
	    }
	  temp = expand_binop (imode, and_optab,
			       gen_lowpart (imode, op0),
			       immed_double_const (~lo, ~hi, imode),
			       NULL_RTX, 1, OPTAB_LIB_WIDEN);
	  if (temp != 0)
2902 2903 2904 2905 2906 2907 2908 2909 2910 2911
	    {
	      rtx insn;
	      if (target == 0)
		target = gen_reg_rtx (mode);
	      insn = emit_move_insn (target, gen_lowpart (mode, temp));
	      set_unique_reg_note (insn, REG_EQUAL,
				   gen_rtx_fmt_e (ABS, mode,
						  copy_rtx (op0)));
	      return target;
	    }
2912 2913 2914 2915
	  delete_insns_since (last);
	}
    }

Richard Kenner committed
2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931
  /* If we have a MAX insn, we can do this as MAX (x, -x).  */
  if (smax_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
    {
      rtx last = get_last_insn ();

      temp = expand_unop (mode, neg_optab, op0, NULL_RTX, 0);
      if (temp != 0)
	temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
			     OPTAB_WIDEN);

      if (temp != 0)
	return temp;

      delete_insns_since (last);
    }

2932 2933
  /* If this machine has expensive jumps, we can do integer absolute
     value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
2934
     where W is the width of MODE.  */
2935 2936 2937 2938 2939 2940 2941 2942 2943 2944

  if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
    {
      rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
				   size_int (GET_MODE_BITSIZE (mode) - 1),
				   NULL_RTX, 0);

      temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
			   OPTAB_LIB_WIDEN);
      if (temp != 0)
2945 2946
	temp = expand_binop (mode, result_unsignedp ? sub_optab : subv_optab,
                             temp, extended, target, 0, OPTAB_LIB_WIDEN);
2947 2948 2949 2950 2951

      if (temp != 0)
	return temp;
    }

2952 2953 2954 2955
  return NULL_RTX;
}

rtx
2956 2957
expand_abs (enum machine_mode mode, rtx op0, rtx target,
	    int result_unsignedp, int safe)
2958 2959 2960
{
  rtx temp, op1;

2961 2962 2963
  if (! flag_trapv)
    result_unsignedp = 1;

2964 2965 2966 2967
  temp = expand_abs_nojump (mode, op0, target, result_unsignedp);
  if (temp != 0)
    return temp;

2968
  /* If that does not win, use conditional jump and negate.  */
2969 2970 2971 2972 2973 2974 2975

  /* It is safe to use the target if it is the same
     as the source if this is also a pseudo register */
  if (op0 == target && GET_CODE (op0) == REG
      && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
    safe = 1;

2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988
  op1 = gen_label_rtx ();
  if (target == 0 || ! safe
      || GET_MODE (target) != mode
      || (GET_CODE (target) == MEM && MEM_VOLATILE_P (target))
      || (GET_CODE (target) == REG
	  && REGNO (target) < FIRST_PSEUDO_REGISTER))
    target = gen_reg_rtx (mode);

  emit_move_insn (target, op0);
  NO_DEFER_POP;

  /* If this mode is an integer too wide to compare properly,
     compare word by word.  Rely on CSE to optimize constant cases.  */
2989 2990
  if (GET_MODE_CLASS (mode) == MODE_INT
      && ! can_compare_p (GE, mode, ccp_jump))
2991
    do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx,
2992 2993
				  NULL_RTX, op1);
  else
2994
    do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode,
2995
			     NULL_RTX, NULL_RTX, op1);
2996

2997 2998
  op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab,
                     target, target, 0);
2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012
  if (op0 != target)
    emit_move_insn (target, op0);
  emit_label (op1);
  OK_DEFER_POP;
  return target;
}

/* Emit code to compute the absolute value of OP0, with result to
   TARGET if convenient.  (TARGET may be 0.)  The return value says
   where the result actually is to be found.

   MODE is the mode of the operand; the mode of the result is
   different but can be deduced from MODE.

3013 3014 3015
   UNSIGNEDP is relevant for complex integer modes.  */

rtx
3016 3017
expand_complex_abs (enum machine_mode mode, rtx op0, rtx target,
		    int unsignedp)
3018 3019 3020
{
  enum mode_class class = GET_MODE_CLASS (mode);
  enum machine_mode wider_mode;
3021
  rtx temp;
3022 3023
  rtx entry_last = get_last_insn ();
  rtx last;
3024
  rtx pat;
3025
  optab this_abs_optab;
3026 3027

  /* Find the correct mode for the real and imaginary parts.  */
3028
  enum machine_mode submode = GET_MODE_INNER (mode);
3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039

  if (submode == BLKmode)
    abort ();

  op0 = protect_from_queue (op0, 0);

  if (flag_force_mem)
    {
      op0 = force_not_mem (op0);
    }

3040 3041
  last = get_last_insn ();

3042 3043 3044
  if (target)
    target = protect_from_queue (target, 1);

3045 3046 3047 3048 3049
  this_abs_optab = ! unsignedp && flag_trapv
                   && (GET_MODE_CLASS(mode) == MODE_INT)
                   ? absv_optab : abs_optab;

  if (this_abs_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3050
    {
3051
      int icode = (int) this_abs_optab->handlers[(int) mode].insn_code;
3052
      enum machine_mode mode0 = insn_data[icode].operand[1].mode;
3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065
      rtx xop0 = op0;

      if (target)
	temp = target;
      else
	temp = gen_reg_rtx (submode);

      if (GET_MODE (xop0) != VOIDmode
	  && GET_MODE (xop0) != mode0)
	xop0 = convert_to_mode (mode0, xop0, unsignedp);

      /* Now, if insn doesn't accept our operand, put it into a pseudo.  */

3066
      if (! (*insn_data[icode].operand[1].predicate) (xop0, mode0))
3067 3068
	xop0 = copy_to_mode_reg (mode0, xop0);

3069
      if (! (*insn_data[icode].operand[0].predicate) (temp, submode))
3070 3071 3072 3073 3074
	temp = gen_reg_rtx (submode);

      pat = GEN_FCN (icode) (temp, xop0);
      if (pat)
	{
3075
	  if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
3076
	      && ! add_equal_note (pat, temp, this_abs_optab->code, xop0,
3077
				   NULL_RTX))
3078 3079
	    {
	      delete_insns_since (last);
3080
	      return expand_unop (mode, this_abs_optab, op0, NULL_RTX,
3081
				  unsignedp);
3082 3083 3084
	    }

	  emit_insn (pat);
3085

3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096
	  return temp;
	}
      else
	delete_insns_since (last);
    }

  /* It can't be done in this mode.  Can we open-code it in a wider mode?  */

  for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
       wider_mode = GET_MODE_WIDER_MODE (wider_mode))
    {
3097
      if (this_abs_optab->handlers[(int) wider_mode].insn_code
3098
	  != CODE_FOR_nothing)
3099 3100 3101
	{
	  rtx xop0 = op0;

3102
	  xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123
	  temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);

	  if (temp)
	    {
	      if (class != MODE_COMPLEX_INT)
		{
		  if (target == 0)
		    target = gen_reg_rtx (submode);
		  convert_move (target, temp, 0);
		  return target;
		}
	      else
		return gen_lowpart (submode, temp);
	    }
	  else
	    delete_insns_since (last);
	}
    }

  /* Open-code the complex absolute-value operation
     if we can open-code sqrt.  Otherwise it's not worth while.  */
3124 3125
  if (sqrt_optab->handlers[(int) submode].insn_code != CODE_FOR_nothing
      && ! flag_trapv)
3126 3127 3128 3129 3130
    {
      rtx real, imag, total;

      real = gen_realpart (submode, op0);
      imag = gen_imagpart (submode, op0);
3131

3132
      /* Square both parts.  */
3133 3134 3135
      real = expand_mult (submode, real, real, NULL_RTX, 0);
      imag = expand_mult (submode, imag, imag, NULL_RTX, 0);

3136
      /* Sum the parts.  */
3137
      total = expand_binop (submode, add_optab, real, imag, NULL_RTX,
3138
			    0, OPTAB_LIB_WIDEN);
3139

3140 3141 3142 3143 3144 3145 3146 3147 3148
      /* Get sqrt in TARGET.  Set TARGET to where the result is.  */
      target = expand_unop (submode, sqrt_optab, total, target, 0);
      if (target == 0)
	delete_insns_since (last);
      else
	return target;
    }

  /* Now try a library call in this mode.  */
3149
  if (this_abs_optab->handlers[(int) mode].libfunc)
3150 3151
    {
      rtx insns;
3152
      rtx value;
3153 3154 3155 3156 3157

      start_sequence ();

      /* Pass 1 for NO_QUEUE so we don't lose any increments
	 if the libcall is cse'd or moved.  */
3158
      value = emit_library_call_value (abs_optab->handlers[(int) mode].libfunc,
3159
				       NULL_RTX, LCT_CONST, submode, 1, op0, mode);
3160 3161 3162 3163
      insns = get_insns ();
      end_sequence ();

      target = gen_reg_rtx (submode);
3164
      emit_libcall_block (insns, target, value,
3165
			  gen_rtx_fmt_e (this_abs_optab->code, mode, op0));
3166 3167 3168 3169 3170 3171 3172 3173 3174

      return target;
    }

  /* It can't be done in this mode.  Can we do it in a wider mode?  */

  for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode;
       wider_mode = GET_MODE_WIDER_MODE (wider_mode))
    {
3175
      if ((this_abs_optab->handlers[(int) wider_mode].insn_code
3176
	   != CODE_FOR_nothing)
3177
	  || this_abs_optab->handlers[(int) wider_mode].libfunc)
3178 3179 3180
	{
	  rtx xop0 = op0;

3181
	  xop0 = convert_modes (wider_mode, mode, xop0, unsignedp);
3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201

	  temp = expand_complex_abs (wider_mode, xop0, NULL_RTX, unsignedp);

	  if (temp)
	    {
	      if (class != MODE_COMPLEX_INT)
		{
		  if (target == 0)
		    target = gen_reg_rtx (submode);
		  convert_move (target, temp, 0);
		  return target;
		}
	      else
		return gen_lowpart (submode, temp);
	    }
	  else
	    delete_insns_since (last);
	}
    }

3202
  delete_insns_since (entry_last);
3203 3204 3205
  return 0;
}

Richard Kenner committed
3206 3207 3208 3209 3210 3211 3212
/* Generate an instruction whose insn-code is INSN_CODE,
   with two operands: an output TARGET and an input OP0.
   TARGET *must* be nonzero, and the output is always stored there.
   CODE is an rtx code such that (CODE OP0) is an rtx that describes
   the value that is stored into TARGET.  */

void
3213
emit_unop_insn (int icode, rtx target, rtx op0, enum rtx_code code)
Richard Kenner committed
3214
{
3215
  rtx temp;
3216
  enum machine_mode mode0 = insn_data[icode].operand[1].mode;
Richard Kenner committed
3217 3218 3219 3220 3221 3222
  rtx pat;

  temp = target = protect_from_queue (target, 1);

  op0 = protect_from_queue (op0, 0);

3223 3224 3225 3226
  /* Sign and zero extension from memory is often done specially on
     RISC machines, so forcing into a register here can pessimize
     code.  */
  if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND)
Richard Kenner committed
3227 3228 3229 3230
    op0 = force_not_mem (op0);

  /* Now, if insn does not accept our operands, put them into pseudos.  */

3231
  if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
Richard Kenner committed
3232 3233
    op0 = copy_to_mode_reg (mode0, op0);

3234
  if (! (*insn_data[icode].operand[0].predicate) (temp, GET_MODE (temp))
Richard Kenner committed
3235 3236 3237 3238 3239
      || (flag_force_mem && GET_CODE (temp) == MEM))
    temp = gen_reg_rtx (GET_MODE (temp));

  pat = GEN_FCN (icode) (temp, op0);

3240
  if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN)
Charles Hannum committed
3241
    add_equal_note (pat, temp, code, op0, NULL_RTX);
3242

Richard Kenner committed
3243 3244 3245 3246 3247 3248 3249 3250 3251
  emit_insn (pat);

  if (temp != target)
    emit_move_insn (target, temp);
}

/* Emit code to perform a series of operations on a multi-word quantity, one
   word at a time.

3252
   Such a block is preceded by a CLOBBER of the output, consists of multiple
Richard Kenner committed
3253 3254 3255 3256 3257 3258 3259 3260 3261 3262
   insns, each setting one word of the output, and followed by a SET copying
   the output to itself.

   Each of the insns setting words of the output receives a REG_NO_CONFLICT
   note indicating that it doesn't conflict with the (also multi-word)
   inputs.  The entire block is surrounded by REG_LIBCALL and REG_RETVAL
   notes.

   INSNS is a block of code generated to perform the operation, not including
   the CLOBBER and final copy.  All insns that compute intermediate values
3263
   are first emitted, followed by the block as described above.
Richard Kenner committed
3264 3265 3266 3267

   TARGET, OP0, and OP1 are the output and inputs of the operations,
   respectively.  OP1 may be zero for a unary operation.

3268
   EQUIV, if nonzero, is an expression to be placed into a REG_EQUAL note
Richard Kenner committed
3269 3270 3271
   on the last insn.

   If TARGET is not a register, INSNS is simply emitted with no special
3272 3273
   processing.  Likewise if anything in INSNS is not an INSN or if
   there is a libcall block inside INSNS.
Richard Kenner committed
3274 3275 3276 3277

   The final insn emitted is returned.  */

rtx
3278
emit_no_conflict_block (rtx insns, rtx target, rtx op0, rtx op1, rtx equiv)
Richard Kenner committed
3279 3280 3281 3282
{
  rtx prev, next, first, last, insn;

  if (GET_CODE (target) != REG || reload_in_progress)
3283
    return emit_insn (insns);
3284 3285 3286 3287
  else
    for (insn = insns; insn; insn = NEXT_INSN (insn))
      if (GET_CODE (insn) != INSN
	  || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
3288
	return emit_insn (insns);
Richard Kenner committed
3289 3290 3291 3292 3293

  /* First emit all insns that do not store into words of the output and remove
     these from the list.  */
  for (insn = insns; insn; insn = next)
    {
3294
      rtx set = 0, note;
Richard Kenner committed
3295 3296 3297 3298
      int i;

      next = NEXT_INSN (insn);

3299
      /* Some ports (cris) create a libcall regions at their own.  We must
3300 3301 3302 3303 3304 3305
	 avoid any potential nesting of LIBCALLs.  */
      if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
	remove_note (insn, note);
      if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
	remove_note (insn, note);

Jeff Law committed
3306 3307
      if (GET_CODE (PATTERN (insn)) == SET || GET_CODE (PATTERN (insn)) == USE
	  || GET_CODE (PATTERN (insn)) == CLOBBER)
Richard Kenner committed
3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340
	set = PATTERN (insn);
      else if (GET_CODE (PATTERN (insn)) == PARALLEL)
	{
	  for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
	    if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
	      {
		set = XVECEXP (PATTERN (insn), 0, i);
		break;
	      }
	}

      if (set == 0)
	abort ();

      if (! reg_overlap_mentioned_p (target, SET_DEST (set)))
	{
	  if (PREV_INSN (insn))
	    NEXT_INSN (PREV_INSN (insn)) = next;
	  else
	    insns = next;

	  if (next)
	    PREV_INSN (next) = PREV_INSN (insn);

	  add_insn (insn);
	}
    }

  prev = get_last_insn ();

  /* Now write the CLOBBER of the output, followed by the setting of each
     of the words, followed by the final copy.  */
  if (target != op0 && target != op1)
3341
    emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
Richard Kenner committed
3342 3343 3344 3345 3346 3347 3348

  for (insn = insns; insn; insn = next)
    {
      next = NEXT_INSN (insn);
      add_insn (insn);

      if (op1 && GET_CODE (op1) == REG)
3349 3350
	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op1,
					      REG_NOTES (insn));
Richard Kenner committed
3351 3352

      if (op0 && GET_CODE (op0) == REG)
3353 3354
	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_NO_CONFLICT, op0,
					      REG_NOTES (insn));
Richard Kenner committed
3355 3356
    }

3357 3358 3359 3360 3361
  if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
      != CODE_FOR_nothing)
    {
      last = emit_move_insn (target, target);
      if (equiv)
3362
	set_unique_reg_note (last, REG_EQUAL, equiv);
3363 3364
    }
  else
3365 3366 3367 3368 3369 3370 3371 3372 3373 3374
    {
      last = get_last_insn ();

      /* Remove any existing REG_EQUAL note from "last", or else it will
	 be mistaken for a note referring to the full contents of the
	 alleged libcall value when found together with the REG_RETVAL
	 note added below.  An existing note can come from an insn
	 expansion at "last".  */
      remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
    }
Richard Kenner committed
3375 3376 3377 3378 3379 3380 3381

  if (prev == 0)
    first = get_insns ();
  else
    first = NEXT_INSN (prev);

  /* Encapsulate the block so it gets manipulated as a unit.  */
3382 3383 3384
  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
					 REG_NOTES (first));
  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
Richard Kenner committed
3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400

  return last;
}

/* Emit code to make a call to a constant function or a library call.

   INSNS is a list containing all insns emitted in the call.
   These insns leave the result in RESULT.  Our block is to copy RESULT
   to TARGET, which is logically equivalent to EQUIV.

   We first emit any insns that set a pseudo on the assumption that these are
   loading constants into registers; doing so allows them to be safely cse'ed
   between blocks.  Then we emit all the other insns in the block, followed by
   an insn to move RESULT to TARGET.  This last insn will have a REQ_EQUAL
   note with an operand of EQUIV.

3401 3402 3403 3404 3405 3406 3407 3408 3409 3410
   Moving assignments to pseudos outside of the block is done to improve
   the generated code, but is not required to generate correct code,
   hence being unable to move an assignment is not grounds for not making
   a libcall block.  There are two reasons why it is safe to leave these
   insns inside the block: First, we know that these pseudos cannot be
   used in generated RTL outside the block since they are created for
   temporary purposes within the block.  Second, CSE will not record the
   values of anything set inside a libcall block, so we know they must
   be dead at the end of the block.

Richard Kenner committed
3411 3412 3413 3414
   Except for the first group of insns (the ones setting pseudos), the
   block is delimited by REG_RETVAL and REG_LIBCALL notes.  */

void
3415
emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv)
Richard Kenner committed
3416
{
3417
  rtx final_dest = target;
Richard Kenner committed
3418 3419
  rtx prev, next, first, last, insn;

3420 3421 3422 3423
  /* If this is a reg with REG_USERVAR_P set, then it could possibly turn
     into a MEM later.  Protect the libcall block from this change.  */
  if (! REG_P (target) || REG_USERVAR_P (target))
    target = gen_reg_rtx (GET_MODE (target));
3424

3425 3426 3427 3428 3429 3430 3431 3432
  /* If we're using non-call exceptions, a libcall corresponding to an
     operation that may trap may also trap.  */
  if (flag_non_call_exceptions && may_trap_p (equiv))
    {
      for (insn = insns; insn; insn = NEXT_INSN (insn))
	if (GET_CODE (insn) == CALL_INSN)
	  {
	    rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3433

3434 3435 3436 3437 3438
	    if (note != 0 && INTVAL (XEXP (note, 0)) <= 0)
	      remove_note (insn, note);
	  }
    }
  else
3439
  /* look for any CALL_INSNs in this sequence, and attach a REG_EH_REGION
3440
     reg note to indicate that this call cannot throw or execute a nonlocal
3441
     goto (unless there is already a REG_EH_REGION note, in which case
3442
     we update it).  */
3443 3444 3445 3446
    for (insn = insns; insn; insn = NEXT_INSN (insn))
      if (GET_CODE (insn) == CALL_INSN)
	{
	  rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3447

3448
	  if (note != 0)
3449
	    XEXP (note, 0) = constm1_rtx;
3450
	  else
3451
	    REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx,
3452 3453
						  REG_NOTES (insn));
	}
3454

Richard Kenner committed
3455
  /* First emit all insns that set pseudos.  Remove them from the list as
3456
     we go.  Avoid insns that set pseudos which were referenced in previous
3457
     insns.  These can be generated by move_by_pieces, for example,
3458 3459
     to update an address.  Similarly, avoid insns that reference things
     set in previous insns.  */
Richard Kenner committed
3460 3461 3462 3463

  for (insn = insns; insn; insn = next)
    {
      rtx set = single_set (insn);
3464 3465
      rtx note;

3466
      /* Some ports (cris) create a libcall regions at their own.  We must
3467 3468 3469 3470 3471
	 avoid any potential nesting of LIBCALLs.  */
      if ((note = find_reg_note (insn, REG_LIBCALL, NULL)) != NULL)
	remove_note (insn, note);
      if ((note = find_reg_note (insn, REG_RETVAL, NULL)) != NULL)
	remove_note (insn, note);
Richard Kenner committed
3472 3473 3474 3475

      next = NEXT_INSN (insn);

      if (set != 0 && GET_CODE (SET_DEST (set)) == REG
3476
	  && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
3477
	  && (insn == insns
3478 3479
	      || ((! INSN_P(insns)
		   || ! reg_mentioned_p (SET_DEST (set), PATTERN (insns)))
3480 3481 3482
		  && ! reg_used_between_p (SET_DEST (set), insns, insn)
		  && ! modified_in_p (SET_SRC (set), insns)
		  && ! modified_between_p (SET_SRC (set), insns, insn))))
Richard Kenner committed
3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493
	{
	  if (PREV_INSN (insn))
	    NEXT_INSN (PREV_INSN (insn)) = next;
	  else
	    insns = next;

	  if (next)
	    PREV_INSN (next) = PREV_INSN (insn);

	  add_insn (insn);
	}
3494 3495 3496 3497 3498

      /* Some ports use a loop to copy large arguments onto the stack.
	 Don't move anything outside such a loop.  */
      if (GET_CODE (insn) == CODE_LABEL)
	break;
Richard Kenner committed
3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512
    }

  prev = get_last_insn ();

  /* Write the remaining insns followed by the final copy.  */

  for (insn = insns; insn; insn = next)
    {
      next = NEXT_INSN (insn);

      add_insn (insn);
    }

  last = emit_move_insn (target, result);
3513 3514
  if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
      != CODE_FOR_nothing)
3515
    set_unique_reg_note (last, REG_EQUAL, copy_rtx (equiv));
3516 3517 3518 3519 3520 3521 3522 3523 3524
  else
    {
      /* Remove any existing REG_EQUAL note from "last", or else it will
	 be mistaken for a note referring to the full contents of the
	 libcall value when found together with the REG_RETVAL note added
	 below.  An existing note can come from an insn expansion at
	 "last".  */
      remove_note (last, find_reg_note (last, REG_EQUAL, NULL_RTX));
    }
Richard Kenner committed
3525

3526 3527
  if (final_dest != target)
    emit_move_insn (final_dest, target);
3528

Richard Kenner committed
3529 3530 3531 3532 3533 3534
  if (prev == 0)
    first = get_insns ();
  else
    first = NEXT_INSN (prev);

  /* Encapsulate the block so it gets manipulated as a unit.  */
3535 3536
  if (!flag_non_call_exceptions || !may_trap_p (equiv))
    {
3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556
      /* We can't attach the REG_LIBCALL and REG_RETVAL notes
	 when the encapsulated region would not be in one basic block,
	 i.e. when there is a control_flow_insn_p insn between FIRST and LAST.
       */
      bool attach_libcall_retval_notes = true;
      next = NEXT_INSN (last);
      for (insn = first; insn != next; insn = NEXT_INSN (insn))
	if (control_flow_insn_p (insn))
	  {
	    attach_libcall_retval_notes = false;
	    break;
	  }

      if (attach_libcall_retval_notes)
	{
	  REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last,
						 REG_NOTES (first));
	  REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first,
						REG_NOTES (last));
	}
3557
    }
Richard Kenner committed
3558 3559 3560 3561 3562
}

/* Generate code to store zero in X.  */

void
3563
emit_clr_insn (rtx x)
Richard Kenner committed
3564 3565 3566 3567 3568 3569 3570 3571
{
  emit_move_insn (x, const0_rtx);
}

/* Generate code to store 1 in X
   assuming it contains zero beforehand.  */

void
3572
emit_0_to_1_insn (rtx x)
Richard Kenner committed
3573 3574 3575 3576
{
  emit_move_insn (x, const1_rtx);
}

3577
/* Nonzero if we can perform a comparison of mode MODE straightforwardly.
3578 3579 3580 3581
   PURPOSE describes how this comparison will be used.  CODE is the rtx
   comparison code we will be using.

   ??? Actually, CODE is slightly weaker than that.  A target is still
3582
   required to implement all of the normal bcc operations, but not
3583
   required to implement all (or any) of the unordered bcc operations.  */
3584

3585
int
3586 3587
can_compare_p (enum rtx_code code, enum machine_mode mode,
	       enum can_compare_purpose purpose)
3588 3589 3590
{
  do
    {
3591
      if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3592 3593
	{
	  if (purpose == ccp_jump)
3594
	    return bcc_gen_fctn[(int) code] != NULL;
3595
	  else if (purpose == ccp_store_flag)
3596
	    return setcc_gen_code[(int) code] != CODE_FOR_nothing;
3597 3598 3599 3600
	  else
	    /* There's only one cmov entry point, and it's allowed to fail.  */
	    return 1;
	}
3601
      if (purpose == ccp_jump
3602
	  && cbranch_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3603 3604
	return 1;
      if (purpose == ccp_cmov
3605
	  && cmov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3606 3607
	return 1;
      if (purpose == ccp_store_flag
3608
	  && cstore_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
3609 3610
	return 1;

3611
      mode = GET_MODE_WIDER_MODE (mode);
3612 3613
    }
  while (mode != VOIDmode);
3614 3615 3616 3617 3618 3619 3620 3621 3622

  return 0;
}

/* This function is called when we are going to emit a compare instruction that
   compares the values found in *PX and *PY, using the rtl operator COMPARISON.

   *PMODE is the mode of the inputs (in case they are const_int).
   *PUNSIGNEDP nonzero says that the operands are unsigned;
Richard Kenner committed
3623 3624
   this matters if they need to be widened.

3625
   If they have mode BLKmode, then SIZE specifies the size of both operands.
Richard Kenner committed
3626

3627 3628 3629 3630 3631 3632
   This function performs all the setup necessary so that the caller only has
   to emit a single comparison insn.  This setup can involve doing a BLKmode
   comparison or emitting a library call to perform the comparison if no insn
   is available to handle it.
   The values which are passed in through pointers can be modified; the caller
   should perform the comparison on the modified values.  */
Richard Kenner committed
3633

3634
static void
3635 3636 3637
prepare_cmp_insn (rtx *px, rtx *py, enum rtx_code *pcomparison, rtx size,
		  enum machine_mode *pmode, int *punsignedp,
		  enum can_compare_purpose purpose)
Richard Kenner committed
3638
{
3639 3640 3641
  enum machine_mode mode = *pmode;
  rtx x = *px, y = *py;
  int unsignedp = *punsignedp;
Richard Kenner committed
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652
  enum mode_class class;

  class = GET_MODE_CLASS (mode);

  /* They could both be VOIDmode if both args are immediate constants,
     but we should fold that at an earlier stage.
     With no special code here, this will call abort,
     reminding the programmer to implement such folding.  */

  if (mode != BLKmode && flag_force_mem)
    {
3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663
      /* Load duplicate non-volatile operands once.  */
      if (rtx_equal_p (x, y) && ! volatile_refs_p (x))
	{
	  x = force_not_mem (x);
	  y = x;
	}
      else
	{
	  x = force_not_mem (x);
	  y = force_not_mem (y);
	}
Richard Kenner committed
3664 3665 3666 3667
    }

  /* If we are inside an appropriately-short loop and one operand is an
     expensive constant, force it into a register.  */
3668
  if (CONSTANT_P (x) && preserve_subexpressions_p ()
3669
      && rtx_cost (x, COMPARE) > COSTS_N_INSNS (1))
Richard Kenner committed
3670 3671
    x = force_reg (mode, x);

3672
  if (CONSTANT_P (y) && preserve_subexpressions_p ()
3673
      && rtx_cost (y, COMPARE) > COSTS_N_INSNS (1))
Richard Kenner committed
3674 3675
    y = force_reg (mode, y);

3676 3677 3678 3679 3680
#ifdef HAVE_cc0
  /* Abort if we have a non-canonical comparison.  The RTL documentation
     states that canonical comparisons are required only for targets which
     have cc0.  */
  if (CONSTANT_P (x) && ! CONSTANT_P (y))
3681
    abort ();
3682 3683
#endif

Richard Kenner committed
3684 3685 3686 3687 3688 3689 3690 3691
  /* Don't let both operands fail to indicate the mode.  */
  if (GET_MODE (x) == VOIDmode && GET_MODE (y) == VOIDmode)
    x = force_reg (mode, x);

  /* Handle all BLKmode compares.  */

  if (mode == BLKmode)
    {
3692 3693 3694 3695
      enum machine_mode cmp_mode, result_mode;
      enum insn_code cmp_code;
      tree length_type;
      rtx libfunc;
3696
      rtx result;
3697
      rtx opalign
3698
	= GEN_INT (MIN (MEM_ALIGN (x), MEM_ALIGN (y)) / BITS_PER_UNIT);
3699

3700 3701 3702
      if (size == 0)
	abort ();

Richard Kenner committed
3703 3704 3705
      emit_queue ();
      x = protect_from_queue (x, 0);
      y = protect_from_queue (y, 0);
3706
      size = protect_from_queue (size, 0);
Richard Kenner committed
3707

3708 3709 3710 3711 3712
      /* Try to use a memory block compare insn - either cmpstr
	 or cmpmem will do.  */
      for (cmp_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
	   cmp_mode != VOIDmode;
	   cmp_mode = GET_MODE_WIDER_MODE (cmp_mode))
3713
	{
3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727
	  cmp_code = cmpmem_optab[cmp_mode];
	  if (cmp_code == CODE_FOR_nothing)
	    cmp_code = cmpstr_optab[cmp_mode];
	  if (cmp_code == CODE_FOR_nothing)
	    continue;

	  /* Must make sure the size fits the insn's mode.  */
	  if ((GET_CODE (size) == CONST_INT
	       && INTVAL (size) >= (1 << GET_MODE_BITSIZE (cmp_mode)))
	      || (GET_MODE_BITSIZE (GET_MODE (size))
		  > GET_MODE_BITSIZE (cmp_mode)))
	    continue;

	  result_mode = insn_data[cmp_code].operand[0].mode;
3728
	  result = gen_reg_rtx (result_mode);
3729 3730 3731 3732 3733 3734 3735
	  size = convert_to_mode (cmp_mode, size, 1);
	  emit_insn (GEN_FCN (cmp_code) (result, x, y, size, opalign));

	  *px = result;
	  *py = const0_rtx;
	  *pmode = result_mode;
	  return;
Richard Kenner committed
3736
	}
3737 3738 3739

      /* Otherwise call a library function, memcmp if we've got it,
	 bcmp otherwise.  */
Richard Kenner committed
3740
#ifdef TARGET_MEM_FUNCTIONS
3741 3742
      libfunc = memcmp_libfunc;
      length_type = sizetype;
Richard Kenner committed
3743
#else
3744 3745
      libfunc = bcmp_libfunc;
      length_type = integer_type_node;
Richard Kenner committed
3746
#endif
3747 3748 3749
      result_mode = TYPE_MODE (integer_type_node);
      cmp_mode = TYPE_MODE (length_type);
      size = convert_to_mode (TYPE_MODE (length_type), size,
3750
			      TYPE_UNSIGNED (length_type));
3751 3752 3753 3754 3755 3756

      result = emit_library_call_value (libfunc, 0, LCT_PURE_MAKE_BLOCK,
					result_mode, 3,
					XEXP (x, 0), Pmode,
					XEXP (y, 0), Pmode,
					size, cmp_mode);
3757 3758 3759
      *px = result;
      *py = const0_rtx;
      *pmode = result_mode;
Richard Kenner committed
3760 3761 3762
      return;
    }

3763 3764 3765 3766 3767 3768 3769 3770 3771 3772
  /* Don't allow operands to the compare to trap, as that can put the
     compare and branch in different basic blocks.  */
  if (flag_non_call_exceptions)
    {
      if (may_trap_p (x))
	x = force_reg (mode, x);
      if (may_trap_p (y))
	y = force_reg (mode, y);
    }

3773 3774
  *px = x;
  *py = y;
3775
  if (can_compare_p (*pcomparison, mode, purpose))
3776
    return;
Richard Kenner committed
3777 3778 3779

  /* Handle a lib call just for the mode we are using.  */

3780
  if (cmp_optab->handlers[(int) mode].libfunc && class != MODE_FLOAT)
Richard Kenner committed
3781 3782
    {
      rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
3783 3784
      rtx result;

Richard Kenner committed
3785 3786 3787 3788 3789
      /* If we want unsigned, and this mode has a distinct unsigned
	 comparison routine, use that.  */
      if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
	libfunc = ucmp_optab->handlers[(int) mode].libfunc;

3790 3791
      result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
					word_mode, 2, x, mode, y, mode);
3792

Richard Kenner committed
3793 3794 3795
      /* Integer comparison returns a result that must be compared against 1,
	 so that even if we do an unsigned compare afterward,
	 there is still a value that can represent the result "less than".  */
3796 3797 3798
      *px = result;
      *py = const1_rtx;
      *pmode = word_mode;
Richard Kenner committed
3799 3800 3801 3802
      return;
    }

  if (class == MODE_FLOAT)
3803
    prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
Richard Kenner committed
3804 3805 3806 3807 3808

  else
    abort ();
}

3809 3810
/* Before emitting an insn with code ICODE, make sure that X, which is going
   to be used for operand OPNUM of the insn, is converted from mode MODE to
3811
   WIDER_MODE (UNSIGNEDP determines whether it is an unsigned conversion), and
3812
   that it is accepted by the operand predicate.  Return the new value.  */
3813

3814
rtx
3815 3816
prepare_operand (int icode, rtx x, int opnum, enum machine_mode mode,
		 enum machine_mode wider_mode, int unsignedp)
3817 3818 3819 3820 3821 3822
{
  x = protect_from_queue (x, 0);

  if (mode != wider_mode)
    x = convert_modes (wider_mode, mode, x, unsignedp);

3823 3824
  if (! (*insn_data[icode].operand[opnum].predicate)
      (x, insn_data[icode].operand[opnum].mode))
3825 3826 3827 3828 3829 3830
    {
      if (no_new_pseudos)
	return NULL_RTX;
      x = copy_to_mode_reg (insn_data[icode].operand[opnum].mode, x);
    }

3831 3832 3833 3834 3835 3836 3837 3838 3839
  return x;
}

/* Subroutine of emit_cmp_and_jump_insns; this function is called when we know
   we can do the comparison.
   The arguments are the same as for emit_cmp_and_jump_insns; but LABEL may
   be NULL_RTX which indicates that only a comparison is to be generated.  */

static void
3840 3841
emit_cmp_and_jump_insn_1 (rtx x, rtx y, enum machine_mode mode,
			  enum rtx_code comparison, int unsignedp, rtx label)
3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852
{
  rtx test = gen_rtx_fmt_ee (comparison, mode, x, y);
  enum mode_class class = GET_MODE_CLASS (mode);
  enum machine_mode wider_mode = mode;

  /* Try combined insns first.  */
  do
    {
      enum insn_code icode;
      PUT_MODE (test, wider_mode);

3853
      if (label)
3854
	{
3855
	  icode = cbranch_optab->handlers[(int) wider_mode].insn_code;
3856

3857 3858 3859 3860 3861 3862 3863 3864 3865 3866
	  if (icode != CODE_FOR_nothing
	      && (*insn_data[icode].operand[0].predicate) (test, wider_mode))
	    {
	      x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp);
	      y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp);
	      emit_jump_insn (GEN_FCN (icode) (test, x, y, label));
	      return;
	    }
	}

3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895
      /* Handle some compares against zero.  */
      icode = (int) tst_optab->handlers[(int) wider_mode].insn_code;
      if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
	{
	  x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
	  emit_insn (GEN_FCN (icode) (x));
	  if (label)
	    emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
	  return;
	}

      /* Handle compares for which there is a directly suitable insn.  */

      icode = (int) cmp_optab->handlers[(int) wider_mode].insn_code;
      if (icode != CODE_FOR_nothing)
	{
	  x = prepare_operand (icode, x, 0, mode, wider_mode, unsignedp);
	  y = prepare_operand (icode, y, 1, mode, wider_mode, unsignedp);
	  emit_insn (GEN_FCN (icode) (x, y));
	  if (label)
	    emit_jump_insn ((*bcc_gen_fctn[(int) comparison]) (label));
	  return;
	}

      if (class != MODE_INT && class != MODE_FLOAT
	  && class != MODE_COMPLEX_FLOAT)
	break;

      wider_mode = GET_MODE_WIDER_MODE (wider_mode);
3896 3897
    }
  while (wider_mode != VOIDmode);
3898 3899 3900 3901

  abort ();
}

3902 3903 3904 3905 3906
/* Generate code to compare X with Y so that the condition codes are
   set and to jump to LABEL if the condition is true.  If X is a
   constant and Y is not a constant, then the comparison is swapped to
   ensure that the comparison RTL has the canonical form.

3907 3908 3909
   UNSIGNEDP nonzero says that X and Y are unsigned; this matters if they
   need to be widened by emit_cmp_insn.  UNSIGNEDP is also used to select
   the proper branch condition code.
3910

3911
   If X and Y have mode BLKmode, then SIZE specifies the size of both X and Y.
3912

3913 3914 3915 3916 3917
   MODE is the mode of the inputs (in case they are const_int).

   COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  It will
   be passed unchanged to emit_cmp_insn, then potentially converted into an
   unsigned variant based on UNSIGNEDP to select a proper jump instruction.  */
3918 3919

void
3920 3921
emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size,
			 enum machine_mode mode, int unsignedp, rtx label)
3922
{
3923 3924 3925 3926
  rtx op0 = x, op1 = y;

  /* Swap operands and condition to ensure canonical RTL.  */
  if (swap_commutative_operands_p (x, y))
3927
    {
3928 3929 3930 3931 3932 3933 3934
      /* If we're not emitting a branch, this means some caller
         is out of sync.  */
      if (! label)
	abort ();

      op0 = y, op1 = x;
      comparison = swap_condition (comparison);
3935
    }
3936 3937 3938 3939 3940 3941 3942 3943 3944

#ifdef HAVE_cc0
  /* If OP0 is still a constant, then both X and Y must be constants.  Force
     X into a register to avoid aborting in emit_cmp_insn due to non-canonical
     RTL.  */
  if (CONSTANT_P (op0))
    op0 = force_reg (mode, op0);
#endif

3945
  emit_queue ();
3946 3947
  if (unsignedp)
    comparison = unsigned_condition (comparison);
3948 3949

  prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp,
3950
		    ccp_jump);
3951 3952 3953 3954
  emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
}

/* Like emit_cmp_and_jump_insns, but generate only the comparison.  */
3955

3956
void
3957 3958
emit_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size,
	       enum machine_mode mode, int unsignedp)
3959
{
3960
  emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, 0);
3961
}
Richard Kenner committed
3962 3963 3964 3965

/* Emit a library call comparison between floating point X and Y.
   COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */

3966
static void
3967 3968
prepare_float_lib_cmp (rtx *px, rtx *py, enum rtx_code *pcomparison,
		       enum machine_mode *pmode, int *punsignedp)
Richard Kenner committed
3969
{
3970
  enum rtx_code comparison = *pcomparison;
Zack Weinberg committed
3971 3972 3973 3974 3975
  enum rtx_code swapped = swap_condition (comparison);
  rtx x = protect_from_queue (*px, 0);
  rtx y = protect_from_queue (*py, 0);
  enum machine_mode orig_mode = GET_MODE (x);
  enum machine_mode mode;
3976
  rtx value, target, insns, equiv;
3977
  rtx libfunc = 0;
Richard Kenner committed
3978

Zack Weinberg committed
3979
  for (mode = orig_mode; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
Richard Kenner committed
3980
    {
Zack Weinberg committed
3981 3982
      if ((libfunc = code_to_optab[comparison]->handlers[mode].libfunc))
	break;
Richard Kenner committed
3983

Zack Weinberg committed
3984
      if ((libfunc = code_to_optab[swapped]->handlers[mode].libfunc))
Richard Kenner committed
3985
	{
Zack Weinberg committed
3986 3987 3988 3989
	  rtx tmp;
	  tmp = x; x = y; y = tmp;
	  comparison = swapped;
	  break;
Richard Kenner committed
3990 3991 3992
	}
    }

Zack Weinberg committed
3993
  if (mode == VOIDmode)
3994 3995
    abort ();

Zack Weinberg committed
3996 3997 3998 3999 4000 4001
  if (mode != orig_mode)
    {
      x = convert_to_mode (mode, x, 0);
      y = convert_to_mode (mode, y, 0);
    }

4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015
  /* Attach a REG_EQUAL note describing the semantics of the libcall to
     the RTL.  The allows the RTL optimizers to delete the libcall if the
     condition can be determined at compile-time.  */
  if (comparison == UNORDERED)
    {
      rtx temp = simplify_gen_relational (NE, word_mode, mode, x, x);
      equiv = simplify_gen_relational (NE, word_mode, mode, y, y);
      equiv = simplify_gen_ternary (IF_THEN_ELSE, word_mode, word_mode,
				    temp, const_true_rtx, equiv);
    }
  else
    {
      equiv = simplify_gen_relational (comparison, word_mode, mode, x, y);
      if (! FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
4016
	{
4017
	  rtx true_rtx, false_rtx;
4018

4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052
	  switch (comparison)
	    {
	    case EQ:
	      true_rtx = const0_rtx;
	      false_rtx = const_true_rtx;
	      break;

	    case NE:
	      true_rtx = const_true_rtx;
	      false_rtx = const0_rtx;
	      break;

	    case GT:
	      true_rtx = const1_rtx;
	      false_rtx = const0_rtx;
	      break;

	    case GE:
	      true_rtx = const0_rtx;
	      false_rtx = constm1_rtx;
	      break;

	    case LT:
	      true_rtx = constm1_rtx;
	      false_rtx = const0_rtx;
	      break;

	    case LE:
	      true_rtx = const0_rtx;
	      false_rtx = const1_rtx;
	      break;

	    default:
	      abort ();
4053
	    }
4054 4055
	  equiv = simplify_gen_ternary (IF_THEN_ELSE, word_mode, word_mode,
					equiv, true_rtx, false_rtx);
4056 4057
	}
    }
4058 4059 4060 4061 4062 4063 4064 4065 4066 4067

  start_sequence ();
  value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
				   word_mode, 2, x, mode, y, mode);
  insns = get_insns ();
  end_sequence ();

  target = gen_reg_rtx (word_mode);
  emit_libcall_block (insns, target, value, equiv);

4068

Zack Weinberg committed
4069 4070 4071 4072
  if (comparison == UNORDERED
      || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
    comparison = NE;

4073
  *px = target;
4074 4075
  *py = const0_rtx;
  *pmode = word_mode;
Zack Weinberg committed
4076
  *pcomparison = comparison;
4077
  *punsignedp = 0;
Richard Kenner committed
4078 4079 4080 4081 4082
}

/* Generate code to indirectly jump to a location given in the rtx LOC.  */

void
4083
emit_indirect_jump (rtx loc)
Richard Kenner committed
4084
{
4085
  if (! ((*insn_data[(int) CODE_FOR_indirect_jump].operand[0].predicate)
4086 4087
	 (loc, Pmode)))
    loc = copy_to_mode_reg (Pmode, loc);
Richard Kenner committed
4088 4089

  emit_jump_insn (gen_indirect_jump (loc));
4090
  emit_barrier ();
Richard Kenner committed
4091 4092
}

4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109
#ifdef HAVE_conditional_move

/* Emit a conditional move instruction if the machine supports one for that
   condition and machine mode.

   OP0 and OP1 are the operands that should be compared using CODE.  CMODE is
   the mode to use should they be constants.  If it is VOIDmode, they cannot
   both be constants.

   OP2 should be stored in TARGET if the comparison is true, otherwise OP3
   should be stored there.  MODE is the mode to use should they be constants.
   If it is VOIDmode, they cannot both be constants.

   The result is either TARGET (perhaps modified) or NULL_RTX if the operation
   is not supported.  */

rtx
4110 4111 4112
emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
		       enum machine_mode cmode, rtx op2, rtx op3,
		       enum machine_mode mode, int unsignedp)
4113 4114 4115
{
  rtx tem, subtarget, comparison, insn;
  enum insn_code icode;
4116
  enum rtx_code reversed;
4117 4118 4119 4120

  /* If one operand is constant, make it the second one.  Only do this
     if the other operand is not constant as well.  */

4121
  if (swap_commutative_operands_p (op0, op1))
4122 4123 4124 4125 4126 4127 4128
    {
      tem = op0;
      op0 = op1;
      op1 = tem;
      code = swap_condition (code);
    }

Jeff Law committed
4129 4130 4131
  /* get_condition will prefer to generate LT and GT even if the old
     comparison was against zero, so undo that canonicalization here since
     comparisons against zero are cheaper.  */
4132
  if (code == LT && op1 == const1_rtx)
Jeff Law committed
4133
    code = LE, op1 = const0_rtx;
4134
  else if (code == GT && op1 == constm1_rtx)
Jeff Law committed
4135 4136
    code = GE, op1 = const0_rtx;

4137 4138 4139
  if (cmode == VOIDmode)
    cmode = GET_MODE (op0);

4140 4141 4142
  if (swap_commutative_operands_p (op2, op3)
      && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
          != UNKNOWN))
4143 4144 4145 4146
    {
      tem = op2;
      op2 = op3;
      op3 = tem;
4147
      code = reversed;
4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177
    }

  if (mode == VOIDmode)
    mode = GET_MODE (op2);

  icode = movcc_gen_code[mode];

  if (icode == CODE_FOR_nothing)
    return 0;

  if (flag_force_mem)
    {
      op2 = force_not_mem (op2);
      op3 = force_not_mem (op3);
    }

  if (target)
    target = protect_from_queue (target, 1);
  else
    target = gen_reg_rtx (mode);

  subtarget = target;

  emit_queue ();

  op2 = protect_from_queue (op2, 0);
  op3 = protect_from_queue (op3, 0);

  /* If the insn doesn't accept these operands, put them in pseudos.  */

4178 4179 4180
  if (! (*insn_data[icode].operand[0].predicate)
      (subtarget, insn_data[icode].operand[0].mode))
    subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);
4181

4182 4183 4184
  if (! (*insn_data[icode].operand[2].predicate)
      (op2, insn_data[icode].operand[2].mode))
    op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
4185

4186 4187 4188
  if (! (*insn_data[icode].operand[3].predicate)
      (op3, insn_data[icode].operand[3].mode))
    op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);
4189 4190 4191 4192

  /* Everything should now be in the suitable form, so emit the compare insn
     and then the conditional move.  */

4193
  comparison
4194
    = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX);
4195 4196

  /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)?  */
4197 4198 4199
  /* We can get const0_rtx or const_true_rtx in some circumstances.  Just
     return NULL and let the caller figure out how best to deal with this
     situation.  */
4200
  if (GET_CODE (comparison) != code)
4201
    return NULL_RTX;
4202

4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216
  insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);

  /* If that failed, then give up.  */
  if (insn == 0)
    return 0;

  emit_insn (insn);

  if (subtarget != target)
    convert_move (target, subtarget, 0);

  return target;
}

4217
/* Return nonzero if a conditional move of mode MODE is supported.
4218 4219 4220 4221 4222 4223 4224 4225

   This function is for combine so it can tell whether an insn that looks
   like a conditional move is actually supported by the hardware.  If we
   guess wrong we lose a bit on optimization, but that's it.  */
/* ??? sparc64 supports conditionally moving integers values based on fp
   comparisons, and vice versa.  How do we handle them?  */

int
4226
can_conditionally_move_p (enum machine_mode mode)
4227 4228 4229 4230 4231 4232 4233 4234
{
  if (movcc_gen_code[mode] != CODE_FOR_nothing)
    return 1;

  return 0;
}

#endif /* HAVE_conditional_move */
4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250

/* Emit a conditional addition instruction if the machine supports one for that
   condition and machine mode.

   OP0 and OP1 are the operands that should be compared using CODE.  CMODE is
   the mode to use should they be constants.  If it is VOIDmode, they cannot
   both be constants.

   OP2 should be stored in TARGET if the comparison is true, otherwise OP2+OP3
   should be stored there.  MODE is the mode to use should they be constants.
   If it is VOIDmode, they cannot both be constants.

   The result is either TARGET (perhaps modified) or NULL_RTX if the operation
   is not supported.  */

rtx
4251 4252 4253
emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1,
		      enum machine_mode cmode, rtx op2, rtx op3,
		      enum machine_mode mode, int unsignedp)
4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272
{
  rtx tem, subtarget, comparison, insn;
  enum insn_code icode;
  enum rtx_code reversed;

  /* If one operand is constant, make it the second one.  Only do this
     if the other operand is not constant as well.  */

  if (swap_commutative_operands_p (op0, op1))
    {
      tem = op0;
      op0 = op1;
      op1 = tem;
      code = swap_condition (code);
    }

  /* get_condition will prefer to generate LT and GT even if the old
     comparison was against zero, so undo that canonicalization here since
     comparisons against zero are cheaper.  */
4273
  if (code == LT && op1 == const1_rtx)
4274
    code = LE, op1 = const0_rtx;
4275
  else if (code == GT && op1 == constm1_rtx)
4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333
    code = GE, op1 = const0_rtx;

  if (cmode == VOIDmode)
    cmode = GET_MODE (op0);

  if (swap_commutative_operands_p (op2, op3)
      && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL))
          != UNKNOWN))
    {
      tem = op2;
      op2 = op3;
      op3 = tem;
      code = reversed;
    }

  if (mode == VOIDmode)
    mode = GET_MODE (op2);

  icode = addcc_optab->handlers[(int) mode].insn_code;

  if (icode == CODE_FOR_nothing)
    return 0;

  if (flag_force_mem)
    {
      op2 = force_not_mem (op2);
      op3 = force_not_mem (op3);
    }

  if (target)
    target = protect_from_queue (target, 1);
  else
    target = gen_reg_rtx (mode);

  subtarget = target;

  emit_queue ();

  op2 = protect_from_queue (op2, 0);
  op3 = protect_from_queue (op3, 0);

  /* If the insn doesn't accept these operands, put them in pseudos.  */

  if (! (*insn_data[icode].operand[0].predicate)
      (subtarget, insn_data[icode].operand[0].mode))
    subtarget = gen_reg_rtx (insn_data[icode].operand[0].mode);

  if (! (*insn_data[icode].operand[2].predicate)
      (op2, insn_data[icode].operand[2].mode))
    op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);

  if (! (*insn_data[icode].operand[3].predicate)
      (op3, insn_data[icode].operand[3].mode))
    op3 = copy_to_mode_reg (insn_data[icode].operand[3].mode, op3);

  /* Everything should now be in the suitable form, so emit the compare insn
     and then the conditional move.  */

4334
  comparison
4335 4336 4337 4338 4339 4340 4341 4342
    = compare_from_rtx (op0, op1, code, unsignedp, cmode, NULL_RTX);

  /* ??? Watch for const0_rtx (nop) and const_true_rtx (unconditional)?  */
  /* We can get const0_rtx or const_true_rtx in some circumstances.  Just
     return NULL and let the caller figure out how best to deal with this
     situation.  */
  if (GET_CODE (comparison) != code)
    return NULL_RTX;
4343

4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356
  insn = GEN_FCN (icode) (subtarget, comparison, op2, op3);

  /* If that failed, then give up.  */
  if (insn == 0)
    return 0;

  emit_insn (insn);

  if (subtarget != target)
    convert_move (target, subtarget, 0);

  return target;
}
4357

4358 4359 4360
/* These functions attempt to generate an insn body, rather than
   emitting the insn, but if the gen function already emits them, we
   make no attempt to turn them back into naked patterns.
Richard Kenner committed
4361 4362 4363 4364 4365 4366 4367 4368

   They do not protect from queued increments,
   because they may be used 1) in protect_from_queue itself
   and 2) in other passes where there is no queue.  */

/* Generate and return an insn body to add Y to X.  */

rtx
4369
gen_add2_insn (rtx x, rtx y)
Richard Kenner committed
4370
{
4371
  int icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
Richard Kenner committed
4372

4373 4374 4375 4376 4377 4378
  if (! ((*insn_data[icode].operand[0].predicate)
	 (x, insn_data[icode].operand[0].mode))
      || ! ((*insn_data[icode].operand[1].predicate)
	    (x, insn_data[icode].operand[1].mode))
      || ! ((*insn_data[icode].operand[2].predicate)
	    (y, insn_data[icode].operand[2].mode)))
Richard Kenner committed
4379 4380 4381 4382 4383
    abort ();

  return (GEN_FCN (icode) (x, x, y));
}

4384 4385 4386
/* Generate and return an insn body to add r1 and c,
   storing the result in r0.  */
rtx
4387
gen_add3_insn (rtx r0, rtx r1, rtx c)
4388 4389 4390
{
  int icode = (int) add_optab->handlers[(int) GET_MODE (r0)].insn_code;

4391
  if (icode == CODE_FOR_nothing
4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402
      || ! ((*insn_data[icode].operand[0].predicate)
	    (r0, insn_data[icode].operand[0].mode))
      || ! ((*insn_data[icode].operand[1].predicate)
	    (r1, insn_data[icode].operand[1].mode))
      || ! ((*insn_data[icode].operand[2].predicate)
	    (c, insn_data[icode].operand[2].mode)))
    return NULL_RTX;

  return (GEN_FCN (icode) (r0, r1, c));
}

Richard Kenner committed
4403
int
4404
have_add2_insn (rtx x, rtx y)
Richard Kenner committed
4405
{
4406 4407 4408 4409 4410
  int icode;

  if (GET_MODE (x) == VOIDmode)
    abort ();

4411
  icode = (int) add_optab->handlers[(int) GET_MODE (x)].insn_code;
4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424

  if (icode == CODE_FOR_nothing)
    return 0;

  if (! ((*insn_data[icode].operand[0].predicate)
	 (x, insn_data[icode].operand[0].mode))
      || ! ((*insn_data[icode].operand[1].predicate)
	    (x, insn_data[icode].operand[1].mode))
      || ! ((*insn_data[icode].operand[2].predicate)
	    (y, insn_data[icode].operand[2].mode)))
    return 0;

  return 1;
Richard Kenner committed
4425 4426 4427 4428 4429
}

/* Generate and return an insn body to subtract Y from X.  */

rtx
4430
gen_sub2_insn (rtx x, rtx y)
Richard Kenner committed
4431
{
4432
  int icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
Richard Kenner committed
4433

4434 4435 4436 4437 4438 4439
  if (! ((*insn_data[icode].operand[0].predicate)
	 (x, insn_data[icode].operand[0].mode))
      || ! ((*insn_data[icode].operand[1].predicate)
	    (x, insn_data[icode].operand[1].mode))
      || ! ((*insn_data[icode].operand[2].predicate)
	    (y, insn_data[icode].operand[2].mode)))
Richard Kenner committed
4440 4441 4442 4443 4444
    abort ();

  return (GEN_FCN (icode) (x, x, y));
}

4445 4446 4447
/* Generate and return an insn body to subtract r1 and c,
   storing the result in r0.  */
rtx
4448
gen_sub3_insn (rtx r0, rtx r1, rtx c)
4449 4450 4451
{
  int icode = (int) sub_optab->handlers[(int) GET_MODE (r0)].insn_code;

4452
  if (icode == CODE_FOR_nothing
4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463
      || ! ((*insn_data[icode].operand[0].predicate)
	    (r0, insn_data[icode].operand[0].mode))
      || ! ((*insn_data[icode].operand[1].predicate)
	    (r1, insn_data[icode].operand[1].mode))
      || ! ((*insn_data[icode].operand[2].predicate)
	    (c, insn_data[icode].operand[2].mode)))
    return NULL_RTX;

  return (GEN_FCN (icode) (r0, r1, c));
}

Richard Kenner committed
4464
int
4465
have_sub2_insn (rtx x, rtx y)
Richard Kenner committed
4466
{
4467 4468 4469 4470 4471
  int icode;

  if (GET_MODE (x) == VOIDmode)
    abort ();

4472
  icode = (int) sub_optab->handlers[(int) GET_MODE (x)].insn_code;
4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485

  if (icode == CODE_FOR_nothing)
    return 0;

  if (! ((*insn_data[icode].operand[0].predicate)
	 (x, insn_data[icode].operand[0].mode))
      || ! ((*insn_data[icode].operand[1].predicate)
	    (x, insn_data[icode].operand[1].mode))
      || ! ((*insn_data[icode].operand[2].predicate)
	    (y, insn_data[icode].operand[2].mode)))
    return 0;

  return 1;
Richard Kenner committed
4486 4487
}

4488
/* Generate the body of an instruction to copy Y into X.
4489
   It may be a list of insns, if one insn isn't enough.  */
Richard Kenner committed
4490 4491

rtx
4492
gen_move_insn (rtx x, rtx y)
Richard Kenner committed
4493
{
4494
  rtx seq;
Richard Kenner committed
4495

4496 4497
  start_sequence ();
  emit_move_insn_1 (x, y);
4498
  seq = get_insns ();
4499 4500
  end_sequence ();
  return seq;
Richard Kenner committed
4501 4502
}

4503 4504 4505
/* Return the insn code used to extend FROM_MODE to TO_MODE.
   UNSIGNEDP specifies zero-extension instead of sign-extension.  If
   no such operation exists, CODE_FOR_nothing will be returned.  */
Richard Kenner committed
4506

4507
enum insn_code
4508 4509
can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode,
	      int unsignedp)
Richard Kenner committed
4510
{
4511
  convert_optab tab;
4512 4513 4514 4515
#ifdef HAVE_ptr_extend
  if (unsignedp < 0)
    return CODE_FOR_ptr_extend;
#endif
4516 4517 4518

  tab = unsignedp ? zext_optab : sext_optab;
  return tab->handlers[to_mode][from_mode].insn_code;
Richard Kenner committed
4519 4520 4521 4522 4523 4524
}

/* Generate the body of an insn to extend Y (with mode MFROM)
   into X (with mode MTO).  Do zero-extension if UNSIGNEDP is nonzero.  */

rtx
4525 4526
gen_extend_insn (rtx x, rtx y, enum machine_mode mto,
		 enum machine_mode mfrom, int unsignedp)
Richard Kenner committed
4527
{
4528 4529
  enum insn_code icode = can_extend_p (mto, mfrom, unsignedp);
  return GEN_FCN (icode) (x, y);
Richard Kenner committed
4530 4531 4532 4533 4534 4535
}

/* can_fix_p and can_float_p say whether the target machine
   can directly convert a given fixed point type to
   a given floating point type, or vice versa.
   The returned value is the CODE_FOR_... value to use,
4536
   or CODE_FOR_nothing if these modes cannot be directly converted.
Richard Kenner committed
4537

4538
   *TRUNCP_PTR is set to 1 if it is necessary to output
Richard Kenner committed
4539 4540 4541
   an explicit FTRUNC insn before the fix insn; otherwise 0.  */

static enum insn_code
4542 4543
can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode,
	   int unsignedp, int *truncp_ptr)
Richard Kenner committed
4544
{
4545 4546 4547 4548 4549 4550 4551 4552 4553 4554
  convert_optab tab;
  enum insn_code icode;

  tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
  icode = tab->handlers[fixmode][fltmode].insn_code;
  if (icode != CODE_FOR_nothing)
    {
      *truncp_ptr = 0;
      return icode;
    }
Richard Kenner committed
4555

4556 4557 4558
  /* FIXME: This requires a port to define both FIX and FTRUNC pattern
     for this to work. We need to rework the fix* and ftrunc* patterns
     and documentation.  */
4559 4560 4561 4562
  tab = unsignedp ? ufix_optab : sfix_optab;
  icode = tab->handlers[fixmode][fltmode].insn_code;
  if (icode != CODE_FOR_nothing
      && ftrunc_optab->handlers[fltmode].insn_code != CODE_FOR_nothing)
Richard Kenner committed
4563 4564
    {
      *truncp_ptr = 1;
4565
      return icode;
Richard Kenner committed
4566
    }
4567 4568

  *truncp_ptr = 0;
Richard Kenner committed
4569 4570 4571 4572
  return CODE_FOR_nothing;
}

static enum insn_code
4573 4574
can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
	     int unsignedp)
Richard Kenner committed
4575
{
4576 4577 4578 4579
  convert_optab tab;

  tab = unsignedp ? ufloat_optab : sfloat_optab;
  return tab->handlers[fltmode][fixmode].insn_code;
Richard Kenner committed
4580 4581 4582
}

/* Generate code to convert FROM to floating point
4583
   and store in TO.  FROM must be fixed point and not VOIDmode.
Richard Kenner committed
4584 4585 4586 4587 4588
   UNSIGNEDP nonzero means regard FROM as unsigned.
   Normally this is done by correcting the final value
   if it is negative.  */

void
4589
expand_float (rtx to, rtx from, int unsignedp)
Richard Kenner committed
4590 4591
{
  enum insn_code icode;
4592
  rtx target = to;
Richard Kenner committed
4593 4594
  enum machine_mode fmode, imode;

4595 4596 4597 4598
  /* Crash now, because we won't be able to decide which mode to use.  */
  if (GET_MODE (from) == VOIDmode)
    abort ();

Richard Kenner committed
4599 4600 4601 4602 4603
  /* Look for an insn to do the conversion.  Do it in the specified
     modes if possible; otherwise convert either input, output or both to
     wider mode.  If the integer mode is wider than the mode of FROM,
     we can do the conversion signed even if the input is unsigned.  */

4604 4605 4606 4607
  for (fmode = GET_MODE (to); fmode != VOIDmode;
       fmode = GET_MODE_WIDER_MODE (fmode))
    for (imode = GET_MODE (from); imode != VOIDmode;
	 imode = GET_MODE_WIDER_MODE (imode))
Richard Kenner committed
4608 4609 4610
      {
	int doing_unsigned = unsignedp;

4611 4612 4613 4614
	if (fmode != GET_MODE (to)
	    && significand_size (fmode) < GET_MODE_BITSIZE (GET_MODE (from)))
	  continue;

Richard Kenner committed
4615 4616 4617 4618 4619 4620 4621
	icode = can_float_p (fmode, imode, unsignedp);
	if (icode == CODE_FOR_nothing && imode != GET_MODE (from) && unsignedp)
	  icode = can_float_p (fmode, imode, 0), doing_unsigned = 0;

	if (icode != CODE_FOR_nothing)
	  {
	    to = protect_from_queue (to, 1);
4622
	    from = protect_from_queue (from, 0);
Richard Kenner committed
4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636

	    if (imode != GET_MODE (from))
	      from = convert_to_mode (imode, from, unsignedp);

	    if (fmode != GET_MODE (to))
	      target = gen_reg_rtx (fmode);

	    emit_unop_insn (icode, target, from,
			    doing_unsigned ? UNSIGNED_FLOAT : FLOAT);

	    if (target != to)
	      convert_move (to, target, 0);
	    return;
	  }
4637
      }
Richard Kenner committed
4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654

  /* Unsigned integer, and no way to convert directly.
     Convert as signed, then conditionally adjust the result.  */
  if (unsignedp)
    {
      rtx label = gen_label_rtx ();
      rtx temp;
      REAL_VALUE_TYPE offset;

      emit_queue ();

      to = protect_from_queue (to, 1);
      from = protect_from_queue (from, 0);

      if (flag_force_mem)
	from = force_not_mem (from);

4655 4656 4657
      /* Look for a usable floating mode FMODE wider than the source and at
	 least as wide as the target.  Using FMODE will avoid rounding woes
	 with unsigned values greater than the signed maximum value.  */
4658

4659 4660 4661 4662 4663
      for (fmode = GET_MODE (to);  fmode != VOIDmode;
	   fmode = GET_MODE_WIDER_MODE (fmode))
	if (GET_MODE_BITSIZE (GET_MODE (from)) < GET_MODE_BITSIZE (fmode)
	    && can_float_p (fmode, GET_MODE (from), 0) != CODE_FOR_nothing)
	  break;
4664

4665 4666
      if (fmode == VOIDmode)
	{
4667
	  /* There is no such mode.  Pretend the target is wide enough.  */
4668
	  fmode = GET_MODE (to);
4669

Mike Stump committed
4670
	  /* Avoid double-rounding when TO is narrower than FROM.  */
4671 4672 4673 4674 4675 4676
	  if ((significand_size (fmode) + 1)
	      < GET_MODE_BITSIZE (GET_MODE (from)))
	    {
	      rtx temp1;
	      rtx neglabel = gen_label_rtx ();

4677
	      /* Don't use TARGET if it isn't a register, is a hard register,
4678
		 or is the wrong mode.  */
4679
	      if (GET_CODE (target) != REG
4680 4681
		  || REGNO (target) < FIRST_PSEUDO_REGISTER
		  || GET_MODE (target) != fmode)
4682 4683
		target = gen_reg_rtx (fmode);

4684 4685 4686 4687
	      imode = GET_MODE (from);
	      do_pending_stack_adjust ();

	      /* Test whether the sign bit is set.  */
4688
	      emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
4689
				       0, neglabel);
4690 4691 4692 4693

	      /* The sign bit is not set.  Convert as signed.  */
	      expand_float (target, from, 0);
	      emit_jump_insn (gen_jump (label));
4694
	      emit_barrier ();
4695 4696 4697 4698 4699 4700 4701 4702

	      /* The sign bit is set.
		 Convert to a usable (positive signed) value by shifting right
		 one bit, while remembering if a nonzero bit was shifted
		 out; i.e., compute  (from & 1) | (from >> 1).  */

	      emit_label (neglabel);
	      temp = expand_binop (imode, and_optab, from, const1_rtx,
4703
				   NULL_RTX, 1, OPTAB_LIB_WIDEN);
4704 4705
	      temp1 = expand_shift (RSHIFT_EXPR, imode, from, integer_one_node,
				    NULL_RTX, 1);
4706
	      temp = expand_binop (imode, ior_optab, temp, temp1, temp, 1,
4707
				   OPTAB_LIB_WIDEN);
4708 4709 4710
	      expand_float (target, temp, 0);

	      /* Multiply by 2 to undo the shift above.  */
4711
	      temp = expand_binop (fmode, add_optab, target, target,
4712
				   target, 0, OPTAB_LIB_WIDEN);
4713 4714 4715
	      if (temp != target)
		emit_move_insn (target, temp);

4716 4717 4718 4719
	      do_pending_stack_adjust ();
	      emit_label (label);
	      goto done;
	    }
4720 4721
	}

Richard Kenner committed
4722 4723 4724
      /* If we are about to do some arithmetic to correct for an
	 unsigned operand, do it in a pseudo-register.  */

4725
      if (GET_MODE (to) != fmode
4726
	  || GET_CODE (to) != REG || REGNO (to) < FIRST_PSEUDO_REGISTER)
4727
	target = gen_reg_rtx (fmode);
Richard Kenner committed
4728 4729 4730 4731 4732 4733 4734 4735

      /* Convert as signed integer to floating.  */
      expand_float (target, from, 0);

      /* If FROM is negative (and therefore TO is negative),
	 correct its value by 2**bitwidth.  */

      do_pending_stack_adjust ();
4736
      emit_cmp_and_jump_insns (from, const0_rtx, GE, NULL_RTX, GET_MODE (from),
4737
			       0, label);
4738

4739

4740
      real_2expN (&offset, GET_MODE_BITSIZE (GET_MODE (from)));
4741
      temp = expand_binop (fmode, add_optab, target,
4742
			   CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode),
Richard Kenner committed
4743 4744 4745
			   target, 0, OPTAB_LIB_WIDEN);
      if (temp != target)
	emit_move_insn (target, temp);
4746

Richard Kenner committed
4747 4748
      do_pending_stack_adjust ();
      emit_label (label);
4749
      goto done;
Richard Kenner committed
4750 4751
    }

4752
  /* No hardware instruction available; call a library routine.  */
Richard Kenner committed
4753
    {
4754
      rtx libfunc;
Richard Kenner committed
4755
      rtx insns;
4756
      rtx value;
4757
      convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
Richard Kenner committed
4758 4759

      to = protect_from_queue (to, 1);
4760
      from = protect_from_queue (from, 0);
Richard Kenner committed
4761 4762 4763 4764 4765 4766 4767

      if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
	from = convert_to_mode (SImode, from, unsignedp);

      if (flag_force_mem)
	from = force_not_mem (from);

4768 4769
      libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
      if (!libfunc)
Richard Kenner committed
4770 4771 4772 4773
	abort ();

      start_sequence ();

4774
      value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4775 4776
				       GET_MODE (to), 1, from,
				       GET_MODE (from));
Richard Kenner committed
4777 4778 4779
      insns = get_insns ();
      end_sequence ();

4780
      emit_libcall_block (insns, target, value,
4781
			  gen_rtx_FLOAT (GET_MODE (to), from));
Richard Kenner committed
4782 4783
    }

4784 4785
 done:

Richard Kenner committed
4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797
  /* Copy result to requested destination
     if we have been computing in a temp location.  */

  if (target != to)
    {
      if (GET_MODE (target) == GET_MODE (to))
	emit_move_insn (to, target);
      else
	convert_move (to, target, 0);
    }
}

4798 4799
/* Generate code to convert FROM to fixed point and store in TO.  FROM
   must be floating point.  */
Richard Kenner committed
4800 4801

void
4802
expand_fix (rtx to, rtx from, int unsignedp)
Richard Kenner committed
4803 4804
{
  enum insn_code icode;
4805
  rtx target = to;
Richard Kenner committed
4806 4807 4808 4809 4810 4811 4812 4813
  enum machine_mode fmode, imode;
  int must_trunc = 0;

  /* We first try to find a pair of modes, one real and one integer, at
     least as wide as FROM and TO, respectively, in which we can open-code
     this conversion.  If the integer mode is wider than the mode of TO,
     we can do the conversion either signed or unsigned.  */

4814 4815 4816 4817
  for (fmode = GET_MODE (from); fmode != VOIDmode;
       fmode = GET_MODE_WIDER_MODE (fmode))
    for (imode = GET_MODE (to); imode != VOIDmode;
	 imode = GET_MODE_WIDER_MODE (imode))
Richard Kenner committed
4818 4819 4820 4821 4822 4823 4824 4825 4826 4827
      {
	int doing_unsigned = unsignedp;

	icode = can_fix_p (imode, fmode, unsignedp, &must_trunc);
	if (icode == CODE_FOR_nothing && imode != GET_MODE (to) && unsignedp)
	  icode = can_fix_p (imode, fmode, 0, &must_trunc), doing_unsigned = 0;

	if (icode != CODE_FOR_nothing)
	  {
	    to = protect_from_queue (to, 1);
4828
	    from = protect_from_queue (from, 0);
Richard Kenner committed
4829 4830 4831 4832 4833

	    if (fmode != GET_MODE (from))
	      from = convert_to_mode (fmode, from, 0);

	    if (must_trunc)
4834 4835 4836 4837 4838
	      {
		rtx temp = gen_reg_rtx (GET_MODE (from));
		from = expand_unop (GET_MODE (from), ftrunc_optab, from,
				    temp, 0);
	      }
Richard Kenner committed
4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857

	    if (imode != GET_MODE (to))
	      target = gen_reg_rtx (imode);

	    emit_unop_insn (icode, target, from,
			    doing_unsigned ? UNSIGNED_FIX : FIX);
	    if (target != to)
	      convert_move (to, target, unsignedp);
	    return;
	  }
      }

  /* For an unsigned conversion, there is one more way to do it.
     If we have a signed conversion, we generate code that compares
     the real value to the largest representable positive number.  If if
     is smaller, the conversion is done normally.  Otherwise, subtract
     one plus the highest signed number, convert, and add it back.

     We only need to check all real modes, since we know we didn't find
4858
     anything with a wider integer mode.
4859 4860 4861 4862 4863 4864 4865 4866 4867 4868

     This code used to extend FP value into mode wider than the destination.
     This is not needed.  Consider, for instance conversion from SFmode
     into DImode.

     The hot path trought the code is dealing with inputs smaller than 2^63
     and doing just the conversion, so there is no bits to lose.

     In the other path we know the value is positive in the range 2^63..2^64-1
     inclusive.  (as for other imput overflow happens and result is undefined)
4869
     So we know that the most important bit set in mantissa corresponds to
4870 4871
     2^63.  The subtraction of 2^63 should not generate any rounding as it
     simply clears out that bit.  The rest is trivial.  */
Richard Kenner committed
4872

Charles Hannum committed
4873
  if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
Richard Kenner committed
4874 4875
    for (fmode = GET_MODE (from); fmode != VOIDmode;
	 fmode = GET_MODE_WIDER_MODE (fmode))
4876 4877
      if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
					 &must_trunc))
Richard Kenner committed
4878
	{
4879 4880 4881 4882 4883
	  int bitsize;
	  REAL_VALUE_TYPE offset;
	  rtx limit, lab1, lab2, insn;

	  bitsize = GET_MODE_BITSIZE (GET_MODE (to));
4884
	  real_2expN (&offset, bitsize - 1);
4885
	  limit = CONST_DOUBLE_FROM_REAL_VALUE (offset, fmode);
4886 4887
	  lab1 = gen_label_rtx ();
	  lab2 = gen_label_rtx ();
Richard Kenner committed
4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900

	  emit_queue ();
	  to = protect_from_queue (to, 1);
	  from = protect_from_queue (from, 0);

	  if (flag_force_mem)
	    from = force_not_mem (from);

	  if (fmode != GET_MODE (from))
	    from = convert_to_mode (fmode, from, 0);

	  /* See if we need to do the subtraction.  */
	  do_pending_stack_adjust ();
4901
	  emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
4902
				   0, lab1);
Richard Kenner committed
4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913

	  /* If not, do the signed "fix" and branch around fixup code.  */
	  expand_fix (to, from, 0);
	  emit_jump_insn (gen_jump (lab2));
	  emit_barrier ();

	  /* Otherwise, subtract 2**(N-1), convert to signed number,
	     then add 2**(N-1).  Do the addition using XOR since this
	     will often generate better code.  */
	  emit_label (lab1);
	  target = expand_binop (GET_MODE (from), sub_optab, from, limit,
Charles Hannum committed
4914
				 NULL_RTX, 0, OPTAB_LIB_WIDEN);
Richard Kenner committed
4915 4916
	  expand_fix (to, target, 0);
	  target = expand_binop (GET_MODE (to), xor_optab, to,
4917 4918 4919
				 gen_int_mode
				 ((HOST_WIDE_INT) 1 << (bitsize - 1),
				  GET_MODE (to)),
Richard Kenner committed
4920 4921 4922 4923 4924 4925 4926
				 to, 1, OPTAB_LIB_WIDEN);

	  if (target != to)
	    emit_move_insn (to, target);

	  emit_label (lab2);

4927 4928 4929 4930 4931
	  if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
	      != CODE_FOR_nothing)
	    {
	      /* Make a place for a REG_NOTE and add it.  */
	      insn = emit_move_insn (to, to);
4932 4933 4934 4935 4936
	      set_unique_reg_note (insn,
	                           REG_EQUAL,
				   gen_rtx_fmt_e (UNSIGNED_FIX,
						  GET_MODE (to),
						  copy_rtx (from)));
4937
	    }
Jeff Law committed
4938

Richard Kenner committed
4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954
	  return;
	}

  /* We can't do it with an insn, so use a library call.  But first ensure
     that the mode of TO is at least as wide as SImode, since those are the
     only library calls we know about.  */

  if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode))
    {
      target = gen_reg_rtx (SImode);

      expand_fix (target, from, unsignedp);
    }
  else
    {
      rtx insns;
4955
      rtx value;
4956 4957 4958 4959 4960 4961
      rtx libfunc;
      
      convert_optab tab = unsignedp ? ufix_optab : sfix_optab;
      libfunc = tab->handlers[GET_MODE (to)][GET_MODE (from)].libfunc;
      if (!libfunc)
	abort ();
Richard Kenner committed
4962 4963 4964 4965 4966 4967 4968 4969 4970

      to = protect_from_queue (to, 1);
      from = protect_from_queue (from, 0);

      if (flag_force_mem)
	from = force_not_mem (from);

      start_sequence ();

4971
      value = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
4972 4973
				       GET_MODE (to), 1, from,
				       GET_MODE (from));
Richard Kenner committed
4974 4975 4976
      insns = get_insns ();
      end_sequence ();

4977
      emit_libcall_block (insns, target, value,
4978 4979
			  gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
					 GET_MODE (to), from));
Richard Kenner committed
4980
    }
4981

4982 4983 4984 4985 4986 4987 4988
  if (target != to)
    {
      if (GET_MODE (to) == GET_MODE (target))
        emit_move_insn (to, target);
      else
        convert_move (to, target, 0);
    }
Richard Kenner committed
4989 4990
}

4991 4992 4993
/* Report whether we have an instruction to perform the operation
   specified by CODE on operands of mode MODE.  */
int
4994
have_insn_for (enum rtx_code code, enum machine_mode mode)
4995 4996 4997 4998 4999 5000 5001 5002
{
  return (code_to_optab[(int) code] != 0
	  && (code_to_optab[(int) code]->handlers[(int) mode].insn_code
	      != CODE_FOR_nothing));
}

/* Create a blank optab.  */
static optab
5003
new_optab (void)
Richard Kenner committed
5004 5005
{
  int i;
5006
  optab op = ggc_alloc (sizeof (struct optab));
Richard Kenner committed
5007 5008 5009 5010 5011
  for (i = 0; i < NUM_MACHINE_MODES; i++)
    {
      op->handlers[i].insn_code = CODE_FOR_nothing;
      op->handlers[i].libfunc = 0;
    }
5012

5013 5014
  return op;
}
5015

5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029
static convert_optab
new_convert_optab (void)
{
  int i, j;
  convert_optab op = ggc_alloc (sizeof (struct convert_optab));
  for (i = 0; i < NUM_MACHINE_MODES; i++)
    for (j = 0; j < NUM_MACHINE_MODES; j++)
      {
	op->handlers[i][j].insn_code = CODE_FOR_nothing;
	op->handlers[i][j].libfunc = 0;
      }
  return op;
}

5030 5031 5032
/* Same, but fill in its code as CODE, and write it into the
   code_to_optab table.  */
static inline optab
5033
init_optab (enum rtx_code code)
5034 5035 5036 5037 5038 5039 5040 5041 5042 5043
{
  optab op = new_optab ();
  op->code = code;
  code_to_optab[(int) code] = op;
  return op;
}

/* Same, but fill in its code as CODE, and do _not_ write it into
   the code_to_optab table.  */
static inline optab
5044
init_optabv (enum rtx_code code)
5045 5046 5047
{
  optab op = new_optab ();
  op->code = code;
Richard Kenner committed
5048 5049 5050
  return op;
}

5051 5052 5053 5054 5055 5056 5057 5058 5059
/* Conversion optabs never go in the code_to_optab table.  */
static inline convert_optab
init_convert_optab (enum rtx_code code)
{
  convert_optab op = new_convert_optab ();
  op->code = code;
  return op;
}

Jim Wilson committed
5060 5061 5062
/* Initialize the libfunc fields of an entire group of entries in some
   optab.  Each entry is set equal to a string consisting of a leading
   pair of underscores followed by a generic operation name followed by
5063
   a mode name (downshifted to lowercase) followed by a single character
Jim Wilson committed
5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077
   representing the number of operands for the given operation (which is
   usually one of the characters '2', '3', or '4').

   OPTABLE is the table in which libfunc fields are to be initialized.
   FIRST_MODE is the first machine mode index in the given optab to
     initialize.
   LAST_MODE is the last machine mode index in the given optab to
     initialize.
   OPNAME is the generic (string) name of the operation.
   SUFFIX is the character which specifies the number of operands for
     the given generic operation.
*/

static void
5078 5079
init_libfuncs (optab optable, int first_mode, int last_mode,
	       const char *opname, int suffix)
Jim Wilson committed
5080
{
5081 5082
  int mode;
  unsigned opname_len = strlen (opname);
Jim Wilson committed
5083

5084 5085
  for (mode = first_mode; (int) mode <= (int) last_mode;
       mode = (enum machine_mode) ((int) mode + 1))
Jim Wilson committed
5086
    {
5087
      const char *mname = GET_MODE_NAME (mode);
5088 5089 5090 5091
      unsigned mname_len = strlen (mname);
      char *libfunc_name = alloca (2 + opname_len + mname_len + 1 + 1);
      char *p;
      const char *q;
Jim Wilson committed
5092 5093 5094 5095 5096 5097 5098

      p = libfunc_name;
      *p++ = '_';
      *p++ = '_';
      for (q = opname; *q; )
	*p++ = *q++;
      for (q = mname; *q; q++)
5099
	*p++ = TOLOWER (*q);
Jim Wilson committed
5100
      *p++ = suffix;
Zack Weinberg committed
5101
      *p = '\0';
5102

Jim Wilson committed
5103
      optable->handlers[(int) mode].libfunc
5104
	= init_one_libfunc (ggc_alloc_string (libfunc_name, p - libfunc_name));
Jim Wilson committed
5105 5106 5107 5108 5109 5110 5111 5112 5113
    }
}

/* Initialize the libfunc fields of an entire group of entries in some
   optab which correspond to all integer mode operations.  The parameters
   have the same meaning as similarly named ones for the `init_libfuncs'
   routine.  (See above).  */

static void
5114
init_integral_libfuncs (optab optable, const char *opname, int suffix)
Jim Wilson committed
5115
{
5116 5117 5118
  int maxsize = 2*BITS_PER_WORD;
  if (maxsize < LONG_LONG_TYPE_SIZE)
    maxsize = LONG_LONG_TYPE_SIZE;
5119
  init_libfuncs (optable, word_mode,
5120
		 mode_for_size (maxsize, MODE_INT, 0),
5121
		 opname, suffix);
Jim Wilson committed
5122 5123 5124 5125 5126 5127 5128 5129
}

/* Initialize the libfunc fields of an entire group of entries in some
   optab which correspond to all real mode operations.  The parameters
   have the same meaning as similarly named ones for the `init_libfuncs'
   routine.  (See above).  */

static void
5130
init_floating_libfuncs (optab optable, const char *opname, int suffix)
Jim Wilson committed
5131
{
5132
  init_libfuncs (optable, MIN_MODE_FLOAT, MAX_MODE_FLOAT, opname, suffix);
Jim Wilson committed
5133 5134
}

5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239
/* Initialize the libfunc fields of an entire group of entries of an
   inter-mode-class conversion optab.  The string formation rules are
   similar to the ones for init_libfuncs, above, but instead of having
   a mode name and an operand count these functions have two mode names
   and no operand count.  */
static void
init_interclass_conv_libfuncs (convert_optab tab, const char *opname,
			       enum mode_class from_class,
			       enum mode_class to_class)
{
  enum machine_mode first_from_mode = GET_CLASS_NARROWEST_MODE (from_class);
  enum machine_mode first_to_mode = GET_CLASS_NARROWEST_MODE (to_class);
  size_t opname_len = strlen (opname);
  size_t max_mname_len = 0;

  enum machine_mode fmode, tmode;
  const char *fname, *tname;
  const char *q;
  char *libfunc_name, *suffix;
  char *p;

  for (fmode = first_from_mode;
       fmode != VOIDmode;
       fmode = GET_MODE_WIDER_MODE (fmode))
    max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (fmode)));

  for (tmode = first_to_mode;
       tmode != VOIDmode;
       tmode = GET_MODE_WIDER_MODE (tmode))
    max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (tmode)));

  libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1);
  libfunc_name[0] = '_';
  libfunc_name[1] = '_';
  memcpy (&libfunc_name[2], opname, opname_len);
  suffix = libfunc_name + opname_len + 2;

  for (fmode = first_from_mode; fmode != VOIDmode;
       fmode = GET_MODE_WIDER_MODE (fmode))
    for (tmode = first_to_mode; tmode != VOIDmode;
	 tmode = GET_MODE_WIDER_MODE (tmode))
      {
	fname = GET_MODE_NAME (fmode);
	tname = GET_MODE_NAME (tmode);

	p = suffix;
	for (q = fname; *q; p++, q++)
	  *p = TOLOWER (*q);
	for (q = tname; *q; p++, q++)
	  *p = TOLOWER (*q);

	*p = '\0';

	tab->handlers[tmode][fmode].libfunc
	  = init_one_libfunc (ggc_alloc_string (libfunc_name,
						p - libfunc_name));
      }
}

/* Initialize the libfunc fields of an entire group of entries of an
   intra-mode-class conversion optab.  The string formation rules are
   similar to the ones for init_libfunc, above.  WIDENING says whether
   the optab goes from narrow to wide modes or vice versa.  These functions
   have two mode names _and_ an operand count.  */
static void
init_intraclass_conv_libfuncs (convert_optab tab, const char *opname,
			       enum mode_class class, bool widening)
{
  enum machine_mode first_mode = GET_CLASS_NARROWEST_MODE (class);
  size_t opname_len = strlen (opname);
  size_t max_mname_len = 0;

  enum machine_mode nmode, wmode;
  const char *nname, *wname;
  const char *q;
  char *libfunc_name, *suffix;
  char *p;

  for (nmode = first_mode; nmode != VOIDmode;
       nmode = GET_MODE_WIDER_MODE (nmode))
    max_mname_len = MAX (max_mname_len, strlen (GET_MODE_NAME (nmode)));

  libfunc_name = alloca (2 + opname_len + 2*max_mname_len + 1 + 1);
  libfunc_name[0] = '_';
  libfunc_name[1] = '_';
  memcpy (&libfunc_name[2], opname, opname_len);
  suffix = libfunc_name + opname_len + 2;

  for (nmode = first_mode; nmode != VOIDmode;
       nmode = GET_MODE_WIDER_MODE (nmode))
    for (wmode = GET_MODE_WIDER_MODE (nmode); wmode != VOIDmode;
	 wmode = GET_MODE_WIDER_MODE (wmode))
      {
	nname = GET_MODE_NAME (nmode);
	wname = GET_MODE_NAME (wmode);

	p = suffix;
	for (q = widening ? nname : wname; *q; p++, q++)
	  *p = TOLOWER (*q);
	for (q = widening ? wname : nname; *q; p++, q++)
	  *p = TOLOWER (*q);

	*p++ = '2';
	*p = '\0';

5240 5241
	tab->handlers[widening ? wmode : nmode]
	             [widening ? nmode : wmode].libfunc
5242 5243 5244 5245 5246 5247
	  = init_one_libfunc (ggc_alloc_string (libfunc_name,
						p - libfunc_name));
      }
}


5248
rtx
5249
init_one_libfunc (const char *name)
5250
{
5251 5252
  rtx symbol;

5253 5254
  /* Create a FUNCTION_DECL that can be passed to
     targetm.encode_section_info.  */
5255
  /* ??? We don't have any type information except for this is
5256
     a function.  Pretend this is "int foo()".  */
5257
  tree decl = build_decl (FUNCTION_DECL, get_identifier (name),
5258
			  build_function_type (integer_type_node, NULL_TREE));
5259 5260 5261 5262
  DECL_ARTIFICIAL (decl) = 1;
  DECL_EXTERNAL (decl) = 1;
  TREE_PUBLIC (decl) = 1;

5263 5264 5265 5266 5267 5268 5269
  symbol = XEXP (DECL_RTL (decl), 0);

  /* Zap the nonsensical SYMBOL_REF_DECL for this.  What we're left with
     are the flags assigned by targetm.encode_section_info.  */
  SYMBOL_REF_DECL (symbol) = 0;

  return symbol;
5270 5271
}

5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282
/* Call this to reset the function entry for one optab (OPTABLE) in mode
   MODE to NAME, which should be either 0 or a string constant.  */
void
set_optab_libfunc (optab optable, enum machine_mode mode, const char *name)
{
  if (name)
    optable->handlers[mode].libfunc = init_one_libfunc (name);
  else
    optable->handlers[mode].libfunc = 0;
}

5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295
/* Call this to reset the function entry for one conversion optab
   (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
   either 0 or a string constant.  */
void
set_conv_libfunc (convert_optab optable, enum machine_mode tmode,
		  enum machine_mode fmode, const char *name)
{
  if (name)
    optable->handlers[tmode][fmode].libfunc = init_one_libfunc (name);
  else
    optable->handlers[tmode][fmode].libfunc = 0;
}

Richard Kenner committed
5296 5297 5298 5299
/* Call this once to initialize the contents of the optabs
   appropriately for the current target machine.  */

void
5300
init_optabs (void)
Richard Kenner committed
5301
{
5302
  unsigned int i;
Richard Kenner committed
5303

5304
  /* Start by initializing all tables to contain CODE_FOR_nothing.  */
Richard Kenner committed
5305

5306 5307 5308
  for (i = 0; i < NUM_RTX_CODE; i++)
    setcc_gen_code[i] = CODE_FOR_nothing;

5309 5310 5311 5312 5313
#ifdef HAVE_conditional_move
  for (i = 0; i < NUM_MACHINE_MODES; i++)
    movcc_gen_code[i] = CODE_FOR_nothing;
#endif

5314
  add_optab = init_optab (PLUS);
5315
  addv_optab = init_optabv (PLUS);
5316
  sub_optab = init_optab (MINUS);
5317
  subv_optab = init_optabv (MINUS);
5318
  smul_optab = init_optab (MULT);
5319
  smulv_optab = init_optabv (MULT);
5320 5321
  smul_highpart_optab = init_optab (UNKNOWN);
  umul_highpart_optab = init_optab (UNKNOWN);
5322 5323 5324
  smul_widen_optab = init_optab (UNKNOWN);
  umul_widen_optab = init_optab (UNKNOWN);
  sdiv_optab = init_optab (DIV);
5325
  sdivv_optab = init_optabv (DIV);
5326 5327 5328 5329 5330
  sdivmod_optab = init_optab (UNKNOWN);
  udiv_optab = init_optab (UDIV);
  udivmod_optab = init_optab (UNKNOWN);
  smod_optab = init_optab (MOD);
  umod_optab = init_optab (UMOD);
Richard Kenner committed
5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343
  ftrunc_optab = init_optab (UNKNOWN);
  and_optab = init_optab (AND);
  ior_optab = init_optab (IOR);
  xor_optab = init_optab (XOR);
  ashl_optab = init_optab (ASHIFT);
  ashr_optab = init_optab (ASHIFTRT);
  lshr_optab = init_optab (LSHIFTRT);
  rotl_optab = init_optab (ROTATE);
  rotr_optab = init_optab (ROTATERT);
  smin_optab = init_optab (SMIN);
  smax_optab = init_optab (SMAX);
  umin_optab = init_optab (UMIN);
  umax_optab = init_optab (UMAX);
5344 5345
  pow_optab = init_optab (UNKNOWN);
  atan2_optab = init_optab (UNKNOWN);
5346 5347 5348 5349 5350 5351 5352

  /* These three have codes assigned exclusively for the sake of
     have_insn_for.  */
  mov_optab = init_optab (SET);
  movstrict_optab = init_optab (STRICT_LOW_PART);
  cmp_optab = init_optab (COMPARE);

Richard Kenner committed
5353 5354
  ucmp_optab = init_optab (UNKNOWN);
  tst_optab = init_optab (UNKNOWN);
Zack Weinberg committed
5355 5356 5357 5358 5359 5360 5361 5362 5363

  eq_optab = init_optab (EQ);
  ne_optab = init_optab (NE);
  gt_optab = init_optab (GT);
  ge_optab = init_optab (GE);
  lt_optab = init_optab (LT);
  le_optab = init_optab (LE);
  unord_optab = init_optab (UNORDERED);

Richard Kenner committed
5364
  neg_optab = init_optab (NEG);
5365
  negv_optab = init_optabv (NEG);
Richard Kenner committed
5366
  abs_optab = init_optab (ABS);
5367
  absv_optab = init_optabv (ABS);
5368
  addcc_optab = init_optab (UNKNOWN);
Richard Kenner committed
5369 5370
  one_cmpl_optab = init_optab (NOT);
  ffs_optab = init_optab (FFS);
Richard Henderson committed
5371 5372 5373 5374
  clz_optab = init_optab (CLZ);
  ctz_optab = init_optab (CTZ);
  popcount_optab = init_optab (POPCOUNT);
  parity_optab = init_optab (PARITY);
5375
  sqrt_optab = init_optab (SQRT);
5376 5377 5378
  floor_optab = init_optab (UNKNOWN);
  ceil_optab = init_optab (UNKNOWN);
  round_optab = init_optab (UNKNOWN);
5379
  btrunc_optab = init_optab (UNKNOWN);
5380
  nearbyint_optab = init_optab (UNKNOWN);
5381
  sincos_optab = init_optab (UNKNOWN);
5382 5383
  sin_optab = init_optab (UNKNOWN);
  cos_optab = init_optab (UNKNOWN);
5384
  exp_optab = init_optab (UNKNOWN);
5385 5386
  exp10_optab = init_optab (UNKNOWN);
  exp2_optab = init_optab (UNKNOWN);
5387 5388
  logb_optab = init_optab (UNKNOWN);
  ilogb_optab = init_optab (UNKNOWN);
5389
  log_optab = init_optab (UNKNOWN);
5390 5391
  log10_optab = init_optab (UNKNOWN);
  log2_optab = init_optab (UNKNOWN);
5392 5393
  tan_optab = init_optab (UNKNOWN);
  atan_optab = init_optab (UNKNOWN);
5394
  strlen_optab = init_optab (UNKNOWN);
5395 5396 5397
  cbranch_optab = init_optab (UNKNOWN);
  cmov_optab = init_optab (UNKNOWN);
  cstore_optab = init_optab (UNKNOWN);
5398
  push_optab = init_optab (UNKNOWN);
Richard Kenner committed
5399

5400 5401 5402
  vec_extract_optab = init_optab (UNKNOWN);
  vec_set_optab = init_optab (UNKNOWN);
  vec_init_optab = init_optab (UNKNOWN);
5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413
  /* Conversions.  */
  sext_optab = init_convert_optab (SIGN_EXTEND);
  zext_optab = init_convert_optab (ZERO_EXTEND);
  trunc_optab = init_convert_optab (TRUNCATE);
  sfix_optab = init_convert_optab (FIX);
  ufix_optab = init_convert_optab (UNSIGNED_FIX);
  sfixtrunc_optab = init_convert_optab (UNKNOWN);
  ufixtrunc_optab = init_convert_optab (UNKNOWN);
  sfloat_optab = init_convert_optab (FLOAT);
  ufloat_optab = init_convert_optab (UNSIGNED_FLOAT);

5414 5415 5416
  for (i = 0; i < NUM_MACHINE_MODES; i++)
    {
      movstr_optab[i] = CODE_FOR_nothing;
5417
      clrstr_optab[i] = CODE_FOR_nothing;
5418 5419
      cmpstr_optab[i] = CODE_FOR_nothing;
      cmpmem_optab[i] = CODE_FOR_nothing;
5420 5421 5422

#ifdef HAVE_SECONDARY_RELOADS
      reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
Richard Kenner committed
5423
#endif
5424 5425 5426 5427 5428 5429
    }

  /* Fill in the optabs with the insns we support.  */
  init_all_optabs ();

  /* Initialize the optabs with the names of the library functions.  */
Jim Wilson committed
5430 5431
  init_integral_libfuncs (add_optab, "add", '3');
  init_floating_libfuncs (add_optab, "add", '3');
5432 5433
  init_integral_libfuncs (addv_optab, "addv", '3');
  init_floating_libfuncs (addv_optab, "add", '3');
Jim Wilson committed
5434 5435
  init_integral_libfuncs (sub_optab, "sub", '3');
  init_floating_libfuncs (sub_optab, "sub", '3');
5436 5437
  init_integral_libfuncs (subv_optab, "subv", '3');
  init_floating_libfuncs (subv_optab, "sub", '3');
Jim Wilson committed
5438 5439
  init_integral_libfuncs (smul_optab, "mul", '3');
  init_floating_libfuncs (smul_optab, "mul", '3');
5440 5441
  init_integral_libfuncs (smulv_optab, "mulv", '3');
  init_floating_libfuncs (smulv_optab, "mul", '3');
5442
  init_integral_libfuncs (sdiv_optab, "div", '3');
5443
  init_floating_libfuncs (sdiv_optab, "div", '3');
5444
  init_integral_libfuncs (sdivv_optab, "divv", '3');
5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464
  init_integral_libfuncs (udiv_optab, "udiv", '3');
  init_integral_libfuncs (sdivmod_optab, "divmod", '4');
  init_integral_libfuncs (udivmod_optab, "udivmod", '4');
  init_integral_libfuncs (smod_optab, "mod", '3');
  init_integral_libfuncs (umod_optab, "umod", '3');
  init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
  init_integral_libfuncs (and_optab, "and", '3');
  init_integral_libfuncs (ior_optab, "ior", '3');
  init_integral_libfuncs (xor_optab, "xor", '3');
  init_integral_libfuncs (ashl_optab, "ashl", '3');
  init_integral_libfuncs (ashr_optab, "ashr", '3');
  init_integral_libfuncs (lshr_optab, "lshr", '3');
  init_integral_libfuncs (smin_optab, "min", '3');
  init_floating_libfuncs (smin_optab, "min", '3');
  init_integral_libfuncs (smax_optab, "max", '3');
  init_floating_libfuncs (smax_optab, "max", '3');
  init_integral_libfuncs (umin_optab, "umin", '3');
  init_integral_libfuncs (umax_optab, "umax", '3');
  init_integral_libfuncs (neg_optab, "neg", '2');
  init_floating_libfuncs (neg_optab, "neg", '2');
5465 5466
  init_integral_libfuncs (negv_optab, "negv", '2');
  init_floating_libfuncs (negv_optab, "neg", '2');
5467 5468
  init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
  init_integral_libfuncs (ffs_optab, "ffs", '2');
Richard Henderson committed
5469 5470 5471 5472
  init_integral_libfuncs (clz_optab, "clz", '2');
  init_integral_libfuncs (ctz_optab, "ctz", '2');
  init_integral_libfuncs (popcount_optab, "popcount", '2');
  init_integral_libfuncs (parity_optab, "parity", '2');
5473 5474 5475 5476 5477

  /* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */
  init_integral_libfuncs (cmp_optab, "cmp", '2');
  init_integral_libfuncs (ucmp_optab, "ucmp", '2');
  init_floating_libfuncs (cmp_optab, "cmp", '2');
Richard Kenner committed
5478

Zack Weinberg committed
5479 5480 5481 5482 5483 5484 5485 5486 5487
  /* EQ etc are floating point only.  */
  init_floating_libfuncs (eq_optab, "eq", '2');
  init_floating_libfuncs (ne_optab, "ne", '2');
  init_floating_libfuncs (gt_optab, "gt", '2');
  init_floating_libfuncs (ge_optab, "ge", '2');
  init_floating_libfuncs (lt_optab, "lt", '2');
  init_floating_libfuncs (le_optab, "le", '2');
  init_floating_libfuncs (unord_optab, "unord", '2');

5488 5489 5490 5491
  /* Conversions.  */
  init_interclass_conv_libfuncs (sfloat_optab, "float", MODE_INT, MODE_FLOAT);
  init_interclass_conv_libfuncs (sfix_optab, "fix",     MODE_FLOAT, MODE_INT);
  init_interclass_conv_libfuncs (ufix_optab, "fixuns",  MODE_FLOAT, MODE_INT);
Richard Kenner committed
5492

5493 5494 5495
  /* sext_optab is also used for FLOAT_EXTEND.  */
  init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true);
  init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, false);
5496

5497 5498 5499 5500 5501
  /* Use cabs for double complex abs, since systems generally have cabs.
     Don't define any libcall for float complex, so that cabs will be used.  */
  if (complex_double_type_node)
    abs_optab->handlers[TYPE_MODE (complex_double_type_node)].libfunc
      = init_one_libfunc ("cabs");
5502

5503
  /* The ffs function operates on `int'.  */
5504 5505
  ffs_optab->handlers[(int) mode_for_size (INT_TYPE_SIZE, MODE_INT, 0)].libfunc
    = init_one_libfunc ("ffs");
5506

5507
  abort_libfunc = init_one_libfunc ("abort");
5508
  memcpy_libfunc = init_one_libfunc ("memcpy");
5509
  memmove_libfunc = init_one_libfunc ("memmove");
5510 5511 5512 5513 5514
  bcopy_libfunc = init_one_libfunc ("bcopy");
  memcmp_libfunc = init_one_libfunc ("memcmp");
  bcmp_libfunc = init_one_libfunc ("__gcc_bcmp");
  memset_libfunc = init_one_libfunc ("memset");
  bzero_libfunc = init_one_libfunc ("bzero");
5515
  setbits_libfunc = init_one_libfunc ("__setbits");
5516

5517 5518 5519
  unwind_resume_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
					    ? "_Unwind_SjLj_Resume"
					    : "_Unwind_Resume");
5520
#ifndef DONT_USE_BUILTIN_SETJMP
5521 5522
  setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
  longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
5523
#else
5524 5525
  setjmp_libfunc = init_one_libfunc ("setjmp");
  longjmp_libfunc = init_one_libfunc ("longjmp");
5526
#endif
5527 5528 5529
  unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
  unwind_sjlj_unregister_libfunc
    = init_one_libfunc ("_Unwind_SjLj_Unregister");
Mike Stump committed
5530

5531 5532
  /* For function entry/exit instrumentation.  */
  profile_function_entry_libfunc
5533
    = init_one_libfunc ("__cyg_profile_func_enter");
5534
  profile_function_exit_libfunc
5535
    = init_one_libfunc ("__cyg_profile_func_exit");
5536

5537 5538 5539
  gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
  gcov_init_libfunc = init_one_libfunc ("__gcov_init");

5540 5541
  if (HAVE_conditional_trap)
    trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
5542

5543
  /* Allow the target to add more libcalls or rename some, etc.  */
5544
  targetm.init_libfuncs ();
Richard Kenner committed
5545
}
5546

5547 5548 5549 5550
/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
   CODE.  Return 0 on failure.  */

rtx
5551 5552
gen_cond_trap (enum rtx_code code ATTRIBUTE_UNUSED, rtx op1,
	       rtx op2 ATTRIBUTE_UNUSED, rtx tcode ATTRIBUTE_UNUSED)
5553 5554
{
  enum machine_mode mode = GET_MODE (op1);
5555 5556 5557 5558 5559
  enum insn_code icode;
  rtx insn;

  if (!HAVE_conditional_trap)
    return 0;
5560 5561 5562 5563

  if (mode == VOIDmode)
    return 0;

5564 5565 5566 5567 5568 5569
  icode = cmp_optab->handlers[(int) mode].insn_code;
  if (icode == CODE_FOR_nothing)
    return 0;

  start_sequence ();
  op1 = prepare_operand (icode, op1, 0, mode, mode, 0);
5570
  op2 = prepare_operand (icode, op2, 1, mode, mode, 0);
5571 5572 5573 5574 5575
  if (!op1 || !op2)
    {
      end_sequence ();
      return 0;
    }
5576 5577 5578 5579 5580
  emit_insn (GEN_FCN (icode) (op1, op2));

  PUT_CODE (trap_rtx, code);
  insn = gen_conditional_trap (trap_rtx, tcode);
  if (insn)
5581
    {
5582 5583
      emit_insn (insn);
      insn = get_insns ();
5584
    }
5585
  end_sequence ();
5586

5587
  return insn;
5588
}
5589 5590

#include "gt-optabs.h"