home *** CD-ROM | disk | FTP | other *** search
- /* Superoptimizer. Finds the shortest instruction sequences for an
- arbitrary function f(x,y) where x and y are integers. The algorithm is
- based on exhaustive search with backtracking and iterative deepening.
-
- Copyright (C) 1991, 1992 Free Software Foundation, Inc.
-
- This program 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.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include <stdio.h>
-
- #include "superopt.h"
- #include "run_program.def"
- #include "version.h"
-
- int goal_function_arity;
- enum goal_func goal_function;
- word (*eval_goal_function) (const word *);
-
- int flag_output_assembler = 0;
- int flag_use_carry = 1;
-
- /* Counts the number of solutions found. Flags to top loop that it should
- not go deeper. */
- int success;
-
- #ifdef TIMING
- #ifndef USG
- #include <sys/time.h>
- #include <sys/resource.h>
-
- unsigned long
- cputime ()
- {
- struct rusage rus;
-
- getrusage (0, &rus);
- return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
- }
- #else
- #include <time.h>
-
- unsigned long
- cputime ()
- {
- return clock () / 1000;
- }
- #endif
- int timings[100];
- #endif
-
- #ifdef STATISTICS
- unsigned int heuristic_reject_count = 0;
- unsigned int heuristic_accept_count = 0;
- #endif
-
- char *insn_name[] =
- {
- #undef DEF_INSN
- #define DEF_INSN(SYM,CLASS,NAME) NAME,
- #include "insn.def"
- };
-
- char insn_class[] =
- {
- #undef DEF_INSN
- #define DEF_INSN(SYM,CLASS,NAME) CLASS,
- #include "insn.def"
- };
-
- /* Initialize the "immediate" values in the top registers. */
- void
- init_immediates(word *values)
- {
- int i;
- for (i = -1; i < BITS_PER_WORD; i++)
- values[0x20 + i] = i;
-
- values[0x20 - 2] = VALUE_MIN_SIGNED;
- values[0x20 - 3] = VALUE_MAX_SIGNED;
- }
-
- inline word
- random_word(void)
- {
- #ifdef __hpux
- return mrand48();
- #else
- /* random returns 31 bits. We need 32. */
- return random() ^ (random() << 1);
- #endif
- }
-
- char *
- xrealloc (ptr, size)
- char *ptr;
- unsigned size;
- {
- char *result = (char *) realloc (ptr, size);
- if (!result)
- abort ();
- return result;
- }
-
- char *
- xmalloc (size)
- unsigned size;
- {
- register char *val = (char *) malloc (size);
-
- if (val == 0)
- abort ();
- return val;
- }
-
- #define RECURSE(opcode, s1, s2, prune_hint) \
- recurse(opcode, n_values, s1, s2, v, 1, sequence, n_insns, values, \
- n_values + 1, goal_value, allowed_cost, co, prune_hint)
- #define CRECURSE_2OP(opcode, d, s1, s2, cost, prune_hint) \
- recurse(opcode, d, s1, s2, v, cost, sequence, n_insns, values, \
- n_values, goal_value, allowed_cost, co, prune_hint)
- #define CRECURSE_NEW(opcode, d, s1, s2, cost, prune_hint) \
- recurse(opcode, d, s1, s2, v, cost, sequence, n_insns, values, \
- n_values + 1, goal_value, allowed_cost, co, prune_hint)
-
- /* Save the last generated instruction and recursively call `synth', if we
- are not at a leaf node. Otherwise test the computed value and
- back-track. This function is extremely critical for the performance!
-
- OPCODE is the opcode of the insn that was just generated.
-
- D is the destination register.
-
- S1 is the left source register or immediate reference. It is an
- immediate reference if IMMEDIATE_P(S1) is true.
-
- S2 is the right source register or immediate reference. It is an
- immediate reference if IMMEDIATE_P(S2) is true.
-
- V is the computed result from "rD = rS1 OPCODE rS2".
-
- COST is the cost of OPCODE with the the actual operands.
-
- SEQUENCE is the insn sequence so far, excluding the just generated insn.
-
- N_INSNS is the number of insns in SEQUENCE.
-
- VALUES contains the values in register 0..N_VALUES.
-
- N_VALUES is the number of registers that have been assigned values by
- the insns so far.
-
- GOAL_VALUE is the value we aim at, when the sequence is ready.
-
- ALLOWED_COST is the maximum allowed cost of the remaining sequence.
-
- CY is the carry flag. It is negative if it has an undefined value (this
- for pruning the search tree), and otherwise takes the values 0 or 1
- according to the conventions of the current target.
-
- PRUNE_HINT contains flags to assist pruning of the search tree. */
-
- static inline void
- recurse(opcode_t opcode,
- int d,
- int s1,
- int s2,
- word v,
- int cost,
- insn_t *sequence,
- int n_insns,
- word *values,
- int n_values,
- const word goal_value,
- int allowed_cost,
- int cy,
- int prune_flags)
- {
- insn_t insn;
-
- /* Update the remaining allowed cost with the cost of the last
- instruction. */
- allowed_cost -= cost;
-
- if (allowed_cost > 0)
- {
- /* ALLOWED_COST is still positive, meaning we can generate more
- instructions. */
- word old_d;
-
- old_d = values[d]; /* Remember old value of dest. reg. */
- values[d] = v;
-
- #if __GNUC__
- sequence[n_insns] = (insn_t) {opcode, s1, s2, d};
- #else
- insn.opcode = opcode;
- insn.s1 = s1;
- insn.s2 = s2;
- insn.d = d;
- sequence[n_insns] = insn;
- #endif
-
- synth(sequence, n_insns + 1, values, n_values,
- goal_value, allowed_cost, cy, prune_flags);
-
- values[d] = old_d; /* Restore value of dest. reg. */
- }
- else if (goal_value == v)
- {
- /* We are at a leaf node and got the right answer for the
- random value operands. However, we probably have an
- incorrect sequence. Call test_sequence to find out. */
-
- #if __GNUC__
- sequence[n_insns] = (insn_t) {opcode, s1, s2, d};
- #else
- insn.opcode = opcode;
- insn.s1 = s1;
- insn.s2 = s2;
- insn.d = d;
- sequence[n_insns] = insn;
- #endif
- test_sequence(sequence, n_insns + 1);
-
- #ifdef STATISTICS
- heuristic_accept_count++;
- #endif
-
- }
- #ifdef STATISTICS
- else
- heuristic_reject_count++;
- #endif
- }
-
- #define NAME(op) operand_names[op]
- static char *operand_names[256]=
- {
- #if SPARC
- "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i6", "%i7",
- #elif RS6000
- "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
- #elif M88000
- "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
- #elif AM29K
- "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", "lr8", "lr9",
- #elif M68000
- "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
- #elif I386
- "%eax", "%edx", "%ecx", "%ebx", "%esi", "%edi", "%noooo!", "%crash!!!",
- #elif PYR
- "pr0", "pr1", "pr2", "pr3", "pr4", "pr5", "pr6", "pr7",
- #elif ALPHA
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- #else
- #error no register names for this CPU
- #endif
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- #if SPARC
- "???%hi(0x7fffffff)","%hi(0x80000000)","-1","%g0","1","2","3","4","5","6",
- "7","8","9","10","11","12","13","14","15","16","17","18","19",
- "20","21","22","23","24","25","26","27","28","29","30","31",
- #elif RS6000
- "0x7fff","0x8000","-1","0","1","2","3","4","5","6",
- "7","8","9","10","11","12","13","14","15","16","17","18","19",
- "20","21","22","23","24","25","26","27","28","29","30","31",
- #elif M88000
- "hi16(0x7fffffff)","hi16(0x80000000)","-1","r0","1","2","3","4","5","6",
- "7","8","9","10","11","12","13","14","15","16","17","18","19",
- "20","21","22","23","24","25","26","27","28","29","30","31",
- #elif AM29K
- "0x7fff","0x8000","-1","0","1","2","3","4","5","6",
- "7","8","9","10","11","12","13","14","15","16","17","18","19",
- "20","21","22","23","24","25","26","27","28","29","30","31",
- #elif M68000
- "#0x7fffffff","#0x80000000","#-1","#0","#1","#2","#3","#4","#5","#6",
- "#7","#8","#9","#10","#11","#12","#13","#14","#15","#16","#17","#18","#19",
- "#20","#21","#22","#23","#24","#25","#26","#27","#28","#29","#30","#31",
- #elif I386
- "$0x7fffffff","$0x80000000","$-1","$0","$1","$2","$3","$4","$5","$6",
- "$7","$8","$9","$10","$11","$12","$13","$14","$15","$16","$17","$18","$19",
- "$20","$21","$22","$23","$24","$25","$26","$27","$28","$29","$30","$31",
- #elif PYR
- "$0x7fffffff","$0x80000000","$-1","$0","$1","$2","$3","$4","$5","$6",
- "$7","$8","$9","$10","$11","$12","$13","$14","$15","$16","$17","$18","$19",
- "$20","$21","$22","$23","$24","$25","$26","$27","$28","$29","$30","$31",
- #elif ALPHA
- "0x7fff","0x8000","-1","$31","1","2","3","4","5","6",
- "7","8","9","10","11","12","13","14","15","16","17","18","19",
- "20","21","22","23","24","25","26","27","28","29","30","31",
- "32","33","34","35","36","37","38","39","40","41","42","43",
- "44","45","46","47","48","49","50","51","52","53","54","55",
- "56","57","58","59","60","61","62","63",
- #else
- #error no constant syntax for this CPU
- #endif
- };
-
- /* Output INSN in assembler mnemonic format on stdout. */
-
- void
- output_assembler(insn_t insn)
- {
- int d, s1, s2;
-
- d = insn.d;
- s1 = insn.s1;
- s2 = insn.s2;
-
- printf("\t");
- switch (insn.opcode)
- {
- #if SPARC
- case COPY:
- if (IMMEDIATE_P(s1) && (IMMEDIATE_VAL(s1) & 0x1fff) == 0)
- printf("sethi %s,%s",NAME(s1),NAME(d));
- else
- printf("mov %s,%s",NAME(s1),NAME(d));
- break;
- case ADD: printf("add %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case ADD_CI:printf("addx %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case ADD_CO:printf("addcc %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case ADD_CIO:printf("addxcc %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case SUB:
- if (IMMEDIATE_P(s1) && IMMEDIATE_VAL(s1) == -1)
- printf("xnor %%g0,%s,%s",NAME(s2),NAME(d));
- else
- printf("sub %s,%s,%s",NAME(s1),NAME(s2),NAME(d));
- break;
- case SUB_CI:printf("subx %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case SUB_CO:printf("subcc %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case SUB_CIO:printf("subxcc %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case AND: printf("and %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case IOR: printf("or %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case XOR: printf("xor %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case ANDC: printf("andn %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case IORC: printf("orn %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case EQV: printf("xnor %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case LSHIFTR:printf("srl %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case ASHIFTR:printf("sra %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case SHIFTL:printf("sll %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- #elif RS6000
- case COPY:
- if (IMMEDIATE_P(s1))
- {
- if (IMMEDIATE_VAL(s1) >= 0 && IMMEDIATE_VAL(s1) < 0x8000)
- printf("lil %s,0x%x",NAME(d),IMMEDIATE_VAL(s1));
- else
- printf("liu %s,%s",NAME(d),NAME(s1));
- }
- else
- printf("oril %s,%s,0",NAME(d),NAME(s1));
- break;
- case ADD:
- if (IMMEDIATE_P(s2))
- {
- if (IMMEDIATE_VAL(s2) + 0x4000 < 0x8000)
- printf("cal %s,%d(%s)",NAME(d),IMMEDIATE_VAL(s2),NAME(s1));
- else if ((IMMEDIATE_VAL(s2) & 0xffff) == 0)
- printf("cau %s,%s,0x%x",NAME(d),NAME(s1),IMMEDIATE_VAL(s2) >> 16);
- else
- abort ();
- }
- else
- printf("cax %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case ADD_CO:
- if (IMMEDIATE_P(s2))
- printf("ai %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- else
- printf("a %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case ADD_CIO:
- if (IMMEDIATE_P(s2))
- {
- if (IMMEDIATE_VAL(s2) == -1)
- printf("ame %s,%s",NAME(d),NAME(s1));
- else if (IMMEDIATE_VAL(s2) == 0)
- printf("aze %s,%s",NAME(d),NAME(s1));
- }
- else
- printf("ae %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case SUB:
- if (IMMEDIATE_P(s1))
- {
- if (IMMEDIATE_VAL(s1) == 0)
- printf("neg %s,%s",NAME(d),NAME(s2));
- else if (IMMEDIATE_VAL(s1) == -1)
- printf("nand %s,%s,%s",NAME(d),NAME(s2),NAME(s2));
- }
- else abort();
- break;
- case ADC_CO:
- if (IMMEDIATE_P(s1))
- printf("sfi %s,%s,%s",NAME(d),NAME(s2),NAME(s1));
- else
- printf("sf %s,%s,%s",NAME(d),NAME(s2),NAME(s1));
- break;
- case ADC_CIO:
- if (IMMEDIATE_P(s1))
- {
- if (IMMEDIATE_VAL(s1) == -1)
- printf("sfme %s,%s",NAME(d),NAME(s2));
- else if (IMMEDIATE_VAL(s1) == 0)
- printf("sfze %s,%s",NAME(d),NAME(s2));
- else abort();
- }
- else
- printf("sfe %s,%s,%s",NAME(d),NAME(s2),NAME(s1));
- break;
- case AND:
- if (IMMEDIATE_P(s2))
- {
- if (IMMEDIATE_VAL(s2) == 0x80000000)
- printf("rlinm %s,%s,0,0,0",NAME(d),NAME(s1));
- else if (IMMEDIATE_VAL(s2) == 0x7fffffff)
- printf("rlinm %s,%s,0,1,31",NAME(d),NAME(s1));
- else if (IMMEDIATE_VAL(s2) == 1)
- printf("rlinm %s,%s,0,31,31",NAME(d),NAME(s1));
- else abort();
- }
- else
- printf("and %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case IOR:
- if (IMMEDIATE_P(s2))
- {
- if (IMMEDIATE_VAL(s2) == 0x80000000)
- printf("oriu %s,%s,0x8000",NAME(d),NAME(s1));
- else abort();
- }
- else
- printf("or %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case XOR:
- if (IMMEDIATE_P(s2))
- {
- if (IMMEDIATE_VAL(s2) == 1)
- printf("xoril\t%s,%s,1",NAME(d),NAME(s1));
- else if (IMMEDIATE_VAL(s2) == 0x80000000)
- printf("xoriu\t%s,%s,0x8000",NAME(d),NAME(s1));
- else abort();
- }
- else
- printf("xor %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case ANDC: printf("andc %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case IORC: printf("orc %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case EQV: printf("eqv %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case NAND: printf("nand %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case NOR: printf("nor %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case LSHIFTR:
- if (IMMEDIATE_P(s2))
- printf("sri %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- else
- printf("sre %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case ASHIFTR_CON:
- if (IMMEDIATE_P(s2))
- printf("srai %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- else
- printf("srea %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case SHIFTL:
- if (IMMEDIATE_P(s2))
- printf("sli %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- else
- printf("sle %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case ROTATEL:
- if (IMMEDIATE_P(s2))
- printf("rlinm %s,%s,%s,0,31",NAME(d),NAME(s1),NAME(s2));
- else
- printf("rlnm %s,%s,%s,0,31",NAME(d),NAME(s1),NAME(s2));
- break;
- case ABSVAL:printf("abs %s,%s",NAME(d),NAME(s1));break;
- case NABSVAL:printf("nabs %s,%s",NAME(d),NAME(s1));break;
- case DOZ:
- if (IMMEDIATE_P(s1))
- printf("dozi %s,%s,%s",NAME(d),NAME(s2),NAME(s1));
- else
- printf("doz %s,%s,%s",NAME(d),NAME(s2),NAME(s1));
- break;
- case MUL:
- if (IMMEDIATE_P(s1))
- printf("muli %s,%s,%s",NAME(d),NAME(s2),NAME(s1));
- else
- printf("muls %s,%s,%s",NAME(d),NAME(s2),NAME(s1));
- break;
- case CLZ:
- printf("cntlz %s,%s",NAME(d),NAME(s1));break;
-
- #elif M88000
- case COPY:
- if (IMMEDIATE_P(s1))
- {
- if ((IMMEDIATE_VAL(s1) & 0xffff) == 0)
- printf("or.u %s,r0,0x%x",NAME(d),IMMEDIATE_VAL(s1));
- else if ((IMMEDIATE_VAL(s1) & 0xffff0000) == 0)
- printf("or %s,r0,0x%x",NAME(d),IMMEDIATE_VAL(s1));
- else if ((IMMEDIATE_VAL(s1) & 0xffff0000) == 0xffff0000)
- printf("subu %s,r0,0x%x",NAME(d),-IMMEDIATE_VAL(s1));
- else
- {
- word x = IMMEDIATE_VAL(s1);
- int i, j;
- for (i = 31; i > 0; i--)
- if ((x & (1 << i)) != 0)
- break;
- for (j = i; j >= 0; j--)
- if ((x & (1 << j)) == 0)
- break;
- printf("set %s,r0,%d<%d>",NAME(d), i - j, j + 1);
- }
- }
- else
- printf("or %s,%s",NAME(d),NAME(s1));
- break;
- case ADD: printf("addu %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ADD_CI:printf("addu.ci %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ADD_CO:printf("addu.co %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ADD_CIO:
- if (IMMEDIATE_P(s2))
- {
- if (IMMEDIATE_VAL(s2) == -1)
- {
- printf("subu.cio %s,%s,r0",NAME(d),NAME(s1));
- break;
- }
- if (IMMEDIATE_VAL(s2) != 0)
- abort();
- }
- printf("addu.cio %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case SUB:
- if (IMMEDIATE_P(s1) && IMMEDIATE_VAL(s1) == -1)
- printf("xor.c %s,%s,r0",NAME(d),NAME(s2));
- else
- printf("subu %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case ADC_CI:printf("subu.ci %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ADC_CO:printf("subu.co %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ADC_CIO:printf("subu.cio %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case AND:
- if (IMMEDIATE_P(s2))
- {
- if (IMMEDIATE_VAL(s2) == 0x80000000)
- printf("mask.u %s,%s,0x8000",NAME(d),NAME(s1));
- else if (IMMEDIATE_VAL(s2) == 0x7fffffff)
- printf("and.u %s,%s,0x7fff",NAME(d),NAME(s1));
- else if (IMMEDIATE_VAL(s2) == 1)
- printf("mask %s,%s,1",NAME(d),NAME(s1));
- else abort();
- }
- else
- printf("and %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case IOR:
- if (IMMEDIATE_P(s2))
- {
- if ((IMMEDIATE_VAL(s2) & 0xffff) == 0)
- printf("or.u %s,%s,0x%x",NAME(d),NAME(s1),
- IMMEDIATE_VAL(s2)>>16);
- else if (IMMEDIATE_VAL(s2) < 0x10000)
- printf("or %s,%s,0x%x",NAME(d),NAME(s1),IMMEDIATE_VAL(s2));
- else abort();
- }
- else
- printf("or %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case XOR:
- if (IMMEDIATE_P(s2))
- {
- if ((IMMEDIATE_VAL(s2) & 0xffff) == 0)
- printf("xor.u %s,%s,0x%x",NAME(d),NAME(s1),
- IMMEDIATE_VAL(s2)>>16);
- else if (IMMEDIATE_VAL(s2) < 0x10000)
- printf("xor %s,%s,0x%x",NAME(d),NAME(s1),IMMEDIATE_VAL(s2));
- else abort();
- }
- else
- printf("xor %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case ANDC: printf("and.c %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case IORC: printf("or.c %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case EQV: printf("xor.c %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case LSHIFTR:printf("extu %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ASHIFTR:printf("ext %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case SHIFTL:printf("mak %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ROTATEL:
- printf("rot %s,%s,%d",NAME(d),NAME(s1),32-IMMEDIATE_VAL(s2));
- break;
- case FF1:
- printf("ff1 %s,%s",NAME(d),NAME(s1)); break;
- case FF0:
- printf("ff0 %s,%s",NAME(d),NAME(s1)); break;
- case CMPPAR:
- if (IMMEDIATE_P(s2))
- printf("cmp %s,%s,0x%x",NAME(d),NAME(s1),IMMEDIATE_VAL(s2));
- else if (IMMEDIATE_P(s1))
- printf("cmp %s,r0,%s",NAME(d),NAME(s2));
- else
- printf("cmp %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case EXTS1:
- printf("ext %s,%s,1<%d>",NAME(d),NAME(s1),IMMEDIATE_VAL(s2));
- break;
- case EXTS2:
- printf("ext %s,%s,2<%d>",NAME(d),NAME(s1),IMMEDIATE_VAL(s2));
- break;
- case EXTU1:
- printf("extu %s,%s,1<%d>",NAME(d),NAME(s1),IMMEDIATE_VAL(s2));
- break;
- case EXTU2:
- printf("extu %s,%s,2<%d>",NAME(d),NAME(s1),IMMEDIATE_VAL(s2));
- break;
- case MUL:
- printf("mul %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- #elif AM29K
- case COPY:
- if (IMMEDIATE_P(s1))
- {
- if (IMMEDIATE_VAL(s1) < 0x10000)
- printf("const %s,0x%x",NAME(d),IMMEDIATE_VAL(s1));
- else if (-IMMEDIATE_VAL(s1) < 0x10000)
- printf("constn %s,-0x%x",NAME(d),-IMMEDIATE_VAL(s1));
- else if (IMMEDIATE_VAL(s1) == 0x80000000)
- printf("cpeq %s,gr1,gr1",NAME(d));
- else abort();
- }
- else
- printf("or %s,%s,0",NAME(d),NAME(s1));
- break;
- case ADD_CO:
- if (IMMEDIATE_P(s2) && (signed_word) IMMEDIATE_VAL(s2) < 0)
- printf("sub %s,%s,0x%x",NAME(d),NAME(s1),-IMMEDIATE_VAL(s2));
- else
- printf("add %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case ADD_CIO:
- if (IMMEDIATE_P(s2) && (signed_word) IMMEDIATE_VAL(s2) < 0)
- printf("subc %s,%s,0x%x",NAME(d),NAME(s1),-IMMEDIATE_VAL(s2));
- else
- printf("addc %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case SUB:
- if (IMMEDIATE_P(s1) && IMMEDIATE_VAL(s1) == -1)
- printf("nor %s,%s,0",NAME(d),NAME(s2));
- else abort();
- break;
- case ADC_CO:printf("sub %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ADC_CIO:printf("subc %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case AND: printf("and %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case IOR: printf("or %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case XOR: printf("xor %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ANDC: printf("andn %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case EQV: printf("xnor %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case NAND: printf("nand %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case NOR: printf("nor %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case LSHIFTR:printf("srl %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case ASHIFTR:printf("sra %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case SHIFTL:printf("sll %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPEQ: printf("cpeq %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPGE: printf("cpge %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPGEU: printf("cpgeu %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPGT: printf("cpgt %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPGTU: printf("cpgtu %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPLE: printf("cple %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPLEU: printf("cpleu %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPLT: printf("cplt %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPLTU: printf("cpltu %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case CPNEQ: printf("cpneq %s,%s,%s",NAME(d),NAME(s1),NAME(s2));break;
- case MUL:
- printf("multiply %s,%s,%s",NAME(d),NAME(s1),NAME(s2));
- break;
- case CLZ:
- printf("clz %s,%s",NAME(d),NAME(s1));break;
- #elif M68000
- case COPY:
- if (IMMEDIATE_P(s1))
- {
- if ((signed_word) IMMEDIATE_VAL(s1) >= -128
- && (signed_word) IMMEDIATE_VAL(s1) < 128)
- {
- printf("moveq #%ld,%s", IMMEDIATE_VAL(s1),NAME(d));
- break;
- }
- }
- printf("movel %s,%s",NAME(s1),NAME(d));
- break;
- case EXCHANGE:
- printf("exgl %s,%s",NAME(s2),NAME(d));break;
- case ADD_CO:
- if (IMMEDIATE_P(s2)
- && IMMEDIATE_VAL(s2) >= 1 && IMMEDIATE_VAL(s2) <= 8)
- printf("addql %s,%s",NAME(s2),NAME(d));
- else
- printf("addl %s,%s",NAME(s2),NAME(d));
- break;
- case ADD_CIO:
- printf("addxl %s,%s",NAME(s2),NAME(d));break;
- case SUB:
- if (IMMEDIATE_P(s1) && IMMEDIATE_VAL(s1) == -1)
- printf("notl %s",NAME(d));
- else abort();
- break;
- case SUB_CO:
- if (IMMEDIATE_P(s1) && IMMEDIATE_VAL(s1) == 0)
- printf("negl %s",NAME(d));
- else if (IMMEDIATE_P(s2)
- && IMMEDIATE_VAL(s2) >= 1 && IMMEDIATE_VAL(s2) <= 8)
- printf("subql %s,%s",NAME(s2),NAME(d));
- else
- printf("subl %s,%s",NAME(s2),NAME(d));
- break;
- case SUB_CIO:
- if (IMMEDIATE_P(s1) && IMMEDIATE_VAL(s1) == 0)
- printf("negxl %s",NAME(d));
- else
- printf("subxl %s,%s",NAME(s2),NAME(d));
- break;
- case AND:
- if (IMMEDIATE_P(s2) && IMMEDIATE_VAL(s2) + 0x8000 < 0x10000)
- printf("andw %s,%s",NAME(s2),NAME(d));
- else
- printf("andl %s,%s",NAME(s2),NAME(d));
- break;
- case IOR:
- if (IMMEDIATE_P(s2) && IMMEDIATE_VAL(s2) + 0x8000 < 0x10000)
- printf("orw %s,%s",NAME(s2),NAME(d));
- else
- printf("orl %s,%s",NAME(s2),NAME(d));
- break;
- case XOR:
- if (IMMEDIATE_P(s2) && IMMEDIATE_VAL(s2) + 0x8000 < 0x10000)
- printf("eorw %s,%s",NAME(s2),NAME(d));
- else
- printf("eorl %s,%s",NAME(s2),NAME(d));
- break;
- case LSHIFTR_CO:
- printf("lsrl %s,%s",NAME(s2),NAME(d));break;
- case ASHIFTR_CO:
- printf("asrl %s,%s",NAME(s2),NAME(d));break;
- case SHIFTL_CO:
- printf("lsll %s,%s",NAME(s2),NAME(d));break;
- case ROTATEL_CO:
- printf("roll %s,%s",NAME(s2),NAME(d));break;
- case ROTATEXL_CIO:
- printf("roxll %s,%s",NAME(s2),NAME(d));break;
- case MUL:
- printf("mulsl %s,%s",NAME(s2),NAME(d));break;
- #elif I386
- case COPY:
- printf("movl %s,%s",NAME(s1),NAME(d));break;
- case EXCHANGE:
- printf("xchgl %s,%s",NAME(s2),NAME(d));break;
- case ADD:
- if (IMMEDIATE_P(s2) && IMMEDIATE_VAL(s2) == 1)
- printf("incl %s",NAME(d));
- else abort();
- break;
- case ADD_CO:
- printf("addl %s,%s",NAME(s2),NAME(d));break;
- case ADD_CIO:
- printf("adcl %s,%s",NAME(s2),NAME(d));break;
- case SUB:
- if (IMMEDIATE_P(s2) && IMMEDIATE_VAL(s2) == 1)
- printf("decl %s",NAME(d));
- else if (IMMEDIATE_P(s1) && IMMEDIATE_VAL(s1) == -1)
- printf("notl %s",NAME(d));
- else abort();
- break;
- case SUB_CO:
- if (IMMEDIATE_P(s1) && IMMEDIATE_VAL(s1) == 0)
- printf("negl %s",NAME(d));
- else
- printf("subl %s,%s",NAME(s2),NAME(d));
- break;
- case SUB_CIO:
- printf("sbbl %s,%s",NAME(s2),NAME(d));break;
- case CMP:
- printf("cmpl %s,%s",NAME(s2),NAME(s1));break;
- case AND_RC:
- if (IMMEDIATE_P(s2) && IMMEDIATE_VAL(s2) + 0x80 < 0x100)
- printf("andb $%d,%s",IMMEDIATE_VAL(s2),NAME(d));
- else
- printf("andl %s,%s",NAME(s2),NAME(d));
- break;
- case IOR_RC:
- if (IMMEDIATE_P(s2) && IMMEDIATE_VAL(s2) + 0x80 < 0x100)
- printf("orb $%d,%s",IMMEDIATE_VAL(s2),NAME(d));
- else
- printf("orl %s,%s",NAME(s2),NAME(d));
- break;
- case XOR_RC:
- if (IMMEDIATE_P(s2) && IMMEDIATE_VAL(s2) + 0x80 < 0x100)
- printf("xorb $%d,%s",IMMEDIATE_VAL(s2),NAME(d));
- else
- printf("xorl %s,%s",NAME(s2),NAME(d));
- break;
- case LSHIFTR_CO:
- printf("shrl %s,%s",NAME(s2),NAME(d));break;
- case ASHIFTR_CO:
- printf("sarl %s,%s",NAME(s2),NAME(d));break;
- case SHIFTL_CO:
- printf("shll %s,%s",NAME(s2),NAME(d));break;
- case ROTATEL_CO:
- printf("roll %s,%s",NAME(s2),NAME(d));break;
- case ROTATEXL_CIO:
- printf("rlcl %s,%s",NAME(s2),NAME(d));break;
- case COMCY:
- printf("cmc");break;
- case MUL:
- printf("imull %s,%s",NAME(s2),NAME(d));break;
- #elif PYR
- case COPY:
- printf("movw %s,%s",NAME(s1),NAME(d));break;
- case EXCHANGE:
- printf("xchw %s,%s",NAME(s2),NAME(d));break;
- case ADD:
- printf("mova 0x%x(%s),%s",IMMEDIATE_VAL(s2),NAME(s1),NAME(d));
- break;
- case ADD_CO:
- printf("addw %s,%s",NAME(s2),NAME(d));break;
- case ADD_CIO:
- printf("addwc %s,%s",NAME(s2),NAME(d));break;
- case ADC_CO:
- printf("subw %s,%s",NAME(s2),NAME(d));break;
- case ADC_CIO:
- printf("subwb %s,%s",NAME(s2),NAME(d));break;
- case AND_CC:
- printf("andw %s,%s",NAME(s2),NAME(d));break;
- case IOR_CC:
- printf("orw %s,%s",NAME(s2),NAME(d));break;
- case XOR_CC:
- printf("xorw %s,%s",NAME(s2),NAME(d)); break;
- case ANDC_CC:
- printf("bicw %s,%s",NAME(s2),NAME(d)); break;
- case LSHIFTR_CO:
- printf("lshrw %s,%s",NAME(s2),NAME(d));break;
- case ASHIFTR_CO:
- printf("ashrw %s,%s",NAME(s2),NAME(d));break;
- case SHIFTL_CO:
- printf("lshlw %s,%s",NAME(s2),NAME(d));break;
- case MUL:
- printf("mulw %s,%s",NAME(s2),NAME(d));break;
- #elif ALPHA
- case ADD: printf("addq %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case SUB:
- if (IMMEDIATE_P(s1) && IMMEDIATE_VAL(s1) == -1)
- printf("ornot $31,%s,%s",NAME(s2),NAME(d));
- else
- printf("subq %s,%s,%s",NAME(s1),NAME(s2),NAME(d));
- break;
- case AND: printf("and %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case IOR: printf("bis %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case XOR: printf("xor %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case ANDC: printf("bic %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case IORC: printf("ornot %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case EQV: printf("eqv %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case LSHIFTR:printf("srl %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case ASHIFTR:printf("sra %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case SHIFTL:printf("sll %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMPEQ: printf("cmpeq %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMPLE: printf("cmple %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMPLEU:printf("cmpleu %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMPLT: printf("cmplt %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMPLTU:printf("cmpltu %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMOVEQ:printf("cmoveq %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMOVNE:printf("cmovne %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMOVLT:printf("cmovlt %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMOVGE:printf("cmovge %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMOVLE:printf("cmovle %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- case CMOVGT:printf("cmovgt %s,%s,%s",NAME(s1),NAME(s2),NAME(d));break;
- #else
- #error no assembler output code for this CPU
- #endif
- default:abort();
- }
- printf("\n");
- }
-
- word tvalues[0x100];
-
- /* TEST_SETS contains sets of input values and corresponding goal value used
- to test the correctness of a sequence. N_TEST_SETS says how many sets
- are defined. */
- word *test_sets;
- int n_test_sets;
-
- word test_operands[] =
- {
- 0,
- 1,
- -1,
- -2,
- VALUE_MIN_SIGNED,
- VALUE_MAX_SIGNED,
- VALUE_MIN_SIGNED + 1,
- VALUE_MAX_SIGNED - 1,
- };
- #define N_TEST_OPERANDS (sizeof(test_operands)/sizeof(test_operands[0]))
-
- void
- init_test_sets()
- {
- unsigned int loop_vars[8];
- int pc, i, j;
- word *test_set;
- const int arity = goal_function_arity;
- word (*eval) (const word *) = eval_goal_function;
-
- if (sizeof (loop_vars) / sizeof (loop_vars[0]) <= arity)
- abort ();
-
- /* Allocate enough space in TEST_SETS for all combinations of TEST_OPERANDS
- and an additional 10,000 random test sets. */
- {
- static int n_words;
-
- j = 1 + arity;
- for (i = arity - 1; i >= 0; i--)
- j *= N_TEST_OPERANDS;
-
- j += (1 + arity) * 10000;
-
- if (n_words < j)
- {
- test_sets = (n_words == 0
- ? (word *) xmalloc (sizeof (word) * j)
- : (word *) xrealloc (test_sets, sizeof (word) * j));
- n_words = j;
- }
- }
-
- test_set = test_sets;
- j = 0;
-
- /* Start with all combinations of operands from TEST_OPERANDS. */
- for (i = arity - 1; i >= 0; i--)
- loop_vars[i] = 0;
- for (;;)
- {
- for (i = arity - 1; i >= 0; i--)
- tvalues[i] = *test_set++ = test_operands[loop_vars[i]];
-
- /* Get the desired value for the current operand values. */
- *test_set++ = (*eval)(tvalues);
- j++;
-
- /* General loop control. This implements ARITY loops using induction
- variables in loop_vars[0] through loop_vars[ARITY - 1]. */
- i = 0;
- loop_vars[i] = (loop_vars[i] + 1) % N_TEST_OPERANDS;
- while (loop_vars[i] == 0)
- {
- i++;
- if (i >= arity)
- goto random;
- loop_vars[i] = (loop_vars[i] + 1) % N_TEST_OPERANDS;
- }
- }
-
- /* Now add the additional random test sets. */
- random:
- for (i = 9999; i >= 0; i--)
- {
- for (pc = arity - 1; pc >= 0; pc--)
- tvalues[pc] = *test_set++ = random_word();
-
- *test_set++ = (*eval)(tvalues);
- j++;
- }
-
- n_test_sets = j;
- }
-
- /* Test the correctness of a sequence in SEQUENCE[0] through
- SEQUENCE[N_INSNS - 1]. */
-
- void
- test_sequence(insn_t *sequence, int n_insns)
- {
- int pc;
- int i, j;
- word *test_set = test_sets;
- const int arity = goal_function_arity;
-
- /* Test each of the precomputed values. */
- for (j = n_test_sets; j > 0; j--)
- {
- /* Update the tvalues array in each iteration, as execution of the
- sequence might clobber the values. (On 2-operand machines.) */
- for (i = arity - 1; i >= 0; i--)
- tvalues[i] = *test_set++;
-
- /* Execute the synthesised sequence for the current operand
- values. */
- run_program (sequence, n_insns, tvalues);
- if (tvalues[sequence[n_insns - 1].d] != *test_set++)
- {
- /* Adaptively rearrange the order of the tests. This set of test
- values is better than all that preceed it. The optimal
- ordering changes with the search space. */
- if ((j = n_test_sets - j) != 0)
- {
- int k = j >> 1;
- j *= (arity + 1);
- k *= (arity + 1);
- for (i = 0; i <= arity; i++)
- {
- word t = test_sets[j + i];
- test_sets[j + i] = test_sets[k + i];
- test_sets[k + i] = t;
- }
- }
- return;
- }
- }
-
- /* The tests passed. Print the instruction sequence. */
- if (success == 0)
- printf("\n");
- success++;
-
- printf("%d:", success);
- for (pc = 0; pc < n_insns; pc++)
- {
- insn_t insn;
-
- insn = sequence[pc];
- if (flag_output_assembler)
- output_assembler(insn);
- else
- {
- if (insn.opcode == CMP)
- printf("\t%s(", GET_INSN_NAME(insn.opcode));
- else
- printf("\tr%u:=%s(", insn.d, GET_INSN_NAME(insn.opcode));
- if (IMMEDIATE_P(insn.s1))
- {
- if ((signed_word) IMMEDIATE_VAL(insn.s1) >= 10
- || (signed_word) IMMEDIATE_VAL(insn.s1) <= -10)
- printf("0x%lx", IMMEDIATE_VAL(insn.s1));
- else
- printf("%ld", IMMEDIATE_VAL(insn.s1));
- }
- else
- printf("r%u", insn.s1);
-
- if (!UNARY_OPERATION(insn))
- {
- if (IMMEDIATE_P(insn.s2))
- {
- if ((signed_word) IMMEDIATE_VAL(insn.s2) >= 10
- || (signed_word) IMMEDIATE_VAL(insn.s2) <= -10)
- printf(",0x%lx", IMMEDIATE_VAL(insn.s2));
- else
- printf(",%ld", IMMEDIATE_VAL(insn.s2));
- }
- else
- printf(",r%u", insn.s2);
- }
- printf(")\n");
- }
- }
- fflush(stdout);
- }
-
-
- /* Recursively investigate all possible instruction sequences for the
- current target.
-
- SEQUENCE contains the instructions defined so far.
-
- N_INSNS is the number of instructions, including the one we will
- generate this time, in SEQUENCE.
-
- VALUES contains the values in register 0..N_VALUES.
-
- N_VALUES is the number of registers that have been assigned values by
- the insns so far.
-
- GOAL_VALUE is the value we aim at, when the sequence is ready.
-
- ALLOWED_COST is the maximum allowed cost of the remaining sequence.
-
- CY_IN is the carry flag. It is negative if no instruction has yet
- defined it (this to pruning the search tree), and otherwise takes the
- values 0 or 1 according to the conventions of the current target.
-
- PRUNE_HINT contains flags to assist pruning of the search tree. */
-
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- void
- synth(insn_t *sequence,
- int n_insns,
- word *values,
- int n_values,
- word goal_value,
- int allowed_cost,
- int ci,
- int prune_hint)
- {
- int s1, s2;
- word v, r1, r2;
- int co;
- int last_dest;
-
- #ifdef TIMING
- int time_start = cputime();
- #endif
-
- if (n_insns > 0)
- last_dest = sequence[n_insns - 1].d;
- else
- last_dest = -1;
-
- /* Binary operations with carry-in. */
- if (ci >= 0 && flag_use_carry)
- {
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- r1 = values[s1];
- for (s2 = s1 - 1; s2 >= 0; s2--)
- {
- r2 = values[s2];
-
- if (allowed_cost <= 1 && (prune_hint & CY_JUST_SET) == 0)
- {
- /* We are in a leaf node. CY was not set (to 0, 1 or to
- a data dependent value) by the previous insn.
-
- So one of the input operands has to be the result
- operand of the previous insn for that insn to be
- meaningful. */
- if (last_dest >= 0 && s1 != last_dest && s2 != last_dest)
- continue;
- }
-
- #if SPARC || RS6000 || M88000 || AM29K
- /* sparc: addxcc
- rs6000: ae
- m88000: addu.cio
- am29k: addc */
- PERFORM_ADD_CIO(v, co, r1, r2, ci);
- RECURSE(ADD_CIO, s1, s2, CY_JUST_SET);
- #endif
- #if SPARC || M88000
- /* sparc: addx
- m88000: addu.ci */
- PERFORM_ADD_CI(v, co, r1, r2, ci);
- RECURSE(ADD_CI, s1, s2, prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC
- /* sparc: subxcc */
- PERFORM_SUB_CIO(v, co, r1, r2, ci);
- RECURSE(SUB_CIO, s1, s2, CY_JUST_SET);
- PERFORM_SUB_CIO(v, co, r2, r1, ci);
- RECURSE(SUB_CIO, s2, s1, CY_JUST_SET);
- #endif
- #if SPARC
- /* sparc: subx */
- PERFORM_SUB_CI(v, co, r1, r2, ci);
- RECURSE(SUB_CI, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_SUB_CI(v, co, r2, r1, ci);
- RECURSE(SUB_CI, s2, s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || M88000 || AM29K
- /* rs6000: sfe
- m88000: subu.cio
- am29k: subc */
- PERFORM_ADC_CIO(v, co, r1, r2, ci);
- RECURSE(ADC_CIO, s1, s2, CY_JUST_SET);
- PERFORM_ADC_CIO(v, co, r2, r1, ci);
- RECURSE(ADC_CIO, s2, s1, CY_JUST_SET);
- #endif
- #if M88000
- /* m88000: subu.ci */
- PERFORM_ADC_CI(v, co, r1, r2, ci);
- RECURSE(ADC_CI, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_ADC_CI(v, co, r2, r1, ci);
- RECURSE(ADC_CI, s2, s1, prune_hint & ~CY_JUST_SET);
- #endif
- }
- }
- }
-
- /* Binary operations without carry-in. */
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- r1 = values[s1];
- for (s2 = s1 - 1; s2 >= 0; s2--)
- {
- r2 = values[s2];
-
- if (allowed_cost <= 1)
- {
- /* We are in a leaf node.
-
- So one of the input operands has to be the result operand
- of the previous insn for that insn to be meaningful. */
- if (last_dest >= 0 && s1 != last_dest && s2 != last_dest)
- continue;
- }
-
- #ifdef DM
- PERFORM_UMULWIDEN_HI(v, co, r1, r2, ci);
- RECURSE(UMULWIDEN_HI, s1, s2, prune_hint & ~CY_JUST_SET);
- #endif
- #if defined (DM) || defined (MM)
- PERFORM_MUL(v, co, r1, r2, ci);
- RECURSE(MUL, s1, s2, prune_hint & ~CY_JUST_SET);
- #endif
- #ifdef UDIV_WITH_SDIV
- PERFORM_SDIV (v, co, r1, r2, ci);
- RECURSE(SDIV, s1, s2, prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K
- /* sparc: addcc
- rs6000: a
- m88000: addu.co
- am29k: add */
- PERFORM_ADD_CO(v, co, r1, r2, ci);
- RECURSE(ADD_CO, s1, s2, CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || ALPHA
- /* sparc: add
- rs6000: cax
- m88000: addu
- alpha: addq */
- PERFORM_ADD(v, co, r1, r2, ci);
- RECURSE(ADD, s1, s2, prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC
- /* sparc: subcc */
- PERFORM_SUB_CO(v, co, r1, r2, ci);
- RECURSE(SUB_CO, s1, s2, CY_JUST_SET);
- PERFORM_SUB_CO(v, co, r2, r1, ci);
- RECURSE(SUB_CO, s2, s1, CY_JUST_SET);
- #endif
- #if SPARC || M88000 || ALPHA
- /* sparc: sub
- m88000: subu
- alpha: subq */
- PERFORM_SUB(v, co, r1, r2, ci);
- RECURSE(SUB, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_SUB(v, co, r2, r1, ci);
- RECURSE(SUB, s2, s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || M88000 || AM29K
- /* rs6000: sf
- m88000: subu.co
- am29k: sub */
- PERFORM_ADC_CO(v, co, r1, r2, ci);
- RECURSE(ADC_CO, s1, s2, CY_JUST_SET);
- PERFORM_ADC_CO(v, co, r2, r1, ci);
- RECURSE(ADC_CO, s2, s1, CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- PERFORM_AND(v, co, r1, r2, ci);
- RECURSE(AND, s1, s2, prune_hint & ~CY_JUST_SET);
-
- PERFORM_IOR(v, co, r1, r2, ci);
- RECURSE(IOR, s1, s2, prune_hint & ~CY_JUST_SET);
-
- PERFORM_XOR(v, co, r1, r2, ci);
- RECURSE(XOR, s1, s2, prune_hint & ~CY_JUST_SET);
-
- PERFORM_ANDC(v, co, r1, r2, ci);
- RECURSE(ANDC, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_ANDC(v, co, r2, r1, ci);
- RECURSE(ANDC, s2, s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || ALPHA
- PERFORM_IORC(v, co, r1, r2, ci);
- RECURSE(IORC, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_IORC(v, co, r2, r1, ci);
- RECURSE(IORC, s2, s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- PERFORM_EQV(v, co, r1, r2, ci);
- RECURSE(EQV, s1, s2, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || AM29K
- PERFORM_NAND(v, co, r1, r2, ci);
- RECURSE(NAND, s1, s2, prune_hint & ~CY_JUST_SET);
-
- PERFORM_NOR(v, co, r1, r2, ci);
- RECURSE(NOR, s1, s2, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 && !defined (AVOID_DOZ)
- PERFORM_DOZ(v, co, r1, r2, ci);
- RECURSE(DOZ, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_DOZ(v, co, r2, r1, ci);
- RECURSE(DOZ, s2, s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if AM29K
- PERFORM_CPEQ(v, co, r1, r2, ci);
- RECURSE(CPEQ, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CPGE(v, co, r1, r2, ci);
- RECURSE(CPGE, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CPGEU(v, co, r1, r2, ci);
- RECURSE(CPGEU, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CPGT(v, co, r1, r2, ci);
- RECURSE(CPGT, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CPGTU(v, co, r1, r2, ci);
- RECURSE(CPGTU, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CPLE(v, co, r1, r2, ci);
- RECURSE(CPLE, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CPLEU(v, co, r1, r2, ci);
- RECURSE(CPLEU, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CPLT(v, co, r1, r2, ci);
- RECURSE(CPLT, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CPLTU(v, co, r1, r2, ci);
- RECURSE(CPLTU, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CPNEQ(v, co, r1, r2, ci);
- RECURSE(CPNEQ, s1, s2, prune_hint & ~CY_JUST_SET);
- #endif
- #if ALPHA
- PERFORM_CMPEQ(v, co, r1, r2, ci);
- RECURSE(CMPEQ, s1, s2, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMPLE(v, co, r1, r2, ci);
- RECURSE(CMPLE, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CMPLE(v, co, r2, r1, ci);
- RECURSE(CMPLE, s2, s1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMPLEU(v, co, r1, r2, ci);
- RECURSE(CMPLEU, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CMPLEU(v, co, r2, r1, ci);
- RECURSE(CMPLEU, s2, s1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMPLT(v, co, r1, r2, ci);
- RECURSE(CMPLT, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CMPLT(v, co, r2, r1, ci);
- RECURSE(CMPLT, s2, s1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMPLTU(v, co, r1, r2, ci);
- RECURSE(CMPLTU, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CMPLTU(v, co, r2, r1, ci);
- RECURSE(CMPLTU, s2, s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if M88000
- PERFORM_CMPPAR (v, co, r1, r2, ci);
- RECURSE(CMPPAR, s1, s2, prune_hint & ~CY_JUST_SET);
- PERFORM_CMPPAR (v, co, r2, r1, ci);
- RECURSE(CMPPAR, s2, s1, prune_hint & ~CY_JUST_SET);
- #endif
- }
- }
-
- /* Unary operations with carry-in. */
- if (ci >= 0 && flag_use_carry)
- {
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- r1 = values[s1];
-
- if (allowed_cost <= 1 && (prune_hint & CY_JUST_SET) == 0)
- {
- /* We are in a leaf node and CY was not set (to 1 or to a
- data dependent value) by the previous insn.
-
- The input operand has to be the result operand of the
- previous insn for that insn to be meaningful. */
- if (last_dest >= 0 && s1 != last_dest)
- continue;
- }
-
- #if SPARC || RS6000 || M88000 || AM29K
- /* d,cy = 2*r1 + cy
- sparc: addxcc s1,s1,d
- rs6000: ae d,s1,s1
- m88000: addu.cio d,s1,s1
- am29k: addc d,s1,s1 */
- PERFORM_ADD_CIO(v, co, r1, r1, ci);
- RECURSE(ADD_CIO, s1, s1, CY_JUST_SET);
- #endif
- #if SPARC || M88000
- /* d = 2*r1 + cy
- sparc: addx s1,s1,d
- m88000: addu.ci d,s1,s1 */
- PERFORM_ADD_CI(v, co, r1, r1, ci);
- RECURSE(ADD_CI, s1, s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K
- /* d,cy = r1 + cy - 1
- sparc: addxcc s1,-1,d
- rs6000: ame d,s1
- m88000: subu.cio d,s1,r0
- am29k: subc d,s1,0 */
- PERFORM_ADD_CIO(v, co, r1, VALUE(-1), ci);
- RECURSE(ADD_CIO, s1, CNST(-1), CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K
- /* d,cy = r1 + cy
- sparc: addxcc s1,0,d
- rs6000: aze d,s1
- m88000: addu.cio d,s1,r0
- am29k: addc d,s1,0 */
- PERFORM_ADD_CIO(v, co, r1, VALUE(0), ci);
- RECURSE(ADD_CIO, s1, CNST(0), CY_JUST_SET);
- #endif
- #if SPARC
- /* d,cy = 0 - r1 - cy
- sparc: subxcc %g0,s1,d */
- PERFORM_SUB_CIO(v, co, VALUE(0), r1, ci);
- RECURSE(SUB_CIO, CNST(0), s1, CY_JUST_SET);
- #endif
- #if SPARC
- /* d = r1 + 1 - cy
- sparc: subx s1,-1,d */
- PERFORM_SUB_CI(v, co, r1, VALUE(-1), ci);
- RECURSE(SUB_CI, s1, CNST(-1), prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC
- /* d,cy = r1 + 1 - cy
- sparc: subxcc s1,-1,d */
- PERFORM_SUB_CIO(v, co, r1, VALUE(-1), ci);
- RECURSE(SUB_CIO, s1, CNST(-1), CY_JUST_SET);
- #endif
- #if RS6000
- /* d,cy = -1 + ~r1 + cy
- rs6000: sfme d,s1 */
- PERFORM_ADC_CIO(v, co, VALUE(-1), r1, ci);
- RECURSE(ADC_CIO, CNST(-1), s1, CY_JUST_SET);
- #endif
- #if RS6000 || M88000 || AM29K
- /* d,cy = ~r1 + cy
- m88000: subu.cio d,r0,s1
- rs6000: sfze d,s1
- am29k: subrc d,s1,0 */
- PERFORM_ADC_CIO(v, co, VALUE(0), r1, ci);
- RECURSE(ADC_CIO, CNST(0), s1, CY_JUST_SET);
- #endif
- }
- }
-
- /* Unary operations without carry-in. */
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- r1 = values[s1];
-
- if (allowed_cost <= 1)
- {
- /* We are in a leaf node.
-
- The input operand has to be the result operand of the
- previous insns for that insn to be meaningful. */
- if (last_dest >= 0 && s1 != last_dest)
- continue;
- }
-
- #ifdef DM
- PERFORM_INVDIV(v, co, r1, ci);
- RECURSE(INVDIV, s1, 0, prune_hint & ~CY_JUST_SET);
-
- PERFORM_INVMOD(v, co, r1, ci);
- RECURSE(INVMOD, s1, 0, prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K
- /* d,cy = 2*r1
- sparc: addcc s1,s1,d
- rs6000: a d,s1,s1
- m88000: addu.co d,s1,s1
- am29k: add d,s1,s1 */
- PERFORM_ADD_CO(v, co, r1, r1, ci);
- RECURSE(ADD_CO, s1, s1, CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- /* d = r1 & 1
- sparc: and s1,1,d
- rs6000: rlinm d,s1,0,31,31
- m88000: mask d,s1,1
- am29k: and d,s1,1
- alpha: and s1,1,d */
- PERFORM_AND(v, co, r1, VALUE(1), ci);
- RECURSE(AND, s1, CNST(1), prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || M88000
- /* d = r1 & 0x80000000
- rs6000: rlinm d,s1,0,0,0
- m88000: mask.u d,s1,0x8000 */
- PERFORM_AND(v, co, r1, VALUE_MIN_SIGNED, ci);
- RECURSE(AND, s1, CNST_0x80000000, prune_hint & ~CY_JUST_SET);
-
- /* d = r1 & 0x7fffffff
- rs6000: rlinm d,s1,0,1,31
- m88000: and.u d,s1,0x7fff */
- PERFORM_AND(v, co, r1, VALUE_MAX_SIGNED, ci);
- RECURSE(AND, s1, CNST_0x7FFFFFFF, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || M88000
- PERFORM_XOR(v, co, r1, VALUE_MIN_SIGNED, ci);
- RECURSE(XOR, s1, CNST_0x80000000, prune_hint & ~CY_JUST_SET);
-
- PERFORM_IOR(v, co, r1, VALUE_MIN_SIGNED, ci);
- RECURSE(IOR, s1, CNST_0x80000000, prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- /* d = r1 ^ 1
- sparc: xor s1,1,d
- rs6000: xoril d,s1,1
- m88000: xor d,s1,1
- am29k: xor d,s1,1
- alpha: xor s1,1,d */
- PERFORM_XOR(v, co, r1, VALUE(1), ci);
- RECURSE(XOR, s1, CNST(1), prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- /* d = ~r1
- sparc: xnor %g0,s1,d
- rs6000: nand d,s1,s1
- m88000: xor.c d,s1,r0
- am29k: nand d,s1,s1
- alpha: ornot $31,s1,d */
- PERFORM_SUB(v, co, VALUE(-1), r1, ci);
- RECURSE(SUB, CNST(-1), s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000
- /* d,cy = -1 + ~r1 (i.e. one's complement and set carry.)
- rs6000: sfi d,s1,-1 */
- PERFORM_ADC_CO(v, co, VALUE(-1), r1, ci);
- RECURSE(ADC_CO, CNST(-1), s1, CY_JUST_SET | CY_1);
- #endif
- #if SPARC || RS6000 || AM29K
- /* d,cy = r1 + 1
- sparc: addcc s1,1,d
- rs6000: ai d,s1,1
- am29k: add d,s1,1 */
- PERFORM_ADD_CO(v, co, r1, VALUE(1), ci);
- RECURSE(ADD_CO, s1, CNST(1), CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || ALPHA
- /* d = r1 + 1
- sparc: add s1,1,d
- rs6000: cal d,1(s1)
- m88000: addu d,s1,1
- alpha: addq s1,1,d */
- PERFORM_ADD(v, co, r1, VALUE(1), ci);
- RECURSE(ADD, s1, CNST(1), prune_hint & ~CY_JUST_SET);
- #endif
- #if 0 && RS6000 /* This has the same effect as a "xoriu". */
- /* d = r1 + 0x80000000
- rs6000: cau d,s1,0x8000 */
- PERFORM_ADD(v, co, r1, VALUE_MIN_SIGNED, ci);
- RECURSE(ADD, s1, CNST_0x80000000, CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || AM29K /* not M88000 */
- /* d,cy = r1 + -1
- sparc: addcc s1,-1,d
- rs6000: ai d,s1,-1
- am29k: sub d,s1,1 */
- PERFORM_ADD_CO(v, co, r1, VALUE(-1), ci);
- RECURSE(ADD_CO, s1, CNST(-1), CY_JUST_SET);
- #endif
- #if SPARC
- /* d,cy = r1 - 1. [This isn't redundant, in spite we add -1 above.]
- sparc: subcc s1,1,d */
- PERFORM_SUB_CO(v, co, r1, VALUE(1), ci);
- RECURSE(SUB_CO, s1, CNST(1), CY_JUST_SET);
- #endif
- #if SPARC
- /* d,cy = -r1
- sparc: subcc %g0,s1,d */
- PERFORM_SUB_CO(v, co, VALUE(0), r1, ci);
- RECURSE(SUB_CO, CNST(0), s1, CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || ALPHA
- /* d = -r1
- sparc: sub %g0,s1,d
- rs6000: neg d,s1
- m88000: subu d,r0,s1
- alpha: subq $31,s1,d */
- PERFORM_SUB(v, co, VALUE(0), r1, ci);
- RECURSE(SUB, CNST(0), s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || M88000 || AM29K
- /* d,cy = -r1
- rs6000: sf d,s1,0
- m88000: subu.co d,r0,s1
- am29k: subr d,s1,0 */
- PERFORM_ADC_CO(v, co, VALUE(0), r1, ci);
- RECURSE(ADC_CO, CNST(0), s1, CY_JUST_SET);
- #endif
- #if RS6000
- /* d = abs(r1)
- rs6000: abs d,s1 */
- PERFORM_ABSVAL(v, co, r1, ci);
- RECURSE(ABSVAL, s1, 0, prune_hint & ~CY_JUST_SET);
-
- /* d = -abs(r1)
- rs6000: nabs d,s1 */
- PERFORM_NABSVAL(v, co, r1, ci);
- RECURSE(NABSVAL, s1, 0, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 && !defined (AVOID_DOZ)
- PERFORM_DOZ(v, co, VALUE(0), r1, ci);
- RECURSE(DOZ, CNST(0), s1, prune_hint & ~CY_JUST_SET);
- PERFORM_DOZ(v, co, VALUE(-1), r1, ci);
- RECURSE(DOZ, CNST(-1), s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if SHIFTS
- {
- int cnt;
- for (cnt = 1; cnt < BITS_PER_WORD; cnt++)
- {
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- PERFORM_LSHIFTR(v, co, r1, VALUE(cnt), ci);
- RECURSE(LSHIFTR, s1, CNST(cnt), prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || M88000 || AM29K || ALPHA
- PERFORM_ASHIFTR(v, co, r1, VALUE(cnt), ci);
- RECURSE(ASHIFTR, s1, CNST(cnt), prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000
- PERFORM_ASHIFTR_CON(v, co, r1, VALUE(cnt), ci);
- RECURSE(ASHIFTR_CON, s1, CNST(cnt), CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- PERFORM_SHIFTL(v, co, r1, VALUE(cnt), ci);
- RECURSE(SHIFTL, s1, CNST(cnt), prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || M88000
- PERFORM_ROTATEL(v, co, r1, VALUE(cnt), ci);
- RECURSE(ROTATEL, s1, CNST(cnt), prune_hint & ~CY_JUST_SET);
- #endif
- }
- }
- #else
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- PERFORM_LSHIFTR(v, co, r1, VALUE(1), ci);
- RECURSE(LSHIFTR, s1, CNST(1), prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || M88000 || AM29K || ALPHA
- PERFORM_ASHIFTR(v, co, r1, VALUE(1), ci);
- RECURSE(ASHIFTR, s1, CNST(1), prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000
- PERFORM_ASHIFTR_CON(v, co, r1, VALUE(1), ci);
- RECURSE(ASHIFTR_CON, s1, CNST(1), CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- PERFORM_SHIFTL(v, co, r1, VALUE(1), ci);
- RECURSE(SHIFTL, s1, CNST(1), prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || M88000
- PERFORM_ROTATEL(v, co, r1, VALUE(1), ci);
- RECURSE(ROTATEL, s1, CNST(1), prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- PERFORM_LSHIFTR(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- RECURSE(LSHIFTR, s1, CNST(BITS_PER_WORD-1), prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || M88000 || AM29K || ALPHA
- PERFORM_ASHIFTR(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- RECURSE(ASHIFTR, s1, CNST(BITS_PER_WORD-1), prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000
- PERFORM_ASHIFTR_CON(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- RECURSE(ASHIFTR_CON, s1, CNST(BITS_PER_WORD-1), CY_JUST_SET);
- #endif
- #if SHIFT16
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- PERFORM_LSHIFTR(v, co, r1, VALUE(16), ci);
- RECURSE(LSHIFTR, s1, CNST(16), prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || M88000 || AM29K || ALPHA
- PERFORM_ASHIFTR(v, co, r1, VALUE(16), ci);
- RECURSE(ASHIFTR, s1, CNST(16), prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000
- PERFORM_ASHIFTR_CON(v, co, r1, VALUE(16), ci);
- RECURSE(ASHIFTR_CON, s1, CNST(16), CY_JUST_SET);
- #endif
- #if SPARC || RS6000 || M88000 || AM29K || ALPHA
- PERFORM_SHIFTL(v, co, r1, VALUE(16), ci);
- RECURSE(SHIFTL, s1, CNST(16), prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || M88000
- PERFORM_ROTATEL(v, co, r1, VALUE(16), ci);
- RECURSE(ROTATEL, s1, CNST(16), prune_hint & ~CY_JUST_SET);
- #endif
- #endif /* SHIFT16 */
- #endif /* SHIFTS */
- #if EXTRACTS
- {
- int cnt;
- for (cnt = 1; cnt < BITS_PER_WORD; cnt++)
- {
- #if M88000
- PERFORM_EXTS1(v, co, r1, VALUE(cnt), ci);
- RECURSE(EXTS1, s1, CNST(cnt), prune_hint & ~CY_JUST_SET);
- PERFORM_EXTU1(v, co, r1, VALUE(cnt), ci);
- RECURSE(EXTU1, s1, CNST(cnt), prune_hint & ~CY_JUST_SET);
- PERFORM_EXTS2(v, co, r1, VALUE(cnt), ci);
- RECURSE(EXTS2, s1, CNST(cnt), prune_hint & ~CY_JUST_SET);
- PERFORM_EXTU2(v, co, r1, VALUE(cnt), ci);
- RECURSE(EXTU2, s1, CNST(cnt), prune_hint & ~CY_JUST_SET);
- #endif
- }
- }
- #endif
- #if AM29K
- PERFORM_CPEQ(v, co, r1, VALUE(0), ci);
- RECURSE(CPEQ, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CPGE(v, co, r1, VALUE(0), ci);
- RECURSE(CPGE, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CPGEU(v, co, r1, VALUE(0), ci);
- RECURSE(CPGEU, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CPGT(v, co, r1, VALUE(0), ci);
- RECURSE(CPGT, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CPGTU(v, co, r1, VALUE(0), ci);
- RECURSE(CPGTU, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CPLE(v, co, r1, VALUE(0), ci);
- RECURSE(CPLE, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CPLEU(v, co, r1, VALUE(0), ci);
- RECURSE(CPLEU, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CPLT(v, co, r1, VALUE(0), ci);
- RECURSE(CPLT, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CPLTU(v, co, r1, VALUE(0), ci);
- RECURSE(CPLTU, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CPNEQ(v, co, r1, VALUE(0), ci);
- RECURSE(CPNEQ, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- #endif
- #if ALPHA
- PERFORM_CMPEQ(v, co, r1, VALUE(0), ci);
- RECURSE(CMPEQ, s1, CNST(0), prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMPLE(v, co, r1, VALUE(0), ci);
- RECURSE(CMPLE, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CMPLE(v, co, VALUE(0), r1, ci);
- RECURSE(CMPLE, CNST(0), s1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMPLEU(v, co, r1, VALUE(0), ci);
- RECURSE(CMPLEU, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CMPLEU(v, co, VALUE(0), r1, ci);
- RECURSE(CMPLEU, CNST(0), s1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMPLT(v, co, r1, VALUE(0), ci);
- RECURSE(CMPLT, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CMPLT(v, co, VALUE(0), r1, ci);
- RECURSE(CMPLT, CNST(0), s1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMPLTU(v, co, r1, VALUE(0), ci);
- RECURSE(CMPLTU, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CMPLTU(v, co, VALUE(0), r1, ci);
- RECURSE(CMPLTU, CNST(0), s1, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || AM29K
- PERFORM_CLZ(v, co, r1, ci);
- RECURSE(CLZ, s1, 0, prune_hint & ~CY_JUST_SET);
- #endif
- #if M88000
- PERFORM_FF1(v, co, r1, ci);
- RECURSE(FF1, s1, 0, prune_hint & ~CY_JUST_SET);
- #endif
- #if M88000
- PERFORM_CMPPAR (v, co, r1, VALUE(0), ci);
- RECURSE(CMPPAR, s1, CNST(0), prune_hint & ~CY_JUST_SET);
- PERFORM_CMPPAR (v, co, VALUE(0), r1, ci);
- RECURSE(CMPPAR, CNST(0), s1, prune_hint & ~CY_JUST_SET);
- #endif
- }
-
- #if ALPHA
- /* Alpha Conditional move instructions need special treatment. We let all
- other instructions assign the next higher-numbered register, but we
- can't do that here since cmov insns leave the register undefined if the
- instruction condition is not satisfied. Instead we let the cmov
- instructions non-deterministically overwrite all already-defined
- registers. */
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- r1 = values[s1];
- for (s2 = s1 - 1; s2 >= 0; s2--)
- {
- int dr;
- r2 = values[s2];
-
- if (allowed_cost <= 1)
- {
- /* We are in a leaf node. */
-
- /* One of the input operands has to be the result operand
- of the previous insn for that insn to be meaningful. */
- if (last_dest >= 0 && s1 != last_dest && s2 != last_dest)
- continue;
- }
-
- for (dr = n_values - 1; dr >= 0; dr--)
- {
- v = values[dr];
-
- PERFORM_CMOVEQ (v, co, r1, r2, ci);
- CRECURSE_2OP(CMOVEQ, dr, s1, s2, 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVEQ (v, co, r2, r1, ci);
- CRECURSE_2OP(CMOVEQ, dr, s2, s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVNE (v, co, r1, r2, ci);
- CRECURSE_2OP(CMOVNE, dr, s1, s2, 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVNE (v, co, r2, r1, ci);
- CRECURSE_2OP(CMOVNE, dr, s2, s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVLT (v, co, r1, r2, ci);
- CRECURSE_2OP(CMOVLT, dr, s1, s2, 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVLT (v, co, r2, r1, ci);
- CRECURSE_2OP(CMOVLT, dr, s2, s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVGE (v, co, r1, r2, ci);
- CRECURSE_2OP(CMOVGE, dr, s1, s2, 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVGE (v, co, r2, r1, ci);
- CRECURSE_2OP(CMOVGE, dr, s2, s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVLE (v, co, r1, r2, ci);
- CRECURSE_2OP(CMOVLE, dr, s1, s2, 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVLE (v, co, r2, r1, ci);
- CRECURSE_2OP(CMOVLE, dr, s2, s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVGT (v, co, r1, r2, ci);
- CRECURSE_2OP(CMOVGT, dr, s1, s2, 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVGT (v, co, r2, r1, ci);
- CRECURSE_2OP(CMOVGT, dr, s2, s1, 1, prune_hint & ~CY_JUST_SET);
- }
- }
- }
-
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- int dr;
- r1 = values[s1];
-
- if (allowed_cost <= 1)
- {
- /* We are in a leaf node.
-
- The input operand has to be the result operand of the
- previous insns for that insn to be meaningful. */
- if (last_dest >= 0 && s1 != last_dest)
- continue;
- }
-
- for (dr = n_values - 1; dr >= 0; dr--)
- {
- v = values[dr];
-
- PERFORM_CMOVEQ (v, co, r1, VALUE(0), ci);
- CRECURSE_2OP(CMOVEQ, dr, s1, CNST(0), 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVEQ (v, co, VALUE(0), r1, ci);
- CRECURSE_2OP(CMOVEQ, dr, CNST(0), s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVNE (v, co, r1, VALUE(0), ci);
- CRECURSE_2OP(CMOVNE, dr, s1, CNST(0), 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVNE (v, co, VALUE(0), r1, ci);
- CRECURSE_2OP(CMOVNE, dr, CNST(0), s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVLT (v, co, r1, VALUE(0), ci);
- CRECURSE_2OP(CMOVLT, dr, s1, CNST(0), 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVLT (v, co, VALUE(0), r1, ci);
- CRECURSE_2OP(CMOVLT, dr, CNST(0), s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVGE (v, co, r1, VALUE(0), ci);
- CRECURSE_2OP(CMOVGE, dr, s1, CNST(0), 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVGE (v, co, VALUE(0), r1, ci);
- CRECURSE_2OP(CMOVGE, dr, CNST(0), s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVLE (v, co, r1, VALUE(0), ci);
- CRECURSE_2OP(CMOVLE, dr, s1, CNST(0), 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVLE (v, co, VALUE(0), r1, ci);
- CRECURSE_2OP(CMOVLE, dr, CNST(0), s1, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_CMOVGT (v, co, r1, VALUE(0), ci);
- CRECURSE_2OP(CMOVGT, dr, s1, CNST(0), 1, prune_hint & ~CY_JUST_SET);
- PERFORM_CMOVGT (v, co, VALUE(0), r1, ci);
- CRECURSE_2OP(CMOVGT, dr, CNST(0), s1, 1, prune_hint & ~CY_JUST_SET);
- }
- }
- #endif /* ALPHA */
-
- /* 0-ary instructions, just dependent on carry. */
- if (ci >= 0 && flag_use_carry
- && (allowed_cost <= 1 ? ((prune_hint & CY_JUST_SET) != 0) : 1))
- {
- /* We don't do "0 - 1 - cy" or "0 + 1 + cy" here. It would
- probably give very few new sequences. */
- #if SPARC || M88000
- /* d = cy.
- sparc: addx %g0,0,d
- m88000: addu.ci d,r0,r0 */
- PERFORM_ADD_CI(v, co, VALUE(0), VALUE(0), ci);
- RECURSE(ADD_CI, CNST(0), CNST(0), prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC || M88000
- /* d = cy, cy = 0.
- sparc: addxcc %g0,0,d
- m88000: addu.cio d,r0,r0 */
- PERFORM_ADD_CIO(v, co, VALUE(0), VALUE(0), ci);
- RECURSE(ADD_CIO, CNST(0), CNST(0), CY_JUST_SET | CY_0);
- #endif
- #if SPARC
- /* Using SUB_CIO instead would make no difference.
- It'd just set carry to it's old value. */
- /* d = -cy.
- sparc: subx %g0,0,d */
- PERFORM_SUB_CI(v, co, VALUE(0), VALUE(0), ci);
- RECURSE(SUB_CI, CNST(0), CNST(0), prune_hint & ~CY_JUST_SET);
- #endif
- #if SPARC
- /* d = 1 - cy.
- sparc: subx %g0,-1,d */
- PERFORM_SUB_CI(v, co, VALUE(0), VALUE(-1), ci);
- RECURSE(SUB_CI, CNST(0), CNST(-1), CY_JUST_SET | CY_1);
- #endif
- #if SPARC
- /* d = 1 - cy, cy = 1.
- sparc: subxcc %g0,-1,d */
- PERFORM_SUB_CIO(v, co, VALUE(0), VALUE(-1), ci);
- RECURSE(SUB_CIO, CNST(0), CNST(-1), CY_JUST_SET | CY_1);
- #endif
- #if SPARC
- /* Using ADD_CIO instead would make no difference.
- It'd just set carry to it's old value. */
- /* d = -1 + cy.
- sparc: addx %g0,-1,d */
- PERFORM_ADD_CI(v, co, VALUE(0), VALUE(-1), ci);
- RECURSE(ADD_CI, CNST(0), CNST(-1), prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || AM29K /* Use subu.ci on 88k instead with same result */
- /* d = -1 + cy, cy = cy
- rs6000: sfe d,d,d
- am29k: subc d,d,d */
- PERFORM_ADC_CIO(v, co, VALUE(0), VALUE(0), ci);
- RECURSE(ADC_CIO, n_values, n_values, prune_hint & ~CY_JUST_SET);
- #endif
- #if M88000
- /* d = -1 + cy
- m88000: subu.ci d,r0,r0 */
- PERFORM_ADC_CI(v, co, VALUE(0), VALUE(0), ci);
- RECURSE(ADC_CI, CNST(0), CNST(0), prune_hint & ~CY_JUST_SET);
- #endif
- }
-
- /* Move instructions.
- Don't do this if we are just permitted to do one more instruction. */
- if (allowed_cost > 1)
- {
- #if SPARC || RS6000 || M88000 || AM29K
- /* d = 0x80000000
- sparc: sethi %hi(0x80000000),d
- rs6000: liu d,0x8000
- m88000: or.u d,r0,0x8000
- am29k: cpeq d,gr1,gr1 */
- PERFORM_COPY(v, co, VALUE_MIN_SIGNED, ci);
- RECURSE(COPY, CNST_0x80000000, 0, prune_hint & ~CY_JUST_SET);
- /* d = -1
- sparc: mov -1,d
- rs6000: lil d,-1
- m88000: subu d,r0,1
- am29k: constn d,1 */
- PERFORM_COPY(v, co, VALUE(-1), ci);
- RECURSE(COPY, CNST(-1), 0, prune_hint & ~CY_JUST_SET);
- /* d = 1
- sparc: mov 1,d
- rs6000: lil d,1
- m88000: addu d,r0,1
- am29k: const d,1 */
- PERFORM_COPY(v, co, VALUE(1), ci);
- RECURSE(COPY, CNST(1), 0, prune_hint & ~CY_JUST_SET);
- #endif
- #if RS6000 || AM29K /* sparc and 88k should not need this. */
- /* d = 0
- sparc: mov 0,d
- rs6000: lil d,0
- m88000: or d,r0,0
- am29k: const d,0 */
- PERFORM_COPY(v, co, VALUE(0), ci);
- RECURSE(COPY, CNST(0), 0, prune_hint & ~CY_JUST_SET);
- #endif
- #if M88000
- /* d = 0x7fffffff
- m88000: set d,r0,31<0> */
- PERFORM_COPY(v, co, VALUE_MAX_SIGNED, ci);
- RECURSE(COPY, CNST_0x7FFFFFFF, 0, prune_hint & ~CY_JUST_SET);
- #endif
- }
-
- #ifdef TIMING
- timings[allowed_cost] += cputime() - time_start;
- #endif
- }
- #endif
-
- /* This function is commented above, before the previous function. */
-
- #if M68000 || I386 || PYR
- void
- synth(insn_t *sequence,
- int n_insns,
- word *values,
- int n_values,
- word goal_value,
- int allowed_cost,
- int ci,
- int prune_hint)
- {
- int s1, s2;
- word v, r1, r2;
- int co;
- int last_dest;
-
- if (n_insns > 0)
- last_dest = sequence[n_insns - 1].d;
- else
- last_dest = -1;
-
- /* Binary operations with carry-in. */
- if (ci >= 0 && (prune_hint & CY_0) == 0 && flag_use_carry)
- {
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- r1 = values[s1];
- for (s2 = n_values - 1; s2 >= 0; s2--)
- {
- r2 = values[s2];
-
- if (allowed_cost <= 1 && (prune_hint & CY_JUST_SET) == 0)
- {
- /* We are in a leaf node. CY was not set (to 1 or to a
- data dependent value) by the previous insn.
-
- So one of the input operands has to be the result
- operand of the previous insn for that insn to be
- meaningful. */
- if (last_dest >= 0 && s1 != last_dest && s2 != last_dest)
- continue;
- }
-
- #if M68000 || I386 || PYR
- /* m68000: addx
- i80386: adc
- pyramid: addwc */
- PERFORM_ADD_CIO(v, co, r1, r2, ci);
- CRECURSE_2OP(ADD_CIO, s1, s1, s2, 1, CY_JUST_SET);
- #endif
- #if M68000 || I386
- if (s1 != s2)
- {
- /* m68000: subx
- i80386: sbb */
- PERFORM_SUB_CIO(v, co, r1, r2, ci);
- CRECURSE_2OP(SUB_CIO, s1, s1, s2, 1, CY_JUST_SET);
- }
- #endif
- #if PYR
- if (s1 != s2)
- {
- /* pyramid: subwb */
- PERFORM_ADC_CIO(v, co, r1, r2, ci);
- CRECURSE_2OP(ADC_CIO, s1, s1, s2, 1, CY_JUST_SET);
- }
- #endif
- }
- }
- }
-
- /* Binary operations without carry-in. */
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- r1 = values[s1];
- for (s2 = n_values - 1; s2 >= 0; s2--)
- {
- r2 = values[s2];
-
- if (allowed_cost <= 1)
- {
- /* We are in a leaf node.
-
- So one of the input operands has to be the result operand
- of the previous insn for that insn to be meaningful. */
- if (last_dest >= 0 && s1 != last_dest && s2 != last_dest)
- continue;
- }
-
- #if M68000 || I386 || PYR
- /* m68000: add
- i80386: add
- pyramid: addw */
- PERFORM_ADD_CO(v, co, r1, r2, ci);
- CRECURSE_2OP(ADD_CO, s1, s1, s2, 1, CY_JUST_SET);
- #endif
- if (s1 != s2)
- {
- #if M68000 || I386
- /* m68000: sub
- i80386: sub */
- PERFORM_SUB_CO(v, co, r1, r2, ci);
- CRECURSE_2OP(SUB_CO, s1, s1, s2, 1, CY_JUST_SET);
- #endif
- #if PYR
- /* pyramid: subw */
- PERFORM_ADC_CO(v, co, r1, r2, ci);
- CRECURSE_2OP(ADC_CO, s1, s1, s2, 1, CY_JUST_SET);
- #endif
- #if M68000
- PERFORM_AND(v, co, r1, r2, ci);
- CRECURSE_2OP(AND, s1, s1, s2, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_IOR(v, co, r1, r2, ci);
- CRECURSE_2OP(IOR, s1, s1, s2, 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_XOR(v, co, r1, r2, ci);
- CRECURSE_2OP(XOR, s1, s1, s2, 1, prune_hint & ~CY_JUST_SET);
- #endif
- #if I386
- PERFORM_AND_RC(v, co, r1, r2, ci);
- CRECURSE_2OP(AND_RC, s1, s1, s2, 1, CY_JUST_SET | CY_0);
-
- PERFORM_IOR_RC(v, co, r1, r2, ci);
- CRECURSE_2OP(IOR_RC, s1, s1, s2, 1, CY_JUST_SET | CY_0);
-
- PERFORM_XOR_RC(v, co, r1, r2, ci);
- CRECURSE_2OP(XOR_RC, s1, s1, s2, 1, CY_JUST_SET | CY_0);
- #endif
- #if PYR
- PERFORM_AND_CC(v, co, r1, r2, ci);
- CRECURSE_2OP(AND_CC, s1, s1, s2, 1, 0);
-
- PERFORM_ANDC_CC(v, co, r1, r2, ci);
- CRECURSE_2OP(ANDC_CC, s1, s1, s2, 1, 0);
-
- PERFORM_IOR_CC(v, co, r1, r2, ci);
- CRECURSE_2OP(IOR_CC, s1, s1, s2, 1, 0);
-
- PERFORM_XOR_CC(v, co, r1, r2, ci);
- CRECURSE_2OP(XOR_CC, s1, s1, s2, 1, 0);
- #endif
- #if I386
- PERFORM_CMP(v, co, r1, r2, ci);
- /* kludge: lie that the result is written to
- register <n_values>. */
- CRECURSE_2OP(CMP, n_values, s1, s2, 1, CY_JUST_SET);
- #endif
- }
- #if M68000 || I386 || PYR
- /* Exchange registers. An ugly kludge. */
- if (s1 < s2)
- {
- values[s2] = r1;
- /* Assign r2 to v to make `recurse' and rely on `recurse'
- to handle the writing of it to the values array. */
- v = r2;
- CRECURSE_2OP(EXCHANGE, s1, s1, s2, 1,
- prune_hint & ~CY_JUST_SET);
- values[s2] = r2;
- }
- #endif
- }
- }
-
- /* Unary operations with carry-in. */
- if (ci >= 0 && (prune_hint & CY_0) == 0 && flag_use_carry)
- {
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- r1 = values[s1];
-
- if (allowed_cost <= 1 && (prune_hint & CY_JUST_SET) == 0)
- {
- /* We are in a leaf node. CY was not set (to 1 or to a
- data dependent value) by the previous insn.
-
- The input operand has to be the result operand of the
- previous insn for that insn to be meaningful. */
- if (last_dest >= 0 && s1 != last_dest)
- continue;
- }
-
- #if I386 || PYR
- /* d,cy = r1 + 1 + cy
- i80386: adc 1,d
- pyramid: addwc $1,d */
- PERFORM_ADD_CIO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ADD_CIO, s1, s1, CNST(1), 1, CY_JUST_SET);
- #endif
- #if I386
- /* d,cy = r1 - 1 - cy
- i80386: sbb 1,d */
- PERFORM_SUB_CIO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(SUB_CIO, s1, s1, CNST(1), 1, CY_JUST_SET);
- #endif
- #if PYR
- /* d,cy = r1 + (-2) + cy
- pyramid: subwb $1,d */
- PERFORM_ADC_CIO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ADC_CIO, s1, s1, CNST(1), 1, CY_JUST_SET);
- #endif
- #if I386 || PYR
- /* d,cy = r1 + (-1) + cy
- i80386: adc -1,d
- pyramid: addwc $-1,d */
- PERFORM_ADD_CIO(v, co, r1, VALUE(-1), ci);
- CRECURSE_2OP(ADD_CIO, s1, s1, CNST(-1), 1, CY_JUST_SET);
- #endif
- #if I386
- /* d,cy = r1 - -1 - cy
- i80386: sbb -1,d */
- PERFORM_SUB_CIO(v, co, r1, VALUE(-1), ci);
- CRECURSE_2OP(SUB_CIO, s1, s1, CNST(-1), 1, CY_JUST_SET);
- #endif
- #if PYR
- /* d,cy = r1 + cy [or if you prefer, r1 + 0 + cy]
- pyramid: subwb $-1,d */
- PERFORM_ADC_CIO(v, co, r1, VALUE(-1), ci);
- CRECURSE_2OP(ADC_CIO, s1, s1, CNST(-1), 1, CY_JUST_SET);
- #endif
- #if I386 || PYR
- /* d,cy = r1 + cy
- i80386: adc 0,d
- pyramid: addwc $0,d */
- PERFORM_ADD_CIO(v, co, r1, VALUE(0), ci);
- CRECURSE_2OP(ADD_CIO, s1, s1, CNST(0), 1, CY_JUST_SET);
- #endif
- #if I386
- /* d,cy = r1 - cy
- i80386: sbb 0,d */
- PERFORM_SUB_CIO(v, co, r1, VALUE(0), ci);
- CRECURSE_2OP(SUB_CIO, s1, s1, CNST(0), 1, CY_JUST_SET);
- #endif
- #if PYR
- /* d,cy = r1 + (-1) + cy
- pyramid: subwb $0,d */
- PERFORM_ADC_CIO(v, co, r1, VALUE(0), ci);
- CRECURSE_2OP(ADC_CIO, s1, s1, CNST(0), 1, CY_JUST_SET);
- #endif
- #if M68000
- /* d,cy = 0 - r1 - cy
- m68000: negx d */
- PERFORM_SUB_CIO(v, co, VALUE(0), r1, ci);
- CRECURSE_2OP(SUB_CIO, s1, CNST(0), s1, 1, CY_JUST_SET);
- #endif
- #if M68000
- /* d,cy = circular rotate left thru carry
- m68000: roxll #1,d */
- PERFORM_ROTATEXL_CIO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ROTATEXL_CIO, s1, s1, CNST(1), SHIFT_COST(1), CY_JUST_SET);
- #endif
- #if I386
- PERFORM_ROTATEXL_CIO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(ROTATEXL_CIO, s1, s1, CNST(BITS_PER_WORD-1), 2, CY_JUST_SET);
-
- PERFORM_ROTATEXL_CIO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ROTATEXL_CIO, s1, s1, CNST(1), 2, CY_JUST_SET);
- #endif
- }
- }
-
- /* Unary operations without carry-in. */
- for (s1 = n_values - 1; s1 >= 0; s1--)
- {
- r1 = values[s1];
-
- if (allowed_cost <= 1)
- {
- /* We are in a leaf node.
-
- The input operand has to be the result operand of the
- previous insns for that insn to be meaningful. */
- if (last_dest >= 0 && s1 != last_dest)
- continue;
- }
- else
- {
- /* Certain instructions should not terminate a sequence. So we
- only generate them in non-leaf nodes. */
- #if M68000 || I386 || PYR
- /* d = r1
- m68000: move s1,d
- i80386: move s1,d
- pyramid: movw s1,d */
- PERFORM_COPY(v, co, r1, ci);
- CRECURSE_NEW(COPY, n_values, s1, CNST(0), 1,
- prune_hint & ~CY_JUST_SET);
- #endif
- #if I386
- /* cmp kludge: lie that the result is written to register
- <n_values>. */
-
- /* i80386: cmp -1,s1 */
- PERFORM_CMP(v, co, r1, VALUE(-1), ci);
- CRECURSE_2OP(CMP, n_values, s1, CNST(-1), 1, CY_JUST_SET);
-
- /* i80386: cmp 1,s1 */
- PERFORM_CMP(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(CMP, n_values, s1, CNST(1), 1, CY_JUST_SET);
-
- /* i80386: cmp 0x7fffffff,s1 */
- PERFORM_CMP(v, co, r1, VALUE_MAX_SIGNED, ci);
- CRECURSE_2OP(CMP, n_values, s1, CNST_0x7FFFFFFF, 2, CY_JUST_SET);
-
- /* i80386: cmp 0x80000000,s1 */
- PERFORM_CMP(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(CMP, n_values, s1, CNST_0x80000000, 2, CY_JUST_SET);
- #endif
- }
-
- #if M68000 || PYR
- PERFORM_LSHIFTR_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(LSHIFTR_CO, s1, s1, CNST(1), SHIFT_COST(1), CY_JUST_SET);
-
- PERFORM_ASHIFTR_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ASHIFTR_CO, s1, s1, CNST(1), SHIFT_COST(1), CY_JUST_SET);
-
- PERFORM_SHIFTL_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(SHIFTL_CO, s1, s1, CNST(1), SHIFT_COST(1), CY_JUST_SET);
-
- /* Pyramids's rotlw and rotrw clobber cy */
- #endif
- #if M68000
- PERFORM_ROTATEL_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ROTATEL_CO, s1, s1, CNST(1), SHIFT_COST(1), CY_JUST_SET);
- #endif
- #if PYR
- PERFORM_LSHIFTR_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(LSHIFTR_CO, s1, s1, CNST(BITS_PER_WORD-1), 1, CY_JUST_SET);
-
- PERFORM_ASHIFTR_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(ASHIFTR_CO, s1, s1, CNST(BITS_PER_WORD-1), 1, CY_JUST_SET);
-
- PERFORM_SHIFTL_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(SHIFTL_CO, s1, s1, CNST(BITS_PER_WORD-1), 1, CY_JUST_SET);
-
- /* Pyramids's rotlw and rotrw clobber cy */
- #endif
- #if I386
- PERFORM_LSHIFTR_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(LSHIFTR_CO, s1, s1, CNST(BITS_PER_WORD-1), 2, CY_JUST_SET);
-
- PERFORM_ASHIFTR_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(ASHIFTR_CO, s1, s1, CNST(BITS_PER_WORD-1), 2, CY_JUST_SET);
-
- PERFORM_SHIFTL_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(SHIFTL_CO, s1, s1, CNST(BITS_PER_WORD-1), 2, CY_JUST_SET);
-
- PERFORM_ROTATEL_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(ROTATEL_CO, s1, s1, CNST(BITS_PER_WORD-1), 2, CY_JUST_SET);
-
- PERFORM_LSHIFTR_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(LSHIFTR_CO, s1, s1, CNST(1), 2, CY_JUST_SET);
-
- PERFORM_ASHIFTR_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ASHIFTR_CO, s1, s1, CNST(1), 2, CY_JUST_SET);
-
- PERFORM_SHIFTL_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(SHIFTL_CO, s1, s1, CNST(1), 2, CY_JUST_SET);
-
- PERFORM_ROTATEL_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ROTATEL_CO, s1, s1, CNST(1), 2, CY_JUST_SET);
- #endif
- #if M68000
- /* m68000: andw $1,d */
- PERFORM_AND(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(AND, s1, s1, CNST(1), 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_AND(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(AND, s1, s1, CNST_0x80000000, 2, prune_hint & ~CY_JUST_SET);
-
- PERFORM_IOR(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(IOR, s1, s1, CNST_0x80000000, 2, prune_hint & ~CY_JUST_SET);
-
- /* d = r1 ^ 1
- m68000: eorw #1,d */
- PERFORM_XOR(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(XOR, s1, s1, CNST(1), 1, prune_hint & ~CY_JUST_SET);
-
- PERFORM_XOR(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(XOR, s1, s1, CNST_0x80000000, 2, prune_hint & ~CY_JUST_SET);
- #endif
- #if I386
- /* i80386: andb $1,d */
- PERFORM_AND_RC(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(AND_RC, s1, s1, CNST(1), 1, CY_JUST_SET | CY_0);
-
- PERFORM_AND_RC(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(AND_RC, s1, s1, CNST_0x80000000, 2, CY_JUST_SET | CY_0);
-
- PERFORM_IOR_RC(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(IOR_RC, s1, s1, CNST_0x80000000, 2, CY_JUST_SET | CY_0);
-
- /* d = r1 ^ 1
- i80386: xorb $1,d */
- PERFORM_XOR_RC(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(XOR_RC, s1, s1, CNST(1), 1, CY_JUST_SET | CY_0);
-
- PERFORM_XOR_RC(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(XOR_RC, s1, s1, CNST_0x80000000, 2, CY_JUST_SET | CY_0);
- #endif
- #if PYR
- PERFORM_AND_CC(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(AND_CC, s1, s1, CNST(1), 1, 0);
-
- PERFORM_AND_CC(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(AND_CC, s1, s1, CNST_0x80000000, 2, 0);
-
- PERFORM_IOR_CC(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(IOR_CC, s1, s1, CNST_0x80000000, 2, 0);
-
- /* d = r1 ^ 1
- pyramid: xorw $1,d */
- PERFORM_XOR_CC(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(XOR_CC, s1, s1, CNST(1), 1, 0);
-
- PERFORM_XOR_CC(v, co, r1, VALUE_MIN_SIGNED, ci);
- CRECURSE_2OP(XOR_CC, s1, s1, CNST_0x80000000, 2, 0);
- #endif
- #if M68000 || I386
- /* d = ~r1
- m68000: not d
- i80386: not d */
- PERFORM_SUB(v, co, VALUE(-1), r1, ci);
- CRECURSE_2OP(SUB, s1, CNST(-1), s1, 1, prune_hint & ~CY_JUST_SET);
- #endif
- #if PYR
- /* d = ~r1
- pyramid: mcomw s1,d */
- /* We need a new insn: SUB_CC, for Subtract and Clobber Carry */
- #endif
- #if I386
- /* d = r1 + 1
- i80386: inc d */
- PERFORM_ADD(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ADD, s1, s1, CNST(1), 2, prune_hint & ~CY_JUST_SET);
- #endif
- #if PYR
- /* d = r1 + 1
- pyramid: mova 1(s1),d */
- PERFORM_ADD(v, co, r1, VALUE(1), ci);
- RECURSE(ADD, s1, CNST(1), prune_hint & ~CY_JUST_SET);
- #endif
- #if I386
- /* d = r1 - 1
- i80386: dec d */
- PERFORM_SUB(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(SUB, s1, s1, CNST(1), 1, prune_hint & ~CY_JUST_SET);
- #endif
- #if PYR
- /* d = r1 - 1
- pyramid: mova -1(s1),d */
- PERFORM_ADD(v, co, r1, VALUE(-1), ci);
- RECURSE(ADD, s1, CNST(-1), prune_hint & ~CY_JUST_SET);
- #endif
- #if M68000 || I386 || PYR
- /* d,cy = r1 + 1
- m68000: addq 1,d
- i80386: add 1,d [short immediate form]
- pyramid: addw $1,d */
- PERFORM_ADD_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ADD_CO, s1, s1, CNST(1), 1, CY_JUST_SET);
- #endif
- #if M68000 || I386
- /* d,cy = r1 - 1
- m68000: subq 1,d
- i80386: sub 1,d [short immediate form] */
- PERFORM_SUB_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(SUB_CO, s1, s1, CNST(1), 1, CY_JUST_SET);
- #endif
- #if PYR && 0 /* same effect as addw $-1,d */
- /* d,cy = r1 + (-1)
- pyramid: subw 1,d */
- PERFORM_ADC_CO(v, co, r1, VALUE(1), ci);
- CRECURSE_2OP(ADC_CO, s1, s1, CNST(1), 1, CY_JUST_SET);
- #endif
- #if M68000
- /* d,cy = r1 + (-1)
- m68000: add -1,d */
- PERFORM_ADD_CO(v, co, r1, VALUE(-1), ci);
- CRECURSE_2OP(ADD_CO, s1, s1, CNST(-1), 2, CY_JUST_SET);
- #endif
- #if I386 || PYR
- /* d,cy = r1 + (-1)
- i80386: add -1,d
- pyramid: addw $-1,d */
- PERFORM_ADD_CO(v, co, r1, VALUE(-1), ci);
- CRECURSE_2OP(ADD_CO, s1, s1, CNST(-1), 1, CY_JUST_SET);
- #endif
- #if M68000
- /* d,cy = r1 - (-1)
- m68000: sub -1,d */
- PERFORM_SUB_CO(v, co, r1, VALUE(-1), ci);
- CRECURSE_2OP(SUB_CO, s1, s1, CNST(-1), 2, CY_JUST_SET);
- #endif
- #if I386
- /* d,cy = r1 - (-1)
- i80386: sub -1,d */
- PERFORM_SUB_CO(v, co, r1, VALUE(-1), ci);
- CRECURSE_2OP(SUB_CO, s1, s1, CNST(-1), 1, CY_JUST_SET);
- #endif
- #if M68000 || I386
- /* d,cy = -r1
- m68000: neg d
- i80386: neg d */
- PERFORM_SUB_CO(v, co, VALUE(0), r1, ci);
- CRECURSE_2OP(SUB_CO, s1, CNST(0), s1, 1, CY_JUST_SET);
- #endif
- #if PYR
- /* d,cy = 0 + (-r1)
- pyramid: rsubw $0,d */
- PERFORM_ADC_CO(v, co, VALUE(0), r1, ci);
- CRECURSE_2OP(ADC_CO, s1, CNST(0), s1, 1, CY_JUST_SET);
- #endif
- }
-
- #if M68020 && !M68000 /* don't do this for plain 68000 */
- /* kludge for immediate shift on 68k */
- if (last_dest >= 0 && last_dest == n_values - 1
- && values[last_dest] == VALUE(BITS_PER_WORD-1)
- && sequence[n_insns - 1].opcode == COPY)
- {
- for (s1 = n_values - 2; s1 >= 0; s1--)
- {
- r1 = values[s1];
-
- PERFORM_LSHIFTR_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(LSHIFTR_CO, s1, s1, last_dest, 1, CY_JUST_SET);
-
- PERFORM_ASHIFTR_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(ASHIFTR_CO, s1, s1, last_dest, 1, CY_JUST_SET);
-
- PERFORM_SHIFTL_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(SHIFTL_CO, s1, s1, last_dest, 1, CY_JUST_SET);
-
- PERFORM_ROTATEL_CO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(ROTATEL_CO, s1, s1, last_dest, 1, CY_JUST_SET);
-
- if (ci >= 0)
- {
- PERFORM_ROTATEXL_CIO(v, co, r1, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_2OP(ROTATEXL_CIO, s1, s1, last_dest, 1, CY_JUST_SET);
- }
- }
- }
- #endif
-
- if (ci >= 0 && (prune_hint & CY_0) == 0 && flag_use_carry
- && (allowed_cost <= 1 ? ((prune_hint & CY_JUST_SET) != 0) : 1))
- {
- #if M68000 || I386
- /* d = -cy, cy = cy
- m68000: subx d,d
- i80386: sbb d,d */
- PERFORM_SUB_CIO(v, co, VALUE(0), VALUE(0), ci);
- CRECURSE_NEW(SUB_CIO, n_values, n_values, n_values, 1,
- prune_hint & ~CY_JUST_SET); /* cy not really affected */
- #endif
- #if PYR
- /* d = -cy, cy = cy
- pyramid: subwb d,d */
- PERFORM_ADC_CIO(v, co, VALUE(0), VALUE(0), ci);
- CRECURSE_NEW(ADC_CIO, n_values, n_values, n_values, 1,
- prune_hint & ~CY_JUST_SET); /* cy not really affected */
- #endif
- #if I386 /* slow on m68000 */
- /* i80386: cmc */
- co = ci ^ 1;
- CRECURSE_2OP(COMCY, n_values, n_values, n_values, 1, CY_JUST_SET);
- #endif
- }
-
- /* Move instructions.
- Don't do this if we are just permitted to do one more instruction. */
- if (allowed_cost > 1)
- {
- #if M68000 || PYR
- /* d = 0
- m68000: moveq 0,d
- pyramid: movw 0,d */
- PERFORM_COPY(v, co, VALUE(0), ci);
- CRECURSE_NEW(COPY, n_values, CNST(0), CNST(0), 1,
- prune_hint & ~CY_JUST_SET);
- #endif
- #if M68000 || I386
- /* d = 0, cy = 0
- m68000: sub d,d
- i80386: sub d,d */
- PERFORM_SUB_CO(v, co, r1, r1, ci);
- CRECURSE_NEW(SUB_CO, n_values, n_values, n_values, 1, CY_JUST_SET | CY_0);
- #endif
- #if PYR
- /* d = 0, cy = 0
- pyramid: subw d,d */
- PERFORM_ADC_CO(v, co, r1, r1, ci);
- CRECURSE_NEW(ADC_CO, n_values, n_values, n_values, 1, CY_JUST_SET | CY_0);
- #endif
- #if M68000
- /* d = 31
- m68000: moveq 31,d */
- PERFORM_COPY(v, co, VALUE(BITS_PER_WORD-1), ci);
- CRECURSE_NEW(COPY, n_values, CNST(BITS_PER_WORD-1), CNST(0), 1,
- prune_hint & ~CY_JUST_SET);
- #endif
- #if M68000 || PYR
- /* d = 1
- m68000: moveq 1,d
- pyramid: movw $1,d */
- PERFORM_COPY(v, co, VALUE(1), ci);
- CRECURSE_NEW(COPY, n_values, CNST(1), CNST(0), 1,
- prune_hint & ~CY_JUST_SET);
- /* d = -1
- m68000: moveq -1,d
- pyramid: movw $-1,d */
- PERFORM_COPY(v, co, VALUE(-1), ci);
- CRECURSE_NEW(COPY, n_values, CNST(-1), CNST(0), 1,
- prune_hint & ~CY_JUST_SET);
- #endif
- #if M68000 || I386 || PYR /* these cost 2 cost units */
- /* d = 0x80000000 */
- PERFORM_COPY(v, co, VALUE_MIN_SIGNED, ci);
- CRECURSE_NEW(COPY, n_values, CNST_0x80000000, CNST(0), 2,
- prune_hint & ~CY_JUST_SET);
-
- /* d = 0x7fffffff */
- PERFORM_COPY(v, co, VALUE_MAX_SIGNED, ci);
- CRECURSE_NEW(COPY, n_values, CNST_0x7FFFFFFF, CNST(0), 2,
- prune_hint & ~CY_JUST_SET);
- #endif
- }
- }
- #endif
-
- /* Call `synth' allowing deeper and deeper searches for each call.
- This way we achieve iterative deepening search.
-
- MAXMAX_COST is the maximum cost for any sequence we will accept. */
- void
- main_synth(int maxmax_cost, int allowed_extra_cost)
- {
- int max_cost;
- word values[0x100];
- insn_t sequence[0x100];
- int i, ii;
-
- init_immediates(tvalues);
- init_immediates(values);
- init_test_sets();
-
- /* Speed hack: Try to find random values that makes the goal function
- take a value != 0. Many false sequences give 0 for all input,
- and this hack achieve quick reject of these sequences. */
- for (i = 0; i < 50; i++)
- {
- for (ii = 0; ii < goal_function_arity; ii++)
- values[ii] = random_word();
- if ((*eval_goal_function)(values) != 0)
- break;
- }
-
- ii = 0;
- #if KNOW_START
- switch (goal_function)
- {
- case FFS:
- #if M88000
- /* Best ffs starting place. */
- sequence[ii++] = (insn_t) { ADC_CO, CNST(0), 0, 1 };
- sequence[ii++] = (insn_t) { AND, 0, 1, 2 };
- #endif
- break;
-
- case ZDEPI_FOR_MOVSI:
- #if SPARC
- sequence[ii++] = (insn_t) { SUB, CNST(0), 0, 1 };
- sequence[ii++] = (insn_t) { AND, 0, 1, 2 };
- #endif
- break;
- default: break;
- }
- #endif
-
- fprintf(stderr, "Superoptimizing at cost");
- success = 0;
- for (max_cost = 1; max_cost <= maxmax_cost; max_cost++)
- {
- #if TIMING
- for (i = 0; i <= max_cost; i++)
- timings[i] = 0;
- #endif
-
- if (success)
- fprintf (stderr, "[cost %d]\n", max_cost + ii);
- else
- fprintf(stderr, " %d", max_cost + ii);
- fflush(stderr);
-
- i = run_program (sequence, ii, values);
-
- /* Don't pass CY_JUST_SET ever, since we don't know which of the
- predefined insn above set cy. */
- synth(sequence, ii, values, goal_function_arity+ii,
- (*eval_goal_function)(values),
- max_cost, i, NO_PRUNE);
-
- #ifdef STATISTICS
- if (isatty(fileno(stdout)) == isatty(fileno(stderr)))
- printf("\n");
- printf("heuristic accept count:%u\n", heuristic_accept_count);
- printf("heuristic reject count:%u\n", heuristic_reject_count);
- #endif
- #if TIMING
- for (i = 1; i <= max_cost; i++)
- printf ("time %d: %d\n", i, timings[i] - timings[i - 1]);
- #endif
-
- if (success)
- {
- allowed_extra_cost--;
- if (allowed_extra_cost < 0)
- {
- static char *s[] = {"", "s"};
- fprintf(stderr, " [%d sequence%s found]\n", success,
- s[success != 1]);
- return;
- }
- }
- }
- fprintf(stderr, " failure.\n");
- }
-
- /* Create a function for each DEF_GOAL. When optimized, these are very
- efficient. */
- #undef DEF_GOAL
- #ifdef __STDC__
- #define DEF_GOAL(SYM,ARITY,NAME,CODE) \
- word SYM ## _func (const word *v) \
- GOAL_FUNCTION (ARITY, CODE)
- #else
- #define DEF_GOAL(SYM,ARITY,NAME,CODE) \
- word SYM/**/_func (v) word *v; \
- GOAL_FUNCTION (ARITY, CODE)
- #endif
- #define GOAL_FUNCTION(ARITY,CODE) \
- { \
- word r, v0, v1, v2, v3; \
- switch (ARITY) \
- { \
- default: \
- abort (); \
- case 4: v3 = v[3]; \
- case 3: v2 = v[2]; \
- case 2: v1 = v[1]; \
- case 1: v0 = v[0]; \
- } \
- CODE; \
- return r; \
- }
- #undef DEF_SYNONYM
- #define DEF_SYNONYM(SYM,NAME)
- #include "goal.def"
-
- struct
- {
- char *fname;
- enum goal_func fcode;
- int arity;
- char *c_code;
- word (*function)(const word*);
- } goal_table[] =
- {
- /* Start off with entries so that goal_names[i].fcode == i. */
- #undef DEF_GOAL
- #ifdef __STDC__
- #define DEF_GOAL(SYM,ARITY,NAME,CODE) {NAME, SYM, ARITY, #CODE, SYM ## _func},
- #else
- #define DEF_GOAL(SYM,ARITY,NAME,CODE) {NAME, SYM, ARITY, "CODE", SYM/**/_func},
- #endif
- #undef DEF_SYNONYM
- #define DEF_SYNONYM(SYM,NAME)
- #include "goal.def"
-
- /* Now add the synonyms. */
- #undef DEF_GOAL
- #define DEF_GOAL(SYM,ARITY,NAME,CODE)
- #undef DEF_SYNONYM
- #define DEF_SYNONYM(SYM,NAME) {NAME, SYM, 0, 0},
- #include "goal.def"
- };
-
- #define GET_GOAL_NAME(X) (goal_table[X].fname)
- #define GET_GOAL_ARITY(X) (goal_table[X].arity)
- #define GET_GOAL_C_CODE(X) (goal_table[X].c_code)
- #define GET_GOAL_FUNCTION(X) (goal_table[X].function)
-
- int
- main(int argc, char **argv)
- {
- int maxmax_cost = 5;
- int allowed_extra_cost = 0;
- int flag_all = 0;
-
- goal_function = LAST_AND_UNUSED_GOAL_CODE;
-
- argv++;
- argc--;
-
- while (argc > 0)
- {
- char *arg = argv[0];
- int arglen = strlen(arg);
-
- if (arglen < 2)
- arglen = 2;
-
- if (!strncmp(arg, "-version", arglen))
- {
- printf ("GSO version %s\n", version_string);
- if (argc == 1)
- exit (0);
- }
- else if (!strncmp(arg, "-assembler", arglen))
- flag_output_assembler = 1;
- else if (!strncmp(arg, "-no-carry-insns", arglen))
- flag_use_carry = 0;
- else if (!strncmp(arg, "-all", arglen))
- flag_all = 1;
- else if (!strncmp(arg, "-max-cost", arglen))
- {
- argv++;
- argc--;
- if (argc == 0)
- {
- fprintf(stderr, "superoptimizer: argument to `-max-cost' expected\n");
- exit(-1);
- }
- maxmax_cost = atoi(argv[0]);
- }
- else if (!strncmp(arg, "-extra-cost", arglen))
- {
- argv++;
- argc--;
- if (argc == 0)
- {
- fprintf(stderr, "superoptimizer: argument `-extra-cost' expected\n");
- exit(-1);
- }
- allowed_extra_cost = atoi(argv[0]);
- }
- else if (!strncmp(arg, "-f", 2))
- {
- int i;
- for (i = 0; i < sizeof(goal_table) / sizeof(goal_table[0]); i++)
- {
- if (!strcmp(arg + 2, goal_table[i].fname))
- {
- goal_function = goal_table[i].fcode;
- goal_function_arity = GET_GOAL_ARITY(goal_function);
- eval_goal_function = GET_GOAL_FUNCTION(goal_function);
- break;
- }
- }
- if (goal_function == LAST_AND_UNUSED_GOAL_CODE)
- {
- fprintf(stderr,
- "superoptimizer: unknown goal function\n");
- exit(-1);
- }
- }
- else
- {
- fprintf(stderr, "superoptimizer: syntax error at command line\n");
- exit(-1);
- }
-
- argv++;
- argc--;
- }
-
- if (flag_all)
- {
- for (goal_function = 0; goal_function < LAST_AND_UNUSED_GOAL_CODE;
- goal_function++)
- {
- fprintf(stderr, "Searching for goal %s\n",
- GET_GOAL_NAME (goal_function));
-
- goal_function_arity = GET_GOAL_ARITY(goal_function);
- eval_goal_function = GET_GOAL_FUNCTION(goal_function);
- main_synth(maxmax_cost, allowed_extra_cost);
- if (success)
- fprintf(stderr, "%s\n", GET_GOAL_C_CODE(goal_function));
- }
- return 0;
- }
-
- if (goal_function == LAST_AND_UNUSED_GOAL_CODE)
- {
- fprintf(stderr, "superoptimizer: missing goal function definition\n");
- exit(-1);
- }
-
- fprintf(stderr, "Searching for %s\n", GET_GOAL_C_CODE(goal_function));
- main_synth(maxmax_cost, allowed_extra_cost);
- return !success;
- }
-
- /* Aux stuff that should go into a separate file. */
-
- int
- ffs_internal(x)
- word x;
- {
- int co, ci;
- word d;
- PERFORM_FFS(d, co, x, ci);
- return d;
- }
-
- const char clz_tab[] =
- {
- 32,31,30,30,29,29,29,29,28,28,28,28,28,28,28,28,
- 27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,
- 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,
- 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,
- 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
- 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
- 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
- 25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
- 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
- 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
- 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
- 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
- 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
- 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
- 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
- 24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
- };
-
- const char ctz_tab[] =
- {
- 8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- 4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
- };
-
- const char ff1_tab[] =
- {
- 32,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
- 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- };
-