summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/i386/include/arch/romcc_io.h12
-rw-r--r--src/mainboard/amd/solo/auto.c57
-rw-r--r--src/northbridge/amd/amdk8/coherent_ht.c8
-rw-r--r--src/northbridge/amd/amdk8/raminit.c202
-rw-r--r--src/southbridge/amd/amd8111/amd8111_early_smbus.c2
-rw-r--r--util/romcc/Makefile1
-rw-r--r--util/romcc/romcc.c192
-rw-r--r--util/romcc/tests/simple_test33.c41
8 files changed, 447 insertions, 68 deletions
diff --git a/src/arch/i386/include/arch/romcc_io.h b/src/arch/i386/include/arch/romcc_io.h
index 7d3d50e39c..d67b3b60d6 100644
--- a/src/arch/i386/include/arch/romcc_io.h
+++ b/src/arch/i386/include/arch/romcc_io.h
@@ -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)
diff --git a/src/mainboard/amd/solo/auto.c b/src/mainboard/amd/solo/auto.c
index e8e3976ef2..f61b794256 100644
--- a/src/mainboard/amd/solo/auto.c
+++ b/src/mainboard/amd/solo/auto.c
@@ -11,6 +11,13 @@
#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);
}
}
diff --git a/src/northbridge/amd/amdk8/coherent_ht.c b/src/northbridge/amd/amdk8/coherent_ht.c
index 68d8b39e36..fe2f3723ad 100644
--- a/src/northbridge/amd/amdk8/coherent_ht.c
+++ b/src/northbridge/amd/amdk8/coherent_ht.c
@@ -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[] = {
diff --git a/src/northbridge/amd/amdk8/raminit.c b/src/northbridge/amd/amdk8/raminit.c
index 6c757c993e..54ca82e65a 100644
--- a/src/northbridge/amd/amdk8/raminit.c
+++ b/src/northbridge/amd/amdk8/raminit.c
@@ -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
diff --git a/src/southbridge/amd/amd8111/amd8111_early_smbus.c b/src/southbridge/amd/amd8111/amd8111_early_smbus.c
index 6b6d9ad144..33f558896e 100644
--- a/src/southbridge/amd/amd8111/amd8111_early_smbus.c
+++ b/src/southbridge/amd/amd8111/amd8111_early_smbus.c
@@ -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);
diff --git a/util/romcc/Makefile b/util/romcc/Makefile
index be2d031055..9722ca3fc7 100644
--- a/util/romcc/Makefile
+++ b/util/romcc/Makefile
@@ -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 \
diff --git a/util/romcc/romcc.c b/util/romcc/romcc.c
index 7aea1b40b8..24fe206b1b 100644
--- a/util/romcc/romcc.c
+++ b/util/romcc/romcc.c
@@ -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
index 0000000000..4caaa3a9e5
--- /dev/null
+++ b/util/romcc/tests/simple_test33.c
@@ -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;
+}
+
+