diff --git a/rt/.gitignore b/rt/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c64a20d51b42b8f4914d08967f5530b70e58bb04
--- /dev/null
+++ b/rt/.gitignore
@@ -0,0 +1,5 @@
+*.bin
+*.elf
+*.o
+*.sh
+*.stp
diff --git a/rt/Makefile b/rt/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..fa5ca99c5c8063a7b0bf8814470baa953e30288a
--- /dev/null
+++ b/rt/Makefile
@@ -0,0 +1,29 @@
+CROSS_COMPILE ?= /opt/gcc-lm32/bin/lm32-elf-
+
+OBJS = main.o dev/uart.o dev/timer.o lib/mprintf.o dev/ad9516.o
+
+CFLAGS_PLATFORM = -mmultiply-enabled -mbarrel-shift-enabled 
+LDFLAGS_PLATFORM = -mmultiply-enabled -mbarrel-shift-enabled   -nostdlib -T target/lm32/ram.ld 
+OBJS_PLATFORM=target/lm32/crt0.o target/lm32/irq.o
+
+CC=$(CROSS_COMPILE)gcc
+OBJCOPY=$(CROSS_COMPILE)objcopy
+OBJDUMP=$(CROSS_COMPILE)objdump
+CFLAGS= $(CFLAGS_PLATFORM) -ffunction-sections -fdata-sections -Os -Iinclude -include include/trace.h 
+LDFLAGS= $(LDFLAGS_PLATFORM) -ffunction-sections -fdata-sections -Os -Iinclude
+SIZE = $(CROSS_COMPILE)size
+OBJS += $(OBJS_PLATFORM)
+
+OUTPUT=rt_cpu
+
+all: 		$(OBJS)
+				$(SIZE) -t $(OBJS)
+				${CC} -o $(OUTPUT).elf $(OBJS) $(LDFLAGS) 
+				${OBJCOPY} -O binary $(OUTPUT).elf $(OUTPUT).bin
+
+clean:	
+				rm -f $(OBJS) $(OUTPUT).elf $(OUTPUT).bin $(OUTPUT).ram
+
+%.o:		%.c
+				${CC} $(CFLAGS) $(LIB_DIR) -c $^ -o $@
+
diff --git a/rt/dev/ad9516.c b/rt/dev/ad9516.c
new file mode 100644
index 0000000000000000000000000000000000000000..9f9443b6cf5882da78b4263c07fbea5fa1ea779e
--- /dev/null
+++ b/rt/dev/ad9516.c
@@ -0,0 +1,167 @@
+/*
+ * Trivial pll programmer using an spi controoler.
+ * PLL is AD9516, SPI is opencores
+ * Tomasz Wlostowski, Alessandro Rubini, 2011, for CERN.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "board.h"
+#include "timer.h"
+#include "gpio.h"
+
+#include "ad9516.h"
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+#endif
+
+struct ad9516_reg {
+	uint16_t reg;
+	uint8_t val;
+};
+
+#include "ad9516_config.h"
+
+/*
+ * SPI stuff, used by later code
+ */
+
+#define SPI_REG_RX0	0
+#define SPI_REG_TX0	0
+#define SPI_REG_RX1	4
+#define SPI_REG_TX1	4
+#define SPI_REG_RX2	8
+#define SPI_REG_TX2	8
+#define SPI_REG_RX3	12
+#define SPI_REG_TX3	12
+
+#define SPI_REG_CTRL	16
+#define SPI_REG_DIVIDER	20
+#define SPI_REG_SS	24
+
+#define SPI_CTRL_ASS		(1<<13)
+#define SPI_CTRL_IE		(1<<12)
+#define SPI_CTRL_LSB		(1<<11)
+#define SPI_CTRL_TXNEG		(1<<10)
+#define SPI_CTRL_RXNEG		(1<<9)
+#define SPI_CTRL_GO_BSY		(1<<8)
+#define SPI_CTRL_CHAR_LEN(x)	((x) & 0x7f)
+
+#define GPIO_PLL_RESET_N 1
+#define GPIO_SYS_CLK_SEL 0
+#define GPIO_PERIPH_RESET_N 3
+
+#define CS_PLL	0 /* AD9516 on SPI CS0 */
+
+static void *oc_spi_base;
+
+int oc_spi_init(void *base_addr)
+{
+	oc_spi_base = base_addr;
+
+	writel(100, oc_spi_base + SPI_REG_DIVIDER);
+	return 0;
+}
+
+int oc_spi_txrx(int ss, int nbits, uint32_t in, uint32_t *out)
+{
+	uint32_t rval;
+
+	if (!out)
+		out = &rval;
+
+	writel(SPI_CTRL_ASS | SPI_CTRL_CHAR_LEN(nbits)
+		     | SPI_CTRL_TXNEG,
+		     oc_spi_base + SPI_REG_CTRL);
+
+	writel(in, oc_spi_base + SPI_REG_TX0);
+	writel((1 << ss), oc_spi_base + SPI_REG_SS);
+	writel(SPI_CTRL_ASS | SPI_CTRL_CHAR_LEN(nbits)
+		     | SPI_CTRL_TXNEG | SPI_CTRL_GO_BSY,
+		     oc_spi_base + SPI_REG_CTRL);
+
+	while(readl(oc_spi_base + SPI_REG_CTRL) & SPI_CTRL_GO_BSY)
+		;
+	*out = readl(oc_spi_base + SPI_REG_RX0);
+	return 0;
+}
+
+/*
+ * AD9516 stuff, using SPI, used by later code.
+ * "reg" is 12 bits, "val" is 8 bits, but both are better used as int
+ */
+
+static void ad9516_write_reg(int reg, int val)
+{
+	oc_spi_txrx(CS_PLL, 24, (reg << 8) | val, NULL);
+}
+
+static int ad9516_read_reg(int reg)
+{
+	uint32_t rval;
+	oc_spi_txrx(CS_PLL, 24, (reg << 8) | (1 << 23), &rval);
+	return rval & 0xff;
+}
+
+
+
+static void ad9516_load_regset(const struct ad9516_reg *regs, int n_regs, int commit)
+{
+	int i;
+	for(i=0; i<n_regs; i++)
+		ad9516_write_reg(regs[i].reg, regs[i].val);
+		
+	if(commit)
+		ad9516_write_reg(0x232, 1);
+}
+
+
+static void ad9516_wait_lock()
+{
+	while ((ad9516_read_reg(0x1f) & 1) == 0);
+}
+
+int ad9516_init()
+{
+	TRACE("Initializing AD9516 PLL...\n");
+
+	oc_spi_init((void *)BASE_SPI);
+
+	gpio_out(GPIO_SYS_CLK_SEL, 0); /* switch to the standby reference clock, since the PLL is off after reset */
+
+	/* reset the PLL */
+	gpio_out(GPIO_PLL_RESET_N, 0);
+	timer_delay(10);
+	gpio_out(GPIO_PLL_RESET_N, 1);
+	timer_delay(10);
+	
+	/* Use unidirectional SPI mode */
+	ad9516_write_reg(0x000, 0x99);
+
+	/* Check the presence of the chip */
+	if (ad9516_read_reg(0x3) != 0xc3) {
+		TRACE("Error: AD9516 PLL not responding.\n");
+		return -1;
+	}
+
+	ad9516_load_regset(ad9516_base_config, ARRAY_SIZE(ad9516_base_config), 0);
+	ad9516_load_regset(ad9516_ref_tcxo, ARRAY_SIZE(ad9516_ref_tcxo), 1);
+	ad9516_wait_lock();
+
+	/* sync channels */
+	ad9516_write_reg(0x230, 1);
+	ad9516_write_reg(0x232, 1);
+	ad9516_write_reg(0x230, 0);
+	ad9516_write_reg(0x232, 1);
+
+	TRACE("AD9516 locked.\n");
+
+	gpio_out(GPIO_SYS_CLK_SEL, 1); /* switch the system clock to the PLL reference */
+	gpio_out(GPIO_PERIPH_RESET_N, 0); /* reset all peripherals which use AD9516-provided clocks */
+	gpio_out(GPIO_PERIPH_RESET_N, 1);
+
+	return 0;
+}
+
diff --git a/rt/dev/ad9516_config.h b/rt/dev/ad9516_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..bcb9dd84094cab67340bfbc773b8171d76d9371a
--- /dev/null
+++ b/rt/dev/ad9516_config.h
@@ -0,0 +1,79 @@
+
+/* Base configuration (global dividers, output config, reference-independent) */
+const struct ad9516_reg ad9516_base_config[] = {
+{0x0000, 0x99},
+{0x0001, 0x00},
+{0x0002, 0x10},
+{0x0003, 0xC3},
+{0x0004, 0x00},
+{0x0010, 0x7C},
+{0x0011, 0x05},
+{0x0012, 0x00},
+{0x0013, 0x0C},
+{0x0014, 0x12},
+{0x0015, 0x00},
+{0x0016, 0x05},
+{0x0017, 0x88},
+{0x0018, 0x07},
+{0x0019, 0x00},
+{0x001A, 0x00},
+{0x001B, 0x00},
+{0x001C, 0x02},
+{0x001D, 0x00},
+{0x001E, 0x00},
+{0x001F, 0x0E},
+{0x00A0, 0x01},
+{0x00A1, 0x00},
+{0x00A2, 0x00},
+{0x00A3, 0x01},
+{0x00A4, 0x00},
+{0x00A5, 0x00},
+{0x00A6, 0x01},
+{0x00A7, 0x00},
+{0x00A8, 0x00},
+{0x00A9, 0x01},
+{0x00AA, 0x00},
+{0x00AB, 0x00},
+{0x00F0, 0x0A},
+{0x00F1, 0x0A},
+{0x00F2, 0x0A},
+{0x00F3, 0x0A},
+{0x00F4, 0x08},
+{0x00F5, 0x08},
+{0x0140, 0x43},
+{0x0141, 0x42},
+{0x0142, 0x43},
+{0x0143, 0x42},
+{0x0190, 0x00},
+{0x0191, 0x80},
+{0x0192, 0x00},
+{0x0193, 0xBB},
+{0x0194, 0x00},
+{0x0195, 0x00},
+{0x0196, 0x00},
+{0x0197, 0x00},
+{0x0198, 0x00},
+{0x0199, 0x00},
+{0x019A, 0x00},
+{0x019B, 0x11},
+{0x019C, 0x20},
+{0x019D, 0x00},
+{0x019E, 0x11},
+{0x019F, 0x00},
+{0x01A0, 0x11},
+{0x01A1, 0x20},
+{0x01A2, 0x00},
+{0x01A3, 0x00},
+{0x01E0, 0x04},
+{0x01E1, 0x02},
+{0x0230, 0x00},
+{0x0231, 0x00},
+};
+
+/* Config for 25 MHz VCTCXO reference (RDiv = 5, use REF1) */
+const struct ad9516_reg ad9516_ref_tcxo[] = {
+{0x0011, 0x05},
+{0x0012, 0x00}, /* RDiv = 5 */
+{0x001C, 0x02}  /* Use REF1 */
+};
+
diff --git a/rt/dev/ad9516_regs.h b/rt/dev/ad9516_regs.h
new file mode 100644
index 0000000000000000000000000000000000000000..e44974c2f4bceb985dc2e01a8605ddce9179b464
--- /dev/null
+++ b/rt/dev/ad9516_regs.h
@@ -0,0 +1,70 @@
+const struct {int reg; uint8_t val} ad9516_regs[] = {
+{0x0000, 0x99},
+{0x0001, 0x00},
+{0x0002, 0x10},
+{0x0003, 0xC3},
+{0x0004, 0x00},
+{0x0010, 0x7C},
+{0x0011, 0x01},
+{0x0012, 0x00},
+{0x0013, 0x04},
+{0x0014, 0x07},
+{0x0015, 0x00},
+{0x0016, 0x04},
+{0x0017, 0x00},
+{0x0018, 0x07},
+{0x0019, 0x00},
+{0x001A, 0x00},
+{0x001B, 0x00},
+{0x001C, 0x02},
+{0x001D, 0x00},
+{0x001E, 0x00},
+{0x001F, 0x0E},
+{0x00A0, 0x01},
+{0x00A1, 0x00},
+{0x00A2, 0x00},
+{0x00A3, 0x01},
+{0x00A4, 0x00},
+{0x00A5, 0x00},
+{0x00A6, 0x01},
+{0x00A7, 0x00},
+{0x00A8, 0x00},
+{0x00A9, 0x01},
+{0x00AA, 0x00},
+{0x00AB, 0x00},
+{0x00F0, 0x0A},
+{0x00F1, 0x0A},
+{0x00F2, 0x0A},
+{0x00F3, 0x0A},
+{0x00F4, 0x08},
+{0x00F5, 0x0A},
+{0x0140, 0x43},
+{0x0141, 0x43},
+{0x0142, 0x43},
+{0x0143, 0x43},
+{0x0190, 0x00},
+{0x0191, 0x80},
+{0x0192, 0x00},
+{0x0193, 0xBB},
+{0x0194, 0x00},
+{0x0195, 0x00},
+{0x0196, 0x00},
+{0x0197, 0x00},
+{0x0198, 0x00},
+{0x0199, 0x22},
+{0x019A, 0x00},
+{0x019B, 0x11},
+{0x019C, 0x00},
+{0x019D, 0x00},
+{0x019E, 0x22},
+{0x019F, 0x00},
+{0x01A0, 0x11},
+{0x01A1, 0x00},
+{0x01A2, 0x00},
+{0x01A3, 0x00},
+{0x01E0, 0x04},
+{0x01E1, 0x02},
+{0x0230, 0x00},
+{0x0231, 0x00},
+{0x0232, 0x00},
+{-1, 0}};
diff --git a/rt/dev/timer.c b/rt/dev/timer.c
new file mode 100644
index 0000000000000000000000000000000000000000..ea70de978a6d99461290c48dff219edd8a3499a3
--- /dev/null
+++ b/rt/dev/timer.c
@@ -0,0 +1,20 @@
+#include "board.h"
+
+#include "timer.h"
+
+uint32_t timer_get_tics()
+{
+  return *(volatile uint32_t *) (BASE_TIMER);
+}
+
+void timer_delay(uint32_t how_long)
+{
+  uint32_t t_start;
+
+  t_start = timer_get_tics();
+
+	if(t_start + how_long < t_start)
+		while(t_start + how_long < timer_get_tics());
+
+	while(t_start + how_long > timer_get_tics());
+}
diff --git a/rt/dev/uart.c b/rt/dev/uart.c
new file mode 100644
index 0000000000000000000000000000000000000000..4596c2de093449c1011a71fd49f8a3b5425701c2
--- /dev/null
+++ b/rt/dev/uart.c
@@ -0,0 +1,41 @@
+#include "defs.h"
+#include "board.h"
+#include "uart.h"
+
+#include <hw/wb_uart.h>
+
+#define CALC_BAUD(baudrate) \
+    ( ((( (unsigned long long)baudrate * 8ULL) << (16 - 7)) + \
+      (CPU_CLOCK >> 8)) / (CPU_CLOCK >> 7) )
+
+static volatile struct UART_WB *uart = (volatile struct UART_WB *) BASE_UART;
+
+void uart_init()
+{
+	uart->BCR = CALC_BAUD(UART_BAUDRATE);
+}
+
+void uart_write_byte(int b)
+{
+	if(b == '\n')
+		uart_write_byte('\r');
+	while(uart->SR & UART_SR_TX_BUSY)
+		;
+	uart->TDR = b;
+}
+
+void uart_write_string(char *s)
+{
+	while (*s)
+		uart_write_byte(*(s++));
+}
+
+int uart_poll()
+{
+ 	return uart->SR & UART_SR_RX_RDY;
+}
+
+int uart_read_byte()
+{
+ 	return uart ->RDR & 0xff;
+}
\ No newline at end of file
diff --git a/rt/include/ad9516.h b/rt/include/ad9516.h
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/rt/include/board.h b/rt/include/board.h
new file mode 100644
index 0000000000000000000000000000000000000000..55a3e1685f4f45566f9913527d1f6e098b38954a
--- /dev/null
+++ b/rt/include/board.h
@@ -0,0 +1,16 @@
+#ifndef __BOARD_H
+#define __BOARD_H
+
+/* RT CPU Memory layout */
+
+#define CPU_CLOCK 62500000
+
+#define UART_BAUDRATE 115200
+
+#define BASE_UART 0x10000
+#define BASE_SOFTPLL 0x10100
+#define BASE_SPI 0x10200
+#define BASE_GPIO 0x10300
+#define BASE_TIMER 0x10400
+
+#endif
diff --git a/rt/include/defs.h b/rt/include/defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2727173e3344ff436f7f3d8916e7ace60ce8a99
--- /dev/null
+++ b/rt/include/defs.h
@@ -0,0 +1,17 @@
+#ifndef __DEFS_H
+#define __DEFS_H
+
+#include <stdint.h>
+
+static inline void writel(uint32_t data, void *where)
+{
+	* (volatile uint32_t *)where = data;
+}
+
+static inline uint32_t readl(void *where)
+{
+	return * (volatile uint32_t *)where;
+}
+
+
+#endif
diff --git a/rt/include/gpio.h b/rt/include/gpio.h
new file mode 100644
index 0000000000000000000000000000000000000000..7fb7035585bfd345dac4cd5278732fe4445e9e00
--- /dev/null
+++ b/rt/include/gpio.h
@@ -0,0 +1,41 @@
+#ifndef __GPIO_H
+#define __GPIO_H
+
+#include <inttypes.h>
+
+#include "board.h"
+
+struct GPIO_WB
+{
+  uint32_t CODR;  /*Clear output register*/
+  uint32_t SODR;  /*Set output register*/
+  uint32_t DDR;   /*Data direction register (1 means out)*/
+  uint32_t PSR;   /*Pin state register*/
+};
+
+static volatile struct GPIO_WB *__gpio = (volatile struct GPIO_WB *) BASE_GPIO;
+
+static inline void gpio_out(int pin, int val)
+{
+  if(val)
+    __gpio->SODR = (1<<pin);
+  else
+    __gpio->CODR = (1<<pin);
+}
+
+static inline void gpio_dir(int pin, int val)
+{
+  if(val)
+    __gpio->DDR |= (1<<pin);
+  else
+    __gpio->DDR &= ~(1<<pin);
+}
+
+static inline int gpio_in(int bank, int pin)
+{
+  return __gpio->PSR & (1<<pin) ? 1: 0;
+}
+
+        
+#endif
+        
diff --git a/rt/include/hw/wb_uart.h b/rt/include/hw/wb_uart.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef51bb281f7da0fa13b538877d48198a5255c1a9
--- /dev/null
+++ b/rt/include/hw/wb_uart.h
@@ -0,0 +1,79 @@
+/*
+  Register definitions for slave core: Simple Wishbone UART
+
+  * File           : ../../../../software/include/hw/wb_uart.h
+  * Author         : auto-generated by wbgen2 from uart.wb
+  * Created        : Mon Feb 21 22:25:02 2011
+  * Standard       : ANSI C
+
+    THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE uart.wb
+    DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
+
+*/
+
+#ifndef __WBGEN2_REGDEFS_UART_WB
+#define __WBGEN2_REGDEFS_UART_WB
+
+#include <inttypes.h>
+
+#if defined( __GNUC__)
+#define PACKED __attribute__ ((packed))
+#else
+#error "Unsupported compiler?"
+#endif
+
+#ifndef __WBGEN2_MACROS_DEFINED__
+#define __WBGEN2_MACROS_DEFINED__
+#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
+#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
+#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
+#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
+#endif
+
+
+/* definitions for register: Status Register */
+
+/* definitions for field: TX busy in reg: Status Register */
+#define UART_SR_TX_BUSY                       WBGEN2_GEN_MASK(0, 1)
+
+/* definitions for field: RX ready in reg: Status Register */
+#define UART_SR_RX_RDY                        WBGEN2_GEN_MASK(1, 1)
+
+/* definitions for register: Baudrate control register */
+
+/* definitions for register: Transmit data regsiter */
+
+/* definitions for field: Transmit data in reg: Transmit data regsiter */
+#define UART_TDR_TX_DATA_MASK                 WBGEN2_GEN_MASK(0, 8)
+#define UART_TDR_TX_DATA_SHIFT                0
+#define UART_TDR_TX_DATA_W(value)             WBGEN2_GEN_WRITE(value, 0, 8)
+#define UART_TDR_TX_DATA_R(reg)               WBGEN2_GEN_READ(reg, 0, 8)
+
+/* definitions for register: Receive data regsiter */
+
+/* definitions for field: Received data in reg: Receive data regsiter */
+#define UART_RDR_RX_DATA_MASK                 WBGEN2_GEN_MASK(0, 8)
+#define UART_RDR_RX_DATA_SHIFT                0
+#define UART_RDR_RX_DATA_W(value)             WBGEN2_GEN_WRITE(value, 0, 8)
+#define UART_RDR_RX_DATA_R(reg)               WBGEN2_GEN_READ(reg, 0, 8)
+/* [0x0]: REG Status Register */
+#define UART_REG_SR 0x00000000
+/* [0x4]: REG Baudrate control register */
+#define UART_REG_BCR 0x00000004
+/* [0x8]: REG Transmit data regsiter */
+#define UART_REG_TDR 0x00000008
+/* [0xc]: REG Receive data regsiter */
+#define UART_REG_RDR 0x0000000c
+
+PACKED struct UART_WB {
+  /* [0x0]: REG Status Register */
+  uint32_t SR;
+  /* [0x4]: REG Baudrate control register */
+  uint32_t BCR;
+  /* [0x8]: REG Transmit data regsiter */
+  uint32_t TDR;
+  /* [0xc]: REG Receive data regsiter */
+  uint32_t RDR;
+};
+
+#endif
diff --git a/rt/include/irq.h b/rt/include/irq.h
new file mode 100644
index 0000000000000000000000000000000000000000..6dee657134900fa58abebdb2a975dfd7825b5705
--- /dev/null
+++ b/rt/include/irq.h
@@ -0,0 +1,10 @@
+#ifndef __IRQ_H
+#define __IRQ_H
+
+static inline void clear_irq()
+{
+  unsigned int val = 1;
+  asm volatile ("wcsr ip, %0"::"r"(val));
+}
+
+#endif
diff --git a/rt/include/rt_ipc.h b/rt/include/rt_ipc.h
new file mode 100644
index 0000000000000000000000000000000000000000..96d1d12fa2361c2ef96b1194a25541fb67c98628
--- /dev/null
+++ b/rt/include/rt_ipc.h
@@ -0,0 +1,83 @@
+#include <stdint.h>
+
+#define RTS_PLL_CHANNELS 32
+
+/* Individual channel flags */
+/* Reference input frequency valid */
+#define CHAN_REF_VALID (1<<0)
+/* Frequency out of range */
+#define CHAN_FREQ_OUT_OF_RANGE (1<<1)
+/* Phase is drifting too fast */
+#define CHAN_DRIFTING (1<<2)
+
+
+/* DMTD clock is present */
+#define RTS_DMTD_LOCKED (1<<0)
+
+/* 125 MHz reference locked */
+#define RTS_REF_LOCKED (1<<1)
+
+/* External 10 MHz reference present */
+#define RTS_EXT_10M_VALID (1<<2)
+
+/* External 1-PPS present */
+#define RTS_EXT_PPS_VALID (1<<3)
+
+/* External 10 MHz frequency out-of-range */
+#define RTS_EXT_10M_OUT_OF_RANGE (1<<4)
+
+/* External 1-PPS frequency out-of-range */
+#define RTS_EXT_PPS_OUT_OF_RANGE (1<<5)
+
+/* Holdover mode active */
+#define RTS_HOLDOVER_ACTIVE (1<<6)
+
+/* Grandmaster mode active (uses 10 MHz / 1-PPS reference) */
+#define RTS_MODE_GRANDMASTER (1<<7)
+
+/* Boundary clock mode active (uses network reference) */
+#define RTS_MODE_BC (1<<8)
+
+/* When set, phase_loopback contains a valid phase measurement */
+#define RTS_LOOPBACK_PHASE_READY (1<<9)
+
+/* null reference input */
+#define REF_NONE 255
+
+struct rts_pll_state {
+
+/* State of an individual input channel (i.e. switch port) */
+	struct channel {
+		/* Switchover priority: 0 = highest, 1 - 254 = high..low, 255 = channel disabled (a master port) */
+		uint8_t priority; 
+		/* channel phase setpoint in picoseconds. Used only when channel is a slave */
+		int32_t phase_setpoint; 
+		/* TX-RX Loopback phase measurement in picoseconds */
+		int32_t phase_looback;
+		/* flags (per channel - see CHAN_xxx defines) */
+		uint32_t flags; 
+	} channels[RTS_PLL_CHANNELS];
+
+	/* flags (global - RTS_xxx defines) */	
+	uint32_t flags; 
+
+	/* duration of current holdover period in 10us units */
+	int32_t holdover_duration;
+	
+	/* current reference source - or REF_NONE if free-running or grandmaster */
+	uint8_t current_ref;
+};
+
+/* API */
+
+/* Queries the RT CPU PLL state */
+int rts_get_state(struct rts_pll_state *state);
+
+/* Sets the phase setpoint on a given channel */
+int rts_adjust_phase(uint8_t channel, int32_t phase_setpoint);
+
+/* Sets the RT subsystem mode (Boundary Clock or Grandmaster) */
+int rts_set_mode(uint32_t mode);
+
+/* Reference channel configuration (BC mode only) */
+int rts_config_channel(uint8_t channel, uint8_t priority);
diff --git a/rt/include/timer.h b/rt/include/timer.h
new file mode 100644
index 0000000000000000000000000000000000000000..9fa2b6990031a3449b65d29594b86e943cbc1ee9
--- /dev/null
+++ b/rt/include/timer.h
@@ -0,0 +1,12 @@
+#ifndef __TIMER_H
+#define __TIMER_H
+
+#include "defs.h"
+
+#define TICS_PER_SECOND 100000
+
+uint32_t timer_get_tics();
+void timer_delay(uint32_t how_long);
+int timer_expired(uint32_t t_start, uint32_t how_long);
+
+#endif
diff --git a/rt/include/trace.h b/rt/include/trace.h
new file mode 100644
index 0000000000000000000000000000000000000000..76d6097fe1bdfb821a3e47a1742be7caeab1fd17
--- /dev/null
+++ b/rt/include/trace.h
@@ -0,0 +1,6 @@
+#ifndef __FREESTANDING_TRACE_H__
+#define __FREESTANDING_TRACE_H__
+
+#define TRACE(...) mprintf(__VA_ARGS__)
+
+#endif
diff --git a/rt/include/uart.h b/rt/include/uart.h
new file mode 100644
index 0000000000000000000000000000000000000000..86e8e9d85567047b6e69b7ae008068a6624e1dad
--- /dev/null
+++ b/rt/include/uart.h
@@ -0,0 +1,12 @@
+#ifndef __UART_H
+#define __UART_H
+
+int mprintf(char const *format, ...);
+
+void uart_init();
+void uart_write_byte(int b);
+void uart_write_string(char *s);
+int uart_poll();
+int uart_read_byte();
+
+#endif
diff --git a/rt/lib/mprintf.c b/rt/lib/mprintf.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a3d912ce8fc4f406b7245a8465206a25e302235
--- /dev/null
+++ b/rt/lib/mprintf.c
@@ -0,0 +1,276 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include "uart.h"
+
+int vprintf(char const *format,va_list ap)
+{
+  unsigned char  	scratch[16];
+  unsigned char  	format_flag;
+  unsigned int 	u_val=0;
+  unsigned char 	base;
+  unsigned char 	*ptr;
+  unsigned char 	width = 0;
+  unsigned char  	fill;
+
+  while(1)
+  {
+  
+  	width = 0;
+  	fill = ' ';
+    while ((format_flag = *format++) != '%')
+	{  
+      if (!format_flag)
+	  {
+		  va_end (ap); 
+		  return (0);
+	  }
+	
+      uart_write_byte(format_flag);
+    }
+
+
+	// check for zero pad
+	format_flag = *format - '0'; 
+	if (format_flag == 0)	// zero pad
+	{
+		fill = '0';
+		format++;
+	}
+	
+	// check for width spec
+	format_flag = *format - '0'; 
+	if (format_flag > 0 && format_flag <= 9)	// width set
+	{
+		width = format_flag;
+		format++;	
+	}
+	
+    switch (format_flag = *format++)
+	{
+		case 'c':
+		  format_flag = va_arg(ap,int);
+
+		  //fall through
+		  
+		default:
+      uart_write_byte(format_flag);
+
+		  continue;
+		  
+		case 'S':
+		case 's':
+		  ptr = (unsigned char *)va_arg(ap, char *);
+		  while (*ptr)
+	          uart_write_byte(*ptr++);
+		  continue;
+
+
+
+		case 'd':
+
+		  base = 10;
+		  goto CONVERSION_LOOP;
+
+		case 'u':
+		  base = 10;
+		  goto CONVERSION_LOOP;
+		  
+		case 'x':
+		  base = 16;
+
+CONVERSION_LOOP:
+
+	  	u_val = va_arg(ap,unsigned int);
+		if((format_flag=='d') && (u_val&0x80000000))
+		{
+		    uart_write_byte('-');
+		    u_val=-u_val;
+		}
+
+		  	
+		 ptr = scratch + 16;
+
+		  *--ptr = 0;
+
+		  do
+		  {
+			char ch = (u_val % base) + '0';
+			if (ch > '9')
+			  ch += 'a' - '9' - 1;
+
+			*--ptr = ch;
+
+			u_val /= base;
+
+			if (width)
+				width--;
+		
+		  } while (u_val>0);
+
+//	  while (width--)
+//		 	*--ptr = fill; 		      
+      
+		  while (*ptr)
+	          uart_write_byte(*ptr++);
+
+    }
+  }
+  return 0;
+}
+
+
+static int _p_vsprintf(char const *format,va_list ap, char*dst)
+{
+  unsigned char  	scratch[16];
+  unsigned char  	format_flag;
+  unsigned int 	u_val=0;
+  unsigned char 	base;
+  unsigned char 	*ptr;
+  unsigned char 	width = 0;
+  unsigned char  	fill;
+
+  while(1)
+  {
+  
+  	width = 0;
+  	fill = ' ';
+    while ((format_flag = *format++) != '%')
+	{  
+      if (!format_flag)
+	  {
+		  va_end (ap); 
+		    *dst++=0;
+		  return (0);
+	  }
+	
+     *dst++=format_flag;
+    }
+
+
+	// check for zero pad
+	format_flag = *format - '0'; 
+	if (format_flag == 0)	// zero pad
+	{
+		fill = '0';
+		format++;
+	}
+	
+	// check for width spec
+	format_flag = *format - '0'; 
+	if (format_flag > 0 && format_flag <= 9)	// width set
+	{
+		width = format_flag;
+		format++;	
+	}
+	
+    switch (format_flag = *format++)
+	{
+		case 'c':
+		  format_flag = va_arg(ap,int);
+
+		  //fall through
+		  
+		default:
+       *dst++=format_flag;
+
+		  continue;
+		  
+		case 'S':
+		case 's':
+		  ptr = (unsigned char *)va_arg(ap, char *);
+		  while (*ptr)
+	           *dst++=*ptr++;
+		  continue;
+
+
+
+		case 'd':
+		case 'u':
+		  base = 10;
+		  goto CONVERSION_LOOP;
+		  
+		case 'x':
+		  base = 16;
+
+CONVERSION_LOOP:
+
+	  	u_val = va_arg(ap,unsigned int);
+		  	
+		 ptr = scratch + 16;
+
+		  *--ptr = 0;
+
+		  do
+		  {
+			char ch = (u_val % base) + '0';
+			if (ch > '9')
+			  ch += 'a' - '9' - 1;
+
+			*--ptr = ch;
+
+			u_val /= base;
+
+			if (width)
+				width--;
+		
+		  } while (u_val>0);
+
+//	  while (width--)
+//		 	*--ptr = fill; 		      
+      
+		  while (*ptr)
+	           *dst++=*ptr++;
+
+    }
+  }
+    *dst++=0;
+  return 0;
+}
+
+int mprintf(char const *format, ...)
+{
+	int rval;
+  	va_list ap;
+  	va_start (ap, format);
+  	rval = vprintf(format,ap);
+  	va_end(ap);
+  	return rval;
+  	
+}
+
+int sprintf(char *dst, char const *format, ...)
+{
+  	va_list ap;
+  	va_start (ap, format);
+  	int r= _p_vsprintf(format,ap,dst);
+		return r;
+	
+}
+
+#define C_DIM 0x80                                                                                                    
+void m_cprintf(int color, const char *fmt, ...)                                                                    
+{
+  va_list ap;                                                                                                       
+  mprintf("\033[0%d;3%dm",color & C_DIM ? 2:1, color&0x7f);                                                          
+  va_start(ap, fmt);
+  vprintf(fmt, ap);                                                                                                 
+  va_end(ap);
+}
+
+void m_pcprintf(int row, int col, int color, const char *fmt, ...)                                                 
+{
+  va_list ap;                                                                                                       
+  mprintf("\033[%d;%df", row, col);
+  mprintf("\033[0%d;3%dm",color & C_DIM ? 2:1, color&0x7f); 
+  va_start(ap, fmt);                                                                                                
+  vprintf(fmt, ap);                                                                                                 
+  va_end(ap);
+}
+
+void m_term_clear()                                                                                                     
+{
+  mprintf("\033[2J\033[1;1H");                                                                                       
+}
+
diff --git a/rt/main.c b/rt/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..2087f1b3101f41b9e226f6ae0d64fafca404eb28
--- /dev/null
+++ b/rt/main.c
@@ -0,0 +1,17 @@
+#include "defs.h"
+#include "uart.h"
+#include "timer.h"
+
+void _irq_entry() {};
+
+main()
+{
+	uart_init();
+	ad9516_init();
+	
+	for(;;)
+	{
+		mprintf("Ping!\n");
+		timer_delay(TICS_PER_SECOND);
+	}
+}
\ No newline at end of file
diff --git a/rt/target/lm32/crt0.S b/rt/target/lm32/crt0.S
new file mode 100755
index 0000000000000000000000000000000000000000..eca382680209c235195f9e68f09765b2909f00ca
--- /dev/null
+++ b/rt/target/lm32/crt0.S
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+**  Name: crt0ram.S
+**
+**  Description:
+**        Implements boot-code that calls LatticeDDInit (that calls main())
+**        Implements exception handlers (actually, redirectors)
+**
+**  $Revision: $
+**
+** Disclaimer:
+**
+**   This source code is intended as a design reference which
+**   illustrates how these types of functions can be implemented.  It
+**   is the user's responsibility to verify their design for
+**   consistency and functionality through the use of formal
+**   verification methods.  Lattice Semiconductor provides no warranty
+**   regarding the use or functionality of this code.
+**
+** --------------------------------------------------------------------
+**
+**                     Lattice Semiconductor Corporation
+**                     5555 NE Moore Court
+**                     Hillsboro, OR 97214
+**                     U.S.A
+**
+**                     TEL: 1-800-Lattice (USA and Canada)
+**                          (503)268-8001 (other locations)
+**
+**                     web:   http://www.latticesemi.com
+**                     email: techsupport@latticesemi.com
+**
+** --------------------------------------------------------------------------
+**
+**  Change History (Latest changes on top)
+**
+**  Ver    Date        Description
+** --------------------------------------------------------------------------
+**  3.8   Apr-15-2011  Added __MICO_USER_<handler>_HANDLER__ preprocessor to 
+**                     allow customers to implement their own handlers for:
+**                     DATA_ABORT, INST_ABORT
+**  
+**  3.1   Jun-18-2008  Added __MICO_NO_INTERRUPTS__ preprocessor
+**                     option to exclude invoking MicoISRHandler
+**                     to reduce code-size in apps that don't use
+**                     interrupts
+**
+**  3.0   Mar-25-2008  Added Header
+**
+**---------------------------------------------------------------------------
+*****************************************************************************/
+
+/*
+ * LatticeMico32 C startup code.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* From include/sys/signal.h */  
+#define SIGINT  2   /* interrupt */
+#define SIGTRAP 5   /* trace trap */
+#define SIGFPE  8   /* arithmetic exception */
+#define SIGSEGV 11  /* segmentation violation */
+
+//#define MICO32_FULL_CONTEXT_SAVE_RESTORE
+
+
+/* Exception handlers - Must be 32 bytes long. */
+        .section    .boot, "ax", @progbits
+	
+        .global	_start  
+_start: 
+	   
+        .global _reset_handler
+        .type 	_reset_handler, @function
+_reset_handler:
+    xor r0, r0, r0
+    wcsr    IE, r0
+    wcsr    IM, r0
+    mvhi    r1, hi(_reset_handler)
+    ori     r1, r1, lo(_reset_handler)
+    wcsr    EBA, r1
+    calli   _crt0
+    nop
+        .size	_reset_handler, .-_reset_handler
+	
+.extern _irq_entry
+.org 0xc0
+        .global _interrupt_handler
+        .type 	_interrupt_handler, @function
+_interrupt_handler:
+    sw      (sp+0), ra
+    calli   _save_all
+    mvi     r1, SIGINT
+#ifndef __MICO_NO_INTERRUPTS__
+    calli  _irq_entry
+#else
+    wcsr    IE, r0
+#endif
+    bi      _restore_all_and_return
+    nop
+    nop
+    nop
+
+.org 0x100
+        .global _crt0
+        .type 	_crt0, @function
+_crt0:
+    /* Clear r0 */
+    xor     r0, r0, r0
+    /* Setup stack and global pointer */
+    mvhi    sp, hi(_fstack)
+    ori     sp, sp, lo(_fstack)
+    mvhi    gp, hi(_gp)
+    ori     gp, gp, lo(_gp)
+	
+    mvhi    r1, hi(_fbss)
+    ori     r1, r1, lo(_fbss)
+    mvi     r2, 0
+    mvhi    r3, hi(_ebss)
+    ori     r3, r3, lo(_ebss)
+    sub     r3, r3, r1
+    calli   memset
+    mvi     r1, 0
+    mvi     r2, 0
+    mvi     r3, 0
+    calli   main
+
+loopf:
+	bi loopf
+
+        .global _save_all
+        .type 	_save_all, @function
+_save_all:
+#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
+    addi    sp, sp, -128
+#else
+    addi    sp, sp, -60
+#endif
+    sw      (sp+4), r1
+    sw      (sp+8), r2
+    sw      (sp+12), r3
+    sw      (sp+16), r4
+    sw      (sp+20), r5
+    sw      (sp+24), r6
+    sw      (sp+28), r7
+    sw      (sp+32), r8
+    sw      (sp+36), r9
+    sw      (sp+40), r10
+#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
+    sw      (sp+44), r11
+    sw      (sp+48), r12
+    sw      (sp+52), r13
+    sw      (sp+56), r14
+    sw      (sp+60), r15
+    sw      (sp+64), r16
+    sw      (sp+68), r17
+    sw      (sp+72), r18
+    sw      (sp+76), r19
+    sw      (sp+80), r20
+    sw      (sp+84), r21
+    sw      (sp+88), r22
+    sw      (sp+92), r23
+    sw      (sp+96), r24
+    sw      (sp+100), r25
+    sw      (sp+104), r26
+    sw      (sp+108), r27
+    sw      (sp+120), ea
+    sw      (sp+124), ba
+    /* ra and sp need special handling, as they have been modified */
+    lw      r1, (sp+128)
+    sw      (sp+116), r1
+    mv      r1, sp
+    addi    r1, r1, 128
+    sw      (sp+112), r1
+#else
+    sw      (sp+52), ea
+    sw      (sp+56), ba
+    /* ra and sp need special handling, as they have been modified */
+    lw      r1, (sp+60)
+    sw      (sp+48), r1
+    mv      r1, sp
+    addi    r1, r1, 60
+    sw      (sp+44), r1
+#endif
+//    xor     r1, r1, r1
+//    wcsr    ie, r1
+    ret
+        .size  	_save_all, .-_save_all
+	
+        .global _restore_all_and_return
+        .type 	_restore_all_and_return, @function
+    /* Restore all registers and return from exception */
+_restore_all_and_return:
+//    addi    r1, r0, 2
+//    wcsr    ie, r1
+    lw      r1, (sp+4)
+    lw      r2, (sp+8) 
+    lw      r3, (sp+12) 
+    lw      r4, (sp+16) 
+    lw      r5, (sp+20) 
+    lw      r6, (sp+24) 
+    lw      r7, (sp+28) 
+    lw      r8, (sp+32) 
+    lw      r9, (sp+36) 
+    lw      r10, (sp+40)
+#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
+    lw      r11, (sp+44)
+    lw      r12, (sp+48)
+    lw      r13, (sp+52)
+    lw      r14, (sp+56)
+    lw      r15, (sp+60)
+    lw      r16, (sp+64)
+    lw      r17, (sp+68)
+    lw      r18, (sp+72)
+    lw      r19, (sp+76)
+    lw      r20, (sp+80)
+    lw      r21, (sp+84)
+    lw      r22, (sp+88)
+    lw      r23, (sp+92)
+    lw      r24, (sp+96)
+    lw      r25, (sp+100)
+    lw      r26, (sp+104)
+    lw      r27, (sp+108)
+    lw      ra, (sp+116)
+    lw      ea, (sp+120)
+    lw      ba, (sp+124)
+    /* Stack pointer must be restored last, in case it has been updated */
+    lw      sp, (sp+112)
+#else
+    lw      ra, (sp+48)
+    lw      ea, (sp+52)
+    lw      ba, (sp+56)
+    /* Stack pointer must be restored last, in case it has been updated */
+    lw      sp, (sp+44)
+#endif
+    nop
+    eret
+        .size   _restore_all_and_return, .-_restore_all_and_return
+
diff --git a/rt/target/lm32/debug.S b/rt/target/lm32/debug.S
new file mode 100644
index 0000000000000000000000000000000000000000..315f69731830a4317426b50c40131bd14ff3c92f
--- /dev/null
+++ b/rt/target/lm32/debug.S
@@ -0,0 +1,460 @@
+/* LM32 JTAG relocatable debug ROM
+ *
+ * Load this code anywhere in memory and point DEBA at it.
+ * When DC=1 it chain loads the exception handlers at EBA.
+ * User exception handlers must save to the stack.
+ * 
+ * Copyright (C) 2011 by Wesley W. Terpstra <w.terpstra@gsi.de>
+ */
+
+
+.section    .boot, "ax", @progbits
+.global     _debug_unit
+.align      256
+
+_debug_unit:
+_reset_handler:
+	ori	r0, ra, 0			/* Save RA before destroying it */
+	calli	_find0
+_find0: addi	ra, ra, _registers-_find0	/* RA now points to _registers */
+	sw	(ra+_gp-_registers), gp		/* Save user GP */
+	ori	gp, ra, 0			/* GP now points to _registers */
+	calli	save_all
+_eid_offset:
+	calli	handle_debug_trap
+	bi	_e_restore_and_return
+
+_breakpoint_handler:
+	ori	r0, ra, 0			/* Save RA before destroying it */
+	calli	_find1
+_find1: addi	ra, ra, _registers-_find1	/* RA now points to _registers */
+	sw	(ra+_gp-_registers), gp		/* Save user GP */
+	ori	gp, ra, 0			/* GP now points to _registers */
+	calli	save_all
+	calli	handle_debug_trap
+	bi	_b_restore_and_return
+
+_instruction_bus_error_handler:
+	ori	r0, ra, 0			/* Save RA before destroying it */
+	calli	_find2
+_find2: addi	ra, ra, _registers-_find2	/* RA now points to _registers */
+	sw	(ra+_gp-_registers), gp		/* Save user GP */
+	ori	gp, ra, 0			/* GP now points to _registers */
+	calli	save_all
+	calli	handle_debug_trap
+	bi	_e_restore_and_return
+
+_watchpoint_handler:
+	ori	r0, ra, 0			/* Save RA before destroying it */
+	calli	_find3
+_find3: addi	ra, ra, _registers-_find3	/* RA now points to _registers */
+	sw	(ra+_gp-_registers), gp		/* Save user GP */
+	ori	gp, ra, 0			/* GP now points to _registers */
+	calli	save_all
+	calli	handle_debug_trap
+	bi	_b_restore_and_return
+
+_data_bus_error_handler:
+	ori	r0, ra, 0			/* Save RA before destroying it */
+	calli	_find4
+_find4: addi	ra, ra, _registers-_find4	/* RA now points to _registers */
+	sw	(ra+_gp-_registers), gp		/* Save user GP */
+	ori	gp, ra, 0			/* GP now points to _registers */
+	calli	save_all
+	calli	handle_debug_trap
+	bi	_e_restore_and_return
+
+_divide_by_zero_handler:
+	ori	r0, ra, 0			/* Save RA before destroying it */
+	calli	_find5
+_find5: addi	ra, ra, _registers-_find5	/* RA now points to _registers */
+	sw	(ra+_gp-_registers), gp		/* Save user GP */
+	ori	gp, ra, 0			/* GP now points to _registers */
+	calli	save_all
+	calli	handle_debug_trap
+	bi	_e_restore_and_return
+
+_interrupt_handler:
+	ori	r0, ra, 0			/* Save RA before destroying it */
+	calli	_find6
+_find6: addi	ra, ra, _registers-_find6	/* RA now points to _registers */
+	sw	(ra+_gp-_registers), gp		/* Save user GP */
+	ori	gp, ra, 0			/* GP now points to _registers */
+	calli	save_all
+	calli	handle_debug_trap
+	bi	_e_restore_and_return
+
+_system_call_handler:
+	ori	r0, ra, 0			/* Save RA before destroying it */
+	calli	_find7
+_find7: addi	ra, ra, _registers-_find7	/* RA now points to _registers */
+	sw	(ra+_gp-_registers), gp		/* Save user GP */
+	ori	gp, ra, 0			/* GP now points to _registers */
+	calli	save_all
+	calli	handle_debug_trap
+	bi	_e_restore_and_return
+
+/* Restore registers and return from breakpoint */
+_b_restore_and_return:
+	/* first restore gp registers */
+	calli	restore_gp
+	/* load the last two registers */
+	lw	ra, (gp+_ra-_registers)
+	lw	gp, (gp+_gp-_registers)
+	bret
+
+/* Restore registers and chain execution to the user exception handler */
+_e_restore_and_return:
+	/* first restore gp registers */
+	calli	restore_gp
+	lw	ba, (gp+_eid-_registers)
+	rcsr	ra, EBA
+	add	ba, ba, ra
+	/* load the last two registers */
+	lw	ra, (gp+_ra-_registers)
+	lw	gp, (gp+_gp-_registers)
+	b	ba
+
+save_all:
+	/* Save registers */
+	sw	(gp+_r1 -_registers), r1
+	sw	(gp+_r2 -_registers), r2
+	sw	(gp+_r3 -_registers), r3
+	sw	(gp+_r4 -_registers), r4
+	sw	(gp+_r5 -_registers), r5
+	sw	(gp+_r6 -_registers), r6
+	sw	(gp+_r7 -_registers), r7
+	sw	(gp+_r8 -_registers), r8
+	sw	(gp+_r9 -_registers), r9
+	sw	(gp+_r10-_registers), r10
+	sw	(gp+_r11-_registers), r11
+	sw	(gp+_r12-_registers), r12
+	sw	(gp+_r13-_registers), r13
+	sw	(gp+_r14-_registers), r14
+	sw	(gp+_r15-_registers), r15
+	sw	(gp+_r16-_registers), r16
+	sw	(gp+_r17-_registers), r17
+	sw	(gp+_r18-_registers), r18
+	sw	(gp+_r19-_registers), r19
+	sw	(gp+_r20-_registers), r20
+	sw	(gp+_r21-_registers), r21
+	sw	(gp+_r22-_registers), r22
+	sw	(gp+_r23-_registers), r23
+	sw	(gp+_r24-_registers), r24
+	sw	(gp+_r25-_registers), r25
+	/* GP already saved by handler */
+	sw	(gp+_fp -_registers), fp
+	sw	(gp+_sp -_registers), sp
+	sw	(gp+_ra -_registers), r0 /* handler saved RA in R0 */
+	sw	(gp+_ea -_registers), ea
+	sw	(gp+_ba -_registers), ba
+
+	/* Calculate EID*32 = ra - _eid_offset */
+	sub	r1, ra, gp
+	addi	r1, r1, _registers-_eid_offset
+	sw	(gp+_eid-_registers), r1
+
+	/* Start saving the CSRs */
+	rcsr	r1, EBA
+	sw	(gp+_eba-_registers), r1
+	rcsr	r1, DEBA
+	sw	(gp+_deba-_registers), r1
+	rcsr	r1, IE
+	sw	(gp+_ie-_registers), r1
+	rcsr	r1, IM
+	sw	(gp+_im-_registers), r1
+	rcsr	r1, IP
+	sw	(gp+_ip-_registers), r1
+	rcsr	r1, CC
+	sw	(gp+_cc-_registers), r1
+	rcsr	r1, CFG
+	sw	(gp+_cfg-_registers), r1
+
+	/* Prep R0 for normal work */
+	xor	r0, r0, r0
+	ret
+
+/* Restore gp registers */
+restore_gp:
+	/* Write CSRs */
+	lw	r1, (gp + _eba-_registers)
+	wcsr	EBA, r1
+	lw	r1, (gp + _deba-_registers)
+	wcsr	DEBA, r1
+	lw	r1, (gp + _ie-_registers)
+	wcsr	IE, r1
+	lw	r1, (gp + _im-_registers)
+	wcsr	IM, r1
+	lw	r1, (gp + _dc-_registers)
+	wcsr	DC, r1
+	lw	r1, (gp + _bp0-_registers)
+	wcsr	BP0, r1
+	lw	r1, (gp + _bp1-_registers)
+	wcsr	BP1, r1
+	lw	r1, (gp + _bp2-_registers)
+	wcsr	BP2, r1
+	lw	r1, (gp + _bp3-_registers)
+	wcsr	BP3, r1
+	lw	r1, (gp + _wp0-_registers)
+	wcsr	WP0, r1
+	lw	r1, (gp + _wp1-_registers)
+	wcsr	WP1, r1
+	lw	r1, (gp + _wp2-_registers)
+	wcsr	WP2, r1
+	lw	r1, (gp + _wp3-_registers)
+	wcsr	WP3, r1
+
+	/* Write registers */
+	lw	r1,  (gp+_r1 -_registers)
+	lw	r2,  (gp+_r2 -_registers)
+	lw	r3,  (gp+_r3 -_registers)
+	lw	r4,  (gp+_r4 -_registers)
+	lw	r5,  (gp+_r5 -_registers)
+	lw	r6,  (gp+_r6 -_registers)
+	lw	r7,  (gp+_r7 -_registers)
+	lw	r8,  (gp+_r8 -_registers)
+	lw	r9,  (gp+_r9 -_registers)
+	lw	r10, (gp+_r10-_registers)
+	lw	r11, (gp+_r11-_registers)
+	lw	r12, (gp+_r12-_registers)
+	lw	r13, (gp+_r13-_registers)
+	lw	r14, (gp+_r14-_registers)
+	lw	r15, (gp+_r15-_registers)
+	lw	r16, (gp+_r16-_registers)
+	lw	r17, (gp+_r17-_registers)
+	lw	r18, (gp+_r18-_registers)
+	lw	r19, (gp+_r19-_registers)
+	lw	r20, (gp+_r20-_registers)
+	lw	r21, (gp+_r21-_registers)
+	lw	r22, (gp+_r22-_registers)
+	lw	r23, (gp+_r23-_registers)
+	lw	r24, (gp+_r24-_registers)
+	lw	r25, (gp+_r25-_registers)
+	/* Restore GP later */
+	lw	fp,  (gp+_fp -_registers)
+	/* Restore RA later */
+	lw	sp,  (gp+_sp -_registers)
+	lw	ea,  (gp+_ea -_registers)
+	lw	ba,  (gp+_ba -_registers)
+	ret
+
+jtag_get_byte:
+	rcsr	r2, JRX
+	andi	r1, r2, 0x100
+	be	r1, r0, jtag_get_byte
+	wcsr	JRX, r0
+	andi	r1, r2, 0xff
+	ret
+
+jtag_get_word:
+	ori	r27, ra, 0
+	calli	jtag_get_byte
+	sb	(gp+_scratch-_registers+0), r1
+	calli	jtag_get_byte
+	sb	(gp+_scratch-_registers+1), r1
+	calli	jtag_get_byte
+	sb	(gp+_scratch-_registers+2), r1
+	calli	jtag_get_byte
+	sb	(gp+_scratch-_registers+3), r1
+	lw	r1, (gp+_scratch-_registers)
+	ori	ra, r27, 0
+	ret
+
+jtag_put_byte:
+	rcsr	r2, JTX
+	bne	r2, r0, jtag_put_byte
+	andi	r2, r1, 0xff
+	wcsr	JTX, r2
+	ret
+
+jtag_put_word:
+	ori	r27, ra, 0
+	sw	(gp+_scratch-_registers), r1
+	lbu	r1, (gp+_scratch-_registers+0)
+	calli	jtag_put_byte
+	lbu	r1, (gp+_scratch-_registers+1)
+	calli	jtag_put_byte
+	lbu	r1, (gp+_scratch-_registers+2)
+	calli	jtag_put_byte
+	lbu	r1, (gp+_scratch-_registers+3)
+	calli	jtag_put_byte
+	ori	ra, r27, 0
+	ret
+
+handle_debug_trap:
+	ori	r28, ra, 0
+
+	/* Report the debug ROM version */
+	mvi	r1, 0x80 + 'B'
+	calli	jtag_put_byte
+
+_get_command:
+	/* Input: [Wxxxxxxx] 
+         *   W=0, x=0:  quit debug trap
+         *   W=1, x=0:  report register dump location
+         *   W=0, x>0:  read 'x' bytes
+         *   W=1, x>0:  write 'x' bytes
+         */
+	calli	jtag_get_byte
+	be	r1, r0, _done_debug_trap
+
+	/* Setup args: r10=write, r11=base, r12=length */
+	andi	r10, r1, 0x80
+	andi	r12, r1, 0x7f
+	be	r12, r0, _read_registers
+
+	/* Load memory access address */
+	calli	jtag_get_word
+	mv	r11, r1
+	
+	/* Either read or write */
+	bne	r10, r0, _read_mem
+
+_write_mem:
+	be	r12, r0, _write_end
+	calli	jtag_get_byte
+	sb	(r11+0), r1
+	addi	r11, r11, 1
+	addi	r12, r12, -1
+	bi	_write_mem
+_write_end:
+	bi	_get_command
+
+_read_mem:
+	be	r12, r0, _read_end
+	lbu	r1, (r11+0)
+	calli	jtag_put_byte
+	addi	r11, r11, 1
+	addi	r12, r12, -1
+	bi	_read_mem
+_read_end:
+	bi	_get_command
+
+_read_registers:
+	/* Report the offset of the registers */
+	mv	r1, gp
+	calli	jtag_put_word
+	bi	_get_command
+
+_done_debug_trap:
+	wcsr	DCC, r0
+	wcsr	ICC, r0
+	nop
+	nop
+	nop
+	nop
+	ori	ra, r28, 0
+	ret
+
+_registers:
+_r0:	/* Never used */
+	.space 4
+_r1:
+	.space 4
+_r2:
+	.space 4
+_r3:
+	.space 4
+_r4:
+	.space 4
+_r5:
+	.space 4
+_r6:
+	.space 4
+_r7:
+	.space 4
+_r8:
+	.space 4
+_r9:
+	.space 4
+_r10:
+	.space 4
+_r11:
+	.space 4
+_r12:
+	.space 4
+_r13:
+	.space 4
+_r14:
+	.space 4
+_r15:
+	.space 4
+_r16:
+	.space 4
+_r17:
+	.space 4
+_r18:
+	.space 4
+_r19:
+	.space 4
+_r20:
+	.space 4
+_r21:
+	.space 4
+_r22:
+	.space 4
+_r23:
+	.space 4
+_r24:
+	.space 4
+_r25:
+	.space 4
+_gp:
+	.space 4
+_fp:
+	.space 4
+_sp:
+	.space 4
+_ra:
+	.space 4
+_ea:
+	.space 4
+_ba:
+	.space 4
+
+/* Never used -- but matches gdb layout (filled in by lm32-rom.cpp) */
+_pc:
+	.space 4
+/* What exception happened *32 */
+_eid:
+	.space 4
+
+/* CSRs */
+_eba:	/* RW */
+	.space 4
+_deba:	/* RW */
+	.space 4
+_ie:	/* RW */
+	.space 4
+_im:	/* RW */
+	.space 4
+_ip:	/* R */
+	.space 4
+/* ICC and DCC flushed on continue */
+_cc:	/* R */
+	.space 4
+_cfg:	/* R */
+	.space 4
+_dc:	/* W */
+	.space 4
+/* JTX and JRX used by ROM */
+_bp0:	/* W */
+	.space 4
+_bp1:	/* W */
+	.space 4
+_bp2:	/* W */
+	.space 4
+_bp3:	/* W */
+	.space 4
+_wp0:	/* W */
+	.space 4
+_wp1:	/* W */
+	.space 4
+_wp2:	/* W */
+	.space 4
+_wp3:	/* W */
+	.space 4
+
+/* used for assembling a word from bytes */
+_scratch:
+	.space 4
diff --git a/rt/target/lm32/irq.c b/rt/target/lm32/irq.c
new file mode 100644
index 0000000000000000000000000000000000000000..d1ac86b53b5d6f585b8fc1a2fa8e6a332ba6462d
--- /dev/null
+++ b/rt/target/lm32/irq.c
@@ -0,0 +1,39 @@
+#include "irq.h"
+
+void disable_irq()
+{
+    unsigned int ie, im;
+    unsigned int Mask = ~1;
+
+    /* disable peripheral interrupts in case they were enabled */
+    asm volatile ("rcsr %0,ie":"=r"(ie));
+    ie &= (~0x1);
+    asm volatile ("wcsr ie, %0"::"r"(ie));
+
+    /* disable mask-bit in im */
+    asm volatile ("rcsr %0, im":"=r"(im));
+    im &= Mask;
+    asm volatile ("wcsr im, %0"::"r"(im));
+
+}
+
+
+void enable_irq()
+{
+    unsigned int ie, im;
+    unsigned int Mask = 1;
+
+
+    /* disable peripheral interrupts in-case they were enabled*/
+    asm volatile ("rcsr %0,ie":"=r"(ie));
+    ie &= (~0x1);
+    asm volatile ("wcsr ie, %0"::"r"(ie));
+
+    /* enable mask-bit in im */
+    asm volatile ("rcsr %0, im":"=r"(im));
+    im |= Mask;
+    asm volatile ("wcsr im, %0"::"r"(im));
+
+    ie |= 0x1;
+    asm volatile ("wcsr ie, %0"::"r"(ie));
+}
diff --git a/rt/target/lm32/ram.ld b/rt/target/lm32/ram.ld
new file mode 100644
index 0000000000000000000000000000000000000000..669d85a1bd1014017b5f1a439673750e7c738d1f
--- /dev/null
+++ b/rt/target/lm32/ram.ld
@@ -0,0 +1,149 @@
+/*
+ * Simulator Link script for Lattice Mico32.
+ * Contributed by Jon Beniston <jon@beniston.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+OUTPUT_FORMAT("elf32-lm32")
+ENTRY(_start)
+/*INPUT() */
+GROUP(-lgcc -lc)
+
+MEMORY
+{
+    ram : ORIGIN = 0x00000000, LENGTH = 0x4000
+}
+
+SECTIONS
+{
+
+  .boot : { *(.boot) } > ram
+   
+  /* Code */
+  .text           :
+  {
+    . = ALIGN(4);
+    _ftext = .;
+    _ftext_rom = LOADADDR(.text);
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    *(.gnu.warning)
+    KEEP (*(.init))
+    KEEP (*(.fini))
+    /* Constructors and destructors */
+    KEEP (*crtbegin*.o(.ctors))
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+    KEEP (*crtbegin*.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+    KEEP (*(.jcr))
+    _etext = .;
+  } > ram =0 
+
+  /* Exception handlers */
+  .eh_frame_hdr : { *(.eh_frame_hdr) } > ram
+  .eh_frame : { KEEP (*(.eh_frame)) } > ram
+  .gcc_except_table : { *(.gcc_except_table) *(.gcc_except_table.*) } > ram
+    
+  /* Read-only data */
+  .rodata         : 
+  { 
+    . = ALIGN(4);
+    _frodata = .;
+    _frodata_rom = LOADADDR(.rodata);
+    *(.rodata .rodata.* .gnu.linkonce.r.*) 
+    *(.rodata1)
+    _erodata = .;
+  } > ram
+        
+  /* Data */
+  .data           : 
+  {
+    . = ALIGN(4);
+    _fdata = .;
+    _fdata_rom = LOADADDR(.data);
+    *(.data .data.* .gnu.linkonce.d.*)
+    *(.data1)
+    SORT(CONSTRUCTORS)
+    _gp = ALIGN(16) + 0x7ff0;
+    *(.sdata .sdata.* .gnu.linkonce.s.*)
+    _edata = .;
+  } > ram 
+  
+  /* BSS */
+  .bss           :
+  {
+    . = ALIGN(4);
+    _fbss = .;
+    *(.dynsbss)
+    *(.sbss .sbss.* .gnu.linkonce.sb.*)
+    *(.scommon)
+    *(.dynbss)
+    *(.bss .bss.* .gnu.linkonce.b.*)
+    *(COMMON)
+    . = ALIGN(4);
+    _ebss = .;
+    _end = .;
+    PROVIDE (end = .);
+  } > ram
+  
+  /* First location in stack is highest address in RAM */
+  PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
+  
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  
+  /* 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) }
+}