/* * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include "pico/bootrom.h" #include "pico/bootrom/sf_table.h" // NOTE THIS FUNCTION TABLE IS NOT PUBLIC OR NECESSARILY COMPLETE... // IT IS ***NOT*** SAFE TO CALL THESE FUNCTION POINTERS FROM ARBITRARY CODE uint32_t sf_table[SF_TABLE_V2_SIZE / 2]; void __attribute__((weak)) *sf_clz_func; #if !PICO_FLOAT_SUPPORT_ROM_V1 static __attribute__((noreturn)) void missing_float_func_shim(void) { panic(""); } #endif void __aeabi_float_init(void) { int rom_version = rp2040_rom_version(); void *rom_table = rom_data_lookup(rom_table_code('S', 'F')); #if PICO_FLOAT_SUPPORT_ROM_V1 if (rom_version == 1) { memcpy(&sf_table, rom_table, SF_TABLE_V1_SIZE); extern void float_table_shim_on_use_helper(void); // todo replace NDEBUG with a more exclusive assertion guard #ifndef NDEBUG if (*(uint16_t *)0x29ee != 0x0fc4 || // this is packx *(uint16_t *)0x29c0 != 0x0dc2 || // this is upackx *(uint16_t *)0x2b96 != 0xb5c0 || // this is cordic_vec *(uint16_t *)0x2b18 != 0x2500 || // this is packretns *(uint16_t *)0x2acc != 0xb510 || // this is float2fix *(uint32_t *)0x2cfc != 0x6487ed51 // pi_q29 ) { panic(""); } #endif // this is a little tricky.. we only want to pull in a shim if the corresponding function // is called. to that end we include a SVC instruction with the table offset as the call number // followed by the shim function pointer inside the actual wrapper function. that way if the wrapper // function is garbage collected, so is the shim function. // // float_table_shim_on_use_helper expects this SVC instruction in the calling code soon after the address // pointed to by IP and patches the float_table entry with the real shim the first time the function is called. for(uint i=SF_TABLE_V1_SIZE/4; i= 2) { assert(*((uint8_t *)(rom_table-2)) * 4 >= SF_TABLE_V2_SIZE); memcpy(&sf_table, rom_table, SF_TABLE_V2_SIZE); } sf_clz_func = rom_func_lookup(rom_table_code('L', '3')); }