- Upgrade to romcc version 0.63
  This includes more test cases
  Lots of small bug fixes
  A built in C preprocessor
  Initial support for not inlining everything
  __attribute__((noinline)) works
  Better command line options and help
  Constants arrays can be read at compile time
  Asm statements that are not volatile will now be removed when their outputs go unused
  Loads and stores that are not volatile will be removed when their values go unused
  The number of FIXMES in the code is finally starting to go down.


git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1582 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
diff --git a/util/romcc/tests/fail_test10.c b/util/romcc/tests/fail_test10.c
new file mode 100644
index 0000000..1993e0e
--- /dev/null
+++ b/util/romcc/tests/fail_test10.c
@@ -0,0 +1,19 @@
+
+
+struct result {
+	int a, b, c, d;
+};
+
+struct big_arg {
+	int a, b;
+};
+static struct result main(int a, int b, struct big_arg d)
+{
+	struct result result;
+	result.a = 1;
+	result.b = 1;
+	result.c = b + 1;
+	result.d = a + 1;
+		
+}
+
diff --git a/util/romcc/tests/fail_test11.c b/util/romcc/tests/fail_test11.c
new file mode 100644
index 0000000..3252060
--- /dev/null
+++ b/util/romcc/tests/fail_test11.c
@@ -0,0 +1,21 @@
+
+
+struct big_arg {
+	int x, y;
+};
+struct result {
+	struct big_arg a;
+	int c, d;
+};
+
+static struct result main(int a, int b, int c, int  d)
+{
+	struct result result;
+	result.a.x = d + 1;
+	result.a.y = c + 1;
+	result.c = b + 1;
+	result.d = a + 1;
+
+	return result;
+}
+
diff --git a/util/romcc/tests/fail_test9.c b/util/romcc/tests/fail_test9.c
new file mode 100644
index 0000000..a24ce9e
--- /dev/null
+++ b/util/romcc/tests/fail_test9.c
@@ -0,0 +1,9 @@
+typedef __builtin_msr_t msr_t;
+
+static msr_t rdmsr(unsigned long index)
+{
+	return __builtin_rdmsr(index);
+}
+
+#warning "romcc should die gracefully here"
+
diff --git a/util/romcc/tests/hello_world1.c b/util/romcc/tests/hello_world1.c
new file mode 100644
index 0000000..6dd80d8
--- /dev/null
+++ b/util/romcc/tests/hello_world1.c
@@ -0,0 +1,128 @@
+void outb(unsigned char value, unsigned short port)
+{
+	__builtin_outb(value, port);
+}
+
+unsigned char inb(unsigned short port)
+{
+	return __builtin_inb(port);
+}
+
+/* Base Address */
+#ifndef TTYS0_BASE
+#define TTYS0_BASE 0x3f8
+#endif
+
+#ifndef TTYS0_BAUD
+#define TTYS0_BAUD 115200
+#endif
+
+#if ((115200%TTYS0_BAUD) != 0)
+#error Bad ttys0 baud rate
+#endif
+
+#if TTYS0_BAUD == 115200
+#define TTYS0_DIV (1)
+#else
+#define TTYS0_DIV	(115200/TTYS0_BAUD)
+#endif
+
+/* Line Control Settings */
+#ifndef TTYS0_LCS
+/* Set 8bit, 1 stop bit, no parity */
+#define TTYS0_LCS	0x3
+#endif
+
+#define UART_LCS	TTYS0_LCS
+
+/* Data */
+#define UART_RBR 0x00
+#define UART_TBR 0x00
+
+/* Control */
+#define UART_IER 0x01
+#define UART_IIR 0x02
+#define UART_FCR 0x02
+#define UART_LCR 0x03
+#define UART_MCR 0x04
+#define UART_DLL 0x00
+#define UART_DLM 0x01
+
+/* Status */
+#define UART_LSR 0x05
+#define UART_MSR 0x06
+#define UART_SCR 0x07
+
+int uart_can_tx_byte(void)
+{
+	return inb(TTYS0_BASE + UART_LSR) & 0x20;
+}
+
+void uart_wait_to_tx_byte(void)
+{
+	while(!uart_can_tx_byte())
+		;
+}
+
+void uart_wait_until_sent(void)
+{
+	while(!(inb(TTYS0_BASE + UART_LSR) & 0x40)) 
+		;
+}
+
+static void uart_tx_byte(unsigned char data)
+{
+	uart_wait_to_tx_byte();
+	outb(data, TTYS0_BASE + UART_TBR);
+	/* Make certain the data clears the fifos */
+	uart_wait_until_sent();
+}
+
+
+void uart_init(void)
+{
+	/* disable interrupts */
+	outb(0x0, TTYS0_BASE + UART_IER);
+	/* enable fifo's */
+	outb(0x01, TTYS0_BASE + UART_FCR);
+	/* Set Baud Rate Divisor to 12 ==> 115200 Baud */
+	outb(0x80 | UART_LCS, TTYS0_BASE + UART_LCR);
+	outb(TTYS0_DIV & 0xFF,   TTYS0_BASE + UART_DLL);
+	outb((TTYS0_DIV >> 8) & 0xFF,    TTYS0_BASE + UART_DLM);
+	outb(UART_LCS, TTYS0_BASE + UART_LCR);
+}
+
+
+void __console_tx_char(unsigned char byte)
+{
+	uart_tx_byte(byte);
+		
+}
+
+void __console_tx_string(char *str)
+{
+	unsigned char ch;
+	while((ch = *str++) != '\0') {
+		__console_tx_char(ch);
+	}
+}
+
+
+void print_debug_char(unsigned char byte) { __console_tx_char(byte); }
+void print_debug(char *str) { __console_tx_string(str); }
+
+void main(void)
+{
+	static const char msg[] = "hello world\r\n";
+	uart_init();
+#if 0
+	print_debug(msg);
+#endif
+#if 1
+	print_debug("hello world\r\n");
+	print_debug("how are you today\r\n");
+#endif
+	while(1) {
+		;
+	}
+}
diff --git a/util/romcc/tests/include/linux_console.h b/util/romcc/tests/include/linux_console.h
new file mode 100644
index 0000000..861c701
--- /dev/null
+++ b/util/romcc/tests/include/linux_console.h
@@ -0,0 +1,136 @@
+#ifndef LINUX_CONSOLE_H
+#define LINUX_CONSOLE_H
+
+#include "linux_syscall.h"
+
+static const char *addr_of_char(unsigned char ch)
+{
+	static const char byte[] = {
+		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+		0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
+		0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 
+		0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+		0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 
+		0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
+		0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+		0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 
+		0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 
+		0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+		0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 
+		0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 
+		0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+		0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 
+		0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 
+		0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+		0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 
+		0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 
+		0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+		0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 
+		0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 
+		0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+		0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 
+		0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+	};
+	return byte + ch;
+}
+
+static void console_tx_byte(unsigned char ch)
+{
+	write(STDOUT_FILENO, addr_of_char(ch), 1);
+}
+
+static inline void console_tx_nibble(unsigned nibble)
+{
+	unsigned char digit;
+	digit = nibble + '0';
+	if (digit > '9') {
+		digit += 39;
+	}
+	console_tx_byte(digit);
+}
+
+static void console_tx_char(unsigned char byte)
+{
+	console_tx_byte(byte);
+}
+
+static void console_tx_hex8(unsigned char value)
+{
+	console_tx_nibble((value >> 4U) & 0x0fU);
+	console_tx_nibble(value & 0x0fU);
+}
+
+static void console_tx_hex16(unsigned short value)
+{
+	console_tx_nibble((value >> 12U) & 0x0FU);
+	console_tx_nibble((value >>  8U) & 0x0FU);
+	console_tx_nibble((value >>  4U) & 0x0FU);
+	console_tx_nibble(value & 0x0FU);
+}
+
+static void console_tx_hex32(unsigned int value)
+{
+	console_tx_nibble((value >> 28U) & 0x0FU);
+	console_tx_nibble((value >> 24U) & 0x0FU);
+	console_tx_nibble((value >> 20U) & 0x0FU);
+	console_tx_nibble((value >> 16U) & 0x0FU);
+	console_tx_nibble((value >> 12U) & 0x0FU);
+	console_tx_nibble((value >>  8U) & 0x0FU);
+	console_tx_nibble((value >>  4U) & 0x0FU);
+	console_tx_nibble(value & 0x0FU);
+}
+
+static void console_tx_string(const char *str)
+{
+	unsigned char ch;
+	while((ch = *str++) != '\0') {
+		console_tx_byte(ch);
+	}
+}
+
+static void print_emerg_char(unsigned char byte) { console_tx_char(byte); }
+static void print_emerg_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_emerg_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_emerg_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_emerg(const char *str) { console_tx_string(str); }
+
+static void print_warn_char(unsigned char byte) { console_tx_char(byte); }
+static void print_warn_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_warn_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_warn_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_warn(const char *str) { console_tx_string(str); }
+
+static void print_info_char(unsigned char byte) { console_tx_char(byte); }
+static void print_info_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_info_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_info_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_info(const char *str) { console_tx_string(str); }
+
+static void print_debug_char(unsigned char byte) { console_tx_char(byte); }
+static void print_debug_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_debug_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_debug_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_debug(const char *str) { console_tx_string(str); }
+
+static void print_spew_char(unsigned char byte) { console_tx_char(byte); }
+static void print_spew_hex8(unsigned char value) { console_tx_hex8(value); }
+static void print_spew_hex16(unsigned short value){ console_tx_hex16(value); }
+static void print_spew_hex32(unsigned int value) { console_tx_hex32(value); }
+static void print_spew(const char *str) { console_tx_string(str); }
+
+static void die(const char *str)
+{
+	print_emerg(str);
+	do {
+		asm volatile (" ");
+	} while(1);
+}
+#endif /* LINUX_CONSOLE_H */
diff --git a/util/romcc/tests/include/linux_syscall.h b/util/romcc/tests/include/linux_syscall.h
new file mode 100644
index 0000000..487095f
--- /dev/null
+++ b/util/romcc/tests/include/linux_syscall.h
@@ -0,0 +1,7 @@
+#ifndef LINUX_SYSCALL_H
+#define LINUX_SYSCALL_H
+
+/* When I support other platforms use #ifdefs here */
+#include "linuxi386_syscall.h"
+
+#endif /* LINUX_SYSCALL_H */
diff --git a/util/romcc/tests/include/linuxi386_syscall.h b/util/romcc/tests/include/linuxi386_syscall.h
new file mode 100644
index 0000000..d202661
--- /dev/null
+++ b/util/romcc/tests/include/linuxi386_syscall.h
@@ -0,0 +1,299 @@
+struct syscall_result {
+	long val;
+	int errno;
+};
+
+static inline struct syscall_result syscall_return(long result)
+{
+	struct syscall_result res;
+	if (((unsigned long)result) >= ((unsigned long)-125)) {
+		res.errno = - result;
+		res.val = -1;
+	} else {
+		res.errno = 0;
+		res.val = result;
+	}
+	return res;
+}
+
+static struct syscall_result syscall0(unsigned long nr)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr));
+	return syscall_return(res);
+}
+
+static struct syscall_result syscall1(unsigned long nr, unsigned long arg1)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr), "b" (arg1));
+	return syscall_return(res);
+	
+}
+
+static struct syscall_result syscall2(unsigned long nr, unsigned long arg1, unsigned long arg2)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr), "b" (arg1), "c" (arg2));
+	return syscall_return(res);
+	
+}
+
+
+static struct syscall_result syscall3(unsigned long nr, unsigned long arg1, unsigned long arg2,
+	unsigned long arg3)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3));
+	return syscall_return(res);
+	
+}
+
+static struct syscall_result syscall4(unsigned long nr, unsigned long arg1, unsigned long arg2,
+	unsigned long arg3, unsigned long arg4)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4));
+	return syscall_return(res);
+	
+}
+
+static struct syscall_result syscall5(unsigned long nr, unsigned long arg1, unsigned long arg2,
+	unsigned long arg3, unsigned long arg4, unsigned long arg5)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3), 
+		"S" (arg4), "D" (arg5));
+	return syscall_return(res);
+	
+}
+
+#define NR_exit                 1
+#define NR_fork                 2
+#define NR_read                 3
+#define NR_write                4
+#define NR_open                 5
+#define NR_close                6
+#define NR_waitpid              7
+#define NR_creat                8
+#define NR_link                 9
+#define NR_unlink              10
+#define NR_execve              11
+#define NR_chdir               12
+#define NR_time                13
+#define NR_mknod               14
+#define NR_chmod               15
+#define NR_lchown              16
+#define NR_break               17
+#define NR_oldstat             18
+#define NR_lseek               19
+#define NR_getpid              20
+#define NR_mount               21
+#define NR_umount              22
+#define NR_setuid              23
+#define NR_getuid              24
+#define NR_stime               25
+#define NR_ptrace              26
+#define NR_alarm               27
+#define NR_oldfstat            28
+#define NR_pause               29
+#define NR_utime               30
+#define NR_stty                31
+#define NR_gtty                32
+#define NR_access              33
+#define NR_nice                34
+#define NR_ftime               35
+#define NR_sync                36
+#define NR_kill                37
+#define NR_rename              38
+#define NR_mkdir               39
+#define NR_rmdir               40
+#define NR_dup                 41
+#define NR_pipe                42
+#define NR_times               43
+#define NR_prof                44
+#define NR_brk                 45
+#define NR_setgid              46
+#define NR_getgid              47
+#define NR_signal              48
+#define NR_geteuid             49
+#define NR_getegid             50
+#define NR_acct                51
+#define NR_umount2             52
+#define NR_lock                53
+#define NR_ioctl               54
+#define NR_fcntl               55
+#define NR_mpx                 56
+#define NR_setpgid             57
+#define NR_ulimit              58
+#define NR_oldolduname         59
+#define NR_umask               60
+#define NR_chroot              61
+#define NR_ustat               62
+#define NR_dup2                63
+#define NR_getppid             64
+#define NR_getpgrp             65
+#define NR_setsid              66
+#define NR_sigaction           67
+#define NR_sgetmask            68
+#define NR_ssetmask            69
+#define NR_setreuid            70
+#define NR_setregid            71
+#define NR_sigsuspend          72
+#define NR_sigpending          73
+#define NR_sethostname         74
+#define NR_setrlimit           75
+#define NR_getrlimit           76
+#define NR_getrusage           77
+#define NR_gettimeofday        78
+#define NR_settimeofday        79
+#define NR_getgroups           80
+#define NR_setgroups           81
+#define NR_select              82
+#define NR_symlink             83
+#define NR_oldlstat            84
+#define NR_readlink            85
+#define NR_uselib              86
+#define NR_swapon              87
+#define NR_reboot              88
+#define NR_readdir             89
+#define NR_mmap                90
+#define NR_munmap              91
+#define NR_truncate            92
+#define NR_ftruncate           93
+#define NR_fchmod              94
+#define NR_fchown              95
+#define NR_getpriority         96
+#define NR_setpriority         97
+#define NR_profil              98
+#define NR_statfs              99
+#define NR_fstatfs            100
+#define NR_ioperm             101
+#define NR_socketcall         102
+#define NR_syslog             103
+#define NR_setitimer          104
+#define NR_getitimer          105
+#define NR_stat               106
+#define NR_lstat              107
+#define NR_fstat              108
+#define NR_olduname           109
+#define NR_iopl               110
+#define NR_vhangup            111
+#define NR_idle               112
+#define NR_vm86old            113
+#define NR_wait4              114
+#define NR_swapoff            115
+#define NR_sysinfo            116
+#define NR_ipc                117
+#define NR_fsync              118
+#define NR_sigreturn          119
+#define NR_clone              120
+#define NR_setdomainname      121
+#define NR_uname              122
+#define NR_modify_ldt         123
+#define NR_adjtimex           124
+#define NR_mprotect           125
+#define NR_sigprocmask        126
+#define NR_create_module      127
+#define NR_init_module        128
+#define NR_delete_module      129
+#define NR_get_kernel_syms    130
+#define NR_quotactl           131
+#define NR_getpgid            132
+#define NR_fchdir             133
+#define NR_bdflush            134
+#define NR_sysfs              135
+#define NR_personality        136
+#define NR_afs_syscall        137 /* Syscall for Andrew File System */
+#define NR_setfsuid           138
+#define NR_setfsgid           139
+#define NR__llseek            140
+#define NR_getdents           141
+#define NR__newselect         142
+#define NR_flock              143
+#define NR_msync              144
+#define NR_readv              145
+#define NR_writev             146
+#define NR_getsid             147
+#define NR_fdatasync          148
+#define NR__sysctl            149
+#define NR_mlock              150
+#define NR_munlock            151
+#define NR_mlockall           152
+#define NR_munlockall         153
+#define NR_sched_setparam             154
+#define NR_sched_getparam             155
+#define NR_sched_setscheduler         156
+#define NR_sched_getscheduler         157
+#define NR_sched_yield                158
+#define NR_sched_get_priority_max     159
+#define NR_sched_get_priority_min     160
+#define NR_sched_rr_get_interval      161
+#define NR_nanosleep          162
+#define NR_mremap             163
+#define NR_setresuid          164
+#define NR_getresuid          165
+#define NR_vm86               166
+#define NR_query_module       167
+#define NR_poll               168
+#define NR_nfsservctl         169
+#define NR_setresgid          170
+#define NR_getresgid          171
+#define NR_prctl              172
+#define NR_rt_sigreturn       173
+#define NR_rt_sigaction       174
+#define NR_rt_sigprocmask     175
+#define NR_rt_sigpending      176
+#define NR_rt_sigtimedwait    177
+#define NR_rt_sigqueueinfo    178
+#define NR_rt_sigsuspend      179
+#define NR_pread              180
+#define NR_pwrite             181
+#define NR_chown              182
+#define NR_getcwd             183
+#define NR_capget             184
+#define NR_capset             185
+#define NR_sigaltstack        186
+#define NR_sendfile           187
+#define NR_getpmsg            188     /* some people actually want streams */
+#define NR_putpmsg            189     /* some people actually want streams */
+#define NR_vfork              190
+
+/* Standard file descriptors */
+#define STDIN_FILENO    0  /* Standard input */
+#define STDOUT_FILENO   1  /* Standard output */
+#define STDERR_FILENO   2  /* Standard error output */
+
+typedef long ssize_t;
+typedef unsigned long size_t;
+
+static ssize_t write(int fd, const void *buf, size_t count)
+{
+	struct syscall_result res;
+	res = syscall3(NR_write, fd, (unsigned long)buf, count);
+	return res.val;
+}
+
+static void _exit(int status)
+{
+	struct syscall_result res;
+	res = syscall1(NR_exit, status);
+}
diff --git a/util/romcc/tests/ldscript.ld b/util/romcc/tests/ldscript.ld
index 97b307f..249ebd5 100644
--- a/util/romcc/tests/ldscript.ld
+++ b/util/romcc/tests/ldscript.ld
@@ -4,6 +4,7 @@
 SECTIONS
 {
 	. = 0x1000;
+	__cpu_reset = 0xdeadbeef;
 	.text . : {
 		. = ALIGN(16);
 		_start = . ;
diff --git a/util/romcc/tests/linux_test10.c b/util/romcc/tests/linux_test10.c
new file mode 100644
index 0000000..ef8c930
--- /dev/null
+++ b/util/romcc/tests/linux_test10.c
@@ -0,0 +1,57 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+struct stuff {
+	signed int   a : 5;
+	signed int   b : 6;
+	signed int   c : 2;
+	unsigned int d : 3;
+};
+
+static void test(void)
+{
+	struct stuff var;
+#if 0
+	int a, b, c, d;
+
+	a = 1;
+	b = 2;
+	c = 3;
+	d = 7;
+
+	var.a = a;
+	var.b = b;
+	var.c = c;
+	var.d = d;
+
+	a = var.a;
+	b = var.b;
+	c = var.c;
+	d = var.d;
+
+	print_debug(" a: ");
+	print_debug_hex32(a);
+	print_debug(" b: ");
+	print_debug_hex32(b);
+	print_debug(" c: ");
+	print_debug_hex32(c);
+	print_debug(" d: ");
+	print_debug_hex32(d);
+#else
+	var.a = 1;
+	var.b = 2;
+	var.c = 3;
+	var.d = 7;
+
+	print_debug(" a: ");
+	print_debug_hex32(var.a);
+	print_debug(" b: ");
+	print_debug_hex32(var.b);
+	print_debug(" c: ");
+	print_debug_hex32(var.c);
+	print_debug(" d: ");
+	print_debug_hex32(var.d);
+#endif
+	print_debug("\n");
+	_exit(0);
+}
diff --git a/util/romcc/tests/linux_test11.c b/util/romcc/tests/linux_test11.c
new file mode 100644
index 0000000..9c1183f
--- /dev/null
+++ b/util/romcc/tests/linux_test11.c
@@ -0,0 +1,11 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+static void test(void)
+{
+	signed char x;
+	x = -1;
+	print_debug_hex32(x);
+	print_debug("\n");
+	_exit(0);
+}
diff --git a/util/romcc/tests/linux_test12.c b/util/romcc/tests/linux_test12.c
new file mode 100644
index 0000000..5503aa0
--- /dev/null
+++ b/util/romcc/tests/linux_test12.c
@@ -0,0 +1,70 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+#define MACRO(hello, hello2) 1
+
+#ifndef A
+#define A 135
+#endif
+#define B A
+#define C B
+#define D C
+#define E D
+#define F E
+#define G F
+#define H G
+#define I H
+
+#define FOO() "hah?\n"
+#define BAR(X) ( X " There\n" )
+#define BAZ(X) #X
+#define SUM(X, Y) ((X) + (Y))
+#define REALLY_SUM(...) SUM(__VA_ARGS__)
+
+
+#define hash_hash #   	/* comment */	 ## #
+#define mkstr(a) # a
+#define in_between(a) mkstr(a)
+#define join(c, d) in_between(c hash_hash d)
+
+#define ECHO(X) X
+#define print_debug(X) ECHO(print_debug(X))
+
+static void test(void)
+{
+	print_debug(FOO());
+	print_debug(BAR("Hi!!"));
+	print_debug(BAZ(This should be shown as a string... "enclosed in quotes") "\n");
+	print_debug("This is a quote\" see\n");
+	print_debug(BAR(BAZ(I)));
+
+	print_debug_hex32(REALLY_SUM(1,2));
+	print_debug("\n");
+
+	print_debug(join(x, y) "\n");
+
+	print_debug("romcc: ");
+	print_debug_hex8(__ROMCC__);
+	print_debug(".");
+	print_debug_hex8(__ROMCC_MINOR__);
+	print_debug("\n");
+
+	print_debug(__FILE__);
+	print_debug(":");
+	print_debug(__func__);
+	print_debug(":");
+	print_debug_hex32(__LINE__);
+	print_debug("\n");
+
+	print_debug("Compiled at: ");
+	print_debug(__DATE__);
+	print_debug(" ");
+	print_debug(__TIME__);
+	print_debug("\n");
+
+	print_debug("Compile time: ");
+	print_debug(__TIME__);
+	print_debug("\n");
+
+	_exit(0);
+}
diff --git a/util/romcc/tests/linux_test13.c b/util/romcc/tests/linux_test13.c
new file mode 100644
index 0000000..83ef239
--- /dev/null
+++ b/util/romcc/tests/linux_test13.c
@@ -0,0 +1,47 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+struct mem_controller {
+	unsigned short channel0[4];
+};
+
+static unsigned int spd_detect_dimms(const struct mem_controller *ctrl)
+{
+        unsigned dimm_mask;
+        int i;
+
+	print_debug("1\n");
+        dimm_mask = 0;
+        for(i = 0; i < 4; i++) {
+                int byte;
+                unsigned device;
+
+		print_debug("2\n");
+                device = ctrl->channel0[i];
+                if (device) {
+			print_debug("3\n");
+                        byte = ctrl->channel0[i] + 2;
+                        if (byte == 7) {
+                                dimm_mask |= (1 << i);
+                        }
+                }
+		print_debug("4\n");
+        }
+	print_debug("5\n");
+        return dimm_mask;
+}
+
+
+static void main(void)
+{
+        static const struct mem_controller cpu[] = {
+                {
+                        .channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 },
+                },
+        };
+	long dimm_mask;
+	print_debug("A\n");
+	dimm_mask = spd_detect_dimms(cpu);
+	print_debug("B\n");
+	_exit(0);	
+}
diff --git a/util/romcc/tests/linux_test5.c b/util/romcc/tests/linux_test5.c
index 55613c2..13093fb 100644
--- a/util/romcc/tests/linux_test5.c
+++ b/util/romcc/tests/linux_test5.c
@@ -1,7 +1,7 @@
 #include "linux_syscall.h"
 #include "linux_console.h"
 
-int log2(int value)
+inline int log2(int value)
 {
 	/* __builtin_bsr is a exactly equivalent to the x86 machine
 	 * instruction with the exception that it returns -1  
diff --git a/util/romcc/tests/linux_test9.c b/util/romcc/tests/linux_test9.c
new file mode 100644
index 0000000..2a900a5
--- /dev/null
+++ b/util/romcc/tests/linux_test9.c
@@ -0,0 +1,13 @@
+#include "linux_syscall.h"
+#include "linux_console.h"
+
+static void test(void)
+{
+	unsigned char i;
+	for(i = 127; i != 5; i++) {
+		print_debug("i: ");
+		print_debug_hex32((unsigned )i);
+		print_debug("\n");
+	}
+	_exit(0);
+}
diff --git a/util/romcc/tests/raminit_test1.c b/util/romcc/tests/raminit_test1.c
new file mode 100644
index 0000000..9b6cf5d
--- /dev/null
+++ b/util/romcc/tests/raminit_test1.c
@@ -0,0 +1,1292 @@
+#define HAVE_STRING_SUPPORT          0
+#define HAVE_CAST_SUPPORT            1
+#define HAVE_STATIC_ARRAY_SUPPORT    1
+#define HAVE_POINTER_SUPPORT         1
+#define HAVE_MACRO_ARG_SUPPORT       0
+
+void outb(unsigned char value, unsigned short port)
+{
+	__builtin_outb(value, port);
+}
+
+void outw(unsigned short value, unsigned short port)
+{
+	__builtin_outw(value, port);
+}
+
+void outl(unsigned int value, unsigned short port)
+{
+	__builtin_outl(value, port);
+}
+
+unsigned char inb(unsigned short port)
+{
+	return __builtin_inb(port);
+}
+
+unsigned char inw(unsigned short port)
+{
+	return __builtin_inw(port);
+}
+
+unsigned char inl(unsigned short port)
+{
+	return __builtin_inl(port);
+}
+
+static unsigned int config_cmd(unsigned char bus, unsigned devfn, unsigned where)
+{
+	return 0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3);
+}
+
+static unsigned char pcibios_read_config_byte(
+	unsigned char bus, unsigned devfn, unsigned where)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	return inb(0xCFC + (where & 3));
+}
+
+static unsigned short pcibios_read_config_word(
+	unsigned char bus, unsigned devfn, unsigned where)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	return inw(0xCFC + (where & 2));
+}
+
+static unsigned int pcibios_read_config_dword(
+	unsigned char bus, unsigned devfn, unsigned where)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	return inl(0xCFC);
+}
+
+
+static void pcibios_write_config_byte(
+	unsigned char bus, unsigned devfn, unsigned where, unsigned char value)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	outb(value, 0xCFC + (where & 3));
+}
+
+static void pcibios_write_config_word(
+	unsigned char bus, unsigned devfn, unsigned where, unsigned short value)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	outw(value, 0xCFC + (where & 2));
+}
+
+static void pcibios_write_config_dword(
+	unsigned char bus, unsigned devfn, unsigned where, unsigned int value)
+{
+	outl(config_cmd(bus, devfn, where), 0xCF8);
+	outl(value, 0xCFC);
+}
+
+/* Base Address */
+#ifndef TTYS0_BASE
+#define TTYS0_BASE 0x3f8
+#endif
+
+#ifndef TTYS0_BAUD
+#define TTYS0_BAUD 115200
+#endif
+
+#if ((115200%TTYS0_BAUD) != 0)
+#error Bad ttys0 baud rate
+#endif
+
+#define TTYS0_DIV	(115200/TTYS0_BAUD)
+
+/* Line Control Settings */
+#ifndef TTYS0_LCS
+/* Set 8bit, 1 stop bit, no parity */
+#define TTYS0_LCS	0x3
+#endif
+
+#define UART_LCS	TTYS0_LCS
+
+/* Data */
+#define UART_RBR 0x00
+#define UART_TBR 0x00
+
+/* Control */
+#define UART_IER 0x01
+#define UART_IIR 0x02
+#define UART_FCR 0x02
+#define UART_LCR 0x03
+#define UART_MCR 0x04
+#define UART_DLL 0x00
+#define UART_DLM 0x01
+
+/* Status */
+#define UART_LSR 0x05
+#define UART_MSR 0x06
+#define UART_SCR 0x07
+
+int uart_can_tx_byte(void)
+{
+	return inb(TTYS0_BASE + UART_LSR) & 0x20;
+}
+
+void uart_wait_to_tx_byte(void)
+{
+	while(!uart_can_tx_byte())
+		;
+}
+
+void uart_wait_until_sent(void)
+{
+	while(!(inb(TTYS0_BASE + UART_LSR) & 0x40)) 
+		;
+}
+
+void uart_tx_byte(unsigned char data)
+{
+	uart_wait_to_tx_byte();
+	outb(data, TTYS0_BASE + UART_TBR);
+	/* Make certain the data clears the fifos */
+	uart_wait_until_sent();
+}
+
+void uart_init(void)
+{
+	/* disable interrupts */
+	outb(0x0, TTYS0_BASE + UART_IER);
+	/* enable fifo's */
+	outb(0x01, TTYS0_BASE + UART_FCR);
+	/* Set Baud Rate Divisor to 12 ==> 115200 Baud */
+	outb(0x80 | UART_LCS, TTYS0_BASE + UART_LCR);
+	outb(TTYS0_DIV & 0xFF,   TTYS0_BASE + UART_DLL);
+	outb((TTYS0_DIV >> 8) & 0xFF,    TTYS0_BASE + UART_DLM);
+	outb(UART_LCS, TTYS0_BASE + UART_LCR);
+}
+
+void __console_tx_char(unsigned char byte)
+{
+	uart_tx_byte(byte);
+}
+void __console_tx_nibble(unsigned nibble)
+{
+	unsigned char digit;
+	digit = nibble + '0';
+	if (digit > '9') {
+		digit += 39;
+	}
+	__console_tx_char(digit);
+}
+void __console_tx_hex8(unsigned char byte)
+{
+	__console_tx_nibble(byte >> 4);
+	__console_tx_nibble(byte & 0x0f);
+}
+
+void __console_tx_hex32(unsigned char value)
+{
+	__console_tx_nibble((value >> 28) & 0x0f);
+	__console_tx_nibble((value >> 24) & 0x0f);
+	__console_tx_nibble((value >> 20) & 0x0f);
+	__console_tx_nibble((value >> 16) & 0x0f);
+	__console_tx_nibble((value >> 12) & 0x0f);
+	__console_tx_nibble((value >>  8) & 0x0f);
+	__console_tx_nibble((value >>  4) & 0x0f);
+	__console_tx_nibble(value & 0x0f);
+}
+
+#if HAVE_STRING_SUPPORT
+void __console_tx_string(char *str)
+{
+	unsigned char ch;
+	while((ch = *str++) != '\0') {
+		__console_tx_char(ch);
+	}
+}
+#else
+void __console_tx_string(char *str)
+{
+}
+#endif
+
+
+void print_emerg_char(unsigned char byte) { __console_tx_char(byte); }
+void print_emerg_hex8(unsigned char value) { __console_tx_hex8(value); }
+void print_emerg_hex32(unsigned int value) { __console_tx_hex32(value); }
+void print_emerg(char *str) { __console_tx_string(str); }
+
+void print_alert_char(unsigned char byte) { __console_tx_char(byte); }
+void print_alert_hex8(unsigned char value) { __console_tx_hex8(value); }
+void print_alert_hex32(unsigned int value) { __console_tx_hex32(value); }
+void print_alert(char *str) { __console_tx_string(str); }
+
+void print_crit_char(unsigned char byte) { __console_tx_char(byte); }
+void print_crit_hex8(unsigned char value) { __console_tx_hex8(value); }
+void print_crit_hex32(unsigned int value) { __console_tx_hex32(value); }
+void print_crit(char *str) { __console_tx_string(str); }
+
+void print_err_char(unsigned char byte) { __console_tx_char(byte); }
+void print_err_hex8(unsigned char value) { __console_tx_hex8(value); }
+void print_err_hex32(unsigned int value) { __console_tx_hex32(value); }
+void print_err(char *str) { __console_tx_string(str); }
+
+void print_warning_char(unsigned char byte) { __console_tx_char(byte); }
+void print_warning_hex8(unsigned char value) { __console_tx_hex8(value); }
+void print_warning_hex32(unsigned int value) { __console_tx_hex32(value); }
+void print_warning(char *str) { __console_tx_string(str); }
+
+void print_notice_char(unsigned char byte) { __console_tx_char(byte); }
+void print_notice_hex8(unsigned char value) { __console_tx_hex8(value); }
+void print_notice_hex32(unsigned int value) { __console_tx_hex32(value); }
+void print_notice(char *str) { __console_tx_string(str); }
+
+void print_info_char(unsigned char byte) { __console_tx_char(byte); }
+void print_info_hex8(unsigned char value) { __console_tx_hex8(value); }
+void print_info_hex32(unsigned int value) { __console_tx_hex32(value); }
+void print_info(char *str) { __console_tx_string(str); }
+
+void print_debug_char(unsigned char byte) { __console_tx_char(byte); }
+void print_debug_hex8(unsigned char value) { __console_tx_hex8(value); }
+void print_debug_hex32(unsigned int value) { __console_tx_hex32(value); }
+void print_debug(char *str) { __console_tx_string(str); }
+
+void print_spew_char(unsigned char byte) { __console_tx_char(byte); }
+void print_spew_hex8(unsigned char value) { __console_tx_hex8(value); }
+void print_spew_hex32(unsigned int value) { __console_tx_hex32(value); }
+void print_spew(char *str) { __console_tx_string(str); }
+
+#define PIIX4_DEVFN 0x90
+#define SMBUS_MEM_DEVICE_START 0x50
+#define SMBUS_MEM_DEVICE_END 0x53
+#define SMBUS_MEM_DEVICE_INC 1
+
+
+#define PM_BUS 0
+#define PM_DEVFN (PIIX4_DEVFN+3)
+
+#define SMBUS_IO_BASE 0x1000
+#define SMBHSTSTAT 0
+#define SMBHSTCTL  2
+#define SMBHSTCMD  3
+#define SMBHSTADD  4
+#define SMBHSTDAT0 5
+#define SMBHSTDAT1 6
+#define SMBBLKDAT  7
+
+void smbus_enable(void)
+{
+	/* iobase addr */
+	pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x90, SMBUS_IO_BASE | 1);
+	/* smbus enable */
+	pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0xd2, (0x4 << 1) | 1);
+	/* iospace enable */
+	pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1);
+}
+
+void smbus_setup(void)
+{
+	outb(0, SMBUS_IO_BASE + SMBHSTSTAT);
+}
+
+static void smbus_wait_until_ready(void)
+{
+	while((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) {
+		/* nop */
+	}
+}
+
+static void smbus_wait_until_done(void)
+{
+	unsigned char byte;
+	do {
+		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	}while((byte &1) == 1);
+	while( (byte & ~1) == 0) {
+		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	}
+}
+
+int smbus_read_byte(unsigned device, unsigned address)
+{
+	unsigned char host_status_register;
+	unsigned char byte;
+	int result;
+
+	smbus_wait_until_ready();
+
+	/* setup transaction */
+	/* disable interrupts */
+	outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
+	/* set the device I'm talking too */
+	outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADD);
+	/* set the command/address... */
+	outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
+	/* set up for a byte data read */
+	outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2), SMBUS_IO_BASE + SMBHSTCTL);
+
+	/* clear any lingering errors, so the transaction will run */
+	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
+
+	/* clear the data byte...*/
+	outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
+
+	/* start the command */
+	outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL);
+
+	/* poll for transaction completion */
+	smbus_wait_until_done();
+
+	host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+
+	/* read results of transaction */
+	byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
+
+	result = byte;
+	if (host_status_register != 0x02) {
+		result = -1;
+	}
+	return result;
+}
+
+#define I440GX_BUS 0
+#define I440GX_DEVFN ((0x00 << 3) + 0)
+
+#define USE_ECC 0
+
+#define CAS_LATENCY 3
+
+	/* CAS latency 2 */
+#if (CAS_LATENCY == 2)
+#define CAS_NB 0x17
+	/* 
+	 * 7 == 0111
+	 * 1 == 0001
+	 */
+#define CAS_MODE 0x2a
+	/*
+	 * a == 1010
+	 * 2 == 0010
+	 */
+#endif
+
+	/* CAS latency 3 */
+#if (CAS_LATENCY == 3) 
+#define CAS_NB 0x13
+	/*
+	 * 3 == 0011
+	 * 1 == 0001
+	 */
+#define CAS_MODE 0x3a
+	/*
+	 * a == 1010
+	 * 3 == 0011
+	 */
+#endif
+
+#ifndef CAS_NB
+#error "Nothing defined" 
+#endif
+
+/* Default values for config registers */
+	
+static void set_nbxcfg(void)
+{
+	/* NBXCFG 0x50 - 0x53 */
+	/* f == 1111
+	 * 0 == 0000
+	 * 0 == 0000
+	 * 0 == 0000
+	 * 0 == 0000
+	 * 1 == 0001
+	 * 8 == 1000
+	 * c == 1100
+	 * SDRAM Row without ECC:
+	 * row 0 == 1 No ECC
+	 * row 1 == 1 No ECC
+	 * row 2 == 1 No ECC
+	 * row 3 == 1 No ECC
+	 * row 4 == 1 No ECC
+	 * row 5 == 1 No ECC
+	 * row 6 == 1 No ECC
+	 * row 7 == 1 No ECC
+	 * Host Bus Fast Data Ready Enable == 0 Disabled
+	 * IDSEL_REDIRECT == 0 (430TX compatibility disable?)
+	 * WSC# Hanshake Disable == 0 enable (Use External IOAPIC)
+	 * Host/DRAM Frequence == 00 100Mhz
+	 * AGP to PCI Access Enable == 0 Disable
+	 * PCI Agent to Aperture Access Disable == 0 Enable (Ignored)
+	 * Aperture Access Global Enable == 0 Disable
+	 * DRAM Data Integrity Mode == 11 (Error Checking/Correction)
+	 * ECC Diagnostic Mode Enable == 0 Not Enabled
+	 * MDA present == 0 Not Present
+	 * USWC Write Post During During I/O Bridge Access Enable == 1 Enabled
+	 * In Order Queue Depth (IQD) (RO) == ?? 
+	 */
+	pcibios_write_config_dword(I440GX_BUS, I440GX_DEVFN, 0x50, 0xff00000c);
+}
+
+static void set_dramc(void)
+{
+	/* 0 == 0000
+	 * 8 == 1000
+	 * Not registered SDRAM
+	 * refresh disabled
+	 */
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, 0x8);
+}
+
+static void set_pam(void)
+{
+	/* PAM - Programmable Attribute Map Registers */
+	/* Ideally we want to enable all of these as DRAM and teach
+	 * linux it is o.k. to use them...
+	 */
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x59, 0x00);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5a, 0x00);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5b, 0x00);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5d, 0x00);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5e, 0x00);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5f, 0x00);
+}
+
+static void set_drb(void)
+{
+	/* DRB - DRAM Row Boundary Registers */
+	/* Conservative setting 8MB of ram on first DIMM... */
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x60, 0x01);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x61, 0x01);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x62, 0x01);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x63, 0x01);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x64, 0x01);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x65, 0x01);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x66, 0x01);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x67, 0x01);
+}
+
+static void set_fdhc(void)
+{
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x68, 0x00);
+}
+static void set_mbsc(void)
+{
+	/* MBSC - Memory Buffer Strength Control */
+	/* 00c00003e820
+	 * [47:44] 0 == 0000
+	 * [43:40] 0 == 0000
+	 * [39:36] c == 1100
+	 * [35:32] 0 == 0000
+	 * [31:28] 0 == 0000
+	 * [27:24] 0 == 0000
+	 * [23:20] 0 == 0000
+	 * [19:16] 3 == 0011
+	 * [15:12] e == 1110
+	 * [11: 8] 8 == 1000
+	 * [ 7: 4] 2 == 0010
+	 * [ 3: 0] 0 == 0000
+	 * MAA[14:0]#, WEA#, SRASA#, SCASA# Buffer Strengths  ==  3x
+	 * MAB[14,13,10,12:11,9:0]#, WEB#, SRASB#, SCASB# Buffer Strengths == 3x
+	 * MD[63:0]# Buffer Strength Control 2 == 3x
+	 * MD[63:0]# Buffer Strength Control 1 == 3x
+	 * MECC[7:0] Buffer Strength Control 2 == 3x
+	 * MECC[7:0] Buffer Strength Control 1 == 3x
+	 * CSB7# Buffer Strength == 3x	
+	 * CSA7# Buffer Strength == 3x
+	 * CSB6# Buffer Strength == 3x
+	 * CSA6# Buffer Strength == 3x
+	 * CSA5#/CSB5# Buffer Strength == 2x
+	 * CSA4#/CSB4# Buffer Strength == 2x
+	 * CSA3#/CSB3# Buffer Strength == 2x
+	 * CSA2#/CSB2# Buffer Strength == 2x
+	 * CSA1#/CSB1# Buffer Strength == 2x
+	 * CSA0#/CSB0# Buffer Strength == 2x
+	 * DQMA5 Buffer Strength == 2x
+	 * DQMA1 Buffer Strength == 3x
+	 * DQMB5 Buffer Strength == 2x
+	 * DQMB1 Buffer Strength == 2x
+	 * DQMA[7:6,4:2,0] Buffer Strength == 3x
+	 * GCKE Buffer Strength == 1x
+	 * FENA Buffer Strength == 3x
+	 */
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x69, 0xB3);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6a, 0xee);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6b, 0xff);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6c, 0xff);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6d, 0xff);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6e, 0x03);
+}
+
+static void set_smram(void)
+{
+	/* 0x72 SMRAM */
+	/* 1 == 0001
+	 * a == 1010
+	 * SMM Compatible base segment == 010 (Hardcoded value)
+	 */
+}
+
+static void set_esramc(void)
+{
+	/* 0x73 ESMRAMC */
+}
+
+static void set_rps(void)
+{
+	/* RPS - Row Page Size Register */
+	/* 0x0055
+	 * [15:12] 0 == 0000
+	 * [11: 8] 0 == 0000
+	 * [ 7: 4] 5 == 0101
+	 * [ 3: 0] 5 == 0101
+	 * DRB[0] == 4KB
+	 * DRB[1] == 4KB
+	 * DRB[2] == 4KB
+	 * DRB[3] == 4KB
+	 * DRB[4] == 2KB
+	 * DRB[5] == 2KB
+	 * DRB[6] == 2KB
+	 * DRB[7] == 2KB
+	 */
+	pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x74, 0x5555);
+}
+
+static void set_sdramc(void)
+{
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, CAS_NB);
+}
+
+static void set_pgpol(void)
+{
+	/* PGPOL - Paging Policy Register */
+	/* 0xff07
+	 * [15:12] f == 1111
+	 * [11: 8] f == 1111
+	 * [ 7: 4] 0 == 0000
+	 * [ 3: 0] 7 == 0111
+	 * row0 == 4banks
+	 * row1 == 4banks
+	 * row2 == 4banks
+	 * row3 == 4banks
+	 * row4 == 4banks
+	 * row5 == 4banks
+	 * row6 == 4banks
+	 * row7 == 4banks
+	 * Dram Idle Timer (DIT) == 32 clocks
+	 */
+	pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x78, 0xff07);
+}
+
+static void set_mbfs(void)
+{
+	/* MBFS - Memory Buffer Frequencey Select Register */
+	/* 0xffff7f					     
+	 * [23:20] f == 1111				     
+	 * [19:16] f == 1111				     
+	 * [15:12] f == 1111				     
+	 * [11: 8] f == 1111				     
+	 * [ 7: 4] 7 == 0111				     
+	 * [ 3: 0] f == 1111				     
+	 * MAA[14:0], WEA#, SRASA#, SCASA# == 100Mhz Buffers Enabled
+	 * MAB[14,13,10,12:11,9:0], WEB#, SRASB#, SCASB# == 100Mhz Buffers Enabled
+	 * MD[63:0] Control 2 == 100 Mhz Buffer Enable
+	 * MD[63:0] Control 1 == 100 Mhz B
+	 * MECC[7:0] Control 2 == 100 Mhz B
+	 *
+	 */
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xca, 0xff);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcb, 0xff);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcc, 0x7f);
+}
+
+static void set_dwtc(void)
+{
+	/* DWTC - DRAM Write Thermal Throttle Control */
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe0, 0xb4);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe1, 0xbe);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe2, 0xff);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe3, 0xd7);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe4, 0x97);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe5, 0x3e);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe6, 0x00);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe7, 0x80);
+}
+
+static void set_drtc(void)
+{
+	/* DRTC - DRAM Read Thermal Throttle Control */
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe8, 0x2c);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe9, 0xd3);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xea, 0xf7);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xeb, 0xcf);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xec, 0x9d);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xed, 0x3e);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xee, 0x00);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xef, 0x00);
+}
+
+static void set_pmcr(void)
+{
+	/* PMCR -- BIOS sets 0x90 into it. 
+	 * 0x10 is REQUIRED.
+	 * we have never used it. So why did this ever work?
+	 */
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x7a, 0x90);
+	
+}
+void sdram_set_registers(void)
+{
+	set_nbxcfg();
+	set_dramc();
+	set_pam();
+	set_drb();
+	set_fdhc();
+	set_mbsc();
+	set_smram();
+	set_esramc();
+	set_rps();
+	set_sdramc();
+	set_pgpol();
+	set_mbfs();
+	set_dwtc();
+	set_drtc();
+	set_pmcr();
+}
+
+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);
+}
+
+
+static void spd_set_drb(void)
+{
+	/*
+	 * Effects:	Uses serial presence detect to set the
+	 *              DRB registers which holds the ending memory address assigned
+	 *              to each DIMM.
+	 */
+	unsigned end_of_memory;
+	unsigned device;
+	unsigned drb_reg;
+	
+	end_of_memory = 0; /* in multiples of 8MiB */
+	device = SMBUS_MEM_DEVICE_START;
+	drb_reg = 0x60;
+	while (device <= SMBUS_MEM_DEVICE_END) {
+		unsigned side1_bits, side2_bits;
+		int byte, byte2;
+
+		side1_bits = side2_bits = -1;
+
+		/* rows */
+		byte = smbus_read_byte(device, 3);
+		if (byte >= 0) {
+			side1_bits += byte & 0xf;
+
+			/* columns */
+			byte = smbus_read_byte(device, 4);
+			side1_bits += byte & 0xf;
+
+			/* banks */
+			byte = smbus_read_byte(device, 17);
+			side1_bits += log2(byte);
+
+			/* Get the moduel data width and convert it to a power of two */
+			/* low byte */
+			byte = smbus_read_byte(device, 6);
+
+			/* high byte */
+			byte2 = smbus_read_byte(device, 7);
+#if HAVE_CAST_SUPPORT
+			side1_bits += log2((((unsigned long)byte2 << 8)| byte));
+#else
+			side1_bits += log2((byte2 << 8) | byte);
+#endif
+			
+			/* now I have the ram size in bits as a power of two (less 1) */
+			/* Make it mulitples of 8MB */
+			side1_bits -= 25;
+			
+			/* side two */
+			
+			/* number of physical banks */
+			byte = smbus_read_byte(device, 5);
+			if (byte > 1) {
+				/* for now only handle the symmetrical case */
+				side2_bits = side1_bits;
+			}
+		}
+
+		/* Compute the end address for the DRB register */
+		/* Only process dimms < 2GB (2^8 * 8MB) */
+		if (side1_bits < 8) {
+			end_of_memory += (1 << side1_bits);
+		}
+#if HAVE_STRING_SUPPORT
+		print_debug("end_of_memory: "); print_debug_hex32(end_of_memory); print_debug("\n");
+#endif
+		pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, drb_reg, end_of_memory);
+
+		if (side2_bits < 8 ) {
+			end_of_memory += (1 << side2_bits);
+		}
+#if HAVE_STRING_SUPPORT
+		print_debug("end_of_memory: "); print_debug_hex32(end_of_memory); print_debug("\n");
+#endif
+		pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, drb_reg +1, end_of_memory);
+
+		drb_reg += 2;
+		device += SMBUS_MEM_DEVICE_INC;
+	}
+}
+
+void sdram_no_memory(void)
+{
+#if HAVE_STRING_SUPPORT
+	print_err("No memory!!\n");
+#endif
+	while(1) ;
+}
+
+static void spd_set_dramc(void)
+{
+	/*
+	 * Effects:	Uses serial presence detect to set the
+	 *              DRAMC register, which records if ram is registerd or not,
+	 *              and controls the refresh rate.
+	 *              The refresh rate is not set here, as memory refresh
+	 *              cannot be enbaled until after memory is initialized.
+	 *		see spd_enable_refresh.
+	 */
+	/* auto detect if ram is registered or not. */
+	/* The DRAMC register also contorls the refresh rate but we can't
+         * set that here because we must leave refresh disabled.
+	 * see:	spd_enable_refresh
+	 */
+	/* Find the first dimm and assume the rest are the same */
+	/* FIXME Check for illegal/unsupported ram configurations and abort */
+	unsigned device;
+	int byte;
+	unsigned dramc;
+	byte = -1;
+	device = SMBUS_MEM_DEVICE_START;
+
+	while ((byte < 0) && (device <= SMBUS_MEM_DEVICE_END)) {
+		byte = smbus_read_byte(device, 21);
+		device += SMBUS_MEM_DEVICE_INC;
+	}
+	if (byte < 0) {
+		/* We couldn't find anything we must have no memory */
+		sdram_no_memory();
+	}
+	dramc = 0x8;
+	if ((byte & 0x12) != 0) {
+		/* this is a registered part. 
+		 * observation: for register parts, BIOS zeros (!) 
+		 * registers CA-CC. This has an undocumented meaning.
+		 */
+		/* But it does make sense the oppisite of registered
+		 * sdram is buffered and 0xca - 0xcc control the buffers.
+		 * Clearing them aparently disables them.
+		 */
+		pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xca, 0);
+		pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcb, 0);
+		pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcc, 0);
+		dramc = 0x10;
+	}
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, dramc);
+}
+
+static void spd_enable_refresh(void)
+{
+	/*
+	 * Effects:	Uses serial presence detect to set the
+	 *              refresh rate in the DRAMC register.
+	 *		see spd_set_dramc for the other values.
+	 * FIXME:	Check for illegal/unsupported ram configurations and abort
+	 */
+#if HAVE_STATIC_ARRAY_SUPPORT
+	static const unsigned char refresh_rates[] = {
+		0x01, /* Normal        15.625 us -> 15.6 us */
+		0x05, /* Reduced(.25X) 3.9 us    -> 7.8 us */
+		0x05, /* Reduced(.5X)  7.8 us    -> 7.8 us */
+		0x02, /* Extended(2x)  31.3 us   -> 31.2 us */
+		0x03, /* Extended(4x)  62.5 us   -> 62.4 us */
+		0x04, /* Extended(8x)  125 us    -> 124.8 us */
+	};
+#endif
+	/* Find the first dimm and assume the rest are the same */
+	int status;
+	int byte;
+	unsigned device;
+	unsigned refresh_rate;
+	byte = -1;
+	status = -1;
+	device = SMBUS_MEM_DEVICE_START;
+	while ((byte < 0) && (device <= SMBUS_MEM_DEVICE_END)) {
+		byte = smbus_read_byte(device, 12);
+		device += SMBUS_MEM_DEVICE_INC;
+	}
+	if (byte < 0) {
+		/* We couldn't find anything we must have no memory */
+		sdram_no_memory();
+	}
+	byte &= 0x7f;
+	/* Default refresh rate be conservative */
+	refresh_rate = 5; 
+	/* see if the ram refresh is a supported one */
+	if (byte < 6) {
+#if HAVE_STATIC_ARRAY_SUPPORT
+		refresh_rate = refresh_rates[byte];
+#endif
+	}
+	byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57);
+	byte &= 0xf8;
+	byte |= refresh_rate;
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, byte);
+}
+
+static void spd_set_sdramc(void)
+{
+	return;
+}
+
+static void spd_set_rps(void)
+{
+	/*
+	 * Effects:	Uses serial presence detect to set the row size 
+	 *		on a given DIMM
+	 * FIXME:	Check for illegal/unsupported ram configurations and abort
+	 */
+	/* The RPS register holds the size of a ``page'' of DRAM on each DIMM */
+	unsigned page_sizes;
+	unsigned index;
+	unsigned device;
+	unsigned char dramc;
+	/* default all page sizes to 2KB */
+	page_sizes = 0;
+	index = 0;
+	device = SMBUS_MEM_DEVICE_START;
+	for(; device <= SMBUS_MEM_DEVICE_END; index += 4, device += SMBUS_MEM_DEVICE_INC) {
+		unsigned int status;
+		unsigned int byte;
+		int page_size;
+
+		byte = smbus_read_byte(device, 3);
+		if (byte < 0) continue;
+
+		/* I now have the row page size as a power of 2 */
+		page_size = byte & 0xf;
+		/* make it in multiples of 2Kb */
+		page_size -= 11;
+		
+		if (page_size <= 0) continue;
+		
+		/* FIXME: do something with page sizes greather than 8KB!! */
+		page_sizes |= (page_size << index);
+				
+		/* side two */
+		byte = smbus_read_byte(device, 5);
+		if (byte <= 1)  continue;
+			
+		/* For now only handle the symmetrical case */
+		page_sizes |= (page_size << (index +2));
+	}
+	/* next block is for Ron's attempt to get registered to work. */
+	/* we have just verified that we have to have this code. It appears that
+	 * the registered SDRAMs do indeed set the RPS wrong. sheesh.
+	 */
+	/* at this point, page_sizes holds the RPS for all ram. 
+	 * we have verified that for registered DRAM the values are 
+	 * 1/2 the size they should be. So we test for registered
+	 * and then double the sizes if needed. 
+	 */
+
+	dramc = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57);
+	if (dramc & 0x10) {
+		/* registered */
+
+		/* BIOS makes weird page size for registered! */
+		/* what we have found is you need to set the EVEN banks to 
+		 * twice the size. Fortunately there is a very easy way to 
+		 * do this. First, read the WORD value of register 0x74. 
+		 */
+		page_sizes += 0x1111;
+	}
+
+	pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x74, page_sizes);
+}
+
+static void spd_set_pgpol(void)
+{
+	/*
+	 * Effects:	Uses serial presence detect to set the number of banks
+	 *		on a given DIMM
+	 * FIXME:	Check for illegal/unsupported ram configurations and abort
+	 */
+	/* The PGPOL register stores the number of logical banks per DIMM,
+	 * and number of clocks the DRAM controller waits in the idle
+	 * state.
+	 */
+	unsigned device;
+	unsigned bank_sizes;
+	unsigned bank;
+	unsigned reg;
+	/* default all bank counts 2 */
+	bank_sizes = 0;
+	bank = 0;
+	device = SMBUS_MEM_DEVICE_START;
+	for(; device <= SMBUS_MEM_DEVICE_END; 
+	    bank += 2, device += SMBUS_MEM_DEVICE_INC) { 
+		int byte;
+
+		/* logical banks */
+		byte = smbus_read_byte(device, 17);
+		if (byte < 0) continue;
+		if (byte < 4) continue;
+		bank_sizes |= (1 << bank);
+		
+		/* side 2 */
+		/* Number of physical banks */
+		byte  = smbus_read_byte(device, 5);
+		if (byte <= 1) continue;
+		/* for now only handle the symmetrical case */
+		bank_sizes |= (1 << (bank +1));
+	}
+	reg = bank_sizes << 8;
+	reg |= 0x7; /* 32 clocks idle time */
+	pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x78, reg);
+}
+
+static void spd_set_nbxcfg(void)
+{
+	/*
+	 * Effects:	Uses serial presence detect to set the
+	 *              ECC support flags in the NBXCFG register
+	 * FIXME:	Check for illegal/unsupported ram configurations and abort
+	 */
+	unsigned reg;
+	unsigned index;
+	unsigned device;
+
+	/* Say all dimms have no ECC support */
+	reg = 0xff;
+	index = 0;
+	
+	device = SMBUS_MEM_DEVICE_START;
+	for(; device <= SMBUS_MEM_DEVICE_END; index += 2, device += SMBUS_MEM_DEVICE_INC) {
+		int byte;
+
+		byte = smbus_read_byte(device, 11);
+		if (byte < 0) continue;
+#if !USE_ECC 
+		byte = 0; /* Disable ECC */
+#endif
+		/* 0 == None, 1 == Parity, 2 == ECC */
+		if (byte != 2) continue;
+		reg ^= (1 << index);
+
+		/* side two */
+		/* number of physical banks */
+		byte = smbus_read_byte(device, 5);
+		if (byte <= 1) continue;
+		/* There is only the symmetrical case */
+		reg ^= (1 << (index +1));
+	}
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x53, reg);
+	/* Now see if reg is 0xff.  If it is we are done.  If not,
+	 * we need to set 0x18 into regster 0x50.l
+	 * we will do this in two steps, first or in 0x80 to 0x50.b,
+	 * then or in 0x1 to 0x51.b
+	 */
+#if HAVE_STRING_SUPPORT
+	print_debug("spd_set_nbxcfg reg="); print_debug_hex8(reg); print_debug("\n");
+#endif
+	if (reg != 0xff) {
+		unsigned char byte;
+		byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x50);
+		byte |= 0x80;
+		pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x50, byte);
+		byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x51);
+		byte |= 1;
+		pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x51, byte);
+		/* try this.
+		 * We should be setting bit 2 in register 76 and we're not
+		 * technically we should see if CL=2 for the ram,
+		 * but registered is so screwed up that it's kind of a lost 
+		 * cause.
+		 */
+		byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76);
+		byte |= 4;
+		pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, byte);
+#if HAVE_STRING_SUPPORT
+		print_debug("spd_set_nbxcfg 0x76.b="); print_debug_hex8(byte); print_debug("\n");
+#endif
+	}
+}
+
+void sdram_set_spd_registers(void)
+{
+	spd_set_drb();
+	spd_set_dramc();
+	spd_set_rps();
+	spd_set_sdramc();
+	spd_set_pgpol();
+	spd_set_nbxcfg();
+}
+
+void sdram_first_normal_reference(void)
+{
+	return;
+}
+
+void sdram_special_finishup(void)
+{
+	return;
+}
+
+static void set_ram_command(unsigned command)
+{
+	unsigned char byte;
+	command &= 0x7;
+	byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76);
+	byte &= 0x1f;
+	byte |= (command << 5);
+	pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, byte);
+#if HAVE_STRING_SUPPORT
+	print_debug("set_ram_command 0x76.b="); print_debug_hex8(byte); print_debug("\n");
+#endif
+}
+
+#define RAM_COMMAND_NONE	0x0
+#define RAM_COMMAND_NOOP	0x1
+#define RAM_COMMAND_PRECHARGE	0x2
+#define RAM_COMMAND_MRS		0x3
+#define RAM_COMMAND_CBR		0x4
+
+void sdram_set_command_none(void)
+{
+	set_ram_command(RAM_COMMAND_NONE);
+}
+void sdram_set_command_noop(void)
+{
+	set_ram_command(RAM_COMMAND_NOOP);
+}
+void sdram_set_command_precharge(void)
+{
+	set_ram_command(RAM_COMMAND_PRECHARGE);
+}
+
+static unsigned long dimm_base(int n)
+{
+	unsigned char byte;
+	unsigned long result;
+	if (n == 0) {
+		return 0;
+	}
+
+	byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x60 + (n - 1));
+	result = byte;
+	result <<= 23;
+	return result;
+}
+
+static void dimms_read(unsigned long offset)
+{
+	int i;
+	for(i = 0; i < 8; i++) {
+		unsigned long dummy;
+		unsigned long addr; 
+		unsigned long next_base;
+
+		next_base = dimm_base(i +1);
+		addr =  dimm_base(i);
+		if (addr == next_base) {
+			continue;
+		}
+		addr += offset;
+#if HAVE_STRING_SUPPORT
+		print_debug("Reading "); 
+		print_debug_hex32(addr); 
+		print_debug("\n");
+#endif
+#if HAVE_POINTER_SUPPORT
+#if HAVE_MACRO_ARG_SUPPORT
+		dummy = RAM(unsigned long, addr);
+#else
+		dummy = *((volatile unsigned long *)(addr));
+#endif
+#endif
+#if HAVE_STRING_SUPPORT
+		print_debug("Reading "); 
+		print_debug_hex32(addr ^ 0xddf8); 
+		print_debug("\n");
+#endif
+#if HAVE_POINTER_SUPPORT
+#if HAVE_MACRO_ARG_SUPPORT
+		dummy = RAM(unsigned long, addr ^ 0xdff8);
+#else
+		dummy = *((volatile unsigned long *)(addr ^ 0xdff8));
+#endif
+#endif
+#if HAVE_STRING_SUPPORT
+		print_debug("Read "); 
+		print_debug_hex32(addr); 
+		print_debug_hex32(addr ^ 0xddf8); 
+		print_debug("\n");
+#endif
+	}
+}
+
+void sdram_set_command_cbr(void)
+{
+	set_ram_command(RAM_COMMAND_CBR);
+}
+
+void sdram_assert_command(void)
+{
+	dimms_read(0x400);
+}
+
+void sdram_set_mode_register(void)
+{
+	unsigned char byte;
+	unsigned cas_mode;
+	set_ram_command(RAM_COMMAND_MRS);
+	byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76);
+	cas_mode = byte & 0x4;
+	cas_mode ^= 4;
+	cas_mode <<= 2;
+	cas_mode |= 0x2a;
+	cas_mode <<= 3;
+	dimms_read(cas_mode);
+}
+
+void sdram_enable_refresh(void)
+{
+	spd_enable_refresh();
+}
+
+
+unsigned long sdram_get_ecc_size_bytes(void)
+{
+	unsigned char byte;
+	unsigned long size;
+	/* FIXME handle the no ram case. */
+	/* Read the RAM SIZE */
+	byte = pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x67);
+	/* Convert it to bytes */
+	size = byte;
+	size <<= 23;
+#if !USE_ECC
+	size = 0;
+#endif
+	return size;
+}
+
+/* Dummy udelay code acting as a place holder... */
+void udelay(int count)
+{
+	int i;
+	i = 5;
+}
+
+void sdram_enable(void)
+{
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram Enable 1\n");
+#endif
+
+	/* noop command */
+	sdram_set_command_noop();
+	udelay(200);
+	sdram_assert_command();
+
+	/* Precharge all */
+	sdram_set_command_precharge();
+	sdram_assert_command();
+
+	/* wait until the all banks idle state... */
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram Enable 2\n");
+#endif
+	
+	/* Now we need 8 AUTO REFRESH / CBR cycles to be performed */
+	
+	sdram_set_command_cbr();
+	sdram_assert_command();
+	sdram_assert_command();
+	sdram_assert_command();
+	sdram_assert_command();
+	sdram_assert_command();
+	sdram_assert_command();
+	sdram_assert_command();
+	sdram_assert_command();
+	
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram Enable 3\n");
+#endif
+	
+	/* mode register set */
+	sdram_set_mode_register();
+	/* MAx[14:0] lines,
+	 * MAx[2:0 ] 010 == burst mode of 4
+	 * MAx[3:3 ] 1 == interleave wrap type
+	 * MAx[4:4 ] == CAS# latency bit
+	 * MAx[6:5 ] == 01
+	 * MAx[12:7] ==	0
+	 */
+
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram Enable 4\n");
+#endif
+
+	/* normal operation */
+	sdram_set_command_none();
+	
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram Enable 5\n");
+#endif
+}
+
+/* Setup SDRAM */
+void sdram_initialize(void)
+{
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram1\n");
+#endif
+	/* Set the registers we can set once to reasonable values */
+	sdram_set_registers();
+
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram2\n");
+#endif
+	/* Now setup those things we can auto detect */
+	sdram_set_spd_registers();
+
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram3\n");
+#endif
+	/* Now that everything is setup enable the SDRAM.
+	 * Some chipsets do the work for use while on others 
+	 * we need to it by hand.
+	 */
+	sdram_enable();
+
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram4\n");
+#endif
+	sdram_first_normal_reference();
+
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram5\n");
+#endif
+	sdram_enable_refresh();
+	sdram_special_finishup();
+
+#if HAVE_STRING_SUPPORT
+	print_debug("Ram6\n");
+#endif
+}
diff --git a/util/romcc/tests/raminit_test7.c b/util/romcc/tests/raminit_test7.c
new file mode 100644
index 0000000..be62d30
--- /dev/null
+++ b/util/romcc/tests/raminit_test7.c
@@ -0,0 +1,2805 @@
+typedef unsigned char      uint8_t;
+typedef signed char        int8_t; 
+typedef unsigned short     uint16_t;
+typedef signed short       int16_t;
+typedef unsigned int       uint32_t;
+typedef signed int         int32_t;
+ 
+typedef unsigned char      uint_least8_t;
+typedef signed char        int_least8_t; 
+typedef unsigned short     uint_least16_t;
+typedef signed short       int_least16_t;
+typedef unsigned int       uint_least32_t;
+typedef signed int         int_least32_t;
+ 
+typedef unsigned char      uint_fast8_t;
+typedef signed char        int_fast8_t; 
+typedef unsigned int       uint_fast16_t;
+typedef signed int         int_fast16_t;
+typedef unsigned int       uint_fast32_t;
+typedef signed int         int_fast32_t;
+ 
+typedef int                intptr_t;
+typedef unsigned int       uintptr_t;
+ 
+typedef long int           intmax_t;
+typedef unsigned long int  uintmax_t;
+ 
+static inline unsigned long apic_read(unsigned long reg)
+{
+	return *((volatile unsigned long *)(0xfee00000 +reg));
+}
+static inline void apic_write(unsigned long reg, unsigned long v)
+{
+	*((volatile unsigned long *)(0xfee00000 +reg)) = v;
+}
+static inline void apic_wait_icr_idle(void)
+{
+	do { } while ( apic_read( 0x300  ) & 0x01000  );
+}
+ 
+static void outb(unsigned char value, unsigned short port)
+{
+	__builtin_outb(value, port);
+}
+static void outw(unsigned short value, unsigned short port)
+{
+	__builtin_outw(value, port);
+}
+static void outl(unsigned int value, unsigned short port)
+{
+	__builtin_outl(value, port);
+}
+static unsigned char inb(unsigned short port)
+{
+	return __builtin_inb(port);
+}
+static unsigned char inw(unsigned short port)
+{
+	return __builtin_inw(port);
+}
+static unsigned char inl(unsigned short port)
+{
+	return __builtin_inl(port);
+}
+static inline void outsb(uint16_t port, const void *addr, unsigned long count)
+{
+	__asm__ __volatile__ (
+		"cld ; rep ; outsb " 
+		: "=S" (addr), "=c" (count)
+		: "d"(port), "0"(addr), "1" (count)
+		);
+}
+static inline void outsw(uint16_t port, const void *addr, unsigned long count)
+{
+	__asm__ __volatile__ (
+		"cld ; rep ; outsw " 
+		: "=S" (addr), "=c" (count)
+		: "d"(port), "0"(addr), "1" (count)
+		);
+}
+static inline void outsl(uint16_t port, const void *addr, unsigned long count)
+{
+	__asm__ __volatile__ (
+		"cld ; rep ; outsl " 
+		: "=S" (addr), "=c" (count)
+		: "d"(port), "0"(addr), "1" (count)
+		);
+}
+static inline void insb(uint16_t port, void *addr, unsigned long count)
+{
+	__asm__ __volatile__ (
+		"cld ; rep ; insb " 
+		: "=D" (addr), "=c" (count)
+		: "d"(port), "0"(addr), "1" (count)
+		);
+}
+static inline void insw(uint16_t port, void *addr, unsigned long count)
+{
+	__asm__ __volatile__ (
+		"cld ; rep ; insw " 
+		: "=D" (addr), "=c" (count)
+		: "d"(port), "0"(addr), "1" (count)
+		);
+}
+static inline void insl(uint16_t port, void *addr, unsigned long count)
+{
+	__asm__ __volatile__ (
+		"cld ; rep ; insl " 
+		: "=D" (addr), "=c" (count)
+		: "d"(port), "0"(addr), "1" (count)
+		);
+}
+static inline void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg)
+{
+	outb(reg, port);
+	outb(value, port +1);
+}
+static inline unsigned char pnp_read_config(unsigned char port, unsigned char reg)
+{
+	outb(reg, port);
+	return inb(port +1);
+}
+static inline void pnp_set_logical_device(unsigned char port, int device)
+{
+	pnp_write_config(port, device, 0x07);
+}
+static inline void pnp_set_enable(unsigned char port, int enable)
+{
+	pnp_write_config(port, enable?0x1:0x0, 0x30);
+}
+static inline int pnp_read_enable(unsigned char port)
+{
+	return !!pnp_read_config(port, 0x30);
+}
+static inline void pnp_set_iobase0(unsigned char port, unsigned iobase)
+{
+	pnp_write_config(port, (iobase >> 8) & 0xff, 0x60);
+	pnp_write_config(port, iobase & 0xff, 0x61);
+}
+static inline void pnp_set_iobase1(unsigned char port, unsigned iobase)
+{
+	pnp_write_config(port, (iobase >> 8) & 0xff, 0x62);
+	pnp_write_config(port, iobase & 0xff, 0x63);
+}
+static inline void pnp_set_irq0(unsigned char port, unsigned irq)
+{
+	pnp_write_config(port, irq, 0x70);
+}
+static inline void pnp_set_irq1(unsigned char port, unsigned irq)
+{
+	pnp_write_config(port, irq, 0x72);
+}
+static inline void pnp_set_drq(unsigned char port, unsigned drq)
+{
+	pnp_write_config(port, drq & 0xff, 0x74);
+}
+static void hlt(void)
+{
+	__builtin_hlt();
+}
+typedef __builtin_div_t div_t;
+typedef __builtin_ldiv_t ldiv_t;
+typedef __builtin_udiv_t udiv_t;
+typedef __builtin_uldiv_t uldiv_t;
+static div_t div(int numer, int denom)
+{
+	return __builtin_div(numer, denom);
+}
+static ldiv_t ldiv(long numer, long denom)
+{
+	return __builtin_ldiv(numer, denom);
+}
+static udiv_t udiv(unsigned numer, unsigned denom)
+{
+	return __builtin_udiv(numer, denom);
+}
+static uldiv_t uldiv(unsigned long numer, unsigned long denom)
+{
+	return __builtin_uldiv(numer, denom);
+}
+int log2(int value)
+{
+	 
+	return __builtin_bsr(value);
+}
+typedef unsigned device_t;
+static unsigned char pci_read_config8(device_t dev, unsigned where)
+{
+	unsigned addr;
+	addr = dev | where;
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	return inb(0xCFC + (addr & 3));
+}
+static unsigned short pci_read_config16(device_t dev, unsigned where)
+{
+	unsigned addr;
+	addr = dev | where;
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	return inw(0xCFC + (addr & 2));
+}
+static unsigned int pci_read_config32(device_t dev, unsigned where)
+{
+	unsigned addr;
+	addr = dev | where;
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	return inl(0xCFC);
+}
+static void pci_write_config8(device_t dev, unsigned where, unsigned char value)
+{
+	unsigned addr;
+	addr = dev | where;
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	outb(value, 0xCFC + (addr & 3));
+}
+static void pci_write_config16(device_t dev, unsigned where, unsigned short value)
+{
+	unsigned addr;
+	addr = dev | where;
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	outw(value, 0xCFC + (addr & 2));
+}
+static void pci_write_config32(device_t dev, unsigned where, unsigned int value)
+{
+	unsigned addr;
+	addr = dev | where;
+	outl(0x80000000 | (addr & ~3), 0xCF8);
+	outl(value, 0xCFC);
+}
+static device_t pci_locate_device(unsigned pci_id, device_t dev)
+{
+	for(; dev <= ( ((( 255 ) & 0xFF) << 16) | (((  31 ) & 0x1f) << 11) | (((  7 )  & 0x7) << 8)) ; dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8)) ) {
+		unsigned int id;
+		id = pci_read_config32(dev, 0);
+		if (id == pci_id) {
+			return dev;
+		}
+	}
+	return (0xffffffffU) ;
+}
+ 
+ 
+ 
+ 
+ 
+static int uart_can_tx_byte(void)
+{
+	return inb(1016  + 0x05 ) & 0x20;
+}
+static void uart_wait_to_tx_byte(void)
+{
+	while(!uart_can_tx_byte())
+		;
+}
+static void uart_wait_until_sent(void)
+{
+	while(!(inb(1016  + 0x05 ) & 0x40)) 
+		;
+}
+static void uart_tx_byte(unsigned char data)
+{
+	uart_wait_to_tx_byte();
+	outb(data, 1016  + 0x00 );
+	 
+	uart_wait_until_sent();
+}
+static void uart_init(void)
+{
+	 
+	outb(0x0, 1016  + 0x01 );
+	 
+	outb(0x01, 1016  + 0x02 );
+	 
+	outb(0x80 | 3  , 1016  + 0x03 );
+	outb((115200/ 115200 )  & 0xFF,   1016  + 0x00 );
+	outb(((115200/ 115200 )  >> 8) & 0xFF,    1016  + 0x01 );
+	outb(3  , 1016  + 0x03 );
+}
+ 
+static void __console_tx_byte(unsigned char byte)
+{
+	uart_tx_byte(byte);
+}
+static void __console_tx_nibble(unsigned nibble)
+{
+	unsigned char digit;
+	digit = nibble + '0';
+	if (digit > '9') {
+		digit += 39;
+	}
+	__console_tx_byte(digit);
+}
+static void __console_tx_char(int loglevel, unsigned char byte)
+{
+	if (8   > loglevel) {
+		uart_tx_byte(byte);
+	}
+}
+static void __console_tx_hex8(int loglevel, unsigned char value)
+{
+	if (8   > loglevel) {
+		__console_tx_nibble((value >>  4U) & 0x0fU);
+		__console_tx_nibble(value & 0x0fU);
+	}
+}
+static void __console_tx_hex16(int loglevel, unsigned short value)
+{
+	if (8   > loglevel) {
+		__console_tx_nibble((value >> 12U) & 0x0fU);
+		__console_tx_nibble((value >>  8U) & 0x0fU);
+		__console_tx_nibble((value >>  4U) & 0x0fU);
+		__console_tx_nibble(value & 0x0fU);
+	}
+}
+static void __console_tx_hex32(int loglevel, unsigned int value)
+{
+	if (8   > loglevel) {
+		__console_tx_nibble((value >> 28U) & 0x0fU);
+		__console_tx_nibble((value >> 24U) & 0x0fU);
+		__console_tx_nibble((value >> 20U) & 0x0fU);
+		__console_tx_nibble((value >> 16U) & 0x0fU);
+		__console_tx_nibble((value >> 12U) & 0x0fU);
+		__console_tx_nibble((value >>  8U) & 0x0fU);
+		__console_tx_nibble((value >>  4U) & 0x0fU);
+		__console_tx_nibble(value & 0x0fU);
+	}
+}
+
+static void do_console_tx_string(const char *str) __attribute__((noinline))
+{
+	unsigned char ch;
+	while((ch = *str++) != '\0') {
+		__console_tx_byte(ch);
+	}
+}
+static void __console_tx_string(int loglevel, const char *str)
+{
+	if (8   > loglevel) {
+		do_console_tx_string(str);
+	}
+}
+static void print_emerg_char(unsigned char byte) { __console_tx_char(0 , byte); }
+static void print_emerg_hex8(unsigned char value){ __console_tx_hex8(0 , value); }
+static void print_emerg_hex16(unsigned short value){ __console_tx_hex16(0 , value); }
+static void print_emerg_hex32(unsigned int value) { __console_tx_hex32(0 , value); }
+static void print_emerg(const char *str) { __console_tx_string(0 , str); }
+static void print_alert_char(unsigned char byte) { __console_tx_char(1 , byte); }
+static void print_alert_hex8(unsigned char value) { __console_tx_hex8(1 , value); }
+static void print_alert_hex16(unsigned short value){ __console_tx_hex16(1 , value); }
+static void print_alert_hex32(unsigned int value) { __console_tx_hex32(1 , value); }
+static void print_alert(const char *str) { __console_tx_string(1 , str); }
+static void print_crit_char(unsigned char byte) { __console_tx_char(2 , byte); }
+static void print_crit_hex8(unsigned char value) { __console_tx_hex8(2 , value); }
+static void print_crit_hex16(unsigned short value){ __console_tx_hex16(2 , value); }
+static void print_crit_hex32(unsigned int value) { __console_tx_hex32(2 , value); }
+static void print_crit(const char *str) { __console_tx_string(2 , str); }
+static void print_err_char(unsigned char byte) { __console_tx_char(3 , byte); }
+static void print_err_hex8(unsigned char value) { __console_tx_hex8(3 , value); }
+static void print_err_hex16(unsigned short value){ __console_tx_hex16(3 , value); }
+static void print_err_hex32(unsigned int value) { __console_tx_hex32(3 , value); }
+static void print_err(const char *str) { __console_tx_string(3 , str); }
+static void print_warning_char(unsigned char byte) { __console_tx_char(4 , byte); }
+static void print_warning_hex8(unsigned char value) { __console_tx_hex8(4 , value); }
+static void print_warning_hex16(unsigned short value){ __console_tx_hex16(4 , value); }
+static void print_warning_hex32(unsigned int value) { __console_tx_hex32(4 , value); }
+static void print_warning(const char *str) { __console_tx_string(4 , str); }
+static void print_notice_char(unsigned char byte) { __console_tx_char(5 , byte); }
+static void print_notice_hex8(unsigned char value) { __console_tx_hex8(5 , value); }
+static void print_notice_hex16(unsigned short value){ __console_tx_hex16(5 , value); }
+static void print_notice_hex32(unsigned int value) { __console_tx_hex32(5 , value); }
+static void print_notice(const char *str) { __console_tx_string(5 , str); }
+static void print_info_char(unsigned char byte) { __console_tx_char(6 , byte); }
+static void print_info_hex8(unsigned char value) { __console_tx_hex8(6 , value); }
+static void print_info_hex16(unsigned short value){ __console_tx_hex16(6 , value); }
+static void print_info_hex32(unsigned int value) { __console_tx_hex32(6 , value); }
+static void print_info(const char *str) { __console_tx_string(6 , str); }
+static void print_debug_char(unsigned char byte) { __console_tx_char(7 , byte); }
+static void print_debug_hex8(unsigned char value) { __console_tx_hex8(7 , value); }
+static void print_debug_hex16(unsigned short value){ __console_tx_hex16(7 , value); }
+static void print_debug_hex32(unsigned int value) { __console_tx_hex32(7 , value); }
+static void print_debug(const char *str) { __console_tx_string(7 , str); }
+static void print_spew_char(unsigned char byte) { __console_tx_char(8 , byte); }
+static void print_spew_hex8(unsigned char value) { __console_tx_hex8(8 , value); }
+static void print_spew_hex16(unsigned short value){ __console_tx_hex16(8 , value); }
+static void print_spew_hex32(unsigned int value) { __console_tx_hex32(8 , value); }
+static void print_spew(const char *str) { __console_tx_string(8 , str); }
+static void console_init(void)
+{
+	static const char console_test[] = 
+		"\r\n\r\nLinuxBIOS-"
+		"1.1.4"  
+		".0Fallback"  
+		" "
+		"Thu Oct 9 20:29:48 MDT 2003"  
+		" starting...\r\n";
+	print_info(console_test);
+}
+static void die(const char *str)
+{
+	print_emerg(str);
+	do {
+		hlt();
+	} while(1);
+}
+static void write_phys(unsigned long addr, unsigned long value)
+{
+	asm volatile(
+		"movnti %1, (%0)"
+		:  
+		: "r" (addr), "r" (value)  
+		:  
+		);
+}
+static unsigned long read_phys(unsigned long addr)
+{
+	volatile unsigned long *ptr;
+	ptr = (void *)addr;
+	return *ptr;
+}
+static void ram_fill(unsigned long start, unsigned long stop)
+{
+	unsigned long addr;
+	 
+	print_debug("DRAM fill: ");
+	print_debug_hex32(start);
+	print_debug("-");
+	print_debug_hex32(stop);
+	print_debug("\r\n");
+	for(addr = start; addr < stop ; addr += 4) {
+		 
+		if (!(addr & 0xffff)) {
+			print_debug_hex32(addr);
+			print_debug("\r");
+		}
+		write_phys(addr, addr);
+	};
+	 
+	print_debug_hex32(addr);
+	print_debug("\r\nDRAM filled\r\n");
+}
+static void ram_verify(unsigned long start, unsigned long stop)
+{
+	unsigned long addr;
+	 
+	print_debug("DRAM verify: ");
+	print_debug_hex32(start);
+	print_debug_char('-');
+	print_debug_hex32(stop);
+	print_debug("\r\n");
+	for(addr = start; addr < stop ; addr += 4) {
+		unsigned long value;
+		 
+		if (!(addr & 0xffff)) {
+			print_debug_hex32(addr);
+			print_debug("\r");
+		}
+		value = read_phys(addr);
+		if (value != addr) {
+			 
+			print_err_hex32(addr);
+			print_err_char(':');
+			print_err_hex32(value);
+			print_err("\r\n");
+		}
+	}
+	 
+	print_debug_hex32(addr);
+	print_debug("\r\nDRAM verified\r\n");
+}
+void ram_check(unsigned long start, unsigned long stop)
+{
+	int result;
+	 
+	print_debug("Testing DRAM : ");
+	print_debug_hex32(start);
+	print_debug("-");	
+	print_debug_hex32(stop);
+	print_debug("\r\n");
+	ram_fill(start, stop);
+	ram_verify(start, stop);
+	print_debug("Done.\r\n");
+}
+static int enumerate_ht_chain(unsigned link)
+{
+	 
+	unsigned next_unitid, last_unitid;
+	int reset_needed = 0;
+	next_unitid = 1;
+	do {
+		uint32_t id;
+		uint8_t hdr_type, pos;
+		last_unitid = next_unitid;
+		id = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , 0x00 );
+		 
+		if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0x0000)) {
+			break;
+		}
+		hdr_type = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , 0x0e );
+		pos = 0;
+		hdr_type &= 0x7f;
+		if ((hdr_type == 0 ) ||
+			(hdr_type == 1 )) {
+			pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , 0x34 );
+		}
+		while(pos != 0) {
+			uint8_t cap;
+			cap = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , pos + 0 );
+			if (cap == 0x08 ) {
+				uint16_t flags;
+				flags = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8)) , pos + 2 );
+				if ((flags >> 13) == 0) {
+					unsigned count;
+					flags &= ~0x1f;
+					flags |= next_unitid & 0x1f;
+					count = (flags >> 5) & 0x1f;
+					pci_write_config16(( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , pos + 2 , flags);
+					next_unitid += count;
+					break;
+				}
+			}
+			pos = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , pos + 1 );
+		}
+	} while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
+	return reset_needed;
+}
+static void enable_smbus(void)
+{
+	device_t dev;
+	dev = pci_locate_device(((((  0x746b ) & 0xFFFF) << 16) | (( 0x1022 ) & 0xFFFF)) , 0);
+	if (dev == (0xffffffffU) ) {
+		die("SMBUS controller not found\r\n");
+	}
+	uint8_t enable;
+	print_debug("SMBus controller enabled\r\n");
+	pci_write_config32(dev, 0x58, 0x0f00  | 1);
+	enable = pci_read_config8(dev, 0x41);
+	pci_write_config8(dev, 0x41, enable | (1 << 7));
+	 
+	outw(inw(0x0f00  + 0xe0 ), 0x0f00  + 0xe0 );
+}
+static inline void smbus_delay(void)
+{
+	outb(0x80, 0x80);
+}
+static int smbus_wait_until_ready(void)
+{
+	unsigned long loops;
+	loops = (100*1000*10) ;
+	do {
+		unsigned short val;
+		smbus_delay();
+		val = inw(0x0f00  + 0xe0 );
+		if ((val & 0x800) == 0) {
+			break;
+		}
+		if(loops == ((100*1000*10)  / 2)) {
+			outw(inw(0x0f00  + 0xe0 ), 
+				0x0f00  + 0xe0 );
+		}
+	} while(--loops);
+	return loops?0:-2;
+}
+static int smbus_wait_until_done(void)
+{
+	unsigned long loops;
+	loops = (100*1000*10) ;
+	do {
+		unsigned short val;
+		smbus_delay();
+		
+		val = inw(0x0f00  + 0xe0 );
+		if (((val & 0x8) == 0) | ((val & 0x437) != 0)) {
+			break;
+		}
+	} while(--loops);
+	return loops?0:-3;
+}
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+	unsigned char global_control_register;
+	unsigned char global_status_register;
+	unsigned char byte;
+	if (smbus_wait_until_ready() < 0) {
+		return -2;
+	}
+	
+	 
+	 
+	outw(inw(0x0f00  + 0xe2 ) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), 0x0f00  + 0xe2 );
+	 
+	outw(((device & 0x7f) << 1) | 1, 0x0f00  + 0xe4 );
+	 
+	outb(address & 0xFF, 0x0f00  + 0xe8 );
+	 
+	outw((inw(0x0f00  + 0xe2 ) & ~7) | (0x2), 0x0f00  + 0xe2 );
+	 
+	 
+	outw(inw(0x0f00  + 0xe0 ), 0x0f00  + 0xe0 );
+	 
+	outw(0, 0x0f00  + 0xe6 );
+	 
+	outw((inw(0x0f00  + 0xe2 ) | (1 << 3)), 0x0f00  + 0xe2 );
+	 
+	if (smbus_wait_until_done() < 0) {
+		return -3;
+	}
+	global_status_register = inw(0x0f00  + 0xe0 );
+	 
+	byte = inw(0x0f00  + 0xe6 ) & 0xff;
+	if (global_status_register != (1 << 4)) {
+		return -1;
+	}
+	return byte;
+}
+static void smbus_write_byte(unsigned device, unsigned address, unsigned char val)
+{
+	return;
+}
+struct mem_controller {
+	unsigned node_id;
+	device_t f0, f1, f2, f3;
+	uint8_t channel0[4];
+	uint8_t channel1[4];
+};
+typedef __builtin_msr_t msr_t;
+static msr_t rdmsr(unsigned long index)
+{
+	return __builtin_rdmsr(index);
+}
+static void wrmsr(unsigned long index, msr_t msr)
+{
+	__builtin_wrmsr(index, msr.lo, msr.hi);
+}
+struct tsc_struct {
+	unsigned lo;
+	unsigned hi;
+};
+typedef struct tsc_struct tsc_t;
+static tsc_t rdtsc(void)
+{
+	tsc_t res;
+	asm ("rdtsc"
+		: "=a" (res.lo), "=d"(res.hi)  
+		:  
+		:  
+		);
+	return res;
+}
+void init_timer(void)
+{
+	 
+	apic_write(0x320 , (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0));
+	 
+	apic_write(0x3E0 , 0xB );
+	 
+	apic_write(0x380 , 0xffffffff);
+}
+void udelay(unsigned usecs)
+{
+	uint32_t start, value, ticks;
+	 
+	ticks = usecs * 200;
+	start = apic_read(0x390 );
+	do {
+		value = apic_read(0x390 );
+	} while((start - value) < ticks);
+	
+}
+void mdelay(unsigned msecs)
+{
+	unsigned i;
+	for(i = 0; i < msecs; i++) {
+		udelay(1000);
+	}
+}
+void delay(unsigned secs)
+{
+	unsigned i;
+	for(i = 0; i < secs; i++) {
+		mdelay(1000);
+	}
+}
+int boot_cpu(void)
+{
+	volatile unsigned long *local_apic;
+	unsigned long apic_id;
+	int bsp;
+	msr_t msr;
+	msr = rdmsr(0x1b);
+	bsp = !!(msr.lo & (1 << 8));
+	return bsp;
+}
+static int cpu_init_detected(void)
+{
+	unsigned long htic;
+	htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
+	return !!(htic & (1<<6) );
+}
+static int bios_reset_detected(void)
+{
+	unsigned long htic;
+	htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
+	return (htic & (1<<4) ) && !(htic & (1<<5) );
+}
+static int cold_reset_detected(void)
+{
+	unsigned long htic;
+	htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
+	return !(htic & (1<<4) );
+}
+static void distinguish_cpu_resets(unsigned node_id)
+{
+	uint32_t htic;
+	device_t device;
+	device = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 + node_id ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ;
+	htic = pci_read_config32(device, 0x6c );
+	htic |= (1<<4)  | (1<<5)  | (1<<6) ;
+	pci_write_config32(device, 0x6c , htic);
+}
+static void set_bios_reset(void)
+{
+	unsigned long htic;
+	htic = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c );
+	htic &= ~(1<<5) ;
+	pci_write_config32(( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) , 0x6c , htic);
+}
+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;
+	for(dev = ( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ; 
+		dev <= ( ((( 0 ) & 0xFF) << 16) | (((  0x1f ) & 0x1f) << 11) | (((  0x7 )  & 0x7) << 8)) ; 
+		dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8)) ) {
+		uint32_t id;
+		id = pci_read_config32(dev, 0x00 );
+		if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0x0000)) {
+			continue;
+		}
+		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_pci_devices(void)
+{
+	device_t dev;
+	for(dev = ( ((( 0 ) & 0xFF) << 16) | (((  0 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ; 
+		dev <= ( ((( 0 ) & 0xFF) << 16) | (((  0x1f ) & 0x1f) << 11) | (((  0x7 )  & 0x7) << 8)) ; 
+		dev += ( ((( 0 ) & 0xFF) << 16) | ((( 0 ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8)) ) {
+		uint32_t id;
+		id = pci_read_config32(dev, 0x00 );
+		if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0xffff) ||
+			(((id >> 16) & 0xffff) == 0x0000)) {
+			continue;
+		}
+		dump_pci_device(dev);
+	}
+}
+static void dump_spd_registers(const struct mem_controller *ctrl)
+{
+	int i;
+	print_debug("\r\n");
+	for(i = 0; i < 4; i++) {
+		unsigned device;
+		device = ctrl->channel0[i];
+		if (device) {
+			int j;
+			print_debug("dimm: "); 
+			print_debug_hex8(i); 
+			print_debug(".0: ");
+			print_debug_hex8(device);
+			for(j = 0; j < 256; j++) {
+				int status;
+				unsigned char byte;
+				if ((j & 0xf) == 0) {
+					print_debug("\r\n");
+					print_debug_hex8(j);
+					print_debug(": ");
+				}
+				status = smbus_read_byte(device, j);
+				if (status < 0) {
+					print_debug("bad device\r\n");
+					break;
+				}
+				byte = status & 0xff;
+				print_debug_hex8(byte);
+				print_debug_char(' ');
+			}
+			print_debug("\r\n");
+		}
+		device = ctrl->channel1[i];
+		if (device) {
+			int j;
+			print_debug("dimm: "); 
+			print_debug_hex8(i); 
+			print_debug(".1: ");
+			print_debug_hex8(device);
+			for(j = 0; j < 256; j++) {
+				int status;
+				unsigned char byte;
+				if ((j & 0xf) == 0) {
+					print_debug("\r\n");
+					print_debug_hex8(j);
+					print_debug(": ");
+				}
+				status = smbus_read_byte(device, j);
+				if (status < 0) {
+					print_debug("bad device\r\n");
+					break;
+				}
+				byte = status & 0xff;
+				print_debug_hex8(byte);
+				print_debug_char(' ');
+			}
+			print_debug("\r\n");
+		}
+	}
+}
+ 
+static unsigned int cpuid(unsigned int op)
+{
+	unsigned int ret;
+	unsigned dummy2,dummy3,dummy4;
+	asm volatile ( 
+		"cpuid" 
+		: "=a" (ret), "=b" (dummy2), "=c" (dummy3), "=d" (dummy4)
+		: "a" (op)
+		);
+	return ret;
+}
+static int is_cpu_rev_a0(void)
+{
+	return (cpuid(1) & 0xffff) == 0x0f10;
+}
+static int is_cpu_pre_c0(void)
+{
+	return (cpuid(1) & 0xffef) < 0x0f48;
+}
+static void memreset_setup(void)
+{
+	if (is_cpu_pre_c0()) {
+		 
+		outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00  + 0xc0 + 28);
+		 
+		outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0x0f00  + 0xc0 + 29);
+	}
+	else {
+		 
+		outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00  + 0xc0 + 29);
+	}
+}
+static void memreset(int controllers, const struct mem_controller *ctrl)
+{
+	if (is_cpu_pre_c0()) {
+		udelay(800);
+		 
+		outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0x0f00  + 0xc0 + 28);
+		udelay(90);
+	}
+}
+static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
+{
+	 
+	uint32_t ret=0x00010101;  
+	static const unsigned int rows_2p[2][2] = {
+		{ 0x00050101, 0x00010404 },
+		{ 0x00010404, 0x00050101 }
+	};
+	if(maxnodes>2) {
+		print_debug("this mainboard is only designed for 2 cpus\r\n");
+		maxnodes=2;
+	}
+	if (!(node>=maxnodes || row>=maxnodes)) {
+		ret=rows_2p[node][row];
+	}
+	return ret;
+}
+static inline int spd_read_byte(unsigned device, unsigned address)
+{
+	return smbus_read_byte(device, address);
+}
+ 
+static void coherent_ht_mainboard(unsigned cpus)
+{
+}
+ 
+void cpu_ldtstop(unsigned cpus)
+{
+	uint32_t tmp;
+	device_t dev;
+	unsigned cnt;
+	for(cnt=0; cnt<cpus; cnt++) {
+		 
+        	pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8)) ,0x81,0x23);
+		 
+		pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8)) ,0xd4,0x00000701);
+		 
+		pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8)) ,0xd8,0x00000000);
+		 
+		tmp=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 )  & 0x7) << 8)) ,0x90);
+		pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24 ) & 0x1f) << 11) | ((( 2 )  & 0x7) << 8)) ,0x90, tmp | (1<<24) );
+	}
+}
+ 
+ 
+ 
+ 
+ 
+static void setup_resource_map(const unsigned int *register_values, int max)
+{
+	int i;
+	print_debug("setting up resource map....\r\n");
+	for(i = 0; i < max; i += 3) {
+		device_t dev;
+		unsigned where;
+		unsigned long reg;
+		dev = register_values[i] & ~0xff;
+		where = register_values[i] & 0xff;
+		reg = pci_read_config32(dev, where);
+		reg &= register_values[i+1];
+		reg |= register_values[i+2];
+		pci_write_config32(dev, where, reg);
+	}
+	print_debug("done.\r\n");
+}
+static void setup_default_resource_map(void)
+{
+	static const unsigned int register_values[] = {
+	 
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x84 ) & 0xFF)) , 0x00000048, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x8C ) & 0xFF)) , 0x00000048, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x94 ) & 0xFF)) , 0x00000048, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x9C ) & 0xFF)) , 0x00000048, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xA4 ) & 0xFF)) , 0x00000048, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xAC ) & 0xFF)) , 0x00000048, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xB4 ) & 0xFF)) , 0x00000048, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xBC ) & 0xFF)) , 0x00000048, 0x00ffff00,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x80 ) & 0xFF)) , 0x000000f0, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x88 ) & 0xFF)) , 0x000000f0, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x90 ) & 0xFF)) , 0x000000f0, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x98 ) & 0xFF)) , 0x000000f0, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xA0 ) & 0xFF)) , 0x000000f0, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xA8 ) & 0xFF)) , 0x000000f0, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xB0 ) & 0xFF)) , 0x000000f0, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xB8 ) & 0xFF)) , 0x000000f0, 0x00fc0003,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xC4 ) & 0xFF)) , 0xFE000FC8, 0x01fff000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xCC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xD4 ) & 0xFF)) , 0xFE000FC8, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xDC ) & 0xFF)) , 0xFE000FC8, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xC0 ) & 0xFF)) , 0xFE000FCC, 0x00000003,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xC8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xD0 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xD8 ) & 0xFF)) , 0xFE000FCC, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xE0 ) & 0xFF)) , 0x0000FC88, 0xff000003,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xE4 ) & 0xFF)) , 0x0000FC88, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xE8 ) & 0xFF)) , 0x0000FC88, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0xEC ) & 0xFF)) , 0x0000FC88, 0x00000000,
+	};
+	int max;
+	max = sizeof(register_values)/sizeof(register_values[0]);
+	setup_resource_map(register_values, max);
+}
+static void sdram_set_registers(const struct mem_controller *ctrl)
+{
+	static const unsigned int register_values[] = {
+	 
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x44 ) & 0xFF)) , 0x0000f8f8, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x4C ) & 0xFF)) , 0x0000f8f8, 0x00000001,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x54 ) & 0xFF)) , 0x0000f8f8, 0x00000002,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x0000f8f8, 0x00000003,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x64 ) & 0xFF)) , 0x0000f8f8, 0x00000004,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x6C ) & 0xFF)) , 0x0000f8f8, 0x00000005,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x74 ) & 0xFF)) , 0x0000f8f8, 0x00000006,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x7C ) & 0xFF)) , 0x0000f8f8, 0x00000007,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x40 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x48 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x50 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x68 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x70 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 ) & 0x07) << 8) | ((  0x78 ) & 0xFF)) , 0x0000f8fc, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x40 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x44 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x48 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x4C ) & 0xFF)) , 0x001f01fe, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x50 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x54 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0x001f01fe, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x001f01fe, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x64 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x68 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x6C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x70 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x74 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x78 ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x7C ) & 0xFF)) , 0xC01f01ff, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x80 ) & 0xFF)) , 0xffff8888, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x88 ) & 0xFF)) , 0xe8088008, 0x02522001   ,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x8c ) & 0xFF)) , 0xff8fe08e, (0 << 20)|(0 << 8)|(0 << 4)|(0 << 0),
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x90 ) & 0xFF)) , 0xf0000000, 
+	(4 << 25)|(0 << 24)| 
+	(0 << 23)|(0 << 22)|(0 << 21)|(0 << 20)| 
+	(1 << 19)|(0 << 18)|(1 << 17)|(0 << 16)| 
+	(2 << 14)|(0 << 13)|(0 << 12)| 
+	(0 << 11)|(0 << 10)|(0 << 9)|(0 << 8)| 
+	(0 << 3) |(0 << 1) |(0 << 0),
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x94 ) & 0xFF)) , 0xc180f0f0,
+	(0 << 29)|(0 << 28)|(0 << 27)|(0 << 26)|(0 << 25)|
+	(0 << 20)|(0 << 19)|(3  << 16)|(0 << 8)|(0 << 0),
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 ) & 0x07) << 8) | ((  0x98 ) & 0xFF)) , 0xfc00ffff, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x58 ) & 0xFF)) , 0xffe0e0e0, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x5C ) & 0xFF)) , 0x0000003e, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x60 ) & 0xFF)) , 0xffffff00, 0x00000000,
+	 
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x94 ) & 0xFF)) , 0xffff8000, 0x00000f70,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x90 ) & 0xFF)) , 0xffffff80, 0x00000002,
+	( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 ) & 0x07) << 8) | ((  0x98 ) & 0xFF)) , 0x0000000f, 0x00068300,
+	};
+	int i;
+	int max;
+	print_debug("setting up CPU");
+	print_debug_hex8(ctrl->node_id);
+	print_debug(" northbridge registers\r\n");
+	max = sizeof(register_values)/sizeof(register_values[0]);
+	for(i = 0; i < max; i += 3) {
+		device_t dev;
+		unsigned where;
+		unsigned long reg;
+		dev = (register_values[i] & ~0xff) - ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8))  + ctrl->f0;
+		where = register_values[i] & 0xff;
+		reg = pci_read_config32(dev, where);
+		reg &= register_values[i+1];
+		reg |= register_values[i+2];
+		pci_write_config32(dev, where, reg);
+	}
+	print_debug("done.\r\n");
+}
+static int is_dual_channel(const struct mem_controller *ctrl)
+{
+	uint32_t dcl;
+	dcl = pci_read_config32(ctrl->f2, 0x90 );
+	return dcl & (1<<16) ;
+}
+static int is_opteron(const struct mem_controller *ctrl)
+{
+	 
+	uint32_t nbcap;
+	nbcap = pci_read_config32(ctrl->f3, 0xE8 );
+	return !!(nbcap & 0x0001 );
+}
+static int is_registered(const struct mem_controller *ctrl)
+{
+	 
+	uint32_t dcl;
+	dcl = pci_read_config32(ctrl->f2, 0x90 );
+	return !(dcl & (1<<18) );
+}
+struct dimm_size {
+	unsigned long side1;
+	unsigned long side2;
+};
+static struct dimm_size spd_get_dimm_size(unsigned device)
+{
+	 
+	struct dimm_size sz;
+	int value, low;
+	sz.side1 = 0;
+	sz.side2 = 0;
+	 
+	value = spd_read_byte(device, 3);	 
+	if (value < 0) goto out;
+	sz.side1 += value & 0xf;
+	value = spd_read_byte(device, 4);	 
+	if (value < 0) goto out;
+	sz.side1 += value & 0xf;
+	value = spd_read_byte(device, 17);	 
+	if (value < 0) goto out;
+	sz.side1 += log2(value & 0xff);
+	 
+	value = spd_read_byte(device, 7);	 
+	if (value < 0) goto out;
+	value &= 0xff;
+	value <<= 8;
+	
+	low = spd_read_byte(device, 6);	 
+	if (low < 0) goto out;
+	value = value | (low & 0xff);
+	sz.side1 += log2(value);
+	 
+	value = spd_read_byte(device, 5);	 
+	if (value <= 1) goto out;
+	 
+	sz.side2 = sz.side1;
+	value = spd_read_byte(device, 3);	 
+	if (value < 0) goto out;
+	if ((value & 0xf0) == 0) goto out;	 
+	sz.side2 -= (value & 0x0f);		 
+	sz.side2 += ((value >> 4) & 0x0f);	 
+	value = spd_read_byte(device, 4);	 
+	if (value < 0) goto out;
+	sz.side2 -= (value & 0x0f);		 
+	sz.side2 += ((value >> 4) & 0x0f);	 
+ out:
+	return sz;
+}
+static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index)
+{
+	uint32_t base0, base1, map;
+	uint32_t dch;
+	if (sz.side1 != sz.side2) {
+		sz.side2 = 0;
+	}
+	map = pci_read_config32(ctrl->f2, 0x80 );
+	map &= ~(0xf << (index + 4));
+	 
+	
+	base0 = base1 = 0;
+	 
+	if (sz.side1 >= (25 +3)) {
+		map |= (sz.side1 - (25 + 3)) << (index *4);
+		base0 = (1 << ((sz.side1 - (25 + 3)) + 21)) | 1;
+	}
+	 
+	if (sz.side2 >= (25 + 3)) {
+		base1 = (1 << ((sz.side2 - (25 + 3)) + 21)) | 1;
+	}
+	 
+	if (is_dual_channel(ctrl)) {
+		base0 = (base0 << 1) | (base0 & 1);
+		base1 = (base1 << 1) | (base1 & 1);
+	}
+	 
+	base0 &= ~0x001ffffe;
+	base1 &= ~0x001ffffe;
+	 
+	pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+0)<<2), base0);
+	pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+1)<<2), base1);
+	pci_write_config32(ctrl->f2, 0x80 , map);
+	
+	 
+	if (base0) {
+		dch = pci_read_config32(ctrl->f2, 0x94 );
+		dch |= (1 << 26)  << index;
+		pci_write_config32(ctrl->f2, 0x94 , dch);
+	}
+}
+static void spd_set_ram_size(const struct mem_controller *ctrl)
+{
+	int i;
+	
+	for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+		struct dimm_size sz;
+		sz = spd_get_dimm_size(ctrl->channel0[i]);
+		set_dimm_size(ctrl, sz, i);
+	}
+}
+static void route_dram_accesses(const struct mem_controller *ctrl,
+	unsigned long base_k, unsigned long limit_k)
+{
+	 
+	unsigned node_id;
+	unsigned limit;
+	unsigned base;
+	unsigned index;
+	unsigned limit_reg, base_reg;
+	device_t device;
+	node_id = ctrl->node_id;
+	index = (node_id << 3);
+	limit = (limit_k << 2);
+	limit &= 0xffff0000;
+	limit -= 0x00010000;
+	limit |= ( 0 << 8) | (node_id << 0);
+	base = (base_k << 2);
+	base &= 0xffff0000;
+	base |= (0 << 8) | (1<<1) | (1<<0);
+	limit_reg = 0x44 + index;
+	base_reg = 0x40 + index;
+	for(device = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ; device <= ( ((( 0 ) & 0xFF) << 16) | (((  0x1f ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ; device += ( ((( 0 ) & 0xFF) << 16) | (((  1 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ) {
+		pci_write_config32(device, limit_reg, limit);
+		pci_write_config32(device, base_reg, base);
+	}
+}
+static void set_top_mem(unsigned tom_k)
+{
+	 
+	if (!tom_k) {
+		set_bios_reset();
+		print_debug("No memory - reset");
+		 
+		pci_write_config8(( ((( 0 ) & 0xFF) << 16) | (((  0x04 ) & 0x1f) << 11) | (((  3 )  & 0x7) << 8)) , 0x41, 0xf1);
+		 
+		outb(0x0e, 0x0cf9);
+	}
+	 
+	print_debug("RAM: 0x");
+	print_debug_hex32(tom_k);
+	print_debug(" KB\r\n");
+	 
+	msr_t msr;
+	msr.lo = (tom_k & 0x003fffff) << 10;
+	msr.hi = (tom_k & 0xffc00000) >> 22;
+	wrmsr(0xC001001D , msr);
+	 
+	if (tom_k >= 0x003f0000) {
+		tom_k = 0x3f0000;
+	}
+	msr.lo = (tom_k & 0x003fffff) << 10;
+	msr.hi = (tom_k & 0xffc00000) >> 22;
+	wrmsr(0xC001001A , msr);
+}
+static unsigned long interleave_chip_selects(const struct mem_controller *ctrl)
+{
+	 
+	static const uint32_t csbase_low[] = { 
+	 	(1 << (13 - 4)),
+	 	(1 << (14 - 4)),
+	 	(1 << (14 - 4)), 
+	 	(1 << (15 - 4)),
+	 	(1 << (15 - 4)),
+	 	(1 << (16 - 4)),
+	 	(1 << (16 - 4)), 
+	};
+	uint32_t csbase_inc;
+	int chip_selects, index;
+	int bits;
+	int dual_channel;
+	unsigned common_size;
+	uint32_t csbase, csmask;
+	 
+	chip_selects = 0;
+	common_size = 0;
+	for(index = 0; index < 8; index++) {
+		unsigned size;
+		uint32_t value;
+		
+		value = pci_read_config32(ctrl->f2, 0x40  + (index << 2));
+		
+		 
+		if (!(value & 1)) {
+			continue;
+		}
+		chip_selects++;
+		size = value >> 21;
+		if (common_size == 0) {
+			common_size = size;
+		}
+		 
+		if (common_size != size) {
+			return 0;
+		}
+	}
+	 
+	bits = log2(chip_selects);
+	if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) {
+		return 0;
+		
+	}
+	 
+	if ((bits == 3) && (common_size == (1 << (32 - 3)))) {
+		print_debug("8 4GB chip selects cannot be interleaved\r\n");
+		return 0;
+	}
+	 
+	if (is_dual_channel(ctrl)) {
+		csbase_inc = csbase_low[log2(common_size) - 1] << 1;
+	} else {
+		csbase_inc = csbase_low[log2(common_size)];
+	}
+	 
+	csbase = 0 | 1;
+	csmask = (((common_size  << bits) - 1) << 21);
+	csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc);
+	for(index = 0; index < 8; index++) {
+		uint32_t value;
+		value = pci_read_config32(ctrl->f2, 0x40  + (index << 2));
+		 
+		if (!(value & 1)) {
+			continue;
+		}
+		pci_write_config32(ctrl->f2, 0x40  + (index << 2), csbase);
+		pci_write_config32(ctrl->f2, 0x60  + (index << 2), csmask);
+		csbase += csbase_inc;
+	}
+	
+	print_debug("Interleaved\r\n");
+	 
+	return common_size << (15 + bits);
+}
+static unsigned long order_chip_selects(const struct mem_controller *ctrl)
+{
+	unsigned long tom;
+	
+	 
+	tom = 0;
+	for(;;) {
+		 
+		unsigned index, canidate;
+		uint32_t csbase, csmask;
+		unsigned size;
+		csbase = 0;
+		canidate = 0;
+		for(index = 0; index < 8; index++) {
+			uint32_t value;
+			value = pci_read_config32(ctrl->f2, 0x40  + (index << 2));
+			 
+			if (!(value & 1)) {
+				continue;
+			}
+			
+			 
+			if (value <= csbase) {
+				continue;
+			}
+			
+			 
+			if (tom & (1 << (index + 24))) {
+				continue;
+			}
+			 
+			csbase = value;
+			canidate = index;
+		}
+		 
+		if (csbase == 0) {
+			break;
+		}
+		 
+		size = csbase >> 21;
+		 
+		tom |= (1 << (canidate + 24));
+		 
+		csbase = (tom << 21) | 1;
+		 
+		tom += size;
+		 
+		csmask = ((size -1) << 21);
+		csmask |= 0xfe00;		 
+		 
+		pci_write_config32(ctrl->f2, 0x40  + (canidate << 2), csbase);
+		 
+		pci_write_config32(ctrl->f2, 0x60  + (canidate << 2), csmask);
+		
+	}
+	 
+	return (tom & ~0xff000000) << 15;
+}
+static void order_dimms(const struct mem_controller *ctrl)
+{
+	unsigned long tom, tom_k, base_k;
+	unsigned node_id;
+	tom_k = interleave_chip_selects(ctrl);
+	if (!tom_k) {
+		tom_k = order_chip_selects(ctrl);
+	}
+	 
+	base_k = 0;
+	for(node_id = 0; node_id < ctrl->node_id; node_id++) {
+		uint32_t limit, base;
+		unsigned index;
+		index = node_id << 3;
+		base = pci_read_config32(ctrl->f1, 0x40 + index);
+		 
+		if ((base & 3) == 3) {
+			limit = pci_read_config32(ctrl->f1, 0x44 + index);
+			base_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
+		}
+	}
+	tom_k += base_k;
+	route_dram_accesses(ctrl, base_k, tom_k);
+	set_top_mem(tom_k);
+}
+static void disable_dimm(const struct mem_controller *ctrl, unsigned index)
+{
+	print_debug("disabling dimm"); 
+	print_debug_hex8(index); 
+	print_debug("\r\n");
+	pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+0)<<2), 0);
+	pci_write_config32(ctrl->f2, 0x40  + (((index << 1)+1)<<2), 0);
+}
+static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
+{
+	int i;
+	int registered;
+	int unbuffered;
+	uint32_t dcl;
+	unbuffered = 0;
+	registered = 0;
+	for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+		int value;
+		value = spd_read_byte(ctrl->channel0[i], 21);
+		if (value < 0) {
+			disable_dimm(ctrl, i);
+			continue;
+		}
+		 
+		if (value & (1 << 1)) {
+			registered = 1;
+		} 
+		 
+		else {
+			unbuffered = 1;
+		}
+	}
+	if (unbuffered && registered) {
+		die("Mixed buffered and registered dimms not supported");
+	}
+	if (unbuffered && is_opteron(ctrl)) {
+		die("Unbuffered Dimms not supported on Opteron");
+	}
+	dcl = pci_read_config32(ctrl->f2, 0x90 );
+	dcl &= ~(1<<18) ;
+	if (unbuffered) {
+		dcl |= (1<<18) ;
+	}
+	pci_write_config32(ctrl->f2, 0x90 , dcl);
+}
+static void spd_enable_2channels(const struct mem_controller *ctrl)
+{
+	int i;
+	uint32_t nbcap;
+	 
+	 
+	static const unsigned addresses[] = {
+		2,	 
+		3,	 
+		4,	 
+		5,	 
+		6,	 
+		7,	 
+		9,	 
+		11,	 
+		13,	 
+		17,	 
+		18,	 
+		21,	 
+		23,	 
+		26,	 
+		27,	 
+		28,	 
+		29,	 
+		30,	 
+		41,	 
+		42,	 
+	};
+	nbcap = pci_read_config32(ctrl->f3, 0xE8 );
+	if (!(nbcap & 0x0001 )) {
+		return;
+	}
+	for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+		unsigned device0, device1;
+		int value0, value1;
+		int j;
+		device0 = ctrl->channel0[i];
+		device1 = ctrl->channel1[i];
+		if (!device1)
+			return;
+		for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) {
+			unsigned addr;
+			addr = addresses[j];
+			value0 = spd_read_byte(device0, addr);
+			if (value0 < 0) {
+				break;
+			}
+			value1 = spd_read_byte(device1, addr);
+			if (value1 < 0) {
+				return;
+			}
+			if (value0 != value1) {
+				return;
+			}
+		}
+	}
+	print_debug("Enabling dual channel memory\r\n");
+	uint32_t dcl;
+	dcl = pci_read_config32(ctrl->f2, 0x90 );
+	dcl &= ~(1<<19) ;
+	dcl |= (1<<16) ;
+	pci_write_config32(ctrl->f2, 0x90 , dcl);
+}
+struct mem_param {
+	uint8_t cycle_time;
+	uint8_t divisor;  
+	uint8_t tRC;
+	uint8_t tRFC;
+	uint32_t dch_memclk;
+	uint16_t dch_tref4k, dch_tref8k;
+	uint8_t	 dtl_twr;
+	char name[9];
+};
+static const struct mem_param *get_mem_param(unsigned min_cycle_time)
+{
+	static const struct mem_param speed[] = {
+		{
+			.name	    = "100Mhz\r\n",
+			.cycle_time = 0xa0,
+			.divisor    = (10 <<1),
+			.tRC	    = 0x46,
+			.tRFC	    = 0x50,
+			.dch_memclk = 0  << 20 ,
+			.dch_tref4k = 0x00 ,
+			.dch_tref8k = 0x08 ,
+			.dtl_twr    = 2,
+		},
+		{
+			.name	    = "133Mhz\r\n",
+			.cycle_time = 0x75,
+			.divisor    = (7<<1)+1,
+			.tRC	    = 0x41,
+			.tRFC	    = 0x4B,
+			.dch_memclk = 2  << 20 ,
+			.dch_tref4k = 0x01 ,
+			.dch_tref8k = 0x09 ,
+			.dtl_twr    = 2,
+		},
+		{
+			.name	    = "166Mhz\r\n",
+			.cycle_time = 0x60,
+			.divisor    = (6<<1),
+			.tRC	    = 0x3C,
+			.tRFC	    = 0x48,
+			.dch_memclk = 5  << 20 ,
+			.dch_tref4k = 0x02 ,
+			.dch_tref8k = 0x0A ,
+			.dtl_twr    = 3,
+		},
+		{
+			.name	    = "200Mhz\r\n",
+			.cycle_time = 0x50,
+			.divisor    = (5<<1),
+			.tRC	    = 0x37,
+			.tRFC	    = 0x46,
+			.dch_memclk = 7  << 20 ,
+			.dch_tref4k = 0x03 ,
+			.dch_tref8k = 0x0B ,
+			.dtl_twr    = 3,
+		},
+		{
+			.cycle_time = 0x00,
+		},
+	};
+	const struct mem_param *param;
+	for(param = &speed[0]; param->cycle_time ; param++) {
+		if (min_cycle_time > (param+1)->cycle_time) {
+			break;
+		}
+	}
+	if (!param->cycle_time) {
+		die("min_cycle_time to low");
+	}
+	print_debug(param->name);
+	return param;
+}
+static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
+{
+	 
+	const struct mem_param *param;
+	unsigned min_cycle_time, min_latency;
+	int i;
+	uint32_t value;
+	static const int latency_indicies[] = { 26, 23, 9 };
+	static const unsigned char min_cycle_times[] = {
+		[0 ] = 0x50,  
+		[1 ] = 0x60,  
+		[2 ] = 0x75,  
+		[3 ] = 0xa0,  
+	};
+	value = pci_read_config32(ctrl->f3, 0xE8 );
+	min_cycle_time = min_cycle_times[(value >> 5 ) & 3 ];
+	min_latency = 2;
+	 
+	for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+		int new_cycle_time, new_latency;
+		int index;
+		int latencies;
+		int latency;
+		 
+		new_cycle_time = 0xa0;
+		new_latency = 5;
+		latencies = spd_read_byte(ctrl->channel0[i], 18);
+		if (latencies <= 0) continue;
+		 
+		latency = log2(latencies) -2;
+		 
+		for(index = 0; index < 3; index++, latency++) {
+			int value;
+			if ((latency < 2) || (latency > 4) ||
+				(!(latencies & (1 << latency)))) {
+				continue;
+			}
+			value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
+			if (value < 0) {
+				continue;
+			}
+			 
+			if ((value >= min_cycle_time) && (value < new_cycle_time)) {
+				new_cycle_time = value;
+				new_latency = latency;
+			}
+		}
+		if (new_latency > 4){
+			continue;
+		}
+		 
+		if (new_cycle_time > min_cycle_time) {
+			min_cycle_time = new_cycle_time;
+		}
+		 
+		if (new_latency > min_latency) {
+			min_latency = new_latency;
+		}
+	}
+	 
+	
+	for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+		int latencies;
+		int latency;
+		int index;
+		int value;
+		int dimm;
+		latencies = spd_read_byte(ctrl->channel0[i], 18);
+		if (latencies <= 0) {
+			goto dimm_err;
+		}
+		 
+		latency = log2(latencies) -2;
+		 
+		for(index = 0; index < 3; index++, latency++) {
+			if (!(latencies & (1 << latency))) {
+				continue;
+			}
+			if (latency == min_latency)
+				break;
+		}
+		 
+		if ((latency != min_latency) || (index >= 3)) {
+			goto dimm_err;
+		}
+		
+		 
+		value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
+		
+		 
+		if (value <= min_cycle_time) {
+			continue;
+		}
+		 
+	dimm_err:
+		disable_dimm(ctrl, i);
+	}
+	 
+	param = get_mem_param(min_cycle_time);
+	 
+	value = pci_read_config32(ctrl->f2, 0x94 );
+	value &= ~(0x7  << 20 );
+	value |= param->dch_memclk;
+	pci_write_config32(ctrl->f2, 0x94 , value);
+	static const unsigned latencies[] = { 1 , 5 , 2  };
+	 
+	value = pci_read_config32(ctrl->f2, 0x88 );
+	value &= ~(0x7  << 0 );
+	value |= latencies[min_latency - 2] << 0 ;
+	pci_write_config32(ctrl->f2, 0x88 , value);
+	
+	return param;
+}
+static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+	unsigned clocks, old_clocks;
+	uint32_t dtl;
+	int value;
+	value = spd_read_byte(ctrl->channel0[i], 41);
+	if (value < 0) return -1;
+	if ((value == 0) || (value == 0xff)) {
+		value = param->tRC;
+	}
+	clocks = ((value << 1) + param->divisor - 1)/param->divisor;
+	if (clocks < 7 ) {
+		clocks = 7 ;
+	}
+	if (clocks > 22 ) {
+		return -1;
+	}
+	dtl = pci_read_config32(ctrl->f2, 0x88 );
+	old_clocks = ((dtl >> 4 ) & 0xf ) + 7 ;
+	if (old_clocks > clocks) {
+		clocks = old_clocks;
+	}
+	dtl &= ~(0xf  << 4 );
+	dtl |=	((clocks - 7 ) << 4 );
+	pci_write_config32(ctrl->f2, 0x88 , dtl);
+	return 0;
+}
+static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+	unsigned clocks, old_clocks;
+	uint32_t dtl;
+	int value;
+	value = spd_read_byte(ctrl->channel0[i], 42);
+	if (value < 0) return -1;
+	if ((value == 0) || (value == 0xff)) {
+		value = param->tRFC;
+	}
+	clocks = ((value << 1) + param->divisor - 1)/param->divisor;
+	if (clocks < 9 ) {
+		clocks = 9 ;
+	}
+	if (clocks > 24 ) {
+		return -1;
+	}
+	dtl = pci_read_config32(ctrl->f2, 0x88 );
+	old_clocks = ((dtl >> 8 ) & 0xf ) + 9 ;
+	if (old_clocks > clocks) {
+		clocks = old_clocks;
+	}
+	dtl &= ~(0xf  << 8 );
+	dtl |= ((clocks - 9 ) << 8 );
+	pci_write_config32(ctrl->f2, 0x88 , dtl);
+	return 0;
+}
+static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+	unsigned clocks, old_clocks;
+	uint32_t dtl;
+	int value;
+	value = spd_read_byte(ctrl->channel0[i], 29);
+	if (value < 0) return -1;
+	clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
+	if (clocks < 2 ) {
+		clocks = 2 ;
+	}
+	if (clocks > 6 ) {
+		return -1;
+	}
+	dtl = pci_read_config32(ctrl->f2, 0x88 );
+	old_clocks = ((dtl >> 12 ) & 0x7 ) + 0 ;
+	if (old_clocks > clocks) {
+		clocks = old_clocks;
+	}
+	dtl &= ~(0x7  << 12 );
+	dtl |= ((clocks - 0 ) << 12 );
+	pci_write_config32(ctrl->f2, 0x88 , dtl);
+	return 0;
+}
+static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+	unsigned clocks, old_clocks;
+	uint32_t dtl;
+	int value;
+	value = spd_read_byte(ctrl->channel0[i], 28);
+	if (value < 0) return -1;
+	clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
+	if (clocks < 2 ) {
+		clocks = 2 ;
+	}
+	if (clocks > 4 ) {
+		return -1;
+	}
+	dtl = pci_read_config32(ctrl->f2, 0x88 );
+	old_clocks = ((dtl >> 16 ) & 0x7 ) + 0 ;
+	if (old_clocks > clocks) {
+		clocks = old_clocks;
+	}
+	dtl &= ~(0x7  << 16 );
+	dtl |= ((clocks - 0 ) << 16 );
+	pci_write_config32(ctrl->f2, 0x88 , dtl);
+	return 0;
+}
+static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+	unsigned clocks, old_clocks;
+	uint32_t dtl;
+	int value;
+	value = spd_read_byte(ctrl->channel0[i], 30);
+	if (value < 0) return -1;
+	clocks = ((value << 1) + param->divisor - 1)/param->divisor;
+	if (clocks < 5 ) {
+		clocks = 5 ;
+	}
+	if (clocks > 15 ) {
+		return -1;
+	}
+	dtl = pci_read_config32(ctrl->f2, 0x88 );
+	old_clocks = ((dtl >> 20 ) & 0xf ) + 0 ;
+	if (old_clocks > clocks) {
+		clocks = old_clocks;
+	}
+	dtl &= ~(0xf  << 20 );
+	dtl |= ((clocks - 0 ) << 20 );
+	pci_write_config32(ctrl->f2, 0x88 , dtl);
+	return 0;
+}
+static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+	unsigned clocks, old_clocks;
+	uint32_t dtl;
+	int value;
+	value = spd_read_byte(ctrl->channel0[i], 27);
+	if (value < 0) return -1;
+	clocks = (value + ((param->divisor & 0xff) << 1) - 1)/((param->divisor & 0xff) << 1);
+	if (clocks < 2 ) {
+		clocks = 2 ;
+	}
+	if (clocks > 6 ) {
+		return -1;
+	}
+	dtl = pci_read_config32(ctrl->f2, 0x88 );
+	old_clocks = ((dtl >> 24 ) & 0x7 ) + 0 ;
+	if (old_clocks > clocks) {
+		clocks = old_clocks;
+	}
+	dtl &= ~(0x7  << 24 );
+	dtl |= ((clocks - 0 ) << 24 );
+	pci_write_config32(ctrl->f2, 0x88 , dtl);
+	return 0;
+}
+static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+	uint32_t dtl;
+	dtl = pci_read_config32(ctrl->f2, 0x88 );
+	dtl &= ~(0x1  << 28 );
+	dtl |= (param->dtl_twr - 2 ) << 28 ;
+	pci_write_config32(ctrl->f2, 0x88 , dtl);
+}
+static void init_Tref(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+	uint32_t dth;
+	dth = pci_read_config32(ctrl->f2, 0x8c );
+	dth &= ~(0x1f  << 8 );
+	dth |= (param->dch_tref4k << 8 );
+	pci_write_config32(ctrl->f2, 0x8c , dth);
+}
+static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+	uint32_t dth;
+	int value;
+	unsigned tref, old_tref;
+	value = spd_read_byte(ctrl->channel0[i], 3);
+	if (value < 0) return -1;
+	value &= 0xf;
+	tref = param->dch_tref8k;
+	if (value == 12) {
+		tref = param->dch_tref4k;
+	}
+	dth = pci_read_config32(ctrl->f2, 0x8c );
+	old_tref = (dth >> 8 ) & 0x1f ;
+	if ((value == 12) && (old_tref == param->dch_tref4k)) {
+		tref = param->dch_tref4k;
+	} else {
+		tref = param->dch_tref8k;
+	}
+	dth &= ~(0x1f  << 8 );
+	dth |= (tref << 8 );
+	pci_write_config32(ctrl->f2, 0x8c , dth);
+	return 0;
+}
+static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+	uint32_t dcl;
+	int value;
+	int dimm;
+	value = spd_read_byte(ctrl->channel0[i], 13);
+	if (value < 0) {
+		return -1;
+	}
+	dimm = i;
+	dimm += 20 ;
+	dcl = pci_read_config32(ctrl->f2, 0x90 );
+	dcl &= ~(1 << dimm);
+	if (value == 4) {
+		dcl |= (1 << dimm);
+	}
+	pci_write_config32(ctrl->f2, 0x90 , dcl);
+	return 0;
+}
+static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
+{
+	uint32_t dcl;
+	int value;
+	value = spd_read_byte(ctrl->channel0[i], 11);
+	if (value < 0) {
+		return -1;
+	}
+	if (value != 2) {
+		dcl = pci_read_config32(ctrl->f2, 0x90 );
+		dcl &= ~(1<<17) ;
+		pci_write_config32(ctrl->f2, 0x90 , dcl);
+	}
+	return 0;
+}
+static int count_dimms(const struct mem_controller *ctrl)
+{
+	int dimms;
+	unsigned index;
+	dimms = 0;
+	for(index = 0; index < 8; index += 2) {
+		uint32_t csbase;
+		csbase = pci_read_config32(ctrl->f2, (0x40  + index << 2));
+		if (csbase & 1) {
+			dimms += 1;
+		}
+	}
+	return dimms;
+}
+static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+	uint32_t dth;
+	unsigned clocks;
+	clocks = 1;  
+	dth = pci_read_config32(ctrl->f2, 0x8c );
+	dth &= ~(0x1  << 0 );
+	dth |= ((clocks - 1 ) << 0 );
+	pci_write_config32(ctrl->f2, 0x8c , dth);
+}
+static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+	uint32_t dth, dtl;
+	unsigned divisor;
+	unsigned latency;
+	unsigned clocks;
+	clocks = 0;
+	dtl = pci_read_config32(ctrl->f2, 0x88 );
+	latency = (dtl >> 0 ) & 0x7 ;
+	divisor = param->divisor;
+	if (is_opteron(ctrl)) {
+		if (latency == 1 ) {
+			if (divisor == ((6 << 0) + 0)) {
+				 
+				clocks = 3;
+			}
+			else if (divisor > ((6 << 0)+0)) {
+				 
+				clocks = 2;
+			}
+		}
+		else if (latency == 5 ) {
+			clocks = 3;
+		}
+		else if (latency == 2 ) {
+			if (divisor == ((6 << 0)+0)) {
+				 
+				clocks = 4;
+			}
+			else if (divisor > ((6 << 0)+0)) {
+				 
+				clocks = 3;
+			}
+		}
+	}
+	else   {
+		if (is_registered(ctrl)) {
+			if (latency == 1 ) {
+				clocks = 2;
+			}
+			else if (latency == 5 ) {
+				clocks = 3;
+			}
+			else if (latency == 2 ) {
+				clocks = 3;
+			}
+		}
+		else  {
+			if (latency == 1 ) {
+				clocks = 3;
+			}
+			else if (latency == 5 ) {
+				clocks = 4;
+			}
+			else if (latency == 2 ) {
+				clocks = 4;
+			}
+		}
+	}
+	if ((clocks < 1 ) || (clocks > 6 )) {
+		die("Unknown Trwt");
+	}
+	
+	dth = pci_read_config32(ctrl->f2, 0x8c );
+	dth &= ~(0x7  << 4 );
+	dth |= ((clocks - 1 ) << 4 );
+	pci_write_config32(ctrl->f2, 0x8c , dth);
+	return;
+}
+static void set_Twcl(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+	 
+	uint32_t dth;
+	unsigned clocks;
+	if (is_registered(ctrl)) {
+		clocks = 2;
+	} else {
+		clocks = 1;
+	}
+	dth = pci_read_config32(ctrl->f2, 0x8c );
+	dth &= ~(0x7  << 20 );
+	dth |= ((clocks - 1 ) << 20 );
+	pci_write_config32(ctrl->f2, 0x8c , dth);
+}
+static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+	uint32_t dch;
+	unsigned divisor;
+	unsigned rdpreamble;
+	divisor = param->divisor;
+	dch = pci_read_config32(ctrl->f2, 0x94 );
+	dch &= ~(0xf  << 8 );
+	rdpreamble = 0;
+	if (is_registered(ctrl)) {
+		if (divisor == ((10 << 1)+0)) {
+			 
+			rdpreamble = ((9 << 1)+ 0);
+		}
+		else if (divisor == ((7 << 1)+1)) {
+			 
+			rdpreamble = ((8 << 1)+0);
+		}
+		else if (divisor == ((6 << 1)+0)) {
+			 
+			rdpreamble = ((7 << 1)+1);
+		}
+		else if (divisor == ((5 << 1)+0)) {
+			 
+			rdpreamble = ((7 << 1)+0);
+		}
+	}
+	else {
+		int slots;
+		int i;
+		slots = 0;
+		for(i = 0; i < 4; i++) {
+			if (ctrl->channel0[i]) {
+				slots += 1;
+			}
+		}
+		if (divisor == ((10 << 1)+0)) {
+			 
+			if (slots <= 2) {
+				 
+				rdpreamble = ((9 << 1)+0);
+			} else {
+				 
+				rdpreamble = ((14 << 1)+0);
+			}
+		}
+		else if (divisor == ((7 << 1)+1)) {
+			 
+			if (slots <= 2) {
+				 
+				rdpreamble = ((7 << 1)+0);
+			} else {
+				 
+				rdpreamble = ((11 << 1)+0);
+			}
+		}
+		else if (divisor == ((6 << 1)+0)) {
+			 
+			if (slots <= 2) {
+				 
+				rdpreamble = ((7 << 1)+0);
+			} else {
+				 
+				rdpreamble = ((9 << 1)+0);
+			}
+		}
+		else if (divisor == ((5 << 1)+0)) {
+			 
+			if (slots <= 2) {
+				 
+				rdpreamble = ((5 << 1)+0);
+			} else {
+				 
+				rdpreamble = ((7 << 1)+0);
+			}
+		}
+	}
+	if ((rdpreamble < ((2<<1)+0) ) || (rdpreamble > ((9<<1)+1) )) {
+		die("Unknown rdpreamble");
+	}
+	dch |= (rdpreamble - ((2<<1)+0) ) << 8 ;
+	pci_write_config32(ctrl->f2, 0x94 , dch);
+}
+static void set_max_async_latency(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+	uint32_t dch;
+	int i;
+	unsigned async_lat;
+	int dimms;
+	dimms = count_dimms(ctrl);
+	dch = pci_read_config32(ctrl->f2, 0x94 );
+	dch &= ~(0xf  << 0 );
+	async_lat = 0;
+	if (is_registered(ctrl)) {
+		if (dimms == 4) {
+			 
+			async_lat = 9;
+		} 
+		else {
+			 
+			async_lat = 8;
+		}
+	}
+	else {
+		if (dimms > 3) {
+			die("Too many unbuffered dimms");
+		}
+		else if (dimms == 3) {
+			 
+			async_lat = 7;
+		}
+		else {
+			 
+			async_lat = 6;
+		}
+	}
+	dch |= ((async_lat - 0 ) << 0 );
+	pci_write_config32(ctrl->f2, 0x94 , dch);
+}
+static void set_idle_cycle_limit(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+	uint32_t dch;
+	 
+	dch = pci_read_config32(ctrl->f2, 0x94 );
+	dch &= ~(0x7  << 16 );
+	dch |= 3  << 16 ;
+	dch |= (1 << 19) ;
+	pci_write_config32(ctrl->f2, 0x94 , dch);
+}
+static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param)
+{
+	int dimms;
+	int i;
+	int rc;
+	
+	init_Tref(ctrl, param);
+	for(i = 0; (i < 4) && ctrl->channel0[i]; i++) {
+		int rc;
+		 
+		if (update_dimm_Trc (ctrl, param, i) < 0) goto dimm_err;
+		if (update_dimm_Trfc(ctrl, param, i) < 0) goto dimm_err;
+		if (update_dimm_Trcd(ctrl, param, i) < 0) goto dimm_err;
+		if (update_dimm_Trrd(ctrl, param, i) < 0) goto dimm_err;
+		if (update_dimm_Tras(ctrl, param, i) < 0) goto dimm_err;
+		if (update_dimm_Trp (ctrl, param, i) < 0) goto dimm_err;
+		 
+		if (update_dimm_Tref(ctrl, param, i) < 0) goto dimm_err;
+		 
+		if (update_dimm_x4 (ctrl, param, i) < 0) goto dimm_err;
+		if (update_dimm_ecc(ctrl, param, i) < 0) goto dimm_err;
+		continue;
+	dimm_err:
+		disable_dimm(ctrl, i);
+		
+	}
+	 
+	set_Twr(ctrl, param);
+	 
+	set_Twtr(ctrl, param);
+	set_Trwt(ctrl, param);
+	set_Twcl(ctrl, param);
+	 
+	set_read_preamble(ctrl, param);
+	set_max_async_latency(ctrl, param);
+	set_idle_cycle_limit(ctrl, param);
+}
+static void sdram_set_spd_registers(const struct mem_controller *ctrl) 
+{
+	const struct mem_param *param;
+	spd_enable_2channels(ctrl);
+	spd_set_ram_size(ctrl);
+	spd_handle_unbuffered_dimms(ctrl);
+	param = spd_set_memclk(ctrl);
+	spd_set_dram_timing(ctrl, param);
+	order_dimms(ctrl);
+}
+static void sdram_enable(int controllers, const struct mem_controller *ctrl)
+{
+	int i;
+	 
+	for(i = 0; i < controllers; i++) {
+		uint32_t dch;
+		dch = pci_read_config32(ctrl[i].f2, 0x94 );
+		dch |= (1 << 25) ;
+		pci_write_config32(ctrl[i].f2, 0x94 , dch);
+	}
+	 
+	memreset(controllers, ctrl);
+	for(i = 0; i < controllers; i++) {
+		uint32_t dcl;
+		 
+		dcl = pci_read_config32(ctrl[i].f2, 0x90 );
+		if (dcl & (1<<17) ) {
+			uint32_t mnc;
+			print_debug("ECC enabled\r\n");
+			mnc = pci_read_config32(ctrl[i].f3, 0x44 );
+			mnc |= (1 << 22) ;
+			if (dcl & (1<<16) ) {
+				mnc |= (1 << 23) ;
+			}
+			pci_write_config32(ctrl[i].f3, 0x44 , mnc);
+		}
+		dcl |= (1<<3) ;
+		pci_write_config32(ctrl[i].f2, 0x90 , dcl);
+		dcl &= ~(1<<3) ;
+		dcl &= ~(1<<0) ;
+		dcl &= ~(1<<1) ;
+		dcl &= ~(1<<2) ;
+		dcl |= (1<<8) ;
+		pci_write_config32(ctrl[i].f2, 0x90 , dcl);
+	}
+	for(i = 0; i < controllers; i++) {
+		uint32_t dcl;
+		print_debug("Initializing memory: ");
+		int loops = 0;
+		do {
+			dcl = pci_read_config32(ctrl[i].f2, 0x90 );
+			loops += 1;
+			if ((loops & 1023) == 0) {
+				print_debug(".");
+			}
+		} while(((dcl & (1<<8) ) != 0) && (loops < 300000 ));
+		if (loops >= 300000 ) {
+			print_debug(" failed\r\n");
+		} else {
+			print_debug(" done\r\n");
+		}
+		if (dcl & (1<<17) ) {
+			print_debug("Clearing memory: ");
+			if (!is_cpu_pre_c0()) {
+				 
+				dcl &= ~((1<<11)  | (1<<10) );
+				pci_write_config32(ctrl[i].f2, 0x90 , dcl);
+				do {
+					dcl = pci_read_config32(ctrl[i].f2, 0x90 );
+				} while(((dcl & (1<<11) ) == 0) || ((dcl & (1<<10) ) == 0) );
+			}
+			uint32_t base, last_scrub_k, scrub_k;
+			uint32_t cnt,zstart,zend;
+			msr_t msr,msr_201;
+			 
+			pci_write_config32(ctrl[i].f3, 0x58 ,
+				(0  << 16) | (0  << 8) | (0  << 0));
+			 
+			msr_201 = rdmsr(0x201);
+			zstart = pci_read_config32(ctrl[0].f1, 0x40 + (i*8));
+			zend = pci_read_config32(ctrl[0].f1, 0x44 + (i*8));
+			zstart >>= 16;
+			zend >>=16;
+			print_debug("addr ");
+			print_debug_hex32(zstart);
+			print_debug("-");
+			print_debug_hex32(zend);
+			print_debug("\r\n");
+			
+			 
+			msr = rdmsr(0x2ff );
+			msr.lo &= ~(1<<10);
+			wrmsr(0x2ff , msr);
+			 
+			msr = rdmsr(0xc0010015);
+			msr.lo |= (1<<17);
+			wrmsr(0xc0010015,msr);
+			for(;zstart<zend;zstart+=4) {
+				 
+				if(zstart == 0x0fc)
+					continue;
+				
+				 
+				__asm__ volatile(
+					"movl  %%cr0, %0\n\t"
+					"orl  $0x40000000, %0\n\t"
+					"movl  %0, %%cr0\n\t"
+					:"=r" (cnt)
+					);
+				
+				 
+				msr.lo = 1 + ((zstart&0x0ff)<<24);
+				msr.hi = (zstart&0x0ff00)>>8;
+				wrmsr(0x200,msr);
+				 
+				msr.hi = 0x000000ff;
+				msr.lo = 0xfc000800;
+				wrmsr(0x201,msr);
+				 
+				__asm__ volatile(
+					"movl  %%cr0, %0\n\t"
+					"andl  $0x9fffffff, %0\n\t"
+					"movl  %0, %%cr0\n\t"	
+					:"=r" (cnt)	
+					);
+				 
+				msr.lo = (zstart&0xff) << 24;
+				msr.hi = (zstart&0xff00) >> 8;
+				wrmsr(0xc0000100,msr);
+				print_debug_char((zstart > 0x0ff)?'+':'-');	
+					
+				 
+				__asm__ volatile(
+					"1: \n\t"
+					"movl %0, %%fs:(%1)\n\t"
+					"addl $4,%1\n\t"
+					"subl $1,%2\n\t"
+					"jnz 1b\n\t"
+					:
+					: "a" (0), "D" (0), "c" (0x01000000)
+					);			
+			}
+			
+			 
+			__asm__ volatile(
+				"movl  %%cr0, %0\n\t"
+				"orl  $0x40000000, %0\n\t"
+				"movl  %0, %%cr0\n\t"
+				:"=r" (cnt)	
+				);
+		
+			 	
+			msr = rdmsr(0x2ff );
+			msr.lo |= 0x0400;
+			wrmsr(0x2ff , msr);
+			 
+			msr.lo = 6;
+			msr.hi = 0;
+			wrmsr(0x200,msr);
+			wrmsr(0x201,msr_201);
+			 
+			msr.lo = 0;
+			msr.hi = 0;
+			wrmsr(0xc0000100,msr);
+			 
+			__asm__ volatile(
+				"movl  %%cr0, %0\n\t"
+				"andl  $0x9fffffff, %0\n\t"
+				"movl  %0, %%cr0\n\t"	
+				:"=r" (cnt)	
+				);
+			
+			 
+			msr = rdmsr(0xc0010015);
+			msr.lo &= ~(1<<17);
+			wrmsr(0xc0010015,msr);
+			 
+			base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3));
+			base &= 0xffff0000;
+			 
+			pci_write_config32(ctrl[i].f3, 0x5C , base << 8);
+			pci_write_config32(ctrl[i].f3, 0x60 , base >> 24);
+			 
+			pci_write_config32(ctrl[i].f3, 0x58 , 
+				(22  << 16) | (22  << 8) | (22  << 0));
+			print_debug("done\r\n");
+		}
+	}
+}
+ 
+ 
+ 
+ 
+ 
+typedef uint8_t u8;
+typedef uint32_t u32;
+typedef int8_t bool;
+static void disable_probes(void)
+{
+	 
+	 
+	u32 val;
+	print_debug("Disabling read/write/fill probes for UP... ");
+	val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x68);
+	val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
+	pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x68, val);
+	print_debug("done.\r\n");
+}
+ 
+static void wait_ap_stop(u8 node) 
+{
+	unsigned long reg;
+	unsigned long i;
+	for(i=0;i< 1000 ;i++) {
+		unsigned long regx;
+		regx = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x6c);
+		if((regx & (1<<4))==1) break;
+        }
+	reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x6c);
+        reg &= ~(1<<4);   
+        pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6c, reg);
+}
+static void notify_bsp_ap_is_stopped(void)
+{
+	unsigned long reg;
+	unsigned long apic_id;
+        apic_id = *((volatile unsigned long *)(0xfee00000 + 0x020 ));
+	apic_id >>= 24;
+	 
+        if(apic_id != 0) {
+		 
+                reg = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6C);
+                reg |= 1<<4;
+                pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ apic_id  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6C, reg);
+        }
+ 
+}
+ 
+static void enable_routing(u8 node)
+{
+	u32 val;
+	 
+	 
+	print_debug("Enabling routing table for node ");
+	print_debug_hex32(node);
+	val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6c);
+	val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
+	pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x6c, val);
+ 
+	if(node!=0) {
+		wait_ap_stop(node);
+	}
+ 
+	print_debug(" done.\r\n");
+}
+static void rename_temp_node(u8 node)
+{
+	uint32_t val;
+	print_debug("Renaming current temp node to ");
+	print_debug_hex32(node);
+	val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x60);
+	val &= (~7);   
+        val |= node;    
+	pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x60, val);
+	print_debug(" done.\r\n");
+}
+static bool check_connection(u8 src, u8 dest, u8 link)
+{
+	 
+	u32 val;
+	
+	 
+	val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ src  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x98+link);
+	if ( (val&0x17) != 0x03)
+		return 0;
+	 
+        val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ dest  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0);
+	if(val != 0x11001022)
+		return 0;
+	return 1;
+}
+static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2)
+{
+	static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
+	static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
+	uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
+	uint8_t width_cap1, width_cap2, width_cap, width, ln_width1, ln_width2;
+	uint8_t freq;
+	 
+	 
+	freq_cap1  = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link1 + 0x0a );
+	freq_cap2  = pci_read_config16(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link2 + 0x0a );
+	 
+	 
+	freq = log2(freq_cap1 & freq_cap2 & 0xff);
+	 
+	pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link1 + 0x09 , freq);
+	pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link2 + 0x09 , freq);
+	 
+	width_cap1 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,  0x80 + link1 + 6 );
+	width_cap2 = pci_read_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,  0x80 + link2 + 6 );
+	 
+	ln_width1 = link_width_to_pow2[width_cap1 & 7];
+	ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
+	if (ln_width1 > ln_width2) {
+		ln_width1 = ln_width2;
+	}
+	width = pow2_to_link_width[ln_width1];
+	 
+	ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
+	ln_width2 = link_width_to_pow2[width_cap2 & 7];
+	if (ln_width1 > ln_width2) {
+		ln_width1 = ln_width2;
+	}
+	width |= pow2_to_link_width[ln_width1] << 4;
+	
+	 
+	pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link1 + 6  + 1, width);
+	 
+	width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
+	pci_write_config8(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node2  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x80 + link2 + 6  + 1, width);
+}
+static void fill_row(u8 node, u8 row, u32 value)
+{
+	pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x40+(row<<2), value);
+}
+static void setup_row(u8 source, u8 dest, u8 cpus)
+{
+	fill_row(source,dest,generate_row(source,dest,cpus));
+}
+static void setup_temp_row(u8 source, u8 dest, u8 cpus)
+{
+	fill_row(source,7,((generate_row( source,dest,cpus )&(~0x0f0000))|0x010000) );
+}
+static void setup_node(u8 node, u8 cpus)
+{
+	u8 row;
+	for(row=0; row<cpus; row++)
+		setup_row(node, row, cpus);
+}
+static void setup_remote_row(u8 source, u8 dest, u8 cpus)
+{
+	fill_row(7, dest, generate_row(source, dest, cpus));
+}
+static void setup_remote_node(u8 node, u8 cpus)
+{
+	static const uint8_t pci_reg[] = { 
+		0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c, 
+		0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
+		0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
+		0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
+		0xc4, 0xcc, 0xd4, 0xdc,
+		0xc0, 0xc8, 0xd0, 0xd8,
+		0xe0, 0xe4, 0xe8, 0xec,
+	};
+	uint8_t row;
+	int i;
+	print_debug("setup_remote_node\r\n");
+	for(row=0; row<cpus; row++)
+		setup_remote_row(node, row, cpus);
+	 
+	for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
+		uint32_t value;
+		uint8_t reg;
+		reg = pci_reg[i];
+		value = pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 0  ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8))  , reg);
+		pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ 7  ) & 0x1f) << 11) | ((( 1 )  & 0x7) << 8))  , reg, value);
+	}
+	print_debug("setup_remote_done\r\n");
+}
+static u8 setup_uniprocessor(void)
+{
+	print_debug("Enabling UP settings\r\n");
+	disable_probes();
+	return 1;
+}
+static u8 setup_smp(void)
+{
+	u8 cpus=2;
+	print_debug("Enabling SMP settings\r\n");
+	setup_row(0,0,cpus);
+	 
+	setup_temp_row(0,1,cpus);
+	
+	if (!check_connection(0, 7, 0x20  )) {
+		print_debug("No connection to Node 1.\r\n");
+		fill_row( 0 ,7,0x00010101 ) ;	 
+		setup_uniprocessor();	 
+		return 1;
+	}
+	 
+	optimize_connection(0, 0x20 , 7, 0x20 );
+	setup_node(0, cpus);	 
+	setup_remote_node(1, cpus);   
+        rename_temp_node(1);     
+        enable_routing(1);       
+  	
+	fill_row( 0 ,7,0x00010101 ) ;	 
+	
+	print_debug_hex32(cpus);
+	print_debug(" nodes initialized.\r\n");
+	return cpus;
+}
+static unsigned detect_mp_capabilities(unsigned cpus)
+{
+	unsigned node, row, mask;
+	bool mp_cap= (-1) ;
+	print_debug("detect_mp_capabilities: ");
+	print_debug_hex32(cpus);
+	print_debug("\r\n");
+	if (cpus>2)
+		mask=0x06;	 
+	else
+		mask=0x02;	 
+	for (node=0; node<cpus; node++) {
+		if ((pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 3 )  & 0x7) << 8))  , 0xe8) & mask)!=mask)
+			mp_cap= (0) ;
+	}
+	if (mp_cap)
+		return cpus;
+	 
+	print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
+	for (node=cpus; node>0; node--)
+	    for (row=cpus; row>0; row--)
+		fill_row(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node-1  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , row-1, 0x00010101 );
+	
+	return setup_uniprocessor();
+}
+static void coherent_ht_finalize(unsigned cpus)
+{
+	int node;
+	bool rev_a0;
+	
+	 
+	print_debug("coherent_ht_finalize\r\n");
+	rev_a0= is_cpu_rev_a0();
+	for (node=0; node<cpus; node++) {
+		u32 val;
+		val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x60);
+		val &= (~0x000F0070);
+		val |= ((cpus-1)<<16)|((cpus-1)<<4);
+		pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x60,val);
+		val=pci_read_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  , 0x68);
+		val |= 0x00008000;
+		pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x68,val);
+		if (rev_a0) {
+			pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0x94,0);
+			pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0xb4,0);
+			pci_write_config32(( ((( 0 ) & 0xFF) << 16) | ((( 24+ node  ) & 0x1f) << 11) | ((( 0 )  & 0x7) << 8))  ,0xd4,0);
+		}
+	}
+	print_debug("done\r\n");
+}
+static int setup_coherent_ht_domain(void)
+{
+	unsigned cpus;
+	int reset_needed = 0;
+	enable_routing(0) ;
+	cpus=setup_smp();
+	cpus=detect_mp_capabilities(cpus);
+	coherent_ht_finalize(cpus);
+	 
+	coherent_ht_mainboard(cpus);
+	return reset_needed;
+}
+void sdram_no_memory(void)
+{
+	print_err("No memory!!\r\n");
+	while(1) { 
+		hlt(); 
+	}
+}
+ 
+void sdram_initialize(int controllers, const struct mem_controller *ctrl)
+{
+	int i;
+	 
+	for(i = 0; i < controllers; i++) {
+		print_debug("Ram1.");
+		print_debug_hex8(i);
+		print_debug("\r\n");
+		sdram_set_registers(ctrl + i);
+	}
+	 
+	for(i = 0; i < controllers; i++) {
+		print_debug("Ram2.");
+		print_debug_hex8(i);
+		print_debug("\r\n");
+		sdram_set_spd_registers(ctrl + i);
+	}
+	 
+	print_debug("Ram3\r\n");
+	sdram_enable(controllers, ctrl);
+	print_debug("Ram4\r\n");
+}
+static void enable_lapic(void)
+{
+	msr_t msr;
+	msr = rdmsr(0x1b);
+	msr.hi &= 0xffffff00;
+	msr.lo &= 0x000007ff;
+	msr.lo |= 0xfee00000  | (1 << 11);
+	wrmsr(0x1b, msr);
+}
+static void stop_this_cpu(void)
+{
+	unsigned apicid;
+	apicid = apic_read(0x020 ) >> 24;
+	 
+	apic_write(0x310 , (( apicid )<<24) );
+	apic_write(0x300 , 0x08000  | 0x04000  | 0x00500 );
+	 
+	apic_wait_icr_idle();
+	 
+	apic_write(0x310 , (( apicid )<<24) );
+	apic_write(0x300 ,  0x08000  | 0x00500 );
+	 
+	apic_wait_icr_idle();
+	 
+	for(;;) {
+		hlt();
+	}
+}
+static void pc87360_enable_serial(void)
+{
+	pnp_set_logical_device(0x2e , 0x03 );
+	pnp_set_enable(0x2e , 1);
+	pnp_set_iobase0(0x2e , 0x3f8);
+}
+static void main(void)
+{
+	 
+	static const struct mem_controller cpu[] = {
+		{
+			.node_id = 0,
+			.f0 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ,
+			.f1 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ,
+			.f2 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  2 )  & 0x7) << 8)) ,
+			.f3 = ( ((( 0 ) & 0xFF) << 16) | (((  0x18 ) & 0x1f) << 11) | (((  3 )  & 0x7) << 8)) ,
+			.channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 },
+			.channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 },
+		},
+		{
+			.node_id = 1,
+			.f0 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  0 )  & 0x7) << 8)) ,
+			.f1 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  1 )  & 0x7) << 8)) ,
+			.f2 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  2 )  & 0x7) << 8)) ,
+			.f3 = ( ((( 0 ) & 0xFF) << 16) | (((  0x19 ) & 0x1f) << 11) | (((  3 )  & 0x7) << 8)) ,
+			.channel0 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 },
+			.channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 },
+		},
+	};
+	if (cpu_init_detected()) {
+		asm("jmp __cpu_reset");
+	}
+	enable_lapic();
+	init_timer();
+	if (!boot_cpu()) {
+		stop_this_cpu();
+	}
+	pc87360_enable_serial();
+	uart_init();
+	console_init();
+	setup_default_resource_map();
+	setup_coherent_ht_domain();
+	enumerate_ht_chain(0);
+	distinguish_cpu_resets(0);
+	
+	enable_smbus();
+	memreset_setup();
+	sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
+	 
+}
diff --git a/util/romcc/tests/simple_test1.c b/util/romcc/tests/simple_test1.c
new file mode 100644
index 0000000..feacbfd
--- /dev/null
+++ b/util/romcc/tests/simple_test1.c
@@ -0,0 +1,252 @@
+void land_test(void)
+{
+	int i;
+	i = 1 && 2;
+}
+void lor_test(void)
+{
+	int i;
+	i = 1 || 2;
+}
+
+void outb(unsigned char value, unsigned short port)
+{
+	__builtin_outb(value, port);
+}
+
+unsigned char inb(unsigned short port)
+{
+	return __builtin_inb(port);
+}
+
+static unsigned int config_cmd2(unsigned char bus, unsigned devfn, unsigned where)
+{
+	return 0x80000000 | (bus << 16) | (devfn << 8) | (where & ~3)  ;
+}
+
+/* Base Address */
+#ifndef TTYS0_BASE
+#define TTYS0_BASE 0x3f8
+#endif
+
+#ifndef TTYS0_BAUD
+#define TTYS0_BAUD 115200
+#endif
+
+#if ((115200%TTYS0_BAUD) != 0)
+#error Bad ttys0 baud rate
+#endif
+
+#define TTYS0_DIV	(115200/TTYS0_BAUD)
+
+/* Line Control Settings */
+#ifndef TTYS0_LCS
+/* Set 8bit, 1 stop bit, no parity */
+#define TTYS0_LCS	0x3
+#endif
+
+#define UART_LCS	TTYS0_LCS
+
+/* Data */
+#define UART_RBR 0x00
+#define UART_TBR 0x00
+
+/* Control */
+#define UART_IER 0x01
+#define UART_IIR 0x02
+#define UART_FCR 0x02
+#define UART_LCR 0x03
+#define UART_MCR 0x04
+#define UART_DLL 0x00
+#define UART_DLM 0x01
+
+/* Status */
+#define UART_LSR 0x05
+#define UART_MSR 0x06
+#define UART_SCR 0x07
+
+int uart_can_tx_byte(void)
+{
+	return inb(TTYS0_BASE + UART_LSR) & 0x20;
+}
+
+void uart_wait_to_tx_byte(void)
+{
+	while(!uart_can_tx_byte())
+		;
+}
+
+void uart_wait_until_sent(void)
+{
+	while(!(inb(TTYS0_BASE + UART_LSR) & 0x40)) 
+		;
+}
+
+void uart_tx_byte(unsigned char data)
+{
+	uart_wait_to_tx_byte();
+	outb(data, TTYS0_BASE + UART_TBR);
+	/* Make certain the data clears the fifos */
+	uart_wait_until_sent();
+}
+
+void dummy(void)
+{
+	uart_tx_byte(5);
+}
+
+#define PIIX4_DEVFN 0x90
+#define SMBUS_MEM_DEVICE_START 0x50
+#define SMBUS_MEM_DEVICE_END 0x53
+#define SMBUS_MEM_DEVICE_INC 1
+
+
+#define PM_BUS 0
+#define PM_DEVFN (PIIX4_DEVFN+3)
+
+#define SMBUS_IO_BASE 0x1000
+#define SMBHSTSTAT 0
+#define SMBHSTCTL  2
+#define SMBHSTCMD  3
+#define SMBHSTADD  4
+#define SMBHSTDAT0 5
+#define SMBHSTDAT1 6
+#define SMBBLKDAT  7
+
+static void smbus_wait_until_done(void)
+{
+	unsigned char byte;
+	do {
+		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	}while((byte &1) == 1);
+#if 1
+	while( (byte & ~1) == 0) {
+		byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
+	}
+#endif
+}
+
+#if 0
+void ifthenelse(void)
+{
+	int i;
+	if (5 > 2) {
+		i = 1;
+	}
+	else {
+		i = 2;
+	}
+	i = i + 3;
+}
+#endif
+#if 0
+static int add(int left, int right)
+{
+	{
+		return left + right;
+	}
+}
+#else
+#if 0
+static int add(int left, int right)
+{
+	return left + right;
+}
+#endif
+#endif
+
+#if 0
+static void assign(void)
+{
+	int i, j;
+	i = j = 1;
+}
+#endif
+
+#if 0
+static void and(void)
+{
+	int i, j, k;
+	i = 1;
+	j = 2;
+	k = i && j;
+	
+}
+static void and_test(void)
+{
+	and();
+}
+#endif
+#if 0
+#define INC_TEST 2
+static void inc(void)
+{
+	int i;
+	i = 5;
+#if (INC_TEST == 1)
+	i += 7;
+#endif
+#if (INC_TEST == 2)
+	++i;
+#endif
+#if (INC_TEST == 3)
+	i++;
+#endif
+}
+
+#if 0
+static void inc_test(void)
+{
+	inc();
+}
+#endif
+#endif
+#if 0
+static void loop(void)
+{
+	int i;
+	for(i = 0; i < 10; i++) {
+		;
+	} while(i < 10);
+}
+
+static void loop_test(void)
+{
+	loop();
+}
+#endif
+
+#if 0
+static void simple(void)
+{
+	add(1,2);
+}
+#endif
+
+#if 0
+static void fun(void)
+{
+	int bar;
+	bar = add(1, 2);
+}
+#endif
+
+
+#if 0
+static void func(void)
+{
+	int bar, baz;
+ 	int i; 
+  
+	baz = add(1, 2); 
+	baz = add(1, 2);
+	bar = 1;
+	baz = 2;
+	for(i = 0; i < 10; i = i + 1) {
+		baz = i;
+	}
+	bar = 1 + 2 * 3;
+	bar = add(3, 4);
+	bar = add(bar, baz);
+}
+#endif
diff --git a/util/romcc/tests/simple_test60.c b/util/romcc/tests/simple_test60.c
index d277c94..860bf32 100644
--- a/util/romcc/tests/simple_test60.c
+++ b/util/romcc/tests/simple_test60.c
@@ -27,6 +27,6 @@
 	const struct mem_param *param;
 	param = &param0;
 	value = 0x48;
-#warning "this generates word loads instead of byte loads"
+#warning "this generated word loads instead of byte loads"
 	clocks = (value + (param->divisor << 1) - 1)/(param->divisor << 1);
 }
diff --git a/util/romcc/tests/simple_test71.c b/util/romcc/tests/simple_test71.c
index 35956c5..52ffc8d 100644
--- a/util/romcc/tests/simple_test71.c
+++ b/util/romcc/tests/simple_test71.c
@@ -6,16 +6,10 @@
 {
 	int i;
 
-#if 1
 	foo();
-#endif
-#if 1
 	foo();
-#endif
 	for(i = 0; i < 10; i++) {
-#if 1
 		foo();
-#endif
 #if 0
 		foo();
 #endif
diff --git a/util/romcc/tests/simple_test74.c b/util/romcc/tests/simple_test74.c
new file mode 100644
index 0000000..177e00f
--- /dev/null
+++ b/util/romcc/tests/simple_test74.c
@@ -0,0 +1,88 @@
+struct syscall_result {
+	long val;
+	int errno;
+};
+
+static struct syscall_result syscall_return(long result)
+{
+	struct syscall_result res;
+	if (((unsigned long)result) >= ((unsigned long)-125)) {
+		res.errno = - result;
+		res.val = -1;
+	} else {
+		res.errno = 0;
+		res.val = result;
+	}
+	return res;
+}
+
+static struct syscall_result syscall1(unsigned long nr, unsigned long arg1)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr), "b" (arg1));
+	return syscall_return(res);
+	
+}
+
+
+static struct syscall_result syscall3(unsigned long nr, unsigned long arg1, unsigned long arg2,
+	unsigned long arg3)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3));
+	return syscall_return(res);
+	
+}
+
+#define NR_exit                 1
+#define NR_write                4
+
+/* Standard file descriptors */
+#define STDIN_FILENO    0  /* Standard input */
+#define STDOUT_FILENO   1  /* Standard output */
+#define STDERR_FILENO   2  /* Standard error output */
+
+typedef long ssize_t;
+typedef unsigned long size_t;
+
+static ssize_t write(int fd, const void *buf, size_t count)
+{
+	struct syscall_result res;
+	res = syscall3(NR_write, fd, (unsigned long)buf, count);
+	return res.val;
+}
+
+static void _exit(int status)
+{
+	struct syscall_result res;
+	res = syscall1(NR_exit, status);
+}
+
+static void console_tx_string(const char *str)
+{
+	unsigned char ch;
+	while(1) {
+
+	}
+	for(;1;) {
+	}
+	do {
+	} while(1);
+	if (1) {
+	}else {
+	}
+}
+
+
+static void main(void)
+{
+	static const char msg[] = "hello world\r\n";
+	write(STDOUT_FILENO, msg, sizeof(msg));
+	_exit(0);
+}
diff --git a/util/romcc/tests/simple_test75.c b/util/romcc/tests/simple_test75.c
new file mode 100644
index 0000000..1ad87bd
--- /dev/null
+++ b/util/romcc/tests/simple_test75.c
@@ -0,0 +1,21 @@
+static void goto_test(void)
+{
+	int i;
+	
+	i = 0;
+	goto bottom;
+	{
+	top:
+		i = i + 1;
+	}
+ bottom:
+	if (i < 10) {
+		goto top;
+	}
+	;
+}
+
+static void main(void)
+{
+	goto_test();
+}
diff --git a/util/romcc/tests/simple_test76.c b/util/romcc/tests/simple_test76.c
new file mode 100644
index 0000000..4f682d3
--- /dev/null
+++ b/util/romcc/tests/simple_test76.c
@@ -0,0 +1,69 @@
+struct syscall_result {
+	long val;
+	int errno;
+};
+
+static struct syscall_result syscall_return(long result)
+{
+	struct syscall_result res;
+	if (((unsigned long)result) >= ((unsigned long)-125)) {
+		res.errno = - result;
+		res.val = -1;
+	} else {
+		res.errno = 0;
+		res.val = result;
+	}
+	return res;
+}
+static struct syscall_result syscall1(unsigned long nr, unsigned long arg1)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr), "b" (arg1));
+	return syscall_return(res);
+	
+}
+
+static struct syscall_result syscall3(unsigned long nr, unsigned long arg1, unsigned long arg2,
+	unsigned long arg3)
+{
+	long res;
+	asm volatile(
+		"int $0x80"
+		: "=a" (res)
+		: "a" (nr), "b" (arg1), "c" (arg2), "d" (arg3));
+	return syscall_return(res);
+	
+}
+
+#define NR_exit                 1
+#define NR_write                4
+/* Standard file descriptors */
+#define STDIN_FILENO    0  /* Standard input */
+#define STDOUT_FILENO   1  /* Standard output */
+#define STDERR_FILENO   2  /* Standard error output */
+
+typedef long ssize_t;
+typedef unsigned long size_t;
+
+static ssize_t write(int fd, const void *buf, size_t count)
+{
+	struct syscall_result res;
+	res = syscall3(NR_write, fd, (unsigned long)buf, count);
+	return res.val;
+}
+
+static void _exit(int status)
+{
+	struct syscall_result res;
+	res = syscall1(NR_exit, status);
+}
+
+static void main(void)
+{
+	static const char msg[] = "hello world\r\n";
+	write(STDOUT_FILENO, msg, sizeof(msg));
+	_exit(0);
+}
diff --git a/util/romcc/tests/simple_test77.c b/util/romcc/tests/simple_test77.c
new file mode 100644
index 0000000..74be92e
--- /dev/null
+++ b/util/romcc/tests/simple_test77.c
@@ -0,0 +1,5 @@
+static void main(void)
+{
+	do {
+	} while(1);
+}
diff --git a/util/romcc/tests/simple_test78.c b/util/romcc/tests/simple_test78.c
new file mode 100644
index 0000000..5e6b27b
--- /dev/null
+++ b/util/romcc/tests/simple_test78.c
@@ -0,0 +1,7 @@
+static void main(void)
+{
+	int x = 25;
+	do {
+	} while(1);
+	*((volatile int *)5) = x;
+}
diff --git a/util/romcc/tests/simple_test79.c b/util/romcc/tests/simple_test79.c
new file mode 100644
index 0000000..2f501ca
--- /dev/null
+++ b/util/romcc/tests/simple_test79.c
@@ -0,0 +1,5 @@
+static void main(void)
+{
+	do {
+	} while(0);
+}
diff --git a/util/romcc/tests/simple_test80.c b/util/romcc/tests/simple_test80.c
new file mode 100644
index 0000000..3a31a0a
--- /dev/null
+++ b/util/romcc/tests/simple_test80.c
@@ -0,0 +1,13 @@
+typedef __builtin_msr_t msr_t;
+
+static msr_t rdmsr(unsigned long index)
+{
+	return __builtin_rdmsr(index);
+}
+
+static void main(void)
+{
+	msr_t msr;
+	msr = rdmsr(0x12345678);
+}
+
diff --git a/util/romcc/tests/simple_test81.c b/util/romcc/tests/simple_test81.c
new file mode 100644
index 0000000..e942679
--- /dev/null
+++ b/util/romcc/tests/simple_test81.c
@@ -0,0 +1,8 @@
+static void main(void)
+{
+	int i;
+	i = __builtin_inb(0x1234);
+	int j;
+	j = __builtin_inb(0xabcd);
+		
+}
diff --git a/util/romcc/tests/simple_test82.c b/util/romcc/tests/simple_test82.c
new file mode 100644
index 0000000..25b08ba
--- /dev/null
+++ b/util/romcc/tests/simple_test82.c
@@ -0,0 +1,17 @@
+
+
+struct result {
+	int a, b, c, d;
+};
+
+static struct result main(int a, int b, int c, int  d)
+{
+	struct result result;
+	result.a = d;
+	result.b = c;
+	result.c = b;
+	result.d = a;
+
+	return result;
+}
+
diff --git a/util/romcc/tests/simple_test83.c b/util/romcc/tests/simple_test83.c
new file mode 100644
index 0000000..cf9f817
--- /dev/null
+++ b/util/romcc/tests/simple_test83.c
@@ -0,0 +1,16 @@
+
+
+struct result {
+	int a, b, c, d;
+};
+
+static struct result main(int a, int b, int c, int  d)
+{
+	struct result result;
+	result.a = d + 1;
+	result.b = c + 1;
+	result.c = b + 1;
+	result.d = a + 1;
+
+	return result;
+}
diff --git a/util/romcc/tests/simple_test84.c b/util/romcc/tests/simple_test84.c
new file mode 100644
index 0000000..bc98bf3
--- /dev/null
+++ b/util/romcc/tests/simple_test84.c
@@ -0,0 +1,28 @@
+struct stuff {
+	signed int   a : 5;
+	signed int   b : 6;
+	signed int   c : 2;
+	unsigned int d : 3;
+};
+
+static void main(void)
+{
+	struct stuff var;
+	volatile int a, b, c, d;
+	a = 1;
+	b = 2;
+	c = 3;
+	d = 7;
+
+	var.a = a;
+	var.b = b;
+	var.c = c;
+	var.d = d;
+
+	a = var.a;
+	b = var.b;
+	c = var.c;
+	d = var.d;
+
+	asm(" " :: "r"(a), "r"(b), "r"(c), "r"(d));
+}
diff --git a/util/romcc/tests/simple_test85.c b/util/romcc/tests/simple_test85.c
new file mode 100644
index 0000000..f223e2e
--- /dev/null
+++ b/util/romcc/tests/simple_test85.c
@@ -0,0 +1,51 @@
+struct sub4 {
+	unsigned a;
+	unsigned b;
+	unsigned c;
+	unsigned d;
+	unsigned e;
+	unsigned f;
+	unsigned g;
+};
+struct sub3 {
+	unsigned a;
+	unsigned b;
+	unsigned c;
+	unsigned d;
+	unsigned e;
+	unsigned f;
+	struct sub4 s4;
+};
+struct sub2 {
+	unsigned a;
+	unsigned b;
+	unsigned c;
+	unsigned d;
+	unsigned e;
+	struct sub3 s3;
+};
+struct sub1 {
+	unsigned a;
+	unsigned b;
+	struct sub2 s2;
+};
+
+struct stuff {
+	signed int   a;
+	signed int   b;
+	signed int   c;
+	unsigned int d;
+	struct sub1  s1;
+};
+
+
+static void main(void)
+{
+	struct stuff *var;
+	unsigned int *foo;
+
+	var = (struct stuff *)(0x12345678);
+	foo = &var->d;
+	foo = &((*var).d);
+	foo = &var->s1.s2.s3.s4.g;
+}
diff --git a/util/romcc/tests/simple_test86.c b/util/romcc/tests/simple_test86.c
new file mode 100644
index 0000000..d9d4c65
--- /dev/null
+++ b/util/romcc/tests/simple_test86.c
@@ -0,0 +1,5 @@
+static void main(void)
+{
+	asm("cpuid"
+		::: "eax", "ebx", "ecx", "edx");
+}