Squashed 'third_party/pico-sdk/' content from commit 2062372d2

Change-Id: Ic20f199d3ed0ea8d3a6a1bbf513f875ec7500cc6
git-subtree-dir: third_party/pico-sdk
git-subtree-split: 2062372d203b372849d573f252cf7c6dc2800c0a
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/src/host/CMakeLists.txt b/src/host/CMakeLists.txt
new file mode 100644
index 0000000..9edcd7b
--- /dev/null
+++ b/src/host/CMakeLists.txt
@@ -0,0 +1,37 @@
+pico_add_subdirectory(hardware_divider)
+pico_add_subdirectory(hardware_gpio)
+pico_add_subdirectory(hardware_sync)
+pico_add_subdirectory(hardware_timer)
+pico_add_subdirectory(hardware_uart)
+pico_add_subdirectory(pico_bit_ops)
+pico_add_subdirectory(pico_divider)
+pico_add_subdirectory(pico_multicore)
+pico_add_subdirectory(pico_platform)
+pico_add_subdirectory(pico_printf)
+pico_add_subdirectory(pico_stdio)
+pico_add_subdirectory(pico_stdlib)
+
+pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
+
+macro(pico_set_float_implementation TARGET IMPL)
+    # ignore
+endmacro()
+
+macro(pico_set_double_implementation TARGET IMPL)
+    # ignore
+endmacro()
+
+macro(pico_set_binary_type TARGET IMPL)
+    # ignore
+endmacro()
+
+macro(pico_set_boot_stage2 TARGET IMPL)
+    # ignore
+endmacro()
+
+set(PICO_HOST_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "")
+function(pico_define_boot_stage2 NAME)
+    add_executable(${NAME} ${PICO_HOST_DIR}/boot_stage2.c)
+endfunction()
+
+pico_promote_common_scope_vars()
\ No newline at end of file
diff --git a/src/host/README.md b/src/host/README.md
new file mode 100644
index 0000000..c6d8962
--- /dev/null
+++ b/src/host/README.md
@@ -0,0 +1,14 @@
+This is a basic set of replacement library implementations sufficient to get simple applications
+running on your computer (Raspberry Pi OS, Linux, macOS or Windows using Cygwin or Windows Subsystem for Linux).
+It is selected by `PICO_PLATFORM=host` in your CMake build
+
+This can be extremely useful for testing and debugging higher level application code, or porting code which is not yet small enough 
+to run on the RP2040 device itself.
+
+This base level host library provides a minimal environment to compile programs, but is likely sufficient for programs
+that don't access hardware directly.
+
+It is possible however to inject additional SDK library implementations/simulations to provide 
+more complete functionality. For an example of this see the [pico-host-sdl](https://github.com/raspberrypi/pico-host-sdl) 
+which uses the SDL2 library to add additional library support for pico_multicore, timers/alarms in pico-time and 
+pico-audio/pico-scanvideo from [pico-extras](https://github.com/raspberrypi/pico-extras)
diff --git a/src/host/boot_stage2.c b/src/host/boot_stage2.c
new file mode 100644
index 0000000..52794b1
--- /dev/null
+++ b/src/host/boot_stage2.c
@@ -0,0 +1,3 @@
+void main() {
+
+}
\ No newline at end of file
diff --git a/src/host/hardware_divider/CMakeLists.txt b/src/host/hardware_divider/CMakeLists.txt
new file mode 100644
index 0000000..a6156c0
--- /dev/null
+++ b/src/host/hardware_divider/CMakeLists.txt
@@ -0,0 +1 @@
+pico_simple_hardware_target(divider)
\ No newline at end of file
diff --git a/src/host/hardware_divider/divider.c b/src/host/hardware_divider/divider.c
new file mode 100644
index 0000000..a133179
--- /dev/null
+++ b/src/host/hardware_divider/divider.c
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "hardware/divider.h"
+
+__thread uint64_t hw_divider_result_threadlocal;
diff --git a/src/host/hardware_divider/include/hardware/divider.h b/src/host/hardware_divider/include/hardware/divider.h
new file mode 100644
index 0000000..c126688
--- /dev/null
+++ b/src/host/hardware_divider/include/hardware/divider.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _HARDWARE_DIVIDER_H
+#define _HARDWARE_DIVIDER_H
+
+#include "pico/types.h"
+
+typedef uint64_t divmod_result_t;
+
+static inline int __sign_of(int32_t v) {
+    return v > 0 ? 1 : (v < 0 ? -1 : 0);
+}
+
+// divides unsigned values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
+static inline uint64_t hw_divider_divmod_u32(uint32_t a, uint32_t b) {
+    if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-1); // todo check this
+    return (((uint64_t)(a%b))<<32u) | (a/b);
+}
+
+// divides signed values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
+static inline uint64_t hw_divider_divmod_s32(int32_t a, int32_t b) {
+    if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-__sign_of(a));
+    return (((uint64_t)(a%b))<<32u) | (uint32_t)(a/b);
+}
+
+extern __thread divmod_result_t hw_divider_result_threadlocal;
+
+static inline void hw_divider_divmod_s32_start(int32_t a, int32_t b) {
+    hw_divider_result_threadlocal = hw_divider_divmod_s32(a, b);
+}
+
+static inline void hw_divider_divmod_u32_start(uint32_t a, uint32_t b) {
+    hw_divider_result_threadlocal = hw_divider_divmod_u32(a, b);
+}
+
+static inline divmod_result_t hw_divider_result_wait() {
+    return hw_divider_result_threadlocal;
+}
+
+static inline uint64_t hw_divider_result_nowait() {
+    return hw_divider_result_threadlocal;
+}
+
+inline static uint32_t to_quotient_u32(unsigned long long int r) {
+    return (uint32_t) r;
+}
+
+inline static int32_t to_quotient_s32(unsigned long long int r) {
+    return (int32_t)(uint32_t)r;
+}
+
+inline static uint32_t to_remainder_u32(unsigned long long int r) {
+    return (uint32_t)(r >> 32u);
+}
+
+inline static int32_t to_remainder_s32(unsigned long long int r) {
+    return (int32_t)(r >> 32u);
+}
+
+static inline uint32_t hw_divider_u32_quotient_wait() {
+    return to_quotient_u32(hw_divider_result_wait());
+}
+
+static inline uint32_t hw_divider_u32_remainder_wait() {
+    return to_remainder_u32(hw_divider_result_wait());
+}
+
+static inline int32_t hw_divider_s32_quotient_wait() {
+    return to_quotient_s32(hw_divider_result_wait());
+}
+
+static inline int32_t hw_divider_s32_remainder_wait() {
+    return to_remainder_s32(hw_divider_result_wait());
+}
+
+static inline uint32_t hw_divider_u32_quotient(uint32_t a, uint32_t b) {
+    return b ? (a / b) : (uint32_t)(-1);
+}
+
+static inline uint32_t hw_divider_u32_remainder(uint32_t a, uint32_t b) {
+    return b ? (a % b) : a;
+}
+
+static inline int32_t hw_divider_s32_quotient(int32_t a, int32_t b) {
+    return b ? (a / b) : -__sign_of(a);
+}
+
+static inline int32_t hw_divider_s32_remainder(int32_t a, int32_t b) {
+    return b ? (a % b) : a;
+}
+
+static inline uint32_t hw_divider_u32_quotient_inlined(uint32_t a, uint32_t b) {
+    return hw_divider_u32_quotient(a,b);
+}
+
+static inline uint32_t hw_divider_u32_remainder_inlined(uint32_t a, uint32_t b) {
+    return hw_divider_u32_remainder(a,b);
+}
+
+static inline int32_t hw_divider_s32_quotient_inlined(int32_t a, int32_t b) {
+    return hw_divider_s32_quotient(a,b);
+}
+
+static inline int32_t hw_divider_s32_remainder_inlined(int32_t a, int32_t b) {
+    return hw_divider_s32_remainder(a,b);
+}
+
+typedef uint64_t hw_divider_state_t;
+
+static inline void hw_divider_save_state(hw_divider_state_t *dest) {
+    *dest = hw_divider_result_threadlocal;
+}
+
+static inline void hw_divider_restore_state(hw_divider_state_t *src) {
+    hw_divider_result_threadlocal = *src;
+}
+
+#endif // _HARDWARE_DIVIDER_H
diff --git a/src/host/hardware_gpio/CMakeLists.txt b/src/host/hardware_gpio/CMakeLists.txt
new file mode 100644
index 0000000..1bfb078
--- /dev/null
+++ b/src/host/hardware_gpio/CMakeLists.txt
@@ -0,0 +1 @@
+pico_simple_hardware_target(gpio)
\ No newline at end of file
diff --git a/src/host/hardware_gpio/gpio.c b/src/host/hardware_gpio/gpio.c
new file mode 100644
index 0000000..1cbcbed
--- /dev/null
+++ b/src/host/hardware_gpio/gpio.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "hardware/gpio.h"
+
+// todo weak or replace? probably weak
+void gpio_set_function(uint gpio, enum gpio_function fn) {
+
+}
+
+void gpio_pull_up(uint gpio) {
+
+}
+
+void gpio_pull_down(uint gpio) {
+
+}
+
+void gpio_disable_pulls(uint gpio) {
+
+}
+
+void gpio_set_pulls(uint gpio, bool up, bool down) {
+
+}
+
+void gpio_set_irqover(uint gpio, uint value) {
+
+}
+
+void gpio_set_outover(uint gpio, uint value) {
+
+}
+
+void gpio_set_inover(uint gpio, uint value) {
+
+}
+
+void gpio_set_oeover(uint gpio, uint value) {
+
+}
+
+void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled){
+
+}
+
+bool gpio_is_input_hysteresis_enabled(uint gpio){
+    return true;
+}
+
+void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew){
+
+}
+
+enum gpio_slew_rate gpio_get_slew_rate(uint gpio){
+    return GPIO_SLEW_RATE_FAST;
+}
+
+void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive){
+
+}
+
+enum gpio_drive_strength gpio_get_drive_strength(uint gpio){
+    return GPIO_DRIVE_STRENGTH_4MA;
+}
+
+
+void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enable) {
+
+}
+
+void gpio_acknowledge_irq(uint gpio, uint32_t events) {
+
+}
+
+void gpio_init(uint gpio) {
+
+}
+
+PICO_WEAK_FUNCTION_DEF(gpio_get)
+
+bool PICO_WEAK_FUNCTION_IMPL_NAME(gpio_get)(uint gpio) {
+    return 0;
+}
+
+uint32_t gpio_get_all() {
+    return 0;
+}
+
+void gpio_set_mask(uint32_t mask) {
+
+}
+
+void gpio_clr_mask(uint32_t mask) {
+
+}
+
+void gpio_xor_mask(uint32_t mask) {
+
+}
+
+void gpio_put_masked(uint32_t mask, uint32_t value) {
+
+}
+
+void gpio_put_all(uint32_t value) {
+
+}
+
+void gpio_put(uint gpio, int value) {
+
+}
+
+void gpio_set_dir_out_masked(uint32_t mask) {
+
+}
+
+void gpio_set_dir_in_masked(uint32_t mask) {
+
+}
+
+void gpio_set_dir_masked(uint32_t mask, uint32_t value) {
+
+}
+
+void gpio_set_dir_all_bits(uint32_t value) {
+
+}
+
+void gpio_set_dir(uint gpio, bool out) {
+
+}
+
+void gpio_debug_pins_init() {
+
+}
+
+void gpio_set_input_enabled(uint gpio, bool enable) {
+
+}
+
+void gpio_init_mask(uint gpio_mask) {
+
+}
diff --git a/src/host/hardware_gpio/include/hardware/gpio.h b/src/host/hardware_gpio/include/hardware/gpio.h
new file mode 100644
index 0000000..b2b83a1
--- /dev/null
+++ b/src/host/hardware_gpio/include/hardware/gpio.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _HARDWARE_GPIO_H_
+#define _HARDWARE_GPIO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pico.h"
+
+enum gpio_function {
+    GPIO_FUNC_XIP = 0,
+    GPIO_FUNC_SPI = 1,
+    GPIO_FUNC_UART = 2,
+    GPIO_FUNC_I2C = 3,
+    GPIO_FUNC_PWM = 4,
+    GPIO_FUNC_SIO = 5,
+    GPIO_FUNC_PIO0 = 6,
+    GPIO_FUNC_PIO1 = 7,
+    GPIO_FUNC_GPCK = 8,
+    GPIO_FUNC_USB = 9,
+    GPIO_FUNC_NULL = 0xf,
+};
+
+enum gpio_slew_rate {
+    GPIO_SLEW_RATE_SLOW = 0,  ///< Slew rate limiting enabled
+    GPIO_SLEW_RATE_FAST = 1   ///< Slew rate limiting disabled
+};
+
+enum gpio_drive_strength {
+    GPIO_DRIVE_STRENGTH_2MA = 0, ///< 2 mA nominal drive strength
+    GPIO_DRIVE_STRENGTH_4MA = 1, ///< 4 mA nominal drive strength
+    GPIO_DRIVE_STRENGTH_8MA = 2, ///< 8 mA nominal drive strength
+    GPIO_DRIVE_STRENGTH_12MA = 3 ///< 12 mA nominal drive strength
+};
+
+#define GPIO_OUT 1
+#define GPIO_IN 0
+
+#define NUM_BANK0_GPIOS 30
+
+// ----------------------------------------------------------------------------
+// Pad Controls + IO Muxing
+// ----------------------------------------------------------------------------
+// Declarations for gpio.c
+
+void gpio_set_function(uint gpio, enum gpio_function fn);
+
+enum gpio_function gpio_get_function(uint gpio);
+
+void gpio_pull_up(uint gpio);
+
+void gpio_pull_down(uint gpio);
+
+void gpio_disable_pulls(uint gpio);
+
+void gpio_set_pulls(uint gpio, bool up, bool down);
+
+void gpio_set_irqover(uint gpio, uint value);
+
+void gpio_set_outover(uint gpio, uint value);
+
+void gpio_set_inover(uint gpio, uint value);
+
+void gpio_set_oeover(uint gpio, uint value);
+
+void gpio_set_input_enabled(uint gpio, bool enable);
+
+void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled);
+
+bool gpio_is_input_hysteresis_enabled(uint gpio);
+
+void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew);
+
+enum gpio_slew_rate gpio_get_slew_rate(uint gpio);
+
+void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive);
+
+enum gpio_drive_strength gpio_get_drive_strength(uint gpio);
+
+// Configure a GPIO for direct input/output from software
+void gpio_init(uint gpio);
+
+void gpio_init_mask(uint gpio_mask);
+
+// ----------------------------------------------------------------------------
+// Input
+// ----------------------------------------------------------------------------
+
+// Get the value of a single GPIO
+bool gpio_get(uint gpio);
+
+// Get raw value of all
+uint32_t gpio_get_all();
+
+// ----------------------------------------------------------------------------
+// Output
+// ----------------------------------------------------------------------------
+
+// Drive high every GPIO appearing in mask
+void gpio_set_mask(uint32_t mask);
+
+void gpio_clr_mask(uint32_t mask);
+
+// Toggle every GPIO appearing in mask
+void gpio_xor_mask(uint32_t mask);
+
+
+// For each 1 bit in "mask", drive that pin to the value given by
+// corresponding bit in "value", leaving other pins unchanged.
+// Since this uses the TOGL alias, it is concurrency-safe with e.g. an IRQ
+// bashing different pins from the same core.
+void gpio_put_masked(uint32_t mask, uint32_t value);
+
+// Drive all pins simultaneously
+void gpio_put_all(uint32_t value);
+
+
+// Drive a single GPIO high/low
+void gpio_put(uint gpio, int value);
+
+// ----------------------------------------------------------------------------
+// Direction
+// ----------------------------------------------------------------------------
+
+// Switch all GPIOs in "mask" to output
+void gpio_set_dir_out_masked(uint32_t mask);
+
+// Switch all GPIOs in "mask" to input
+void gpio_set_dir_in_masked(uint32_t mask);
+
+// For each 1 bit in "mask", switch that pin to the direction given by
+// corresponding bit in "value", leaving other pins unchanged.
+// E.g. gpio_set_dir_masked(0x3, 0x2); -> set pin 0 to input, pin 1 to output,
+// simultaneously.
+void gpio_set_dir_masked(uint32_t mask, uint32_t value);
+
+// Set direction of all pins simultaneously.
+// For each bit in value,
+// 1 = out
+// 0 = in
+void gpio_set_dir_all_bits(uint32_t value);
+
+// Set a single GPIO to input/output.
+// true = out
+// 0 = in
+void gpio_set_dir(uint gpio, bool out);
+
+// debugging
+#ifndef PICO_DEBUG_PIN_BASE
+#define PICO_DEBUG_PIN_BASE 19u
+#endif
+
+// note these two macros may only be used once per compilation unit
+#define CU_REGISTER_DEBUG_PINS(p, ...)
+#define CU_SELECT_DEBUG_PINS(x)
+#define DEBUG_PINS_ENABLED(p) false
+
+#define DEBUG_PINS_SET(p, v) ((void)0)
+#define DEBUG_PINS_CLR(p, v) ((void)0)
+#define DEBUG_PINS_XOR(p, v) ((void)0)
+
+void gpio_debug_pins_init();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/host/hardware_sync/CMakeLists.txt b/src/host/hardware_sync/CMakeLists.txt
new file mode 100644
index 0000000..4f69177
--- /dev/null
+++ b/src/host/hardware_sync/CMakeLists.txt
@@ -0,0 +1,12 @@
+pico_simple_hardware_headers_target(sync)
+
+if (NOT TARGET hardware_sync)
+    add_library(hardware_sync INTERFACE)
+
+    target_sources(hardware_sync INTERFACE
+        ${CMAKE_CURRENT_LIST_DIR}/sync_core0_only.c
+    )
+
+    target_link_libraries(hardware_sync INTERFACE hardware_sync_headers pico_platform)
+endif()
+
diff --git a/src/host/hardware_sync/include/hardware/sync.h b/src/host/hardware_sync/include/hardware/sync.h
new file mode 100644
index 0000000..a27ea01
--- /dev/null
+++ b/src/host/hardware_sync/include/hardware/sync.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _HARDWARE_SYNC_H
+#define _HARDWARE_SYNC_H
+
+#include "pico.h"
+
+#ifndef __cplusplus
+
+#if (__STDC_VERSION__ >= 201112L)
+#include <stdatomic.h>
+#else
+enum {
+    memory_order_acquire, memory_order_release
+};
+static inline void atomic_thread_fence(uint x) {}
+#endif
+
+#else
+
+#include <atomic>
+
+#endif
+
+#ifndef PICO_SPINLOCK_ID_TIMER
+#define PICO_SPINLOCK_ID_TIMER 10
+#endif
+
+#ifndef PICO_SPINLOCK_ID_STRIPED_FIRST
+#define PICO_SPINLOCK_ID_STRIPED_FIRST 16
+#endif
+
+#ifndef PICO_SPINLOCK_ID_STRIPED_LAST
+#define PICO_SPINLOCK_ID_STRIPED_LAST 23
+#endif
+
+typedef struct _spin_lock_t spin_lock_t;
+
+inline static void __mem_fence_acquire() {
+#ifndef __cplusplus
+    atomic_thread_fence(memory_order_acquire);
+#else
+    std::atomic_thread_fence(std::memory_order_acquire);
+#endif
+}
+
+inline static void __mem_fence_release() {
+#ifndef __cplusplus
+    atomic_thread_fence(memory_order_release);
+#else
+    std::atomic_thread_fence(std::memory_order_release);
+#endif
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __sev();
+
+void __wev();
+
+void __wfi();
+
+void __wfe();
+
+uint32_t save_and_disable_interrupts();
+
+void restore_interrupts(uint32_t status);
+
+uint spin_lock_get_num(spin_lock_t *lock);
+
+spin_lock_t *spin_lock_instance(uint lock_num);
+
+void spin_lock_unsafe_blocking(spin_lock_t *lock);
+
+void spin_unlock_unsafe(spin_lock_t *lock);
+
+uint32_t spin_lock_blocking(spin_lock_t *lock);
+
+bool is_spin_locked(const spin_lock_t *lock);
+
+void spin_unlock(spin_lock_t *lock, uint32_t saved_irq);
+
+uint get_core_num();
+
+spin_lock_t *spin_lock_init(uint lock_num);
+
+void clear_spin_locks(void);
+
+uint next_striped_spin_lock_num();
+
+void spin_lock_claim(uint lock_num);
+void spin_lock_claim_mask(uint32_t lock_num_mask);
+void spin_lock_unclaim(uint lock_num);
+int spin_lock_claim_unused(bool required);
+uint spin_lock_num(spin_lock_t *lock);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/host/hardware_sync/sync_core0_only.c b/src/host/hardware_sync/sync_core0_only.c
new file mode 100644
index 0000000..878eba6
--- /dev/null
+++ b/src/host/hardware_sync/sync_core0_only.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "hardware/sync.h"
+#include "hardware/platform_defs.h"
+
+// This is a dummy implementation that is single threaded
+
+static struct _spin_lock_t {
+    bool locked;
+} _spinlocks[NUM_SPIN_LOCKS];
+
+PICO_WEAK_FUNCTION_DEF(save_and_disable_interrupts)
+
+//static uint8_t striped_spin_lock_num;
+
+uint32_t PICO_WEAK_FUNCTION_IMPL_NAME(save_and_disable_interrupts)() {
+    return 0;
+}
+
+PICO_WEAK_FUNCTION_DEF(restore_interrupts)
+
+void PICO_WEAK_FUNCTION_IMPL_NAME(restore_interrupts)(uint32_t status) {
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_instance)
+
+spin_lock_t *PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_instance)(uint lock_num) {
+    assert(lock_num < NUM_SPIN_LOCKS);
+    return &_spinlocks[lock_num];
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_get_num)
+
+uint PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_get_num)(spin_lock_t *lock) {
+    return lock - _spinlocks;
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_init)
+
+spin_lock_t *PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_init)(uint lock_num) {
+    spin_lock_t *lock = spin_lock_instance(lock_num);
+    spin_unlock_unsafe(lock);
+    return lock;
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_unsafe_blocking)
+
+void PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_unsafe_blocking)(spin_lock_t *lock) {
+    lock->locked = true;
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_blocking)
+
+uint32_t PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_blocking)(spin_lock_t *lock) {
+    spin_lock_unsafe_blocking(lock);
+    return 1; // todo wrong value
+}
+
+PICO_WEAK_FUNCTION_DEF(is_spin_locked)
+
+bool PICO_WEAK_FUNCTION_IMPL_NAME(is_spin_locked)(const spin_lock_t *lock) {
+    return lock->locked;
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_unlock_unsafe)
+
+void PICO_WEAK_FUNCTION_IMPL_NAME(spin_unlock_unsafe)(spin_lock_t *lock) {
+    lock->locked = false;
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_unlock)
+
+void PICO_WEAK_FUNCTION_IMPL_NAME(spin_unlock)(spin_lock_t *lock, uint32_t saved_irq) {
+    spin_unlock_unsafe(lock);
+}
+
+PICO_WEAK_FUNCTION_DEF(__sev)
+
+volatile bool event_fired;
+
+void PICO_WEAK_FUNCTION_IMPL_NAME(__sev)() {
+    event_fired = true;
+}
+
+PICO_WEAK_FUNCTION_DEF(__wfi)
+
+void PICO_WEAK_FUNCTION_IMPL_NAME(__wfi)() {
+    panic("Can't wait on irq for host core0 only implementation");
+}
+
+PICO_WEAK_FUNCTION_DEF(__wfe)
+
+void PICO_WEAK_FUNCTION_IMPL_NAME(__wfe)() {
+    while (!event_fired) tight_loop_contents();
+}
+
+PICO_WEAK_FUNCTION_DEF(get_core_num)
+
+uint PICO_WEAK_FUNCTION_IMPL_NAME(get_core_num)() {
+    return 0;
+}
+
+PICO_WEAK_FUNCTION_DEF(clear_spin_locks)
+
+void PICO_WEAK_FUNCTION_IMPL_NAME(clear_spin_locks)(void) {
+    for (uint i = 0; i < NUM_SPIN_LOCKS; i++) {
+        spin_unlock_unsafe(spin_lock_instance(i));
+    }
+}
+
+PICO_WEAK_FUNCTION_DEF(next_striped_spin_lock_num)
+uint PICO_WEAK_FUNCTION_IMPL_NAME(next_striped_spin_lock_num)() {
+    return 0;
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_claim)
+void PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_claim)(uint lock_num) {
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_claim_mask)
+void PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_claim_mask)(uint32_t mask) {
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_unclaim)
+void PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_unclaim)(uint lock_num) {
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_claim_unused)
+int PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_claim_unused)(bool required) {
+    return 0;
+}
+
+PICO_WEAK_FUNCTION_DEF(spin_lock_num)
+uint PICO_WEAK_FUNCTION_IMPL_NAME(spin_lock_num)(spin_lock_t *lock) {
+    return 0;
+}
\ No newline at end of file
diff --git a/src/host/hardware_timer/CMakeLists.txt b/src/host/hardware_timer/CMakeLists.txt
new file mode 100644
index 0000000..ba00444
--- /dev/null
+++ b/src/host/hardware_timer/CMakeLists.txt
@@ -0,0 +1,16 @@
+pico_simple_hardware_target(timer)
+
+target_compile_definitions(hardware_timer INTERFACE
+    PICO_HARDWARE_TIMER_RESOLUTION_US=1000 # to loosen tests a little
+)
+
+if (NOT DEFINED PICO_TIME_NO_ALARM_SUPPORT)
+    # we don't have alarm pools in the basic host support, though pico_host_sdl adds it
+    set(PICO_TIME_NO_ALARM_SUPPORT "1" CACHE INTERNAL "")
+endif()
+
+if (PICO_TIME_NO_ALARM_SUPPORT)
+    target_compile_definitions(hardware_timer INTERFACE
+            PICO_TIME_DEFAULT_ALARM_POOL_DISABLED=1
+    )
+endif()
\ No newline at end of file
diff --git a/src/host/hardware_timer/include/hardware/timer.h b/src/host/hardware_timer/include/hardware/timer.h
new file mode 100644
index 0000000..3ddf427
--- /dev/null
+++ b/src/host/hardware_timer/include/hardware/timer.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _HARDWARE_TIMER_H
+#define _HARDWARE_TIMER_H
+
+#include "pico.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef PARAM_ASSERTIONS_ENABLED_TIMER
+#define PARAM_ASSERTIONS_ENABLED_TIMER 0
+#endif
+
+static inline void check_hardware_alarm_num_param(uint alarm_num) {
+    invalid_params_if(TIMER, alarm_num >= NUM_TIMERS);
+}
+
+uint32_t time_us_32();
+uint64_t time_us_64();
+void busy_wait_us_32(uint32_t delay_us);
+void busy_wait_us(uint64_t delay_us);
+void busy_wait_until(absolute_time_t t);
+bool time_reached(absolute_time_t t);
+typedef void (*hardware_alarm_callback_t)(uint alarm_num);
+void hardware_alarm_claim(uint alarm_num);
+void hardware_alarm_unclaim(uint alarm_num);
+void hardware_alarm_set_callback(uint alarm_num, hardware_alarm_callback_t callback);
+bool hardware_alarm_set_target(uint alarm_num, absolute_time_t t);
+void hardware_alarm_cancel(uint alarm_num);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/host/hardware_timer/timer.c b/src/host/hardware_timer/timer.c
new file mode 100644
index 0000000..30f6a20
--- /dev/null
+++ b/src/host/hardware_timer/timer.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "hardware/timer.h"
+#if defined(__unix__) || defined(__APPLE__)
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+
+#endif
+
+// in our case not a busy wait
+PICO_WEAK_FUNCTION_DEF(busy_wait_us)
+void PICO_WEAK_FUNCTION_IMPL_NAME(busy_wait_us_32)(uint32_t delay_us) {
+#if defined(__unix__) || defined(__APPLE__)
+    usleep(delay_us);
+#else
+    assert(false);
+#endif
+}
+PICO_WEAK_FUNCTION_DEF(busy_wait_us)
+void PICO_WEAK_FUNCTION_IMPL_NAME(busy_wait_us)(uint64_t delay_us) {
+    absolute_time_t t;
+    update_us_since_boot(&t, time_us_64() + delay_us);
+    busy_wait_until(t);
+}
+
+// this may or may not wrap
+PICO_WEAK_FUNCTION_DEF(time_us_64)
+uint64_t PICO_WEAK_FUNCTION_IMPL_NAME(time_us_64)() {
+#if defined(__unix__) || defined(__APPLE__)
+//    struct timeval tv;
+//    gettimeofday(&tv, NULL);
+//    return tv.tv_sec * (uint64_t) 1000000 + tv.tv_usec;
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    return ts.tv_sec * (uint64_t) 1000000 + ts.tv_nsec / 1000;
+#else
+    panic_unsupported();
+#endif
+}
+
+PICO_WEAK_FUNCTION_DEF(timer_us_32)
+uint32_t PICO_WEAK_FUNCTION_IMPL_NAME(timer_us_32)() {
+    return (uint32_t) time_us_64();
+}
+
+PICO_WEAK_FUNCTION_DEF(time_reached)
+bool PICO_WEAK_FUNCTION_IMPL_NAME(time_reached)(absolute_time_t t) {
+    uint64_t target = to_us_since_boot(t);
+    return time_us_64() >= target;
+}
+
+PICO_WEAK_FUNCTION_DEF(busy_wait_until)
+void PICO_WEAK_FUNCTION_IMPL_NAME(busy_wait_until)(absolute_time_t target) {
+#if defined(__unix__)
+    struct timespec tspec;
+    tspec.tv_sec = to_us_since_boot(target) / 1000000;
+    tspec.tv_nsec = (to_us_since_boot(target) % 1000000) * 1000;
+    clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &tspec, NULL);
+#else
+    const int chunk = 1u<<30u;
+    uint64_t target_us = to_us_since_boot(target);
+    uint64_t time_us = time_us_64();
+    while ((int64_t)(target_us - time_us) >= chunk) {
+        busy_wait_us_32(chunk);
+        time_us = time_us_64();
+    }
+    if (target_us > time_us) {
+        busy_wait_us_32(target_us - time_us);
+    }
+#endif
+}
+
+static uint8_t claimed_alarms;
+
+void hardware_alarm_claim(uint alarm_num) {
+    assert(!(claimed_alarms & (1u << alarm_num)));
+    claimed_alarms |= 1u <<alarm_num;
+}
+
+void hardware_alarm_unclaim(uint alarm_num) {
+    assert(claimed_alarms & (1u << alarm_num));
+    claimed_alarms &= ~(1u <<alarm_num);
+}
+
+PICO_WEAK_FUNCTION_DEF(hardware_alarm_set_callback)
+void PICO_WEAK_FUNCTION_IMPL_NAME(hardware_alarm_set_callback)(uint alarm_num, hardware_alarm_callback_t callback) {
+    panic_unsupported();
+}
+
+PICO_WEAK_FUNCTION_DEF(hardware_alarm_set_target)
+bool PICO_WEAK_FUNCTION_IMPL_NAME(hardware_alarm_set_target)(uint alarm_num, absolute_time_t target) {
+    panic_unsupported();
+}
+
+PICO_WEAK_FUNCTION_DEF(hardware_alarm_cancel)
+void PICO_WEAK_FUNCTION_IMPL_NAME(hardware_alarm_cancel)(uint alarm_num) {
+    panic_unsupported();
+}
diff --git a/src/host/hardware_uart/CMakeLists.txt b/src/host/hardware_uart/CMakeLists.txt
new file mode 100644
index 0000000..9fe65d5
--- /dev/null
+++ b/src/host/hardware_uart/CMakeLists.txt
@@ -0,0 +1 @@
+pico_simple_hardware_target(uart)
\ No newline at end of file
diff --git a/src/host/hardware_uart/include/hardware/uart.h b/src/host/hardware_uart/include/hardware/uart.h
new file mode 100644
index 0000000..0c5e890
--- /dev/null
+++ b/src/host/hardware_uart/include/hardware/uart.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _HARDWARE_UART_H
+#define _HARDWARE_UART_H
+
+#include "pico.h"
+
+#ifndef PARAM_ASSERTIONS_ENABLED_UART
+#define PARAM_ASSERTIONS_ENABLED_UART 0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct uart_inst uart_inst_t;
+
+extern uart_inst_t * const uart0;
+extern uart_inst_t * const uart1;
+#define uart_default uart0
+
+typedef enum {
+    UART_PARITY_NONE,
+    UART_PARITY_EVEN,
+    UART_PARITY_ODD
+} uart_parity_t;
+
+// ----------------------------------------------------------------------------
+// Setup
+
+// Put the UART into a known state, and enable it. Must be called before other
+// functions.
+uint uart_init(uart_inst_t *uart, uint baudrate);
+
+// Disable the UART if it is no longer used. Must be reinitialised before
+// being used again.
+void uart_deinit(uart_inst_t *uart);
+
+// Set baud rate as close as possible to requested, and return actual rate.
+uint uart_set_baudrate(uart_inst_t *uart, uint baudrate);
+
+// cts: enable flow control of TX by clear-to-send input
+// rts: enable assertion of request-to-send output by RX flow control
+void uart_set_hw_flow(uart_inst_t *uart, bool cts, bool rts);
+
+// Configure how the UART serialises and deserialises data on the wire
+void uart_set_format(uart_inst_t *uart, uint data_bits, uint stop_bits, uart_parity_t parity);
+
+// Enable the UART's interrupt output. Need to install an interrupt handler first.
+void uart_set_irq_enables(uart_inst_t *uart, bool rx_has_data, bool tx_needs_data);
+
+// ----------------------------------------------------------------------------
+// Generic input/output
+
+// If returns 0, no space is available in the UART to write more data.
+// If returns nonzero, at least that many bytes can be written without blocking.
+size_t uart_is_writable(uart_inst_t *uart);
+
+// If returns 0, no data is available to be read from UART.
+// If returns nonzero, at least that many bytes can be written without blocking.
+size_t uart_is_readable(uart_inst_t *uart);
+
+// Write len bytes directly from src to the UART
+void uart_write_blocking(uart_inst_t *uart, const uint8_t *src, size_t len);
+
+// Read len bytes directly from the UART to dst
+void uart_read_blocking(uart_inst_t *uart, uint8_t *dst, size_t len);
+
+// ----------------------------------------------------------------------------
+// UART-specific operations and aliases
+
+void uart_putc(uart_inst_t *uart, char c);
+
+void uart_puts(uart_inst_t *uart, const char *s);
+
+char uart_getc(uart_inst_t *uart);
+
+// en: assert break condition (TX held low) if true. Clear break condition if false.
+void uart_set_break(uart_inst_t *uart, bool en);
+
+void uart_default_tx_wait_blocking();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/host/hardware_uart/uart.c b/src/host/hardware_uart/uart.c
new file mode 100644
index 0000000..e610402
--- /dev/null
+++ b/src/host/hardware_uart/uart.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdio.h>
+#include "hardware/uart.h"
+
+#if defined(__unix) || defined(__APPLE__)
+#define _XOPEN_SOURCE 600 /* for ONLCR */
+#define __BSD_VISIBLE 1 /* for ONLCR in *BSD */
+
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#ifndef FNONBLOCK
+#define FNONBLOCK O_NONBLOCK
+#endif
+
+struct termios _tty;
+static tcflag_t _res_oflg = 0;
+static tcflag_t _res_lflg = 0;
+
+void _resettty(void) {
+    if (!isatty(STDIN_FILENO))
+        return;
+
+    /* reset tty: */
+    _tty.c_oflag = _res_oflg;
+    _tty.c_lflag = _res_lflg;
+    tcsetattr(STDIN_FILENO, TCSADRAIN, &_tty);
+}
+
+void _inittty(void) {
+    if (!isatty(STDIN_FILENO))
+        return;
+
+    /* save tty: */
+    tcgetattr(STDIN_FILENO, &_tty);
+    _res_oflg = _tty.c_oflag;
+    _res_lflg = _tty.c_lflag;
+
+    /* set raw: */
+    _tty.c_lflag &= ~(ICANON | ICRNL);// | ISIG);
+    //_tty.c_oflag &= ~ONLCR;
+    tcsetattr(STDIN_FILENO, TCSANOW, &_tty);
+
+    fcntl(STDIN_FILENO, F_SETFL, FNONBLOCK);
+    atexit(_resettty);
+}
+
+#else
+void _inittty() {}
+#endif
+
+typedef struct {
+    bool dummy;
+} uart_hw_t;
+
+uart_inst_t *const uart0;
+uart_inst_t *const uart1;
+
+static int _nextchar = EOF;
+
+static bool _peekchar() {
+    if (_nextchar == EOF) {
+        _nextchar = getchar();
+    }
+    return _nextchar != EOF;
+}
+
+uint uart_init(uart_inst_t *uart, uint baud_rate) {
+    _inittty();
+    return baud_rate;
+}
+
+size_t uart_is_writable(uart_inst_t *uart) {
+    return 1;
+}
+
+// If returns 0, no data is available to be read from UART.
+// If returns nonzero, at least that many bytes can be written without blocking.
+size_t uart_is_readable(uart_inst_t *uart) {
+    return _peekchar() ? 1 : 0;
+}
+
+// Write len bytes directly from src to the UART
+void uart_write_blocking(uart_inst_t *uart, const uint8_t *src, size_t len) {
+    for (size_t i = 0; i < len; i++) {
+        uart_putc(uart, src[i]);
+    }
+}
+
+// Read len bytes directly from the UART to dst
+void uart_read_blocking(uart_inst_t *uart, uint8_t *dst, size_t len) {
+    for (size_t i = 0; i < len; i++) {
+        dst[i] = uart_getc(uart);
+    }
+}
+
+// ----------------------------------------------------------------------------
+// UART-specific operations and aliases
+
+void uart_putc(uart_inst_t *uart, char c) {
+    putchar(c);
+}
+
+void uart_puts(uart_inst_t *uart, const char *s) {
+    puts(s);
+}
+
+char uart_getc(uart_inst_t *uart) {
+    while (!_peekchar()) {
+        tight_loop_contents();
+    }
+    char rc = (char) _nextchar;
+    _nextchar = EOF;
+    return rc;
+}
+
+void uart_default_tx_wait_blocking() {
+
+}
diff --git a/src/host/pico_bit_ops/CMakeLists.txt b/src/host/pico_bit_ops/CMakeLists.txt
new file mode 100644
index 0000000..7732b1e
--- /dev/null
+++ b/src/host/pico_bit_ops/CMakeLists.txt
@@ -0,0 +1,9 @@
+pico_add_impl_library(pico_bit_ops)
+
+target_sources(pico_bit_ops INTERFACE
+        ${CMAKE_CURRENT_LIST_DIR}/bit_ops.c)
+
+target_link_libraries(pico_bit_ops INTERFACE pico_bit_ops_headers)
+
+macro(pico_set_bit_ops_implementation TARGET IMPL)
+endmacro()
\ No newline at end of file
diff --git a/src/host/pico_bit_ops/bit_ops.c b/src/host/pico_bit_ops/bit_ops.c
new file mode 100644
index 0000000..11f69fe
--- /dev/null
+++ b/src/host/pico_bit_ops/bit_ops.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "pico/bit_ops.h"
+
+uint32_t __rev(uint32_t v) {
+    v = ((v & 0x55555555u) << 1u) | ((v >> 1u) & 0x55555555u);
+    v = ((v & 0x33333333u) << 2u) | ((v >> 2u) & 0x33333333u);
+    v = ((v & 0x0f0f0f0fu) << 4u) | ((v >> 4u) & 0x0f0f0f0fu);
+    return (v << 24u) | ((v & 0xff00u) << 8u) | ((v >> 8u) & 0xff00u) | (v >> 24u);
+}
+
+uint64_t __revll(uint64_t v) {
+    v = ((v & 0x5555555555555555u) << 1u) | ((v >> 1u) & 0x5555555555555555u);
+    v = ((v & 0x3333333333333333u) << 2u) | ((v >> 2u) & 0x3333333333333333u);
+    v = ((v & 0x0f0f0f0f0f0f0f0fu) << 4u) | ((v >> 4u) & 0x0f0f0f0f0f0f0f0fu);
+    v = ((v & 0x00ff00ff00ff00ffu) << 8u) | ((v >> 8u) & 0x00ff00ff00ff00ffu);
+    return (v << 48u) | ((v & 0xffff0000u) << 16u) | ((v >> 16u) & 0xffff0000u) | (v >> 48u);
+}
diff --git a/src/host/pico_divider/CMakeLists.txt b/src/host/pico_divider/CMakeLists.txt
new file mode 100644
index 0000000..f6936dd
--- /dev/null
+++ b/src/host/pico_divider/CMakeLists.txt
@@ -0,0 +1,9 @@
+pico_add_impl_library(pico_divider)
+
+target_sources(pico_divider INTERFACE
+        ${CMAKE_CURRENT_LIST_DIR}/divider.c)
+
+target_link_libraries(pico_divider INTERFACE pico_divider_headers)
+
+macro(pico_set_divider_implementation TARGET IMPL)
+endmacro()
\ No newline at end of file
diff --git a/src/host/pico_divider/divider.c b/src/host/pico_divider/divider.c
new file mode 100644
index 0000000..df0e275
--- /dev/null
+++ b/src/host/pico_divider/divider.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "pico/divider.h"
+
+// These functions save/restore divider state, so are safe to call from interrupts
+int32_t div_s32s32(int32_t a, int32_t b) {
+    return hw_divider_s32_quotient(a, b);
+}
+
+divmod_result_t divmod_s32s32(int32_t a, int32_t b) {
+    return hw_divider_divmod_s32(a, b);
+}
+
+uint32_t div_u32u32(uint32_t a, uint32_t b) {
+    return hw_divider_u32_quotient(a, b);
+}
+
+divmod_result_t divmod_u32u32(uint32_t a, uint32_t b) {
+    return hw_divider_divmod_u32(a, b);
+}
+
+static inline int __sign_of_64(int32_t v) {
+    return v > 0 ? 1 : (v < 0 ? -1 : 0);
+}
+
+typedef struct {
+    uint64_t quotient;
+    uint64_t remainder;
+} qr_u64;
+
+typedef struct {
+    int64_t quotient;
+    int64_t remainder;
+} qr_s64;
+
+// divides unsigned values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
+static inline qr_u64 udiv64(uint64_t a, uint64_t b) {
+    qr_u64 rc;
+    if (!b) {
+        rc.quotient = (uint64_t)-1; // todo check this
+        rc.remainder = a;
+    } else {
+        rc.quotient = a/b;
+        rc.remainder = a%b;
+    }
+    return rc;
+}
+
+// divides signed values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
+static inline qr_s64 div64(int64_t a, int64_t b) {
+    qr_s64 rc;
+    if (!b) {
+        rc.quotient = (uint64_t)(-__sign_of_64(a));
+        rc.remainder = a;
+    } else {
+        rc.quotient = a/b;
+        rc.remainder = a%b;
+    }
+    return rc;
+}
+
+int64_t div_s64s64(int64_t a, int64_t b) {
+    qr_s64 qr = div64(a, b);
+    return qr.quotient;
+}
+
+int64_t divmod_s64s64_rem(int64_t a, int64_t b, int64_t *rem) {
+    qr_s64 qr = div64(a, b);
+    *rem = qr.remainder;
+    return qr.quotient;
+}
+
+int64_t divmod_s64s64(int64_t a, int64_t b) {
+    qr_s64 qr = div64(a, b);
+    return qr.quotient;
+}
+
+uint64_t div_u64u64(uint64_t a, uint64_t b) {
+    qr_u64 qr = udiv64(a, b);
+    return qr.quotient;
+}
+
+uint64_t divmod_u64u64_rem(uint64_t a, uint64_t b, uint64_t *rem) {
+    qr_u64 qr = udiv64(a, b);
+    *rem = qr.remainder;
+    return qr.quotient;
+}
+
+uint64_t divmod_u64u64(uint64_t a, uint64_t b) {
+    qr_u64 qr = udiv64(a, b);
+    return qr.quotient;
+}
+
+// these functions are slightly faster, but unsafe the divider state, so are not generally safe to be called from interrupts
+
+int32_t div_s32s32_unsafe(int32_t a, int32_t b) { return div_s32s32(a,b); }
+int32_t divmod_s32s32_rem_unsafe(int32_t a, int32_t b, int32_t *rem) { return divmod_s32s32_rem(a, b, rem); }
+int64_t divmod_s32s32_unsafe(int32_t a, int32_t b) { return divmod_s32s32(a, b); }
+
+uint32_t div_u32u32_unsafe(uint32_t a, uint32_t b) { return div_u32u32(a, b); }
+uint32_t divmod_u32u32_rem_unsafe(uint32_t a, uint32_t b, uint32_t *rem) { return divmod_u32u32_rem(a, b, rem); }
+uint64_t divmod_u32u32_unsafe(uint32_t a, uint32_t b) { return divmod_u32u32(a, b); }
+
+int64_t div_s64s64_unsafe(int64_t a, int64_t b) { return div_s64s64(a, b); }
+int64_t divmod_s64s64_rem_unsafe(int64_t a, int64_t b, int64_t *rem) { return divmod_s64s64_rem(a, b, rem); }
+int64_t divmod_s64s64_unsafe(int64_t a, int64_t b) { return divmod_s64s64(a, b); }
+
+uint64_t div_u64u64_unsafe(uint64_t a, uint64_t b) { return div_u64u64(a, b); }
+uint64_t divmod_u64u64_rem_unsafe(uint64_t a, uint64_t b, uint64_t *rem) { return divmod_u64u64_rem(a, b, rem); }
+uint64_t divmod_u64u64_unsafe(uint64_t a, uint64_t b) { return divmod_u64u64(a, b); }
diff --git a/src/host/pico_multicore/CMakeLists.txt b/src/host/pico_multicore/CMakeLists.txt
new file mode 100644
index 0000000..5b90fa3
--- /dev/null
+++ b/src/host/pico_multicore/CMakeLists.txt
@@ -0,0 +1,8 @@
+if (NOT TARGET pico_multicore)
+    pico_add_impl_library(pico_multicore)
+
+    target_include_directories(pico_multicore INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
+endif()
+
+
+
diff --git a/src/host/pico_multicore/include/pico/multicore.h b/src/host/pico_multicore/include/pico/multicore.h
new file mode 100644
index 0000000..1be1694
--- /dev/null
+++ b/src/host/pico_multicore/include/pico/multicore.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _PICO_MULTICORE_H
+#define _PICO_MULTICORE_H
+
+#include "pico/types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void multicore_reset_core1(void);
+void multicore_launch_core1(void (*entry)(void));
+void multicore_launch_core1_with_stack(void (*entry)(void), uint32_t *stack_bottom, size_t stack_size_bytes);
+void multicore_launch_core1_raw(void (*entry)(void), uint32_t *sp, uint32_t vector_table);
+
+bool multicore_fifo_rvalid(void);
+bool multicore_fifo_wready(void);
+void multicore_fifo_push_blocking(uint32_t data);
+bool multicore_fifo_push_timeout_us(uint32_t data, uint64_t timeout_us);
+uint32_t multicore_fifo_pop_blocking();
+bool multicore_fifo_pop_timeout_us(uint64_t timeout_us, uint32_t *out);
+void multicore_fifo_drain(void);
+void multicore_fifo_clear_irq(void);
+uint32_t multicore_fifo_get_status(void);
+
+// call this from the lockout victim thread
+void multicore_lockout_victim_init(void);
+
+// start locking out the other core (it will be
+bool multicore_lockout_start_timeout_us(uint64_t timeout_us);
+void multicore_lockout_start_blocking(void);
+
+bool multicore_lockout_end_timeout_us(uint64_t timeout_us);
+void multicore_lockout_end_blocking(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/host/pico_platform/CMakeLists.txt b/src/host/pico_platform/CMakeLists.txt
new file mode 100644
index 0000000..c78e330
--- /dev/null
+++ b/src/host/pico_platform/CMakeLists.txt
@@ -0,0 +1,31 @@
+# This file may be included directly by a build to get common SDK macros and types
+
+if (NOT TARGET pico_platform_headers)
+    add_library(pico_platform_headers INTERFACE)
+
+    target_compile_definitions(pico_platform_headers INTERFACE
+            PICO_NO_HARDWARE=1
+            PICO_ON_DEVICE=0
+            PICO_BUILD=1
+    )
+
+    target_include_directories(pico_platform_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
+endif()
+
+if (NOT TARGET pico_platform)
+    if (COMMAND pico_add_platform_library)
+        pico_add_platform_library(pico_platform)
+    else()
+        add_library(pico_platform INTERFACE)
+    endif()
+
+    target_sources(pico_platform INTERFACE
+        ${CMAKE_CURRENT_LIST_DIR}/platform_base.c
+    )
+
+    target_link_libraries(pico_platform INTERFACE pico_platform_headers pico_bit_ops ${PICO_PLATFORM_EXTRA_LIBRARIES})
+endif()
+
+function(pico_add_platform_library TARGET)
+    target_link_libraries(pico_platform INTERFACE ${TARGET})
+endfunction()
diff --git a/src/host/pico_platform/include/hardware/platform_defs.h b/src/host/pico_platform/include/hardware/platform_defs.h
new file mode 100644
index 0000000..6d0aa84
--- /dev/null
+++ b/src/host/pico_platform/include/hardware/platform_defs.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _HARDWARE_PLATFORM_DEFS_H
+#define _HARDWARE_PLATFORM_DEFS_H
+
+#define NUM_CORES 2u
+
+#define NUM_DMA_CHANNELS 12u
+
+#define NUM_TIMERS 4u
+
+#define NUM_IRQS 32u
+
+#define NUM_SPIN_LOCKS 32u
+
+#define XOSC_MHZ 12
+
+#define NUM_SPIN_LOCKS 32u
+
+#ifndef _u
+#define _u(x) x ## u
+#endif
+
+#endif
diff --git a/src/host/pico_platform/include/pico/platform.h b/src/host/pico_platform/include/pico/platform.h
new file mode 100644
index 0000000..27e5c08
--- /dev/null
+++ b/src/host/pico_platform/include/pico/platform.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _PICO_PLATFORM_H_
+#define _PICO_PLATFORM_H_
+
+#include "hardware/platform_defs.h"
+#include <stddef.h>
+
+#ifdef __unix__
+
+#include <sys/cdefs.h>
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __not_in_flash(group)
+#define __not_in_flash_func(func) func
+#define __no_inline_not_in_flash_func(func)
+#define __in_flash(group)
+#define __scratch_x(group)
+#define __scratch_y(group)
+
+#ifndef _MSC_VER
+#define __packed __attribute__((packed))
+#define __packed_aligned __packed __attribute((aligned))
+#else
+// MSVC requires #pragma pack which isn't compatible with a single attribute style define
+#define __packed
+#define __packed_aligned
+#endif
+
+#define __time_critical_func(x) x
+#define __after_data(group)
+
+//int running_on_fpga() { return false; }
+extern void tight_loop_contents();
+
+#ifndef __STRING
+#define __STRING(x) #x
+#endif
+
+#ifndef _MSC_VER
+#ifndef __noreturn
+#define __noreturn __attribute((noreturn))
+#endif
+
+#ifndef __unused
+#define __unused __attribute__((unused))
+#endif
+
+#ifndef __noinline
+#define __noinline __attribute__((noinline))
+#endif
+
+#ifndef __aligned
+#define __aligned(x) __attribute__((aligned(x)))
+#endif
+
+#define PICO_WEAK_FUNCTION_DEF(x) _Pragma(__STRING(weak x))
+#define PICO_WEAK_FUNCTION_IMPL_NAME(x) x
+
+#else
+#ifndef __noreturn
+#define __noreturn __declspec(noreturn)
+#endif
+
+#ifndef __unused
+#define __unused
+#endif
+
+#ifndef __noinline
+#define __noinline __declspec(noinline)
+#endif
+
+#ifndef __aligned
+#define __aligned(x) __declspec(align(x))
+#endif
+
+#ifndef __CONCAT
+#define __CONCAT(x,y) x ## y
+#endif
+
+#define __thread __declspec( thread )
+
+#define PICO_WEAK_FUNCTION_DEF(x) __pragma(comment(linker, __STRING(/alternatename:_##x=_##x##__weak)));
+#define PICO_WEAK_FUNCTION_IMPL_NAME(x) x ## __weak
+
+static __noreturn void __builtin_unreachable() {
+}
+
+#include <intrin.h>
+#define __builtin_clz __lzcnt
+#endif
+
+#ifndef count_of
+#define count_of(a) (sizeof(a)/sizeof((a)[0]))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) ((a)>(b)?(a):(b))
+#endif
+
+#ifndef MIN
+#define MIN(a, b) ((b)>(a)?(a):(b))
+#endif
+
+// abort in our case
+void __noreturn __breakpoint();
+
+void __noreturn panic_unsupported();
+
+void __noreturn panic(const char *fmt, ...);
+
+// arggggghhhh there is a weak function called sem_init used by SDL
+#define sem_init sem_init_alternative
+
+extern uint32_t host_safe_hw_ptr_impl(uintptr_t x);
+// return a 32 bit handle for a raw ptr; DMA chaining for example embeds pointers in 32 bit values
+// which of course does not work if we're running the code natively on a 64 bit platforms. Therefore
+// we provide this macro which allows that code to provide a 64->32 bit mapping in host mode
+#define host_safe_hw_ptr(x) host_safe_hw_ptr_impl((uintptr_t)(x))
+void *decode_host_safe_hw_ptr(uint32_t ptr);
+
+#define __fast_mul(a,b) ((a)*(b))
+
+typedef unsigned int uint;
+
+static inline int32_t __mul_instruction(int32_t a,int32_t b)
+{
+    return a*b;
+}
+
+static inline void __compiler_memory_barrier(void) {
+}
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/host/pico_platform/platform_base.c b/src/host/pico_platform/platform_base.c
new file mode 100644
index 0000000..be1dbd4
--- /dev/null
+++ b/src/host/pico_platform/platform_base.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "pico.h"
+
+PICO_WEAK_FUNCTION_DEF(tight_loop_contents)
+
+void PICO_WEAK_FUNCTION_IMPL_NAME(tight_loop_contents)() {
+
+}
+
+void __noreturn panic_unsupported() {
+    panic("not supported");
+}
+
+void hard_assertion_failure(void) {
+    panic("Hard assert");
+}
+
+void panic(const char *fmt, ...) {
+    va_list args;
+
+    puts("*** PANIC ***\n");
+    if (fmt) {
+        va_start(args, fmt);
+        vprintf(fmt, args);
+        va_end(args);
+    }
+
+    puts("\n");
+
+    __breakpoint();
+}
+
+void __breakpoint() {
+    #ifdef _MSC_VER
+        __debugbreak();
+    #else
+        __builtin_trap();
+    #endif
+}
\ No newline at end of file
diff --git a/src/host/pico_printf/CMakeLists.txt b/src/host/pico_printf/CMakeLists.txt
new file mode 100644
index 0000000..8bfbdee
--- /dev/null
+++ b/src/host/pico_printf/CMakeLists.txt
@@ -0,0 +1,6 @@
+if (NOT TARGET pico_printf)
+    pico_add_impl_library(pico_printf)
+    function(pico_set_printf_implementation)
+    endfunction()
+endif()
+
diff --git a/src/host/pico_stdio/CMakeLists.txt b/src/host/pico_stdio/CMakeLists.txt
new file mode 100644
index 0000000..428c1a9
--- /dev/null
+++ b/src/host/pico_stdio/CMakeLists.txt
@@ -0,0 +1,20 @@
+if (NOT TARGET pico_stdio)
+    pico_add_impl_library(pico_stdio)
+
+    target_include_directories(pico_stdio INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
+
+    target_sources(pico_stdio INTERFACE
+            ${CMAKE_CURRENT_LIST_DIR}/stdio.c
+            )
+    pico_add_impl_library(pico_stdio_usb)
+    pico_add_impl_library(pico_stdio_uart)
+    pico_add_impl_library(pico_stdio_semihosting)
+    
+    function(pico_enable_stdio_uart)
+    endfunction()
+    function(pico_enable_stdio_usb)
+    endfunction()
+    function(pico_enable_stdio_semihosting)
+    endfunction()
+endif()
+
diff --git a/src/host/pico_stdio/include/pico/stdio.h b/src/host/pico_stdio/include/pico/stdio.h
new file mode 100644
index 0000000..de0bde1
--- /dev/null
+++ b/src/host/pico_stdio/include/pico/stdio.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef _PICO_STDIO_H
+#define _PICO_STDIO_H
+
+typedef struct stdio_driver stdio_driver_t;
+
+#define STDIO_ERROR -1
+#define STDIO_NO_INPUT -2
+
+static inline void stdio_usb_init() {}
+void stdio_uart_init();
+static inline void stdio_init_all() { stdio_uart_init(); }
+static inline void stdio_filter_driver(stdio_driver_t *driver) {}
+static inline void stdio_set_translate_crlf(stdio_driver_t *driver, bool enabled) {}
+static inline bool stdio_usb_connected(void) { return true; }
+int getchar_timeout_us(uint32_t timeout_us);
+#define puts_raw puts
+#define putchar_raw putchar
+
+#endif
diff --git a/src/host/pico_stdio/stdio.c b/src/host/pico_stdio/stdio.c
new file mode 100644
index 0000000..87be91d
--- /dev/null
+++ b/src/host/pico_stdio/stdio.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "pico/stdlib.h"
+#include "hardware/uart.h"
+
+int getchar_timeout_us(uint32_t timeout_us) {
+    absolute_time_t t = make_timeout_time_us(timeout_us);
+    while (!uart_is_readable(uart_default)) {
+        if (absolute_time_diff_us(t, get_absolute_time()) > 0) {
+            return STDIO_NO_INPUT;
+        }
+        sleep_ms(1);
+    }
+    return uart_getc(uart_default);
+}
+
+void stdio_uart_init() {
+    uart_init(uart_default, 0);
+}
\ No newline at end of file
diff --git a/src/host/pico_stdlib/CMakeLists.txt b/src/host/pico_stdlib/CMakeLists.txt
new file mode 100644
index 0000000..257798c
--- /dev/null
+++ b/src/host/pico_stdlib/CMakeLists.txt
@@ -0,0 +1,19 @@
+if (NOT TARGET pico_stdlib)
+    pico_add_impl_library(pico_stdlib)
+
+    target_sources(pico_stdlib INTERFACE
+            ${CMAKE_CURRENT_LIST_DIR}/stdlib.c
+    )
+
+    target_link_libraries(pico_stdlib INTERFACE
+            pico_stdlib_headers
+            pico_platform
+            pico_time
+            pico_divider
+            pico_binary_info
+            pico_printf
+            pico_stdio
+            hardware_gpio
+    )
+endif()
+
diff --git a/src/host/pico_stdlib/stdlib.c b/src/host/pico_stdlib/stdlib.c
new file mode 100644
index 0000000..166bd5f
--- /dev/null
+++ b/src/host/pico_stdlib/stdlib.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "pico/stdlib.h"
+
+void setup_default_uart() {
+
+}
+
+void set_sys_clock_48mhz() {
+
+}
+
+bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_out, uint *postdiv1_out, uint *postdiv2_out) {
+    *vco_out = 1000000;
+    *postdiv1_out = 0;
+    *postdiv2_out = 0;
+    return true;
+}
+
+void set_sys_clock_pll(__unused uint32_t vco_freq, __unused uint post_div1, __unused uint post_div2) {
+
+}
+