- A new test case for romcc
- 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
This commit is contained in:
parent
99acb49cf7
commit
d3283ec05f
|
@ -35,6 +35,18 @@ static void hlt(void)
|
||||||
__builtin_hlt();
|
__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;
|
typedef __builtin_msr_t msr_t;
|
||||||
|
|
||||||
static msr_t rdmsr(unsigned long index)
|
static msr_t rdmsr(unsigned long index)
|
||||||
|
|
|
@ -11,6 +11,13 @@
|
||||||
#include "northbridge/amd/amdk8/coherent_ht.c"
|
#include "northbridge/amd/amdk8/coherent_ht.c"
|
||||||
#include "sdram/generic_sdram.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)
|
static int boot_cpu(void)
|
||||||
{
|
{
|
||||||
volatile unsigned long *local_apic;
|
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)
|
static void print_pci_devices(void)
|
||||||
{
|
{
|
||||||
device_t dev;
|
device_t dev;
|
||||||
|
@ -72,15 +89,33 @@ static void print_pci_devices(void)
|
||||||
(((id >> 16) & 0xffff) == 0x0000)) {
|
(((id >> 16) & 0xffff) == 0x0000)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
print_debug("PCI: 00:");
|
print_debug_pci_dev(dev);
|
||||||
print_debug_hex8(dev >> 11);
|
|
||||||
print_debug_char('.');
|
|
||||||
print_debug_hex8((dev >> 8) & 7);
|
|
||||||
print_debug("\r\n");
|
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)
|
static void dump_spd_registers(void)
|
||||||
{
|
{
|
||||||
unsigned device;
|
unsigned device;
|
||||||
|
@ -112,6 +147,7 @@ static void dump_spd_registers(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void main(void)
|
static void main(void)
|
||||||
{
|
{
|
||||||
uart_init();
|
uart_init();
|
||||||
|
@ -132,7 +168,16 @@ static void main(void)
|
||||||
sdram_initialize();
|
sdram_initialize();
|
||||||
|
|
||||||
dump_spd_registers();
|
dump_spd_registers();
|
||||||
/* Check the first 8M */
|
dump_pci_device(PCI_DEV(0, 0x18, 2));
|
||||||
ram_check(0x00100000, 0x00800000);
|
|
||||||
|
/* 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 void setup_coherent_ht_domain(void)
|
||||||
{
|
{
|
||||||
static const unsigned int register_values[] = {
|
static const unsigned int register_values[] = {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <cpu/k8/mtrr.h>
|
||||||
#define MEMORY_SUSE_SOLO 1 /* SuSE Solo configuration */
|
#define MEMORY_SUSE_SOLO 1 /* SuSE Solo configuration */
|
||||||
#define MEMORY_LNXI_SOLO 2 /* LNXI Solo configuration */
|
#define MEMORY_LNXI_SOLO 2 /* LNXI Solo configuration */
|
||||||
#define MEMORY_LNXI_HDAMA 3 /* LNXI HDAMA configuration */
|
#define MEMORY_LNXI_HDAMA 3 /* LNXI HDAMA configuration */
|
||||||
|
@ -1112,6 +1113,192 @@ static void sdram_set_registers(void)
|
||||||
print_debug("done.\r\n");
|
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 DRAM_CONFIG_LOW 0x90
|
||||||
#define DCL_DLL_Disable (1<<0)
|
#define DCL_DLL_Disable (1<<0)
|
||||||
#define DCL_D_DRV (1<<1)
|
#define DCL_D_DRV (1<<1)
|
||||||
|
@ -1122,20 +1309,21 @@ static void sdram_set_registers(void)
|
||||||
#define DCL_MemClrStatus (1<<11)
|
#define DCL_MemClrStatus (1<<11)
|
||||||
#define DCL_DimmEcEn (1<<17)
|
#define DCL_DimmEcEn (1<<17)
|
||||||
|
|
||||||
#define NODE_ID 0x60
|
|
||||||
#define HT_INIT_CONTROL 0x6c
|
|
||||||
|
|
||||||
#define HTIC_ColdR_Detect (1<<4)
|
static void spd_set_ecc_mode(void)
|
||||||
#define HTIC_BIOSR_Detect (1<<5)
|
|
||||||
#define HTIC_INIT_Detect (1<<6)
|
|
||||||
|
|
||||||
static void sdram_set_spd_registers(void)
|
|
||||||
{
|
{
|
||||||
unsigned long dcl;
|
unsigned long dcl;
|
||||||
dcl = pci_read_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW);
|
dcl = pci_read_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW);
|
||||||
/* Until I know what is going on disable ECC support */
|
/* Until I know what is going on disable ECC support */
|
||||||
dcl &= ~DCL_DimmEcEn;
|
dcl &= ~DCL_DimmEcEn;
|
||||||
pci_write_config32(PCI_DEV(0, 0x18, 2), DRAM_CONFIG_LOW, dcl);
|
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
|
#define TIMEOUT_LOOPS 300000
|
||||||
|
|
|
@ -53,7 +53,7 @@ static int smbus_wait_until_done(void)
|
||||||
smbus_delay();
|
smbus_delay();
|
||||||
|
|
||||||
val = inw(SMBUS_IO_BASE + SMBGSTATUS);
|
val = inw(SMBUS_IO_BASE + SMBGSTATUS);
|
||||||
if (((val & 0x8) == 0) || ((val & 0x437) != 0)) {
|
if (((val & 0x8) == 0) | ((val & 0x437) != 0)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(--loops);
|
} while(--loops);
|
||||||
|
|
|
@ -51,6 +51,7 @@ TESTS=\
|
||||||
simple_test30.c \
|
simple_test30.c \
|
||||||
simple_test31.c \
|
simple_test31.c \
|
||||||
simple_test32.c \
|
simple_test32.c \
|
||||||
|
simple_test33.c \
|
||||||
raminit_test.c \
|
raminit_test.c \
|
||||||
raminit_test2.c \
|
raminit_test2.c \
|
||||||
raminit_test3.c \
|
raminit_test3.c \
|
||||||
|
|
|
@ -1428,6 +1428,10 @@ static struct triple *pre_triple(struct compile_state *state,
|
||||||
{
|
{
|
||||||
struct block *block;
|
struct block *block;
|
||||||
struct triple *ret;
|
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);
|
block = block_of_triple(state, base);
|
||||||
ret = build_triple(state, op, type, left, right,
|
ret = build_triple(state, op, type, left, right,
|
||||||
base->filename, base->line, base->col);
|
base->filename, base->line, base->col);
|
||||||
|
@ -1447,6 +1451,17 @@ static struct triple *post_triple(struct compile_state *state,
|
||||||
{
|
{
|
||||||
struct block *block;
|
struct block *block;
|
||||||
struct triple *ret;
|
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);
|
block = block_of_triple(state, base);
|
||||||
ret = build_triple(state, op, type, left, right,
|
ret = build_triple(state, op, type, left, right,
|
||||||
base->filename, base->line, base->col);
|
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]);
|
fprintf(fp, " %-10p", ins->param[i]);
|
||||||
}
|
}
|
||||||
for(; i < 2; i++) {
|
for(; i < 2; i++) {
|
||||||
printf(" ");
|
fprintf(fp, " ");
|
||||||
}
|
}
|
||||||
fprintf(fp, " @ %s:%d.%d\n",
|
fprintf(fp, " @ %s:%d.%d\n",
|
||||||
ins->filename, ins->line, ins->col);
|
ins->filename, ins->line, ins->col);
|
||||||
|
@ -12248,6 +12263,7 @@ struct least_conflict {
|
||||||
struct triple *ins;
|
struct triple *ins;
|
||||||
struct triple_reg_set *live;
|
struct triple_reg_set *live;
|
||||||
size_t count;
|
size_t count;
|
||||||
|
int constraints;
|
||||||
};
|
};
|
||||||
static void least_conflict(struct compile_state *state,
|
static void least_conflict(struct compile_state *state,
|
||||||
struct reg_block *blocks, struct triple_reg_set *live,
|
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 live_range_edge *edge;
|
||||||
struct triple_reg_set *set;
|
struct triple_reg_set *set;
|
||||||
size_t count;
|
size_t count;
|
||||||
|
int constraints;
|
||||||
#if 0
|
|
||||||
#define HI() fprintf(stderr, "%-10p(%-15s) %d\n", ins, tops(ins->op), __LINE__)
|
|
||||||
#else
|
|
||||||
#define HI()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#warning "FIXME handle instructions with left hand sides..."
|
#warning "FIXME handle instructions with left hand sides..."
|
||||||
/* Only instructions that introduce a new definition
|
/* Only instructions that introduce a new definition
|
||||||
* can be the conflict instruction.
|
* can be the conflict instruction.
|
||||||
*/
|
*/
|
||||||
if (!triple_is_def(state, ins)) {
|
if (!triple_is_def(state, ins)) {
|
||||||
HI();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12280,22 +12290,25 @@ HI();
|
||||||
for(set = live; set; set = set->next) {
|
for(set = live; set; set = set->next) {
|
||||||
struct live_range *lr;
|
struct live_range *lr;
|
||||||
lr = conflict->rstate->lrd[set->member->id].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) {
|
for(edge = conflict->ref_range->edges; edge; edge = edge->next) {
|
||||||
if (edge->node == lr) {
|
if (edge->node == lr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!edge && (lr != conflict->ref_range)) {
|
if (!edge && (lr != conflict->ref_range)) {
|
||||||
HI();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
if (count <= 1) {
|
if (count <= 1) {
|
||||||
HI();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* See if there is an uncolored member in this subset.
|
/* See if there is an uncolored member in this subset.
|
||||||
*/
|
*/
|
||||||
for(set = live; set; set = set->next) {
|
for(set = live; set; set = set->next) {
|
||||||
|
@ -12306,11 +12319,79 @@ HI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!set && (conflict->ref_range != REG_UNSET)) {
|
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;
|
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
|
/* Find the instruction with the largest possible subset of
|
||||||
* conflict ranges and that dominates any other instruction
|
* conflict ranges and that dominates any other instruction
|
||||||
* with an equal sized set of conflicting ranges.
|
* with an equal sized set of conflicting ranges.
|
||||||
|
@ -12322,6 +12403,7 @@ HI();
|
||||||
/* Remember the canidate instruction */
|
/* Remember the canidate instruction */
|
||||||
conflict->ins = ins;
|
conflict->ins = ins;
|
||||||
conflict->count = count;
|
conflict->count = count;
|
||||||
|
conflict->constraints = constraints;
|
||||||
/* Free the old collection of live registers */
|
/* Free the old collection of live registers */
|
||||||
for(set = conflict->live; set; set = next) {
|
for(set = conflict->live; set; set = next) {
|
||||||
next = set->next;
|
next = set->next;
|
||||||
|
@ -12353,7 +12435,6 @@ HI();
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HI();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12362,12 +12443,6 @@ static void find_range_conflict(struct compile_state *state,
|
||||||
struct least_conflict *conflict)
|
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.
|
/* there are 3 kinds ways conflicts can occure.
|
||||||
* 1) the life time of 2 values simply overlap.
|
* 1) the life time of 2 values simply overlap.
|
||||||
* 2) the 2 values feed into the same instruction.
|
* 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.
|
* is at or after the instruction.
|
||||||
*/
|
*/
|
||||||
memset(conflict, 0, sizeof(*conflict));
|
memset(conflict, 0, sizeof(*conflict));
|
||||||
conflict->rstate = rstate;
|
conflict->rstate = rstate;
|
||||||
conflict->ref_range = ref_range;
|
conflict->ref_range = ref_range;
|
||||||
conflict->ins = 0;
|
conflict->ins = 0;
|
||||||
conflict->count = 0;
|
conflict->live = 0;
|
||||||
conflict->live = 0;
|
conflict->count = 0;
|
||||||
|
conflict->constraints = 0;
|
||||||
walk_variable_lifetimes(state, rstate->blocks, least_conflict, conflict);
|
walk_variable_lifetimes(state, rstate->blocks, least_conflict, conflict);
|
||||||
|
|
||||||
if (!conflict->ins) {
|
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?");
|
internal_error(state, ref_range->defs->def, "No conflict ins?");
|
||||||
}
|
}
|
||||||
if (!conflict->live) {
|
if (!conflict->live) {
|
||||||
internal_error(state, ref_range->defs->def, "No 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12452,6 +12515,13 @@ static struct triple *split_constrained_range(struct compile_state *state,
|
||||||
* be assigned to.
|
* be assigned to.
|
||||||
*/
|
*/
|
||||||
info = arch_reg_lhs(state, cset->member, 0);
|
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?"
|
#warning "FIXME do I need a call to arch_reg_rhs around here somewhere?"
|
||||||
if ((info.reg == REG_UNSET) || (info.reg >= MAX_REGISTERS)) {
|
if ((info.reg == REG_UNSET) || (info.reg >= MAX_REGISTERS)) {
|
||||||
cur_size = regc_max_size(state, info.regcm);
|
cur_size = regc_max_size(state, info.regcm);
|
||||||
|
@ -12497,6 +12567,10 @@ static int split_ranges(
|
||||||
{
|
{
|
||||||
struct triple *new;
|
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) ||
|
if ((range->color == REG_UNNEEDED) ||
|
||||||
(rstate->passes >= rstate->max_passes)) {
|
(rstate->passes >= rstate->max_passes)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -12506,6 +12580,9 @@ static int split_ranges(
|
||||||
if (arch_select_free_register(state, used, range->classes) == REG_UNSET) {
|
if (arch_select_free_register(state, used, range->classes) == REG_UNSET) {
|
||||||
struct least_conflict conflict;
|
struct least_conflict conflict;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
fprintf(stderr, "find_range_conflict\n");
|
||||||
|
#endif
|
||||||
/* Find where in the set of registers the conflict
|
/* Find where in the set of registers the conflict
|
||||||
* actually occurs.
|
* actually occurs.
|
||||||
*/
|
*/
|
||||||
|
@ -12528,6 +12605,11 @@ static int split_ranges(
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#warning "WISHLIST implement live range splitting..."
|
#warning "WISHLIST implement live range splitting..."
|
||||||
|
#if 0
|
||||||
|
print_blocks(state, stderr);
|
||||||
|
print_dominators(state, stderr);
|
||||||
|
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12536,7 +12618,13 @@ static int split_ranges(
|
||||||
new->id = rstate->defs;
|
new->id = rstate->defs;
|
||||||
rstate->defs++;
|
rstate->defs++;
|
||||||
#if 0
|
#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
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -12717,17 +12805,29 @@ static int select_free_color(struct compile_state *state,
|
||||||
arch_select_free_register(state, used, range->classes);
|
arch_select_free_register(state, used, range->classes);
|
||||||
}
|
}
|
||||||
if (range->color == REG_UNSET) {
|
if (range->color == REG_UNSET) {
|
||||||
|
struct live_range_def *lrd;
|
||||||
int i;
|
int i;
|
||||||
if (split_ranges(state, rstate, used, range)) {
|
if (split_ranges(state, rstate, used, range)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for(edge = range->edges; edge; edge = edge->next) {
|
for(edge = range->edges; edge; edge = edge->next) {
|
||||||
if (edge->node->color == REG_UNSET) {
|
warning(state, edge->node->defs->def, "edge reg %s",
|
||||||
continue;
|
|
||||||
}
|
|
||||||
warning(state, edge->node->defs->def, "reg %s",
|
|
||||||
arch_reg_str(edge->node->color));
|
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",
|
warning(state, range->defs->def, "classes: %x",
|
||||||
range->classes);
|
range->classes);
|
||||||
for(i = 0; i < MAX_REGISTERS; i++) {
|
for(i = 0; i < MAX_REGISTERS; i++) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue