YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
float_init_rom.c
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <string.h>
8#include <assert.h>
9#include "bootrom.h"
10#include "sf_table.h"
11
12void __attribute((noreturn)) panic(char *);
13uint8_t rp2040_rom_version(void);
14
15// NOTE THIS FUNCTION TABLE IS NOT PUBLIC OR NECESSARILY COMPLETE...
16// IT IS ***NOT*** SAFE TO CALL THESE FUNCTION POINTERS FROM ARBITRARY CODE
17uint32_t sf_table[SF_TABLE_V2_SIZE / 2];
18void __attribute__((weak)) *sf_clz_func;
19
20#if !(PICO_FLOAT_SUPPORT_ROM_V1 && PICO_RP2040_B0_SUPPORTED)
21static __attribute__((noreturn)) void missing_float_func_shim(void) {
22 panic("");
23}
24#endif
25
26void __aeabi_float_init(void) {
27 int rom_version = rp2040_rom_version();
28 void *rom_table = rom_data_lookup(rom_table_code('S', 'F'));
29#if PICO_FLOAT_SUPPORT_ROM_V1 && PICO_RP2040_B0_SUPPORTED
30 if (rom_version == 1) {
31 memcpy(&sf_table, rom_table, SF_TABLE_V1_SIZE);
32 extern void float_table_shim_on_use_helper(void);
33 // todo replace NDEBUG with a more exclusive assertion guard
34#ifndef NDEBUG
35 if (*(uint16_t *)0x29ee != 0x0fc4 || // this is packx
36 *(uint16_t *)0x29c0 != 0x0dc2 || // this is upackx
37 *(uint16_t *)0x2b96 != 0xb5c0 || // this is cordic_vec
38 *(uint16_t *)0x2b18 != 0x2500 || // this is packretns
39 *(uint16_t *)0x2acc != 0xb510 || // this is float2fix
40 *(uint32_t *)0x2cfc != 0x6487ed51 // pi_q29
41 ) {
42 panic("");
43 }
44#endif
45
46 // this is a little tricky.. we only want to pull in a shim if the corresponding function
47 // is called. to that end we include a SVC instruction with the table offset as the call number
48 // followed by the shim function pointer inside the actual wrapper function. that way if the wrapper
49 // function is garbage collected, so is the shim function.
50 //
51 // float_table_shim_on_use_helper expects this SVC instruction in the calling code soon after the address
52 // pointed to by IP and patches the float_table entry with the real shim the first time the function is called.
53
54 for(uint32_t i=SF_TABLE_V1_SIZE/4; i<SF_TABLE_V2_SIZE/4; i++) {
55 sf_table[i] = (uintptr_t)float_table_shim_on_use_helper;
56 }
57 // we shim these for -0 and -denormal handling
58 sf_table[SF_TABLE_FLOAT2INT/4] = sf_table[SF_TABLE_FLOAT2FIX/4] = (uintptr_t)float_table_shim_on_use_helper;
59 }
60#else
61 if (rom_version == 1) {
62 memcpy(&sf_table, rom_table, SF_TABLE_V1_SIZE);
63 // opting for soft failure for now - you'll get a panic at runtime if you call any of the missing methods
64 for(uint32_t i=0;i<SF_TABLE_V2_SIZE/4;i++) {
65 if (!sf_table[i]) sf_table[i] = (uintptr_t)missing_float_func_shim;
66 }
67 }
68#endif
69 if (rom_version >= 2) {
70 assert(*((uint8_t *)(rom_table-2)) * 4 >= SF_TABLE_V2_SIZE);
71 memcpy(&sf_table, rom_table, SF_TABLE_V2_SIZE);
72 }
73 sf_clz_func = rom_func_lookup(ROM_FUNC_CLZ32);
74}
void * rom_func_lookup(uint32_t code)
Lookup a bootrom function by code.
Definition bootrom.c:15
void * rom_data_lookup(uint32_t code)
Lookup a bootrom address by code.
Definition bootrom.c:19
void __attribute__((noreturn))(*rom_reset_usb_boot_fn)(uint32_t
Reboot the device into BOOTSEL mode.
Definition bootrom.h:66