- A new test case for romcc
authorEric Biederman <ebiederm@xmission.com>
Wed, 18 Jun 2003 11:03:18 +0000 (11:03 +0000)
committerEric Biederman <ebiederm@xmission.com>
Wed, 18 Jun 2003 11:03:18 +0000 (11:03 +0000)
- Minor romcc fixes
- In smbus_wail_until_done a romcc glitch with || in romcc where it likes
  to run out of registers.  Use | to be explicit that I don't need the short
  circuiting behavior.
- Remove unused #defines from coherent_ht.c
- Update the test in auto.c to 512M
- Add definition of log2 to romcc_io.h
- Implement SPD memory sizing in raminit.c
- Reduce the number of memory devices back 2 to for the SOLO board.

git-svn-id: svn://svn.coreboot.org/coreboot/trunk@883 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

src/arch/i386/include/arch/romcc_io.h
src/mainboard/amd/solo/auto.c
src/northbridge/amd/amdk8/coherent_ht.c
src/northbridge/amd/amdk8/raminit.c
src/southbridge/amd/amd8111/amd8111_early_smbus.c
util/romcc/Makefile
util/romcc/romcc.c
util/romcc/tests/simple_test33.c [new file with mode: 0644]

index 7d3d50e39cf6bd73d2ba0667fef11a858cbd5613..d67b3b60d631747482263e9af8459dd32dce4bd3 100644 (file)
@@ -35,6 +35,18 @@ static void hlt(void)
        __builtin_hlt();
 }
 
+int log2(int value)
+{
+       /* __builtin_bsr is a exactly equivalent to the x86 machine
+        * instruction with the exception that it returns -1  
+        * when the value presented to it is zero.
+        * Otherwise __builtin_bsr returns the zero based index of
+        * the highest bit set.
+        */
+       return __builtin_bsr(value);
+}
+
+
 typedef __builtin_msr_t msr_t;
 
 static msr_t rdmsr(unsigned long index)
index e8e3976ef2f725e6b79a908fe3d13db7ca6d5d4f..f61b79425619eea2b525d8096a970ba589de3273 100644 (file)
 #include "northbridge/amd/amdk8/coherent_ht.c"
 #include "sdram/generic_sdram.c"
 
+#define NODE_ID                0x60
+#define        HT_INIT_CONTROL 0x6c
+
+#define HTIC_ColdR_Detect  (1<<4)
+#define HTIC_BIOSR_Detect  (1<<5)
+#define HTIC_INIT_Detect   (1<<6)
+
 static int boot_cpu(void)
 {
        volatile unsigned long *local_apic;
@@ -59,6 +66,16 @@ static int cpu_init_detected(void)
 }
 
 
+static void print_debug_pci_dev(unsigned dev)
+{
+       print_debug("PCI: ");
+       print_debug_hex8((dev >> 16) & 0xff);
+       print_debug_char(':');
+       print_debug_hex8((dev >> 11) & 0x1f);
+       print_debug_char('.');
+       print_debug_hex8((dev >> 8) & 7);
+}
+
 static void print_pci_devices(void)
 {
        device_t dev;
@@ -72,15 +89,33 @@ static void print_pci_devices(void)
                        (((id >> 16) & 0xffff) == 0x0000)) {
                        continue;
                }
-               print_debug("PCI: 00:");
-               print_debug_hex8(dev >> 11);
-               print_debug_char('.');
-               print_debug_hex8((dev >> 8) & 7);
+               print_debug_pci_dev(dev);
                print_debug("\r\n");
        }
 }
 
 
+static void dump_pci_device(unsigned dev)
+{
+       int i;
+       print_debug_pci_dev(dev);
+       print_debug("\r\n");
+       
+       for(i = 0; i <= 255; i++) {
+               unsigned char val;
+               if ((i & 0x0f) == 0) {
+                       print_debug_hex8(i);
+                       print_debug_char(':');
+               }
+               val = pci_read_config8(dev, i);
+               print_debug_char(' ');
+               print_debug_hex8(val);
+               if ((i & 0x0f) == 0x0f) {
+                       print_debug("\r\n");
+               }
+       }
+}
+
 static void dump_spd_registers(void)
 {
        unsigned device;
@@ -112,6 +147,7 @@ static void dump_spd_registers(void)
        }
 }
 
+
 static void main(void)
 {
        uart_init();
@@ -132,7 +168,16 @@ static void main(void)
                sdram_initialize();
 
                dump_spd_registers();
-               /* Check the first 8M */
-               ram_check(0x00100000, 0x00800000);
+               dump_pci_device(PCI_DEV(0, 0x18, 2));
+               
+               /* Check the first 512M */
+               msr_t msr;
+               msr = rdmsr(TOP_MEM);
+               print_debug("TOP_MEM: ");
+               print_debug_hex32(msr.hi);
+               print_debug_hex32(msr.lo);
+               print_debug("\r\n");
+#warning "FIXME if I pass msr.lo somehow I get the value 0x00000030 as stop in ram_check"
+               ram_check(0x00000000, 0x20000000);
        }
 }
index 68d8b39e365133ffaff3b6bfbe717431ca308d3f..fe2f3723adf93f9b206f1e1a63a4a6bc2f419be0 100644 (file)
@@ -1,11 +1,3 @@
-#define COHERENT_AMD_SOLO    1 /* AMD Solo motherboard */
-#define COHERENT_ARIMA_HDAMA 2 /* Arima HDAMA motherboard */
-
-#ifndef COHERENT_CONFIG
-#define COHERENT_CONFIG COHERENT_AMD_SOLO
-#endif
-
-
 static void setup_coherent_ht_domain(void)
 {
        static const unsigned int register_values[] = {
index 6c757c993e0eeea00ba19bd1d24ca1728493a22f..54ca82e65abc8320d39edd651112851cf188e839 100644 (file)
@@ -1,3 +1,4 @@
+#include <cpu/k8/mtrr.h>
 #define MEMORY_SUSE_SOLO  1 /* SuSE Solo configuration */
 #define MEMORY_LNXI_SOLO  2 /* LNXI Solo configuration */
 #define MEMORY_LNXI_HDAMA 3 /* LNXI HDAMA configuration */
@@ -1112,6 +1113,192 @@ static void sdram_set_registers(void)
        print_debug("done.\r\n");
 }
 
+
+struct dimm_size {
+       unsigned long side1;
+       unsigned long side2;
+};
+static struct dimm_size spd_get_dimm_size(unsigned device)
+{
+       /* Calculate the log base 2 size of a DIMM in bits */
+       struct dimm_size sz;
+       int value, low;
+       sz.side1 = 0;
+       sz.side2 = 0;
+
+       /* Note it might be easier to use byte 31 here, it has the DIMM size as
+        * a multiple of 4MB.  The way we do it now we can size both
+        * sides of an assymetric dimm.
+        */
+       value = smbus_read_byte(device, 3);     /* rows */
+       if (value < 0) return sz;
+       sz.side1 += value & 0xf;
+
+       value = smbus_read_byte(device, 4);     /* columns */
+       if (value < 0) return sz;
+       sz.side1 += value & 0xf;
+
+       value = smbus_read_byte(device, 17);    /* banks */
+       if (value < 0) return sz;
+       sz.side1 += log2(value & 0xff);
+
+       /* Get the module data widht and convert it to a power of two */
+       value = smbus_read_byte(device, 7);     /* (high byte) */
+       if (value < 0) return sz;
+       value &= 0xff;
+       value <<= 8;
+       
+       low = smbus_read_byte(device, 6);       /* (low byte) */
+       if (low < 0) return sz;
+       value = value | (low & 0xff);
+       sz.side1 += log2(value);
+
+       /* side 2 */
+       value = smbus_read_byte(device, 5);     /* number of physical banks */
+       if (value <= 1) return sz;
+
+       /* Start with the symmetrical case */
+       sz.side2 = sz.side1;
+
+       value = smbus_read_byte(device, 3);     /* rows */
+       if (value < 0) return sz;
+       if ((value & 0xf0) == 0) return sz;     /* If symmetrical we are done */
+       sz.side2 -= (value & 0x0f);             /* Subtract out rows on side 1 */
+       sz.side2 += ((value >> 4) & 0x0f);      /* Add in rows on side 2 */
+
+       value = smbus_read_byte(device, 4);     /* columns */
+       if (value < 0) return sz;
+       sz.side2 -= (value & 0x0f);             /* Subtract out columns on side 1 */
+       sz.side2 += ((value >> 4) & 0x0f);      /* Add in columsn on side 2 */
+       return sz;
+}
+
+static unsigned spd_to_dimm_side0(unsigned device)
+{
+       return (device - SMBUS_MEM_DEVICE_START) << 1;
+}
+
+static unsigned spd_to_dimm_side1(unsigned device)
+{
+       return ((device - SMBUS_MEM_DEVICE_START) << 1) + 1;
+}
+
+static void set_dimm_size(unsigned long size, unsigned index)
+{
+       unsigned value = 0;
+       /* Make certain the dimm is at least 32MB */
+       if (size >= (25 + 3)) {
+               /* Place the dimm size in 32 MB quantities in the bits 31 - 21.
+                * The initialize dimm size is in bits.
+                * Set the base enable bit0.
+                */
+               value = (1 << ((size - (25 + 3)) + 21)) | 1;
+       }
+       /* Set the appropriate DIMM base address register */
+       pci_write_config32(PCI_DEV(0, 0x18, 2), 0x40 + (index << 2), value);
+}
+
+static void spd_set_ram_size(void)
+{
+       unsigned device;
+       for(device = SMBUS_MEM_DEVICE_START; 
+               device <= SMBUS_MEM_DEVICE_END;
+               device += SMBUS_MEM_DEVICE_INC) 
+       {
+               struct dimm_size sz;
+               sz = spd_get_dimm_size(device);
+               set_dimm_size(sz.side1, spd_to_dimm_side0(device));
+               set_dimm_size(sz.side2, spd_to_dimm_side1(device));
+       }
+}
+
+static void set_top_mem(unsigned tom_k)
+{
+       /* Error if I don't have memory */
+       if (!tom_k) {
+               die("No memory");
+       }
+       /* Now set top of memory */
+       msr_t msr;
+       msr.lo = (tom_k & 0x003fffff) << 10;
+       msr.hi = (tom_k & 0xffc00000) >> 22;
+       wrmsr(TOP_MEM, msr);
+
+#if 1
+       /* And report the amount of memory.  (I run out of registers if i don't) */
+       print_debug("RAM: 0x");
+       print_debug_hex32(tom_k);
+       print_debug(" KB\r\n");
+#endif
+}
+
+static void order_dimms(void)
+{
+       unsigned long tom;
+       unsigned mask;
+       unsigned index;
+
+       /* Remember which registers we have used in the high 8 bits of tom */
+       tom = 0;
+       for(;;) {
+               /* Find the largest remaining canidate */
+               unsigned canidate;
+               uint32_t csbase, csmask;
+               unsigned size;
+               csbase = 0;
+               canidate = 0;
+               for(index = 0; index < 8; index++) {
+                       uint32_t value;
+                       value = pci_read_config32(PCI_DEV(0, 0x18, 2), 0x40 + (index << 2));
+
+                       /* Is it enabled? */
+                       if (!(value & 1)) {
+                               continue;
+                       }
+                       
+                       /* Is it greater? */
+                       if (value <= csbase) {
+                               continue;
+                       }
+                       
+                       /* Has it already been selected */
+                       if (tom & (1 << (index + 24))) {
+                               continue;
+                       }
+                       /* I have a new canidate */
+                       csbase = value;
+                       canidate = index;
+               }
+               /* See if I have found a new canidate */
+               if (csbase == 0) {
+                       break;
+               }
+
+               /* Remember I have used this register */
+               tom |= (1 << (canidate + 24));
+
+               /* Remember the dimm size */
+               size = csbase >> 21;
+
+               /* Recompute the cs base register value */
+               csbase = (tom << 21) | 1;
+
+               /* Increment the top of memory */
+               tom += size;
+
+               /* Compute the memory mask */
+               csmask = ((size -1) << 21);
+               csmask |= 0xfe00;               /* For now don't optimize */
+
+               /* Write the new base register */
+               pci_write_config32(PCI_DEV(0, 0x18, 2), 0x40 + (canidate << 2), csbase);
+               pci_write_config32(PCI_DEV(0, 0x18, 2), 0x60 + (canidate << 2), csmask);
+               
+       }
+       set_top_mem((tom & ~0xff000000) << 15);
+}
+
+
 #define DRAM_CONFIG_LOW 0x90
 #define  DCL_DLL_Disable   (1<<0)
 #define  DCL_D_DRV         (1<<1)
@@ -1122,20 +1309,21 @@ static void sdram_set_registers(void)
 #define  DCL_MemClrStatus  (1<<11)
 #define  DCL_DimmEcEn      (1<<17)
 
-#define NODE_ID                0x60
-#define        HT_INIT_CONTROL 0x6c
 
-#define HTIC_ColdR_Detect  (1<<4)
-#define HTIC_BIOSR_Detect  (1<<5)
-#define HTIC_INIT_Detect   (1<<6)
-
-static void sdram_set_spd_registers(void) 
+static void spd_set_ecc_mode(void)
 {
        unsigned long dcl;
        dcl = pci_read_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW);
        /* Until I know what is going on disable ECC support */
        dcl &= ~DCL_DimmEcEn;
        pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW, dcl);
+
+}
+static void sdram_set_spd_registers(void) 
+{
+       spd_set_ram_size();
+       spd_set_ecc_mode();
+       order_dimms();
 }
 
 #define TIMEOUT_LOOPS 300000
index 6b6d9ad14498e49b98b228383f8f98d3b480b06f..33f558896e7e8047909a6aeca09095bc9c70ba9d 100644 (file)
@@ -53,7 +53,7 @@ static int smbus_wait_until_done(void)
                smbus_delay();
                
                val = inw(SMBUS_IO_BASE + SMBGSTATUS);
-               if (((val & 0x8) == 0) || ((val & 0x437) != 0)) {
+               if (((val & 0x8) == 0) | ((val & 0x437) != 0)) {
                        break;
                }
        } while(--loops);
index be2d031055a63b736615a270de9252669d0732dc..9722ca3fc7c7c375a2f1d1b842659d7bbc7f2e98 100644 (file)
@@ -51,6 +51,7 @@ TESTS=\
        simple_test30.c \
        simple_test31.c \
        simple_test32.c \
+       simple_test33.c \
        raminit_test.c \
        raminit_test2.c \
        raminit_test3.c \
index 7aea1b40b84f5106bbb6eb8e45e8252fecca6e8e..24fe206b1b4f44c08415e727fb6c9864d325c97b 100644 (file)
@@ -1428,6 +1428,10 @@ static struct triple *pre_triple(struct compile_state *state,
 {
        struct block *block;
        struct triple *ret;
+       /* If I am an OP_PIECE jump to the real instruction */
+       if (base->op == OP_PIECE) {
+               base = MISC(base, 0);
+       }
        block = block_of_triple(state, base);
        ret = build_triple(state, op, type, left, right, 
                base->filename, base->line, base->col);
@@ -1447,6 +1451,17 @@ static struct triple *post_triple(struct compile_state *state,
 {
        struct block *block;
        struct triple *ret;
+       int zlhs;
+       /* If I am an OP_PIECE jump to the real instruction */
+       if (base->op == OP_PIECE) {
+               base = MISC(base, 0);
+       }
+       /* If I have a left hand side skip over it */
+       zlhs = TRIPLE_LHS(base->sizes);
+       if (zlhs && (base->op != OP_WRITE) && (base->op != OP_STORE)) {
+               base = LHS(base, zlhs - 1);
+       }
+
        block = block_of_triple(state, base);
        ret = build_triple(state, op, type, left, right, 
                base->filename, base->line, base->col);
@@ -1491,7 +1506,7 @@ static void display_triple(FILE *fp, struct triple *ins)
                        fprintf(fp, " %-10p", ins->param[i]);
                }
                for(; i < 2; i++) {
-                       printf("           ");
+                       fprintf(fp, "           ");
                }
                fprintf(fp, " @ %s:%d.%d\n", 
                        ins->filename, ins->line, ins->col);
@@ -12248,6 +12263,7 @@ struct least_conflict {
        struct triple *ins;
        struct triple_reg_set *live;
        size_t count;
+       int constraints;
 };
 static void least_conflict(struct compile_state *state,
        struct reg_block *blocks, struct triple_reg_set *live,
@@ -12257,19 +12273,13 @@ static void least_conflict(struct compile_state *state,
        struct live_range_edge *edge;
        struct triple_reg_set *set;
        size_t count;
-
-#if 0
-#define HI() fprintf(stderr, "%-10p(%-15s) %d\n", ins, tops(ins->op), __LINE__)
-#else
-#define HI()
-#endif
+       int constraints;
 
 #warning "FIXME handle instructions with left hand sides..."
        /* Only instructions that introduce a new definition
         * can be the conflict instruction.
         */
        if (!triple_is_def(state, ins)) {
-HI();
                return;
        }
 
@@ -12280,22 +12290,25 @@ HI();
        for(set = live; set; set = set->next) {
                struct live_range *lr;
                lr = conflict->rstate->lrd[set->member->id].lr;
+               /* Ignore it if there cannot be an edge between these two nodes */
+               if (!arch_regcm_intersect(conflict->ref_range->classes, lr->classes)) {
+                       continue;
+               }
                for(edge = conflict->ref_range->edges; edge; edge = edge->next) {
                        if (edge->node == lr) {
                                break;
                        }
                }
                if (!edge && (lr != conflict->ref_range)) {
-HI();
                        return;
                }
                count++;
        }
        if (count <= 1) {
-HI();
                return;
        }
 
+#if 0
        /* See if there is an uncolored member in this subset. 
         */
         for(set = live; set; set = set->next) {
@@ -12306,11 +12319,79 @@ HI();
                }
        }
        if (!set && (conflict->ref_range != REG_UNSET)) {
-HI();
+               return;
+       }
+#endif
+
+       /* See if any of the live registers are constrained,
+        * if not it won't be productive to pick this as
+        * a conflict instruction.
+        */
+       constraints = 0;
+       for(set = live; set; set = set->next) {
+               struct triple_set *uset;
+               struct reg_info info;
+               unsigned classes;
+               unsigned cur_size, size;
+               /* Skip this instruction */
+               if (set->member == ins) {
+                       continue;
+               }
+               /* Find how many registers this value can potentially 
+                * be assigned to.
+                */
+               classes = arch_type_to_regcm(state, set->member->type);
+               size = regc_max_size(state, classes);
+               
+               /* Find how many registers we allow this value to
+                * be assigned to.
+                */
+               info = arch_reg_lhs(state, set->member, 0);
+               
+               /* If the value does not live in a register it
+                * isn't constrained.
+                */
+               if (info.reg == REG_UNNEEDED) {
+                       continue;
+               }
+               
+               if ((info.reg == REG_UNSET) || (info.reg >= MAX_REGISTERS)) {
+                       cur_size = regc_max_size(state, info.regcm);
+               } else {
+                       cur_size = 1;
+               }
+
+               /* If there is no difference between potential and
+                * actual register count there is not a constraint
+                */
+               if (cur_size >= size) {
+                       continue;
+               }
+               
+               /* If this live_range feeds into conflict->inds
+                * it isn't a constraint we can relieve.
+                */
+               for(uset = set->member->use; uset; uset = uset->next) {
+                       if (uset->member == ins) {
+                               break;
+                       }
+               }
+               if (uset) {
+                       continue;
+               }
+               constraints = 1;
+               break;
+       }
+       /* Don't drop canidates with constraints */
+       if (conflict->constraints && !constraints) {
                return;
        }
 
 
+#if 0
+       fprintf(stderr, "conflict ins? %p %s count: %d constraints: %d\n",
+               ins, tops(ins->op), count, constraints);
+#endif
        /* Find the instruction with the largest possible subset of
         * conflict ranges and that dominates any other instruction
         * with an equal sized set of conflicting ranges.
@@ -12322,6 +12403,7 @@ HI();
                /* Remember the canidate instruction */
                conflict->ins = ins;
                conflict->count = count;
+               conflict->constraints = constraints;
                /* Free the old collection of live registers */
                for(set = conflict->live; set; set = next) {
                        next = set->next;
@@ -12353,7 +12435,6 @@ HI();
                        ;
                }
        }
-HI();
        return;
 }
 
@@ -12362,12 +12443,6 @@ static void find_range_conflict(struct compile_state *state,
        struct least_conflict *conflict)
 {
 
-#if 0
-       static void verify_blocks(struct compile_state *stae);
-       verify_blocks(state);
-       print_blocks(state, stderr);
-       print_dominators(state, stderr);
-#endif
        /* there are 3 kinds ways conflicts can occure.
         * 1) the life time of 2 values simply overlap.
         * 2) the 2 values feed into the same instruction.
@@ -12387,37 +12462,25 @@ static void find_range_conflict(struct compile_state *state,
         *    is at or after the instruction.
         */
        memset(conflict, 0, sizeof(*conflict));
-       conflict->rstate    = rstate;
-       conflict->ref_range = ref_range;
-       conflict->ins       = 0;
-       conflict->count     = 0;
-       conflict->live      = 0;
+       conflict->rstate      = rstate;
+       conflict->ref_range   = ref_range;
+       conflict->ins         = 0;
+       conflict->live        = 0;
+       conflict->count       = 0;
+       conflict->constraints = 0;
        walk_variable_lifetimes(state, rstate->blocks, least_conflict, conflict);
 
        if (!conflict->ins) {
-               struct live_range_edge *edge;
-               struct live_range_def *lrd;
-               fprintf(stderr, "edges:\n");
-               for(edge = ref_range->edges; edge; edge = edge->next) {
-                       lrd = edge->node->defs;
-                       do {
-                               fprintf(stderr, " %-10p(%s)", lrd->def, tops(lrd->def->op));
-                               lrd = lrd->next;
-                       } while(lrd != edge->node->defs);
-                       fprintf(stderr, "|\n");
-               }
-               fprintf(stderr, "range:\n");
-               lrd = ref_range->defs;
-               do {
-                       fprintf(stderr, " %-10p(%s)", lrd->def, tops(lrd->def->op));
-                       lrd = lrd->next;
-               } while(lrd != ref_range->defs);
-               fprintf(stderr,"\n");
                internal_error(state, ref_range->defs->def, "No conflict ins?");
        }
        if (!conflict->live) {
                internal_error(state, ref_range->defs->def, "No conflict live?");
        }
+#if 0
+       fprintf(stderr, "conflict ins: %p %s count: %d constraints: %d\n", 
+               conflict->ins, tops(conflict->ins->op),
+               conflict->count, conflict->constraints);
+#endif
        return;
 }
 
@@ -12452,6 +12515,13 @@ static struct triple *split_constrained_range(struct compile_state *state,
                 * be assigned to.
                 */
                info = arch_reg_lhs(state, cset->member, 0);
+
+               /* If the register doesn't need a register 
+                * splitting it can't help.
+                */
+               if (info.reg == REG_UNNEEDED) {
+                       continue;
+               }
 #warning "FIXME do I need a call to arch_reg_rhs around here somewhere?"
                if ((info.reg == REG_UNSET) || (info.reg >= MAX_REGISTERS)) {
                        cur_size = regc_max_size(state, info.regcm);
@@ -12497,6 +12567,10 @@ static int split_ranges(
 {
        struct triple *new;
 
+#if 0
+       fprintf(stderr, "split_ranges %d %s %p\n", 
+               rstate->passes, tops(range->defs->def->op), range->defs->def);
+#endif
        if ((range->color == REG_UNNEEDED) ||
                (rstate->passes >= rstate->max_passes)) {
                return 0;
@@ -12506,6 +12580,9 @@ static int split_ranges(
        if (arch_select_free_register(state, used, range->classes) == REG_UNSET) {
                struct least_conflict conflict;
 
+#if 0
+       fprintf(stderr, "find_range_conflict\n");
+#endif
                /* Find where in the set of registers the conflict
                 * actually occurs.
                 */
@@ -12528,6 +12605,11 @@ static int split_ranges(
                 *
                 */
 #warning "WISHLIST implement live range splitting..."
+#if 0
+                       print_blocks(state, stderr);
+                       print_dominators(state, stderr);
+
+#endif
                        return 0;
                }
        }
@@ -12536,7 +12618,13 @@ static int split_ranges(
                new->id = rstate->defs;
                rstate->defs++;
 #if 0
-               fprintf(stderr, "new: %p\n", new);
+               fprintf(stderr, "new: %p old: %s %p\n", 
+                       new, tops(RHS(new, 0)->op), RHS(new, 0));
+#endif
+#if 0
+               print_blocks(state, stderr);
+               print_dominators(state, stderr);
+
 #endif
                return 1;
        }
@@ -12717,17 +12805,29 @@ static int select_free_color(struct compile_state *state,
                        arch_select_free_register(state, used, range->classes);
        }
        if (range->color == REG_UNSET) {
+               struct live_range_def *lrd;
                int i;
                if (split_ranges(state, rstate, used, range)) {
                        return 0;
                }
                for(edge = range->edges; edge; edge = edge->next) {
-                       if (edge->node->color == REG_UNSET) {
-                               continue;
-                       }
-                       warning(state, edge->node->defs->def, "reg %s", 
+                       warning(state, edge->node->defs->def, "edge reg %s",
                                arch_reg_str(edge->node->color));
+                       lrd = edge->node->defs;
+                       do {
+                               warning(state, lrd->def, " %s",
+                                       tops(lrd->def->op));
+                               lrd = lrd->next;
+                       } while(lrd != edge->node->defs);
                }
+               warning(state, range->defs->def, "range: ");
+               lrd = range->defs;
+               do {
+                       warning(state, lrd->def, " %s",
+                               tops(lrd->def->op));
+                       lrd = lrd->next;
+               } while(lrd != range->defs);
+                       
                warning(state, range->defs->def, "classes: %x",
                        range->classes);
                for(i = 0; i < MAX_REGISTERS; i++) {
diff --git a/util/romcc/tests/simple_test33.c b/util/romcc/tests/simple_test33.c
new file mode 100644 (file)
index 0000000..4caaa3a
--- /dev/null
@@ -0,0 +1,41 @@
+static void main(void)
+{
+       unsigned long loops0, loops1, loops2;
+       unsigned long accum;
+
+       accum = 0;
+
+       loops0 = 10;
+       do {
+               unsigned short val;
+               val = __builtin_inw(0x10e0);
+               if (((val & 0x08) == 0)  || (val == 1)) {
+                       break;
+               }
+       } while(--loops0);
+       if (loops0 < 0) return;
+       accum += loops0;
+
+
+       loops1 = 20;
+       do {
+               unsigned short val;
+               val = __builtin_inw(0x10e0);
+               if (((val & 0x08) == 0)  || (val == 1)) {
+                       break;
+               }
+       } while(--loops1);
+
+       loops2 = 30;
+       do {
+               unsigned short val;
+               val = __builtin_inw(0x10e0);
+               if (((val & 0x08) == 0)  || (val == 1)) {
+                       break;
+               }
+       } while(--loops2);
+
+       accum += loops1 + loops0;
+}
+
+