From 400225e95a59e1bed2815969e85c4c856474533a Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Sun, 14 Jul 2024 18:53:05 -0700 Subject: [PATCH 01/14] :zap: Add the folowing optimizations (1) - :recycle: Simplify `restore_cpu_core` assembly a bit - :zap: Unwind becomes a jump table --- src/arm_cortex/estell/exception.cpp | 1041 ++++++++++++++++++++++++++- src/arm_cortex/estell/internal.hpp | 44 -- 2 files changed, 1001 insertions(+), 84 deletions(-) diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index 111826d..34abd09 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -31,7 +31,17 @@ namespace ke { -using instructions_t = std::array; +union instructions_t +{ + // Why the length of 8? ARM unwind instructions are capped at 7 bytes for all + // possible functions. The 8th instruction will always be the finish byte. + // This allows the unwinder to iterate through the whole list without needing + // to compare a length variable which would decrease performance. + std::array data{ + arm_ehabi::finish, arm_ehabi::finish, arm_ehabi::finish, arm_ehabi::finish, + arm_ehabi::finish, arm_ehabi::finish, arm_ehabi::finish, arm_ehabi::finish, + }; +}; namespace { exception_ptr active_exception = nullptr; @@ -52,7 +62,7 @@ exception_ptr current_exception() noexcept return active_exception; } -void capture_cpu_core(ke::cortex_m_cpu& p_cpu_core) +inline void capture_cpu_core(ke::cortex_m_cpu& p_cpu_core) { asm volatile("mrs r0, MSP\n" // Move Main Stack Pointer to r0 "stmia %0, {r0-r12}\n" // Store r0 to r12 into the array @@ -385,7 +395,43 @@ class action_decoder std::uint8_t m_filter = 0; }; -int global_int = 0; +inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) +{ + asm volatile( + "ldr r0, [%[regs], #0]\n" // Load R0 + "ldr r1, [%[regs], #4]\n" // Load R1 + "ldr r2, [%[regs], #8]\n" // Load R2 + // Skip loading R3, R3 will be used for loading all other registers + "ldr r4, [%[regs], #16]\n" // Load R4 + "ldr r5, [%[regs], #20]\n" // Load R5 + "ldr r6, [%[regs], #24]\n" // Load R6 + "ldr r7, [%[regs], #28]\n" // Load R7 + "ldr r8, [%[regs], #32]\n" // Load R8 + "ldr r9, [%[regs], #36]\n" // Load R9 + "ldr r10, [%[regs], #40]\n" // Load R10 + "ldr r11, [%[regs], #44]\n" // Load R11 + "ldr r12, [%[regs], #48]\n" // Load R12 + "ldr sp, [%[regs], #52]\n" // Load SP + "ldr lr, [%[regs], #56]\n" // Load LR + "ldr pc, [%[regs], #60]\n" + : + : [regs] "r"(&p_cpu_core) + : "memory", + "r0", + "r1", + "r2", + // skip r3 + "r4", + "r5", + "r6", + "r7", + "fp", + "r8", + "r9", + "r10", + "r11", + "r12"); +} void enter_function(exception_object& p_exception_object) { @@ -445,14 +491,926 @@ void enter_function(exception_object& p_exception_object) } } +template +std::uint32_t vsp_deallocate_amount() +{ + return (Amount << 2) + 4; +} + +template +inline void pop_register_range(cortex_m_cpu& p_virtual_cpu) +{ + if constexpr (PopLinkRegister == 7) { + p_virtual_cpu.lr = (*p_virtual_cpu.sp)[PopCount + 1]; + } + if constexpr (PopCount == 7) { + p_virtual_cpu[11] = (*p_virtual_cpu.sp)[7]; + } + if constexpr (PopCount >= 6) { + p_virtual_cpu[10] = (*p_virtual_cpu.sp)[6]; + } + if constexpr (PopCount >= 5) { + p_virtual_cpu[9] = (*p_virtual_cpu.sp)[5]; + } + if constexpr (PopCount >= 4) { + p_virtual_cpu[8] = (*p_virtual_cpu.sp)[4]; + } + if constexpr (PopCount >= 3) { + p_virtual_cpu[7] = (*p_virtual_cpu.sp)[3]; + } + if constexpr (PopCount >= 2) { + p_virtual_cpu[6] = (*p_virtual_cpu.sp)[2]; + } + if constexpr (PopCount >= 1) { + p_virtual_cpu[5] = (*p_virtual_cpu.sp)[1]; + } + if constexpr (PopCount >= 0) { + p_virtual_cpu[4] = (*p_virtual_cpu.sp)[0]; + } + + // Move the stack up by the number of registers we popped plus 1 to place it + // in the previous function's frame. + static constexpr auto stack_offset = + 4U * (PopCount + 1U + unsigned{ PopLinkRegister }); + + p_virtual_cpu.sp = p_virtual_cpu.sp + stack_offset; +} + void unwind_frame(instructions_t const& p_instructions, exception_object& p_exception_object) { + static constexpr std::array jump_table{ + &&vsp_add_0, // [0] + &&vsp_add_1, // [1] + &&vsp_add_2, // [2] + &&vsp_add_3, // [3] + &&vsp_add_4, // [4] + &&vsp_add_5, // [5] + &&vsp_add_6, // [6] + &&vsp_add_7, // [7] + &&vsp_add_8, // [8] + &&vsp_add_9, // [9] + &&vsp_add_10, // [10] + &&vsp_add_11, // [11] + &&vsp_add_12, // [12] + &&vsp_add_13, // [13] + &&vsp_add_14, // [14] + &&vsp_add_15, // [15] + &&vsp_add_16, // [16] + &&vsp_add_17, // [17] + &&vsp_add_18, // [18] + &&vsp_add_19, // [19] + &&vsp_add_20, // [20] + &&vsp_add_21, // [21] + &&vsp_add_22, // [22] + &&vsp_add_23, // [23] + &&vsp_add_24, // [24] + &&vsp_add_25, // [25] + &&vsp_add_26, // [26] + &&vsp_add_27, // [27] + &&vsp_add_28, // [28] + &&vsp_add_29, // [29] + &&vsp_add_30, // [30] + &&vsp_add_31, // [31] + &&vsp_add_32, // [32] + &&vsp_add_33, // [33] + &&vsp_add_34, // [34] + &&vsp_add_35, // [35] + &&vsp_add_36, // [36] + &&vsp_add_37, // [37] + &&vsp_add_38, // [38] + &&vsp_add_39, // [39] + &&vsp_add_40, // [40] + &&vsp_add_41, // [41] + &&vsp_add_42, // [42] + &&vsp_add_43, // [43] + &&vsp_add_44, // [44] + &&vsp_add_45, // [45] + &&vsp_add_46, // [46] + &&vsp_add_47, // [47] + &&vsp_add_48, // [48] + &&vsp_add_49, // [49] + &&vsp_add_50, // [50] + &&vsp_add_51, // [51] + &&vsp_add_52, // [52] + &&vsp_add_53, // [53] + &&vsp_add_54, // [54] + &&vsp_add_55, // [55] + &&vsp_add_56, // [56] + &&vsp_add_57, // [57] + &&vsp_add_58, // [58] + &&vsp_add_59, // [59] + &&vsp_add_60, // [60] + &&vsp_add_61, // [61] + &&vsp_add_62, // [62] + &&vsp_add_63, // [63] + + &&vsp_sub_0, // [64] + &&vsp_sub_1, // [65] + &&vsp_sub_2, // [66] + &&vsp_sub_3, // [67] + &&vsp_sub_4, // [68] + &&vsp_sub_5, // [69] + &&vsp_sub_6, // [70] + &&vsp_sub_7, // [71] + &&vsp_sub_8, // [72] + &&vsp_sub_9, // [73] + &&vsp_sub_10, // [74] + &&vsp_sub_11, // [75] + &&vsp_sub_12, // [76] + &&vsp_sub_13, // [77] + &&vsp_sub_14, // [78] + &&vsp_sub_15, // [79] + &&vsp_sub_16, // [80] + &&vsp_sub_17, // [81] + &&vsp_sub_18, // [82] + &&vsp_sub_19, // [83] + &&vsp_sub_20, // [84] + &&vsp_sub_21, // [85] + &&vsp_sub_22, // [86] + &&vsp_sub_23, // [87] + &&vsp_sub_24, // [88] + &&vsp_sub_25, // [89] + &&vsp_sub_26, // [90] + &&vsp_sub_27, // [91] + &&vsp_sub_28, // [92] + &&vsp_sub_29, // [93] + &&vsp_sub_30, // [94] + &&vsp_sub_31, // [95] + &&vsp_sub_32, // [96] + &&vsp_sub_33, // [97] + &&vsp_sub_34, // [98] + &&vsp_sub_35, // [99] + &&vsp_sub_36, // [100] + &&vsp_sub_37, // [101] + &&vsp_sub_38, // [102] + &&vsp_sub_39, // [103] + &&vsp_sub_40, // [104] + &&vsp_sub_41, // [105] + &&vsp_sub_42, // [106] + &&vsp_sub_43, // [107] + &&vsp_sub_44, // [108] + &&vsp_sub_45, // [109] + &&vsp_sub_46, // [110] + &&vsp_sub_47, // [111] + &&vsp_sub_48, // [112] + &&vsp_sub_49, // [113] + &&vsp_sub_50, // [114] + &&vsp_sub_51, // [115] + &&vsp_sub_52, // [116] + &&vsp_sub_53, // [117] + &&vsp_sub_54, // [118] + &&vsp_sub_55, // [119] + &&vsp_sub_56, // [120] + &&vsp_sub_57, // [121] + &&vsp_sub_58, // [122] + &&vsp_sub_59, // [123] + &&vsp_sub_60, // [124] + &&vsp_sub_61, // [125] + &&vsp_sub_62, // [126] + &&vsp_sub_63, // [127] + + // 10000000 + &&refuse_unwind_or_pop, // [0b1000'0000 = 128] + + // 1000iiii ... + &&pop_under_mask, // [0b1000'0001 = 129] + &&pop_under_mask, // [0b1000'0010 = 130] + &&pop_under_mask, // [0b1000'0011 = 131] + &&pop_under_mask, // [0b1000'0100 = 132] + &&pop_under_mask, // [0b1000'0101 = 133] + &&pop_under_mask, // [0b1000'0110 = 134] + &&pop_under_mask, // [0b1000'0111 = 135] + &&pop_under_mask, // [0b1000'1000 = 136] + &&pop_under_mask, // [0b1000'1001 = 137] + &&pop_under_mask, // [0b1000'1010 = 138] + &&pop_under_mask, // [0b1000'1011 = 139] + &&pop_under_mask, // [0b1000'1100 = 140] + &&pop_under_mask, // [0b1000'1101 = 141] + &&pop_under_mask, // [0b1000'1110 = 142] + &&pop_under_mask, // [0b1000'1111 = 143] (128 + 15) + + // 1001nnnn + // TODO: Split up assignments to make them faster + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0000 = 144] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0001 = 145] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0010 = 146] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0011 = 147] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0100 = 148] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0101 = 149] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0110 = 150] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0111 = 151] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1000 = 152] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1001 = 153] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1010 = 154] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1011 = 155] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1100 = 156] + // Reserved as prefix for Arm register to register moves + &&reserved_or_spare_thus_terminate, // [0b1001'1101 = 157] + // Reserved as prefix for Intel Wireless MMX register to register moves + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1110 = 158] + &&reserved_or_spare_thus_terminate, // [0b1001'1111 = 159 reg 15 reserved] + + // 10100nnn + &&pop_off_stack_r4_to_r4, // 0b10100'000 [160] + &&pop_off_stack_r4_to_r5, // 0b10100'001 [161] + &&pop_off_stack_r4_to_r6, // 0b10100'010 [162] + &&pop_off_stack_r4_to_r7, // 0b10100'011 [163] + &&pop_off_stack_r4_to_r8, // 0b10100'100 [164] + &&pop_off_stack_r4_to_r9, // 0b10100'101 [165] + &&pop_off_stack_r4_to_r10, // 0b10100'110 [166] + &&pop_off_stack_r4_to_r11, // 0b10100'111 [167] + + // 10101nnn + &&pop_off_stack_r4_to_r4_and_lr, // 0b10101'000 [168] + &&pop_off_stack_r4_to_r5_and_lr, // 0b10101'001 [169] + &&pop_off_stack_r4_to_r6_and_lr, // 0b10101'010 [170] + &&pop_off_stack_r4_to_r7_and_lr, // 0b10101'011 [171] + &&pop_off_stack_r4_to_r8_and_lr, // 0b10101'100 [172] + &&pop_off_stack_r4_to_r9_and_lr, // 0b10101'101 [173] + &&pop_off_stack_r4_to_r10_and_lr, // 0b10101'110 [174] + &&pop_off_stack_r4_to_r11_and_lr, // 0b10101'111 [175] + + // Finish (0xB0) + &&finish_unwind, // 10110000 [176] + + // Spare (refuse unwind) + &&pop_integer_registers_under_mask_r3_r2_r1_r0, // 10110001 [177] + + // Subtract VSP using uleb128 + &&subtract_vsp_using_uleb128, // 10110010 [178] + + // Pop VFP double-precision registers (not supported currently) + &&reserved_or_spare_thus_terminate, // 10110011 [179] + + // Pop Return Address Authentication Code pseudo-register + &&reserved_or_spare_thus_terminate, // 10110100 [180] + + // Use current vsp as modifier in Return Address Authentication + &&reserved_or_spare_thus_terminate, // 10110101 [181] + + // Spare (was Pop FPA) 1011011n + &&reserved_or_spare_thus_terminate, // 10110110 [182] + &&reserved_or_spare_thus_terminate, // 10110111 [183] + + // Pop VFP double-precision registers D[8]-D[8+nnn] saved 10111nnn + &&reserved_or_spare_thus_terminate, // 10111'000 [184] + &&reserved_or_spare_thus_terminate, // 10111'001 [185] + &&reserved_or_spare_thus_terminate, // 10111'010 [186] + &&reserved_or_spare_thus_terminate, // 10111'011 [187] + &&reserved_or_spare_thus_terminate, // 10111'100 [188] + &&reserved_or_spare_thus_terminate, // 10111'101 [189] + &&reserved_or_spare_thus_terminate, // 10111'110 [190] + &&reserved_or_spare_thus_terminate, // 10111'111 [191] + + // Intel Wireless MMX pop wR[10]-wR[10+nnn] 11000nnn + &&reserved_or_spare_thus_terminate, // 11000'000 [192] + &&reserved_or_spare_thus_terminate, // 11000'001 [193] + &&reserved_or_spare_thus_terminate, // 11000'010 [194] + &&reserved_or_spare_thus_terminate, // 11000'011 [195] + &&reserved_or_spare_thus_terminate, // 11000'100 [196] + &&reserved_or_spare_thus_terminate, // 11000'101 [197] + + // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] + &&reserved_or_spare_thus_terminate, // 11000'110 [198] + + // Spare (11000111) + &&reserved_or_spare_thus_terminate, // 11000'111 [199] + + // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by + // VPUSH (11001000) + &&reserved_or_spare_thus_terminate, // 11001000 [200] + + // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by + // VPUSH (11001001) + &&reserved_or_spare_thus_terminate, // 11001001 [201] + + // Spare (yyy != 000, 001) 11001yyy + &&reserved_or_spare_thus_terminate, // 11001'010 [202] + &&reserved_or_spare_thus_terminate, // 11001'011 [203] + &&reserved_or_spare_thus_terminate, // 11001'100 [204] + &&reserved_or_spare_thus_terminate, // 11001'101 [205] + &&reserved_or_spare_thus_terminate, // 11001'110 [206] + &&reserved_or_spare_thus_terminate, // 11001'111 [207] + + // Pop VFP double-precision registers D[8]-D[8+nnn] saved by VPUSH 11010nnn + &&reserved_or_spare_thus_terminate, // 11010'000 [208] + &&reserved_or_spare_thus_terminate, // 11010'001 [209] + &&reserved_or_spare_thus_terminate, // 11010'010 [210] + &&reserved_or_spare_thus_terminate, // 11010'011 [211] + &&reserved_or_spare_thus_terminate, // 11010'100 [212] + &&reserved_or_spare_thus_terminate, // 11010'101 [213] + &&reserved_or_spare_thus_terminate, // 11010'110 [214] + &&reserved_or_spare_thus_terminate, // 11010'111 [215] + + // Spare (xxx != 000, 001, 010) 11xxxyyy + + &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [] + &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [] + &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [] + &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [] + + &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + &&reserved_or_spare_thus_terminate, // 11111'111 [] + + }; + auto& virtual_cpu = p_exception_object.cpu; - bool set_pc = false; + bool move_lr_to_pc = true; + std::uint32_t u32_storage = 0; + auto const* instruction_ptr = p_instructions.data.data(); + + while (true) { + goto* jump_table[*instruction_ptr++]; + + // +=========================================================================+ + // | Finish! | + // +=========================================================================+ + finish_unwind: + [[likely]] if (move_lr_to_pc) { + virtual_cpu.pc = virtual_cpu.lr; + } + break; - for (auto instruction = p_instructions.begin(); - instruction != p_instructions.end() && *instruction != arm_ehabi::finish; + reserved_or_spare_thus_terminate: + std::terminate(); + break; + + subtract_vsp_using_uleb128: + // TODO(kammce): subtract stack using uleb128 + goto reserved_or_spare_thus_terminate; + + pop_integer_registers_under_mask_r3_r2_r1_r0: + // If the next unwind instruction equals 0, or if the bits from 4 or 7 + // contains any 1s, then its time to terminate + if (*instruction_ptr == 0b0000'0000 || (*instruction_ptr & 0xF0) == 0) { + goto reserved_or_spare_thus_terminate; + } + u32_storage = *(instruction_ptr) & 0xF; + + while (u32_storage) { + // The first bit corresponds to the R0 + std::uint32_t lsb_bit_position = std::countr_zero(u32_storage); + virtual_cpu[lsb_bit_position] = *virtual_cpu.sp; + // Move stack pointer up by 4 bytes + virtual_cpu.sp = virtual_cpu.sp + 4; + // Clear the bit for the lsb_bit_position + u32_storage = u32_storage & ~(1 << lsb_bit_position); + } + + refuse_unwind_or_pop: + // If the next unwind instruction equals 0, then its time to terminate + if (*instruction_ptr == 0b0000'0000) { + goto reserved_or_spare_thus_terminate; + } + + // ************************************************************************* + // !!!! WARNING !!!! + // + // `refuse_unwind_or_pop` MUST BE directly above `pop_under_mask` + // + // refuse_unwind_or_pop ---> [[fallthrough]] --> pop_under_mask + // ************************************************************************* + + pop_under_mask: + // Because this unwind instruction is meant to be rare, we will use a while + // loop here rather than unroll this loop. Unless there is some incentive to + // improve the performance for this instruction. + + // Get the previous instruction and save it to the u32_storage + u32_storage = *(instruction_ptr - 1); + + if (u32_storage & (1 << 3)) { + move_lr_to_pc = false; + } + + while (u32_storage) { + // Get the first 1's distance from the right. We add 12 because the + // mask's first bit represents r4 and increases from there. The first + // byte, the instruction byte, only contains the registers from 12 + // to 15. + std::uint32_t lsb_bit_position = std::countr_zero(u32_storage) + 12U; + virtual_cpu[lsb_bit_position] = *virtual_cpu.sp; + // Move stack pointer up by 4 bytes + virtual_cpu.sp = virtual_cpu.sp + 4; + // Clear the bit for the lsb_bit_position + u32_storage = u32_storage & ~(1 << lsb_bit_position); + } + + u32_storage = *(instruction_ptr); + + while (u32_storage) { + // Get the first 1's distance from the right. We add 4 because the mask's + // first bit represents r4 and increases from there. + std::uint32_t lsb_bit_position = std::countr_zero(u32_storage) + 4U; + virtual_cpu[lsb_bit_position] = *virtual_cpu.sp; + // Move stack pointer up by 4 bytes + virtual_cpu.sp = virtual_cpu.sp + 4; + // Clear the bit for the lsb_bit_position + u32_storage = u32_storage & ~(1 << lsb_bit_position); + } + + continue; + + // +=========================================================================+ + // | VSP = R[nnnn] | + // +=========================================================================+ + assign_to_vsp_to_reg_nnnn: + // Get the current instruction and get all lower 4-bits + u32_storage = *(instruction_ptr - 1U) & 0xF; + virtual_cpu.sp = virtual_cpu[u32_storage]; + continue; + + // +=========================================================================+ + // | Sequentially Pop Registers + LR | + // +=========================================================================+ + pop_off_stack_r4_to_r11_and_lr: + pop_register_range<7, true>(virtual_cpu); + continue; + pop_off_stack_r4_to_r10_and_lr: + pop_register_range<6, true>(virtual_cpu); + continue; + pop_off_stack_r4_to_r9_and_lr: + pop_register_range<5, true>(virtual_cpu); + continue; + pop_off_stack_r4_to_r8_and_lr: + pop_register_range<4, true>(virtual_cpu); + continue; + pop_off_stack_r4_to_r7_and_lr: + pop_register_range<3, true>(virtual_cpu); + continue; + pop_off_stack_r4_to_r6_and_lr: + pop_register_range<2, true>(virtual_cpu); + continue; + pop_off_stack_r4_to_r5_and_lr: + pop_register_range<1, true>(virtual_cpu); + continue; + pop_off_stack_r4_to_r4_and_lr: + pop_register_range<0, true>(virtual_cpu); + continue; + + // +=========================================================================+ + // | Sequentially Pop Registers | + // +=========================================================================+ + pop_off_stack_r4_to_r11: + pop_register_range<7>(virtual_cpu); + continue; + pop_off_stack_r4_to_r10: + pop_register_range<6>(virtual_cpu); + continue; + pop_off_stack_r4_to_r9: + pop_register_range<5>(virtual_cpu); + continue; + pop_off_stack_r4_to_r8: + pop_register_range<4>(virtual_cpu); + continue; + pop_off_stack_r4_to_r7: + pop_register_range<3>(virtual_cpu); + continue; + pop_off_stack_r4_to_r6: + pop_register_range<2>(virtual_cpu); + continue; + pop_off_stack_r4_to_r5: + pop_register_range<1>(virtual_cpu); + continue; + pop_off_stack_r4_to_r4: + pop_register_range<0>(virtual_cpu); + continue; + + // +=========================================================================+ + // | Add VSP | + // +=========================================================================+ + vsp_add_0: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<0>(); + continue; + vsp_add_1: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<1>(); + continue; + vsp_add_2: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<2>(); + continue; + vsp_add_3: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<3>(); + continue; + vsp_add_4: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<4>(); + continue; + vsp_add_5: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<5>(); + continue; + vsp_add_6: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<6>(); + continue; + vsp_add_7: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<7>(); + continue; + vsp_add_8: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<8>(); + continue; + vsp_add_9: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<9>(); + continue; + vsp_add_10: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<10>(); + continue; + vsp_add_11: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<11>(); + continue; + vsp_add_12: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<12>(); + continue; + vsp_add_13: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<13>(); + continue; + vsp_add_14: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<14>(); + continue; + vsp_add_15: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<15>(); + continue; + vsp_add_16: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<16>(); + continue; + vsp_add_17: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<17>(); + continue; + vsp_add_18: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<18>(); + continue; + vsp_add_19: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<19>(); + continue; + vsp_add_20: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<20>(); + continue; + vsp_add_21: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<21>(); + continue; + vsp_add_22: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<22>(); + continue; + vsp_add_23: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<23>(); + continue; + vsp_add_24: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<24>(); + continue; + vsp_add_25: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<25>(); + continue; + vsp_add_26: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<26>(); + continue; + vsp_add_27: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<27>(); + continue; + vsp_add_28: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<28>(); + continue; + vsp_add_29: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<29>(); + continue; + vsp_add_30: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<30>(); + continue; + vsp_add_31: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<31>(); + continue; + vsp_add_32: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<32>(); + continue; + vsp_add_33: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<33>(); + continue; + vsp_add_34: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<34>(); + continue; + vsp_add_35: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<35>(); + continue; + vsp_add_36: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<36>(); + continue; + vsp_add_37: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<37>(); + continue; + vsp_add_38: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<38>(); + continue; + vsp_add_39: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<39>(); + continue; + vsp_add_40: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<40>(); + continue; + vsp_add_41: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<41>(); + continue; + vsp_add_42: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<42>(); + continue; + vsp_add_43: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<43>(); + continue; + vsp_add_44: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<44>(); + continue; + vsp_add_45: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<45>(); + continue; + vsp_add_46: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<46>(); + continue; + vsp_add_47: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<47>(); + continue; + vsp_add_48: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<48>(); + continue; + vsp_add_49: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<49>(); + continue; + vsp_add_50: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<50>(); + continue; + vsp_add_51: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<51>(); + continue; + vsp_add_52: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<52>(); + continue; + vsp_add_53: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<53>(); + continue; + vsp_add_54: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<54>(); + continue; + vsp_add_55: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<55>(); + continue; + vsp_add_56: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<56>(); + continue; + vsp_add_57: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<57>(); + continue; + vsp_add_58: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<58>(); + continue; + vsp_add_59: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<59>(); + continue; + vsp_add_60: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<60>(); + continue; + vsp_add_61: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<61>(); + continue; + vsp_add_62: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<62>(); + continue; + vsp_add_63: + virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<63>(); + continue; + + // +=========================================================================+ + // | Sub VSP | + // +=========================================================================+ + vsp_sub_0: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<0>(); + continue; + vsp_sub_1: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<1>(); + continue; + vsp_sub_2: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<2>(); + continue; + vsp_sub_3: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<3>(); + continue; + vsp_sub_4: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<4>(); + continue; + vsp_sub_5: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<5>(); + continue; + vsp_sub_6: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<6>(); + continue; + vsp_sub_7: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<7>(); + continue; + vsp_sub_8: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<8>(); + continue; + vsp_sub_9: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<9>(); + continue; + vsp_sub_10: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<10>(); + continue; + vsp_sub_11: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<11>(); + continue; + vsp_sub_12: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<12>(); + continue; + vsp_sub_13: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<13>(); + continue; + vsp_sub_14: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<14>(); + continue; + vsp_sub_15: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<15>(); + continue; + vsp_sub_16: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<16>(); + continue; + vsp_sub_17: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<17>(); + continue; + vsp_sub_18: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<18>(); + continue; + vsp_sub_19: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<19>(); + continue; + vsp_sub_20: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<20>(); + continue; + vsp_sub_21: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<21>(); + continue; + vsp_sub_22: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<22>(); + continue; + vsp_sub_23: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<23>(); + continue; + vsp_sub_24: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<24>(); + continue; + vsp_sub_25: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<25>(); + continue; + vsp_sub_26: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<26>(); + continue; + vsp_sub_27: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<27>(); + continue; + vsp_sub_28: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<28>(); + continue; + vsp_sub_29: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<29>(); + continue; + vsp_sub_30: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<30>(); + continue; + vsp_sub_31: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<31>(); + continue; + vsp_sub_32: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<32>(); + continue; + vsp_sub_33: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<33>(); + continue; + vsp_sub_34: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<34>(); + continue; + vsp_sub_35: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<35>(); + continue; + vsp_sub_36: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<36>(); + continue; + vsp_sub_37: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<37>(); + continue; + vsp_sub_38: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<38>(); + continue; + vsp_sub_39: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<39>(); + continue; + vsp_sub_40: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<40>(); + continue; + vsp_sub_41: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<41>(); + continue; + vsp_sub_42: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<42>(); + continue; + vsp_sub_43: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<43>(); + continue; + vsp_sub_44: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<44>(); + continue; + vsp_sub_45: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<45>(); + continue; + vsp_sub_46: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<46>(); + continue; + vsp_sub_47: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<47>(); + continue; + vsp_sub_48: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<48>(); + continue; + vsp_sub_49: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<49>(); + continue; + vsp_sub_50: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<50>(); + continue; + vsp_sub_51: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<51>(); + continue; + vsp_sub_52: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<52>(); + continue; + vsp_sub_53: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<53>(); + continue; + vsp_sub_54: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<54>(); + continue; + vsp_sub_55: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<55>(); + continue; + vsp_sub_56: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<56>(); + continue; + vsp_sub_57: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<57>(); + continue; + vsp_sub_58: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<58>(); + continue; + vsp_sub_59: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<59>(); + continue; + vsp_sub_60: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<60>(); + continue; + vsp_sub_61: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<61>(); + continue; + vsp_sub_62: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<62>(); + continue; + vsp_sub_63: + virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<63>(); + continue; + } + +#if 0 + // +========================================================================== + // | OLD STUFF + // +========================================================================== + for (auto instruction = p_instructions.data.begin(); + instruction != p_instructions.data.end() && + *instruction != arm_ehabi::finish; instruction++) { // Extract the first 4 bits int main_bits = (*instruction & 0b11110000) >> 4; @@ -571,9 +1529,10 @@ void unwind_frame(instructions_t const& p_instructions, } exit_loop: - if (!set_pc) { + if (!move_lr_to_pc) { virtual_cpu.pc = virtual_cpu.lr; } +#endif } instructions_t create_instructions_from_entry(index_entry_t const& p_entry) @@ -581,11 +1540,7 @@ instructions_t create_instructions_from_entry(index_entry_t const& p_entry) constexpr auto personality_type = hal::bit_mask::from<24, 27>(); constexpr auto generic = hal::bit_mask::from<31>(); - instructions_t instructions{}; - - // Fill the whole thing with finish flags such that the code below only - // needs to overwrite the values from the start. - instructions.fill(arm_ehabi::finish); + instructions_t unwind{}; std::uint32_t const* handler_data = nullptr; @@ -600,31 +1555,31 @@ instructions_t create_instructions_from_entry(index_entry_t const& p_entry) std::uint32_t header = handler_data[0]; if (hal::bit_extract(header) == 0x0) { - instructions[0] = hal::bit_extract(header); - instructions[1] = hal::bit_extract(header); - instructions[2] = hal::bit_extract(header); + unwind.data[0] = hal::bit_extract(header); + unwind.data[1] = hal::bit_extract(header); + unwind.data[2] = hal::bit_extract(header); } else { std::uint32_t first_word = handler_data[1]; std::uint32_t length = hal::bit_extract(header); switch (length) { case 1: { - instructions[0] = hal::bit_extract(header); - instructions[1] = hal::bit_extract(header); - instructions[2] = hal::bit_extract(first_word); - instructions[3] = hal::bit_extract(first_word); - instructions[4] = hal::bit_extract(first_word); - instructions[5] = hal::bit_extract(first_word); + unwind.data[0] = hal::bit_extract(header); + unwind.data[1] = hal::bit_extract(header); + unwind.data[2] = hal::bit_extract(first_word); + unwind.data[3] = hal::bit_extract(first_word); + unwind.data[4] = hal::bit_extract(first_word); + unwind.data[5] = hal::bit_extract(first_word); break; } case 2: { uint32_t last_word = handler_data[2]; - instructions[0] = hal::bit_extract(header); - instructions[1] = hal::bit_extract(header); - instructions[2] = hal::bit_extract(first_word); - instructions[3] = hal::bit_extract(first_word); - instructions[4] = hal::bit_extract(first_word); - instructions[5] = hal::bit_extract(first_word); - instructions[6] = hal::bit_extract(last_word); + unwind.data[0] = hal::bit_extract(header); + unwind.data[1] = hal::bit_extract(header); + unwind.data[2] = hal::bit_extract(first_word); + unwind.data[3] = hal::bit_extract(first_word); + unwind.data[4] = hal::bit_extract(first_word); + unwind.data[5] = hal::bit_extract(first_word); + unwind.data[6] = hal::bit_extract(last_word); break; } default: { @@ -636,18 +1591,18 @@ instructions_t create_instructions_from_entry(index_entry_t const& p_entry) // assume that 0xB1 is the first instruction, then 0x08, then 0x84 // 0x00. This works. So when we see this mix, we just collect // instructions in that order as if it were a 2-word PR0. - instructions[0] = hal::bit_extract(header); - instructions[1] = hal::bit_extract(header); - instructions[2] = hal::bit_extract(header); - instructions[3] = hal::bit_extract(first_word); - instructions[4] = hal::bit_extract(first_word); - instructions[5] = hal::bit_extract(first_word); - instructions[6] = hal::bit_extract(first_word); + unwind.data[0] = hal::bit_extract(header); + unwind.data[1] = hal::bit_extract(header); + unwind.data[2] = hal::bit_extract(header); + unwind.data[3] = hal::bit_extract(first_word); + unwind.data[4] = hal::bit_extract(first_word); + unwind.data[5] = hal::bit_extract(first_word); + unwind.data[6] = hal::bit_extract(first_word); } } } - return instructions; + return unwind; } void raise_exception(exception_object& p_exception_object) @@ -750,18 +1705,21 @@ extern "C" exception_object.cache.rethrown(true); // Perform an inline trivial unwind __cxa_throw: -#if defined(OPTIMIZATION_LEVEL) || 1 -#if OPTIMIZATION_LEVEL == Debug || 0 +#if defined(OPTIMIZATION_LEVEL) +#if OPTIMIZATION_LEVEL == Debug std::uint32_t const* stack_pointer = *exception_object.cpu.sp; stack_pointer += 5; exception_object.cpu.pc = stack_pointer[0]; exception_object.cpu.sp = stack_pointer + 1; -#elif OPTIMIZATION_LEVEL == MinSizeRel || 1 +#elif OPTIMIZATION_LEVEL == MinSizeRel std::uint32_t const* stack_pointer = *exception_object.cpu.sp; exception_object.cpu.r4 = stack_pointer[0]; exception_object.cpu.pc = stack_pointer[1]; exception_object.cpu.sp = stack_pointer + 2; -#elif OPTIMIZATION_LEVEL == Release || 0 +#elif OPTIMIZATION_LEVEL == Release +#error "Sorry Release mode unwinding is not supported yet."; +#elif OPTIMIZATION_LEVEL == RelWithDebInfo +#error "Sorry Release mode unwinding is not supported yet."; #endif #endif @@ -795,6 +1753,9 @@ extern "C" exception_object.cpu.pc = stack_pointer[1]; exception_object.cpu.sp = stack_pointer + 2; #elif OPTIMIZATION_LEVEL == Release +#error "Sorry Release mode unwinding is not supported yet."; +#elif OPTIMIZATION_LEVEL == RelWithDebInfo +#error "Sorry Release mode unwinding is not supported yet."; #endif #endif diff --git a/src/arm_cortex/estell/internal.hpp b/src/arm_cortex/estell/internal.hpp index 3165b3e..9998d6d 100644 --- a/src/arm_cortex/estell/internal.hpp +++ b/src/arm_cortex/estell/internal.hpp @@ -242,50 +242,6 @@ inline void* extract_thrown_object(void* p_exception_object) return reinterpret_cast(start_of_thrown); } -[[gnu::always_inline]] inline void restore_cpu_core( - ke::cortex_m_cpu& p_cpu_core) -{ - asm volatile( - "ldr r0, [%[regs], #0]\n" // Load R0 - "ldr r1, [%[regs], #4]\n" // Load R1 - "ldr r2, [%[regs], #8]\n" // Load R2 - // "ldr r3, [%[regs], #12]\n" // Load R3 - "ldr r4, [%[regs], #16]\n" // Load R4 - "ldr r5, [%[regs], #20]\n" // Load R5 - "ldr r6, [%[regs], #24]\n" // Load R6 - "ldr r7, [%[regs], #28]\n" // Load R7 - "ldr r8, [%[regs], #32]\n" // Load R8 - "ldr r9, [%[regs], #36]\n" // Load R9 - "ldr r10, [%[regs], #40]\n" // Load R10 - "ldr r11, [%[regs], #44]\n" // Load R11 - "ldr r12, [%[regs], #48]\n" // Load R12 - // Stack Pointer (R13/SP) and Link Register (R14/LR) require special - // handling - "ldr sp, [%[regs], #52]\n" // Load SP - "ldr lr, [%[regs], #56]\n" // Load LR - // PC and xPSR restoration is more complex due to ARM's execution state and - // alignment requirements Directly loading PC can be dangerous and is - // typically managed through a pop or an exception return mechanism - "ldr pc, [%[regs], #60]\n" - : - : [regs] "r"(&p_cpu_core) - : "memory", - "r0", - "r1", - "r2", - // "r3", - "r4", - "r5", - "r6", - "r7", - "fp", - "r8", - "r9", - "r10", - "r11", - "r12"); -} - std::uint32_t to_absolute_address(void const* p_object) { constexpr auto signed_bit_31 = hal::bit_mask::from<30>(); From d272fad2ae8ecff7fb1aa898baefd77223ab6449 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Wed, 17 Jul 2024 11:15:36 -0700 Subject: [PATCH 02/14] :zap: Jump table working. May have bugs --- src/arm_cortex/estell/exception.cpp | 416 +++++++++++++++------------- src/arm_cortex/estell/internal.hpp | 4 +- 2 files changed, 222 insertions(+), 198 deletions(-) diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index 34abd09..46f75dd 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -199,7 +199,7 @@ void pop_registers(cortex_m_cpu& p_cpu, std::uint32_t mask) p_cpu.sp = stack_pointer; } -std::uint32_t read_uleb128(std::uint8_t const volatile** p_ptr) +std::uint32_t read_uleb128(std::uint8_t const** p_ptr) { std::uint32_t result = 0; std::uint8_t shift_amount = 0; @@ -266,10 +266,10 @@ personality_encoding operator&(personality_encoding const& p_encoding, static_cast(p_encoding) & static_cast(p_byte)); } -std::uintptr_t read_encoded_data(std::uint8_t const volatile** p_data, +std::uintptr_t read_encoded_data(std::uint8_t const** p_data, personality_encoding p_encoding) { - std::uint8_t const volatile* ptr = *p_data; + std::uint8_t const* ptr = *p_data; std::uintptr_t result = 0; auto const encoding = static_cast(p_encoding); @@ -435,9 +435,8 @@ inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) void enter_function(exception_object& p_exception_object) { - std::uint8_t const volatile* lsda_data = - reinterpret_cast( - p_exception_object.cache.entry_ptr->lsda_data()); + std::uint8_t const* lsda_data = reinterpret_cast( + p_exception_object.cache.entry_ptr->lsda_data()); auto const dwarf_offset_info_format = personality_encoding{ *(lsda_data++) }; if (dwarf_offset_info_format != personality_encoding::omit) { @@ -492,48 +491,67 @@ void enter_function(exception_object& p_exception_object) } template -std::uint32_t vsp_deallocate_amount() +constexpr std::uint32_t vsp_deallocate_amount() { - return (Amount << 2) + 4; + return (Amount << 2); } -template -inline void pop_register_range(cortex_m_cpu& p_virtual_cpu) +enum class pop_lr { - if constexpr (PopLinkRegister == 7) { - p_virtual_cpu.lr = (*p_virtual_cpu.sp)[PopCount + 1]; + skip = 0, + do_it = 1, +}; + +template +[[nodiscard("You MUST set the unwind function's stack pointer to this " + "value after executing it!")]] +inline std::uint32_t const* pop_register_range(std::uint32_t const* sp_ptr, + cortex_m_cpu& p_virtual_cpu) +{ + // We pull these pointers out in order to access them incrementally, which + // will give the hint to the compiler to convert them into a sequence of + // immediate load and stores. + auto* r4_pointer = &p_virtual_cpu.r4.data; + + static_assert(PopCount <= 7, "Pop Count cannot be above 7"); + + // NOTE: A for loop has the same cycle count, and is more compact +#if 0 + if constexpr (PopCount >= 0) { + *(r4_pointer++) = *(sp_ptr++); } - if constexpr (PopCount == 7) { - p_virtual_cpu[11] = (*p_virtual_cpu.sp)[7]; + if constexpr (PopCount >= 1) { + *(r4_pointer++) = *(sp_ptr++); } - if constexpr (PopCount >= 6) { - p_virtual_cpu[10] = (*p_virtual_cpu.sp)[6]; + if constexpr (PopCount >= 2) { + *(r4_pointer++) = *(sp_ptr++); } - if constexpr (PopCount >= 5) { - p_virtual_cpu[9] = (*p_virtual_cpu.sp)[5]; + if constexpr (PopCount >= 3) { + *(r4_pointer++) = *(sp_ptr++); } if constexpr (PopCount >= 4) { - p_virtual_cpu[8] = (*p_virtual_cpu.sp)[4]; + *(r4_pointer++) = *(sp_ptr++); } - if constexpr (PopCount >= 3) { - p_virtual_cpu[7] = (*p_virtual_cpu.sp)[3]; + if constexpr (PopCount >= 5) { + *(r4_pointer++) = *(sp_ptr++); } - if constexpr (PopCount >= 2) { - p_virtual_cpu[6] = (*p_virtual_cpu.sp)[2]; + if constexpr (PopCount >= 6) { + *(r4_pointer++) = *(sp_ptr++); } - if constexpr (PopCount >= 1) { - p_virtual_cpu[5] = (*p_virtual_cpu.sp)[1]; + if constexpr (PopCount == 7) { + *(r4_pointer++) = *(sp_ptr++); } - if constexpr (PopCount >= 0) { - p_virtual_cpu[4] = (*p_virtual_cpu.sp)[0]; +#else + for (std::size_t i = 0; i < PopCount + 1; i++) { + *(r4_pointer++) = *(sp_ptr++); } +#endif - // Move the stack up by the number of registers we popped plus 1 to place it - // in the previous function's frame. - static constexpr auto stack_offset = - 4U * (PopCount + 1U + unsigned{ PopLinkRegister }); + if constexpr (PopLinkRegister == pop_lr::do_it) { + p_virtual_cpu.lr = *(sp_ptr++); + } - p_virtual_cpu.sp = p_virtual_cpu.sp + stack_offset; + return sp_ptr; } void unwind_frame(instructions_t const& p_instructions, @@ -805,7 +823,7 @@ void unwind_frame(instructions_t const& p_instructions, // Spare (xxx != 000, 001, 010) 11xxxyyy - &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'000 [216] &&reserved_or_spare_thus_terminate, // 11011'001 [] &&reserved_or_spare_thus_terminate, // 11011'010 [] &&reserved_or_spare_thus_terminate, // 11011'011 [] @@ -820,7 +838,7 @@ void unwind_frame(instructions_t const& p_instructions, &&reserved_or_spare_thus_terminate, // 11011'100 [] &&reserved_or_spare_thus_terminate, // 11011'101 [] &&reserved_or_spare_thus_terminate, // 11011'110 [] - &&reserved_or_spare_thus_terminate, // 11011'111 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [231] &&reserved_or_spare_thus_terminate, // 11011'000 [] &&reserved_or_spare_thus_terminate, // 11011'001 [] &&reserved_or_spare_thus_terminate, // 11011'010 [] @@ -836,16 +854,16 @@ void unwind_frame(instructions_t const& p_instructions, &&reserved_or_spare_thus_terminate, // 11011'100 [] &&reserved_or_spare_thus_terminate, // 11011'101 [] &&reserved_or_spare_thus_terminate, // 11011'110 [] - &&reserved_or_spare_thus_terminate, // 11011'111 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [247] - &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'000 [248] &&reserved_or_spare_thus_terminate, // 11011'001 [] &&reserved_or_spare_thus_terminate, // 11011'010 [] &&reserved_or_spare_thus_terminate, // 11011'011 [] &&reserved_or_spare_thus_terminate, // 11011'100 [] &&reserved_or_spare_thus_terminate, // 11011'101 [] &&reserved_or_spare_thus_terminate, // 11011'110 [] - &&reserved_or_spare_thus_terminate, // 11111'111 [] + &&reserved_or_spare_thus_terminate, // 11111'111 [255] }; @@ -853,14 +871,18 @@ void unwind_frame(instructions_t const& p_instructions, bool move_lr_to_pc = true; std::uint32_t u32_storage = 0; auto const* instruction_ptr = p_instructions.data.data(); + auto const* sp_ptr = *virtual_cpu.sp; while (true) { - goto* jump_table[*instruction_ptr++]; + auto const* jump_location = jump_table[*instruction_ptr]; + instruction_ptr++; + goto* jump_location; // +=========================================================================+ // | Finish! | // +=========================================================================+ finish_unwind: + virtual_cpu.sp = sp_ptr; [[likely]] if (move_lr_to_pc) { virtual_cpu.pc = virtual_cpu.lr; } @@ -871,26 +893,29 @@ void unwind_frame(instructions_t const& p_instructions, break; subtract_vsp_using_uleb128: - // TODO(kammce): subtract stack using uleb128 - goto reserved_or_spare_thus_terminate; + u32_storage = read_uleb128(&instruction_ptr); + sp_ptr += u32_storage; + continue; pop_integer_registers_under_mask_r3_r2_r1_r0: // If the next unwind instruction equals 0, or if the bits from 4 or 7 // contains any 1s, then its time to terminate - if (*instruction_ptr == 0b0000'0000 || (*instruction_ptr & 0xF0) == 0) { + if (*instruction_ptr == 0b0000'0000 || (*instruction_ptr & 0xF0) != 0) { goto reserved_or_spare_thus_terminate; } - u32_storage = *(instruction_ptr) & 0xF; + + u32_storage = *instruction_ptr; while (u32_storage) { // The first bit corresponds to the R0 std::uint32_t lsb_bit_position = std::countr_zero(u32_storage); - virtual_cpu[lsb_bit_position] = *virtual_cpu.sp; - // Move stack pointer up by 4 bytes - virtual_cpu.sp = virtual_cpu.sp + 4; + // Copy value from the stack, increment stack pointer. + virtual_cpu[lsb_bit_position] = *(sp_ptr++); // Clear the bit for the lsb_bit_position u32_storage = u32_storage & ~(1 << lsb_bit_position); } + instruction_ptr++; + continue; refuse_unwind_or_pop: // If the next unwind instruction equals 0, then its time to terminate @@ -924,9 +949,8 @@ void unwind_frame(instructions_t const& p_instructions, // byte, the instruction byte, only contains the registers from 12 // to 15. std::uint32_t lsb_bit_position = std::countr_zero(u32_storage) + 12U; - virtual_cpu[lsb_bit_position] = *virtual_cpu.sp; - // Move stack pointer up by 4 bytes - virtual_cpu.sp = virtual_cpu.sp + 4; + // Copy value from the stack, increment stack pointer. + virtual_cpu[lsb_bit_position] = *(sp_ptr++); // Clear the bit for the lsb_bit_position u32_storage = u32_storage & ~(1 << lsb_bit_position); } @@ -937,13 +961,13 @@ void unwind_frame(instructions_t const& p_instructions, // Get the first 1's distance from the right. We add 4 because the mask's // first bit represents r4 and increases from there. std::uint32_t lsb_bit_position = std::countr_zero(u32_storage) + 4U; - virtual_cpu[lsb_bit_position] = *virtual_cpu.sp; - // Move stack pointer up by 4 bytes - virtual_cpu.sp = virtual_cpu.sp + 4; + // Copy value from the stack, increment stack pointer. + virtual_cpu[lsb_bit_position] = *(sp_ptr++); // Clear the bit for the lsb_bit_position u32_storage = u32_storage & ~(1 << lsb_bit_position); } + instruction_ptr++; continue; // +=========================================================================+ @@ -952,455 +976,455 @@ void unwind_frame(instructions_t const& p_instructions, assign_to_vsp_to_reg_nnnn: // Get the current instruction and get all lower 4-bits u32_storage = *(instruction_ptr - 1U) & 0xF; - virtual_cpu.sp = virtual_cpu[u32_storage]; + sp_ptr = *virtual_cpu[u32_storage]; continue; // +=========================================================================+ // | Sequentially Pop Registers + LR | // +=========================================================================+ pop_off_stack_r4_to_r11_and_lr: - pop_register_range<7, true>(virtual_cpu); + sp_ptr = pop_register_range<7, pop_lr::do_it>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r10_and_lr: - pop_register_range<6, true>(virtual_cpu); + sp_ptr = pop_register_range<6, pop_lr::do_it>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r9_and_lr: - pop_register_range<5, true>(virtual_cpu); + sp_ptr = pop_register_range<5, pop_lr::do_it>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r8_and_lr: - pop_register_range<4, true>(virtual_cpu); + sp_ptr = pop_register_range<4, pop_lr::do_it>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r7_and_lr: - pop_register_range<3, true>(virtual_cpu); + sp_ptr = pop_register_range<3, pop_lr::do_it>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r6_and_lr: - pop_register_range<2, true>(virtual_cpu); + sp_ptr = pop_register_range<2, pop_lr::do_it>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r5_and_lr: - pop_register_range<1, true>(virtual_cpu); + sp_ptr = pop_register_range<1, pop_lr::do_it>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r4_and_lr: - pop_register_range<0, true>(virtual_cpu); + sp_ptr = pop_register_range<0, pop_lr::do_it>(sp_ptr, virtual_cpu); continue; // +=========================================================================+ // | Sequentially Pop Registers | // +=========================================================================+ pop_off_stack_r4_to_r11: - pop_register_range<7>(virtual_cpu); + sp_ptr = pop_register_range<7>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r10: - pop_register_range<6>(virtual_cpu); + sp_ptr = pop_register_range<6>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r9: - pop_register_range<5>(virtual_cpu); + sp_ptr = pop_register_range<5>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r8: - pop_register_range<4>(virtual_cpu); + sp_ptr = pop_register_range<4>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r7: - pop_register_range<3>(virtual_cpu); + sp_ptr = pop_register_range<3>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r6: - pop_register_range<2>(virtual_cpu); + sp_ptr = pop_register_range<2>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r5: - pop_register_range<1>(virtual_cpu); + sp_ptr = pop_register_range<1>(sp_ptr, virtual_cpu); continue; pop_off_stack_r4_to_r4: - pop_register_range<0>(virtual_cpu); + sp_ptr = pop_register_range<0>(sp_ptr, virtual_cpu); continue; // +=========================================================================+ // | Add VSP | // +=========================================================================+ vsp_add_0: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<0>(); + sp_ptr += vsp_deallocate_amount<0>(); continue; vsp_add_1: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<1>(); + sp_ptr += vsp_deallocate_amount<1>(); continue; vsp_add_2: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<2>(); + sp_ptr += vsp_deallocate_amount<2>(); continue; vsp_add_3: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<3>(); + sp_ptr += vsp_deallocate_amount<3>(); continue; vsp_add_4: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<4>(); + sp_ptr += vsp_deallocate_amount<4>(); continue; vsp_add_5: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<5>(); + sp_ptr += vsp_deallocate_amount<5>(); continue; vsp_add_6: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<6>(); + sp_ptr += vsp_deallocate_amount<6>(); continue; vsp_add_7: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<7>(); + sp_ptr += vsp_deallocate_amount<7>(); continue; vsp_add_8: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<8>(); + sp_ptr += vsp_deallocate_amount<8>(); continue; vsp_add_9: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<9>(); + sp_ptr += vsp_deallocate_amount<9>(); continue; vsp_add_10: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<10>(); + sp_ptr += vsp_deallocate_amount<10>(); continue; vsp_add_11: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<11>(); + sp_ptr += vsp_deallocate_amount<11>(); continue; vsp_add_12: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<12>(); + sp_ptr += vsp_deallocate_amount<12>(); continue; vsp_add_13: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<13>(); + sp_ptr += vsp_deallocate_amount<13>(); continue; vsp_add_14: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<14>(); + sp_ptr += vsp_deallocate_amount<14>(); continue; vsp_add_15: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<15>(); + sp_ptr += vsp_deallocate_amount<15>(); continue; vsp_add_16: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<16>(); + sp_ptr += vsp_deallocate_amount<16>(); continue; vsp_add_17: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<17>(); + sp_ptr += vsp_deallocate_amount<17>(); continue; vsp_add_18: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<18>(); + sp_ptr += vsp_deallocate_amount<18>(); continue; vsp_add_19: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<19>(); + sp_ptr += vsp_deallocate_amount<19>(); continue; vsp_add_20: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<20>(); + sp_ptr += vsp_deallocate_amount<20>(); continue; vsp_add_21: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<21>(); + sp_ptr += vsp_deallocate_amount<21>(); continue; vsp_add_22: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<22>(); + sp_ptr += vsp_deallocate_amount<22>(); continue; vsp_add_23: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<23>(); + sp_ptr += vsp_deallocate_amount<23>(); continue; vsp_add_24: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<24>(); + sp_ptr += vsp_deallocate_amount<24>(); continue; vsp_add_25: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<25>(); + sp_ptr += vsp_deallocate_amount<25>(); continue; vsp_add_26: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<26>(); + sp_ptr += vsp_deallocate_amount<26>(); continue; vsp_add_27: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<27>(); + sp_ptr += vsp_deallocate_amount<27>(); continue; vsp_add_28: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<28>(); + sp_ptr += vsp_deallocate_amount<28>(); continue; vsp_add_29: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<29>(); + sp_ptr += vsp_deallocate_amount<29>(); continue; vsp_add_30: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<30>(); + sp_ptr += vsp_deallocate_amount<30>(); continue; vsp_add_31: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<31>(); + sp_ptr += vsp_deallocate_amount<31>(); continue; vsp_add_32: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<32>(); + sp_ptr += vsp_deallocate_amount<32>(); continue; vsp_add_33: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<33>(); + sp_ptr += vsp_deallocate_amount<33>(); continue; vsp_add_34: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<34>(); + sp_ptr += vsp_deallocate_amount<34>(); continue; vsp_add_35: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<35>(); + sp_ptr += vsp_deallocate_amount<35>(); continue; vsp_add_36: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<36>(); + sp_ptr += vsp_deallocate_amount<36>(); continue; vsp_add_37: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<37>(); + sp_ptr += vsp_deallocate_amount<37>(); continue; vsp_add_38: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<38>(); + sp_ptr += vsp_deallocate_amount<38>(); continue; vsp_add_39: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<39>(); + sp_ptr += vsp_deallocate_amount<39>(); continue; vsp_add_40: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<40>(); + sp_ptr += vsp_deallocate_amount<40>(); continue; vsp_add_41: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<41>(); + sp_ptr += vsp_deallocate_amount<41>(); continue; vsp_add_42: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<42>(); + sp_ptr += vsp_deallocate_amount<42>(); continue; vsp_add_43: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<43>(); + sp_ptr += vsp_deallocate_amount<43>(); continue; vsp_add_44: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<44>(); + sp_ptr += vsp_deallocate_amount<44>(); continue; vsp_add_45: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<45>(); + sp_ptr += vsp_deallocate_amount<45>(); continue; vsp_add_46: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<46>(); + sp_ptr += vsp_deallocate_amount<46>(); continue; vsp_add_47: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<47>(); + sp_ptr += vsp_deallocate_amount<47>(); continue; vsp_add_48: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<48>(); + sp_ptr += vsp_deallocate_amount<48>(); continue; vsp_add_49: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<49>(); + sp_ptr += vsp_deallocate_amount<49>(); continue; vsp_add_50: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<50>(); + sp_ptr += vsp_deallocate_amount<50>(); continue; vsp_add_51: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<51>(); + sp_ptr += vsp_deallocate_amount<51>(); continue; vsp_add_52: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<52>(); + sp_ptr += vsp_deallocate_amount<52>(); continue; vsp_add_53: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<53>(); + sp_ptr += vsp_deallocate_amount<53>(); continue; vsp_add_54: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<54>(); + sp_ptr += vsp_deallocate_amount<54>(); continue; vsp_add_55: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<55>(); + sp_ptr += vsp_deallocate_amount<55>(); continue; vsp_add_56: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<56>(); + sp_ptr += vsp_deallocate_amount<56>(); continue; vsp_add_57: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<57>(); + sp_ptr += vsp_deallocate_amount<57>(); continue; vsp_add_58: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<58>(); + sp_ptr += vsp_deallocate_amount<58>(); continue; vsp_add_59: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<59>(); + sp_ptr += vsp_deallocate_amount<59>(); continue; vsp_add_60: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<60>(); + sp_ptr += vsp_deallocate_amount<60>(); continue; vsp_add_61: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<61>(); + sp_ptr += vsp_deallocate_amount<61>(); continue; vsp_add_62: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<62>(); + sp_ptr += vsp_deallocate_amount<62>(); continue; vsp_add_63: - virtual_cpu.sp = virtual_cpu.sp + vsp_deallocate_amount<63>(); + sp_ptr += vsp_deallocate_amount<63>(); continue; // +=========================================================================+ // | Sub VSP | // +=========================================================================+ vsp_sub_0: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<0>(); + sp_ptr -= vsp_deallocate_amount<0>(); continue; vsp_sub_1: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<1>(); + sp_ptr -= vsp_deallocate_amount<1>(); continue; vsp_sub_2: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<2>(); + sp_ptr -= vsp_deallocate_amount<2>(); continue; vsp_sub_3: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<3>(); + sp_ptr -= vsp_deallocate_amount<3>(); continue; vsp_sub_4: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<4>(); + sp_ptr -= vsp_deallocate_amount<4>(); continue; vsp_sub_5: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<5>(); + sp_ptr -= vsp_deallocate_amount<5>(); continue; vsp_sub_6: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<6>(); + sp_ptr -= vsp_deallocate_amount<6>(); continue; vsp_sub_7: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<7>(); + sp_ptr -= vsp_deallocate_amount<7>(); continue; vsp_sub_8: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<8>(); + sp_ptr -= vsp_deallocate_amount<8>(); continue; vsp_sub_9: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<9>(); + sp_ptr -= vsp_deallocate_amount<9>(); continue; vsp_sub_10: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<10>(); + sp_ptr -= vsp_deallocate_amount<10>(); continue; vsp_sub_11: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<11>(); + sp_ptr -= vsp_deallocate_amount<11>(); continue; vsp_sub_12: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<12>(); + sp_ptr -= vsp_deallocate_amount<12>(); continue; vsp_sub_13: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<13>(); + sp_ptr -= vsp_deallocate_amount<13>(); continue; vsp_sub_14: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<14>(); + sp_ptr -= vsp_deallocate_amount<14>(); continue; vsp_sub_15: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<15>(); + sp_ptr -= vsp_deallocate_amount<15>(); continue; vsp_sub_16: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<16>(); + sp_ptr -= vsp_deallocate_amount<16>(); continue; vsp_sub_17: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<17>(); + sp_ptr -= vsp_deallocate_amount<17>(); continue; vsp_sub_18: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<18>(); + sp_ptr -= vsp_deallocate_amount<18>(); continue; vsp_sub_19: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<19>(); + sp_ptr -= vsp_deallocate_amount<19>(); continue; vsp_sub_20: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<20>(); + sp_ptr -= vsp_deallocate_amount<20>(); continue; vsp_sub_21: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<21>(); + sp_ptr -= vsp_deallocate_amount<21>(); continue; vsp_sub_22: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<22>(); + sp_ptr -= vsp_deallocate_amount<22>(); continue; vsp_sub_23: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<23>(); + sp_ptr -= vsp_deallocate_amount<23>(); continue; vsp_sub_24: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<24>(); + sp_ptr -= vsp_deallocate_amount<24>(); continue; vsp_sub_25: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<25>(); + sp_ptr -= vsp_deallocate_amount<25>(); continue; vsp_sub_26: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<26>(); + sp_ptr -= vsp_deallocate_amount<26>(); continue; vsp_sub_27: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<27>(); + sp_ptr -= vsp_deallocate_amount<27>(); continue; vsp_sub_28: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<28>(); + sp_ptr -= vsp_deallocate_amount<28>(); continue; vsp_sub_29: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<29>(); + sp_ptr -= vsp_deallocate_amount<29>(); continue; vsp_sub_30: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<30>(); + sp_ptr -= vsp_deallocate_amount<30>(); continue; vsp_sub_31: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<31>(); + sp_ptr -= vsp_deallocate_amount<31>(); continue; vsp_sub_32: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<32>(); + sp_ptr -= vsp_deallocate_amount<32>(); continue; vsp_sub_33: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<33>(); + sp_ptr -= vsp_deallocate_amount<33>(); continue; vsp_sub_34: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<34>(); + sp_ptr -= vsp_deallocate_amount<34>(); continue; vsp_sub_35: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<35>(); + sp_ptr -= vsp_deallocate_amount<35>(); continue; vsp_sub_36: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<36>(); + sp_ptr -= vsp_deallocate_amount<36>(); continue; vsp_sub_37: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<37>(); + sp_ptr -= vsp_deallocate_amount<37>(); continue; vsp_sub_38: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<38>(); + sp_ptr -= vsp_deallocate_amount<38>(); continue; vsp_sub_39: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<39>(); + sp_ptr -= vsp_deallocate_amount<39>(); continue; vsp_sub_40: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<40>(); + sp_ptr -= vsp_deallocate_amount<40>(); continue; vsp_sub_41: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<41>(); + sp_ptr -= vsp_deallocate_amount<41>(); continue; vsp_sub_42: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<42>(); + sp_ptr -= vsp_deallocate_amount<42>(); continue; vsp_sub_43: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<43>(); + sp_ptr -= vsp_deallocate_amount<43>(); continue; vsp_sub_44: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<44>(); + sp_ptr -= vsp_deallocate_amount<44>(); continue; vsp_sub_45: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<45>(); + sp_ptr -= vsp_deallocate_amount<45>(); continue; vsp_sub_46: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<46>(); + sp_ptr -= vsp_deallocate_amount<46>(); continue; vsp_sub_47: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<47>(); + sp_ptr -= vsp_deallocate_amount<47>(); continue; vsp_sub_48: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<48>(); + sp_ptr -= vsp_deallocate_amount<48>(); continue; vsp_sub_49: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<49>(); + sp_ptr -= vsp_deallocate_amount<49>(); continue; vsp_sub_50: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<50>(); + sp_ptr -= vsp_deallocate_amount<50>(); continue; vsp_sub_51: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<51>(); + sp_ptr -= vsp_deallocate_amount<51>(); continue; vsp_sub_52: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<52>(); + sp_ptr -= vsp_deallocate_amount<52>(); continue; vsp_sub_53: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<53>(); + sp_ptr -= vsp_deallocate_amount<53>(); continue; vsp_sub_54: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<54>(); + sp_ptr -= vsp_deallocate_amount<54>(); continue; vsp_sub_55: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<55>(); + sp_ptr -= vsp_deallocate_amount<55>(); continue; vsp_sub_56: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<56>(); + sp_ptr -= vsp_deallocate_amount<56>(); continue; vsp_sub_57: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<57>(); + sp_ptr -= vsp_deallocate_amount<57>(); continue; vsp_sub_58: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<58>(); + sp_ptr -= vsp_deallocate_amount<58>(); continue; vsp_sub_59: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<59>(); + sp_ptr -= vsp_deallocate_amount<59>(); continue; vsp_sub_60: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<60>(); + sp_ptr -= vsp_deallocate_amount<60>(); continue; vsp_sub_61: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<61>(); + sp_ptr -= vsp_deallocate_amount<61>(); continue; vsp_sub_62: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<62>(); + sp_ptr -= vsp_deallocate_amount<62>(); continue; vsp_sub_63: - virtual_cpu.sp = virtual_cpu.sp - vsp_deallocate_amount<63>(); + sp_ptr -= vsp_deallocate_amount<63>(); continue; } diff --git a/src/arm_cortex/estell/internal.hpp b/src/arm_cortex/estell/internal.hpp index 9998d6d..1589d95 100644 --- a/src/arm_cortex/estell/internal.hpp +++ b/src/arm_cortex/estell/internal.hpp @@ -50,9 +50,9 @@ struct register_t return data; } - std::uint32_t const* operator*() + std::uint32_t* operator*() { - return reinterpret_cast(data); + return reinterpret_cast(data); } }; From ff52ae8697dc3d5216f3898c73a520b84e38d1f5 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Wed, 17 Jul 2024 12:12:36 -0700 Subject: [PATCH 03/14] :zap: [[gnu::always_inline]] Many functions - :zap: Carve out a branch for decoding uleb128 call-site information, the most common and encouraged encoding. - :bug: Add `lr` and `pc` to clobber list to ensure that the compiler does not attempt to use the `lr` register to hold the pointer to the virtual_cpu structure - :zap: Move index entry definitions to the header --- src/arm_cortex/estell/exception.cpp | 126 +++++++++------------- src/arm_cortex/estell/internal.hpp | 158 ++++++++++++++++++---------- 2 files changed, 151 insertions(+), 133 deletions(-) diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index 46f75dd..a194fc5 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -14,8 +14,10 @@ #include #include +#include #include #include +#include #include #include "internal.hpp" @@ -78,63 +80,6 @@ inline void capture_cpu_core(ke::cortex_m_cpu& p_cpu_core) ); } -bool index_entry_t::has_inlined_personality() const -{ - // 31st bit is `1` when the personality/unwind information is inlined, other - // otherwise, personality_offset is an offset. - constexpr auto mask = hal::bit_mask::from<31>(); - return hal::bit_extract(personality_offset); -} - -bool index_entry_t::is_noexcept() const -{ - return personality_offset == 0x1; -} - -std::uint32_t const* index_entry_t::personality() const -{ - return to_absolute_address_ptr(&personality_offset); -} - -std::uint32_t const* index_entry_t::lsda_data() const -{ - constexpr auto personality_type = hal::bit_mask::from<24, 27>(); - // +1 to skip the prel31 offset to the personality function - auto const* header = personality() + 1; - if (hal::bit_extract(*header) == 0x0) { - return header + 1; - } - if (hal::bit_extract(*header) == 1) { - return header + 2; - } - if (hal::bit_extract(*header) > 2) { - return header + 2; - } - return header + 3; -} - -std::uint32_t const* index_entry_t::descriptor_start() const -{ - constexpr auto type_mask = hal::bit_mask{ .position = 24, .width = 8 }; - - auto* personality_address = personality(); - auto type = hal::bit_extract(*personality_address); - - // TODO(kammce): comment why each of these works! - if (type == 0x0) { - return personality_address + 1; - } - - // The limit for ARM exceptions instructions is 7. LD optimizes the ARM - // exception spec by removing the "word length" specifier allowing the - // instructions to fit in 2 words. - return personality_address + 2; -} - -function_t index_entry_t::function() const -{ - return function_t(to_absolute_address(&function_offset)); -} struct index_less_than { @@ -178,7 +123,8 @@ index_entry_t const& get_index_entry(std::uint32_t p_program_counter) return *(index - 1); } -void pop_registers(cortex_m_cpu& p_cpu, std::uint32_t mask) +[[gnu::always_inline]] inline void pop_registers(cortex_m_cpu& p_cpu, + std::uint32_t mask) { // The mask may not demand that the stack pointer be popped, but the // stack pointer will still need to be popped anyway, so this check @@ -199,7 +145,8 @@ void pop_registers(cortex_m_cpu& p_cpu, std::uint32_t mask) p_cpu.sp = stack_pointer; } -std::uint32_t read_uleb128(std::uint8_t const** p_ptr) +[[gnu::always_inline]] inline constexpr std::uint32_t read_uleb128( + std::uint8_t const** p_ptr) { std::uint32_t result = 0; std::uint8_t shift_amount = 0; @@ -266,8 +213,9 @@ personality_encoding operator&(personality_encoding const& p_encoding, static_cast(p_encoding) & static_cast(p_byte)); } -std::uintptr_t read_encoded_data(std::uint8_t const** p_data, - personality_encoding p_encoding) +[[gnu::always_inline]] inline std::uintptr_t read_encoded_data( + std::uint8_t const** p_data, + personality_encoding p_encoding) { std::uint8_t const* ptr = *p_data; std::uintptr_t result = 0; @@ -413,14 +361,14 @@ inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) "ldr r12, [%[regs], #48]\n" // Load R12 "ldr sp, [%[regs], #52]\n" // Load SP "ldr lr, [%[regs], #56]\n" // Load LR - "ldr pc, [%[regs], #60]\n" + "ldr pc, [%[regs], #60]\n" // Load PC : : [regs] "r"(&p_cpu_core) : "memory", "r0", "r1", "r2", - // skip r3 + // skip r3 & use it as the offset register "r4", "r5", "r6", @@ -430,10 +378,12 @@ inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) "r9", "r10", "r11", - "r12"); + "r12", + "lr", + "pc"); } -void enter_function(exception_object& p_exception_object) +inline void enter_function(exception_object& p_exception_object) { std::uint8_t const* lsda_data = reinterpret_cast( p_exception_object.cache.entry_ptr->lsda_data()); @@ -456,20 +406,38 @@ void enter_function(exception_object& p_exception_object) std::uint32_t landing_pad = 0; std::uint32_t action = 0; - do { - auto start = read_encoded_data(&lsda_data, call_site_format); - auto length = read_encoded_data(&lsda_data, call_site_format); - landing_pad = read_encoded_data(&lsda_data, call_site_format); - action = read_uleb128(&lsda_data); + // Optimize for the most common use case and encouraged + if (call_site_format == personality_encoding::uleb128) { + do { + auto start = read_uleb128(&lsda_data); + auto length = read_uleb128(&lsda_data); + landing_pad = read_uleb128(&lsda_data); + action = read_uleb128(&lsda_data); - if (start <= rel_pc && rel_pc <= start + length) { - if (landing_pad == 0) { - p_exception_object.cache.state(runtime_state::unwind_frame); - return; + if (start <= rel_pc && rel_pc <= start + length) { + if (landing_pad == 0) { + p_exception_object.cache.state(runtime_state::unwind_frame); + return; + } + break; } - break; - } - } while (lsda_data < call_site_end); + } while (lsda_data < call_site_end); + } else { + do { + auto start = read_encoded_data(&lsda_data, call_site_format); + auto length = read_encoded_data(&lsda_data, call_site_format); + landing_pad = read_encoded_data(&lsda_data, call_site_format); + action = read_uleb128(&lsda_data); + + if (start <= rel_pc && rel_pc <= start + length) { + if (landing_pad == 0) { + p_exception_object.cache.state(runtime_state::unwind_frame); + return; + } + break; + } + } while (lsda_data < call_site_end); + } action_decoder a_decoder(end_of_tt_table, call_site_end, action); @@ -1645,8 +1613,8 @@ void raise_exception(exception_object& p_exception_object) p_exception_object.cache.state(runtime_state::unwind_frame); break; } - p_exception_object.cache.relative_address(p_exception_object.cpu.pc - - index_entry.function()); + p_exception_object.cache.relative_address( + (p_exception_object.cpu.pc - index_entry.function())); p_exception_object.cache.state(runtime_state::enter_function); [[fallthrough]]; } diff --git a/src/arm_cortex/estell/internal.hpp b/src/arm_cortex/estell/internal.hpp index 1589d95..105f4f6 100644 --- a/src/arm_cortex/estell/internal.hpp +++ b/src/arm_cortex/estell/internal.hpp @@ -62,6 +62,36 @@ constexpr std::uint32_t end_descriptor = 0x0000'0000; constexpr std::uint32_t su16_mask = 0b1111'1111'1111'1110; } // namespace arm_ehabi +std::uint32_t to_absolute_address(void const* p_object) +{ + constexpr auto signed_bit_31 = hal::bit_mask::from<30>(); + constexpr auto signed_bit_32 = hal::bit_mask::from<31>(); + auto object_address = reinterpret_cast(p_object); + auto offset = *reinterpret_cast(p_object); + + // Sign extend the offset to 32-bits + if (hal::bit_extract(offset)) { + hal::bit_modify(offset).set(); + } else { + hal::bit_modify(offset).clear(); + } + + auto signed_offset = static_cast(offset); + std::int32_t final_address = object_address + signed_offset; + return static_cast(final_address); +} + +[[gnu::used]] inline std::uint32_t runtime_to_absolute_address( + void const* p_object) +{ + return to_absolute_address(p_object); +} + +inline std::uint32_t* to_absolute_address_ptr(void const* p_object) +{ + return reinterpret_cast(to_absolute_address(p_object)); +} + // This is only to make GDB debugging easier, the functions are never actually // called so it is not important to include the correct types. struct function_t @@ -96,18 +126,85 @@ struct function_t } }; +namespace su16 { +constexpr auto instruction0 = hal::bit_mask{ .position = 16, .width = 8 }; +constexpr auto instruction1 = hal::bit_mask{ .position = 8, .width = 8 }; +constexpr auto instruction2 = hal::bit_mask{ .position = 0, .width = 8 }; +} // namespace su16 + +namespace lu16_32 { +constexpr auto length = hal::bit_mask::from<16, 23>(); +constexpr auto instruction0 = hal::bit_mask::from<15, 8>(); +constexpr auto instruction1 = hal::bit_mask::from<7, 0>(); +constexpr auto instruction2 = hal::bit_mask::from<31, 24>(); +constexpr auto instruction3 = hal::bit_mask::from<23, 16>(); +constexpr auto instruction4 = hal::bit_mask::from<15, 8>(); +constexpr auto instruction5 = hal::bit_mask::from<7, 0>(); +constexpr auto instruction6 = hal::bit_mask::from<24, 31>(); +} // namespace lu16_32 + struct index_entry_t { std::uint32_t function_offset; std::uint32_t personality_offset; - bool has_inlined_personality() const; - bool is_noexcept() const; - bool short_instructions() const; - std::uint32_t const* personality() const; - std::uint32_t const* lsda_data() const; - std::uint32_t const* descriptor_start() const; - function_t function() const; + [[gnu::always_inline]] inline constexpr bool has_inlined_personality() const + { + // 31st bit is `1` when the personality/unwind information is inlined, other + // otherwise, personality_offset is an offset. + constexpr auto mask = hal::bit_mask::from<31>(); + return hal::bit_extract(personality_offset); + } + + [[gnu::always_inline]] inline bool is_noexcept() const + { + return personality_offset == 0x1; + } + + [[gnu::always_inline]] inline std::uint32_t const* personality() const + { + return to_absolute_address_ptr(&personality_offset); + } + + [[gnu::always_inline]] inline std::uint32_t const* lsda_data() const + { + constexpr auto personality_type = hal::bit_mask::from<24, 27>(); + // +1 to skip the prel31 offset to the personality function + auto const* header = personality() + 1; + if (hal::bit_extract(*header) == 0x0) { + return header + 1; + } + if (hal::bit_extract(*header) == 1) { + return header + 2; + } + if (hal::bit_extract(*header) > 2) { + return header + 2; + } + return header + 3; + } + + [[gnu::always_inline]] inline std::uint32_t const* descriptor_start() const + { + constexpr auto type_mask = hal::bit_mask{ .position = 24, .width = 8 }; + + auto* personality_address = personality(); + auto type = hal::bit_extract(*personality_address); + + // TODO(kammce): comment why each of these works! + if (type == 0x0) { + return personality_address + 1; + } + + // The limit for ARM exceptions instructions is 7. LD optimizes the ARM + // exception spec by removing the "word length" specifier allowing the + // instructions to fit in 2 words. + return personality_address + 2; + } + + [[gnu::always_inline]] function_t function() const + { + return function_t(to_absolute_address(&function_offset)); + } }; struct cortex_m_cpu @@ -140,23 +237,6 @@ struct cortex_m_cpu } }; -namespace su16 { -constexpr auto instruction0 = hal::bit_mask{ .position = 16, .width = 8 }; -constexpr auto instruction1 = hal::bit_mask{ .position = 8, .width = 8 }; -constexpr auto instruction2 = hal::bit_mask{ .position = 0, .width = 8 }; -} // namespace su16 - -namespace lu16_32 { -constexpr auto length = hal::bit_mask::from<16, 23>(); -constexpr auto instruction0 = hal::bit_mask::from<15, 8>(); -constexpr auto instruction1 = hal::bit_mask::from<7, 0>(); -constexpr auto instruction2 = hal::bit_mask::from<31, 24>(); -constexpr auto instruction3 = hal::bit_mask::from<23, 16>(); -constexpr auto instruction4 = hal::bit_mask::from<15, 8>(); -constexpr auto instruction5 = hal::bit_mask::from<7, 0>(); -constexpr auto instruction6 = hal::bit_mask::from<24, 31>(); -} // namespace lu16_32 - enum class runtime_state : std::uint8_t { get_next_frame = 0, @@ -241,36 +321,6 @@ inline void* extract_thrown_object(void* p_exception_object) auto start_of_thrown = object_address + sizeof(exception_object); return reinterpret_cast(start_of_thrown); } - -std::uint32_t to_absolute_address(void const* p_object) -{ - constexpr auto signed_bit_31 = hal::bit_mask::from<30>(); - constexpr auto signed_bit_32 = hal::bit_mask::from<31>(); - auto object_address = reinterpret_cast(p_object); - auto offset = *reinterpret_cast(p_object); - - // Sign extend the offset to 32-bits - if (hal::bit_extract(offset)) { - hal::bit_modify(offset).set(); - } else { - hal::bit_modify(offset).clear(); - } - - auto signed_offset = static_cast(offset); - std::int32_t final_address = object_address + signed_offset; - return static_cast(final_address); -} - -[[gnu::used]] inline std::uint32_t runtime_to_absolute_address( - void const* p_object) -{ - return to_absolute_address(p_object); -} - -inline std::uint32_t* to_absolute_address_ptr(void const* p_object) -{ - return reinterpret_cast(to_absolute_address(p_object)); -} } // namespace ke struct [[gnu::packed]] su16_t From 987a6e53c74c547255c61517177827de5cc65480 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Wed, 17 Jul 2024 15:10:36 -0700 Subject: [PATCH 04/14] :bug: Get multi levels demo to work --- demos/CMakeLists.txt | 1 + demos/applications/multi_levels.cpp | 11411 ++++++++++++++++++++++++++ notes.md | 7 + src/arm_cortex/estell/exception.cpp | 402 +- src/arm_cortex/estell/internal.hpp | 22 +- 5 files changed, 11654 insertions(+), 189 deletions(-) create mode 100644 demos/applications/multi_levels.cpp create mode 100644 notes.md diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt index e96476d..90f87fd 100644 --- a/demos/CMakeLists.txt +++ b/demos/CMakeLists.txt @@ -19,6 +19,7 @@ project(demos LANGUAGES CXX) libhal_build_demos( DEMOS single_level + multi_levels PACKAGES libhal-exceptions diff --git a/demos/applications/multi_levels.cpp b/demos/applications/multi_levels.cpp new file mode 100644 index 0000000..acf3ad1 --- /dev/null +++ b/demos/applications/multi_levels.cpp @@ -0,0 +1,11411 @@ +#include + +#include "../resource_list.hpp" + +int start(); + +std::int32_t volatile side_effect = 0; +std::uint32_t start_cycles = 0; +std::uint32_t end_cycles = 0; + +resource_list* resources; + +std::array cycle_map{}; +std::array happy_cycle_map{}; + +struct my_error_t +{ + std::array data; +}; + +int funct_group0_0(); +int funct_group1_0(); +// int funct_group2_0(); +// int funct_group3_0(); +// int funct_group4_0(); +// int funct_group5_0(); +// int funct_group6_0(); +// int funct_group7_0(); +// int funct_group8_0(); +// int funct_group9_0(); +// int funct_group10_0(); +// int funct_group11_0(); +// int funct_group12_0(); +// int funct_group13_0(); +// int funct_group14_0(); +// int funct_group15_0(); +// int funct_group16_0(); +// int funct_group17_0(); +// int funct_group18_0(); +// int funct_group19_0(); +// int funct_group20_0(); +// int funct_group21_0(); +// int funct_group22_0(); +// int funct_group23_0(); +// int funct_group24_0(); + +using signature = int(void); + +std::array functions = { + &funct_group0_0, + &funct_group1_0, +#if 0 + funct_group2_0, funct_group3_0, + funct_group4_0, funct_group5_0, funct_group6_0, funct_group7_0, + funct_group8_0, funct_group9_0, funct_group10_0, funct_group11_0, + funct_group12_0, funct_group13_0, funct_group14_0, funct_group15_0, + funct_group16_0, + funct_group17_0, funct_group18_0, funct_group19_0, + funct_group20_0, funct_group21_0, funct_group22_0, funct_group23_0, + funct_group24_0 +#endif +}; + +std::uint64_t allocation_cycles = 0; + +void application(resource_list& p_resources) +{ + resources = &p_resources; + + cycle_map.fill(0); + happy_cycle_map.fill(std::numeric_limits::max()); + std::uint32_t index = 0; + for (std::size_t i = 0; i < functions.size(); i++) { + try { + functions.at(i)(); + // NOTE to Khalil before submission. Something is wrong with the unwinder + // and we are jumping to different locations when it completes the first + // time. Local variables are probably being damaged or the stack pointer + // is not in the correct location. + } catch ([[maybe_unused]] my_error_t const& p_error) { + end_cycles = resources->clock->uptime(); + cycle_map[index++] = end_cycles - start_cycles; + } + } + + index = 0; + + for (std::size_t i = 0; i < functions.size(); i++) { + bool was_caught = false; + try { + // should prevent throw from executing + side_effect = -1'000'000'000; + functions.at(i)(); + } catch ([[maybe_unused]] my_error_t const& p_error) { + was_caught = true; + } + if (!was_caught) { + end_cycles = resources->clock->uptime(); + happy_cycle_map[index++] = end_cycles - start_cycles; + } + } + + while (true) { + continue; + } +} + +class class_0 +{ +public: + class_0(std::int32_t p_channel) + : m_channel(p_channel) + { + if (m_channel >= 1'000'000'000) { + throw my_error_t{ .data = { 0x55, 0xAA, 0x33, 0x44 } }; + } + side_effect = side_effect + 1; + } + + class_0(class_0&) = delete; + class_0& operator=(class_0&) = delete; + class_0(class_0&&) noexcept = default; + class_0& operator=(class_0&&) noexcept = default; + ~class_0() = default; + void trigger() + { + if (m_channel >= 1'000'000'000) { + throw my_error_t{ .data = { 0xAA, 0xBB, 0x33, 0x44 } }; + } + side_effect = side_effect + 1; + } + +private: + std::int32_t m_channel = 0; +}; + +class class_1 +{ +public: + class_1(std::int32_t p_channel) + : m_channel(p_channel) + { + if (m_channel >= 1'000'000'000) { + throw my_error_t{ .data = { 0x55, 0xAA, 0x33, 0x44 } }; + } + side_effect = side_effect + 1; + } + + class_1(class_1&) = delete; + class_1& operator=(class_1&) = delete; + class_1(class_1&&) noexcept = default; + class_1& operator=(class_1&&) noexcept = default; +#if 1 + ~class_1() = default; +#elif + ~class_1() + { + side_effect = side_effect & ~(1 << m_channel); + } +#endif + + void trigger() + { + if (m_channel >= 1'000'000'000) { + throw my_error_t{ .data = { 0xAA, 0xBB, 0x33, 0x44 } }; + } + side_effect = side_effect + 1; + } + +private: + std::int32_t m_channel = 0; +}; + +int funct_group0_1(); + +int funct_group0_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group0_1(); + return side_effect; +} + +int funct_group0_2(); + +int funct_group0_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group0_2(); + return side_effect; +} + +int funct_group0_3(); + +int funct_group0_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group0_3(); + return side_effect; +} + +int funct_group0_4(); + +int funct_group0_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group0_4(); + return side_effect; +} + +int funct_group0_5(); + +int funct_group0_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + static float volatile my_float = 0.0f; + my_float = my_float + 5.5f; + instance_0.trigger(); + side_effect = side_effect + funct_group0_5(); + return side_effect; +} + +int funct_group0_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group1_1(); + +int funct_group1_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_1(); + return side_effect; +} + +int funct_group1_2(); + +int funct_group1_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_2(); + return side_effect; +} + +int funct_group1_3(); + +int funct_group1_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_3(); + return side_effect; +} + +int funct_group1_4(); + +int funct_group1_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_4(); + return side_effect; +} + +int funct_group1_5(); + +int funct_group1_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_5(); + return side_effect; +} + +int funct_group1_6(); + +int funct_group1_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_6(); + return side_effect; +} + +int funct_group1_7(); + +int funct_group1_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_7(); + return side_effect; +} + +int funct_group1_8(); + +int funct_group1_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_8(); + return side_effect; +} + +int funct_group1_9(); + +int funct_group1_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_9(); + return side_effect; +} + +int funct_group1_10(); + +int funct_group1_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_10(); + return side_effect; +} + +int funct_group1_11(); + +int funct_group1_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group1_11(); + return side_effect; +} + +int funct_group1_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xBE, 0xEF } }; + } + + return side_effect; +} + +int funct_group2_1(); + +int funct_group2_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_1(); + return side_effect; +} + +int funct_group2_2(); + +int funct_group2_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_2(); + return side_effect; +} + +int funct_group2_3(); + +int funct_group2_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_3(); + return side_effect; +} + +int funct_group2_4(); + +int funct_group2_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_4(); + return side_effect; +} + +int funct_group2_5(); + +int funct_group2_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_5(); + return side_effect; +} + +int funct_group2_6(); + +int funct_group2_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_6(); + return side_effect; +} + +int funct_group2_7(); + +int funct_group2_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_7(); + return side_effect; +} + +int funct_group2_8(); + +int funct_group2_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_8(); + return side_effect; +} + +int funct_group2_9(); + +int funct_group2_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_9(); + return side_effect; +} + +int funct_group2_10(); + +int funct_group2_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_10(); + return side_effect; +} + +int funct_group2_11(); + +int funct_group2_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_11(); + return side_effect; +} + +int funct_group2_12(); + +int funct_group2_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_12(); + return side_effect; +} + +int funct_group2_13(); + +int funct_group2_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_13(); + return side_effect; +} + +int funct_group2_14(); + +int funct_group2_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_14(); + return side_effect; +} + +int funct_group2_15(); + +int funct_group2_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_15(); + return side_effect; +} + +int funct_group2_16(); + +int funct_group2_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_16(); + return side_effect; +} + +int funct_group2_17(); + +int funct_group2_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_17(); + return side_effect; +} + +int funct_group2_18(); + +int funct_group2_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_18(); + return side_effect; +} + +int funct_group2_19(); + +int funct_group2_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_19(); + return side_effect; +} + +int funct_group2_20(); + +int funct_group2_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_20(); + return side_effect; +} + +int funct_group2_21(); + +int funct_group2_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_21(); + return side_effect; +} + +int funct_group2_22(); + +int funct_group2_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_22(); + return side_effect; +} + +int funct_group2_23(); + +int funct_group2_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group2_23(); + return side_effect; +} + +int funct_group2_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group3_1(); + +int funct_group3_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_1(); + return side_effect; +} + +int funct_group3_2(); + +int funct_group3_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_2(); + return side_effect; +} + +int funct_group3_3(); + +int funct_group3_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_3(); + return side_effect; +} + +int funct_group3_4(); + +int funct_group3_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_4(); + return side_effect; +} + +int funct_group3_5(); + +int funct_group3_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_5(); + return side_effect; +} + +int funct_group3_6(); + +int funct_group3_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_6(); + return side_effect; +} + +int funct_group3_7(); + +int funct_group3_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_7(); + return side_effect; +} + +int funct_group3_8(); + +int funct_group3_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_8(); + return side_effect; +} + +int funct_group3_9(); + +int funct_group3_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_9(); + return side_effect; +} + +int funct_group3_10(); + +int funct_group3_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_10(); + return side_effect; +} + +int funct_group3_11(); + +int funct_group3_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_11(); + return side_effect; +} + +int funct_group3_12(); + +int funct_group3_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_12(); + return side_effect; +} + +int funct_group3_13(); + +int funct_group3_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_13(); + return side_effect; +} + +int funct_group3_14(); + +int funct_group3_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_14(); + return side_effect; +} + +int funct_group3_15(); + +int funct_group3_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_15(); + return side_effect; +} + +int funct_group3_16(); + +int funct_group3_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_16(); + return side_effect; +} + +int funct_group3_17(); + +int funct_group3_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_17(); + return side_effect; +} + +int funct_group3_18(); + +int funct_group3_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_18(); + return side_effect; +} + +int funct_group3_19(); + +int funct_group3_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_19(); + return side_effect; +} + +int funct_group3_20(); + +int funct_group3_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_20(); + return side_effect; +} + +int funct_group3_21(); + +int funct_group3_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_21(); + return side_effect; +} + +int funct_group3_22(); + +int funct_group3_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_22(); + return side_effect; +} + +int funct_group3_23(); + +int funct_group3_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_23(); + return side_effect; +} + +int funct_group3_24(); + +int funct_group3_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_24(); + return side_effect; +} + +int funct_group3_25(); + +int funct_group3_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_25(); + return side_effect; +} + +int funct_group3_26(); + +int funct_group3_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_26(); + return side_effect; +} + +int funct_group3_27(); + +int funct_group3_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_27(); + return side_effect; +} + +int funct_group3_28(); + +int funct_group3_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_28(); + return side_effect; +} + +int funct_group3_29(); + +int funct_group3_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_29(); + return side_effect; +} + +int funct_group3_30(); + +int funct_group3_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_30(); + return side_effect; +} + +int funct_group3_31(); + +int funct_group3_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_31(); + return side_effect; +} + +int funct_group3_32(); + +int funct_group3_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_32(); + return side_effect; +} + +int funct_group3_33(); + +int funct_group3_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_33(); + return side_effect; +} + +int funct_group3_34(); + +int funct_group3_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_34(); + return side_effect; +} + +int funct_group3_35(); + +int funct_group3_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_35(); + return side_effect; +} + +int funct_group3_36(); + +int funct_group3_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_36(); + return side_effect; +} + +int funct_group3_37(); + +int funct_group3_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_37(); + return side_effect; +} + +int funct_group3_38(); + +int funct_group3_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_38(); + return side_effect; +} + +int funct_group3_39(); + +int funct_group3_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_39(); + return side_effect; +} + +int funct_group3_40(); + +int funct_group3_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_40(); + return side_effect; +} + +int funct_group3_41(); + +int funct_group3_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_41(); + return side_effect; +} + +int funct_group3_42(); + +int funct_group3_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_42(); + return side_effect; +} + +int funct_group3_43(); + +int funct_group3_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_43(); + return side_effect; +} + +int funct_group3_44(); + +int funct_group3_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_44(); + return side_effect; +} + +int funct_group3_45(); + +int funct_group3_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_45(); + return side_effect; +} + +int funct_group3_46(); + +int funct_group3_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_46(); + return side_effect; +} + +int funct_group3_47(); + +int funct_group3_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group3_47(); + return side_effect; +} + +int funct_group3_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group4_1(); + +int funct_group4_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_1(); + return side_effect; +} + +int funct_group4_2(); + +int funct_group4_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_2(); + return side_effect; +} + +int funct_group4_3(); + +int funct_group4_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_3(); + return side_effect; +} + +int funct_group4_4(); + +int funct_group4_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_4(); + return side_effect; +} + +int funct_group4_5(); + +int funct_group4_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_5(); + return side_effect; +} + +int funct_group4_6(); + +int funct_group4_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_6(); + return side_effect; +} + +int funct_group4_7(); + +int funct_group4_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_7(); + return side_effect; +} + +int funct_group4_8(); + +int funct_group4_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_8(); + return side_effect; +} + +int funct_group4_9(); + +int funct_group4_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_9(); + return side_effect; +} + +int funct_group4_10(); + +int funct_group4_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_10(); + return side_effect; +} + +int funct_group4_11(); + +int funct_group4_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_11(); + return side_effect; +} + +int funct_group4_12(); + +int funct_group4_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_12(); + return side_effect; +} + +int funct_group4_13(); + +int funct_group4_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_13(); + return side_effect; +} + +int funct_group4_14(); + +int funct_group4_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_14(); + return side_effect; +} + +int funct_group4_15(); + +int funct_group4_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_15(); + return side_effect; +} + +int funct_group4_16(); + +int funct_group4_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_16(); + return side_effect; +} + +int funct_group4_17(); + +int funct_group4_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_17(); + return side_effect; +} + +int funct_group4_18(); + +int funct_group4_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_18(); + return side_effect; +} + +int funct_group4_19(); + +int funct_group4_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_19(); + return side_effect; +} + +int funct_group4_20(); + +int funct_group4_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_20(); + return side_effect; +} + +int funct_group4_21(); + +int funct_group4_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_21(); + return side_effect; +} + +int funct_group4_22(); + +int funct_group4_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_22(); + return side_effect; +} + +int funct_group4_23(); + +int funct_group4_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_23(); + return side_effect; +} + +int funct_group4_24(); + +int funct_group4_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_24(); + return side_effect; +} + +int funct_group4_25(); + +int funct_group4_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_25(); + return side_effect; +} + +int funct_group4_26(); + +int funct_group4_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_26(); + return side_effect; +} + +int funct_group4_27(); + +int funct_group4_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_27(); + return side_effect; +} + +int funct_group4_28(); + +int funct_group4_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_28(); + return side_effect; +} + +int funct_group4_29(); + +int funct_group4_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_29(); + return side_effect; +} + +int funct_group4_30(); + +int funct_group4_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_30(); + return side_effect; +} + +int funct_group4_31(); + +int funct_group4_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_31(); + return side_effect; +} + +int funct_group4_32(); + +int funct_group4_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_32(); + return side_effect; +} + +int funct_group4_33(); + +int funct_group4_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_33(); + return side_effect; +} + +int funct_group4_34(); + +int funct_group4_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_34(); + return side_effect; +} + +int funct_group4_35(); + +int funct_group4_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_35(); + return side_effect; +} + +int funct_group4_36(); + +int funct_group4_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_36(); + return side_effect; +} + +int funct_group4_37(); + +int funct_group4_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_37(); + return side_effect; +} + +int funct_group4_38(); + +int funct_group4_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_38(); + return side_effect; +} + +int funct_group4_39(); + +int funct_group4_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_39(); + return side_effect; +} + +int funct_group4_40(); + +int funct_group4_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_40(); + return side_effect; +} + +int funct_group4_41(); + +int funct_group4_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_41(); + return side_effect; +} + +int funct_group4_42(); + +int funct_group4_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_42(); + return side_effect; +} + +int funct_group4_43(); + +int funct_group4_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_43(); + return side_effect; +} + +int funct_group4_44(); + +int funct_group4_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_44(); + return side_effect; +} + +int funct_group4_45(); + +int funct_group4_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_45(); + return side_effect; +} + +int funct_group4_46(); + +int funct_group4_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_46(); + return side_effect; +} + +int funct_group4_47(); + +int funct_group4_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_47(); + return side_effect; +} + +int funct_group4_48(); + +int funct_group4_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_48(); + return side_effect; +} + +int funct_group4_49(); + +int funct_group4_48() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_49(); + return side_effect; +} + +int funct_group4_50(); + +int funct_group4_49() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_50(); + return side_effect; +} + +int funct_group4_51(); + +int funct_group4_50() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_51(); + return side_effect; +} + +int funct_group4_52(); + +int funct_group4_51() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_52(); + return side_effect; +} + +int funct_group4_53(); + +int funct_group4_52() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_53(); + return side_effect; +} + +int funct_group4_54(); + +int funct_group4_53() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_54(); + return side_effect; +} + +int funct_group4_55(); + +int funct_group4_54() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_55(); + return side_effect; +} + +int funct_group4_56(); + +int funct_group4_55() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_56(); + return side_effect; +} + +int funct_group4_57(); + +int funct_group4_56() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_57(); + return side_effect; +} + +int funct_group4_58(); + +int funct_group4_57() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_58(); + return side_effect; +} + +int funct_group4_59(); + +int funct_group4_58() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_59(); + return side_effect; +} + +int funct_group4_60(); + +int funct_group4_59() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_60(); + return side_effect; +} + +int funct_group4_61(); + +int funct_group4_60() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_61(); + return side_effect; +} + +int funct_group4_62(); + +int funct_group4_61() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_62(); + return side_effect; +} + +int funct_group4_63(); + +int funct_group4_62() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_63(); + return side_effect; +} + +int funct_group4_64(); + +int funct_group4_63() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_64(); + return side_effect; +} + +int funct_group4_65(); + +int funct_group4_64() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_65(); + return side_effect; +} + +int funct_group4_66(); + +int funct_group4_65() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_66(); + return side_effect; +} + +int funct_group4_67(); + +int funct_group4_66() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_67(); + return side_effect; +} + +int funct_group4_68(); + +int funct_group4_67() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_68(); + return side_effect; +} + +int funct_group4_69(); + +int funct_group4_68() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_69(); + return side_effect; +} + +int funct_group4_70(); + +int funct_group4_69() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_70(); + return side_effect; +} + +int funct_group4_71(); + +int funct_group4_70() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_71(); + return side_effect; +} + +int funct_group4_72(); + +int funct_group4_71() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_72(); + return side_effect; +} + +int funct_group4_73(); + +int funct_group4_72() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_73(); + return side_effect; +} + +int funct_group4_74(); + +int funct_group4_73() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_74(); + return side_effect; +} + +int funct_group4_75(); + +int funct_group4_74() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_75(); + return side_effect; +} + +int funct_group4_76(); + +int funct_group4_75() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_76(); + return side_effect; +} + +int funct_group4_77(); + +int funct_group4_76() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_77(); + return side_effect; +} + +int funct_group4_78(); + +int funct_group4_77() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_78(); + return side_effect; +} + +int funct_group4_79(); + +int funct_group4_78() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_79(); + return side_effect; +} + +int funct_group4_80(); + +int funct_group4_79() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_80(); + return side_effect; +} + +int funct_group4_81(); + +int funct_group4_80() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_81(); + return side_effect; +} + +int funct_group4_82(); + +int funct_group4_81() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_82(); + return side_effect; +} + +int funct_group4_83(); + +int funct_group4_82() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_83(); + return side_effect; +} + +int funct_group4_84(); + +int funct_group4_83() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_84(); + return side_effect; +} + +int funct_group4_85(); + +int funct_group4_84() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_85(); + return side_effect; +} + +int funct_group4_86(); + +int funct_group4_85() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_86(); + return side_effect; +} + +int funct_group4_87(); + +int funct_group4_86() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_87(); + return side_effect; +} + +int funct_group4_88(); + +int funct_group4_87() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_88(); + return side_effect; +} + +int funct_group4_89(); + +int funct_group4_88() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_89(); + return side_effect; +} + +int funct_group4_90(); + +int funct_group4_89() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_90(); + return side_effect; +} + +int funct_group4_91(); + +int funct_group4_90() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_91(); + return side_effect; +} + +int funct_group4_92(); + +int funct_group4_91() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_92(); + return side_effect; +} + +int funct_group4_93(); + +int funct_group4_92() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_93(); + return side_effect; +} + +int funct_group4_94(); + +int funct_group4_93() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_94(); + return side_effect; +} + +int funct_group4_95(); + +int funct_group4_94() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group4_95(); + return side_effect; +} + +int funct_group4_95() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group5_1(); + +int funct_group5_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group5_1(); + return side_effect; +} + +int funct_group5_2(); + +int funct_group5_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group5_2(); + return side_effect; +} + +int funct_group5_3(); + +int funct_group5_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group5_3(); + return side_effect; +} + +int funct_group5_4(); + +int funct_group5_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group5_4(); + return side_effect; +} + +int funct_group5_5(); + +int funct_group5_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group5_5(); + return side_effect; +} + +int funct_group5_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group6_1(); + +int funct_group6_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_1(); + return side_effect; +} + +int funct_group6_2(); + +int funct_group6_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_2(); + return side_effect; +} + +int funct_group6_3(); + +int funct_group6_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_3(); + return side_effect; +} + +int funct_group6_4(); + +int funct_group6_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_4(); + return side_effect; +} + +int funct_group6_5(); + +int funct_group6_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_5(); + return side_effect; +} + +int funct_group6_6(); + +int funct_group6_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_6(); + return side_effect; +} + +int funct_group6_7(); + +int funct_group6_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_7(); + return side_effect; +} + +int funct_group6_8(); + +int funct_group6_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_8(); + return side_effect; +} + +int funct_group6_9(); + +int funct_group6_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_9(); + return side_effect; +} + +int funct_group6_10(); + +int funct_group6_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_10(); + return side_effect; +} + +int funct_group6_11(); + +int funct_group6_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group6_11(); + return side_effect; +} + +int funct_group6_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group7_1(); + +int funct_group7_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_1(); + return side_effect; +} + +int funct_group7_2(); + +int funct_group7_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_2(); + return side_effect; +} + +int funct_group7_3(); + +int funct_group7_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_3(); + return side_effect; +} + +int funct_group7_4(); + +int funct_group7_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_4(); + return side_effect; +} + +int funct_group7_5(); + +int funct_group7_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_5(); + return side_effect; +} + +int funct_group7_6(); + +int funct_group7_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_6(); + return side_effect; +} + +int funct_group7_7(); + +int funct_group7_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_7(); + return side_effect; +} + +int funct_group7_8(); + +int funct_group7_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_8(); + return side_effect; +} + +int funct_group7_9(); + +int funct_group7_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_9(); + return side_effect; +} + +int funct_group7_10(); + +int funct_group7_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_10(); + return side_effect; +} + +int funct_group7_11(); + +int funct_group7_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_11(); + return side_effect; +} + +int funct_group7_12(); + +int funct_group7_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_12(); + return side_effect; +} + +int funct_group7_13(); + +int funct_group7_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_13(); + return side_effect; +} + +int funct_group7_14(); + +int funct_group7_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_14(); + return side_effect; +} + +int funct_group7_15(); + +int funct_group7_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_15(); + return side_effect; +} + +int funct_group7_16(); + +int funct_group7_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_16(); + return side_effect; +} + +int funct_group7_17(); + +int funct_group7_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_17(); + return side_effect; +} + +int funct_group7_18(); + +int funct_group7_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_18(); + return side_effect; +} + +int funct_group7_19(); + +int funct_group7_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_19(); + return side_effect; +} + +int funct_group7_20(); + +int funct_group7_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_20(); + return side_effect; +} + +int funct_group7_21(); + +int funct_group7_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_21(); + return side_effect; +} + +int funct_group7_22(); + +int funct_group7_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_22(); + return side_effect; +} + +int funct_group7_23(); + +int funct_group7_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group7_23(); + return side_effect; +} + +int funct_group7_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +#if 0 +int funct_group8_1(); + +int funct_group8_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_1(); + return side_effect; +} + +int funct_group8_2(); + +int funct_group8_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_2(); + return side_effect; +} + +int funct_group8_3(); + +int funct_group8_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_3(); + return side_effect; +} + +int funct_group8_4(); + +int funct_group8_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_4(); + return side_effect; +} + +int funct_group8_5(); + +int funct_group8_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_5(); + return side_effect; +} + +int funct_group8_6(); + +int funct_group8_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_6(); + return side_effect; +} + +int funct_group8_7(); + +int funct_group8_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_7(); + return side_effect; +} + +int funct_group8_8(); + +int funct_group8_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_8(); + return side_effect; +} + +int funct_group8_9(); + +int funct_group8_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_9(); + return side_effect; +} + +int funct_group8_10(); + +int funct_group8_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_10(); + return side_effect; +} + +int funct_group8_11(); + +int funct_group8_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_11(); + return side_effect; +} + +int funct_group8_12(); + +int funct_group8_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_12(); + return side_effect; +} + +int funct_group8_13(); + +int funct_group8_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_13(); + return side_effect; +} + +int funct_group8_14(); + +int funct_group8_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_14(); + return side_effect; +} + +int funct_group8_15(); + +int funct_group8_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_15(); + return side_effect; +} + +int funct_group8_16(); + +int funct_group8_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_16(); + return side_effect; +} + +int funct_group8_17(); + +int funct_group8_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_17(); + return side_effect; +} + +int funct_group8_18(); + +int funct_group8_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_18(); + return side_effect; +} + +int funct_group8_19(); + +int funct_group8_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_19(); + return side_effect; +} + +int funct_group8_20(); + +int funct_group8_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_20(); + return side_effect; +} + +int funct_group8_21(); + +int funct_group8_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_21(); + return side_effect; +} + +int funct_group8_22(); + +int funct_group8_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_22(); + return side_effect; +} + +int funct_group8_23(); + +int funct_group8_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_23(); + return side_effect; +} + +int funct_group8_24(); + +int funct_group8_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_24(); + return side_effect; +} + +int funct_group8_25(); + +int funct_group8_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_25(); + return side_effect; +} + +int funct_group8_26(); + +int funct_group8_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_26(); + return side_effect; +} + +int funct_group8_27(); + +int funct_group8_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_27(); + return side_effect; +} + +int funct_group8_28(); + +int funct_group8_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_28(); + return side_effect; +} + +int funct_group8_29(); + +int funct_group8_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_29(); + return side_effect; +} + +int funct_group8_30(); + +int funct_group8_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_30(); + return side_effect; +} + +int funct_group8_31(); + +int funct_group8_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_31(); + return side_effect; +} + +int funct_group8_32(); + +int funct_group8_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_32(); + return side_effect; +} + +int funct_group8_33(); + +int funct_group8_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_33(); + return side_effect; +} + +int funct_group8_34(); + +int funct_group8_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_34(); + return side_effect; +} + +int funct_group8_35(); + +int funct_group8_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_35(); + return side_effect; +} + +int funct_group8_36(); + +int funct_group8_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_36(); + return side_effect; +} + +int funct_group8_37(); + +int funct_group8_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_37(); + return side_effect; +} + +int funct_group8_38(); + +int funct_group8_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_38(); + return side_effect; +} + +int funct_group8_39(); + +int funct_group8_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_39(); + return side_effect; +} + +int funct_group8_40(); + +int funct_group8_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_40(); + return side_effect; +} + +int funct_group8_41(); + +int funct_group8_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_41(); + return side_effect; +} + +int funct_group8_42(); + +int funct_group8_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_42(); + return side_effect; +} + +int funct_group8_43(); + +int funct_group8_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_43(); + return side_effect; +} + +int funct_group8_44(); + +int funct_group8_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_44(); + return side_effect; +} + +int funct_group8_45(); + +int funct_group8_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_45(); + return side_effect; +} + +int funct_group8_46(); + +int funct_group8_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_46(); + return side_effect; +} + +int funct_group8_47(); + +int funct_group8_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group8_47(); + return side_effect; +} + +int funct_group8_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group9_1(); + +int funct_group9_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_1(); + return side_effect; +} + +int funct_group9_2(); + +int funct_group9_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_2(); + return side_effect; +} + +int funct_group9_3(); + +int funct_group9_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_3(); + return side_effect; +} + +int funct_group9_4(); + +int funct_group9_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_4(); + return side_effect; +} + +int funct_group9_5(); + +int funct_group9_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_5(); + return side_effect; +} + +int funct_group9_6(); + +int funct_group9_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_6(); + return side_effect; +} + +int funct_group9_7(); + +int funct_group9_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_7(); + return side_effect; +} + +int funct_group9_8(); + +int funct_group9_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_8(); + return side_effect; +} + +int funct_group9_9(); + +int funct_group9_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_9(); + return side_effect; +} + +int funct_group9_10(); + +int funct_group9_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_10(); + return side_effect; +} + +int funct_group9_11(); + +int funct_group9_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_11(); + return side_effect; +} + +int funct_group9_12(); + +int funct_group9_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_12(); + return side_effect; +} + +int funct_group9_13(); + +int funct_group9_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_13(); + return side_effect; +} + +int funct_group9_14(); + +int funct_group9_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_14(); + return side_effect; +} + +int funct_group9_15(); + +int funct_group9_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_15(); + return side_effect; +} + +int funct_group9_16(); + +int funct_group9_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_16(); + return side_effect; +} + +int funct_group9_17(); + +int funct_group9_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_17(); + return side_effect; +} + +int funct_group9_18(); + +int funct_group9_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_18(); + return side_effect; +} + +int funct_group9_19(); + +int funct_group9_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_19(); + return side_effect; +} + +int funct_group9_20(); + +int funct_group9_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_20(); + return side_effect; +} + +int funct_group9_21(); + +int funct_group9_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_21(); + return side_effect; +} + +int funct_group9_22(); + +int funct_group9_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_22(); + return side_effect; +} + +int funct_group9_23(); + +int funct_group9_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_23(); + return side_effect; +} + +int funct_group9_24(); + +int funct_group9_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_24(); + return side_effect; +} + +int funct_group9_25(); + +int funct_group9_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_25(); + return side_effect; +} + +int funct_group9_26(); + +int funct_group9_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_26(); + return side_effect; +} + +int funct_group9_27(); + +int funct_group9_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_27(); + return side_effect; +} + +int funct_group9_28(); + +int funct_group9_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_28(); + return side_effect; +} + +int funct_group9_29(); + +int funct_group9_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_29(); + return side_effect; +} + +int funct_group9_30(); + +int funct_group9_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_30(); + return side_effect; +} + +int funct_group9_31(); + +int funct_group9_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_31(); + return side_effect; +} + +int funct_group9_32(); + +int funct_group9_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_32(); + return side_effect; +} + +int funct_group9_33(); + +int funct_group9_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_33(); + return side_effect; +} + +int funct_group9_34(); + +int funct_group9_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_34(); + return side_effect; +} + +int funct_group9_35(); + +int funct_group9_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_35(); + return side_effect; +} + +int funct_group9_36(); + +int funct_group9_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_36(); + return side_effect; +} + +int funct_group9_37(); + +int funct_group9_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_37(); + return side_effect; +} + +int funct_group9_38(); + +int funct_group9_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_38(); + return side_effect; +} + +int funct_group9_39(); + +int funct_group9_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_39(); + return side_effect; +} + +int funct_group9_40(); + +int funct_group9_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_40(); + return side_effect; +} + +int funct_group9_41(); + +int funct_group9_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_41(); + return side_effect; +} + +int funct_group9_42(); + +int funct_group9_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_42(); + return side_effect; +} + +int funct_group9_43(); + +int funct_group9_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_43(); + return side_effect; +} + +int funct_group9_44(); + +int funct_group9_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_44(); + return side_effect; +} + +int funct_group9_45(); + +int funct_group9_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_45(); + return side_effect; +} + +int funct_group9_46(); + +int funct_group9_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_46(); + return side_effect; +} + +int funct_group9_47(); + +int funct_group9_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_47(); + return side_effect; +} + +int funct_group9_48(); + +int funct_group9_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_48(); + return side_effect; +} + +int funct_group9_49(); + +int funct_group9_48() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_49(); + return side_effect; +} + +int funct_group9_50(); + +int funct_group9_49() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_50(); + return side_effect; +} + +int funct_group9_51(); + +int funct_group9_50() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_51(); + return side_effect; +} + +int funct_group9_52(); + +int funct_group9_51() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_52(); + return side_effect; +} + +int funct_group9_53(); + +int funct_group9_52() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_53(); + return side_effect; +} + +int funct_group9_54(); + +int funct_group9_53() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_54(); + return side_effect; +} + +int funct_group9_55(); + +int funct_group9_54() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_55(); + return side_effect; +} + +int funct_group9_56(); + +int funct_group9_55() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_56(); + return side_effect; +} + +int funct_group9_57(); + +int funct_group9_56() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_57(); + return side_effect; +} + +int funct_group9_58(); + +int funct_group9_57() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_58(); + return side_effect; +} + +int funct_group9_59(); + +int funct_group9_58() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_59(); + return side_effect; +} + +int funct_group9_60(); + +int funct_group9_59() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_60(); + return side_effect; +} + +int funct_group9_61(); + +int funct_group9_60() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_61(); + return side_effect; +} + +int funct_group9_62(); + +int funct_group9_61() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_62(); + return side_effect; +} + +int funct_group9_63(); + +int funct_group9_62() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_63(); + return side_effect; +} + +int funct_group9_64(); + +int funct_group9_63() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_64(); + return side_effect; +} + +int funct_group9_65(); + +int funct_group9_64() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_65(); + return side_effect; +} + +int funct_group9_66(); + +int funct_group9_65() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_66(); + return side_effect; +} + +int funct_group9_67(); + +int funct_group9_66() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_67(); + return side_effect; +} + +int funct_group9_68(); + +int funct_group9_67() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_68(); + return side_effect; +} + +int funct_group9_69(); + +int funct_group9_68() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_69(); + return side_effect; +} + +int funct_group9_70(); + +int funct_group9_69() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_70(); + return side_effect; +} + +int funct_group9_71(); + +int funct_group9_70() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_71(); + return side_effect; +} + +int funct_group9_72(); + +int funct_group9_71() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_72(); + return side_effect; +} + +int funct_group9_73(); + +int funct_group9_72() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_73(); + return side_effect; +} + +int funct_group9_74(); + +int funct_group9_73() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_74(); + return side_effect; +} + +int funct_group9_75(); + +int funct_group9_74() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_75(); + return side_effect; +} + +int funct_group9_76(); + +int funct_group9_75() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_76(); + return side_effect; +} + +int funct_group9_77(); + +int funct_group9_76() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_77(); + return side_effect; +} + +int funct_group9_78(); + +int funct_group9_77() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_78(); + return side_effect; +} + +int funct_group9_79(); + +int funct_group9_78() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_79(); + return side_effect; +} + +int funct_group9_80(); + +int funct_group9_79() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_80(); + return side_effect; +} + +int funct_group9_81(); + +int funct_group9_80() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_81(); + return side_effect; +} + +int funct_group9_82(); + +int funct_group9_81() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_82(); + return side_effect; +} + +int funct_group9_83(); + +int funct_group9_82() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_83(); + return side_effect; +} + +int funct_group9_84(); + +int funct_group9_83() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_84(); + return side_effect; +} + +int funct_group9_85(); + +int funct_group9_84() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_85(); + return side_effect; +} + +int funct_group9_86(); + +int funct_group9_85() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_86(); + return side_effect; +} + +int funct_group9_87(); + +int funct_group9_86() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_87(); + return side_effect; +} + +int funct_group9_88(); + +int funct_group9_87() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_88(); + return side_effect; +} + +int funct_group9_89(); + +int funct_group9_88() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_89(); + return side_effect; +} + +int funct_group9_90(); + +int funct_group9_89() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_90(); + return side_effect; +} + +int funct_group9_91(); + +int funct_group9_90() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_91(); + return side_effect; +} + +int funct_group9_92(); + +int funct_group9_91() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_92(); + return side_effect; +} + +int funct_group9_93(); + +int funct_group9_92() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_93(); + return side_effect; +} + +int funct_group9_94(); + +int funct_group9_93() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_94(); + return side_effect; +} + +int funct_group9_95(); + +int funct_group9_94() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group9_95(); + return side_effect; +} + +int funct_group9_95() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group10_1(); + +int funct_group10_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group10_1(); + return side_effect; +} + +int funct_group10_2(); + +int funct_group10_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group10_2(); + return side_effect; +} + +int funct_group10_3(); + +int funct_group10_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group10_3(); + return side_effect; +} + +int funct_group10_4(); + +int funct_group10_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group10_4(); + return side_effect; +} + +int funct_group10_5(); + +int funct_group10_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group10_5(); + return side_effect; +} + +int funct_group10_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group11_1(); + +int funct_group11_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_1(); + return side_effect; +} + +int funct_group11_2(); + +int funct_group11_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_2(); + return side_effect; +} + +int funct_group11_3(); + +int funct_group11_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_3(); + return side_effect; +} + +int funct_group11_4(); + +int funct_group11_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_4(); + return side_effect; +} + +int funct_group11_5(); + +int funct_group11_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_5(); + return side_effect; +} + +int funct_group11_6(); + +int funct_group11_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_6(); + return side_effect; +} + +int funct_group11_7(); + +int funct_group11_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_7(); + return side_effect; +} + +int funct_group11_8(); + +int funct_group11_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_8(); + return side_effect; +} + +int funct_group11_9(); + +int funct_group11_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_9(); + return side_effect; +} + +int funct_group11_10(); + +int funct_group11_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_10(); + return side_effect; +} + +int funct_group11_11(); + +int funct_group11_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group11_11(); + return side_effect; +} + +int funct_group11_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group12_1(); + +int funct_group12_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_1(); + return side_effect; +} + +int funct_group12_2(); + +int funct_group12_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_2(); + return side_effect; +} + +int funct_group12_3(); + +int funct_group12_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_3(); + return side_effect; +} + +int funct_group12_4(); + +int funct_group12_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_4(); + return side_effect; +} + +int funct_group12_5(); + +int funct_group12_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_5(); + return side_effect; +} + +int funct_group12_6(); + +int funct_group12_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_6(); + return side_effect; +} + +int funct_group12_7(); + +int funct_group12_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_7(); + return side_effect; +} + +int funct_group12_8(); + +int funct_group12_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_8(); + return side_effect; +} + +int funct_group12_9(); + +int funct_group12_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_9(); + return side_effect; +} + +int funct_group12_10(); + +int funct_group12_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_10(); + return side_effect; +} + +int funct_group12_11(); + +int funct_group12_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_11(); + return side_effect; +} + +int funct_group12_12(); + +int funct_group12_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_12(); + return side_effect; +} + +int funct_group12_13(); + +int funct_group12_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_13(); + return side_effect; +} + +int funct_group12_14(); + +int funct_group12_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_14(); + return side_effect; +} + +int funct_group12_15(); + +int funct_group12_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_15(); + return side_effect; +} + +int funct_group12_16(); + +int funct_group12_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_16(); + return side_effect; +} + +int funct_group12_17(); + +int funct_group12_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_17(); + return side_effect; +} + +int funct_group12_18(); + +int funct_group12_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_18(); + return side_effect; +} + +int funct_group12_19(); + +int funct_group12_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_19(); + return side_effect; +} + +int funct_group12_20(); + +int funct_group12_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_20(); + return side_effect; +} + +int funct_group12_21(); + +int funct_group12_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_21(); + return side_effect; +} + +int funct_group12_22(); + +int funct_group12_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_22(); + return side_effect; +} + +int funct_group12_23(); + +int funct_group12_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group12_23(); + return side_effect; +} + +int funct_group12_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group13_1(); + +int funct_group13_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_1(); + return side_effect; +} + +int funct_group13_2(); + +int funct_group13_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_2(); + return side_effect; +} + +int funct_group13_3(); + +int funct_group13_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_3(); + return side_effect; +} + +int funct_group13_4(); + +int funct_group13_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_4(); + return side_effect; +} + +int funct_group13_5(); + +int funct_group13_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_5(); + return side_effect; +} + +int funct_group13_6(); + +int funct_group13_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_6(); + return side_effect; +} + +int funct_group13_7(); + +int funct_group13_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_7(); + return side_effect; +} + +int funct_group13_8(); + +int funct_group13_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_8(); + return side_effect; +} + +int funct_group13_9(); + +int funct_group13_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_9(); + return side_effect; +} + +int funct_group13_10(); + +int funct_group13_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_10(); + return side_effect; +} + +int funct_group13_11(); + +int funct_group13_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_11(); + return side_effect; +} + +int funct_group13_12(); + +int funct_group13_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_12(); + return side_effect; +} + +int funct_group13_13(); + +int funct_group13_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_13(); + return side_effect; +} + +int funct_group13_14(); + +int funct_group13_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_14(); + return side_effect; +} + +int funct_group13_15(); + +int funct_group13_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_15(); + return side_effect; +} + +int funct_group13_16(); + +int funct_group13_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_16(); + return side_effect; +} + +int funct_group13_17(); + +int funct_group13_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_17(); + return side_effect; +} + +int funct_group13_18(); + +int funct_group13_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_18(); + return side_effect; +} + +int funct_group13_19(); + +int funct_group13_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_19(); + return side_effect; +} + +int funct_group13_20(); + +int funct_group13_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_20(); + return side_effect; +} + +int funct_group13_21(); + +int funct_group13_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_21(); + return side_effect; +} + +int funct_group13_22(); + +int funct_group13_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_22(); + return side_effect; +} + +int funct_group13_23(); + +int funct_group13_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_23(); + return side_effect; +} + +int funct_group13_24(); + +int funct_group13_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_24(); + return side_effect; +} + +int funct_group13_25(); + +int funct_group13_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_25(); + return side_effect; +} + +int funct_group13_26(); + +int funct_group13_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_26(); + return side_effect; +} + +int funct_group13_27(); + +int funct_group13_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_27(); + return side_effect; +} + +int funct_group13_28(); + +int funct_group13_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_28(); + return side_effect; +} + +int funct_group13_29(); + +int funct_group13_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_29(); + return side_effect; +} + +int funct_group13_30(); + +int funct_group13_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_30(); + return side_effect; +} + +int funct_group13_31(); + +int funct_group13_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_31(); + return side_effect; +} + +int funct_group13_32(); + +int funct_group13_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_32(); + return side_effect; +} + +int funct_group13_33(); + +int funct_group13_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_33(); + return side_effect; +} + +int funct_group13_34(); + +int funct_group13_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_34(); + return side_effect; +} + +int funct_group13_35(); + +int funct_group13_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_35(); + return side_effect; +} + +int funct_group13_36(); + +int funct_group13_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_36(); + return side_effect; +} + +int funct_group13_37(); + +int funct_group13_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_37(); + return side_effect; +} + +int funct_group13_38(); + +int funct_group13_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_38(); + return side_effect; +} + +int funct_group13_39(); + +int funct_group13_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_39(); + return side_effect; +} + +int funct_group13_40(); + +int funct_group13_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_40(); + return side_effect; +} + +int funct_group13_41(); + +int funct_group13_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_41(); + return side_effect; +} + +int funct_group13_42(); + +int funct_group13_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_42(); + return side_effect; +} + +int funct_group13_43(); + +int funct_group13_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_43(); + return side_effect; +} + +int funct_group13_44(); + +int funct_group13_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_44(); + return side_effect; +} + +int funct_group13_45(); + +int funct_group13_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_45(); + return side_effect; +} + +int funct_group13_46(); + +int funct_group13_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_46(); + return side_effect; +} + +int funct_group13_47(); + +int funct_group13_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group13_47(); + return side_effect; +} + +int funct_group13_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group14_1(); + +int funct_group14_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_1(); + return side_effect; +} + +int funct_group14_2(); + +int funct_group14_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_2(); + return side_effect; +} + +int funct_group14_3(); + +int funct_group14_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_3(); + return side_effect; +} + +int funct_group14_4(); + +int funct_group14_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_4(); + return side_effect; +} + +int funct_group14_5(); + +int funct_group14_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_5(); + return side_effect; +} + +int funct_group14_6(); + +int funct_group14_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_6(); + return side_effect; +} + +int funct_group14_7(); + +int funct_group14_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_7(); + return side_effect; +} + +int funct_group14_8(); + +int funct_group14_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_8(); + return side_effect; +} + +int funct_group14_9(); + +int funct_group14_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_9(); + return side_effect; +} + +int funct_group14_10(); + +int funct_group14_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_10(); + return side_effect; +} + +int funct_group14_11(); + +int funct_group14_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_11(); + return side_effect; +} + +int funct_group14_12(); + +int funct_group14_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_12(); + return side_effect; +} + +int funct_group14_13(); + +int funct_group14_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_13(); + return side_effect; +} + +int funct_group14_14(); + +int funct_group14_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_14(); + return side_effect; +} + +int funct_group14_15(); + +int funct_group14_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_15(); + return side_effect; +} + +int funct_group14_16(); + +int funct_group14_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_16(); + return side_effect; +} + +int funct_group14_17(); + +int funct_group14_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_17(); + return side_effect; +} + +int funct_group14_18(); + +int funct_group14_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_18(); + return side_effect; +} + +int funct_group14_19(); + +int funct_group14_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_19(); + return side_effect; +} + +int funct_group14_20(); + +int funct_group14_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_20(); + return side_effect; +} + +int funct_group14_21(); + +int funct_group14_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_21(); + return side_effect; +} + +int funct_group14_22(); + +int funct_group14_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_22(); + return side_effect; +} + +int funct_group14_23(); + +int funct_group14_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_23(); + return side_effect; +} + +int funct_group14_24(); + +int funct_group14_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_24(); + return side_effect; +} + +int funct_group14_25(); + +int funct_group14_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_25(); + return side_effect; +} + +int funct_group14_26(); + +int funct_group14_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_26(); + return side_effect; +} + +int funct_group14_27(); + +int funct_group14_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_27(); + return side_effect; +} + +int funct_group14_28(); + +int funct_group14_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_28(); + return side_effect; +} + +int funct_group14_29(); + +int funct_group14_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_29(); + return side_effect; +} + +int funct_group14_30(); + +int funct_group14_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_30(); + return side_effect; +} + +int funct_group14_31(); + +int funct_group14_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_31(); + return side_effect; +} + +int funct_group14_32(); + +int funct_group14_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_32(); + return side_effect; +} + +int funct_group14_33(); + +int funct_group14_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_33(); + return side_effect; +} + +int funct_group14_34(); + +int funct_group14_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_34(); + return side_effect; +} + +int funct_group14_35(); + +int funct_group14_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_35(); + return side_effect; +} + +int funct_group14_36(); + +int funct_group14_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_36(); + return side_effect; +} + +int funct_group14_37(); + +int funct_group14_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_37(); + return side_effect; +} + +int funct_group14_38(); + +int funct_group14_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_38(); + return side_effect; +} + +int funct_group14_39(); + +int funct_group14_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_39(); + return side_effect; +} + +int funct_group14_40(); + +int funct_group14_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_40(); + return side_effect; +} + +int funct_group14_41(); + +int funct_group14_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_41(); + return side_effect; +} + +int funct_group14_42(); + +int funct_group14_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_42(); + return side_effect; +} + +int funct_group14_43(); + +int funct_group14_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_43(); + return side_effect; +} + +int funct_group14_44(); + +int funct_group14_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_44(); + return side_effect; +} + +int funct_group14_45(); + +int funct_group14_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_45(); + return side_effect; +} + +int funct_group14_46(); + +int funct_group14_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_46(); + return side_effect; +} + +int funct_group14_47(); + +int funct_group14_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_47(); + return side_effect; +} + +int funct_group14_48(); + +int funct_group14_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_48(); + return side_effect; +} + +int funct_group14_49(); + +int funct_group14_48() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_49(); + return side_effect; +} + +int funct_group14_50(); + +int funct_group14_49() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_50(); + return side_effect; +} + +int funct_group14_51(); + +int funct_group14_50() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_51(); + return side_effect; +} + +int funct_group14_52(); + +int funct_group14_51() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_52(); + return side_effect; +} + +int funct_group14_53(); + +int funct_group14_52() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_53(); + return side_effect; +} + +int funct_group14_54(); + +int funct_group14_53() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_54(); + return side_effect; +} + +int funct_group14_55(); + +int funct_group14_54() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_55(); + return side_effect; +} + +int funct_group14_56(); + +int funct_group14_55() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_56(); + return side_effect; +} + +int funct_group14_57(); + +int funct_group14_56() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_57(); + return side_effect; +} + +int funct_group14_58(); + +int funct_group14_57() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_58(); + return side_effect; +} + +int funct_group14_59(); + +int funct_group14_58() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_59(); + return side_effect; +} + +int funct_group14_60(); + +int funct_group14_59() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_60(); + return side_effect; +} + +int funct_group14_61(); + +int funct_group14_60() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_61(); + return side_effect; +} + +int funct_group14_62(); + +int funct_group14_61() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_62(); + return side_effect; +} + +int funct_group14_63(); + +int funct_group14_62() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_63(); + return side_effect; +} + +int funct_group14_64(); + +int funct_group14_63() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_64(); + return side_effect; +} + +int funct_group14_65(); + +int funct_group14_64() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_65(); + return side_effect; +} + +int funct_group14_66(); + +int funct_group14_65() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_66(); + return side_effect; +} + +int funct_group14_67(); + +int funct_group14_66() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_67(); + return side_effect; +} + +int funct_group14_68(); + +int funct_group14_67() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_68(); + return side_effect; +} + +int funct_group14_69(); + +int funct_group14_68() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_69(); + return side_effect; +} + +int funct_group14_70(); + +int funct_group14_69() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_70(); + return side_effect; +} + +int funct_group14_71(); + +int funct_group14_70() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_71(); + return side_effect; +} + +int funct_group14_72(); + +int funct_group14_71() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_72(); + return side_effect; +} + +int funct_group14_73(); + +int funct_group14_72() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_73(); + return side_effect; +} + +int funct_group14_74(); + +int funct_group14_73() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_74(); + return side_effect; +} + +int funct_group14_75(); + +int funct_group14_74() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_75(); + return side_effect; +} + +int funct_group14_76(); + +int funct_group14_75() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_76(); + return side_effect; +} + +int funct_group14_77(); + +int funct_group14_76() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_77(); + return side_effect; +} + +int funct_group14_78(); + +int funct_group14_77() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_78(); + return side_effect; +} + +int funct_group14_79(); + +int funct_group14_78() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_79(); + return side_effect; +} + +int funct_group14_80(); + +int funct_group14_79() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_80(); + return side_effect; +} + +int funct_group14_81(); + +int funct_group14_80() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_81(); + return side_effect; +} + +int funct_group14_82(); + +int funct_group14_81() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_82(); + return side_effect; +} + +int funct_group14_83(); + +int funct_group14_82() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_83(); + return side_effect; +} + +int funct_group14_84(); + +int funct_group14_83() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_84(); + return side_effect; +} + +int funct_group14_85(); + +int funct_group14_84() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_85(); + return side_effect; +} + +int funct_group14_86(); + +int funct_group14_85() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_86(); + return side_effect; +} + +int funct_group14_87(); + +int funct_group14_86() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_87(); + return side_effect; +} + +int funct_group14_88(); + +int funct_group14_87() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_88(); + return side_effect; +} + +int funct_group14_89(); + +int funct_group14_88() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_89(); + return side_effect; +} + +int funct_group14_90(); + +int funct_group14_89() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_90(); + return side_effect; +} + +int funct_group14_91(); + +int funct_group14_90() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_91(); + return side_effect; +} + +int funct_group14_92(); + +int funct_group14_91() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_92(); + return side_effect; +} + +int funct_group14_93(); + +int funct_group14_92() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_93(); + return side_effect; +} + +int funct_group14_94(); + +int funct_group14_93() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_94(); + return side_effect; +} + +int funct_group14_95(); + +int funct_group14_94() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group14_95(); + return side_effect; +} + +int funct_group14_95() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group15_1(); + +int funct_group15_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group15_1(); + return side_effect; +} + +int funct_group15_2(); + +int funct_group15_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group15_2(); + return side_effect; +} + +int funct_group15_3(); + +int funct_group15_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group15_3(); + return side_effect; +} + +int funct_group15_4(); + +int funct_group15_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group15_4(); + return side_effect; +} + +int funct_group15_5(); + +int funct_group15_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group15_5(); + return side_effect; +} + +int funct_group15_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group16_1(); + +int funct_group16_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_1(); + return side_effect; +} + +int funct_group16_2(); + +int funct_group16_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_2(); + return side_effect; +} + +int funct_group16_3(); + +int funct_group16_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_3(); + return side_effect; +} + +int funct_group16_4(); + +int funct_group16_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_4(); + return side_effect; +} + +int funct_group16_5(); + +int funct_group16_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_5(); + return side_effect; +} + +int funct_group16_6(); + +int funct_group16_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_6(); + return side_effect; +} + +int funct_group16_7(); + +int funct_group16_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_7(); + return side_effect; +} + +int funct_group16_8(); + +int funct_group16_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_8(); + return side_effect; +} + +int funct_group16_9(); + +int funct_group16_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_9(); + return side_effect; +} + +int funct_group16_10(); + +int funct_group16_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_10(); + return side_effect; +} + +int funct_group16_11(); + +int funct_group16_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group16_11(); + return side_effect; +} + +int funct_group16_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group17_1(); + +int funct_group17_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_1(); + return side_effect; +} + +int funct_group17_2(); + +int funct_group17_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_2(); + return side_effect; +} + +int funct_group17_3(); + +int funct_group17_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_3(); + return side_effect; +} + +int funct_group17_4(); + +int funct_group17_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_4(); + return side_effect; +} + +int funct_group17_5(); + +int funct_group17_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_5(); + return side_effect; +} + +int funct_group17_6(); + +int funct_group17_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_6(); + return side_effect; +} + +int funct_group17_7(); + +int funct_group17_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_7(); + return side_effect; +} + +int funct_group17_8(); + +int funct_group17_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_8(); + return side_effect; +} + +int funct_group17_9(); + +int funct_group17_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_9(); + return side_effect; +} + +int funct_group17_10(); + +int funct_group17_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_10(); + return side_effect; +} + +int funct_group17_11(); + +int funct_group17_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_11(); + return side_effect; +} + +int funct_group17_12(); + +int funct_group17_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_12(); + return side_effect; +} + +int funct_group17_13(); + +int funct_group17_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_13(); + return side_effect; +} + +int funct_group17_14(); + +int funct_group17_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_14(); + return side_effect; +} + +int funct_group17_15(); + +int funct_group17_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_15(); + return side_effect; +} + +int funct_group17_16(); + +int funct_group17_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_16(); + return side_effect; +} + +int funct_group17_17(); + +int funct_group17_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_17(); + return side_effect; +} + +int funct_group17_18(); + +int funct_group17_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_18(); + return side_effect; +} + +int funct_group17_19(); + +int funct_group17_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_19(); + return side_effect; +} + +int funct_group17_20(); + +int funct_group17_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_20(); + return side_effect; +} + +int funct_group17_21(); + +int funct_group17_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_21(); + return side_effect; +} + +int funct_group17_22(); + +int funct_group17_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_22(); + return side_effect; +} + +int funct_group17_23(); + +int funct_group17_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group17_23(); + return side_effect; +} + +int funct_group17_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group18_1(); + +int funct_group18_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_1(); + return side_effect; +} + +int funct_group18_2(); + +int funct_group18_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_2(); + return side_effect; +} + +int funct_group18_3(); + +int funct_group18_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_3(); + return side_effect; +} + +int funct_group18_4(); + +int funct_group18_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_4(); + return side_effect; +} + +int funct_group18_5(); + +int funct_group18_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_5(); + return side_effect; +} + +int funct_group18_6(); + +int funct_group18_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_6(); + return side_effect; +} + +int funct_group18_7(); + +int funct_group18_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_7(); + return side_effect; +} + +int funct_group18_8(); + +int funct_group18_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_8(); + return side_effect; +} + +int funct_group18_9(); + +int funct_group18_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_9(); + return side_effect; +} + +int funct_group18_10(); + +int funct_group18_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_10(); + return side_effect; +} + +int funct_group18_11(); + +int funct_group18_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_11(); + return side_effect; +} + +int funct_group18_12(); + +int funct_group18_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_12(); + return side_effect; +} + +int funct_group18_13(); + +int funct_group18_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_13(); + return side_effect; +} + +int funct_group18_14(); + +int funct_group18_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_14(); + return side_effect; +} + +int funct_group18_15(); + +int funct_group18_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_15(); + return side_effect; +} + +int funct_group18_16(); + +int funct_group18_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_16(); + return side_effect; +} + +int funct_group18_17(); + +int funct_group18_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_17(); + return side_effect; +} + +int funct_group18_18(); + +int funct_group18_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_18(); + return side_effect; +} + +int funct_group18_19(); + +int funct_group18_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_19(); + return side_effect; +} + +int funct_group18_20(); + +int funct_group18_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_20(); + return side_effect; +} + +int funct_group18_21(); + +int funct_group18_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_21(); + return side_effect; +} + +int funct_group18_22(); + +int funct_group18_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_22(); + return side_effect; +} + +int funct_group18_23(); + +int funct_group18_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_23(); + return side_effect; +} + +int funct_group18_24(); + +int funct_group18_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_24(); + return side_effect; +} + +int funct_group18_25(); + +int funct_group18_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_25(); + return side_effect; +} + +int funct_group18_26(); + +int funct_group18_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_26(); + return side_effect; +} + +int funct_group18_27(); + +int funct_group18_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_27(); + return side_effect; +} + +int funct_group18_28(); + +int funct_group18_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_28(); + return side_effect; +} + +int funct_group18_29(); + +int funct_group18_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_29(); + return side_effect; +} + +int funct_group18_30(); + +int funct_group18_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_30(); + return side_effect; +} + +int funct_group18_31(); + +int funct_group18_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_31(); + return side_effect; +} + +int funct_group18_32(); + +int funct_group18_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_32(); + return side_effect; +} + +int funct_group18_33(); + +int funct_group18_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_33(); + return side_effect; +} + +int funct_group18_34(); + +int funct_group18_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_34(); + return side_effect; +} + +int funct_group18_35(); + +int funct_group18_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_35(); + return side_effect; +} + +int funct_group18_36(); + +int funct_group18_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_36(); + return side_effect; +} + +int funct_group18_37(); + +int funct_group18_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_37(); + return side_effect; +} + +int funct_group18_38(); + +int funct_group18_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_38(); + return side_effect; +} + +int funct_group18_39(); + +int funct_group18_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_39(); + return side_effect; +} + +int funct_group18_40(); + +int funct_group18_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_40(); + return side_effect; +} + +int funct_group18_41(); + +int funct_group18_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_41(); + return side_effect; +} + +int funct_group18_42(); + +int funct_group18_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_42(); + return side_effect; +} + +int funct_group18_43(); + +int funct_group18_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_43(); + return side_effect; +} + +int funct_group18_44(); + +int funct_group18_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_44(); + return side_effect; +} + +int funct_group18_45(); + +int funct_group18_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_45(); + return side_effect; +} + +int funct_group18_46(); + +int funct_group18_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_46(); + return side_effect; +} + +int funct_group18_47(); + +int funct_group18_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group18_47(); + return side_effect; +} + +int funct_group18_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group19_1(); + +int funct_group19_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_1(); + return side_effect; +} + +int funct_group19_2(); + +int funct_group19_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_2(); + return side_effect; +} + +int funct_group19_3(); + +int funct_group19_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_3(); + return side_effect; +} + +int funct_group19_4(); + +int funct_group19_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_4(); + return side_effect; +} + +int funct_group19_5(); + +int funct_group19_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_5(); + return side_effect; +} + +int funct_group19_6(); + +int funct_group19_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_6(); + return side_effect; +} + +int funct_group19_7(); + +int funct_group19_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_7(); + return side_effect; +} + +int funct_group19_8(); + +int funct_group19_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_8(); + return side_effect; +} + +int funct_group19_9(); + +int funct_group19_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_9(); + return side_effect; +} + +int funct_group19_10(); + +int funct_group19_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_10(); + return side_effect; +} + +int funct_group19_11(); + +int funct_group19_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_11(); + return side_effect; +} + +int funct_group19_12(); + +int funct_group19_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_12(); + return side_effect; +} + +int funct_group19_13(); + +int funct_group19_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_13(); + return side_effect; +} + +int funct_group19_14(); + +int funct_group19_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_14(); + return side_effect; +} + +int funct_group19_15(); + +int funct_group19_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_15(); + return side_effect; +} + +int funct_group19_16(); + +int funct_group19_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_16(); + return side_effect; +} + +int funct_group19_17(); + +int funct_group19_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_17(); + return side_effect; +} + +int funct_group19_18(); + +int funct_group19_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_18(); + return side_effect; +} + +int funct_group19_19(); + +int funct_group19_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_19(); + return side_effect; +} + +int funct_group19_20(); + +int funct_group19_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_20(); + return side_effect; +} + +int funct_group19_21(); + +int funct_group19_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_21(); + return side_effect; +} + +int funct_group19_22(); + +int funct_group19_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_22(); + return side_effect; +} + +int funct_group19_23(); + +int funct_group19_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_23(); + return side_effect; +} + +int funct_group19_24(); + +int funct_group19_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_24(); + return side_effect; +} + +int funct_group19_25(); + +int funct_group19_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_25(); + return side_effect; +} + +int funct_group19_26(); + +int funct_group19_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_26(); + return side_effect; +} + +int funct_group19_27(); + +int funct_group19_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_27(); + return side_effect; +} + +int funct_group19_28(); + +int funct_group19_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_28(); + return side_effect; +} + +int funct_group19_29(); + +int funct_group19_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_29(); + return side_effect; +} + +int funct_group19_30(); + +int funct_group19_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_30(); + return side_effect; +} + +int funct_group19_31(); + +int funct_group19_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_31(); + return side_effect; +} + +int funct_group19_32(); + +int funct_group19_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_32(); + return side_effect; +} + +int funct_group19_33(); + +int funct_group19_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_33(); + return side_effect; +} + +int funct_group19_34(); + +int funct_group19_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_34(); + return side_effect; +} + +int funct_group19_35(); + +int funct_group19_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_35(); + return side_effect; +} + +int funct_group19_36(); + +int funct_group19_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_36(); + return side_effect; +} + +int funct_group19_37(); + +int funct_group19_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_37(); + return side_effect; +} + +int funct_group19_38(); + +int funct_group19_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_38(); + return side_effect; +} + +int funct_group19_39(); + +int funct_group19_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_39(); + return side_effect; +} + +int funct_group19_40(); + +int funct_group19_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_40(); + return side_effect; +} + +int funct_group19_41(); + +int funct_group19_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_41(); + return side_effect; +} + +int funct_group19_42(); + +int funct_group19_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_42(); + return side_effect; +} + +int funct_group19_43(); + +int funct_group19_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_43(); + return side_effect; +} + +int funct_group19_44(); + +int funct_group19_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_44(); + return side_effect; +} + +int funct_group19_45(); + +int funct_group19_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_45(); + return side_effect; +} + +int funct_group19_46(); + +int funct_group19_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_46(); + return side_effect; +} + +int funct_group19_47(); + +int funct_group19_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_47(); + return side_effect; +} + +int funct_group19_48(); + +int funct_group19_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_48(); + return side_effect; +} + +int funct_group19_49(); + +int funct_group19_48() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_49(); + return side_effect; +} + +int funct_group19_50(); + +int funct_group19_49() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_50(); + return side_effect; +} + +int funct_group19_51(); + +int funct_group19_50() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_51(); + return side_effect; +} + +int funct_group19_52(); + +int funct_group19_51() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_52(); + return side_effect; +} + +int funct_group19_53(); + +int funct_group19_52() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_53(); + return side_effect; +} + +int funct_group19_54(); + +int funct_group19_53() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_54(); + return side_effect; +} + +int funct_group19_55(); + +int funct_group19_54() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_55(); + return side_effect; +} + +int funct_group19_56(); + +int funct_group19_55() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_56(); + return side_effect; +} + +int funct_group19_57(); + +int funct_group19_56() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_57(); + return side_effect; +} + +int funct_group19_58(); + +int funct_group19_57() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_58(); + return side_effect; +} + +int funct_group19_59(); + +int funct_group19_58() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_59(); + return side_effect; +} + +int funct_group19_60(); + +int funct_group19_59() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_60(); + return side_effect; +} + +int funct_group19_61(); + +int funct_group19_60() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_61(); + return side_effect; +} + +int funct_group19_62(); + +int funct_group19_61() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_62(); + return side_effect; +} + +int funct_group19_63(); + +int funct_group19_62() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_63(); + return side_effect; +} + +int funct_group19_64(); + +int funct_group19_63() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_64(); + return side_effect; +} + +int funct_group19_65(); + +int funct_group19_64() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_65(); + return side_effect; +} + +int funct_group19_66(); + +int funct_group19_65() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_66(); + return side_effect; +} + +int funct_group19_67(); + +int funct_group19_66() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_67(); + return side_effect; +} + +int funct_group19_68(); + +int funct_group19_67() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_68(); + return side_effect; +} + +int funct_group19_69(); + +int funct_group19_68() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_69(); + return side_effect; +} + +int funct_group19_70(); + +int funct_group19_69() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_70(); + return side_effect; +} + +int funct_group19_71(); + +int funct_group19_70() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_71(); + return side_effect; +} + +int funct_group19_72(); + +int funct_group19_71() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_72(); + return side_effect; +} + +int funct_group19_73(); + +int funct_group19_72() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_73(); + return side_effect; +} + +int funct_group19_74(); + +int funct_group19_73() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_74(); + return side_effect; +} + +int funct_group19_75(); + +int funct_group19_74() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_75(); + return side_effect; +} + +int funct_group19_76(); + +int funct_group19_75() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_76(); + return side_effect; +} + +int funct_group19_77(); + +int funct_group19_76() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_77(); + return side_effect; +} + +int funct_group19_78(); + +int funct_group19_77() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_78(); + return side_effect; +} + +int funct_group19_79(); + +int funct_group19_78() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_79(); + return side_effect; +} + +int funct_group19_80(); + +int funct_group19_79() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_80(); + return side_effect; +} + +int funct_group19_81(); + +int funct_group19_80() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_81(); + return side_effect; +} + +int funct_group19_82(); + +int funct_group19_81() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_82(); + return side_effect; +} + +int funct_group19_83(); + +int funct_group19_82() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_83(); + return side_effect; +} + +int funct_group19_84(); + +int funct_group19_83() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_84(); + return side_effect; +} + +int funct_group19_85(); + +int funct_group19_84() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_85(); + return side_effect; +} + +int funct_group19_86(); + +int funct_group19_85() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_86(); + return side_effect; +} + +int funct_group19_87(); + +int funct_group19_86() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_87(); + return side_effect; +} + +int funct_group19_88(); + +int funct_group19_87() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_88(); + return side_effect; +} + +int funct_group19_89(); + +int funct_group19_88() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_89(); + return side_effect; +} + +int funct_group19_90(); + +int funct_group19_89() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_90(); + return side_effect; +} + +int funct_group19_91(); + +int funct_group19_90() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_91(); + return side_effect; +} + +int funct_group19_92(); + +int funct_group19_91() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_92(); + return side_effect; +} + +int funct_group19_93(); + +int funct_group19_92() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_93(); + return side_effect; +} + +int funct_group19_94(); + +int funct_group19_93() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_94(); + return side_effect; +} + +int funct_group19_95(); + +int funct_group19_94() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_0 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group19_95(); + return side_effect; +} + +int funct_group19_95() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group20_1(); + +int funct_group20_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group20_1(); + return side_effect; +} + +int funct_group20_2(); + +int funct_group20_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group20_2(); + return side_effect; +} + +int funct_group20_3(); + +int funct_group20_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group20_3(); + return side_effect; +} + +int funct_group20_4(); + +int funct_group20_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group20_4(); + return side_effect; +} + +int funct_group20_5(); + +int funct_group20_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group20_5(); + return side_effect; +} + +int funct_group20_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group21_1(); + +int funct_group21_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_1(); + return side_effect; +} + +int funct_group21_2(); + +int funct_group21_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_2(); + return side_effect; +} + +int funct_group21_3(); + +int funct_group21_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_3(); + return side_effect; +} + +int funct_group21_4(); + +int funct_group21_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_4(); + return side_effect; +} + +int funct_group21_5(); + +int funct_group21_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_5(); + return side_effect; +} + +int funct_group21_6(); + +int funct_group21_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_6(); + return side_effect; +} + +int funct_group21_7(); + +int funct_group21_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_7(); + return side_effect; +} + +int funct_group21_8(); + +int funct_group21_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_8(); + return side_effect; +} + +int funct_group21_9(); + +int funct_group21_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_9(); + return side_effect; +} + +int funct_group21_10(); + +int funct_group21_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_10(); + return side_effect; +} + +int funct_group21_11(); + +int funct_group21_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group21_11(); + return side_effect; +} + +int funct_group21_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group22_1(); + +int funct_group22_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_1(); + return side_effect; +} + +int funct_group22_2(); + +int funct_group22_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_2(); + return side_effect; +} + +int funct_group22_3(); + +int funct_group22_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_3(); + return side_effect; +} + +int funct_group22_4(); + +int funct_group22_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_4(); + return side_effect; +} + +int funct_group22_5(); + +int funct_group22_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_5(); + return side_effect; +} + +int funct_group22_6(); + +int funct_group22_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_6(); + return side_effect; +} + +int funct_group22_7(); + +int funct_group22_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_7(); + return side_effect; +} + +int funct_group22_8(); + +int funct_group22_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_8(); + return side_effect; +} + +int funct_group22_9(); + +int funct_group22_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_9(); + return side_effect; +} + +int funct_group22_10(); + +int funct_group22_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_10(); + return side_effect; +} + +int funct_group22_11(); + +int funct_group22_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_11(); + return side_effect; +} + +int funct_group22_12(); + +int funct_group22_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_12(); + return side_effect; +} + +int funct_group22_13(); + +int funct_group22_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_13(); + return side_effect; +} + +int funct_group22_14(); + +int funct_group22_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_14(); + return side_effect; +} + +int funct_group22_15(); + +int funct_group22_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_15(); + return side_effect; +} + +int funct_group22_16(); + +int funct_group22_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_16(); + return side_effect; +} + +int funct_group22_17(); + +int funct_group22_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_17(); + return side_effect; +} + +int funct_group22_18(); + +int funct_group22_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_18(); + return side_effect; +} + +int funct_group22_19(); + +int funct_group22_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_19(); + return side_effect; +} + +int funct_group22_20(); + +int funct_group22_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_20(); + return side_effect; +} + +int funct_group22_21(); + +int funct_group22_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_21(); + return side_effect; +} + +int funct_group22_22(); + +int funct_group22_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_22(); + return side_effect; +} + +int funct_group22_23(); + +int funct_group22_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group22_23(); + return side_effect; +} + +int funct_group22_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group23_1(); + +int funct_group23_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_1(); + return side_effect; +} + +int funct_group23_2(); + +int funct_group23_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_2(); + return side_effect; +} + +int funct_group23_3(); + +int funct_group23_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_3(); + return side_effect; +} + +int funct_group23_4(); + +int funct_group23_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_4(); + return side_effect; +} + +int funct_group23_5(); + +int funct_group23_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_5(); + return side_effect; +} + +int funct_group23_6(); + +int funct_group23_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_6(); + return side_effect; +} + +int funct_group23_7(); + +int funct_group23_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_7(); + return side_effect; +} + +int funct_group23_8(); + +int funct_group23_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_8(); + return side_effect; +} + +int funct_group23_9(); + +int funct_group23_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_9(); + return side_effect; +} + +int funct_group23_10(); + +int funct_group23_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_10(); + return side_effect; +} + +int funct_group23_11(); + +int funct_group23_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_11(); + return side_effect; +} + +int funct_group23_12(); + +int funct_group23_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_12(); + return side_effect; +} + +int funct_group23_13(); + +int funct_group23_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_13(); + return side_effect; +} + +int funct_group23_14(); + +int funct_group23_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_14(); + return side_effect; +} + +int funct_group23_15(); + +int funct_group23_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_15(); + return side_effect; +} + +int funct_group23_16(); + +int funct_group23_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_16(); + return side_effect; +} + +int funct_group23_17(); + +int funct_group23_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_17(); + return side_effect; +} + +int funct_group23_18(); + +int funct_group23_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_18(); + return side_effect; +} + +int funct_group23_19(); + +int funct_group23_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_19(); + return side_effect; +} + +int funct_group23_20(); + +int funct_group23_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_20(); + return side_effect; +} + +int funct_group23_21(); + +int funct_group23_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_21(); + return side_effect; +} + +int funct_group23_22(); + +int funct_group23_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_22(); + return side_effect; +} + +int funct_group23_23(); + +int funct_group23_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_23(); + return side_effect; +} + +int funct_group23_24(); + +int funct_group23_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_24(); + return side_effect; +} + +int funct_group23_25(); + +int funct_group23_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_25(); + return side_effect; +} + +int funct_group23_26(); + +int funct_group23_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_26(); + return side_effect; +} + +int funct_group23_27(); + +int funct_group23_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_27(); + return side_effect; +} + +int funct_group23_28(); + +int funct_group23_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_28(); + return side_effect; +} + +int funct_group23_29(); + +int funct_group23_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_29(); + return side_effect; +} + +int funct_group23_30(); + +int funct_group23_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_30(); + return side_effect; +} + +int funct_group23_31(); + +int funct_group23_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_31(); + return side_effect; +} + +int funct_group23_32(); + +int funct_group23_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_32(); + return side_effect; +} + +int funct_group23_33(); + +int funct_group23_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_33(); + return side_effect; +} + +int funct_group23_34(); + +int funct_group23_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_34(); + return side_effect; +} + +int funct_group23_35(); + +int funct_group23_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_35(); + return side_effect; +} + +int funct_group23_36(); + +int funct_group23_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_36(); + return side_effect; +} + +int funct_group23_37(); + +int funct_group23_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_37(); + return side_effect; +} + +int funct_group23_38(); + +int funct_group23_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_38(); + return side_effect; +} + +int funct_group23_39(); + +int funct_group23_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_39(); + return side_effect; +} + +int funct_group23_40(); + +int funct_group23_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_40(); + return side_effect; +} + +int funct_group23_41(); + +int funct_group23_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_41(); + return side_effect; +} + +int funct_group23_42(); + +int funct_group23_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_42(); + return side_effect; +} + +int funct_group23_43(); + +int funct_group23_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_43(); + return side_effect; +} + +int funct_group23_44(); + +int funct_group23_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_44(); + return side_effect; +} + +int funct_group23_45(); + +int funct_group23_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_45(); + return side_effect; +} + +int funct_group23_46(); + +int funct_group23_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_46(); + return side_effect; +} + +int funct_group23_47(); + +int funct_group23_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group23_47(); + return side_effect; +} + +int funct_group23_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} + +int funct_group24_1(); + +int funct_group24_0() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_1(); + return side_effect; +} + +int funct_group24_2(); + +int funct_group24_1() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_2(); + return side_effect; +} + +int funct_group24_3(); + +int funct_group24_2() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_3(); + return side_effect; +} + +int funct_group24_4(); + +int funct_group24_3() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_4(); + return side_effect; +} + +int funct_group24_5(); + +int funct_group24_4() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_5(); + return side_effect; +} + +int funct_group24_6(); + +int funct_group24_5() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_6(); + return side_effect; +} + +int funct_group24_7(); + +int funct_group24_6() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_7(); + return side_effect; +} + +int funct_group24_8(); + +int funct_group24_7() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_8(); + return side_effect; +} + +int funct_group24_9(); + +int funct_group24_8() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_9(); + return side_effect; +} + +int funct_group24_10(); + +int funct_group24_9() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_10(); + return side_effect; +} + +int funct_group24_11(); + +int funct_group24_10() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_11(); + return side_effect; +} + +int funct_group24_12(); + +int funct_group24_11() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_12(); + return side_effect; +} + +int funct_group24_13(); + +int funct_group24_12() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_13(); + return side_effect; +} + +int funct_group24_14(); + +int funct_group24_13() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_14(); + return side_effect; +} + +int funct_group24_15(); + +int funct_group24_14() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_15(); + return side_effect; +} + +int funct_group24_16(); + +int funct_group24_15() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_16(); + return side_effect; +} + +int funct_group24_17(); + +int funct_group24_16() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_17(); + return side_effect; +} + +int funct_group24_18(); + +int funct_group24_17() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_18(); + return side_effect; +} + +int funct_group24_19(); + +int funct_group24_18() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_19(); + return side_effect; +} + +int funct_group24_20(); + +int funct_group24_19() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_20(); + return side_effect; +} + +int funct_group24_21(); + +int funct_group24_20() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_21(); + return side_effect; +} + +int funct_group24_22(); + +int funct_group24_21() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_22(); + return side_effect; +} + +int funct_group24_23(); + +int funct_group24_22() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_23(); + return side_effect; +} + +int funct_group24_24(); + +int funct_group24_23() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_24(); + return side_effect; +} + +int funct_group24_25(); + +int funct_group24_24() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_25(); + return side_effect; +} + +int funct_group24_26(); + +int funct_group24_25() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_26(); + return side_effect; +} + +int funct_group24_27(); + +int funct_group24_26() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_27(); + return side_effect; +} + +int funct_group24_28(); + +int funct_group24_27() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_28(); + return side_effect; +} + +int funct_group24_29(); + +int funct_group24_28() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_29(); + return side_effect; +} + +int funct_group24_30(); + +int funct_group24_29() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_30(); + return side_effect; +} + +int funct_group24_31(); + +int funct_group24_30() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_31(); + return side_effect; +} + +int funct_group24_32(); + +int funct_group24_31() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_32(); + return side_effect; +} + +int funct_group24_33(); + +int funct_group24_32() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_33(); + return side_effect; +} + +int funct_group24_34(); + +int funct_group24_33() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_34(); + return side_effect; +} + +int funct_group24_35(); + +int funct_group24_34() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_35(); + return side_effect; +} + +int funct_group24_36(); + +int funct_group24_35() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_36(); + return side_effect; +} + +int funct_group24_37(); + +int funct_group24_36() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_37(); + return side_effect; +} + +int funct_group24_38(); + +int funct_group24_37() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_38(); + return side_effect; +} + +int funct_group24_39(); + +int funct_group24_38() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_39(); + return side_effect; +} + +int funct_group24_40(); + +int funct_group24_39() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_40(); + return side_effect; +} + +int funct_group24_41(); + +int funct_group24_40() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_41(); + return side_effect; +} + +int funct_group24_42(); + +int funct_group24_41() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_42(); + return side_effect; +} + +int funct_group24_43(); + +int funct_group24_42() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_43(); + return side_effect; +} + +int funct_group24_44(); + +int funct_group24_43() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_44(); + return side_effect; +} + +int funct_group24_45(); + +int funct_group24_44() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_45(); + return side_effect; +} + +int funct_group24_46(); + +int funct_group24_45() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_46(); + return side_effect; +} + +int funct_group24_47(); + +int funct_group24_46() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_47(); + return side_effect; +} + +int funct_group24_48(); + +int funct_group24_47() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_48(); + return side_effect; +} + +int funct_group24_49(); + +int funct_group24_48() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_49(); + return side_effect; +} + +int funct_group24_50(); + +int funct_group24_49() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_50(); + return side_effect; +} + +int funct_group24_51(); + +int funct_group24_50() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_51(); + return side_effect; +} + +int funct_group24_52(); + +int funct_group24_51() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_52(); + return side_effect; +} + +int funct_group24_53(); + +int funct_group24_52() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_53(); + return side_effect; +} + +int funct_group24_54(); + +int funct_group24_53() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_54(); + return side_effect; +} + +int funct_group24_55(); + +int funct_group24_54() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_55(); + return side_effect; +} + +int funct_group24_56(); + +int funct_group24_55() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_56(); + return side_effect; +} + +int funct_group24_57(); + +int funct_group24_56() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_57(); + return side_effect; +} + +int funct_group24_58(); + +int funct_group24_57() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_58(); + return side_effect; +} + +int funct_group24_59(); + +int funct_group24_58() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_59(); + return side_effect; +} + +int funct_group24_60(); + +int funct_group24_59() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_60(); + return side_effect; +} + +int funct_group24_61(); + +int funct_group24_60() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_61(); + return side_effect; +} + +int funct_group24_62(); + +int funct_group24_61() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_62(); + return side_effect; +} + +int funct_group24_63(); + +int funct_group24_62() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_63(); + return side_effect; +} + +int funct_group24_64(); + +int funct_group24_63() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_64(); + return side_effect; +} + +int funct_group24_65(); + +int funct_group24_64() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_65(); + return side_effect; +} + +int funct_group24_66(); + +int funct_group24_65() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_66(); + return side_effect; +} + +int funct_group24_67(); + +int funct_group24_66() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_67(); + return side_effect; +} + +int funct_group24_68(); + +int funct_group24_67() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_68(); + return side_effect; +} + +int funct_group24_69(); + +int funct_group24_68() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_69(); + return side_effect; +} + +int funct_group24_70(); + +int funct_group24_69() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_70(); + return side_effect; +} + +int funct_group24_71(); + +int funct_group24_70() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_71(); + return side_effect; +} + +int funct_group24_72(); + +int funct_group24_71() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_72(); + return side_effect; +} + +int funct_group24_73(); + +int funct_group24_72() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_73(); + return side_effect; +} + +int funct_group24_74(); + +int funct_group24_73() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_74(); + return side_effect; +} + +int funct_group24_75(); + +int funct_group24_74() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_75(); + return side_effect; +} + +int funct_group24_76(); + +int funct_group24_75() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_76(); + return side_effect; +} + +int funct_group24_77(); + +int funct_group24_76() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_77(); + return side_effect; +} + +int funct_group24_78(); + +int funct_group24_77() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_78(); + return side_effect; +} + +int funct_group24_79(); + +int funct_group24_78() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_79(); + return side_effect; +} + +int funct_group24_80(); + +int funct_group24_79() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_80(); + return side_effect; +} + +int funct_group24_81(); + +int funct_group24_80() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_81(); + return side_effect; +} + +int funct_group24_82(); + +int funct_group24_81() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_82(); + return side_effect; +} + +int funct_group24_83(); + +int funct_group24_82() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_83(); + return side_effect; +} + +int funct_group24_84(); + +int funct_group24_83() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_84(); + return side_effect; +} + +int funct_group24_85(); + +int funct_group24_84() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_85(); + return side_effect; +} + +int funct_group24_86(); + +int funct_group24_85() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_86(); + return side_effect; +} + +int funct_group24_87(); + +int funct_group24_86() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_87(); + return side_effect; +} + +int funct_group24_88(); + +int funct_group24_87() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_88(); + return side_effect; +} + +int funct_group24_89(); + +int funct_group24_88() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_89(); + return side_effect; +} + +int funct_group24_90(); + +int funct_group24_89() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_90(); + return side_effect; +} + +int funct_group24_91(); + +int funct_group24_90() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_91(); + return side_effect; +} + +int funct_group24_92(); + +int funct_group24_91() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_92(); + return side_effect; +} + +int funct_group24_93(); + +int funct_group24_92() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_93(); + return side_effect; +} + +int funct_group24_94(); + +int funct_group24_93() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_94(); + return side_effect; +} + +int funct_group24_95(); + +int funct_group24_94() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + side_effect = side_effect + funct_group24_95(); + return side_effect; +} + +int funct_group24_95() +{ + static std::uint32_t volatile inner_side_effect = 0; + inner_side_effect = inner_side_effect + 1; + class_1 instance_0(side_effect); + instance_0.trigger(); + + if (side_effect > 0) { + start_cycles = resources->clock->uptime(); + throw my_error_t{ .data = { 0xDE, 0xAD } }; + } + + return side_effect; +} +#endif \ No newline at end of file diff --git a/notes.md b/notes.md new file mode 100644 index 0000000..00a5ce7 --- /dev/null +++ b/notes.md @@ -0,0 +1,7 @@ +# things I changed + +- Reduced the number of instructions for capture +- Used array prefix for the pointers in pop reg range and just add at the end rather than incrementing the pointer each time +- Combine pop under mask because the order was wrong. We need all 15 bits to start from 0 to have the order be correct. Not 12 to 15 then 5 to 11 +- Use bit_cast<> in `to_absolute_address` & `to_absolute_address_ptr`. +- Reduce the instructions for `restore_cpu_state` \ No newline at end of file diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index a194fc5..b8be97b 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -66,21 +66,21 @@ exception_ptr current_exception() noexcept inline void capture_cpu_core(ke::cortex_m_cpu& p_cpu_core) { - asm volatile("mrs r0, MSP\n" // Move Main Stack Pointer to r0 - "stmia %0, {r0-r12}\n" // Store r0 to r12 into the array - "mov r0, SP\n" // Move SP to r0 - "str r0, [%0, #52]\n" // Store SP at the appropriate index - "mov r0, LR\n" // Move LR to r0 - "str r0, [%0, #56]\n" // Store LR at the appropriate index - "mov r0, PC\n" // Move PC to r0 - "str r0, [%0, #60]\n" // Store PC at the appropriate index + // We only capture r4 to r12 because __cxa_throw & __cxa_rethrow should be + // normal functions. Meaning they will not utilize the `sp = r[nnnn]` + // instruction, meaning that the callee unpreserved registers can be left + // alone. + asm volatile("mov r0, pc\n" // Move PC to r0 (Before pipeline) + "stmia %0, {r4-r12}\n" // Store r4 to r12 into the array + "str sp, [%0, #52]\n" // Store SP @ 52 + "str lr, [%0, #56]\n" // Store LR @ 56 + "str r0, [%0, #60]\n" // Store PC @ 60 : // no output : "r"(&p_cpu_core) // input is the address of the array : "r0" // r0 is being modified ); } - struct index_less_than { bool operator()(index_entry_t const& left, index_entry_t const& right) @@ -169,9 +169,9 @@ index_entry_t const& get_index_entry(std::uint32_t p_program_counter) } template -T const volatile* as(void const volatile* p_ptr) +T const* as(void const* p_ptr) { - return reinterpret_cast(p_ptr); + return reinterpret_cast(p_ptr); } /** @@ -309,6 +309,8 @@ class action_decoder std::type_info const* get_next_catch_type() { + // TODO(kammce): This isn't how it actually works. This needs to be + // corrected. if (m_action == nullptr) { return nullptr; } @@ -345,25 +347,26 @@ class action_decoder inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) { +#if 0 asm volatile( - "ldr r0, [%[regs], #0]\n" // Load R0 - "ldr r1, [%[regs], #4]\n" // Load R1 - "ldr r2, [%[regs], #8]\n" // Load R2 + "ldr r0, [%[reg], #0]\n" // Load R0 + "ldr r1, [%[reg], #4]\n" // Load R1 + "ldr r2, [%[reg], #8]\n" // Load R2 // Skip loading R3, R3 will be used for loading all other registers - "ldr r4, [%[regs], #16]\n" // Load R4 - "ldr r5, [%[regs], #20]\n" // Load R5 - "ldr r6, [%[regs], #24]\n" // Load R6 - "ldr r7, [%[regs], #28]\n" // Load R7 - "ldr r8, [%[regs], #32]\n" // Load R8 - "ldr r9, [%[regs], #36]\n" // Load R9 - "ldr r10, [%[regs], #40]\n" // Load R10 - "ldr r11, [%[regs], #44]\n" // Load R11 - "ldr r12, [%[regs], #48]\n" // Load R12 - "ldr sp, [%[regs], #52]\n" // Load SP - "ldr lr, [%[regs], #56]\n" // Load LR - "ldr pc, [%[regs], #60]\n" // Load PC + "ldr r4, [%[reg], #16]\n" // Load R4 + "ldr r5, [%[reg], #20]\n" // Load R5 + "ldr r6, [%[reg], #24]\n" // Load R6 + "ldr r7, [%[reg], #28]\n" // Load R7 + "ldr r8, [%[reg], #32]\n" // Load R8 + "ldr r9, [%[reg], #36]\n" // Load R9 + "ldr r10, [%[reg], #40]\n" // Load R10 + "ldr r11, [%[reg], #44]\n" // Load R11 + "ldr r12, [%[reg], #48]\n" // Load R12 + "ldr sp, [%[reg], #52]\n" // Load SP + "ldr lr, [%[reg], #56]\n" // Load LR + "ldr pc, [%[reg], #60]\n" // Load PC : - : [regs] "r"(&p_cpu_core) + : [reg] "r"(&p_cpu_core) : "memory", "r0", "r1", @@ -381,6 +384,33 @@ inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) "r12", "lr", "pc"); +#else + asm volatile("ldmia.w %[reg], {r0, r1, r2}\n" + "add %[reg], #12\n" + "ldmia.w %[reg], {r4, r5, r6, r7, r8, r9, r10, r11, r12}\n" + "ldr sp, [%[reg], #40]\n" // Load SP + "ldr lr, [%[reg], #44]\n" // Load LR + "ldr pc, [%[reg], #48]\n" // Load PC + : + : [reg] "r"(&p_cpu_core) + : "memory", + "r0", + "r1", + "r2", + // skip r3 & use it as the offset register + "r4", + "r5", + "r6", + "r7", + "fp", + "r8", + "r9", + "r10", + "r11", + "r12", + "lr", + "pc"); +#endif } inline void enter_function(exception_object& p_exception_object) @@ -461,7 +491,7 @@ inline void enter_function(exception_object& p_exception_object) template constexpr std::uint32_t vsp_deallocate_amount() { - return (Amount << 2); + return Amount + 1; } enum class pop_lr @@ -510,16 +540,20 @@ inline std::uint32_t const* pop_register_range(std::uint32_t const* sp_ptr, *(r4_pointer++) = *(sp_ptr++); } #else - for (std::size_t i = 0; i < PopCount + 1; i++) { - *(r4_pointer++) = *(sp_ptr++); + if constexpr (PopCount == 0) { + *r4_pointer = *(sp_ptr++); + } else { + for (std::size_t i = 0; i < PopCount + 1; i++) { + r4_pointer[i] = sp_ptr[i]; + } } #endif if constexpr (PopLinkRegister == pop_lr::do_it) { - p_virtual_cpu.lr = *(sp_ptr++); + p_virtual_cpu.lr = sp_ptr[PopCount + 1]; } - return sp_ptr; + return sp_ptr + PopCount + 1 + unsigned{ PopLinkRegister == pop_lr::do_it }; } void unwind_frame(instructions_t const& p_instructions, @@ -904,42 +938,44 @@ void unwind_frame(instructions_t const& p_instructions, // loop here rather than unroll this loop. Unless there is some incentive to // improve the performance for this instruction. - // Get the previous instruction and save it to the u32_storage - u32_storage = *(instruction_ptr - 1); + // Save the lower 4-bits of the previous instruction and the 8-bits of the + // current instruction and combine them. + u32_storage = *(instruction_ptr - 1) & 0xF; + u32_storage <<= 8; + u32_storage |= *(instruction_ptr); if (u32_storage & (1 << 3)) { move_lr_to_pc = false; } + // TODO(kammce): consider (remark b) + // ======================================================================== + // > ‘Pop’ generally denotes removal from the stack commencing at current + // > vsp, with subsequent increment of vsp to beyond the removed quantities. + // > The sole exception to this rule is popping r13, when the writeback of + // > the loaded value to vsp is delayed until after the whole instruction + // > has completed. When multiple registers are popped by a single + // > instruction they are taken as lowest numbered register at lowest stack + // > address. + // ========================================================================= + while (u32_storage) { // Get the first 1's distance from the right. We add 12 because the // mask's first bit represents r4 and increases from there. The first // byte, the instruction byte, only contains the registers from 12 // to 15. - std::uint32_t lsb_bit_position = std::countr_zero(u32_storage) + 12U; - // Copy value from the stack, increment stack pointer. - virtual_cpu[lsb_bit_position] = *(sp_ptr++); + std::uint32_t lsb_bit_position = std::countr_zero(u32_storage); // Clear the bit for the lsb_bit_position u32_storage = u32_storage & ~(1 << lsb_bit_position); - } - - u32_storage = *(instruction_ptr); - - while (u32_storage) { - // Get the first 1's distance from the right. We add 4 because the mask's - // first bit represents r4 and increases from there. - std::uint32_t lsb_bit_position = std::countr_zero(u32_storage) + 4U; // Copy value from the stack, increment stack pointer. - virtual_cpu[lsb_bit_position] = *(sp_ptr++); - // Clear the bit for the lsb_bit_position - u32_storage = u32_storage & ~(1 << lsb_bit_position); + virtual_cpu[lsb_bit_position + 4U] = *(sp_ptr++); } instruction_ptr++; continue; // +=========================================================================+ - // | VSP = R[nnnn] | + // | VSP = R[nnnn] | // +=========================================================================+ assign_to_vsp_to_reg_nnnn: // Get the current instruction and get all lower 4-bits @@ -1007,392 +1043,392 @@ void unwind_frame(instructions_t const& p_instructions, // | Add VSP | // +=========================================================================+ vsp_add_0: - sp_ptr += vsp_deallocate_amount<0>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<0>(); continue; vsp_add_1: - sp_ptr += vsp_deallocate_amount<1>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<1>(); continue; vsp_add_2: - sp_ptr += vsp_deallocate_amount<2>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<2>(); continue; vsp_add_3: - sp_ptr += vsp_deallocate_amount<3>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<3>(); continue; vsp_add_4: - sp_ptr += vsp_deallocate_amount<4>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<4>(); continue; vsp_add_5: - sp_ptr += vsp_deallocate_amount<5>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<5>(); continue; vsp_add_6: - sp_ptr += vsp_deallocate_amount<6>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<6>(); continue; vsp_add_7: - sp_ptr += vsp_deallocate_amount<7>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<7>(); continue; vsp_add_8: - sp_ptr += vsp_deallocate_amount<8>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<8>(); continue; vsp_add_9: - sp_ptr += vsp_deallocate_amount<9>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<9>(); continue; vsp_add_10: - sp_ptr += vsp_deallocate_amount<10>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<10>(); continue; vsp_add_11: - sp_ptr += vsp_deallocate_amount<11>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<11>(); continue; vsp_add_12: - sp_ptr += vsp_deallocate_amount<12>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<12>(); continue; vsp_add_13: - sp_ptr += vsp_deallocate_amount<13>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<13>(); continue; vsp_add_14: - sp_ptr += vsp_deallocate_amount<14>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<14>(); continue; vsp_add_15: - sp_ptr += vsp_deallocate_amount<15>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<15>(); continue; vsp_add_16: - sp_ptr += vsp_deallocate_amount<16>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<16>(); continue; vsp_add_17: - sp_ptr += vsp_deallocate_amount<17>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<17>(); continue; vsp_add_18: - sp_ptr += vsp_deallocate_amount<18>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<18>(); continue; vsp_add_19: - sp_ptr += vsp_deallocate_amount<19>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<19>(); continue; vsp_add_20: - sp_ptr += vsp_deallocate_amount<20>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<20>(); continue; vsp_add_21: - sp_ptr += vsp_deallocate_amount<21>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<21>(); continue; vsp_add_22: - sp_ptr += vsp_deallocate_amount<22>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<22>(); continue; vsp_add_23: - sp_ptr += vsp_deallocate_amount<23>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<23>(); continue; vsp_add_24: - sp_ptr += vsp_deallocate_amount<24>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<24>(); continue; vsp_add_25: - sp_ptr += vsp_deallocate_amount<25>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<25>(); continue; vsp_add_26: - sp_ptr += vsp_deallocate_amount<26>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<26>(); continue; vsp_add_27: - sp_ptr += vsp_deallocate_amount<27>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<27>(); continue; vsp_add_28: - sp_ptr += vsp_deallocate_amount<28>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<28>(); continue; vsp_add_29: - sp_ptr += vsp_deallocate_amount<29>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<29>(); continue; vsp_add_30: - sp_ptr += vsp_deallocate_amount<30>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<30>(); continue; vsp_add_31: - sp_ptr += vsp_deallocate_amount<31>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<31>(); continue; vsp_add_32: - sp_ptr += vsp_deallocate_amount<32>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<32>(); continue; vsp_add_33: - sp_ptr += vsp_deallocate_amount<33>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<33>(); continue; vsp_add_34: - sp_ptr += vsp_deallocate_amount<34>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<34>(); continue; vsp_add_35: - sp_ptr += vsp_deallocate_amount<35>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<35>(); continue; vsp_add_36: - sp_ptr += vsp_deallocate_amount<36>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<36>(); continue; vsp_add_37: - sp_ptr += vsp_deallocate_amount<37>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<37>(); continue; vsp_add_38: - sp_ptr += vsp_deallocate_amount<38>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<38>(); continue; vsp_add_39: - sp_ptr += vsp_deallocate_amount<39>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<39>(); continue; vsp_add_40: - sp_ptr += vsp_deallocate_amount<40>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<40>(); continue; vsp_add_41: - sp_ptr += vsp_deallocate_amount<41>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<41>(); continue; vsp_add_42: - sp_ptr += vsp_deallocate_amount<42>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<42>(); continue; vsp_add_43: - sp_ptr += vsp_deallocate_amount<43>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<43>(); continue; vsp_add_44: - sp_ptr += vsp_deallocate_amount<44>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<44>(); continue; vsp_add_45: - sp_ptr += vsp_deallocate_amount<45>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<45>(); continue; vsp_add_46: - sp_ptr += vsp_deallocate_amount<46>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<46>(); continue; vsp_add_47: - sp_ptr += vsp_deallocate_amount<47>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<47>(); continue; vsp_add_48: - sp_ptr += vsp_deallocate_amount<48>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<48>(); continue; vsp_add_49: - sp_ptr += vsp_deallocate_amount<49>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<49>(); continue; vsp_add_50: - sp_ptr += vsp_deallocate_amount<50>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<50>(); continue; vsp_add_51: - sp_ptr += vsp_deallocate_amount<51>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<51>(); continue; vsp_add_52: - sp_ptr += vsp_deallocate_amount<52>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<52>(); continue; vsp_add_53: - sp_ptr += vsp_deallocate_amount<53>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<53>(); continue; vsp_add_54: - sp_ptr += vsp_deallocate_amount<54>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<54>(); continue; vsp_add_55: - sp_ptr += vsp_deallocate_amount<55>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<55>(); continue; vsp_add_56: - sp_ptr += vsp_deallocate_amount<56>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<56>(); continue; vsp_add_57: - sp_ptr += vsp_deallocate_amount<57>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<57>(); continue; vsp_add_58: - sp_ptr += vsp_deallocate_amount<58>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<58>(); continue; vsp_add_59: - sp_ptr += vsp_deallocate_amount<59>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<59>(); continue; vsp_add_60: - sp_ptr += vsp_deallocate_amount<60>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<60>(); continue; vsp_add_61: - sp_ptr += vsp_deallocate_amount<61>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<61>(); continue; vsp_add_62: - sp_ptr += vsp_deallocate_amount<62>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<62>(); continue; vsp_add_63: - sp_ptr += vsp_deallocate_amount<63>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<63>(); continue; // +=========================================================================+ // | Sub VSP | // +=========================================================================+ vsp_sub_0: - sp_ptr -= vsp_deallocate_amount<0>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<0>(); continue; vsp_sub_1: - sp_ptr -= vsp_deallocate_amount<1>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<1>(); continue; vsp_sub_2: - sp_ptr -= vsp_deallocate_amount<2>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<2>(); continue; vsp_sub_3: - sp_ptr -= vsp_deallocate_amount<3>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<3>(); continue; vsp_sub_4: - sp_ptr -= vsp_deallocate_amount<4>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<4>(); continue; vsp_sub_5: - sp_ptr -= vsp_deallocate_amount<5>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<5>(); continue; vsp_sub_6: - sp_ptr -= vsp_deallocate_amount<6>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<6>(); continue; vsp_sub_7: - sp_ptr -= vsp_deallocate_amount<7>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<7>(); continue; vsp_sub_8: - sp_ptr -= vsp_deallocate_amount<8>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<8>(); continue; vsp_sub_9: - sp_ptr -= vsp_deallocate_amount<9>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<9>(); continue; vsp_sub_10: - sp_ptr -= vsp_deallocate_amount<10>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<10>(); continue; vsp_sub_11: - sp_ptr -= vsp_deallocate_amount<11>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<11>(); continue; vsp_sub_12: - sp_ptr -= vsp_deallocate_amount<12>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<12>(); continue; vsp_sub_13: - sp_ptr -= vsp_deallocate_amount<13>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<13>(); continue; vsp_sub_14: - sp_ptr -= vsp_deallocate_amount<14>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<14>(); continue; vsp_sub_15: - sp_ptr -= vsp_deallocate_amount<15>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<15>(); continue; vsp_sub_16: - sp_ptr -= vsp_deallocate_amount<16>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<16>(); continue; vsp_sub_17: - sp_ptr -= vsp_deallocate_amount<17>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<17>(); continue; vsp_sub_18: - sp_ptr -= vsp_deallocate_amount<18>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<18>(); continue; vsp_sub_19: - sp_ptr -= vsp_deallocate_amount<19>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<19>(); continue; vsp_sub_20: - sp_ptr -= vsp_deallocate_amount<20>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<20>(); continue; vsp_sub_21: - sp_ptr -= vsp_deallocate_amount<21>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<21>(); continue; vsp_sub_22: - sp_ptr -= vsp_deallocate_amount<22>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<22>(); continue; vsp_sub_23: - sp_ptr -= vsp_deallocate_amount<23>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<23>(); continue; vsp_sub_24: - sp_ptr -= vsp_deallocate_amount<24>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<24>(); continue; vsp_sub_25: - sp_ptr -= vsp_deallocate_amount<25>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<25>(); continue; vsp_sub_26: - sp_ptr -= vsp_deallocate_amount<26>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<26>(); continue; vsp_sub_27: - sp_ptr -= vsp_deallocate_amount<27>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<27>(); continue; vsp_sub_28: - sp_ptr -= vsp_deallocate_amount<28>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<28>(); continue; vsp_sub_29: - sp_ptr -= vsp_deallocate_amount<29>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<29>(); continue; vsp_sub_30: - sp_ptr -= vsp_deallocate_amount<30>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<30>(); continue; vsp_sub_31: - sp_ptr -= vsp_deallocate_amount<31>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<31>(); continue; vsp_sub_32: - sp_ptr -= vsp_deallocate_amount<32>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<32>(); continue; vsp_sub_33: - sp_ptr -= vsp_deallocate_amount<33>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<33>(); continue; vsp_sub_34: - sp_ptr -= vsp_deallocate_amount<34>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<34>(); continue; vsp_sub_35: - sp_ptr -= vsp_deallocate_amount<35>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<35>(); continue; vsp_sub_36: - sp_ptr -= vsp_deallocate_amount<36>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<36>(); continue; vsp_sub_37: - sp_ptr -= vsp_deallocate_amount<37>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<37>(); continue; vsp_sub_38: - sp_ptr -= vsp_deallocate_amount<38>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<38>(); continue; vsp_sub_39: - sp_ptr -= vsp_deallocate_amount<39>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<39>(); continue; vsp_sub_40: - sp_ptr -= vsp_deallocate_amount<40>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<40>(); continue; vsp_sub_41: - sp_ptr -= vsp_deallocate_amount<41>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<41>(); continue; vsp_sub_42: - sp_ptr -= vsp_deallocate_amount<42>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<42>(); continue; vsp_sub_43: - sp_ptr -= vsp_deallocate_amount<43>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<43>(); continue; vsp_sub_44: - sp_ptr -= vsp_deallocate_amount<44>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<44>(); continue; vsp_sub_45: - sp_ptr -= vsp_deallocate_amount<45>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<45>(); continue; vsp_sub_46: - sp_ptr -= vsp_deallocate_amount<46>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<46>(); continue; vsp_sub_47: - sp_ptr -= vsp_deallocate_amount<47>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<47>(); continue; vsp_sub_48: - sp_ptr -= vsp_deallocate_amount<48>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<48>(); continue; vsp_sub_49: - sp_ptr -= vsp_deallocate_amount<49>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<49>(); continue; vsp_sub_50: - sp_ptr -= vsp_deallocate_amount<50>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<50>(); continue; vsp_sub_51: - sp_ptr -= vsp_deallocate_amount<51>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<51>(); continue; vsp_sub_52: - sp_ptr -= vsp_deallocate_amount<52>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<52>(); continue; vsp_sub_53: - sp_ptr -= vsp_deallocate_amount<53>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<53>(); continue; vsp_sub_54: - sp_ptr -= vsp_deallocate_amount<54>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<54>(); continue; vsp_sub_55: - sp_ptr -= vsp_deallocate_amount<55>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<55>(); continue; vsp_sub_56: - sp_ptr -= vsp_deallocate_amount<56>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<56>(); continue; vsp_sub_57: - sp_ptr -= vsp_deallocate_amount<57>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<57>(); continue; vsp_sub_58: - sp_ptr -= vsp_deallocate_amount<58>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<58>(); continue; vsp_sub_59: - sp_ptr -= vsp_deallocate_amount<59>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<59>(); continue; vsp_sub_60: - sp_ptr -= vsp_deallocate_amount<60>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<60>(); continue; vsp_sub_61: - sp_ptr -= vsp_deallocate_amount<61>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<61>(); continue; vsp_sub_62: - sp_ptr -= vsp_deallocate_amount<62>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<62>(); continue; vsp_sub_63: - sp_ptr -= vsp_deallocate_amount<63>(); + sp_ptr = sp_ptr + vsp_deallocate_amount<63>(); continue; } @@ -1709,7 +1745,12 @@ extern "C" exception_object.cpu.pc = stack_pointer[1]; exception_object.cpu.sp = stack_pointer + 2; #elif OPTIMIZATION_LEVEL == Release -#error "Sorry Release mode unwinding is not supported yet."; + std::uint32_t const* stack_pointer = *exception_object.cpu.sp; + exception_object.cpu.r3 = stack_pointer[0]; + exception_object.cpu.r4 = stack_pointer[1]; + exception_object.cpu.r5 = stack_pointer[2]; + exception_object.cpu.pc = stack_pointer[3]; + exception_object.cpu.sp = stack_pointer + 4; #elif OPTIMIZATION_LEVEL == RelWithDebInfo #error "Sorry Release mode unwinding is not supported yet."; #endif @@ -1745,7 +1786,10 @@ extern "C" exception_object.cpu.pc = stack_pointer[1]; exception_object.cpu.sp = stack_pointer + 2; #elif OPTIMIZATION_LEVEL == Release -#error "Sorry Release mode unwinding is not supported yet."; + std::uint32_t const* stack_pointer = *exception_object.cpu.sp; + exception_object.cpu.r4 = stack_pointer[0]; + exception_object.cpu.pc = stack_pointer[1]; + exception_object.cpu.sp = stack_pointer + 2; #elif OPTIMIZATION_LEVEL == RelWithDebInfo #error "Sorry Release mode unwinding is not supported yet."; #endif diff --git a/src/arm_cortex/estell/internal.hpp b/src/arm_cortex/estell/internal.hpp index 105f4f6..0eeb910 100644 --- a/src/arm_cortex/estell/internal.hpp +++ b/src/arm_cortex/estell/internal.hpp @@ -15,8 +15,10 @@ #pragma once #include +#include #include #include +#include #include @@ -62,12 +64,12 @@ constexpr std::uint32_t end_descriptor = 0x0000'0000; constexpr std::uint32_t su16_mask = 0b1111'1111'1111'1110; } // namespace arm_ehabi -std::uint32_t to_absolute_address(void const* p_object) +inline std::uint32_t to_absolute_address(void const* p_object) { constexpr auto signed_bit_31 = hal::bit_mask::from<30>(); constexpr auto signed_bit_32 = hal::bit_mask::from<31>(); - auto object_address = reinterpret_cast(p_object); - auto offset = *reinterpret_cast(p_object); + auto object_address = std::bit_cast(p_object); + auto offset = *std::bit_cast(p_object); // Sign extend the offset to 32-bits if (hal::bit_extract(offset)) { @@ -89,7 +91,7 @@ std::uint32_t to_absolute_address(void const* p_object) inline std::uint32_t* to_absolute_address_ptr(void const* p_object) { - return reinterpret_cast(to_absolute_address(p_object)); + return std::bit_cast(to_absolute_address(p_object)); } // This is only to make GDB debugging easier, the functions are never actually @@ -262,34 +264,34 @@ struct cache_t .width = 24, }; - constexpr runtime_state state() const + constexpr inline runtime_state state() const { auto state_integer = hal::bit_extract(state_and_rel_address); return static_cast(state_integer); } - constexpr std::uint32_t relative_address() const + constexpr inline std::uint32_t relative_address() const { return hal::bit_extract(state_and_rel_address); } - void state(runtime_state p_state) + inline void state(runtime_state p_state) { auto state_int = static_cast(p_state); hal::bit_modify(state_and_rel_address).insert(state_int); } - void rethrown(bool p_rethrown) + inline void rethrown(bool p_rethrown) { hal::bit_modify(state_and_rel_address).insert(p_rethrown); } - constexpr bool rethrown() const + constexpr inline bool rethrown() const { return hal::bit_extract(state_and_rel_address); } - void relative_address(std::uint32_t p_rel_address) + inline void relative_address(std::uint32_t p_rel_address) { hal::bit_modify(state_and_rel_address) .insert(p_rel_address); From 8f29487f0f4aa8bfb3dd18aa443cac3351095ddf Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Thu, 18 Jul 2024 14:21:53 -0700 Subject: [PATCH 05/14] :zap: Many fixes and improvements --- conanfile.py | 10 ++++ demos/applications/multi_levels.cpp | 9 ++-- demos/applications/single_level.cpp | 27 ++++++++-- notes.md | 53 ++++++++++++++++++- src/arm_cortex/estell/exception.cpp | 81 ++++++++--------------------- src/arm_cortex/estell/internal.hpp | 39 +++++++++----- 6 files changed, 138 insertions(+), 81 deletions(-) diff --git a/conanfile.py b/conanfile.py index 297a96a..e5162e1 100644 --- a/conanfile.py +++ b/conanfile.py @@ -131,6 +131,16 @@ def package_info(self): "-Wl,--wrap=__cxa_end_catch", "-Wl,--wrap=__cxa_begin_catch", "-Wl,--wrap=__cxa_end_cleanup", + "-Wl,--wrap=__gnu_unwind_pr_common", + "-Wl,--wrap=__aeabi_unwind_cpp_pr0", + "-Wl,--wrap=_sig_func", + "-Wl,--wrap=__gxx_personality_v0", + "-Wl,--wrap=deregister_tm_clones", + "-Wl,--wrap=register_tm_clones", + # Ensure that all symbols are added to the linker's symbol table + "-Wl,--whole-archive", + lib_path, + "-Wl,--no-whole-archive", ]) # Keep this for now, will update this for the runtime select diff --git a/demos/applications/multi_levels.cpp b/demos/applications/multi_levels.cpp index acf3ad1..2b01412 100644 --- a/demos/applications/multi_levels.cpp +++ b/demos/applications/multi_levels.cpp @@ -69,7 +69,6 @@ void application(resource_list& p_resources) cycle_map.fill(0); happy_cycle_map.fill(std::numeric_limits::max()); - std::uint32_t index = 0; for (std::size_t i = 0; i < functions.size(); i++) { try { functions.at(i)(); @@ -79,12 +78,11 @@ void application(resource_list& p_resources) // is not in the correct location. } catch ([[maybe_unused]] my_error_t const& p_error) { end_cycles = resources->clock->uptime(); - cycle_map[index++] = end_cycles - start_cycles; + cycle_map[i] = end_cycles - start_cycles; } } - index = 0; - +#if 0 for (std::size_t i = 0; i < functions.size(); i++) { bool was_caught = false; try { @@ -96,9 +94,10 @@ void application(resource_list& p_resources) } if (!was_caught) { end_cycles = resources->clock->uptime(); - happy_cycle_map[index++] = end_cycles - start_cycles; + happy_cycle_map[i] = end_cycles - start_cycles; } } +#endif while (true) { continue; diff --git a/demos/applications/single_level.cpp b/demos/applications/single_level.cpp index 938ae2f..8482f23 100644 --- a/demos/applications/single_level.cpp +++ b/demos/applications/single_level.cpp @@ -26,6 +26,9 @@ struct error std::uint64_t start = 0; std::uint64_t end = 0; +std::uint64_t volatile entry_search_start = 0; +std::uint64_t volatile entry_search_end = 0; + void foo() { if (value) { @@ -33,16 +36,34 @@ void foo() throw error{ .data = value }; } } +namespace ke { +struct index_entry_t +{ + uint32_t a; + uint32_t b; +}; +extern index_entry_t const& get_index_entry(std::uint32_t p_program_counter); +} // namespace ke + +ke::index_entry_t const* global_index = nullptr; +std::uint64_t volatile search_time = 0; void application(resource_list& p_resources) { resources = &p_resources; + + entry_search_start = resources->clock->uptime(); + global_index = &ke::get_index_entry(reinterpret_cast(&foo)); + entry_search_end = resources->clock->uptime(); + + search_time = entry_search_end - entry_search_start; + try { foo(); } catch (error const& p_error) { end = resources->clock->uptime(); - while (true) { - continue; - } + } + while (true) { + continue; } } diff --git a/notes.md b/notes.md index 00a5ce7..2a01f71 100644 --- a/notes.md +++ b/notes.md @@ -4,4 +4,55 @@ - Used array prefix for the pointers in pop reg range and just add at the end rather than incrementing the pointer each time - Combine pop under mask because the order was wrong. We need all 15 bits to start from 0 to have the order be correct. Not 12 to 15 then 5 to 11 - Use bit_cast<> in `to_absolute_address` & `to_absolute_address_ptr`. -- Reduce the instructions for `restore_cpu_state` \ No newline at end of file +- Reduce the instructions for `restore_cpu_state` +- Remove shift variable in `read_uleb128` + +info registers +r0 0x7fffffff 2147483647 +r1 0x0 0 +r2 0x20000348 536871752 +r3 0x80012f5 134222581 +r4 0x20000348 536871752 +r5 0x20000118 536871192 +r6 0x20000278 536871544 +r7 0x20000358 536871768 +r8 0x7e 126 +r9 0x0 0 +r10 0x0 0 +r11 0x0 0 +r12 0x0 0 +sp 0x200027d0 0x200027d0 +lr 0x8001059 0x8001059 +pc 0x800107a 0x800107a +xpsr 0x61000000 1627389952 +msp 0x200027d0 0x200027d0 +psp 0x922f3724 0x922f3724 +primask 0x0 0 +control 0x0 0 +basepri 0x0 0 +faultmask 0x0 0 + +(gdb) info registers +r0 0x200001cc 536871372 +r1 0x1 1 +r2 0x8001085 134221957 +r3 0x20000188 536871304 +r4 0x20000348 536871752 +r5 0x20000118 536871192 +r6 0x0 0 +r7 0x0 0 +r8 0x7e 126 +r9 0x0 0 +r10 0x0 0 +r11 0x0 0 +r12 0x0 0 +sp 0x200027d0 0x200027d0 +lr 0x800108d 0x800108d +pc 0x800108c 0x800108c +xpsr 0x1000000 16777216 +msp 0x200027d0 0x200027d0 +psp 0x922f3724 0x922f3724 +primask 0x0 0 +control 0x0 0 +basepri 0x0 0 +faultmask 0x0 0 \ No newline at end of file diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index b8be97b..63a9182 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -14,10 +14,8 @@ #include #include -#include #include #include -#include #include #include "internal.hpp" @@ -66,19 +64,20 @@ exception_ptr current_exception() noexcept inline void capture_cpu_core(ke::cortex_m_cpu& p_cpu_core) { + register std::uint32_t* res asm("r3") = &p_cpu_core.r4.data; + // We only capture r4 to r12 because __cxa_throw & __cxa_rethrow should be // normal functions. Meaning they will not utilize the `sp = r[nnnn]` // instruction, meaning that the callee unpreserved registers can be left // alone. asm volatile("mov r0, pc\n" // Move PC to r0 (Before pipeline) - "stmia %0, {r4-r12}\n" // Store r4 to r12 into the array - "str sp, [%0, #52]\n" // Store SP @ 52 - "str lr, [%0, #56]\n" // Store LR @ 56 - "str r0, [%0, #60]\n" // Store PC @ 60 + "stmia r3, {r4-r12}\n" // Store r4 to r12 into the array @ &r4 + "str sp, [r3, #36]\n" // Store SP @ 36 + "str lr, [r3, #40]\n" // Store LR @ 40 + "str r0, [r3, #44]\n" // Store PC @ 44 : // no output - : "r"(&p_cpu_core) // input is the address of the array - : "r0" // r0 is being modified - ); + : "r"(res) // input is the address of the array + : "memory", "r0"); } struct index_less_than @@ -149,20 +148,20 @@ index_entry_t const& get_index_entry(std::uint32_t p_program_counter) std::uint8_t const** p_ptr) { std::uint32_t result = 0; - std::uint8_t shift_amount = 0; while (true) { constexpr auto more_data = hal::bit_mask::from<7>(); constexpr auto data = hal::bit_mask::from<0, 6>(); std::uint8_t const uleb128 = **p_ptr; - result |= hal::bit_extract(uleb128) << shift_amount; - shift_amount += 7; + result |= hal::bit_extract(uleb128); (*p_ptr)++; if (not hal::bit_extract(uleb128)) { break; } + + result <<= 7; } return result; @@ -347,50 +346,14 @@ class action_decoder inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) { -#if 0 - asm volatile( - "ldr r0, [%[reg], #0]\n" // Load R0 - "ldr r1, [%[reg], #4]\n" // Load R1 - "ldr r2, [%[reg], #8]\n" // Load R2 - // Skip loading R3, R3 will be used for loading all other registers - "ldr r4, [%[reg], #16]\n" // Load R4 - "ldr r5, [%[reg], #20]\n" // Load R5 - "ldr r6, [%[reg], #24]\n" // Load R6 - "ldr r7, [%[reg], #28]\n" // Load R7 - "ldr r8, [%[reg], #32]\n" // Load R8 - "ldr r9, [%[reg], #36]\n" // Load R9 - "ldr r10, [%[reg], #40]\n" // Load R10 - "ldr r11, [%[reg], #44]\n" // Load R11 - "ldr r12, [%[reg], #48]\n" // Load R12 - "ldr sp, [%[reg], #52]\n" // Load SP - "ldr lr, [%[reg], #56]\n" // Load LR - "ldr pc, [%[reg], #60]\n" // Load PC - : - : [reg] "r"(&p_cpu_core) - : "memory", - "r0", - "r1", - "r2", - // skip r3 & use it as the offset register - "r4", - "r5", - "r6", - "r7", - "fp", - "r8", - "r9", - "r10", - "r11", - "r12", - "lr", - "pc"); -#else - asm volatile("ldmia.w %[reg], {r0, r1, r2}\n" - "add %[reg], #12\n" + // Skip R2 because it is not used in the exception unwinding + // Skip R3 because we are using it + asm volatile("ldmia.w %[reg], {r0, r1}\n" // R3 is incremented by 8 + "add %[reg], #16\n" // Skip Past R2 + R3 "ldmia.w %[reg], {r4, r5, r6, r7, r8, r9, r10, r11, r12}\n" - "ldr sp, [%[reg], #40]\n" // Load SP - "ldr lr, [%[reg], #44]\n" // Load LR - "ldr pc, [%[reg], #48]\n" // Load PC + "ldr sp, [%[reg], #36]\n" // Load SP + "ldr lr, [%[reg], #40]\n" // Load LR + "ldr pc, [%[reg], #44]\n" // Load PC : : [reg] "r"(&p_cpu_core) : "memory", @@ -408,9 +371,9 @@ inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) "r10", "r11", "r12", + // sp skipped here as it is deprecated "lr", "pc"); -#endif } inline void enter_function(exception_object& p_exception_object) @@ -541,7 +504,7 @@ inline std::uint32_t const* pop_register_range(std::uint32_t const* sp_ptr, } #else if constexpr (PopCount == 0) { - *r4_pointer = *(sp_ptr++); + *r4_pointer = *sp_ptr; } else { for (std::size_t i = 0; i < PopCount + 1; i++) { r4_pointer[i] = sp_ptr[i]; @@ -895,8 +858,8 @@ void unwind_frame(instructions_t const& p_instructions, break; subtract_vsp_using_uleb128: - u32_storage = read_uleb128(&instruction_ptr); - sp_ptr += u32_storage; + static constexpr auto uleb128_offset = 0x204 / sizeof(std::uint32_t); + sp_ptr += read_uleb128(&instruction_ptr) + uleb128_offset; continue; pop_integer_registers_under_mask_r3_r2_r1_r0: diff --git a/src/arm_cortex/estell/internal.hpp b/src/arm_cortex/estell/internal.hpp index 0eeb910..d639151 100644 --- a/src/arm_cortex/estell/internal.hpp +++ b/src/arm_cortex/estell/internal.hpp @@ -66,6 +66,7 @@ constexpr std::uint32_t su16_mask = 0b1111'1111'1111'1110; inline std::uint32_t to_absolute_address(void const* p_object) { +#if 0 constexpr auto signed_bit_31 = hal::bit_mask::from<30>(); constexpr auto signed_bit_32 = hal::bit_mask::from<31>(); auto object_address = std::bit_cast(p_object); @@ -81,6 +82,19 @@ inline std::uint32_t to_absolute_address(void const* p_object) auto signed_offset = static_cast(offset); std::int32_t final_address = object_address + signed_offset; return static_cast(final_address); +#else + auto const object_address = std::bit_cast(p_object); + auto offset = *std::bit_cast(p_object); + + // Shift bits to the end + offset <<= 1; + // Arithmetic shift to the right to sign extend. + offset >>= 1; + + auto const final_address = object_address + offset; + return static_cast(final_address); + +#endif } [[gnu::used]] inline std::uint32_t runtime_to_absolute_address( @@ -248,8 +262,10 @@ enum class runtime_state : std::uint8_t struct cache_t { - std::uint32_t state_and_rel_address; + std::uint32_t rel_address; index_entry_t const* entry_ptr = nullptr; + runtime_state inner_state; + bool previously_rethrown = false; static constexpr auto state_mask = hal::bit_mask{ .position = 24, @@ -266,35 +282,32 @@ struct cache_t constexpr inline runtime_state state() const { - auto state_integer = hal::bit_extract(state_and_rel_address); - return static_cast(state_integer); + return inner_state; } constexpr inline std::uint32_t relative_address() const { - return hal::bit_extract(state_and_rel_address); + return rel_address; } - inline void state(runtime_state p_state) + constexpr inline void state(runtime_state p_state) { - auto state_int = static_cast(p_state); - hal::bit_modify(state_and_rel_address).insert(state_int); + inner_state = p_state; } - inline void rethrown(bool p_rethrown) + constexpr inline void rethrown(bool p_rethrown) { - hal::bit_modify(state_and_rel_address).insert(p_rethrown); + previously_rethrown = p_rethrown; } constexpr inline bool rethrown() const { - return hal::bit_extract(state_and_rel_address); + return previously_rethrown; } - inline void relative_address(std::uint32_t p_rel_address) + constexpr inline void relative_address(std::uint32_t p_rel_address) { - hal::bit_modify(state_and_rel_address) - .insert(p_rel_address); + rel_address = p_rel_address; } }; From e3354bc7c5349b59f1a93fc1d4564d108a755d0d Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Thu, 18 Jul 2024 15:34:08 -0700 Subject: [PATCH 06/14] :construction: Turn on destructors (currently broken) --- demos/applications/multi_levels.cpp | 34 ++++++++++---------- notes.md | 50 +---------------------------- src/arm_cortex/estell/exception.cpp | 8 ++++- 3 files changed, 25 insertions(+), 67 deletions(-) diff --git a/demos/applications/multi_levels.cpp b/demos/applications/multi_levels.cpp index 2b01412..16149bc 100644 --- a/demos/applications/multi_levels.cpp +++ b/demos/applications/multi_levels.cpp @@ -20,13 +20,13 @@ struct my_error_t int funct_group0_0(); int funct_group1_0(); -// int funct_group2_0(); -// int funct_group3_0(); -// int funct_group4_0(); -// int funct_group5_0(); -// int funct_group6_0(); -// int funct_group7_0(); -// int funct_group8_0(); +int funct_group2_0(); +int funct_group3_0(); +int funct_group4_0(); +int funct_group5_0(); +int funct_group6_0(); +int funct_group7_0(); +int funct_group8_0(); // int funct_group9_0(); // int funct_group10_0(); // int funct_group11_0(); @@ -46,13 +46,12 @@ int funct_group1_0(); using signature = int(void); -std::array functions = { - &funct_group0_0, - &funct_group1_0, +std::array functions = { + &funct_group0_0, &funct_group1_0, &funct_group2_0, + &funct_group3_0, &funct_group4_0, &funct_group5_0, + &funct_group6_0, &funct_group7_0, &funct_group8_0, #if 0 - funct_group2_0, funct_group3_0, - funct_group4_0, funct_group5_0, funct_group6_0, funct_group7_0, - funct_group8_0, funct_group9_0, funct_group10_0, funct_group11_0, + funct_group9_0, funct_group10_0, funct_group11_0, funct_group12_0, funct_group13_0, funct_group14_0, funct_group15_0, funct_group16_0, funct_group17_0, funct_group18_0, funct_group19_0, @@ -82,7 +81,7 @@ void application(resource_list& p_resources) } } -#if 0 +#if 1 for (std::size_t i = 0; i < functions.size(); i++) { bool was_caught = false; try { @@ -149,9 +148,9 @@ class class_1 class_1& operator=(class_1&) = delete; class_1(class_1&&) noexcept = default; class_1& operator=(class_1&&) noexcept = default; -#if 1 +#if 0 ~class_1() = default; -#elif +#else ~class_1() { side_effect = side_effect & ~(1 << m_channel); @@ -2932,7 +2931,6 @@ int funct_group7_23() return side_effect; } -#if 0 int funct_group8_1(); int funct_group8_0() @@ -3512,6 +3510,8 @@ int funct_group8_47() return side_effect; } +#if 0 + int funct_group9_1(); int funct_group9_0() diff --git a/notes.md b/notes.md index 2a01f71..955f09f 100644 --- a/notes.md +++ b/notes.md @@ -7,52 +7,4 @@ - Reduce the instructions for `restore_cpu_state` - Remove shift variable in `read_uleb128` -info registers -r0 0x7fffffff 2147483647 -r1 0x0 0 -r2 0x20000348 536871752 -r3 0x80012f5 134222581 -r4 0x20000348 536871752 -r5 0x20000118 536871192 -r6 0x20000278 536871544 -r7 0x20000358 536871768 -r8 0x7e 126 -r9 0x0 0 -r10 0x0 0 -r11 0x0 0 -r12 0x0 0 -sp 0x200027d0 0x200027d0 -lr 0x8001059 0x8001059 -pc 0x800107a 0x800107a -xpsr 0x61000000 1627389952 -msp 0x200027d0 0x200027d0 -psp 0x922f3724 0x922f3724 -primask 0x0 0 -control 0x0 0 -basepri 0x0 0 -faultmask 0x0 0 - -(gdb) info registers -r0 0x200001cc 536871372 -r1 0x1 1 -r2 0x8001085 134221957 -r3 0x20000188 536871304 -r4 0x20000348 536871752 -r5 0x20000118 536871192 -r6 0x0 0 -r7 0x0 0 -r8 0x7e 126 -r9 0x0 0 -r10 0x0 0 -r11 0x0 0 -r12 0x0 0 -sp 0x200027d0 0x200027d0 -lr 0x800108d 0x800108d -pc 0x800108c 0x800108c -xpsr 0x1000000 16777216 -msp 0x200027d0 0x200027d0 -psp 0x922f3724 0x922f3724 -primask 0x0 0 -control 0x0 0 -basepri 0x0 0 -faultmask 0x0 0 \ No newline at end of file +- I've turned destructors back on and we are terminating. Looks like the encoding byte has 0x15 which we don't support. 0x5 for the encoding type is not present. So we need to figure out what that is. Its either us reading the wrong data OR a new format we need to handle. \ No newline at end of file diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index 63a9182..d201691 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -251,9 +251,15 @@ personality_encoding operator&(personality_encoding const& p_encoding, result = *as(ptr); ptr += sizeof(int32_t); break; - case personality_encoding::sleb128: case personality_encoding::sdata8: + result = *as(ptr); + ptr += sizeof(int64_t); + break; case personality_encoding::udata8: + result = *as(ptr); + ptr += sizeof(uint64_t); + break; + case personality_encoding::sleb128: default: std::terminate(); break; From 225e0ed3efe560d9979b2c1e52524f8afeb301ef Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Fri, 19 Jul 2024 18:00:39 -0700 Subject: [PATCH 07/14] About this code I was trying to make a version of the `enter_function()` function that has less branches. Trading space for speed. --- demos/applications/multi_levels.cpp | 2 +- src/arm_cortex/estell/exception.cpp | 330 ++++++++++++++++++++++++---- 2 files changed, 294 insertions(+), 38 deletions(-) diff --git a/demos/applications/multi_levels.cpp b/demos/applications/multi_levels.cpp index 16149bc..f109ba8 100644 --- a/demos/applications/multi_levels.cpp +++ b/demos/applications/multi_levels.cpp @@ -2634,7 +2634,7 @@ int funct_group6_11() if (side_effect > 0) { start_cycles = resources->clock->uptime(); - throw my_error_t{ .data = { 0xDE, 0xAD } }; + throw my_error_t{ .data = { 0x11, 0x22 } }; } return side_effect; diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index d201691..1c69fa9 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -176,8 +177,10 @@ T const* as(void const* p_ptr) /** * @brief Dwarf exception handling personality encodings * + * Spec: + * https://refspecs.linuxfoundation.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html */ -enum class personality_encoding : std::uint8_t +enum class lsda_encoding : std::uint8_t { absptr = 0x00, uleb128 = 0x01, @@ -199,28 +202,27 @@ enum class personality_encoding : std::uint8_t omit = 0xff, }; -personality_encoding operator&(personality_encoding const& p_encoding, - std::uint8_t const& p_byte) +constexpr lsda_encoding operator&(lsda_encoding const& p_encoding, + std::uint8_t const& p_byte) { - return static_cast( - static_cast(p_encoding) & p_byte); + return static_cast(static_cast(p_encoding) & + p_byte); } -personality_encoding operator&(personality_encoding const& p_encoding, - personality_encoding const& p_byte) +constexpr lsda_encoding operator&(lsda_encoding const& p_encoding, + lsda_encoding const& p_byte) { - return static_cast( - static_cast(p_encoding) & static_cast(p_byte)); + return static_cast(static_cast(p_encoding) & + static_cast(p_byte)); } [[gnu::always_inline]] inline std::uintptr_t read_encoded_data( std::uint8_t const** p_data, - personality_encoding p_encoding) + lsda_encoding p_encoding) { std::uint8_t const* ptr = *p_data; std::uintptr_t result = 0; - auto const encoding = static_cast(p_encoding); - if (encoding == personality_encoding::omit) { + if (p_encoding == lsda_encoding::omit) { return 0; } @@ -228,38 +230,38 @@ personality_encoding operator&(personality_encoding const& p_encoding, auto const encoding_type = p_encoding & 0x0F; switch (encoding_type) { - case personality_encoding::absptr: + case lsda_encoding::absptr: result = *as(ptr); ptr += sizeof(uintptr_t); break; - case personality_encoding::uleb128: + case lsda_encoding::uleb128: result = read_uleb128(&ptr); break; - case personality_encoding::udata2: + case lsda_encoding::udata2: result = *as(ptr); ptr += sizeof(uint16_t); break; - case personality_encoding::udata4: + case lsda_encoding::udata4: result = *as(ptr); ptr += sizeof(uint32_t); break; - case personality_encoding::sdata2: + case lsda_encoding::sdata2: result = *as(ptr); ptr += sizeof(int16_t); break; - case personality_encoding::sdata4: + case lsda_encoding::sdata4: result = *as(ptr); ptr += sizeof(int32_t); break; - case personality_encoding::sdata8: + case lsda_encoding::sdata8: result = *as(ptr); ptr += sizeof(int64_t); break; - case personality_encoding::udata8: + case lsda_encoding::udata8: result = *as(ptr); ptr += sizeof(uint64_t); break; - case personality_encoding::sleb128: + case lsda_encoding::sleb128: default: std::terminate(); break; @@ -269,12 +271,12 @@ personality_encoding operator&(personality_encoding const& p_encoding, auto const encoding_offset = p_encoding & 0x70; switch (encoding_offset) { - case personality_encoding::pcrel: - case personality_encoding::absptr: - case personality_encoding::textrel: - case personality_encoding::datarel: - case personality_encoding::funcrel: - case personality_encoding::aligned: + case lsda_encoding::pcrel: + case lsda_encoding::absptr: + case lsda_encoding::textrel: + case lsda_encoding::datarel: + case lsda_encoding::funcrel: + case lsda_encoding::aligned: default: break; } @@ -384,20 +386,33 @@ inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) inline void enter_function(exception_object& p_exception_object) { - std::uint8_t const* lsda_data = reinterpret_cast( - p_exception_object.cache.entry_ptr->lsda_data()); + auto const* lsda_word = p_exception_object.cache.entry_ptr->lsda_data(); + auto const* lsda_data = reinterpret_cast(lsda_word); + +#if 0 + // [Omit dwarf]-[uleb128 encoding]-[offset uleb128]-[uleb128 encoding] + static constexpr std::uint32_t small_lsda = 0xFF'01'80'01; + static constexpr std::uint32_t small_lsda_go = 0xFF'01'00'01; + static constexpr std::uint32_t medium_lsda = 0xFF'01'80'80; +#endif - auto const dwarf_offset_info_format = personality_encoding{ *(lsda_data++) }; - if (dwarf_offset_info_format != personality_encoding::omit) { + auto const dwarf_offset_info_format = lsda_encoding{ *(lsda_data++) }; + if (dwarf_offset_info_format != lsda_encoding::omit) { // Ignore this because we don't need it for unwinding. - read_encoded_data(&lsda_data, dwarf_offset_info_format); + [[maybe_unused]] auto const _ = + read_encoded_data(&lsda_data, dwarf_offset_info_format); } - [[maybe_unused]] auto const end_of_type_table_format = - personality_encoding{ *(lsda_data++) }; - auto const offset_to_end_of_tt_table = read_uleb128(&lsda_data); + auto const type_table_format = lsda_encoding{ *(lsda_data++) }; + std::uint32_t offset_to_end_of_tt_table = 0; + // if type table offset does not exist then there is only cleanup within + // this function. + if (type_table_format != lsda_encoding::omit) { + offset_to_end_of_tt_table = read_uleb128(&lsda_data); + } auto const* end_of_tt_table = lsda_data + offset_to_end_of_tt_table; - auto const call_site_format = personality_encoding{ *(lsda_data++) }; + + auto const call_site_format = lsda_encoding{ *(lsda_data++) }; auto const call_site_length = read_uleb128(&lsda_data); auto const* call_site_end = lsda_data + call_site_length; @@ -406,7 +421,7 @@ inline void enter_function(exception_object& p_exception_object) std::uint32_t action = 0; // Optimize for the most common use case and encouraged - if (call_site_format == personality_encoding::uleb128) { + if (call_site_format == lsda_encoding::uleb128) { do { auto start = read_uleb128(&lsda_data); auto length = read_uleb128(&lsda_data); @@ -457,6 +472,247 @@ inline void enter_function(exception_object& p_exception_object) } } +template +inline void parse_call_site(std::uint32_t p_rel_pc, std::uint8_t const** p_lsda) +{ +} + +inline void skip_dwarf_info(std::uint8_t const** p_lsda) +{ + auto const* lsda = *p_lsda; + auto const format = lsda_encoding{ *(lsda++) }; + if (format != lsda_encoding::omit) { + // Ignore this because we don't need it for unwinding. + read_encoded_data(&lsda, format); + } + *p_lsda = lsda; +} + +struct lsda_header_info +{ + std::uint8_t const* call_site_end = nullptr; + /// If this pointer is behind the call_site end, then there is no type table + /// available. + std::uint8_t const* type_table_end = nullptr; + lsda_encoding type_table_encoding; + lsda_encoding call_site_encoding; +}; + +inline lsda_header_info parse_header(std::uint8_t const** p_lsda) +{ + lsda_header_info info{}; + + skip_dwarf_info(p_lsda); + + // Capture type table end. Will be before call_site_end if it did not exist + auto const* lsda = *p_lsda; + info.type_table_encoding = lsda_encoding{ *(lsda++) }; + info.type_table_end = lsda; + if (info.type_table_encoding != lsda_encoding::omit) { + info.type_table_end += read_uleb128(&lsda); + } + + info.call_site_encoding = lsda_encoding{ *(lsda++) }; + info.call_site_end = lsda; + info.call_site_end += read_uleb128(&lsda); + + *p_lsda = lsda; + + return info; +} + +inline auto const* to_lsda(exception_object& p_exception_object) +{ + return reinterpret_cast( + p_exception_object.cache.entry_ptr->lsda_data()); +} + +inline auto calculate_relative_pc(exception_object& p_exception_object) +{ + return p_exception_object.cache.relative_address() & ~1; +} + +template +[[gnu::always_inline]] inline std::uintptr_t read_encoded_data( + std::uint8_t const** p_data) +{ + std::uint8_t const* ptr = *p_data; + std::uintptr_t result = 0; + + if constexpr (encoding == lsda_encoding::omit) { + return 0; + } + + static constexpr auto encoding_type = encoding & 0x0F; + + if constexpr (encoding_type == lsda_encoding::absptr) { + result = *as(ptr); + ptr += sizeof(uintptr_t); + } + if constexpr (encoding_type == lsda_encoding::uleb128) { + result = read_uleb128(&ptr); + } + if constexpr (encoding_type == lsda_encoding::udata2) { + result = *as(ptr); + ptr += sizeof(uint16_t); + } + if constexpr (encoding_type == lsda_encoding::udata4) { + result = *as(ptr); + ptr += sizeof(uint32_t); + } + if constexpr (encoding_type == lsda_encoding::sdata2) { + result = *as(ptr); + ptr += sizeof(int16_t); + } + if constexpr (encoding_type == lsda_encoding::sdata4) { + result = *as(ptr); + ptr += sizeof(int32_t); + } + if constexpr (encoding_type == lsda_encoding::sdata8) { + result = *as(ptr); + ptr += sizeof(int64_t); + } + if constexpr (encoding_type == lsda_encoding::udata8) { + result = *as(ptr); + ptr += sizeof(uint64_t); + } + if constexpr (encoding_type == lsda_encoding::sleb128) { + } + + // NOTE: we currently ignore bits in the mask 0x70. + + // Handle indirection GCC extension + if constexpr (static_cast(encoding & 0x80)) { + result = *reinterpret_cast(result); + } + + *p_data = ptr; + + return result; +} + +#if 0 +inline void enter_catch_block_or_cleanup(exception_object& p_exception_object, + std::uint8_t const* p_lsda, + std::uint32_t p_relative_pc) +{ + // fill out later +} +#endif + +struct call_site_info +{ + std::uint32_t start = 0; + std::uint32_t length = 0; + std::uint32_t landing_pad = 0; + std::uint32_t action = 0; + bool unwind = false; +}; + +template +inline call_site_info parse_call_site(std::uint8_t const** p_lsda, + std::uint32_t p_rel_pc, + std::uint8_t const* p_call_site_end) +{ + call_site_info info; + + do { + info.start = read_encoded_data(p_lsda); + info.length = read_encoded_data(p_lsda); + info.landing_pad = read_encoded_data(p_lsda); + info.action = read_encoded_data(p_lsda); + + if (info.start <= p_rel_pc && p_rel_pc <= info.start + info.length) { + if (info.landing_pad == 0) { + info.unwind = true; + } + break; + } + } while (*p_lsda < p_call_site_end); + + return info; +} + +inline void enter_function2(exception_object& p_exception_object) +{ + auto const* lsda = to_lsda(p_exception_object); + auto info = parse_header(&lsda); + auto const rel_pc = calculate_relative_pc(p_exception_object); + + call_site_info site_info{}; + + switch (info.call_site_encoding) { + case lsda_encoding::uleb128: { + site_info = parse_call_site( + &lsda, rel_pc, info.call_site_end); + break; + } + case lsda_encoding::udata2: { + site_info = parse_call_site( + &lsda, rel_pc, info.call_site_end); + break; + } + case lsda_encoding::udata4: { + site_info = parse_call_site( + &lsda, rel_pc, info.call_site_end); + break; + } + case lsda_encoding::udata8: { + site_info = parse_call_site( + &lsda, rel_pc, info.call_site_end); + break; + } + case lsda_encoding::sdata2: { + site_info = parse_call_site( + &lsda, rel_pc, info.call_site_end); + break; + } + case lsda_encoding::sdata4: { + site_info = parse_call_site( + &lsda, rel_pc, info.call_site_end); + break; + } + case lsda_encoding::sdata8: { + site_info = parse_call_site( + &lsda, rel_pc, info.call_site_end); + break; + } + case lsda_encoding::sleb128: { + site_info = parse_call_site( + &lsda, rel_pc, info.call_site_end); + break; + } + default: { + std::terminate(); + } + } + + if (site_info.unwind) { + p_exception_object.cache.state(runtime_state::unwind_frame); + return; + } + +#if 0 // figure out how to do this + action_decoder a_decoder(end_of_tt_table, call_site_end, action); + + auto& cpu = p_exception_object.cpu; + auto* entry_ptr = p_exception_object.cache.entry_ptr; + for (auto const* type_info = a_decoder.get_next_catch_type(); + type_info != nullptr; + type_info = a_decoder.get_next_catch_type()) { + if (type_info == p_exception_object.type_info || + type_info == action_decoder::install_context_type()) { + cpu[0] = &p_exception_object; + cpu[1] = a_decoder.filter(); + // Set the LSB to 1 for some reason. Cortex-mX is interesting + auto final_destination = (entry_ptr->function() + landing_pad) | 0b1; + cpu.pc = final_destination; + restore_cpu_core(cpu); + } + } +#endif +} + template constexpr std::uint32_t vsp_deallocate_amount() { From 56088e1d66068f1ea11a19f2bd39461cfaa83f31 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Mon, 22 Jul 2024 14:25:24 -0700 Subject: [PATCH 08/14] :zap: Add enter_function2() `enter_function2()` will be a replacement for `enter_function()`. This function correctly decodes the call sites using their encoding values and decodes the action table and type table correctly as well. Although the type table parsing is still assumed to be pcrel. This should be fixed at some point. --- demos/CMakeLists.txt | 2 + demos/applications/multi_levels.cpp | 2 +- src/arm_cortex/estell/exception.cpp | 348 ++++++++++++++++++++++++---- 3 files changed, 304 insertions(+), 48 deletions(-) diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt index 90f87fd..a732296 100644 --- a/demos/CMakeLists.txt +++ b/demos/CMakeLists.txt @@ -16,6 +16,8 @@ cmake_minimum_required(VERSION 3.15) project(demos LANGUAGES CXX) +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --save-temps") + libhal_build_demos( DEMOS single_level diff --git a/demos/applications/multi_levels.cpp b/demos/applications/multi_levels.cpp index f109ba8..37a38e5 100644 --- a/demos/applications/multi_levels.cpp +++ b/demos/applications/multi_levels.cpp @@ -66,7 +66,7 @@ void application(resource_list& p_resources) { resources = &p_resources; - cycle_map.fill(0); + cycle_map.fill(std::numeric_limits::max()); happy_cycle_map.fill(std::numeric_limits::max()); for (std::size_t i = 0; i < functions.size(); i++) { try { diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index 1c69fa9..e7acce6 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -149,25 +149,130 @@ index_entry_t const& get_index_entry(std::uint32_t p_program_counter) std::uint8_t const** p_ptr) { std::uint32_t result = 0; + std::uint8_t shift_amount = 0; while (true) { - constexpr auto more_data = hal::bit_mask::from<7>(); - constexpr auto data = hal::bit_mask::from<0, 6>(); std::uint8_t const uleb128 = **p_ptr; - result |= hal::bit_extract(uleb128); + result |= (uleb128 & 0x7F) << shift_amount; (*p_ptr)++; - if (not hal::bit_extract(uleb128)) { + if ((uleb128 == 0x80) == 0x00) { break; } - result <<= 7; + shift_amount += 7; } return result; } +#if 0 +0100'0100 +<< 1 ----> 8 - (7*1) +100'01000 +>> 1 +1100'0100 +#endif + +[[gnu::always_inline]] inline constexpr std::int32_t read_sleb128( + std::uint8_t const** p_ptr) +{ + constexpr std::uint8_t leb128_bits = 7; + std::int32_t result = 0; + std::uint32_t shift_amount = 0; + + // No number we deal with on the 32-bit system will or should exceed 31-bits + // of information + for (std::size_t i = 0; i < sizeof(std::int32_t); i++) { + std::uint8_t const sleb128 = **p_ptr; + + result |= (sleb128 & 0x7F) << shift_amount; + (*p_ptr)++; + + if ((sleb128 & 0x80) == 0x00) { + auto const bytes_consumed = i + 1; + auto const loaded_bits = bytes_consumed * leb128_bits; + auto const ext_shift_amount = (30 - loaded_bits); + // Shift to the left up to the signed MSB bit + result <<= ext_shift_amount; + // Arithmetic shift right to sign extend number + result >>= ext_shift_amount; + break; + } + + shift_amount += 7; + } + + return result; +} + +template +struct decoded_uleb128_t +{ + std::array data{}; + std::uint8_t const* last_read; +}; + +template +inline constexpr decoded_uleb128_t multi_read_uleb128( + std::uint8_t const* p_ptr) +{ + decoded_uleb128_t result{}; + auto iter = result.data.begin(); + std::uint32_t shift_amount = 0; + + // THIS IS WRONG! ULEB is LSB first then ends on MSB. This is big endian + while (iter != result.data.end()) { + std::uint8_t const uleb128 = *(p_ptr++); + + *iter |= (uleb128 & 0x7F) << shift_amount; + + if ((uleb128 & 0x80) == 0x00) { + iter++; + shift_amount = 0; + continue; + } + + shift_amount += 7; + } + + result.last_read = p_ptr; + + return result; +} + +#if 0 +template +[[gnu::always_inline]] inline constexpr decoded_uleb128_t +fast_read_uleb128(std::uint8_t const* p_ptr) +{ + decoded_uleb128_t decoded{}; + + while (true) { + std::uint32_t storage = *p_ptr++ << 24; + storage |= *p_ptr++ << 16; + storage |= *p_ptr++ << 8; + storage |= *p_ptr++ << 0; + + constexpr std::uint32_t uleb128_32_bit_mask = 0x80'80'80'80; + std::uint32_t bit_mask = storage & uleb128_32_bit_mask; + std::uint32_t result = ((bit_mask >> 24) & 0x01) << 3 | + ((bit_mask >> 16) & 0x01) << 2 | + ((bit_mask >> 8) & 0x01) << 1 | ((bit_mask) & 0x01); + + static constexpr std::array jump_table{}; + + while (true) { + auto* jump_location = jump_table[result]; + goto* jump_location; + } + } + + return decoded; +} +#endif + template T const* as(void const* p_ptr) { @@ -317,7 +422,11 @@ class action_decoder std::type_info const* get_next_catch_type() { // TODO(kammce): This isn't how it actually works. This needs to be - // corrected. + // corrected. This kinda works, but the action is biased by 1 and needs to + // be subtracted. I don't understand how I made the old m_action[-1] and + // m_action[0] | 0x80 work. Or why it even works. Seems crazy to me. But it + // do work. I bet it breaks at a specific point. Like if the offset is large + // or the filter number ends up being two bytes. Which would be really rare. if (m_action == nullptr) { return nullptr; } @@ -472,11 +581,6 @@ inline void enter_function(exception_object& p_exception_object) } } -template -inline void parse_call_site(std::uint32_t p_rel_pc, std::uint8_t const** p_lsda) -{ -} - inline void skip_dwarf_info(std::uint8_t const** p_lsda) { auto const* lsda = *p_lsda; @@ -507,14 +611,16 @@ inline lsda_header_info parse_header(std::uint8_t const** p_lsda) // Capture type table end. Will be before call_site_end if it did not exist auto const* lsda = *p_lsda; info.type_table_encoding = lsda_encoding{ *(lsda++) }; - info.type_table_end = lsda; if (info.type_table_encoding != lsda_encoding::omit) { - info.type_table_end += read_uleb128(&lsda); + auto const offset = read_uleb128(&lsda); + info.type_table_end = lsda + offset; + } else { + info.type_table_end = lsda; } info.call_site_encoding = lsda_encoding{ *(lsda++) }; - info.call_site_end = lsda; - info.call_site_end += read_uleb128(&lsda); + auto const offset = read_uleb128(&lsda); + info.call_site_end = lsda + offset; *p_lsda = lsda; @@ -602,8 +708,6 @@ inline void enter_catch_block_or_cleanup(exception_object& p_exception_object, struct call_site_info { - std::uint32_t start = 0; - std::uint32_t length = 0; std::uint32_t landing_pad = 0; std::uint32_t action = 0; bool unwind = false; @@ -617,13 +721,13 @@ inline call_site_info parse_call_site(std::uint8_t const** p_lsda, call_site_info info; do { - info.start = read_encoded_data(p_lsda); - info.length = read_encoded_data(p_lsda); + auto start = read_encoded_data(p_lsda); + auto length = read_encoded_data(p_lsda); info.landing_pad = read_encoded_data(p_lsda); info.action = read_encoded_data(p_lsda); - if (info.start <= p_rel_pc && p_rel_pc <= info.start + info.length) { - if (info.landing_pad == 0) { + if (start <= p_rel_pc && p_rel_pc <= start + length) { + if (info.landing_pad == 0 || info.action == 0) { info.unwind = true; } break; @@ -633,6 +737,112 @@ inline call_site_info parse_call_site(std::uint8_t const** p_lsda, return info; } +inline call_site_info parse_uleb128_call_site( + std::uint8_t const* p_lsda, + std::uint32_t p_rel_pc, + std::uint8_t const* p_call_site_end) +{ + call_site_info info; + + do { + auto const values = multi_read_uleb128<4>(p_lsda); + auto const& start = values.data[0]; + auto const& length = values.data[1]; + auto const& landing_pad = values.data[2]; + auto const& action = values.data[3]; + if (start <= p_rel_pc && p_rel_pc <= start + length) { + if (landing_pad == 0 || action == 0) { + info.unwind = true; + } else { + info.landing_pad = landing_pad; + info.action = action; + } + break; + } + p_lsda = values.last_read; + } while (p_lsda < p_call_site_end); + + return info; +} + +class action_decoder2 +{ +public: + action_decoder2(std::uint8_t const* p_type_table_end, + std::uint8_t const* p_end_of_callsite, + std::uint32_t p_action) + : m_type_table_end(p_type_table_end) + , m_action_position(p_end_of_callsite + (p_action - 1)) + { + } + + static std::type_info const* to_type_info(void const* p_type_info_address) + { + return reinterpret_cast( + to_absolute_address(p_type_info_address)); + } + + static std::type_info const* install_context_type() + { + return reinterpret_cast(0xFFFF'FFFF); + } + + std::type_info const* get_current_type_info_from_filter() + { + auto const* type_table = as(m_type_table_end); + + // We assume absptr here because its easier + // TODO(#___): Consider using the type table encoding format for decoding + // the type table info rather than assuming that the values here are + // prel31_offsets + auto const* current_type = &type_table[-m_filter]; + + if (*current_type == 0x0) { + return install_context_type(); + } + + auto const* test = to_absolute_address_ptr(current_type); + return reinterpret_cast(test); + } + + std::type_info const* get_next_catch_type() + { + if (m_action_position == nullptr) { + return nullptr; + } + + do { + m_filter = read_sleb128(&m_action_position); + auto const next_action_offset = read_sleb128(&m_action_position); + + if (next_action_offset == 0) { + m_action_position = nullptr; + } else { + m_action_position += next_action_offset; + } + // Negative numbers are for the deprecated `throws()` specifier that we do + // not support. We throw those away and continue looking through the + // action table. + } while (m_filter < 0); + + if (m_filter == 0) { + return install_context_type(); + } + + return get_current_type_info_from_filter(); + } + + std::uint8_t filter() + { + return m_filter; + } + +private: + std::uint8_t const* m_type_table_end = nullptr; + std::uint8_t const* m_action_position = nullptr; + std::int32_t m_filter = 0; +}; + inline void enter_function2(exception_object& p_exception_object) { auto const* lsda = to_lsda(p_exception_object); @@ -643,8 +853,7 @@ inline void enter_function2(exception_object& p_exception_object) switch (info.call_site_encoding) { case lsda_encoding::uleb128: { - site_info = parse_call_site( - &lsda, rel_pc, info.call_site_end); + site_info = parse_uleb128_call_site(lsda, rel_pc, info.call_site_end); break; } case lsda_encoding::udata2: { @@ -692,23 +901,71 @@ inline void enter_function2(exception_object& p_exception_object) return; } -#if 0 // figure out how to do this - action_decoder a_decoder(end_of_tt_table, call_site_end, action); - auto& cpu = p_exception_object.cpu; auto* entry_ptr = p_exception_object.cache.entry_ptr; + + // This occurs when a frame has destructors that need cleaning up but no + // try/catch blocks. In such a case, if we found a scope we need to enter, we + // should enter it immediately! + if (info.type_table_end < info.call_site_end) { + // LSB must be set to 1 to jump to an address + auto const final_destination = + (entry_ptr->function() + site_info.landing_pad) | 0b1; + + // Set PC to the cleanup destination + cpu.pc = final_destination; + + // Install CPU state + restore_cpu_core(cpu); + } + + action_decoder2 a_decoder( + info.type_table_end, info.call_site_end, site_info.action); + for (auto const* type_info = a_decoder.get_next_catch_type(); type_info != nullptr; type_info = a_decoder.get_next_catch_type()) { - if (type_info == p_exception_object.type_info || - type_info == action_decoder::install_context_type()) { - cpu[0] = &p_exception_object; - cpu[1] = a_decoder.filter(); - // Set the LSB to 1 for some reason. Cortex-mX is interesting - auto final_destination = (entry_ptr->function() + landing_pad) | 0b1; - cpu.pc = final_destination; - restore_cpu_core(cpu); + + if (type_info != p_exception_object.type_info && + type_info != action_decoder2::install_context_type()) { + continue; + } + + // ====== Prepare to Install context!! ===== + cpu[0] = &p_exception_object; + cpu[1] = a_decoder.filter(); + + // LSB must be set to 1 to jump to an address + auto const final_destination = + (entry_ptr->function() + site_info.landing_pad) | 0b1; + + // Set PC to the cleanup destination + cpu.pc = final_destination; + + // Install CPU state + restore_cpu_core(cpu); + } + +#if 0 + for (auto const* type_info : a_decoder) { + if (type_info != p_exception_object.type_info && + type_info != action_decoder2::install_context_type()) { + continue; } + + // ====== Prepare to Install context!! ===== + cpu[0] = &p_exception_object; + cpu[1] = a_decoder.filter(); + + // LSB must be set to 1 to jump to an address + auto const final_destination = + (entry_ptr->function() + site_info.landing_pad) | 0b1; + + // Set PC to the cleanup destination + cpu.pc = final_destination; + + // Install CPU state + restore_cpu_core(cpu); } #endif } @@ -1880,7 +2137,7 @@ void raise_exception(exception_object& p_exception_object) [[fallthrough]]; } case runtime_state::enter_function: { - enter_function(p_exception_object); + enter_function2(p_exception_object); // enter function returns normally if it determines that there was no // reason to enter the function, thus the function should be unwound. [[fallthrough]]; @@ -1961,9 +2218,9 @@ extern "C" #if defined(OPTIMIZATION_LEVEL) #if OPTIMIZATION_LEVEL == Debug std::uint32_t const* stack_pointer = *exception_object.cpu.sp; - stack_pointer += 5; - exception_object.cpu.pc = stack_pointer[0]; - exception_object.cpu.sp = stack_pointer + 1; + exception_object.cpu.r3 = stack_pointer[0]; + exception_object.cpu.pc = stack_pointer[1]; + exception_object.cpu.sp = stack_pointer + 2; #elif OPTIMIZATION_LEVEL == MinSizeRel std::uint32_t const* stack_pointer = *exception_object.cpu.sp; exception_object.cpu.r4 = stack_pointer[0]; @@ -1972,10 +2229,8 @@ extern "C" #elif OPTIMIZATION_LEVEL == Release std::uint32_t const* stack_pointer = *exception_object.cpu.sp; exception_object.cpu.r3 = stack_pointer[0]; - exception_object.cpu.r4 = stack_pointer[1]; - exception_object.cpu.r5 = stack_pointer[2]; - exception_object.cpu.pc = stack_pointer[3]; - exception_object.cpu.sp = stack_pointer + 4; + exception_object.cpu.pc = stack_pointer[1]; + exception_object.cpu.sp = stack_pointer + 2; #elif OPTIMIZATION_LEVEL == RelWithDebInfo #error "Sorry Release mode unwinding is not supported yet."; #endif @@ -2001,10 +2256,9 @@ extern "C" #if OPTIMIZATION_LEVEL == Debug std::uint32_t const* stack_pointer = *exception_object.cpu.sp; exception_object.cpu.r3 = stack_pointer[0]; - exception_object.cpu.r4 = stack_pointer[1]; - exception_object.cpu.r5 = stack_pointer[2]; - exception_object.cpu.pc = stack_pointer[3]; - exception_object.cpu.sp = stack_pointer + 5; + exception_object.cpu.pc = stack_pointer[1]; + exception_object.cpu.sp = stack_pointer + 2; +#elif OPTIMIZATION_LEVEL == MinSizeRel #elif OPTIMIZATION_LEVEL == MinSizeRel std::uint32_t const* stack_pointer = *exception_object.cpu.sp; exception_object.cpu.r4 = stack_pointer[0]; @@ -2012,7 +2266,7 @@ extern "C" exception_object.cpu.sp = stack_pointer + 2; #elif OPTIMIZATION_LEVEL == Release std::uint32_t const* stack_pointer = *exception_object.cpu.sp; - exception_object.cpu.r4 = stack_pointer[0]; + exception_object.cpu.r3 = stack_pointer[0]; exception_object.cpu.pc = stack_pointer[1]; exception_object.cpu.sp = stack_pointer + 2; #elif OPTIMIZATION_LEVEL == RelWithDebInfo From c20aafa08498c4291755d1cbe2c8309914135372 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Tue, 23 Jul 2024 12:19:28 -0700 Subject: [PATCH 09/14] :poop: unwind_frame2 The idea of unwind_frame2 was to evaluate the instructions in place vs putting them into order in the instruction_t. The problem is word boundaries which requires logic to determine if we are at the end of the instructions. --- src/arm_cortex/estell/exception.cpp | 939 +++++++++++++++++++++++++++- 1 file changed, 931 insertions(+), 8 deletions(-) diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index e7acce6..5fbda84 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -727,7 +727,7 @@ inline call_site_info parse_call_site(std::uint8_t const** p_lsda, info.action = read_encoded_data(p_lsda); if (start <= p_rel_pc && p_rel_pc <= start + length) { - if (info.landing_pad == 0 || info.action == 0) { + if (info.landing_pad == 0) { info.unwind = true; } break; @@ -751,7 +751,7 @@ inline call_site_info parse_uleb128_call_site( auto const& landing_pad = values.data[2]; auto const& action = values.data[3]; if (start <= p_rel_pc && p_rel_pc <= start + length) { - if (landing_pad == 0 || action == 0) { + if (landing_pad == 0) { info.unwind = true; } else { info.landing_pad = landing_pad; @@ -1038,6 +1038,7 @@ inline std::uint32_t const* pop_register_range(std::uint32_t const* sp_ptr, return sp_ptr + PopCount + 1 + unsigned{ PopLinkRegister == pop_lr::do_it }; } +#if 1 void unwind_frame(instructions_t const& p_instructions, exception_object& p_exception_object) { @@ -1358,9 +1359,9 @@ void unwind_frame(instructions_t const& p_instructions, auto const* sp_ptr = *virtual_cpu.sp; while (true) { - auto const* jump_location = jump_table[*instruction_ptr]; + auto const* instruction_handler = jump_table[*instruction_ptr]; instruction_ptr++; - goto* jump_location; + goto* instruction_handler; // +=========================================================================+ // | Finish! | @@ -2044,8 +2045,927 @@ void unwind_frame(instructions_t const& p_instructions, } #endif } +#endif + +#if 0 +void unwind_frame2(exception_object& p_exception_object) +{ + static constexpr std::array jump_table{ + &&vsp_add_0, // [0] + &&vsp_add_1, // [1] + &&vsp_add_2, // [2] + &&vsp_add_3, // [3] + &&vsp_add_4, // [4] + &&vsp_add_5, // [5] + &&vsp_add_6, // [6] + &&vsp_add_7, // [7] + &&vsp_add_8, // [8] + &&vsp_add_9, // [9] + &&vsp_add_10, // [10] + &&vsp_add_11, // [11] + &&vsp_add_12, // [12] + &&vsp_add_13, // [13] + &&vsp_add_14, // [14] + &&vsp_add_15, // [15] + &&vsp_add_16, // [16] + &&vsp_add_17, // [17] + &&vsp_add_18, // [18] + &&vsp_add_19, // [19] + &&vsp_add_20, // [20] + &&vsp_add_21, // [21] + &&vsp_add_22, // [22] + &&vsp_add_23, // [23] + &&vsp_add_24, // [24] + &&vsp_add_25, // [25] + &&vsp_add_26, // [26] + &&vsp_add_27, // [27] + &&vsp_add_28, // [28] + &&vsp_add_29, // [29] + &&vsp_add_30, // [30] + &&vsp_add_31, // [31] + &&vsp_add_32, // [32] + &&vsp_add_33, // [33] + &&vsp_add_34, // [34] + &&vsp_add_35, // [35] + &&vsp_add_36, // [36] + &&vsp_add_37, // [37] + &&vsp_add_38, // [38] + &&vsp_add_39, // [39] + &&vsp_add_40, // [40] + &&vsp_add_41, // [41] + &&vsp_add_42, // [42] + &&vsp_add_43, // [43] + &&vsp_add_44, // [44] + &&vsp_add_45, // [45] + &&vsp_add_46, // [46] + &&vsp_add_47, // [47] + &&vsp_add_48, // [48] + &&vsp_add_49, // [49] + &&vsp_add_50, // [50] + &&vsp_add_51, // [51] + &&vsp_add_52, // [52] + &&vsp_add_53, // [53] + &&vsp_add_54, // [54] + &&vsp_add_55, // [55] + &&vsp_add_56, // [56] + &&vsp_add_57, // [57] + &&vsp_add_58, // [58] + &&vsp_add_59, // [59] + &&vsp_add_60, // [60] + &&vsp_add_61, // [61] + &&vsp_add_62, // [62] + &&vsp_add_63, // [63] + + &&vsp_sub_0, // [64] + &&vsp_sub_1, // [65] + &&vsp_sub_2, // [66] + &&vsp_sub_3, // [67] + &&vsp_sub_4, // [68] + &&vsp_sub_5, // [69] + &&vsp_sub_6, // [70] + &&vsp_sub_7, // [71] + &&vsp_sub_8, // [72] + &&vsp_sub_9, // [73] + &&vsp_sub_10, // [74] + &&vsp_sub_11, // [75] + &&vsp_sub_12, // [76] + &&vsp_sub_13, // [77] + &&vsp_sub_14, // [78] + &&vsp_sub_15, // [79] + &&vsp_sub_16, // [80] + &&vsp_sub_17, // [81] + &&vsp_sub_18, // [82] + &&vsp_sub_19, // [83] + &&vsp_sub_20, // [84] + &&vsp_sub_21, // [85] + &&vsp_sub_22, // [86] + &&vsp_sub_23, // [87] + &&vsp_sub_24, // [88] + &&vsp_sub_25, // [89] + &&vsp_sub_26, // [90] + &&vsp_sub_27, // [91] + &&vsp_sub_28, // [92] + &&vsp_sub_29, // [93] + &&vsp_sub_30, // [94] + &&vsp_sub_31, // [95] + &&vsp_sub_32, // [96] + &&vsp_sub_33, // [97] + &&vsp_sub_34, // [98] + &&vsp_sub_35, // [99] + &&vsp_sub_36, // [100] + &&vsp_sub_37, // [101] + &&vsp_sub_38, // [102] + &&vsp_sub_39, // [103] + &&vsp_sub_40, // [104] + &&vsp_sub_41, // [105] + &&vsp_sub_42, // [106] + &&vsp_sub_43, // [107] + &&vsp_sub_44, // [108] + &&vsp_sub_45, // [109] + &&vsp_sub_46, // [110] + &&vsp_sub_47, // [111] + &&vsp_sub_48, // [112] + &&vsp_sub_49, // [113] + &&vsp_sub_50, // [114] + &&vsp_sub_51, // [115] + &&vsp_sub_52, // [116] + &&vsp_sub_53, // [117] + &&vsp_sub_54, // [118] + &&vsp_sub_55, // [119] + &&vsp_sub_56, // [120] + &&vsp_sub_57, // [121] + &&vsp_sub_58, // [122] + &&vsp_sub_59, // [123] + &&vsp_sub_60, // [124] + &&vsp_sub_61, // [125] + &&vsp_sub_62, // [126] + &&vsp_sub_63, // [127] + + // 10000000 + &&refuse_unwind_or_pop, // [0b1000'0000 = 128] + + // 1000iiii ... + &&pop_under_mask, // [0b1000'0001 = 129] + &&pop_under_mask, // [0b1000'0010 = 130] + &&pop_under_mask, // [0b1000'0011 = 131] + &&pop_under_mask, // [0b1000'0100 = 132] + &&pop_under_mask, // [0b1000'0101 = 133] + &&pop_under_mask, // [0b1000'0110 = 134] + &&pop_under_mask, // [0b1000'0111 = 135] + &&pop_under_mask, // [0b1000'1000 = 136] + &&pop_under_mask, // [0b1000'1001 = 137] + &&pop_under_mask, // [0b1000'1010 = 138] + &&pop_under_mask, // [0b1000'1011 = 139] + &&pop_under_mask, // [0b1000'1100 = 140] + &&pop_under_mask, // [0b1000'1101 = 141] + &&pop_under_mask, // [0b1000'1110 = 142] + &&pop_under_mask, // [0b1000'1111 = 143] (128 + 15) + + // 1001nnnn + // TODO: Split up assignments to make them faster + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0000 = 144] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0001 = 145] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0010 = 146] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0011 = 147] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0100 = 148] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0101 = 149] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0110 = 150] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'0111 = 151] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1000 = 152] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1001 = 153] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1010 = 154] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1011 = 155] + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1100 = 156] + // Reserved as prefix for Arm register to register moves + &&reserved_or_spare_thus_terminate, // [0b1001'1101 = 157] + // Reserved as prefix for Intel Wireless MMX register to register moves + &&assign_to_vsp_to_reg_nnnn, // [0b1001'1110 = 158] + &&reserved_or_spare_thus_terminate, // [0b1001'1111 = 159 reg 15 reserved] + + // 10100nnn + &&pop_off_stack_r4_to_r4, // 0b10100'000 [160] + &&pop_off_stack_r4_to_r5, // 0b10100'001 [161] + &&pop_off_stack_r4_to_r6, // 0b10100'010 [162] + &&pop_off_stack_r4_to_r7, // 0b10100'011 [163] + &&pop_off_stack_r4_to_r8, // 0b10100'100 [164] + &&pop_off_stack_r4_to_r9, // 0b10100'101 [165] + &&pop_off_stack_r4_to_r10, // 0b10100'110 [166] + &&pop_off_stack_r4_to_r11, // 0b10100'111 [167] + + // 10101nnn + &&pop_off_stack_r4_to_r4_and_lr, // 0b10101'000 [168] + &&pop_off_stack_r4_to_r5_and_lr, // 0b10101'001 [169] + &&pop_off_stack_r4_to_r6_and_lr, // 0b10101'010 [170] + &&pop_off_stack_r4_to_r7_and_lr, // 0b10101'011 [171] + &&pop_off_stack_r4_to_r8_and_lr, // 0b10101'100 [172] + &&pop_off_stack_r4_to_r9_and_lr, // 0b10101'101 [173] + &&pop_off_stack_r4_to_r10_and_lr, // 0b10101'110 [174] + &&pop_off_stack_r4_to_r11_and_lr, // 0b10101'111 [175] + + // Finish (0xB0) + &&finish_unwind, // 10110000 [176] + + // Spare (refuse unwind) + &&pop_integer_registers_under_mask_r3_r2_r1_r0, // 10110001 [177] + + // Subtract VSP using uleb128 + &&subtract_vsp_using_uleb128, // 10110010 [178] + + // Pop VFP double-precision registers (not supported currently) + &&reserved_or_spare_thus_terminate, // 10110011 [179] + + // Pop Return Address Authentication Code pseudo-register + &&reserved_or_spare_thus_terminate, // 10110100 [180] + + // Use current vsp as modifier in Return Address Authentication + &&reserved_or_spare_thus_terminate, // 10110101 [181] + + // Spare (was Pop FPA) 1011011n + &&reserved_or_spare_thus_terminate, // 10110110 [182] + &&reserved_or_spare_thus_terminate, // 10110111 [183] + + // Pop VFP double-precision registers D[8]-D[8+nnn] saved 10111nnn + &&reserved_or_spare_thus_terminate, // 10111'000 [184] + &&reserved_or_spare_thus_terminate, // 10111'001 [185] + &&reserved_or_spare_thus_terminate, // 10111'010 [186] + &&reserved_or_spare_thus_terminate, // 10111'011 [187] + &&reserved_or_spare_thus_terminate, // 10111'100 [188] + &&reserved_or_spare_thus_terminate, // 10111'101 [189] + &&reserved_or_spare_thus_terminate, // 10111'110 [190] + &&reserved_or_spare_thus_terminate, // 10111'111 [191] + + // Intel Wireless MMX pop wR[10]-wR[10+nnn] 11000nnn + &&reserved_or_spare_thus_terminate, // 11000'000 [192] + &&reserved_or_spare_thus_terminate, // 11000'001 [193] + &&reserved_or_spare_thus_terminate, // 11000'010 [194] + &&reserved_or_spare_thus_terminate, // 11000'011 [195] + &&reserved_or_spare_thus_terminate, // 11000'100 [196] + &&reserved_or_spare_thus_terminate, // 11000'101 [197] + + // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] + &&reserved_or_spare_thus_terminate, // 11000'110 [198] + + // Spare (11000111) + &&reserved_or_spare_thus_terminate, // 11000'111 [199] + + // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by + // VPUSH (11001000) + &&reserved_or_spare_thus_terminate, // 11001000 [200] + + // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by + // VPUSH (11001001) + &&reserved_or_spare_thus_terminate, // 11001001 [201] + + // Spare (yyy != 000, 001) 11001yyy + &&reserved_or_spare_thus_terminate, // 11001'010 [202] + &&reserved_or_spare_thus_terminate, // 11001'011 [203] + &&reserved_or_spare_thus_terminate, // 11001'100 [204] + &&reserved_or_spare_thus_terminate, // 11001'101 [205] + &&reserved_or_spare_thus_terminate, // 11001'110 [206] + &&reserved_or_spare_thus_terminate, // 11001'111 [207] + + // Pop VFP double-precision registers D[8]-D[8+nnn] saved by VPUSH 11010nnn + &&reserved_or_spare_thus_terminate, // 11010'000 [208] + &&reserved_or_spare_thus_terminate, // 11010'001 [209] + &&reserved_or_spare_thus_terminate, // 11010'010 [210] + &&reserved_or_spare_thus_terminate, // 11010'011 [211] + &&reserved_or_spare_thus_terminate, // 11010'100 [212] + &&reserved_or_spare_thus_terminate, // 11010'101 [213] + &&reserved_or_spare_thus_terminate, // 11010'110 [214] + &&reserved_or_spare_thus_terminate, // 11010'111 [215] + + // Spare (xxx != 000, 001, 010) 11xxxyyy + + &&reserved_or_spare_thus_terminate, // 11011'000 [216] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [] + &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [231] + &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [] + &&reserved_or_spare_thus_terminate, // 11011'000 [] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + &&reserved_or_spare_thus_terminate, // 11011'111 [247] + + &&reserved_or_spare_thus_terminate, // 11011'000 [248] + &&reserved_or_spare_thus_terminate, // 11011'001 [] + &&reserved_or_spare_thus_terminate, // 11011'010 [] + &&reserved_or_spare_thus_terminate, // 11011'011 [] + &&reserved_or_spare_thus_terminate, // 11011'100 [] + &&reserved_or_spare_thus_terminate, // 11011'101 [] + &&reserved_or_spare_thus_terminate, // 11011'110 [] + // TODO(kammce): change this back to `&&reserved_or_spare_thus_terminate` + // Using this last instruction to mean "0xB0" finish. Because the LSDA data + // will typically as the DWARF offset encoding type set to 0xFF OMIT, we can + // utilize this to end the unwinding when the word boundary is hit. + &&finish_unwind, // 11111'111 [255] + }; + + static constexpr std::array big_to_little_endian_sequencer{ + 2, 1, 0, 7, 6, 5, 4, 11 + }; + + constexpr auto personality_type = hal::bit_mask::from<24, 27>(); + constexpr auto generic = hal::bit_mask::from<31>(); + + std::uint8_t const* unwind_instructions = nullptr; + auto const& entry = *p_exception_object.cache.entry_ptr; + if (entry.has_inlined_personality()) { + unwind_instructions = as(&entry.personality_offset); + } else { + auto const* personality = entry.personality(); + if (hal::bit_extract(personality[0])) { + unwind_instructions = as(&personality[0]); + } else { + // If the generic bit is not set, then this is an LSDA. + // + // The first 4-byte word [0] will be the prel31 offset to GCC's + // __gcc_personality_v0 as per the Itanium EH spec. The next word(s) [1] + // are the native unwind instructions. Following the unwind information is + // the LSDA area. + unwind_instructions = as(&personality[1]); + } + } + + auto byte_sequencer = big_to_little_endian_sequencer.begin(); + + if (hal::bit_extract(unwind_instructions[0]) != 0x0) { + byte_sequencer++; + } + + auto& virtual_cpu = p_exception_object.cpu; + bool move_lr_to_pc = true; + std::uint32_t u32_storage = 0; + auto const* sp_ptr = *virtual_cpu.sp; + + while (true) { + auto const instruction = unwind_instructions[*byte_sequencer++]; + auto const next_instruction = unwind_instructions[*byte_sequencer]; + auto const* instruction_handler = jump_table[instruction]; + goto* instruction_handler; + + // +=========================================================================+ + // | Finish! | + // +=========================================================================+ + finish_unwind: + virtual_cpu.sp = sp_ptr; + [[likely]] if (move_lr_to_pc) { + virtual_cpu.pc = virtual_cpu.lr; + } + break; + + reserved_or_spare_thus_terminate: + std::terminate(); + break; + + subtract_vsp_using_uleb128: + static constexpr auto uleb128_offset = 0x204 / sizeof(std::uint32_t); + // TODO(kammce): this is obviously broken. You may need to write this in + // from scratch to manage the fact that the bytes are in big endian sequence + // vs the native little endian. + sp_ptr += read_uleb128(nullptr) + uleb128_offset; + continue; + + pop_integer_registers_under_mask_r3_r2_r1_r0: + // If the next unwind instruction equals 0, or if the bits from 4 or 7 + // contains any 1s, then its time to terminate + if (next_instruction == 0b0000'0000 || (next_instruction & 0xF0) != 0) { + goto reserved_or_spare_thus_terminate; + } + + u32_storage = next_instruction; + + while (u32_storage) { + // The first bit corresponds to the R0 + std::uint32_t lsb_bit_position = std::countr_zero(u32_storage); + // Copy value from the stack, increment stack pointer. + virtual_cpu[lsb_bit_position] = *(sp_ptr++); + // Clear the bit for the lsb_bit_position + u32_storage = u32_storage & ~(1 << lsb_bit_position); + } + byte_sequencer++; + continue; + + refuse_unwind_or_pop: + // If the next unwind instruction equals 0, then its time to terminate + if (next_instruction == 0b0000'0000) { + goto reserved_or_spare_thus_terminate; + } + + // ************************************************************************* + // !!!! WARNING !!!! + // + // `refuse_unwind_or_pop` MUST BE directly above `pop_under_mask` + // + // refuse_unwind_or_pop ---> [[fallthrough]] --> pop_under_mask + // ************************************************************************* + + pop_under_mask: + // Because this unwind instruction is meant to be rare, we will use a while + // loop here rather than unroll this loop. Unless there is some incentive to + // improve the performance for this instruction. + + // Save the lower 4-bits of the previous instruction and the 8-bits of the + // current instruction and combine them. + u32_storage = instruction & 0xF; + u32_storage <<= 8; + u32_storage |= next_instruction; + + if (u32_storage & (1 << 3)) { + move_lr_to_pc = false; + } + + // TODO(kammce): consider (remark b) + // ======================================================================== + // > ‘Pop’ generally denotes removal from the stack commencing at current + // > vsp, with subsequent increment of vsp to beyond the removed quantities. + // > The sole exception to this rule is popping r13, when the writeback of + // > the loaded value to vsp is delayed until after the whole instruction + // > has completed. When multiple registers are popped by a single + // > instruction they are taken as lowest numbered register at lowest stack + // > address. + // ========================================================================= + + while (u32_storage) { + // Get the first 1's distance from the right. We add 12 because the + // mask's first bit represents r4 and increases from there. The first + // byte, the instruction byte, only contains the registers from 12 + // to 15. + std::uint32_t lsb_bit_position = std::countr_zero(u32_storage); + // Clear the bit for the lsb_bit_position + u32_storage = u32_storage & ~(1 << lsb_bit_position); + // Copy value from the stack, increment stack pointer. + virtual_cpu[lsb_bit_position + 4U] = *(sp_ptr++); + } + + byte_sequencer++; + continue; + + // +=========================================================================+ + // | VSP = R[nnnn] | + // +=========================================================================+ + assign_to_vsp_to_reg_nnnn: + // Get the current instruction and get all lower 4-bits + u32_storage = instruction & 0xF; + sp_ptr = *virtual_cpu[u32_storage]; + continue; + + // +=========================================================================+ + // | Sequentially Pop Registers + LR | + // +=========================================================================+ + pop_off_stack_r4_to_r11_and_lr: + sp_ptr = pop_register_range<7, pop_lr::do_it>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r10_and_lr: + sp_ptr = pop_register_range<6, pop_lr::do_it>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r9_and_lr: + sp_ptr = pop_register_range<5, pop_lr::do_it>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r8_and_lr: + sp_ptr = pop_register_range<4, pop_lr::do_it>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r7_and_lr: + sp_ptr = pop_register_range<3, pop_lr::do_it>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r6_and_lr: + sp_ptr = pop_register_range<2, pop_lr::do_it>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r5_and_lr: + sp_ptr = pop_register_range<1, pop_lr::do_it>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r4_and_lr: + sp_ptr = pop_register_range<0, pop_lr::do_it>(sp_ptr, virtual_cpu); + continue; + + // +=========================================================================+ + // | Sequentially Pop Registers | + // +=========================================================================+ + pop_off_stack_r4_to_r11: + sp_ptr = pop_register_range<7>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r10: + sp_ptr = pop_register_range<6>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r9: + sp_ptr = pop_register_range<5>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r8: + sp_ptr = pop_register_range<4>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r7: + sp_ptr = pop_register_range<3>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r6: + sp_ptr = pop_register_range<2>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r5: + sp_ptr = pop_register_range<1>(sp_ptr, virtual_cpu); + continue; + pop_off_stack_r4_to_r4: + sp_ptr = pop_register_range<0>(sp_ptr, virtual_cpu); + continue; + + // +=========================================================================+ + // | Add VSP | + // +=========================================================================+ + vsp_add_0: + sp_ptr = sp_ptr + vsp_deallocate_amount<0>(); + continue; + vsp_add_1: + sp_ptr = sp_ptr + vsp_deallocate_amount<1>(); + continue; + vsp_add_2: + sp_ptr = sp_ptr + vsp_deallocate_amount<2>(); + continue; + vsp_add_3: + sp_ptr = sp_ptr + vsp_deallocate_amount<3>(); + continue; + vsp_add_4: + sp_ptr = sp_ptr + vsp_deallocate_amount<4>(); + continue; + vsp_add_5: + sp_ptr = sp_ptr + vsp_deallocate_amount<5>(); + continue; + vsp_add_6: + sp_ptr = sp_ptr + vsp_deallocate_amount<6>(); + continue; + vsp_add_7: + sp_ptr = sp_ptr + vsp_deallocate_amount<7>(); + continue; + vsp_add_8: + sp_ptr = sp_ptr + vsp_deallocate_amount<8>(); + continue; + vsp_add_9: + sp_ptr = sp_ptr + vsp_deallocate_amount<9>(); + continue; + vsp_add_10: + sp_ptr = sp_ptr + vsp_deallocate_amount<10>(); + continue; + vsp_add_11: + sp_ptr = sp_ptr + vsp_deallocate_amount<11>(); + continue; + vsp_add_12: + sp_ptr = sp_ptr + vsp_deallocate_amount<12>(); + continue; + vsp_add_13: + sp_ptr = sp_ptr + vsp_deallocate_amount<13>(); + continue; + vsp_add_14: + sp_ptr = sp_ptr + vsp_deallocate_amount<14>(); + continue; + vsp_add_15: + sp_ptr = sp_ptr + vsp_deallocate_amount<15>(); + continue; + vsp_add_16: + sp_ptr = sp_ptr + vsp_deallocate_amount<16>(); + continue; + vsp_add_17: + sp_ptr = sp_ptr + vsp_deallocate_amount<17>(); + continue; + vsp_add_18: + sp_ptr = sp_ptr + vsp_deallocate_amount<18>(); + continue; + vsp_add_19: + sp_ptr = sp_ptr + vsp_deallocate_amount<19>(); + continue; + vsp_add_20: + sp_ptr = sp_ptr + vsp_deallocate_amount<20>(); + continue; + vsp_add_21: + sp_ptr = sp_ptr + vsp_deallocate_amount<21>(); + continue; + vsp_add_22: + sp_ptr = sp_ptr + vsp_deallocate_amount<22>(); + continue; + vsp_add_23: + sp_ptr = sp_ptr + vsp_deallocate_amount<23>(); + continue; + vsp_add_24: + sp_ptr = sp_ptr + vsp_deallocate_amount<24>(); + continue; + vsp_add_25: + sp_ptr = sp_ptr + vsp_deallocate_amount<25>(); + continue; + vsp_add_26: + sp_ptr = sp_ptr + vsp_deallocate_amount<26>(); + continue; + vsp_add_27: + sp_ptr = sp_ptr + vsp_deallocate_amount<27>(); + continue; + vsp_add_28: + sp_ptr = sp_ptr + vsp_deallocate_amount<28>(); + continue; + vsp_add_29: + sp_ptr = sp_ptr + vsp_deallocate_amount<29>(); + continue; + vsp_add_30: + sp_ptr = sp_ptr + vsp_deallocate_amount<30>(); + continue; + vsp_add_31: + sp_ptr = sp_ptr + vsp_deallocate_amount<31>(); + continue; + vsp_add_32: + sp_ptr = sp_ptr + vsp_deallocate_amount<32>(); + continue; + vsp_add_33: + sp_ptr = sp_ptr + vsp_deallocate_amount<33>(); + continue; + vsp_add_34: + sp_ptr = sp_ptr + vsp_deallocate_amount<34>(); + continue; + vsp_add_35: + sp_ptr = sp_ptr + vsp_deallocate_amount<35>(); + continue; + vsp_add_36: + sp_ptr = sp_ptr + vsp_deallocate_amount<36>(); + continue; + vsp_add_37: + sp_ptr = sp_ptr + vsp_deallocate_amount<37>(); + continue; + vsp_add_38: + sp_ptr = sp_ptr + vsp_deallocate_amount<38>(); + continue; + vsp_add_39: + sp_ptr = sp_ptr + vsp_deallocate_amount<39>(); + continue; + vsp_add_40: + sp_ptr = sp_ptr + vsp_deallocate_amount<40>(); + continue; + vsp_add_41: + sp_ptr = sp_ptr + vsp_deallocate_amount<41>(); + continue; + vsp_add_42: + sp_ptr = sp_ptr + vsp_deallocate_amount<42>(); + continue; + vsp_add_43: + sp_ptr = sp_ptr + vsp_deallocate_amount<43>(); + continue; + vsp_add_44: + sp_ptr = sp_ptr + vsp_deallocate_amount<44>(); + continue; + vsp_add_45: + sp_ptr = sp_ptr + vsp_deallocate_amount<45>(); + continue; + vsp_add_46: + sp_ptr = sp_ptr + vsp_deallocate_amount<46>(); + continue; + vsp_add_47: + sp_ptr = sp_ptr + vsp_deallocate_amount<47>(); + continue; + vsp_add_48: + sp_ptr = sp_ptr + vsp_deallocate_amount<48>(); + continue; + vsp_add_49: + sp_ptr = sp_ptr + vsp_deallocate_amount<49>(); + continue; + vsp_add_50: + sp_ptr = sp_ptr + vsp_deallocate_amount<50>(); + continue; + vsp_add_51: + sp_ptr = sp_ptr + vsp_deallocate_amount<51>(); + continue; + vsp_add_52: + sp_ptr = sp_ptr + vsp_deallocate_amount<52>(); + continue; + vsp_add_53: + sp_ptr = sp_ptr + vsp_deallocate_amount<53>(); + continue; + vsp_add_54: + sp_ptr = sp_ptr + vsp_deallocate_amount<54>(); + continue; + vsp_add_55: + sp_ptr = sp_ptr + vsp_deallocate_amount<55>(); + continue; + vsp_add_56: + sp_ptr = sp_ptr + vsp_deallocate_amount<56>(); + continue; + vsp_add_57: + sp_ptr = sp_ptr + vsp_deallocate_amount<57>(); + continue; + vsp_add_58: + sp_ptr = sp_ptr + vsp_deallocate_amount<58>(); + continue; + vsp_add_59: + sp_ptr = sp_ptr + vsp_deallocate_amount<59>(); + continue; + vsp_add_60: + sp_ptr = sp_ptr + vsp_deallocate_amount<60>(); + continue; + vsp_add_61: + sp_ptr = sp_ptr + vsp_deallocate_amount<61>(); + continue; + vsp_add_62: + sp_ptr = sp_ptr + vsp_deallocate_amount<62>(); + continue; + vsp_add_63: + sp_ptr = sp_ptr + vsp_deallocate_amount<63>(); + continue; + + // +=========================================================================+ + // | Sub VSP | + // +=========================================================================+ + vsp_sub_0: + sp_ptr = sp_ptr + vsp_deallocate_amount<0>(); + continue; + vsp_sub_1: + sp_ptr = sp_ptr + vsp_deallocate_amount<1>(); + continue; + vsp_sub_2: + sp_ptr = sp_ptr + vsp_deallocate_amount<2>(); + continue; + vsp_sub_3: + sp_ptr = sp_ptr + vsp_deallocate_amount<3>(); + continue; + vsp_sub_4: + sp_ptr = sp_ptr + vsp_deallocate_amount<4>(); + continue; + vsp_sub_5: + sp_ptr = sp_ptr + vsp_deallocate_amount<5>(); + continue; + vsp_sub_6: + sp_ptr = sp_ptr + vsp_deallocate_amount<6>(); + continue; + vsp_sub_7: + sp_ptr = sp_ptr + vsp_deallocate_amount<7>(); + continue; + vsp_sub_8: + sp_ptr = sp_ptr + vsp_deallocate_amount<8>(); + continue; + vsp_sub_9: + sp_ptr = sp_ptr + vsp_deallocate_amount<9>(); + continue; + vsp_sub_10: + sp_ptr = sp_ptr + vsp_deallocate_amount<10>(); + continue; + vsp_sub_11: + sp_ptr = sp_ptr + vsp_deallocate_amount<11>(); + continue; + vsp_sub_12: + sp_ptr = sp_ptr + vsp_deallocate_amount<12>(); + continue; + vsp_sub_13: + sp_ptr = sp_ptr + vsp_deallocate_amount<13>(); + continue; + vsp_sub_14: + sp_ptr = sp_ptr + vsp_deallocate_amount<14>(); + continue; + vsp_sub_15: + sp_ptr = sp_ptr + vsp_deallocate_amount<15>(); + continue; + vsp_sub_16: + sp_ptr = sp_ptr + vsp_deallocate_amount<16>(); + continue; + vsp_sub_17: + sp_ptr = sp_ptr + vsp_deallocate_amount<17>(); + continue; + vsp_sub_18: + sp_ptr = sp_ptr + vsp_deallocate_amount<18>(); + continue; + vsp_sub_19: + sp_ptr = sp_ptr + vsp_deallocate_amount<19>(); + continue; + vsp_sub_20: + sp_ptr = sp_ptr + vsp_deallocate_amount<20>(); + continue; + vsp_sub_21: + sp_ptr = sp_ptr + vsp_deallocate_amount<21>(); + continue; + vsp_sub_22: + sp_ptr = sp_ptr + vsp_deallocate_amount<22>(); + continue; + vsp_sub_23: + sp_ptr = sp_ptr + vsp_deallocate_amount<23>(); + continue; + vsp_sub_24: + sp_ptr = sp_ptr + vsp_deallocate_amount<24>(); + continue; + vsp_sub_25: + sp_ptr = sp_ptr + vsp_deallocate_amount<25>(); + continue; + vsp_sub_26: + sp_ptr = sp_ptr + vsp_deallocate_amount<26>(); + continue; + vsp_sub_27: + sp_ptr = sp_ptr + vsp_deallocate_amount<27>(); + continue; + vsp_sub_28: + sp_ptr = sp_ptr + vsp_deallocate_amount<28>(); + continue; + vsp_sub_29: + sp_ptr = sp_ptr + vsp_deallocate_amount<29>(); + continue; + vsp_sub_30: + sp_ptr = sp_ptr + vsp_deallocate_amount<30>(); + continue; + vsp_sub_31: + sp_ptr = sp_ptr + vsp_deallocate_amount<31>(); + continue; + vsp_sub_32: + sp_ptr = sp_ptr + vsp_deallocate_amount<32>(); + continue; + vsp_sub_33: + sp_ptr = sp_ptr + vsp_deallocate_amount<33>(); + continue; + vsp_sub_34: + sp_ptr = sp_ptr + vsp_deallocate_amount<34>(); + continue; + vsp_sub_35: + sp_ptr = sp_ptr + vsp_deallocate_amount<35>(); + continue; + vsp_sub_36: + sp_ptr = sp_ptr + vsp_deallocate_amount<36>(); + continue; + vsp_sub_37: + sp_ptr = sp_ptr + vsp_deallocate_amount<37>(); + continue; + vsp_sub_38: + sp_ptr = sp_ptr + vsp_deallocate_amount<38>(); + continue; + vsp_sub_39: + sp_ptr = sp_ptr + vsp_deallocate_amount<39>(); + continue; + vsp_sub_40: + sp_ptr = sp_ptr + vsp_deallocate_amount<40>(); + continue; + vsp_sub_41: + sp_ptr = sp_ptr + vsp_deallocate_amount<41>(); + continue; + vsp_sub_42: + sp_ptr = sp_ptr + vsp_deallocate_amount<42>(); + continue; + vsp_sub_43: + sp_ptr = sp_ptr + vsp_deallocate_amount<43>(); + continue; + vsp_sub_44: + sp_ptr = sp_ptr + vsp_deallocate_amount<44>(); + continue; + vsp_sub_45: + sp_ptr = sp_ptr + vsp_deallocate_amount<45>(); + continue; + vsp_sub_46: + sp_ptr = sp_ptr + vsp_deallocate_amount<46>(); + continue; + vsp_sub_47: + sp_ptr = sp_ptr + vsp_deallocate_amount<47>(); + continue; + vsp_sub_48: + sp_ptr = sp_ptr + vsp_deallocate_amount<48>(); + continue; + vsp_sub_49: + sp_ptr = sp_ptr + vsp_deallocate_amount<49>(); + continue; + vsp_sub_50: + sp_ptr = sp_ptr + vsp_deallocate_amount<50>(); + continue; + vsp_sub_51: + sp_ptr = sp_ptr + vsp_deallocate_amount<51>(); + continue; + vsp_sub_52: + sp_ptr = sp_ptr + vsp_deallocate_amount<52>(); + continue; + vsp_sub_53: + sp_ptr = sp_ptr + vsp_deallocate_amount<53>(); + continue; + vsp_sub_54: + sp_ptr = sp_ptr + vsp_deallocate_amount<54>(); + continue; + vsp_sub_55: + sp_ptr = sp_ptr + vsp_deallocate_amount<55>(); + continue; + vsp_sub_56: + sp_ptr = sp_ptr + vsp_deallocate_amount<56>(); + continue; + vsp_sub_57: + sp_ptr = sp_ptr + vsp_deallocate_amount<57>(); + continue; + vsp_sub_58: + sp_ptr = sp_ptr + vsp_deallocate_amount<58>(); + continue; + vsp_sub_59: + sp_ptr = sp_ptr + vsp_deallocate_amount<59>(); + continue; + vsp_sub_60: + sp_ptr = sp_ptr + vsp_deallocate_amount<60>(); + continue; + vsp_sub_61: + sp_ptr = sp_ptr + vsp_deallocate_amount<61>(); + continue; + vsp_sub_62: + sp_ptr = sp_ptr + vsp_deallocate_amount<62>(); + continue; + vsp_sub_63: + sp_ptr = sp_ptr + vsp_deallocate_amount<63>(); + continue; + } +} +#endif -instructions_t create_instructions_from_entry(index_entry_t const& p_entry) +[[gnu::always_inline]] +inline instructions_t create_instructions_from_entry( + index_entry_t const& p_entry) { constexpr auto personality_type = hal::bit_mask::from<24, 27>(); constexpr auto generic = hal::bit_mask::from<31>(); @@ -2056,10 +2976,13 @@ instructions_t create_instructions_from_entry(index_entry_t const& p_entry) if (p_entry.has_inlined_personality()) { handler_data = &p_entry.personality_offset; - } else if (hal::bit_extract(p_entry.personality()[0])) { - handler_data = &p_entry.personality()[0]; } else { - handler_data = &p_entry.personality()[1]; + auto const* personality = p_entry.personality(); + if (hal::bit_extract(personality[0])) { + handler_data = &personality[0]; + } else { + handler_data = &personality[1]; + } } std::uint32_t header = handler_data[0]; From bb00c65fb98009e17ba316c830464aa8ae6b83d7 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Tue, 23 Jul 2024 12:22:46 -0700 Subject: [PATCH 10/14] :fire: Remove some uneeded unwind code --- src/arm_cortex/estell/exception.cpp | 1074 +-------------------------- 1 file changed, 1 insertion(+), 1073 deletions(-) diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index 5fbda84..9768cb4 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -996,32 +996,7 @@ inline std::uint32_t const* pop_register_range(std::uint32_t const* sp_ptr, static_assert(PopCount <= 7, "Pop Count cannot be above 7"); // NOTE: A for loop has the same cycle count, and is more compact -#if 0 - if constexpr (PopCount >= 0) { - *(r4_pointer++) = *(sp_ptr++); - } - if constexpr (PopCount >= 1) { - *(r4_pointer++) = *(sp_ptr++); - } - if constexpr (PopCount >= 2) { - *(r4_pointer++) = *(sp_ptr++); - } - if constexpr (PopCount >= 3) { - *(r4_pointer++) = *(sp_ptr++); - } - if constexpr (PopCount >= 4) { - *(r4_pointer++) = *(sp_ptr++); - } - if constexpr (PopCount >= 5) { - *(r4_pointer++) = *(sp_ptr++); - } - if constexpr (PopCount >= 6) { - *(r4_pointer++) = *(sp_ptr++); - } - if constexpr (PopCount == 7) { - *(r4_pointer++) = *(sp_ptr++); - } -#else + if constexpr (PopCount == 0) { *r4_pointer = *sp_ptr; } else { @@ -1029,7 +1004,6 @@ inline std::uint32_t const* pop_register_range(std::uint32_t const* sp_ptr, r4_pointer[i] = sp_ptr[i]; } } -#endif if constexpr (PopLinkRegister == pop_lr::do_it) { p_virtual_cpu.lr = sp_ptr[PopCount + 1]; @@ -1914,1052 +1888,6 @@ void unwind_frame(instructions_t const& p_instructions, sp_ptr = sp_ptr + vsp_deallocate_amount<63>(); continue; } - -#if 0 - // +========================================================================== - // | OLD STUFF - // +========================================================================== - for (auto instruction = p_instructions.data.begin(); - instruction != p_instructions.data.end() && - *instruction != arm_ehabi::finish; - instruction++) { - // Extract the first 4 bits - int main_bits = (*instruction & 0b11110000) >> 4; - - switch (main_bits) { - case 0b0000: - case 0b0001: - case 0b0010: - case 0b0011: { - // vsp = vsp + (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive - int shift_amount = *instruction & 0b111111; - virtual_cpu.sp = virtual_cpu.sp + ((shift_amount << 2) + 4); - break; - } - case 0b0100: - case 0b0101: - case 0b0110: - case 0b0111: { - // vsp = vsp - (xxxxxx << 2) + 4. Covers range 0x04-0x100 inclusive - int shift_amount = *instruction & 0b111111; - virtual_cpu.sp = virtual_cpu.sp - ((shift_amount << 2) + 4); - break; - } - case 0b1001: { - // Handle "1001nnnn" - int nnnn = *instruction & 0xF; - if (nnnn != 13 && nnnn != 15) { - // Set vsp = r[nnnn] - virtual_cpu.sp = virtual_cpu[nnnn]; - } else { - // Handle "10011101" or "10011111" - // Reserved as prefix for Arm register to register moves - // Reserved as prefix for Intel Wireless MMX register to register - // moves - std::terminate(); - } - break; - } - case 0b1010: { - // Handle: - // - // "10100nnn" (Pop r4-r[4+nnn]), and - // "10101nnn" (Pop r4-r[4+nnn], r14) - // - std::uint32_t const* sp_ptr = *virtual_cpu.sp; - int nnn = *instruction & 0b111; // Extract the last 3 bits - switch (nnn) { - case 7: - virtual_cpu[11] = sp_ptr[7]; - [[fallthrough]]; - case 6: - virtual_cpu[10] = sp_ptr[6]; - [[fallthrough]]; - case 5: - virtual_cpu[9] = sp_ptr[5]; - [[fallthrough]]; - case 4: - virtual_cpu[8] = sp_ptr[4]; - [[fallthrough]]; - case 3: - virtual_cpu[7] = sp_ptr[3]; - [[fallthrough]]; - case 2: - virtual_cpu[6] = sp_ptr[2]; - [[fallthrough]]; - case 1: - virtual_cpu[5] = sp_ptr[1]; - [[fallthrough]]; - case 0: - virtual_cpu[4] = sp_ptr[0]; - } - - if (*instruction & 0b1000) { - virtual_cpu.lr = sp_ptr[nnn + 1]; - // +1 because "nnn" starts at zero and we need to decrement something. - // The second +1 is for popping the LR register. - sp_ptr += (nnn + 2); - } else { - // See above comments. - sp_ptr += (nnn + 1); - } - - virtual_cpu.sp = sp_ptr; - break; - } - case 0b1011: { - // Handle "10110000", and "1011011n" - if (*instruction == arm_ehabi::finish) { - // "10110000" - // Finish (see remark c) - goto exit_loop; - } else if ((*instruction & 0b1100) == 0b1100) { - // "1011011n" - // Spare (was Pop FPA) - std::terminate(); - } else if (*instruction == 0xB1) { - std::uint32_t mask = *(++instruction); - pop_registers(virtual_cpu, mask); - } - break; - } - case 0b1000: { - std::uint32_t mask = (*instruction & 0xF) << (8 + 4); - instruction++; - mask |= (*instruction << 4); - pop_registers(virtual_cpu, mask); - break; - } - // No additional groupings are left as all provided instructions are - // covered - default: { - // Handle unknown or undefined instruction - std::terminate(); - } - } - } - -exit_loop: - if (!move_lr_to_pc) { - virtual_cpu.pc = virtual_cpu.lr; - } -#endif -} -#endif - -#if 0 -void unwind_frame2(exception_object& p_exception_object) -{ - static constexpr std::array jump_table{ - &&vsp_add_0, // [0] - &&vsp_add_1, // [1] - &&vsp_add_2, // [2] - &&vsp_add_3, // [3] - &&vsp_add_4, // [4] - &&vsp_add_5, // [5] - &&vsp_add_6, // [6] - &&vsp_add_7, // [7] - &&vsp_add_8, // [8] - &&vsp_add_9, // [9] - &&vsp_add_10, // [10] - &&vsp_add_11, // [11] - &&vsp_add_12, // [12] - &&vsp_add_13, // [13] - &&vsp_add_14, // [14] - &&vsp_add_15, // [15] - &&vsp_add_16, // [16] - &&vsp_add_17, // [17] - &&vsp_add_18, // [18] - &&vsp_add_19, // [19] - &&vsp_add_20, // [20] - &&vsp_add_21, // [21] - &&vsp_add_22, // [22] - &&vsp_add_23, // [23] - &&vsp_add_24, // [24] - &&vsp_add_25, // [25] - &&vsp_add_26, // [26] - &&vsp_add_27, // [27] - &&vsp_add_28, // [28] - &&vsp_add_29, // [29] - &&vsp_add_30, // [30] - &&vsp_add_31, // [31] - &&vsp_add_32, // [32] - &&vsp_add_33, // [33] - &&vsp_add_34, // [34] - &&vsp_add_35, // [35] - &&vsp_add_36, // [36] - &&vsp_add_37, // [37] - &&vsp_add_38, // [38] - &&vsp_add_39, // [39] - &&vsp_add_40, // [40] - &&vsp_add_41, // [41] - &&vsp_add_42, // [42] - &&vsp_add_43, // [43] - &&vsp_add_44, // [44] - &&vsp_add_45, // [45] - &&vsp_add_46, // [46] - &&vsp_add_47, // [47] - &&vsp_add_48, // [48] - &&vsp_add_49, // [49] - &&vsp_add_50, // [50] - &&vsp_add_51, // [51] - &&vsp_add_52, // [52] - &&vsp_add_53, // [53] - &&vsp_add_54, // [54] - &&vsp_add_55, // [55] - &&vsp_add_56, // [56] - &&vsp_add_57, // [57] - &&vsp_add_58, // [58] - &&vsp_add_59, // [59] - &&vsp_add_60, // [60] - &&vsp_add_61, // [61] - &&vsp_add_62, // [62] - &&vsp_add_63, // [63] - - &&vsp_sub_0, // [64] - &&vsp_sub_1, // [65] - &&vsp_sub_2, // [66] - &&vsp_sub_3, // [67] - &&vsp_sub_4, // [68] - &&vsp_sub_5, // [69] - &&vsp_sub_6, // [70] - &&vsp_sub_7, // [71] - &&vsp_sub_8, // [72] - &&vsp_sub_9, // [73] - &&vsp_sub_10, // [74] - &&vsp_sub_11, // [75] - &&vsp_sub_12, // [76] - &&vsp_sub_13, // [77] - &&vsp_sub_14, // [78] - &&vsp_sub_15, // [79] - &&vsp_sub_16, // [80] - &&vsp_sub_17, // [81] - &&vsp_sub_18, // [82] - &&vsp_sub_19, // [83] - &&vsp_sub_20, // [84] - &&vsp_sub_21, // [85] - &&vsp_sub_22, // [86] - &&vsp_sub_23, // [87] - &&vsp_sub_24, // [88] - &&vsp_sub_25, // [89] - &&vsp_sub_26, // [90] - &&vsp_sub_27, // [91] - &&vsp_sub_28, // [92] - &&vsp_sub_29, // [93] - &&vsp_sub_30, // [94] - &&vsp_sub_31, // [95] - &&vsp_sub_32, // [96] - &&vsp_sub_33, // [97] - &&vsp_sub_34, // [98] - &&vsp_sub_35, // [99] - &&vsp_sub_36, // [100] - &&vsp_sub_37, // [101] - &&vsp_sub_38, // [102] - &&vsp_sub_39, // [103] - &&vsp_sub_40, // [104] - &&vsp_sub_41, // [105] - &&vsp_sub_42, // [106] - &&vsp_sub_43, // [107] - &&vsp_sub_44, // [108] - &&vsp_sub_45, // [109] - &&vsp_sub_46, // [110] - &&vsp_sub_47, // [111] - &&vsp_sub_48, // [112] - &&vsp_sub_49, // [113] - &&vsp_sub_50, // [114] - &&vsp_sub_51, // [115] - &&vsp_sub_52, // [116] - &&vsp_sub_53, // [117] - &&vsp_sub_54, // [118] - &&vsp_sub_55, // [119] - &&vsp_sub_56, // [120] - &&vsp_sub_57, // [121] - &&vsp_sub_58, // [122] - &&vsp_sub_59, // [123] - &&vsp_sub_60, // [124] - &&vsp_sub_61, // [125] - &&vsp_sub_62, // [126] - &&vsp_sub_63, // [127] - - // 10000000 - &&refuse_unwind_or_pop, // [0b1000'0000 = 128] - - // 1000iiii ... - &&pop_under_mask, // [0b1000'0001 = 129] - &&pop_under_mask, // [0b1000'0010 = 130] - &&pop_under_mask, // [0b1000'0011 = 131] - &&pop_under_mask, // [0b1000'0100 = 132] - &&pop_under_mask, // [0b1000'0101 = 133] - &&pop_under_mask, // [0b1000'0110 = 134] - &&pop_under_mask, // [0b1000'0111 = 135] - &&pop_under_mask, // [0b1000'1000 = 136] - &&pop_under_mask, // [0b1000'1001 = 137] - &&pop_under_mask, // [0b1000'1010 = 138] - &&pop_under_mask, // [0b1000'1011 = 139] - &&pop_under_mask, // [0b1000'1100 = 140] - &&pop_under_mask, // [0b1000'1101 = 141] - &&pop_under_mask, // [0b1000'1110 = 142] - &&pop_under_mask, // [0b1000'1111 = 143] (128 + 15) - - // 1001nnnn - // TODO: Split up assignments to make them faster - &&assign_to_vsp_to_reg_nnnn, // [0b1001'0000 = 144] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'0001 = 145] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'0010 = 146] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'0011 = 147] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'0100 = 148] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'0101 = 149] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'0110 = 150] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'0111 = 151] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'1000 = 152] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'1001 = 153] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'1010 = 154] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'1011 = 155] - &&assign_to_vsp_to_reg_nnnn, // [0b1001'1100 = 156] - // Reserved as prefix for Arm register to register moves - &&reserved_or_spare_thus_terminate, // [0b1001'1101 = 157] - // Reserved as prefix for Intel Wireless MMX register to register moves - &&assign_to_vsp_to_reg_nnnn, // [0b1001'1110 = 158] - &&reserved_or_spare_thus_terminate, // [0b1001'1111 = 159 reg 15 reserved] - - // 10100nnn - &&pop_off_stack_r4_to_r4, // 0b10100'000 [160] - &&pop_off_stack_r4_to_r5, // 0b10100'001 [161] - &&pop_off_stack_r4_to_r6, // 0b10100'010 [162] - &&pop_off_stack_r4_to_r7, // 0b10100'011 [163] - &&pop_off_stack_r4_to_r8, // 0b10100'100 [164] - &&pop_off_stack_r4_to_r9, // 0b10100'101 [165] - &&pop_off_stack_r4_to_r10, // 0b10100'110 [166] - &&pop_off_stack_r4_to_r11, // 0b10100'111 [167] - - // 10101nnn - &&pop_off_stack_r4_to_r4_and_lr, // 0b10101'000 [168] - &&pop_off_stack_r4_to_r5_and_lr, // 0b10101'001 [169] - &&pop_off_stack_r4_to_r6_and_lr, // 0b10101'010 [170] - &&pop_off_stack_r4_to_r7_and_lr, // 0b10101'011 [171] - &&pop_off_stack_r4_to_r8_and_lr, // 0b10101'100 [172] - &&pop_off_stack_r4_to_r9_and_lr, // 0b10101'101 [173] - &&pop_off_stack_r4_to_r10_and_lr, // 0b10101'110 [174] - &&pop_off_stack_r4_to_r11_and_lr, // 0b10101'111 [175] - - // Finish (0xB0) - &&finish_unwind, // 10110000 [176] - - // Spare (refuse unwind) - &&pop_integer_registers_under_mask_r3_r2_r1_r0, // 10110001 [177] - - // Subtract VSP using uleb128 - &&subtract_vsp_using_uleb128, // 10110010 [178] - - // Pop VFP double-precision registers (not supported currently) - &&reserved_or_spare_thus_terminate, // 10110011 [179] - - // Pop Return Address Authentication Code pseudo-register - &&reserved_or_spare_thus_terminate, // 10110100 [180] - - // Use current vsp as modifier in Return Address Authentication - &&reserved_or_spare_thus_terminate, // 10110101 [181] - - // Spare (was Pop FPA) 1011011n - &&reserved_or_spare_thus_terminate, // 10110110 [182] - &&reserved_or_spare_thus_terminate, // 10110111 [183] - - // Pop VFP double-precision registers D[8]-D[8+nnn] saved 10111nnn - &&reserved_or_spare_thus_terminate, // 10111'000 [184] - &&reserved_or_spare_thus_terminate, // 10111'001 [185] - &&reserved_or_spare_thus_terminate, // 10111'010 [186] - &&reserved_or_spare_thus_terminate, // 10111'011 [187] - &&reserved_or_spare_thus_terminate, // 10111'100 [188] - &&reserved_or_spare_thus_terminate, // 10111'101 [189] - &&reserved_or_spare_thus_terminate, // 10111'110 [190] - &&reserved_or_spare_thus_terminate, // 10111'111 [191] - - // Intel Wireless MMX pop wR[10]-wR[10+nnn] 11000nnn - &&reserved_or_spare_thus_terminate, // 11000'000 [192] - &&reserved_or_spare_thus_terminate, // 11000'001 [193] - &&reserved_or_spare_thus_terminate, // 11000'010 [194] - &&reserved_or_spare_thus_terminate, // 11000'011 [195] - &&reserved_or_spare_thus_terminate, // 11000'100 [196] - &&reserved_or_spare_thus_terminate, // 11000'101 [197] - - // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] - &&reserved_or_spare_thus_terminate, // 11000'110 [198] - - // Spare (11000111) - &&reserved_or_spare_thus_terminate, // 11000'111 [199] - - // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by - // VPUSH (11001000) - &&reserved_or_spare_thus_terminate, // 11001000 [200] - - // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by - // VPUSH (11001001) - &&reserved_or_spare_thus_terminate, // 11001001 [201] - - // Spare (yyy != 000, 001) 11001yyy - &&reserved_or_spare_thus_terminate, // 11001'010 [202] - &&reserved_or_spare_thus_terminate, // 11001'011 [203] - &&reserved_or_spare_thus_terminate, // 11001'100 [204] - &&reserved_or_spare_thus_terminate, // 11001'101 [205] - &&reserved_or_spare_thus_terminate, // 11001'110 [206] - &&reserved_or_spare_thus_terminate, // 11001'111 [207] - - // Pop VFP double-precision registers D[8]-D[8+nnn] saved by VPUSH 11010nnn - &&reserved_or_spare_thus_terminate, // 11010'000 [208] - &&reserved_or_spare_thus_terminate, // 11010'001 [209] - &&reserved_or_spare_thus_terminate, // 11010'010 [210] - &&reserved_or_spare_thus_terminate, // 11010'011 [211] - &&reserved_or_spare_thus_terminate, // 11010'100 [212] - &&reserved_or_spare_thus_terminate, // 11010'101 [213] - &&reserved_or_spare_thus_terminate, // 11010'110 [214] - &&reserved_or_spare_thus_terminate, // 11010'111 [215] - - // Spare (xxx != 000, 001, 010) 11xxxyyy - - &&reserved_or_spare_thus_terminate, // 11011'000 [216] - &&reserved_or_spare_thus_terminate, // 11011'001 [] - &&reserved_or_spare_thus_terminate, // 11011'010 [] - &&reserved_or_spare_thus_terminate, // 11011'011 [] - &&reserved_or_spare_thus_terminate, // 11011'100 [] - &&reserved_or_spare_thus_terminate, // 11011'101 [] - &&reserved_or_spare_thus_terminate, // 11011'110 [] - &&reserved_or_spare_thus_terminate, // 11011'111 [] - &&reserved_or_spare_thus_terminate, // 11011'000 [] - &&reserved_or_spare_thus_terminate, // 11011'001 [] - &&reserved_or_spare_thus_terminate, // 11011'010 [] - &&reserved_or_spare_thus_terminate, // 11011'011 [] - &&reserved_or_spare_thus_terminate, // 11011'100 [] - &&reserved_or_spare_thus_terminate, // 11011'101 [] - &&reserved_or_spare_thus_terminate, // 11011'110 [] - &&reserved_or_spare_thus_terminate, // 11011'111 [231] - &&reserved_or_spare_thus_terminate, // 11011'000 [] - &&reserved_or_spare_thus_terminate, // 11011'001 [] - &&reserved_or_spare_thus_terminate, // 11011'010 [] - &&reserved_or_spare_thus_terminate, // 11011'011 [] - &&reserved_or_spare_thus_terminate, // 11011'100 [] - &&reserved_or_spare_thus_terminate, // 11011'101 [] - &&reserved_or_spare_thus_terminate, // 11011'110 [] - &&reserved_or_spare_thus_terminate, // 11011'111 [] - &&reserved_or_spare_thus_terminate, // 11011'000 [] - &&reserved_or_spare_thus_terminate, // 11011'001 [] - &&reserved_or_spare_thus_terminate, // 11011'010 [] - &&reserved_or_spare_thus_terminate, // 11011'011 [] - &&reserved_or_spare_thus_terminate, // 11011'100 [] - &&reserved_or_spare_thus_terminate, // 11011'101 [] - &&reserved_or_spare_thus_terminate, // 11011'110 [] - &&reserved_or_spare_thus_terminate, // 11011'111 [247] - - &&reserved_or_spare_thus_terminate, // 11011'000 [248] - &&reserved_or_spare_thus_terminate, // 11011'001 [] - &&reserved_or_spare_thus_terminate, // 11011'010 [] - &&reserved_or_spare_thus_terminate, // 11011'011 [] - &&reserved_or_spare_thus_terminate, // 11011'100 [] - &&reserved_or_spare_thus_terminate, // 11011'101 [] - &&reserved_or_spare_thus_terminate, // 11011'110 [] - // TODO(kammce): change this back to `&&reserved_or_spare_thus_terminate` - // Using this last instruction to mean "0xB0" finish. Because the LSDA data - // will typically as the DWARF offset encoding type set to 0xFF OMIT, we can - // utilize this to end the unwinding when the word boundary is hit. - &&finish_unwind, // 11111'111 [255] - }; - - static constexpr std::array big_to_little_endian_sequencer{ - 2, 1, 0, 7, 6, 5, 4, 11 - }; - - constexpr auto personality_type = hal::bit_mask::from<24, 27>(); - constexpr auto generic = hal::bit_mask::from<31>(); - - std::uint8_t const* unwind_instructions = nullptr; - auto const& entry = *p_exception_object.cache.entry_ptr; - if (entry.has_inlined_personality()) { - unwind_instructions = as(&entry.personality_offset); - } else { - auto const* personality = entry.personality(); - if (hal::bit_extract(personality[0])) { - unwind_instructions = as(&personality[0]); - } else { - // If the generic bit is not set, then this is an LSDA. - // - // The first 4-byte word [0] will be the prel31 offset to GCC's - // __gcc_personality_v0 as per the Itanium EH spec. The next word(s) [1] - // are the native unwind instructions. Following the unwind information is - // the LSDA area. - unwind_instructions = as(&personality[1]); - } - } - - auto byte_sequencer = big_to_little_endian_sequencer.begin(); - - if (hal::bit_extract(unwind_instructions[0]) != 0x0) { - byte_sequencer++; - } - - auto& virtual_cpu = p_exception_object.cpu; - bool move_lr_to_pc = true; - std::uint32_t u32_storage = 0; - auto const* sp_ptr = *virtual_cpu.sp; - - while (true) { - auto const instruction = unwind_instructions[*byte_sequencer++]; - auto const next_instruction = unwind_instructions[*byte_sequencer]; - auto const* instruction_handler = jump_table[instruction]; - goto* instruction_handler; - - // +=========================================================================+ - // | Finish! | - // +=========================================================================+ - finish_unwind: - virtual_cpu.sp = sp_ptr; - [[likely]] if (move_lr_to_pc) { - virtual_cpu.pc = virtual_cpu.lr; - } - break; - - reserved_or_spare_thus_terminate: - std::terminate(); - break; - - subtract_vsp_using_uleb128: - static constexpr auto uleb128_offset = 0x204 / sizeof(std::uint32_t); - // TODO(kammce): this is obviously broken. You may need to write this in - // from scratch to manage the fact that the bytes are in big endian sequence - // vs the native little endian. - sp_ptr += read_uleb128(nullptr) + uleb128_offset; - continue; - - pop_integer_registers_under_mask_r3_r2_r1_r0: - // If the next unwind instruction equals 0, or if the bits from 4 or 7 - // contains any 1s, then its time to terminate - if (next_instruction == 0b0000'0000 || (next_instruction & 0xF0) != 0) { - goto reserved_or_spare_thus_terminate; - } - - u32_storage = next_instruction; - - while (u32_storage) { - // The first bit corresponds to the R0 - std::uint32_t lsb_bit_position = std::countr_zero(u32_storage); - // Copy value from the stack, increment stack pointer. - virtual_cpu[lsb_bit_position] = *(sp_ptr++); - // Clear the bit for the lsb_bit_position - u32_storage = u32_storage & ~(1 << lsb_bit_position); - } - byte_sequencer++; - continue; - - refuse_unwind_or_pop: - // If the next unwind instruction equals 0, then its time to terminate - if (next_instruction == 0b0000'0000) { - goto reserved_or_spare_thus_terminate; - } - - // ************************************************************************* - // !!!! WARNING !!!! - // - // `refuse_unwind_or_pop` MUST BE directly above `pop_under_mask` - // - // refuse_unwind_or_pop ---> [[fallthrough]] --> pop_under_mask - // ************************************************************************* - - pop_under_mask: - // Because this unwind instruction is meant to be rare, we will use a while - // loop here rather than unroll this loop. Unless there is some incentive to - // improve the performance for this instruction. - - // Save the lower 4-bits of the previous instruction and the 8-bits of the - // current instruction and combine them. - u32_storage = instruction & 0xF; - u32_storage <<= 8; - u32_storage |= next_instruction; - - if (u32_storage & (1 << 3)) { - move_lr_to_pc = false; - } - - // TODO(kammce): consider (remark b) - // ======================================================================== - // > ‘Pop’ generally denotes removal from the stack commencing at current - // > vsp, with subsequent increment of vsp to beyond the removed quantities. - // > The sole exception to this rule is popping r13, when the writeback of - // > the loaded value to vsp is delayed until after the whole instruction - // > has completed. When multiple registers are popped by a single - // > instruction they are taken as lowest numbered register at lowest stack - // > address. - // ========================================================================= - - while (u32_storage) { - // Get the first 1's distance from the right. We add 12 because the - // mask's first bit represents r4 and increases from there. The first - // byte, the instruction byte, only contains the registers from 12 - // to 15. - std::uint32_t lsb_bit_position = std::countr_zero(u32_storage); - // Clear the bit for the lsb_bit_position - u32_storage = u32_storage & ~(1 << lsb_bit_position); - // Copy value from the stack, increment stack pointer. - virtual_cpu[lsb_bit_position + 4U] = *(sp_ptr++); - } - - byte_sequencer++; - continue; - - // +=========================================================================+ - // | VSP = R[nnnn] | - // +=========================================================================+ - assign_to_vsp_to_reg_nnnn: - // Get the current instruction and get all lower 4-bits - u32_storage = instruction & 0xF; - sp_ptr = *virtual_cpu[u32_storage]; - continue; - - // +=========================================================================+ - // | Sequentially Pop Registers + LR | - // +=========================================================================+ - pop_off_stack_r4_to_r11_and_lr: - sp_ptr = pop_register_range<7, pop_lr::do_it>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r10_and_lr: - sp_ptr = pop_register_range<6, pop_lr::do_it>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r9_and_lr: - sp_ptr = pop_register_range<5, pop_lr::do_it>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r8_and_lr: - sp_ptr = pop_register_range<4, pop_lr::do_it>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r7_and_lr: - sp_ptr = pop_register_range<3, pop_lr::do_it>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r6_and_lr: - sp_ptr = pop_register_range<2, pop_lr::do_it>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r5_and_lr: - sp_ptr = pop_register_range<1, pop_lr::do_it>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r4_and_lr: - sp_ptr = pop_register_range<0, pop_lr::do_it>(sp_ptr, virtual_cpu); - continue; - - // +=========================================================================+ - // | Sequentially Pop Registers | - // +=========================================================================+ - pop_off_stack_r4_to_r11: - sp_ptr = pop_register_range<7>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r10: - sp_ptr = pop_register_range<6>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r9: - sp_ptr = pop_register_range<5>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r8: - sp_ptr = pop_register_range<4>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r7: - sp_ptr = pop_register_range<3>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r6: - sp_ptr = pop_register_range<2>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r5: - sp_ptr = pop_register_range<1>(sp_ptr, virtual_cpu); - continue; - pop_off_stack_r4_to_r4: - sp_ptr = pop_register_range<0>(sp_ptr, virtual_cpu); - continue; - - // +=========================================================================+ - // | Add VSP | - // +=========================================================================+ - vsp_add_0: - sp_ptr = sp_ptr + vsp_deallocate_amount<0>(); - continue; - vsp_add_1: - sp_ptr = sp_ptr + vsp_deallocate_amount<1>(); - continue; - vsp_add_2: - sp_ptr = sp_ptr + vsp_deallocate_amount<2>(); - continue; - vsp_add_3: - sp_ptr = sp_ptr + vsp_deallocate_amount<3>(); - continue; - vsp_add_4: - sp_ptr = sp_ptr + vsp_deallocate_amount<4>(); - continue; - vsp_add_5: - sp_ptr = sp_ptr + vsp_deallocate_amount<5>(); - continue; - vsp_add_6: - sp_ptr = sp_ptr + vsp_deallocate_amount<6>(); - continue; - vsp_add_7: - sp_ptr = sp_ptr + vsp_deallocate_amount<7>(); - continue; - vsp_add_8: - sp_ptr = sp_ptr + vsp_deallocate_amount<8>(); - continue; - vsp_add_9: - sp_ptr = sp_ptr + vsp_deallocate_amount<9>(); - continue; - vsp_add_10: - sp_ptr = sp_ptr + vsp_deallocate_amount<10>(); - continue; - vsp_add_11: - sp_ptr = sp_ptr + vsp_deallocate_amount<11>(); - continue; - vsp_add_12: - sp_ptr = sp_ptr + vsp_deallocate_amount<12>(); - continue; - vsp_add_13: - sp_ptr = sp_ptr + vsp_deallocate_amount<13>(); - continue; - vsp_add_14: - sp_ptr = sp_ptr + vsp_deallocate_amount<14>(); - continue; - vsp_add_15: - sp_ptr = sp_ptr + vsp_deallocate_amount<15>(); - continue; - vsp_add_16: - sp_ptr = sp_ptr + vsp_deallocate_amount<16>(); - continue; - vsp_add_17: - sp_ptr = sp_ptr + vsp_deallocate_amount<17>(); - continue; - vsp_add_18: - sp_ptr = sp_ptr + vsp_deallocate_amount<18>(); - continue; - vsp_add_19: - sp_ptr = sp_ptr + vsp_deallocate_amount<19>(); - continue; - vsp_add_20: - sp_ptr = sp_ptr + vsp_deallocate_amount<20>(); - continue; - vsp_add_21: - sp_ptr = sp_ptr + vsp_deallocate_amount<21>(); - continue; - vsp_add_22: - sp_ptr = sp_ptr + vsp_deallocate_amount<22>(); - continue; - vsp_add_23: - sp_ptr = sp_ptr + vsp_deallocate_amount<23>(); - continue; - vsp_add_24: - sp_ptr = sp_ptr + vsp_deallocate_amount<24>(); - continue; - vsp_add_25: - sp_ptr = sp_ptr + vsp_deallocate_amount<25>(); - continue; - vsp_add_26: - sp_ptr = sp_ptr + vsp_deallocate_amount<26>(); - continue; - vsp_add_27: - sp_ptr = sp_ptr + vsp_deallocate_amount<27>(); - continue; - vsp_add_28: - sp_ptr = sp_ptr + vsp_deallocate_amount<28>(); - continue; - vsp_add_29: - sp_ptr = sp_ptr + vsp_deallocate_amount<29>(); - continue; - vsp_add_30: - sp_ptr = sp_ptr + vsp_deallocate_amount<30>(); - continue; - vsp_add_31: - sp_ptr = sp_ptr + vsp_deallocate_amount<31>(); - continue; - vsp_add_32: - sp_ptr = sp_ptr + vsp_deallocate_amount<32>(); - continue; - vsp_add_33: - sp_ptr = sp_ptr + vsp_deallocate_amount<33>(); - continue; - vsp_add_34: - sp_ptr = sp_ptr + vsp_deallocate_amount<34>(); - continue; - vsp_add_35: - sp_ptr = sp_ptr + vsp_deallocate_amount<35>(); - continue; - vsp_add_36: - sp_ptr = sp_ptr + vsp_deallocate_amount<36>(); - continue; - vsp_add_37: - sp_ptr = sp_ptr + vsp_deallocate_amount<37>(); - continue; - vsp_add_38: - sp_ptr = sp_ptr + vsp_deallocate_amount<38>(); - continue; - vsp_add_39: - sp_ptr = sp_ptr + vsp_deallocate_amount<39>(); - continue; - vsp_add_40: - sp_ptr = sp_ptr + vsp_deallocate_amount<40>(); - continue; - vsp_add_41: - sp_ptr = sp_ptr + vsp_deallocate_amount<41>(); - continue; - vsp_add_42: - sp_ptr = sp_ptr + vsp_deallocate_amount<42>(); - continue; - vsp_add_43: - sp_ptr = sp_ptr + vsp_deallocate_amount<43>(); - continue; - vsp_add_44: - sp_ptr = sp_ptr + vsp_deallocate_amount<44>(); - continue; - vsp_add_45: - sp_ptr = sp_ptr + vsp_deallocate_amount<45>(); - continue; - vsp_add_46: - sp_ptr = sp_ptr + vsp_deallocate_amount<46>(); - continue; - vsp_add_47: - sp_ptr = sp_ptr + vsp_deallocate_amount<47>(); - continue; - vsp_add_48: - sp_ptr = sp_ptr + vsp_deallocate_amount<48>(); - continue; - vsp_add_49: - sp_ptr = sp_ptr + vsp_deallocate_amount<49>(); - continue; - vsp_add_50: - sp_ptr = sp_ptr + vsp_deallocate_amount<50>(); - continue; - vsp_add_51: - sp_ptr = sp_ptr + vsp_deallocate_amount<51>(); - continue; - vsp_add_52: - sp_ptr = sp_ptr + vsp_deallocate_amount<52>(); - continue; - vsp_add_53: - sp_ptr = sp_ptr + vsp_deallocate_amount<53>(); - continue; - vsp_add_54: - sp_ptr = sp_ptr + vsp_deallocate_amount<54>(); - continue; - vsp_add_55: - sp_ptr = sp_ptr + vsp_deallocate_amount<55>(); - continue; - vsp_add_56: - sp_ptr = sp_ptr + vsp_deallocate_amount<56>(); - continue; - vsp_add_57: - sp_ptr = sp_ptr + vsp_deallocate_amount<57>(); - continue; - vsp_add_58: - sp_ptr = sp_ptr + vsp_deallocate_amount<58>(); - continue; - vsp_add_59: - sp_ptr = sp_ptr + vsp_deallocate_amount<59>(); - continue; - vsp_add_60: - sp_ptr = sp_ptr + vsp_deallocate_amount<60>(); - continue; - vsp_add_61: - sp_ptr = sp_ptr + vsp_deallocate_amount<61>(); - continue; - vsp_add_62: - sp_ptr = sp_ptr + vsp_deallocate_amount<62>(); - continue; - vsp_add_63: - sp_ptr = sp_ptr + vsp_deallocate_amount<63>(); - continue; - - // +=========================================================================+ - // | Sub VSP | - // +=========================================================================+ - vsp_sub_0: - sp_ptr = sp_ptr + vsp_deallocate_amount<0>(); - continue; - vsp_sub_1: - sp_ptr = sp_ptr + vsp_deallocate_amount<1>(); - continue; - vsp_sub_2: - sp_ptr = sp_ptr + vsp_deallocate_amount<2>(); - continue; - vsp_sub_3: - sp_ptr = sp_ptr + vsp_deallocate_amount<3>(); - continue; - vsp_sub_4: - sp_ptr = sp_ptr + vsp_deallocate_amount<4>(); - continue; - vsp_sub_5: - sp_ptr = sp_ptr + vsp_deallocate_amount<5>(); - continue; - vsp_sub_6: - sp_ptr = sp_ptr + vsp_deallocate_amount<6>(); - continue; - vsp_sub_7: - sp_ptr = sp_ptr + vsp_deallocate_amount<7>(); - continue; - vsp_sub_8: - sp_ptr = sp_ptr + vsp_deallocate_amount<8>(); - continue; - vsp_sub_9: - sp_ptr = sp_ptr + vsp_deallocate_amount<9>(); - continue; - vsp_sub_10: - sp_ptr = sp_ptr + vsp_deallocate_amount<10>(); - continue; - vsp_sub_11: - sp_ptr = sp_ptr + vsp_deallocate_amount<11>(); - continue; - vsp_sub_12: - sp_ptr = sp_ptr + vsp_deallocate_amount<12>(); - continue; - vsp_sub_13: - sp_ptr = sp_ptr + vsp_deallocate_amount<13>(); - continue; - vsp_sub_14: - sp_ptr = sp_ptr + vsp_deallocate_amount<14>(); - continue; - vsp_sub_15: - sp_ptr = sp_ptr + vsp_deallocate_amount<15>(); - continue; - vsp_sub_16: - sp_ptr = sp_ptr + vsp_deallocate_amount<16>(); - continue; - vsp_sub_17: - sp_ptr = sp_ptr + vsp_deallocate_amount<17>(); - continue; - vsp_sub_18: - sp_ptr = sp_ptr + vsp_deallocate_amount<18>(); - continue; - vsp_sub_19: - sp_ptr = sp_ptr + vsp_deallocate_amount<19>(); - continue; - vsp_sub_20: - sp_ptr = sp_ptr + vsp_deallocate_amount<20>(); - continue; - vsp_sub_21: - sp_ptr = sp_ptr + vsp_deallocate_amount<21>(); - continue; - vsp_sub_22: - sp_ptr = sp_ptr + vsp_deallocate_amount<22>(); - continue; - vsp_sub_23: - sp_ptr = sp_ptr + vsp_deallocate_amount<23>(); - continue; - vsp_sub_24: - sp_ptr = sp_ptr + vsp_deallocate_amount<24>(); - continue; - vsp_sub_25: - sp_ptr = sp_ptr + vsp_deallocate_amount<25>(); - continue; - vsp_sub_26: - sp_ptr = sp_ptr + vsp_deallocate_amount<26>(); - continue; - vsp_sub_27: - sp_ptr = sp_ptr + vsp_deallocate_amount<27>(); - continue; - vsp_sub_28: - sp_ptr = sp_ptr + vsp_deallocate_amount<28>(); - continue; - vsp_sub_29: - sp_ptr = sp_ptr + vsp_deallocate_amount<29>(); - continue; - vsp_sub_30: - sp_ptr = sp_ptr + vsp_deallocate_amount<30>(); - continue; - vsp_sub_31: - sp_ptr = sp_ptr + vsp_deallocate_amount<31>(); - continue; - vsp_sub_32: - sp_ptr = sp_ptr + vsp_deallocate_amount<32>(); - continue; - vsp_sub_33: - sp_ptr = sp_ptr + vsp_deallocate_amount<33>(); - continue; - vsp_sub_34: - sp_ptr = sp_ptr + vsp_deallocate_amount<34>(); - continue; - vsp_sub_35: - sp_ptr = sp_ptr + vsp_deallocate_amount<35>(); - continue; - vsp_sub_36: - sp_ptr = sp_ptr + vsp_deallocate_amount<36>(); - continue; - vsp_sub_37: - sp_ptr = sp_ptr + vsp_deallocate_amount<37>(); - continue; - vsp_sub_38: - sp_ptr = sp_ptr + vsp_deallocate_amount<38>(); - continue; - vsp_sub_39: - sp_ptr = sp_ptr + vsp_deallocate_amount<39>(); - continue; - vsp_sub_40: - sp_ptr = sp_ptr + vsp_deallocate_amount<40>(); - continue; - vsp_sub_41: - sp_ptr = sp_ptr + vsp_deallocate_amount<41>(); - continue; - vsp_sub_42: - sp_ptr = sp_ptr + vsp_deallocate_amount<42>(); - continue; - vsp_sub_43: - sp_ptr = sp_ptr + vsp_deallocate_amount<43>(); - continue; - vsp_sub_44: - sp_ptr = sp_ptr + vsp_deallocate_amount<44>(); - continue; - vsp_sub_45: - sp_ptr = sp_ptr + vsp_deallocate_amount<45>(); - continue; - vsp_sub_46: - sp_ptr = sp_ptr + vsp_deallocate_amount<46>(); - continue; - vsp_sub_47: - sp_ptr = sp_ptr + vsp_deallocate_amount<47>(); - continue; - vsp_sub_48: - sp_ptr = sp_ptr + vsp_deallocate_amount<48>(); - continue; - vsp_sub_49: - sp_ptr = sp_ptr + vsp_deallocate_amount<49>(); - continue; - vsp_sub_50: - sp_ptr = sp_ptr + vsp_deallocate_amount<50>(); - continue; - vsp_sub_51: - sp_ptr = sp_ptr + vsp_deallocate_amount<51>(); - continue; - vsp_sub_52: - sp_ptr = sp_ptr + vsp_deallocate_amount<52>(); - continue; - vsp_sub_53: - sp_ptr = sp_ptr + vsp_deallocate_amount<53>(); - continue; - vsp_sub_54: - sp_ptr = sp_ptr + vsp_deallocate_amount<54>(); - continue; - vsp_sub_55: - sp_ptr = sp_ptr + vsp_deallocate_amount<55>(); - continue; - vsp_sub_56: - sp_ptr = sp_ptr + vsp_deallocate_amount<56>(); - continue; - vsp_sub_57: - sp_ptr = sp_ptr + vsp_deallocate_amount<57>(); - continue; - vsp_sub_58: - sp_ptr = sp_ptr + vsp_deallocate_amount<58>(); - continue; - vsp_sub_59: - sp_ptr = sp_ptr + vsp_deallocate_amount<59>(); - continue; - vsp_sub_60: - sp_ptr = sp_ptr + vsp_deallocate_amount<60>(); - continue; - vsp_sub_61: - sp_ptr = sp_ptr + vsp_deallocate_amount<61>(); - continue; - vsp_sub_62: - sp_ptr = sp_ptr + vsp_deallocate_amount<62>(); - continue; - vsp_sub_63: - sp_ptr = sp_ptr + vsp_deallocate_amount<63>(); - continue; - } } #endif From 1a3c90281c61bec2b5b6c8294468df8728b9af80 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Tue, 23 Jul 2024 13:07:31 -0700 Subject: [PATCH 11/14] :zap: Cache & Use the personality pointer --- demos/applications/multi_levels.cpp | 22 +++++++--------------- notes.md | 2 +- src/arm_cortex/estell/exception.cpp | 12 +++++++++--- src/arm_cortex/estell/internal.hpp | 20 +++++++++++--------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/demos/applications/multi_levels.cpp b/demos/applications/multi_levels.cpp index 37a38e5..f2cf87a 100644 --- a/demos/applications/multi_levels.cpp +++ b/demos/applications/multi_levels.cpp @@ -51,17 +51,14 @@ std::array functions = { &funct_group3_0, &funct_group4_0, &funct_group5_0, &funct_group6_0, &funct_group7_0, &funct_group8_0, #if 0 - funct_group9_0, funct_group10_0, funct_group11_0, - funct_group12_0, funct_group13_0, funct_group14_0, funct_group15_0, - funct_group16_0, - funct_group17_0, funct_group18_0, funct_group19_0, - funct_group20_0, funct_group21_0, funct_group22_0, funct_group23_0, - funct_group24_0 + &funct_group9_0, + &funct_group10_0, &funct_group11_0, &funct_group12_0, &funct_group13_0, + &funct_group14_0, &funct_group15_0, &funct_group16_0, &funct_group17_0, + &funct_group18_0, &funct_group19_0, &funct_group20_0, &funct_group21_0, + &funct_group22_0, &funct_group23_0, &funct_group24_0 #endif }; -std::uint64_t allocation_cycles = 0; - void application(resource_list& p_resources) { resources = &p_resources; @@ -71,17 +68,12 @@ void application(resource_list& p_resources) for (std::size_t i = 0; i < functions.size(); i++) { try { functions.at(i)(); - // NOTE to Khalil before submission. Something is wrong with the unwinder - // and we are jumping to different locations when it completes the first - // time. Local variables are probably being damaged or the stack pointer - // is not in the correct location. } catch ([[maybe_unused]] my_error_t const& p_error) { end_cycles = resources->clock->uptime(); cycle_map[i] = end_cycles - start_cycles; } } -#if 1 for (std::size_t i = 0; i < functions.size(); i++) { bool was_caught = false; try { @@ -96,7 +88,6 @@ void application(resource_list& p_resources) happy_cycle_map[i] = end_cycles - start_cycles; } } -#endif while (true) { continue; @@ -11407,4 +11398,5 @@ int funct_group24_95() return side_effect; } -#endif \ No newline at end of file + +#endif diff --git a/notes.md b/notes.md index 955f09f..5ed7c58 100644 --- a/notes.md +++ b/notes.md @@ -7,4 +7,4 @@ - Reduce the instructions for `restore_cpu_state` - Remove shift variable in `read_uleb128` -- I've turned destructors back on and we are terminating. Looks like the encoding byte has 0x15 which we don't support. 0x5 for the encoding type is not present. So we need to figure out what that is. Its either us reading the wrong data OR a new format we need to handle. \ No newline at end of file +- I've turned destructors back on and we are terminating. Looks like the encoding byte has 0x15 which we don't support. 0x5 for the encoding type is not present. So we need to figure out what that is. Its either us reading the wrong data OR a new format we need to handle. diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index 9768cb4..dc514e9 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -495,7 +495,8 @@ inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) inline void enter_function(exception_object& p_exception_object) { - auto const* lsda_word = p_exception_object.cache.entry_ptr->lsda_data(); + auto const* lsda_word = + index_entry_t::lsda_data(p_exception_object.cache.personality); auto const* lsda_data = reinterpret_cast(lsda_word); #if 0 @@ -630,7 +631,7 @@ inline lsda_header_info parse_header(std::uint8_t const** p_lsda) inline auto const* to_lsda(exception_object& p_exception_object) { return reinterpret_cast( - p_exception_object.cache.entry_ptr->lsda_data()); + index_entry_t::lsda_data(p_exception_object.cache.personality)); } inline auto calculate_relative_pc(exception_object& p_exception_object) @@ -1973,15 +1974,20 @@ void raise_exception(exception_object& p_exception_object) case runtime_state::get_next_frame: { auto const& index_entry = get_index_entry(p_exception_object.cpu.pc); p_exception_object.cache.entry_ptr = &index_entry; + // SU16 data if (index_entry.has_inlined_personality()) { p_exception_object.cache.state(runtime_state::unwind_frame); break; } - auto const* descriptor_start = index_entry.descriptor_start(); + p_exception_object.cache.personality = index_entry.personality(); + auto const* descriptor_start = + index_entry_t::descriptor_start(p_exception_object.cache.personality); + // LU16 data no LSDA if (*descriptor_start == 0x0000'0000) { p_exception_object.cache.state(runtime_state::unwind_frame); break; } + // LSDA p_exception_object.cache.relative_address( (p_exception_object.cpu.pc - index_entry.function())); p_exception_object.cache.state(runtime_state::enter_function); diff --git a/src/arm_cortex/estell/internal.hpp b/src/arm_cortex/estell/internal.hpp index d639151..dc0eed9 100644 --- a/src/arm_cortex/estell/internal.hpp +++ b/src/arm_cortex/estell/internal.hpp @@ -133,7 +133,7 @@ struct function_t bool operator<(function_t const& p_other) const { - return address < p_other.address; + return address < p_other.address; // NOLINT } bool operator==(function_t const& p_other) const @@ -182,11 +182,12 @@ struct index_entry_t return to_absolute_address_ptr(&personality_offset); } - [[gnu::always_inline]] inline std::uint32_t const* lsda_data() const + [[gnu::always_inline]] static inline std::uint32_t const* lsda_data( + std::uint32_t const* p_personality) { constexpr auto personality_type = hal::bit_mask::from<24, 27>(); // +1 to skip the prel31 offset to the personality function - auto const* header = personality() + 1; + auto const* header = p_personality + 1; if (hal::bit_extract(*header) == 0x0) { return header + 1; } @@ -199,22 +200,22 @@ struct index_entry_t return header + 3; } - [[gnu::always_inline]] inline std::uint32_t const* descriptor_start() const + [[gnu::always_inline]] inline static std::uint32_t const* descriptor_start( + std::uint32_t const* p_personality) { constexpr auto type_mask = hal::bit_mask{ .position = 24, .width = 8 }; - auto* personality_address = personality(); - auto type = hal::bit_extract(*personality_address); + auto type = hal::bit_extract(*p_personality); // TODO(kammce): comment why each of these works! if (type == 0x0) { - return personality_address + 1; + return p_personality + 1; } // The limit for ARM exceptions instructions is 7. LD optimizes the ARM // exception spec by removing the "word length" specifier allowing the // instructions to fit in 2 words. - return personality_address + 2; + return p_personality + 2; } [[gnu::always_inline]] function_t function() const @@ -262,8 +263,9 @@ enum class runtime_state : std::uint8_t struct cache_t { - std::uint32_t rel_address; index_entry_t const* entry_ptr = nullptr; + std::uint32_t const* personality = nullptr; + std::uint32_t rel_address; runtime_state inner_state; bool previously_rethrown = false; From 0c6139b0cc9fe66031df7516964644d214769db7 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Tue, 23 Jul 2024 13:22:13 -0700 Subject: [PATCH 12/14] :wastebasket: Remove old unneeded code --- src/arm_cortex/estell/exception.cpp | 357 ++++++---------------------- 1 file changed, 74 insertions(+), 283 deletions(-) diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index dc514e9..fcab6d5 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -320,11 +320,68 @@ constexpr lsda_encoding operator&(lsda_encoding const& p_encoding, static_cast(p_byte)); } +template +[[gnu::always_inline]] inline std::uintptr_t read_encoded_data( + std::uint8_t const** p_data) +{ + std::uint8_t const* ptr = *p_data; + std::uintptr_t result = 0; + + if constexpr (encoding == lsda_encoding::omit) { + return 0; + } + + static constexpr auto encoding_type = encoding & 0x0F; + + if constexpr (encoding_type == lsda_encoding::absptr) { + result = *as(ptr); + ptr += sizeof(uintptr_t); + } + if constexpr (encoding_type == lsda_encoding::uleb128) { + result = read_uleb128(&ptr); + } + if constexpr (encoding_type == lsda_encoding::udata2) { + result = *as(ptr); + ptr += sizeof(uint16_t); + } + if constexpr (encoding_type == lsda_encoding::udata4) { + result = *as(ptr); + ptr += sizeof(uint32_t); + } + if constexpr (encoding_type == lsda_encoding::sdata2) { + result = *as(ptr); + ptr += sizeof(int16_t); + } + if constexpr (encoding_type == lsda_encoding::sdata4) { + result = *as(ptr); + ptr += sizeof(int32_t); + } + if constexpr (encoding_type == lsda_encoding::sdata8) { + result = *as(ptr); + ptr += sizeof(int64_t); + } + if constexpr (encoding_type == lsda_encoding::udata8) { + result = *as(ptr); + ptr += sizeof(uint64_t); + } + if constexpr (encoding_type == lsda_encoding::sleb128) { + result = read_sleb128(&ptr); + } + + // Handle indirection GCC extension + if constexpr (static_cast(encoding & 0x80)) { + result = *reinterpret_cast(result); + } + + *p_data = ptr; + + return result; +} + [[gnu::always_inline]] inline std::uintptr_t read_encoded_data( std::uint8_t const** p_data, lsda_encoding p_encoding) { - std::uint8_t const* ptr = *p_data; std::uintptr_t result = 0; if (p_encoding == lsda_encoding::omit) { @@ -336,131 +393,45 @@ constexpr lsda_encoding operator&(lsda_encoding const& p_encoding, switch (encoding_type) { case lsda_encoding::absptr: - result = *as(ptr); - ptr += sizeof(uintptr_t); + result = read_encoded_data(p_data); break; case lsda_encoding::uleb128: - result = read_uleb128(&ptr); + result = read_encoded_data(p_data); break; case lsda_encoding::udata2: - result = *as(ptr); - ptr += sizeof(uint16_t); + result = read_encoded_data(p_data); break; case lsda_encoding::udata4: - result = *as(ptr); - ptr += sizeof(uint32_t); + result = read_encoded_data(p_data); break; case lsda_encoding::sdata2: - result = *as(ptr); - ptr += sizeof(int16_t); + result = read_encoded_data(p_data); break; case lsda_encoding::sdata4: - result = *as(ptr); - ptr += sizeof(int32_t); + result = read_encoded_data(p_data); break; case lsda_encoding::sdata8: - result = *as(ptr); - ptr += sizeof(int64_t); + result = read_encoded_data(p_data); break; case lsda_encoding::udata8: - result = *as(ptr); - ptr += sizeof(uint64_t); + result = read_encoded_data(p_data); break; case lsda_encoding::sleb128: - default: - std::terminate(); + result = read_encoded_data(p_data); break; - } - - // TODO: convert to hal::bit_extract w/ bit mask - auto const encoding_offset = p_encoding & 0x70; - - switch (encoding_offset) { - case lsda_encoding::pcrel: - case lsda_encoding::absptr: - case lsda_encoding::textrel: - case lsda_encoding::datarel: - case lsda_encoding::funcrel: - case lsda_encoding::aligned: default: + std::terminate(); break; } // Handle indirection GCC extension - // TODO: convert to hal::bit_extract w/ bit mask if (static_cast(p_encoding & 0x80)) { result = *reinterpret_cast(result); } - *p_data = ptr; return result; } -class action_decoder -{ -public: - action_decoder(std::uint8_t const volatile* p_type_table_end, - std::uint8_t const volatile* p_action_table_start, - std::uint32_t p_action) - : m_type_table_end( - reinterpret_cast(p_type_table_end)) - , m_action(p_action_table_start + p_action) - { - } - - static std::type_info const* to_type_info(void const* p_type_info_address) - { - return reinterpret_cast( - to_absolute_address(p_type_info_address)); - } - - static std::type_info const* install_context_type() - { - return reinterpret_cast(0xFFFF'FFFF); - } - - std::type_info const* get_next_catch_type() - { - // TODO(kammce): This isn't how it actually works. This needs to be - // corrected. This kinda works, but the action is biased by 1 and needs to - // be subtracted. I don't understand how I made the old m_action[-1] and - // m_action[0] | 0x80 work. Or why it even works. Seems crazy to me. But it - // do work. I bet it breaks at a specific point. Like if the offset is large - // or the filter number ends up being two bytes. Which would be really rare. - if (m_action == nullptr) { - return nullptr; - } - - m_filter = m_action[-1]; - auto const unsigned_offset = m_action[0] | 0x80; - auto const offset = static_cast(unsigned_offset); - - if (offset == 0) { - m_action = nullptr; - } else { - m_action += (offset + 1); - } - - std::uint32_t const volatile* current_type = &m_type_table_end[-m_filter]; - - if (m_filter == 0 || *current_type == 0x0) { - return install_context_type(); - } - - return to_type_info(const_cast(current_type)); - } - - std::uint8_t filter() - { - return m_filter; - } - -private: - std::uint32_t const volatile* m_type_table_end = nullptr; - std::uint8_t const volatile* m_action = nullptr; - std::uint8_t m_filter = 0; -}; - inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) { // Skip R2 because it is not used in the exception unwinding @@ -493,95 +464,6 @@ inline void restore_cpu_core(ke::cortex_m_cpu& p_cpu_core) "pc"); } -inline void enter_function(exception_object& p_exception_object) -{ - auto const* lsda_word = - index_entry_t::lsda_data(p_exception_object.cache.personality); - auto const* lsda_data = reinterpret_cast(lsda_word); - -#if 0 - // [Omit dwarf]-[uleb128 encoding]-[offset uleb128]-[uleb128 encoding] - static constexpr std::uint32_t small_lsda = 0xFF'01'80'01; - static constexpr std::uint32_t small_lsda_go = 0xFF'01'00'01; - static constexpr std::uint32_t medium_lsda = 0xFF'01'80'80; -#endif - - auto const dwarf_offset_info_format = lsda_encoding{ *(lsda_data++) }; - if (dwarf_offset_info_format != lsda_encoding::omit) { - // Ignore this because we don't need it for unwinding. - [[maybe_unused]] auto const _ = - read_encoded_data(&lsda_data, dwarf_offset_info_format); - } - - auto const type_table_format = lsda_encoding{ *(lsda_data++) }; - std::uint32_t offset_to_end_of_tt_table = 0; - // if type table offset does not exist then there is only cleanup within - // this function. - if (type_table_format != lsda_encoding::omit) { - offset_to_end_of_tt_table = read_uleb128(&lsda_data); - } - auto const* end_of_tt_table = lsda_data + offset_to_end_of_tt_table; - - auto const call_site_format = lsda_encoding{ *(lsda_data++) }; - auto const call_site_length = read_uleb128(&lsda_data); - auto const* call_site_end = lsda_data + call_site_length; - - auto const rel_pc = p_exception_object.cache.relative_address() & ~1; - std::uint32_t landing_pad = 0; - std::uint32_t action = 0; - - // Optimize for the most common use case and encouraged - if (call_site_format == lsda_encoding::uleb128) { - do { - auto start = read_uleb128(&lsda_data); - auto length = read_uleb128(&lsda_data); - landing_pad = read_uleb128(&lsda_data); - action = read_uleb128(&lsda_data); - - if (start <= rel_pc && rel_pc <= start + length) { - if (landing_pad == 0) { - p_exception_object.cache.state(runtime_state::unwind_frame); - return; - } - break; - } - } while (lsda_data < call_site_end); - } else { - do { - auto start = read_encoded_data(&lsda_data, call_site_format); - auto length = read_encoded_data(&lsda_data, call_site_format); - landing_pad = read_encoded_data(&lsda_data, call_site_format); - action = read_uleb128(&lsda_data); - - if (start <= rel_pc && rel_pc <= start + length) { - if (landing_pad == 0) { - p_exception_object.cache.state(runtime_state::unwind_frame); - return; - } - break; - } - } while (lsda_data < call_site_end); - } - - action_decoder a_decoder(end_of_tt_table, call_site_end, action); - - auto& cpu = p_exception_object.cpu; - auto* entry_ptr = p_exception_object.cache.entry_ptr; - for (auto const* type_info = a_decoder.get_next_catch_type(); - type_info != nullptr; - type_info = a_decoder.get_next_catch_type()) { - if (type_info == p_exception_object.type_info || - type_info == action_decoder::install_context_type()) { - cpu[0] = &p_exception_object; - cpu[1] = a_decoder.filter(); - // Set the LSB to 1 for some reason. Cortex-mX is interesting - auto final_destination = (entry_ptr->function() + landing_pad) | 0b1; - cpu.pc = final_destination; - restore_cpu_core(cpu); - } - } -} - inline void skip_dwarf_info(std::uint8_t const** p_lsda) { auto const* lsda = *p_lsda; @@ -639,74 +521,6 @@ inline auto calculate_relative_pc(exception_object& p_exception_object) return p_exception_object.cache.relative_address() & ~1; } -template -[[gnu::always_inline]] inline std::uintptr_t read_encoded_data( - std::uint8_t const** p_data) -{ - std::uint8_t const* ptr = *p_data; - std::uintptr_t result = 0; - - if constexpr (encoding == lsda_encoding::omit) { - return 0; - } - - static constexpr auto encoding_type = encoding & 0x0F; - - if constexpr (encoding_type == lsda_encoding::absptr) { - result = *as(ptr); - ptr += sizeof(uintptr_t); - } - if constexpr (encoding_type == lsda_encoding::uleb128) { - result = read_uleb128(&ptr); - } - if constexpr (encoding_type == lsda_encoding::udata2) { - result = *as(ptr); - ptr += sizeof(uint16_t); - } - if constexpr (encoding_type == lsda_encoding::udata4) { - result = *as(ptr); - ptr += sizeof(uint32_t); - } - if constexpr (encoding_type == lsda_encoding::sdata2) { - result = *as(ptr); - ptr += sizeof(int16_t); - } - if constexpr (encoding_type == lsda_encoding::sdata4) { - result = *as(ptr); - ptr += sizeof(int32_t); - } - if constexpr (encoding_type == lsda_encoding::sdata8) { - result = *as(ptr); - ptr += sizeof(int64_t); - } - if constexpr (encoding_type == lsda_encoding::udata8) { - result = *as(ptr); - ptr += sizeof(uint64_t); - } - if constexpr (encoding_type == lsda_encoding::sleb128) { - } - - // NOTE: we currently ignore bits in the mask 0x70. - - // Handle indirection GCC extension - if constexpr (static_cast(encoding & 0x80)) { - result = *reinterpret_cast(result); - } - - *p_data = ptr; - - return result; -} - -#if 0 -inline void enter_catch_block_or_cleanup(exception_object& p_exception_object, - std::uint8_t const* p_lsda, - std::uint32_t p_relative_pc) -{ - // fill out later -} -#endif - struct call_site_info { std::uint32_t landing_pad = 0; @@ -766,12 +580,12 @@ inline call_site_info parse_uleb128_call_site( return info; } -class action_decoder2 +class action_decoder { public: - action_decoder2(std::uint8_t const* p_type_table_end, - std::uint8_t const* p_end_of_callsite, - std::uint32_t p_action) + action_decoder(std::uint8_t const* p_type_table_end, + std::uint8_t const* p_end_of_callsite, + std::uint32_t p_action) : m_type_table_end(p_type_table_end) , m_action_position(p_end_of_callsite + (p_action - 1)) { @@ -920,7 +734,7 @@ inline void enter_function2(exception_object& p_exception_object) restore_cpu_core(cpu); } - action_decoder2 a_decoder( + action_decoder a_decoder( info.type_table_end, info.call_site_end, site_info.action); for (auto const* type_info = a_decoder.get_next_catch_type(); @@ -928,7 +742,7 @@ inline void enter_function2(exception_object& p_exception_object) type_info = a_decoder.get_next_catch_type()) { if (type_info != p_exception_object.type_info && - type_info != action_decoder2::install_context_type()) { + type_info != action_decoder::install_context_type()) { continue; } @@ -946,29 +760,6 @@ inline void enter_function2(exception_object& p_exception_object) // Install CPU state restore_cpu_core(cpu); } - -#if 0 - for (auto const* type_info : a_decoder) { - if (type_info != p_exception_object.type_info && - type_info != action_decoder2::install_context_type()) { - continue; - } - - // ====== Prepare to Install context!! ===== - cpu[0] = &p_exception_object; - cpu[1] = a_decoder.filter(); - - // LSB must be set to 1 to jump to an address - auto const final_destination = - (entry_ptr->function() + site_info.landing_pad) | 0b1; - - // Set PC to the cleanup destination - cpu.pc = final_destination; - - // Install CPU state - restore_cpu_core(cpu); - } -#endif } template From bef18a5118796834437d775c5642515744986574 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Tue, 23 Jul 2024 13:31:35 -0700 Subject: [PATCH 13/14] :zap: Remove usage of personality in create_instructions_from_entry --- src/arm_cortex/estell/exception.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index fcab6d5..87e8049 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -606,7 +606,7 @@ class action_decoder { auto const* type_table = as(m_type_table_end); - // We assume absptr here because its easier + // We assume prel here because all other options are deprecated // TODO(#___): Consider using the type table encoding format for decoding // the type table info rather than assuming that the values here are // prel31_offsets @@ -658,7 +658,7 @@ class action_decoder std::int32_t m_filter = 0; }; -inline void enter_function2(exception_object& p_exception_object) +inline void enter_function(exception_object& p_exception_object) { auto const* lsda = to_lsda(p_exception_object); auto info = parse_header(&lsda); @@ -1685,7 +1685,7 @@ void unwind_frame(instructions_t const& p_instructions, [[gnu::always_inline]] inline instructions_t create_instructions_from_entry( - index_entry_t const& p_entry) + exception_object const& p_exception_object) { constexpr auto personality_type = hal::bit_mask::from<24, 27>(); constexpr auto generic = hal::bit_mask::from<31>(); @@ -1693,11 +1693,11 @@ inline instructions_t create_instructions_from_entry( instructions_t unwind{}; std::uint32_t const* handler_data = nullptr; - - if (p_entry.has_inlined_personality()) { - handler_data = &p_entry.personality_offset; + auto const& entry = *p_exception_object.cache.entry_ptr; + if (entry.has_inlined_personality()) { + handler_data = &entry.personality_offset; } else { - auto const* personality = p_entry.personality(); + auto const* personality = p_exception_object.cache.personality; if (hal::bit_extract(personality[0])) { handler_data = &personality[0]; } else { @@ -1785,14 +1785,14 @@ void raise_exception(exception_object& p_exception_object) [[fallthrough]]; } case runtime_state::enter_function: { - enter_function2(p_exception_object); + enter_function(p_exception_object); // enter function returns normally if it determines that there was no // reason to enter the function, thus the function should be unwound. [[fallthrough]]; } case runtime_state::unwind_frame: { - auto const& entry = *p_exception_object.cache.entry_ptr; - auto const instructions = create_instructions_from_entry(entry); + auto const instructions = + create_instructions_from_entry(p_exception_object); unwind_frame(instructions, p_exception_object); p_exception_object.cache.state(runtime_state::get_next_frame); } From 33d0f9e1630fd05723292b4985cc1684e2fbd5f4 Mon Sep 17 00:00:00 2001 From: Khalil Estell Date: Wed, 24 Jul 2024 07:31:42 -0700 Subject: [PATCH 14/14] :memo: Add todo w/ github issues everywhere in the code - Remove a few `#if 0` code - Slightly fix up issues with CI --- src/arm_cortex/estell/exception.cpp | 112 +++++++++++++++++----------- src/arm_cortex/estell/internal.hpp | 56 +++++++------- src/control.cpp | 2 +- 3 files changed, 96 insertions(+), 74 deletions(-) diff --git a/src/arm_cortex/estell/exception.cpp b/src/arm_cortex/estell/exception.cpp index 87e8049..3c95c33 100644 --- a/src/arm_cortex/estell/exception.cpp +++ b/src/arm_cortex/estell/exception.cpp @@ -45,7 +45,10 @@ union instructions_t }; namespace { +// TODO(#19): Make this thread local and figure out how to support is using +// emutls. exception_ptr active_exception = nullptr; +// TODO(#42): Use the applications's polymorphic allocator, not our own space. std::array exception_buffer{}; } // namespace @@ -388,7 +391,6 @@ template return 0; } - // TODO: convert to hal::bit_extract w/ bit mask auto const encoding_type = p_encoding & 0x0F; switch (encoding_type) { @@ -607,7 +609,7 @@ class action_decoder auto const* type_table = as(m_type_table_end); // We assume prel here because all other options are deprecated - // TODO(#___): Consider using the type table encoding format for decoding + // TODO(#39): Consider using the type table encoding format for decoding // the type table info rather than assuming that the values here are // prel31_offsets auto const* current_type = &type_table[-m_filter]; @@ -720,8 +722,8 @@ inline void enter_function(exception_object& p_exception_object) auto* entry_ptr = p_exception_object.cache.entry_ptr; // This occurs when a frame has destructors that need cleaning up but no - // try/catch blocks. In such a case, if we found a scope we need to enter, we - // should enter it immediately! + // try/catch blocks resulting in there being no action table or type table. In + // such a case, then the scope found should be entered immediately! if (info.type_table_end < info.call_site_end) { // LSB must be set to 1 to jump to an address auto const final_destination = @@ -741,6 +743,7 @@ inline void enter_function(exception_object& p_exception_object) type_info != nullptr; type_info = a_decoder.get_next_catch_type()) { + // TODO(#6): Replace with dynamic cast if (type_info != p_exception_object.type_info && type_info != action_decoder::install_context_type()) { continue; @@ -778,12 +781,12 @@ template [[nodiscard("You MUST set the unwind function's stack pointer to this " "value after executing it!")]] inline std::uint32_t const* pop_register_range(std::uint32_t const* sp_ptr, - cortex_m_cpu& p_virtual_cpu) + cortex_m_cpu& p_cpu) { // We pull these pointers out in order to access them incrementally, which // will give the hint to the compiler to convert them into a sequence of // immediate load and stores. - auto* r4_pointer = &p_virtual_cpu.r4.data; + auto* r4_pointer = &p_cpu.r4.data; static_assert(PopCount <= 7, "Pop Count cannot be above 7"); @@ -798,15 +801,13 @@ inline std::uint32_t const* pop_register_range(std::uint32_t const* sp_ptr, } if constexpr (PopLinkRegister == pop_lr::do_it) { - p_virtual_cpu.lr = sp_ptr[PopCount + 1]; + p_cpu.lr = sp_ptr[PopCount + 1]; } return sp_ptr + PopCount + 1 + unsigned{ PopLinkRegister == pop_lr::do_it }; } -#if 1 -void unwind_frame(instructions_t const& p_instructions, - exception_object& p_exception_object) +void unwind_frame(instructions_t const& p_instructions, cortex_m_cpu& p_cpu) { static constexpr std::array jump_table{ &&vsp_add_0, // [0] @@ -960,7 +961,13 @@ void unwind_frame(instructions_t const& p_instructions, &&pop_under_mask, // [0b1000'1111 = 143] (128 + 15) // 1001nnnn - // TODO: Split up assignments to make them faster + // NOTE: Consider split up assignments to make them faster. We can remove + // the need to actually compute the register and then assign it to vsp when + // the register number is encoded in the instruction. This would add more + // space cost though. It is an option. But this particular instruction + // should be very rare and typically never used in almost any code so making + // this faster is not a priority. Only do this if there is a client need for + // such a feature. &&assign_to_vsp_to_reg_nnnn, // [0b1001'0000 = 144] &&assign_to_vsp_to_reg_nnnn, // [0b1001'0001 = 145] &&assign_to_vsp_to_reg_nnnn, // [0b1001'0010 = 146] @@ -1009,13 +1016,16 @@ void unwind_frame(instructions_t const& p_instructions, // Subtract VSP using uleb128 &&subtract_vsp_using_uleb128, // 10110010 [178] - // Pop VFP double-precision registers (not supported currently) + // Pop VFP double-precision registers + // TODO(#27): Add support for this &&reserved_or_spare_thus_terminate, // 10110011 [179] // Pop Return Address Authentication Code pseudo-register + // TODO(#28): Add support for this &&reserved_or_spare_thus_terminate, // 10110100 [180] // Use current vsp as modifier in Return Address Authentication + // TODO(#29): Add support for this &&reserved_or_spare_thus_terminate, // 10110101 [181] // Spare (was Pop FPA) 1011011n @@ -1023,6 +1033,7 @@ void unwind_frame(instructions_t const& p_instructions, &&reserved_or_spare_thus_terminate, // 10110111 [183] // Pop VFP double-precision registers D[8]-D[8+nnn] saved 10111nnn + // TODO(#30): Add support for this &&reserved_or_spare_thus_terminate, // 10111'000 [184] &&reserved_or_spare_thus_terminate, // 10111'001 [185] &&reserved_or_spare_thus_terminate, // 10111'010 [186] @@ -1033,6 +1044,10 @@ void unwind_frame(instructions_t const& p_instructions, &&reserved_or_spare_thus_terminate, // 10111'111 [191] // Intel Wireless MMX pop wR[10]-wR[10+nnn] 11000nnn + // NOTE: We will probably never support these. No modern ARM device is still + // using the Intel MMX registers. We will only consider adding support for + // this if a user/client/developer specifically requests it and has a dire + // need for it. &&reserved_or_spare_thus_terminate, // 11000'000 [192] &&reserved_or_spare_thus_terminate, // 11000'001 [193] &&reserved_or_spare_thus_terminate, // 11000'010 [194] @@ -1041,6 +1056,7 @@ void unwind_frame(instructions_t const& p_instructions, &&reserved_or_spare_thus_terminate, // 11000'101 [197] // Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] + // See NOTE in above section... &&reserved_or_spare_thus_terminate, // 11000'110 [198] // Spare (11000111) @@ -1048,10 +1064,12 @@ void unwind_frame(instructions_t const& p_instructions, // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by // VPUSH (11001000) + // TODO(#31): Add support for this &&reserved_or_spare_thus_terminate, // 11001000 [200] // Pop VFP double precision registers D[ssss]-D[ssss+cccc] saved (as if) by // VPUSH (11001001) + // TODO(#32): Add support for this &&reserved_or_spare_thus_terminate, // 11001001 [201] // Spare (yyy != 000, 001) 11001yyy @@ -1063,6 +1081,7 @@ void unwind_frame(instructions_t const& p_instructions, &&reserved_or_spare_thus_terminate, // 11001'111 [207] // Pop VFP double-precision registers D[8]-D[8+nnn] saved by VPUSH 11010nnn + // TODO(#33): Add support for this &&reserved_or_spare_thus_terminate, // 11010'000 [208] &&reserved_or_spare_thus_terminate, // 11010'001 [209] &&reserved_or_spare_thus_terminate, // 11010'010 [210] @@ -1115,14 +1134,12 @@ void unwind_frame(instructions_t const& p_instructions, &&reserved_or_spare_thus_terminate, // 11011'101 [] &&reserved_or_spare_thus_terminate, // 11011'110 [] &&reserved_or_spare_thus_terminate, // 11111'111 [255] - }; - auto& virtual_cpu = p_exception_object.cpu; bool move_lr_to_pc = true; std::uint32_t u32_storage = 0; auto const* instruction_ptr = p_instructions.data.data(); - auto const* sp_ptr = *virtual_cpu.sp; + auto const* sp_ptr = *p_cpu.sp; while (true) { auto const* instruction_handler = jump_table[*instruction_ptr]; @@ -1133,9 +1150,9 @@ void unwind_frame(instructions_t const& p_instructions, // | Finish! | // +=========================================================================+ finish_unwind: - virtual_cpu.sp = sp_ptr; + p_cpu.sp = sp_ptr; [[likely]] if (move_lr_to_pc) { - virtual_cpu.pc = virtual_cpu.lr; + p_cpu.pc = p_cpu.lr; } break; @@ -1161,7 +1178,7 @@ void unwind_frame(instructions_t const& p_instructions, // The first bit corresponds to the R0 std::uint32_t lsb_bit_position = std::countr_zero(u32_storage); // Copy value from the stack, increment stack pointer. - virtual_cpu[lsb_bit_position] = *(sp_ptr++); + p_cpu[lsb_bit_position] = *(sp_ptr++); // Clear the bit for the lsb_bit_position u32_storage = u32_storage & ~(1 << lsb_bit_position); } @@ -1197,7 +1214,7 @@ void unwind_frame(instructions_t const& p_instructions, move_lr_to_pc = false; } - // TODO(kammce): consider (remark b) + // TODO(#40): consider (remark b) // ======================================================================== // > ‘Pop’ generally denotes removal from the stack commencing at current // > vsp, with subsequent increment of vsp to beyond the removed quantities. @@ -1217,7 +1234,7 @@ void unwind_frame(instructions_t const& p_instructions, // Clear the bit for the lsb_bit_position u32_storage = u32_storage & ~(1 << lsb_bit_position); // Copy value from the stack, increment stack pointer. - virtual_cpu[lsb_bit_position + 4U] = *(sp_ptr++); + p_cpu[lsb_bit_position + 4U] = *(sp_ptr++); } instruction_ptr++; @@ -1229,63 +1246,63 @@ void unwind_frame(instructions_t const& p_instructions, assign_to_vsp_to_reg_nnnn: // Get the current instruction and get all lower 4-bits u32_storage = *(instruction_ptr - 1U) & 0xF; - sp_ptr = *virtual_cpu[u32_storage]; + sp_ptr = *p_cpu[u32_storage]; continue; // +=========================================================================+ // | Sequentially Pop Registers + LR | // +=========================================================================+ pop_off_stack_r4_to_r11_and_lr: - sp_ptr = pop_register_range<7, pop_lr::do_it>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<7, pop_lr::do_it>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r10_and_lr: - sp_ptr = pop_register_range<6, pop_lr::do_it>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<6, pop_lr::do_it>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r9_and_lr: - sp_ptr = pop_register_range<5, pop_lr::do_it>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<5, pop_lr::do_it>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r8_and_lr: - sp_ptr = pop_register_range<4, pop_lr::do_it>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<4, pop_lr::do_it>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r7_and_lr: - sp_ptr = pop_register_range<3, pop_lr::do_it>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<3, pop_lr::do_it>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r6_and_lr: - sp_ptr = pop_register_range<2, pop_lr::do_it>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<2, pop_lr::do_it>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r5_and_lr: - sp_ptr = pop_register_range<1, pop_lr::do_it>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<1, pop_lr::do_it>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r4_and_lr: - sp_ptr = pop_register_range<0, pop_lr::do_it>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<0, pop_lr::do_it>(sp_ptr, p_cpu); continue; // +=========================================================================+ // | Sequentially Pop Registers | // +=========================================================================+ pop_off_stack_r4_to_r11: - sp_ptr = pop_register_range<7>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<7>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r10: - sp_ptr = pop_register_range<6>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<6>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r9: - sp_ptr = pop_register_range<5>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<5>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r8: - sp_ptr = pop_register_range<4>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<4>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r7: - sp_ptr = pop_register_range<3>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<3>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r6: - sp_ptr = pop_register_range<2>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<2>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r5: - sp_ptr = pop_register_range<1>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<1>(sp_ptr, p_cpu); continue; pop_off_stack_r4_to_r4: - sp_ptr = pop_register_range<0>(sp_ptr, virtual_cpu); + sp_ptr = pop_register_range<0>(sp_ptr, p_cpu); continue; // +=========================================================================+ @@ -1681,7 +1698,6 @@ void unwind_frame(instructions_t const& p_instructions, continue; } } -#endif [[gnu::always_inline]] inline instructions_t create_instructions_from_entry( @@ -1773,12 +1789,13 @@ void raise_exception(exception_object& p_exception_object) p_exception_object.cache.personality = index_entry.personality(); auto const* descriptor_start = index_entry_t::descriptor_start(p_exception_object.cache.personality); - // LU16 data no LSDA + // The descriptor start value can only be 0x0 if there is LU16 data and + // no LSDA. In such cases, simply unwind the frame. if (*descriptor_start == 0x0000'0000) { p_exception_object.cache.state(runtime_state::unwind_frame); break; } - // LSDA + // LSDA is present! p_exception_object.cache.relative_address( (p_exception_object.cpu.pc - index_entry.function())); p_exception_object.cache.state(runtime_state::enter_function); @@ -1793,7 +1810,7 @@ void raise_exception(exception_object& p_exception_object) case runtime_state::unwind_frame: { auto const instructions = create_instructions_from_entry(p_exception_object); - unwind_frame(instructions, p_exception_object); + unwind_frame(instructions, p_exception_object.cpu); p_exception_object.cache.state(runtime_state::get_next_frame); } } @@ -1803,12 +1820,11 @@ void raise_exception(exception_object& p_exception_object) extern "C" { - void _exit([[maybe_unused]] int rc) // NOLINT { std::terminate(); } - + // TODO(#42): Use the applications's polymorphic allocator, not our own space. void* __wrap___cxa_allocate_exception(size_t p_thrown_size) { if (p_thrown_size > @@ -1862,8 +1878,10 @@ extern "C" exception_object.cache.state(ke::runtime_state::get_next_frame); exception_object.cache.rethrown(true); - // Perform an inline trivial unwind __cxa_throw: + // TODO(35): Replace this with an immediate call to unwind_frame(). What we + // have below is fragile and can break very easily. #if defined(OPTIMIZATION_LEVEL) + // Perform an inline trivial unwind __cxa_throw: #if OPTIMIZATION_LEVEL == Debug std::uint32_t const* stack_pointer = *exception_object.cpu.sp; exception_object.cpu.r3 = stack_pointer[0]; @@ -1886,6 +1904,8 @@ extern "C" // Raise exception returns when an error or call to terminate has been found ke::raise_exception(exception_object); + // TODO(#38): this area is considered a catch block, meaning that the + // exception is handled at this point. We should mark it as such. std::terminate(); } @@ -1899,8 +1919,10 @@ extern "C" exception_object.destructor = p_destructor; ke::capture_cpu_core(exception_object.cpu); - // Perform an inline trivial unwind __cxa_throw: + // TODO(35): Replace this with an immediate call to unwind_frame(). What we + // have below is fragile and can break very easily. #if defined(OPTIMIZATION_LEVEL) + // Perform an inline trivial unwind __cxa_throw: #if OPTIMIZATION_LEVEL == Debug std::uint32_t const* stack_pointer = *exception_object.cpu.sp; exception_object.cpu.r3 = stack_pointer[0]; diff --git a/src/arm_cortex/estell/internal.hpp b/src/arm_cortex/estell/internal.hpp index dc0eed9..8f9ce1f 100644 --- a/src/arm_cortex/estell/internal.hpp +++ b/src/arm_cortex/estell/internal.hpp @@ -66,23 +66,6 @@ constexpr std::uint32_t su16_mask = 0b1111'1111'1111'1110; inline std::uint32_t to_absolute_address(void const* p_object) { -#if 0 - constexpr auto signed_bit_31 = hal::bit_mask::from<30>(); - constexpr auto signed_bit_32 = hal::bit_mask::from<31>(); - auto object_address = std::bit_cast(p_object); - auto offset = *std::bit_cast(p_object); - - // Sign extend the offset to 32-bits - if (hal::bit_extract(offset)) { - hal::bit_modify(offset).set(); - } else { - hal::bit_modify(offset).clear(); - } - - auto signed_offset = static_cast(offset); - std::int32_t final_address = object_address + signed_offset; - return static_cast(final_address); -#else auto const object_address = std::bit_cast(p_object); auto offset = *std::bit_cast(p_object); @@ -93,8 +76,6 @@ inline std::uint32_t to_absolute_address(void const* p_object) auto const final_address = object_address + offset; return static_cast(final_address); - -#endif } [[gnu::used]] inline std::uint32_t runtime_to_absolute_address( @@ -200,15 +181,25 @@ struct index_entry_t return header + 3; } + /** + * @brief Returns the pointer to the personality's descriptor data + * + * Descriptor data is data that comes after the unwind instructions. + * + * @param p_personality - pointer to the function's personality data within + * the exception table. + * @return std::uint32_t const* - pointer to the descriptor start area. Always + * valid so long as p_personality is valid. + */ [[gnu::always_inline]] inline static std::uint32_t const* descriptor_start( std::uint32_t const* p_personality) { - constexpr auto type_mask = hal::bit_mask{ .position = 24, .width = 8 }; - - auto type = hal::bit_extract(*p_personality); + constexpr hal::bit_mask personality_type_mask{ .position = 24, .width = 4 }; + auto const type = hal::bit_extract(*p_personality); - // TODO(kammce): comment why each of these works! - if (type == 0x0) { + // If the personality type is 0 (SU16), then the descriptor start is right + // after the first word. + if (type == 0) { return p_personality + 1; } @@ -226,10 +217,18 @@ struct index_entry_t struct cortex_m_cpu { - register_t r0; // Remove? - register_t r1; // Remove? - register_t r2; // Remove? - register_t r3; // Remove? + // NOTE: We could consider removing r0 to r3. Technically, these are not + // callee preserved. We also destroy the state of R0 and R1 when we drop into + // a function to either run destructors or to execute a catch block. + // + // The only real issue issue is vsp = r[nnnn] where `nnnn` can be 0 + // to 3. Pop r0 to r3 could be instructions we ignore by moving the stack + // pointer but ignoring the results. For now, we will support all operations + // on these registers until we know we can safely remove them. + register_t r0; + register_t r1; + register_t r2; + register_t r3; register_t r4; register_t r5; register_t r6; @@ -259,6 +258,7 @@ enum class runtime_state : std::uint8_t get_next_frame = 0, enter_function = 1, unwind_frame = 2, + // TODO(#37): Add handled state }; struct cache_t diff --git a/src/control.cpp b/src/control.cpp index b290d83..4b90b76 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -56,7 +56,7 @@ class single_exception_allocator : public std::pmr::memory_resource { public: single_exception_allocator() = default; - ~single_exception_allocator() override = default; + ~single_exception_allocator() = default; private: void* do_allocate(std::size_t p_size,