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