TEMP: finished through init_page_tables
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5761abc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.o
diff --git a/Makefile b/Makefile
index 7c2ac35..462046a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,17 @@
 CC = /home/rth/work/gcc/run-axp/bin/alphaev6-linux-gcc
+LD = /home/rth/work/gcc/run-axp/bin/alphaev6-linux-ld
+CFLAGS = -O2 -g -msmall-text -msmall-data -fvisibility=hidden
 
-all: pal.o
+OBJS = pal.o init.o memset.o
 
-pal.o: pal.S
-	$(CC) -c -Wa,-m21264 -g -o $@ $<
+all: palcode
+
+palcode: palcode.ld $(OBJS)
+	$(LD) -relax -o $@ -T palcode.ld -Map palcode.map $(OBJS)
+
+clean:
+	rm -f *.o
+	rm -f palcode palcode.map
+
+pal.o: pal.S osf.h
+	$(CC) $(CFLAGS) -c -Wa,-m21264 -Wa,--noexecstack -o $@ $<
diff --git a/hwrpb.h b/hwrpb.h
new file mode 100644
index 0000000..8e8f871
--- /dev/null
+++ b/hwrpb.h
@@ -0,0 +1,220 @@
+#ifndef __ALPHA_HWRPB_H
+#define __ALPHA_HWRPB_H
+
+#define INIT_HWRPB ((struct hwrpb_struct *) 0x10000000)
+
+/*
+ * DEC processor types for Alpha systems.  Found in HWRPB.
+ * These values are architected.
+ */
+
+#define EV3_CPU                 1       /* EV3                  */
+#define EV4_CPU                 2       /* EV4 (21064)          */
+#define LCA4_CPU                4       /* LCA4 (21066/21068)   */
+#define EV5_CPU                 5       /* EV5 (21164)          */
+#define EV45_CPU                6       /* EV4.5 (21064/xxx)    */
+#define EV56_CPU		7	/* EV5.6 (21164)	*/
+#define EV6_CPU			8	/* EV6 (21264)		*/
+#define PCA56_CPU		9	/* PCA56 (21164PC)	*/
+#define PCA57_CPU		10	/* PCA57 (notyet)	*/
+#define EV67_CPU		11	/* EV67 (21264A)	*/
+#define EV68CB_CPU		12	/* EV68CB (21264C)	*/
+#define EV68AL_CPU		13	/* EV68AL (21264B)	*/
+#define EV68CX_CPU		14	/* EV68CX (21264D)	*/
+#define EV7_CPU			15	/* EV7 (21364)		*/
+#define EV79_CPU		16	/* EV79 (21364??)	*/
+#define EV69_CPU		17	/* EV69 (21264/EV69A)	*/
+
+/*
+ * DEC system types for Alpha systems.  Found in HWRPB.
+ * These values are architected.
+ */
+
+#define ST_ADU			  1	/* Alpha ADU systype	*/
+#define ST_DEC_4000		  2	/* Cobra systype	*/
+#define ST_DEC_7000		  3	/* Ruby systype		*/
+#define ST_DEC_3000_500		  4	/* Flamingo systype	*/
+#define ST_DEC_2000_300		  6	/* Jensen systype	*/
+#define ST_DEC_3000_300		  7	/* Pelican systype	*/
+#define ST_DEC_2100_A500	  9	/* Sable systype	*/
+#define ST_DEC_AXPVME_64	 10	/* AXPvme system type	*/
+#define ST_DEC_AXPPCI_33	 11	/* NoName system type	*/
+#define ST_DEC_TLASER		 12	/* Turbolaser systype	*/
+#define ST_DEC_2100_A50		 13	/* Avanti systype	*/
+#define ST_DEC_MUSTANG		 14	/* Mustang systype	*/
+#define ST_DEC_ALCOR		 15	/* Alcor (EV5) systype	*/
+#define ST_DEC_1000		 17	/* Mikasa systype	*/
+#define ST_DEC_EB64		 18	/* EB64 systype		*/
+#define ST_DEC_EB66		 19	/* EB66 systype		*/
+#define ST_DEC_EB64P		 20	/* EB64+ systype	*/
+#define ST_DEC_BURNS		 21	/* laptop systype	*/
+#define ST_DEC_RAWHIDE		 22	/* Rawhide systype	*/
+#define ST_DEC_K2		 23	/* K2 systype		*/
+#define ST_DEC_LYNX		 24	/* Lynx systype		*/
+#define ST_DEC_XL		 25	/* Alpha XL systype	*/
+#define ST_DEC_EB164		 26	/* EB164 systype	*/
+#define ST_DEC_NORITAKE		 27	/* Noritake systype	*/
+#define ST_DEC_CORTEX		 28	/* Cortex systype	*/
+#define ST_DEC_MIATA		 30	/* Miata systype        */
+#define ST_DEC_XXM		 31	/* XXM systype		*/
+#define ST_DEC_TAKARA		 32	/* Takara systype	*/
+#define ST_DEC_YUKON		 33	/* Yukon systype	*/
+#define ST_DEC_TSUNAMI		 34	/* Tsunami systype	*/
+#define ST_DEC_WILDFIRE		 35	/* Wildfire systype	*/
+#define ST_DEC_CUSCO		 36	/* CUSCO systype	*/
+#define ST_DEC_EIGER		 37	/* Eiger systype	*/
+#define ST_DEC_TITAN		 38	/* Titan systype	*/
+#define ST_DEC_MARVEL		 39	/* Marvel systype	*/
+
+/* UNOFFICIAL!!! */
+#define ST_UNOFFICIAL_BIAS	100
+#define ST_DTI_RUFFIAN		101	/* RUFFIAN systype	*/
+
+/* Alpha Processor, Inc. systems */
+#define ST_API_BIAS		200
+#define ST_API_NAUTILUS		201	/* UP1000 systype	*/
+
+struct pcb_struct {
+	unsigned long ksp;
+	unsigned long usp;
+	unsigned long ptbr;
+	unsigned int pcc;
+	unsigned int asn;
+	unsigned long unique;
+	unsigned long flags;
+	unsigned long res1, res2;
+};
+
+struct percpu_struct {
+	unsigned long hwpcb[16];
+	unsigned long flags;
+	unsigned long pal_mem_size;
+	unsigned long pal_scratch_size;
+	unsigned long pal_mem_pa;
+	unsigned long pal_scratch_pa;
+	unsigned long pal_revision;
+	unsigned long type;
+	unsigned long variation;
+	unsigned long revision;
+	unsigned long serial_no[2];
+	unsigned long logout_area_pa;
+	unsigned long logout_area_len;
+	unsigned long halt_PCBB;
+	unsigned long halt_PC;
+	unsigned long halt_PS;
+	unsigned long halt_arg;
+	unsigned long halt_ra;
+	unsigned long halt_pv;
+	unsigned long halt_reason;
+	unsigned long res;
+	unsigned long ipc_buffer[21];
+	unsigned long palcode_avail[16];
+	unsigned long compatibility;
+	unsigned long console_data_log_pa;
+	unsigned long console_data_log_length;
+	unsigned long bcache_info;
+};
+
+struct procdesc_struct {
+	unsigned long weird_vms_stuff;
+	unsigned long address;
+};
+
+struct vf_map_struct {
+	unsigned long va;
+	unsigned long pa;
+	unsigned long count;
+};
+
+struct crb_struct {
+	struct procdesc_struct * dispatch_va;
+	struct procdesc_struct * dispatch_pa;
+	struct procdesc_struct * fixup_va;
+	struct procdesc_struct * fixup_pa;
+	/* virtual->physical map */
+	unsigned long map_entries;
+	unsigned long map_pages;
+	struct vf_map_struct map[1];
+};
+
+struct memclust_struct {
+	unsigned long start_pfn;
+	unsigned long numpages;
+	unsigned long numtested;
+	unsigned long bitmap_va;
+	unsigned long bitmap_pa;
+	unsigned long bitmap_chksum;
+	unsigned long usage;
+};
+
+struct memdesc_struct {
+	unsigned long chksum;
+	unsigned long optional_pa;
+	unsigned long numclusters;
+	struct memclust_struct cluster[0];
+};
+
+struct dsr_struct {
+	long smm;			/* SMM nubber used by LMF       */
+	unsigned long  lurt_off;	/* offset to LURT table         */
+	unsigned long  sysname_off;	/* offset to sysname char count */
+};
+
+struct hwrpb_struct {
+	unsigned long phys_addr;	/* check: physical address of the hwrpb */
+	unsigned long id;		/* check: "HWRPB\0\0\0" */
+	unsigned long revision;	
+	unsigned long size;		/* size of hwrpb */
+	unsigned long cpuid;
+	unsigned long pagesize;		/* 8192, I hope */
+	unsigned long pa_bits;		/* number of physical address bits */
+	unsigned long max_asn;
+	unsigned char ssn[16];		/* system serial number: big bother is watching */
+	unsigned long sys_type;
+	unsigned long sys_variation;
+	unsigned long sys_revision;
+	unsigned long intr_freq;	/* interval clock frequency * 4096 */
+	unsigned long cycle_freq;	/* cycle counter frequency */
+	unsigned long vptb;		/* Virtual Page Table Base address */
+	unsigned long res1;
+	unsigned long tbhb_offset;	/* Translation Buffer Hint Block */
+	unsigned long nr_processors;
+	unsigned long processor_size;
+	unsigned long processor_offset;
+	unsigned long ctb_nr;
+	unsigned long ctb_size;		/* console terminal block size */
+	unsigned long ctbt_offset;	/* console terminal block table offset */
+	unsigned long crb_offset;	/* console callback routine block */
+	unsigned long mddt_offset;	/* memory data descriptor table */
+	unsigned long cdb_offset;	/* configuration data block (or NULL) */
+	unsigned long frut_offset;	/* FRU table (or NULL) */
+	void (*save_terminal)(unsigned long);
+	unsigned long save_terminal_data;
+	void (*restore_terminal)(unsigned long);
+	unsigned long restore_terminal_data;
+	void (*CPU_restart)(unsigned long);
+	unsigned long CPU_restart_data;
+	unsigned long res2;
+	unsigned long res3;
+	unsigned long chksum;
+	unsigned long rxrdy;
+	unsigned long txrdy;
+	unsigned long dsr_offset;	/* "Dynamic System Recognition Data Block Table" */
+};
+
+#ifdef __KERNEL__
+
+extern struct hwrpb_struct *hwrpb;
+
+static inline void
+hwrpb_update_checksum(struct hwrpb_struct *h)
+{
+	unsigned long sum = 0, *l;
+        for (l = (unsigned long *) h; l < (unsigned long *) &h->chksum; ++l)
+                sum += *l;
+        h->chksum = sum;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __ALPHA_HWRPB_H */
diff --git a/init.c b/init.c
new file mode 100644
index 0000000..70b6297
--- /dev/null
+++ b/init.c
@@ -0,0 +1,206 @@
+#include <string.h>
+#include <stddef.h>
+#include "hwrpb.h"
+#include "osf.h"
+
+#define PAGE_SHIFT	13
+#define PAGE_SIZE	(1ul << PAGE_SHIFT)
+#define PAGE_OFFSET	0xfffffc0000000000UL
+
+#define HZ	1024
+
+struct pcb_struct pal_pcb __attribute__((section(".sbss")));
+
+unsigned long page_dir[1024] __attribute__((aligned(PAGE_SIZE)));
+unsigned long page_L1[1024] __attribute__((aligned(PAGE_SIZE)));
+unsigned long page_L2[1024][1024] __attribute__((aligned(PAGE_SIZE)));
+
+struct hwrpb_combine {
+  struct hwrpb_struct hwrpb;
+  struct percpu_struct processor;
+  struct memdesc_struct md;
+  struct memclust_struct mc[2];
+} hwrpb __attribute__((section(".data.hwrpb"))) = {
+  /* This is HWRPB\0\0\0.  */
+  .hwrpb.id = 0x4857525042000000,
+
+  .hwrpb.size = sizeof(struct hwrpb_struct),
+  .hwrpb.pagesize = PAGE_SIZE,
+  .hwrpb.ssn = "QEMU",
+
+  /* ??? This should match TARGET_PHYS_ADDR_SPACE_BITS from qemu.  */
+  .hwrpb.pa_bits = 44,
+
+  /* ??? Should we be truethful and say 1 asn, or simply pretend we
+     have ASNs but ignore them?  */
+  .hwrpb.max_asn = 127,
+
+  /* For now, hard-code emulation of sx164.  */
+  .hwrpb.cpuid = PCA56_CPU,
+  .processor.type = PCA56_CPU,
+  .hwrpb.sys_type = ST_DEC_EB164,
+  .hwrpb.sys_variation = 15 << 10,
+  .hwrpb.sys_revision = 0,
+
+  .hwrpb.intr_freq = HZ * 4096,
+
+  /* ??? What the hell should we put here.  Measure like the kernel will?  */
+  .hwrpb.cycle_freq = 400000000,
+
+  .hwrpb.vptb = 0x200000000UL,
+  .hwrpb.nr_processors = 1,
+  .hwrpb.processor_size = sizeof(struct percpu_struct),
+  .hwrpb.processor_offset = offsetof(struct hwrpb_combine, processor),
+
+  .hwrpb.mddt_offset = offsetof(struct hwrpb_combine, md),
+  .md.numclusters = 2,
+  .mc[0].usage = 2
+};
+
+static unsigned long
+init_cpuid (void)
+{
+  unsigned long implver, amask;
+
+  __asm ("implver %0" : "=r"(implver));
+  __asm ("amask %1,%0" : "=r"(amask) : "r"(-1));
+  amask = ~amask;
+
+  switch (implver)
+    {
+    case 0: /* EV4 */
+      return EV4_CPU;
+
+    case 1: /* EV5 */
+      if ((amask & 0x101) == 0x101)	/* MAX + BWX */
+	return PCA56_CPU;
+      if (amask & 1)			/* BWX */
+	return EV56_CPU;
+      return EV5_CPU;
+
+    case 2: /* EV6 */
+      if (amask & 4)			/* CIX */
+	return EV67_CPU;
+      return EV6_CPU;
+    }
+    return 0;
+}
+
+static void
+hwrpb_update_checksum (void)
+{
+  unsigned long sum = 0, *l;
+  for (l = (unsigned long *) &hwrpb.hwrpb; l < &hwrpb.hwrpb.chksum; ++l)
+    sum += *l;
+  hwrpb.hwrpb.chksum = sum;
+}
+
+static void
+init_hwrpb (unsigned long memsize)
+{
+  unsigned long end, pal_pages;
+
+  hwrpb.hwrpb.phys_addr = (unsigned int)(unsigned long)&hwrpb;
+
+  /* ??? For some reason GCC wants to use a LITERAL relocation for
+     _end instead of gp-relative relocations.  */
+  __asm ("ldah %0,_end($gp) !gprelhigh\n\tlda %0,_end(%0) !gprellow"
+         : "=r"(end));
+
+  pal_pages = ((unsigned int)end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+  hwrpb.mc[0].numpages = pal_pages;
+  hwrpb.mc[1].start_pfn = pal_pages;
+  hwrpb.mc[1].numpages = (memsize >> PAGE_SHIFT) - pal_pages;
+
+  hwrpb_update_checksum ();
+}
+
+static void
+init_pcb (void)
+{
+  pal_pcb.ptbr = (unsigned int)(unsigned long)page_dir;
+  pal_pcb.flags = 1;
+}
+
+static inline unsigned long
+build_pte (void *page)
+{
+  unsigned long bits;
+
+  bits = ((unsigned long)page - PAGE_OFFSET) << (32 - PAGE_SHIFT);
+  bits |= _PAGE_VALID;
+
+  return bits;
+}
+
+static inline void *
+pte_page (unsigned long pte)
+{
+  return (void *)((pte >> 32 << PAGE_SHIFT) + PAGE_OFFSET);
+}
+
+static void
+set_pte (unsigned long addr, void *page)
+{
+  unsigned long *pt = page_dir;
+  unsigned long index;
+
+  index = (addr >> (PAGE_SHIFT+20)) % 1024;
+  if (pt[index] != 0)
+    pt = pte_page (pt[index]);
+  else
+    __builtin_trap();
+
+  index = (addr >> (PAGE_SHIFT+10)) % 1024;
+  if (pt[index] != 0)
+    pt = pte_page (pt[index]);
+  else
+    __builtin_trap();
+
+  index = (addr >> PAGE_SHIFT) % 1024;
+  pt[index] = build_pte (page);
+}
+
+static void
+init_page_table (unsigned long memsize, unsigned long pal_pages)
+{
+  unsigned long i, addr, max_addr, page;
+
+  page_dir[0] = build_pte (page_L1);
+
+  for (i = 0; i < 1024; ++i)
+    page_L1[i] = build_pte (page_L2[i]);
+
+  set_pte ((unsigned long)INIT_HWRPB, &hwrpb);
+  
+  addr = 0x20000000ul;
+  max_addr = 1ul << (PAGE_SHIFT + 20);
+  page = pal_pages << PAGE_SHIFT;
+
+  while (addr < max_addr && page < memsize)
+    {
+      set_pte (addr, (void *)(PAGE_OFFSET + page));
+      addr += PAGE_SIZE;
+      page += PAGE_SIZE;
+    }
+
+  /* SRM places the self-map for the VPTBR in the second entry.  */
+  page_dir[1] = build_pte (page_dir);
+
+  /* Write the SRM vptptr.  */
+  {
+    register unsigned long a0 __asm__("$16") = max_addr;
+    __asm ("call_pal 0x2d" : : "r"(a0));
+  }
+}
+
+void
+do_start(unsigned long memsize)
+{
+  init_hwrpb (memsize);
+  init_pcb ();
+  init_page_table (memsize, hwrpb.mc[0].numpages);
+
+  while (1) ;
+}
diff --git a/memset.c b/memset.c
new file mode 100644
index 0000000..5f93dc3
--- /dev/null
+++ b/memset.c
@@ -0,0 +1,73 @@
+void *memset(void *optr, int ival, unsigned long size)
+{
+  unsigned long val = ival;
+  void *ptr = optr;
+
+  if (__builtin_expect (size == 0, 0))
+    return;
+
+  if (__builtin_expect (val != 0, 0))
+    {
+      val = val & 0xff;
+      val |= val << 8;
+      val |= val << 16;
+      val |= val << 32;
+    }
+
+  if (__builtin_expect ((unsigned long)ptr & 1, 0))
+    {
+      *(char *)ptr = val;
+      ptr += 1;
+      size -= 1;
+    }
+
+  if (__builtin_expect ((unsigned long)ptr & 2, 0))
+    {
+      if (size < 2)
+	goto tail_1;
+      *(short *)ptr = val;
+      ptr += 2;
+      size -= 2;
+    }
+
+  if (__builtin_expect ((unsigned long)ptr & 4, 0))
+    {
+      if (size < 4)
+	goto tail_3;
+      *(int *)ptr = val;
+      ptr += 4;
+      size -= 4;
+    }
+  
+  while (size >= 8)
+    {
+      *(long *)ptr = val;
+      ptr += 8;
+      size -= 8;
+    }
+
+  if (size >= 4)
+    {
+      *(int *)ptr = val;
+      ptr += 4;
+      size -= 4;
+    }
+
+ tail_3:
+  if (size >= 2)
+    {
+      *(short *)ptr = val;
+      ptr += 2;
+      size -= 2;
+    }
+
+ tail_1:
+  if (size > 0)
+    {
+      *(char *)ptr = val;
+      ptr += 1;
+      size -= 1;
+    }
+
+  return optr;
+}
diff --git a/palcode.ld b/palcode.ld
new file mode 100644
index 0000000..a1304b5
--- /dev/null
+++ b/palcode.ld
@@ -0,0 +1,48 @@
+OUTPUT_FORMAT("elf64-alpha")
+ENTRY(__start)
+
+SECTIONS
+{
+  . = 0xfffffc0000000000;
+  .text : { *(.text*) }
+  .rodata : { *(.rodata) }
+  .data ALIGN(8192) : { *(.data.hwrpb) *(.data*) }
+  .got : { *(.got.plt) *(.got) }
+  .sdata : { *(.sdata*) }
+  .sbss : { *(.sbss) *(.scommon) }
+  .bss : { *(.bss) *(COMMON) }
+  PROVIDE (_end = .);
+
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+  /DISCARD/ : { *(.eh_frame) }
+}