From a36705a93155fcad3b5064fd242444228e8fb0b1 Mon Sep 17 00:00:00 2001 From: Kittycannon Date: Sat, 13 Jun 2026 11:31:07 -0600 Subject: [PATCH] removed unnecessary things, updated and audited the code --- autogen/InstructionMasks.hpp | 8 + calling-convention.ipynb | 658 --------------------- docs/Spider Instructions.xlsx | Bin 106726 -> 113130 bytes pygen.ipynb | 32 +- src/spider/SpiderRuntime.cpp | 12 +- src/spider/runtime/cpu/CPU.cpp | 32 +- src/spider/runtime/cpu/CPU.hpp | 99 ++-- src/spider/runtime/debug/LiveDebug.cpp | 402 ------------- src/spider/runtime/debug/LiveDebug.hpp | 7 - src/spider/runtime/instr/InstrMap.cpp | 306 +++++----- src/spider/runtime/instr/Instr_000-01F.cpp | 512 ++++++++-------- src/spider/runtime/instr/Instr_LLGS.cpp | 61 -- src/spider/test_instrucciones.cpp | 118 ---- 13 files changed, 529 insertions(+), 1718 deletions(-) delete mode 100644 calling-convention.ipynb delete mode 100644 src/spider/runtime/debug/LiveDebug.cpp delete mode 100644 src/spider/runtime/debug/LiveDebug.hpp delete mode 100644 src/spider/runtime/instr/Instr_LLGS.cpp delete mode 100644 src/spider/test_instrucciones.cpp diff --git a/autogen/InstructionMasks.hpp b/autogen/InstructionMasks.hpp index 34a0909..54ad74a 100644 --- a/autogen/InstructionMasks.hpp +++ b/autogen/InstructionMasks.hpp @@ -58,6 +58,10 @@ constexpr u8 ADDR_MODE_MASKS[][2] = { { 0x1E, 0xFF }, // GE { 0x1E, 0xFF }, // LT { 0x1E, 0xFF }, // LE + { 0x1E, 0xFF }, // GTU + { 0x1E, 0xFF }, // GEU + { 0x1E, 0xFF }, // LTU + { 0x1E, 0xFF }, // LEU { 0xFF, 0x00 }, // JMP { 0xFF, 0x00 }, // JEQ { 0xFF, 0x00 }, // JNE @@ -190,6 +194,10 @@ constexpr u8 TYPE_SIZE_MASKS[] = { 0x0F, // GE 0x0F, // LT 0x0F, // LE + 0x0F, // GTU + 0x0F, // GEU + 0x0F, // LTU + 0x0F, // LEU 0x0F, // JMP 0x0F, // JEQ 0x0F, // JNE diff --git a/calling-convention.ipynb b/calling-convention.ipynb deleted file mode 100644 index c71af20..0000000 --- a/calling-convention.ipynb +++ /dev/null @@ -1,658 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "1c7a11d9", - "metadata": {}, - "source": [ - "This test will test (lol) the calling convention in Spider.\n", - "As defined, it will use the CPU as a python object.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "b9c572cd", - "metadata": {}, - "outputs": [], - "source": [ - "# The state of the \"my-language-name\" vm in a simple\n", - "# python object abstraction\n", - "my_language_name_vm = {\n", - " 'regs':{\n", - " 'RA':0,\n", - " 'RB':0,\n", - " 'RC':0,\n", - " 'RD':0,\n", - " 'RX':0,\n", - " 'RY':0,\n", - " 'R0':0,\n", - " 'R1':0,\n", - " 'R2':0,\n", - " 'R3':0,\n", - " 'R4':0,\n", - " 'R5':0,\n", - " 'R6':0,\n", - " 'R7':0,\n", - " 'R8':0,\n", - " 'R9':0,\n", - " 'RF':0,\n", - " 'RI':0,\n", - " 'RS':0,\n", - " 'RZ':0,\n", - " 'RE':0,\n", - " 'RH':0,\n", - " 'RV':0,\n", - " 'RM':0,\n", - " },\n", - " 'stack': [],\n", - "}" - ] - }, - { - "cell_type": "markdown", - "id": "3e3989dc", - "metadata": {}, - "source": [ - "**Test Data Definition**\n", - "\n", - "This block defines the parameters we want to pass into our hypothetical function and what we expect it to return. We use a mix of large data structures (sizes in bytes) and booleans (size 1) to force the VM to use all of its memory allocation rules." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "a1ddd324", - "metadata": {}, - "outputs": [], - "source": [ - "# Input parameters, measured in bytes (booleans are size 1 for logic triggers)\n", - "input_params = [\n", - " {'name': 'int_a', 'size': 4}, # Should go to RA\n", - " {'name': 'bool_1', 'size': 1}, # Should be queued\n", - " {'name': 'bool_2', 'size': 1}, # Should be queued\n", - " {'name': 'double_b', 'size': 8}, # Should go to RB\n", - " {'name': 'big_struct', 'size': 32} # Too large for registers, forces stack usage\n", - "]\n", - "\n", - "# Define the return types here\n", - "output_return = [ \n", - " {'name': 'ret1', 'size': 8} \n", - "]" - ] - }, - { - "cell_type": "markdown", - "id": "bbe2c356", - "metadata": {}, - "source": [ - "Now, on this function it will perform the tasks of ordering the registers and stack based on the parameters.\n", - "\n", - "**The Function Call ABI**\n", - "This is the core logic. It prepares the VM for a jump to another function by safely backing up the current context and routing the parameters to either the registers or the stack according to the strict hardware rules.\n", - "\n", - "**Step 1**: It pushes the caller-saved registers (R0-R3) to the stack so they aren't lost.\n", - "\n", - "**Step 2**: It checks if the function will return a massive object (> 16 bytes). If so, it reserves a pointer space.\n", - "\n", - "**Step 3**: It attempts to put parameters into RA, RB, RC, RD, R8, R9. Booleans are packed together to save space.\n", - "\n", - "**Step 4**: Anything that overflows the registers is pushed to the stack." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "02a2ad1a", - "metadata": {}, - "outputs": [], - "source": [ - "def do_function_call(input_params: list, output_return: list):\n", - " global my_language_name_vm\n", - " \n", - " print(\"--- 1. Saving Caller State ---\")\n", - " # Paso 1: Respaldar registros salvados por el llamador (R0-R3) \n", - " caller_saved = ['R0', 'R1', 'R2', 'R3']\n", - " for reg in caller_saved:\n", - " my_language_name_vm['stack'].append(my_language_name_vm['regs'][reg])\n", - " \n", - " print(\"--- 2. Allocating Parameters ---\")\n", - " \n", - " # Regla: Si el retorno > 16 bytes, se agrega un puntero al INICIO de los parámetros \n", - " actual_params = input_params.copy()\n", - " ret_size = sum(r['size'] for r in output_return)\n", - " if ret_size > 16:\n", - " # Se inserta al frente para que ocupe RA (o el primer espacio disponible) \n", - " actual_params.insert(0, {'name': 'RET_PTR_ALLOCATION', 'size': 8}) \n", - "\n", - " param_regs = ['RA', 'RB', 'RC', 'RD', 'R8', 'R9'] # \n", - " reg_idx = 0\n", - " bool_queue = []\n", - " stack_params = []\n", - " \n", - " # --- FASE 1: ASIGNACIÓN A REGISTROS ---\n", - " for param in actual_params:\n", - " if reg_idx < len(param_regs):\n", - " if param['size'] == 1: # Es Booleano \n", - " bool_queue.append(param['name'])\n", - " if len(bool_queue) == 8: # Cola llena (8 bytes/bits según lógica de la VM) \n", - " my_language_name_vm['regs'][param_regs[reg_idx]] = f\"Packed_Bools({','.join(bool_queue)})\"\n", - " reg_idx += 1\n", - " bool_queue = []\n", - " elif param['size'] <= 8: # Parámetro estándar\n", - " # Antes de asignar un no-booleano, si hay booleanos pendientes, se deben flashear \n", - " if bool_queue:\n", - " my_language_name_vm['regs'][param_regs[reg_idx]] = f\"Padded_Bools({len(bool_queue)})\"\n", - " reg_idx += 1\n", - " bool_queue = []\n", - " \n", - " if reg_idx < len(param_regs):\n", - " my_language_name_vm['regs'][param_regs[reg_idx]] = param['name']\n", - " reg_idx += 1\n", - " else:\n", - " stack_params.append(param)\n", - " else:\n", - " # Si es muy grande para un registro (>8), va a la pila después \n", - " stack_params.append(param)\n", - " else:\n", - " stack_params.append(param)\n", - "\n", - " # Flashear booleanos restantes si queda espacio en registros \n", - " if bool_queue and reg_idx < len(param_regs):\n", - " my_language_name_vm['regs'][param_regs[reg_idx]] = f\"Padded_Bools({len(bool_queue)})\"\n", - " reg_idx += 1\n", - " bool_queue = []\n", - " elif bool_queue:\n", - " # Si no hubo registros, los booleanos pendientes pasan a la lógica de pila\n", - " stack_params = [{'name': b, 'size': 1} for b in bool_queue] + stack_params\n", - " bool_queue = []\n", - "\n", - " # Regla VI: Si sobran registros, guardar SP y respaldar en stack \n", - " while reg_idx < len(param_regs):\n", - " my_language_name_vm['regs'][param_regs[reg_idx]] = \"SP_Backup\"\n", - " my_language_name_vm['stack'].append(f\"SP_for_{param_regs[reg_idx]}\")\n", - " reg_idx += 1\n", - "\n", - " # --- FASE 2: ASIGNACIÓN A PILA ---\n", - " # 1. Parámetros <= 8 bytes (no booleanos)\n", - " remaining_large = []\n", - " for param in stack_params:\n", - " if param['size'] == 1:\n", - " bool_queue.append(param['name'])\n", - " if len(bool_queue) == 8: # Formó un \"byte\" (o bloque) \n", - " my_language_name_vm['stack'].append(\"Packed_Bools_Stack\")\n", - " bool_queue = []\n", - " elif param['size'] <= 8:\n", - " my_language_name_vm['stack'].append(param['name'])\n", - " else:\n", - " remaining_large.append(param)\n", - " \n", - " # Flashear booleanos de la pila con padding \n", - " if bool_queue:\n", - " my_language_name_vm['stack'].append(\"Padded_Bools_Stack\")\n", - " \n", - " # 2. Finalmente parámetros grandes en orden \n", - " for param in remaining_large:\n", - " my_language_name_vm['stack'].append(f\"LARGE_{param['name']}\")" - ] - }, - { - "cell_type": "markdown", - "id": "ac6440ca", - "metadata": {}, - "source": [ - "Now, unwind the stack and stuff to make sure the machine goes back to its previous state BEFORE the function\n", - "\n", - "**The Function Cleanup ABI**\n", - "Once the target function finishes executing and returns its answer in the registers, the caller function must clean up the mess it made on the stack before continuing.\n", - "\n", - "**Step 1**: It pops all the parameters that were pushed to the stack.\n", - "\n", - "**Step 2**: It pops the backup copies of R0-R3 and puts them back into the actual registers, restoring the caller's state perfectly." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "d2e4ce44", - "metadata": {}, - "outputs": [], - "source": [ - "# TODO \n", - "def undo_function_call(input_params: list, output_return: list):\n", - " global my_language_name_vm\n", - " \n", - " print(\"--- 3. Cleaning Up Stack ---\")\n", - " \n", - " # 1. Calcular EXACTAMENTE cuántos elementos se pusieron en la pila (simulando la asignación)\n", - " pops_needed = 0\n", - " \n", - " ret_size = sum(r['size'] for r in output_return)\n", - " if ret_size > 16:\n", - " pops_needed += 1\n", - " \n", - " param_regs = ['RA', 'RB', 'RC', 'RD', 'R8', 'R9']\n", - " reg_idx = 0\n", - " bool_queue = []\n", - " stack_params = []\n", - " \n", - " # Simular qué se fue a registros y qué se fue a la pila\n", - " for param in input_params:\n", - " if reg_idx < len(param_regs):\n", - " if param['size'] == 1:\n", - " bool_queue.append(param['name'])\n", - " if len(bool_queue) == 8:\n", - " reg_idx += 1\n", - " bool_queue = []\n", - " elif param['size'] <= 8:\n", - " reg_idx += 1\n", - " elif param['size'] <= 16 and (len(param_regs) - reg_idx) >= 2:\n", - " reg_idx += 2\n", - " else:\n", - " stack_params.append(param)\n", - " else:\n", - " stack_params.append(param)\n", - " \n", - " if len(bool_queue) > 0 and reg_idx < len(param_regs):\n", - " reg_idx += 1\n", - " bool_queue = []\n", - " \n", - " # Contar los respaldos del Stack Pointer (SP)\n", - " while reg_idx < len(param_regs):\n", - " pops_needed += 1 \n", - " reg_idx += 1\n", - " \n", - " # Contar los argumentos reales que cayeron en la pila\n", - " for param in stack_params:\n", - " if param['size'] == 1:\n", - " bool_queue.append(param['name'])\n", - " if len(bool_queue) == 8:\n", - " pops_needed += 1\n", - " bool_queue = []\n", - " else:\n", - " pops_needed += 1 # Tanto <=8 como >8 ocupan 1 espacio en nuestra lista de Python\n", - " \n", - " if len(bool_queue) > 0:\n", - " pops_needed += 1\n", - "\n", - " # 2. Hacer pop EXACTAMENTE de la cantidad calculada\n", - " for _ in range(pops_needed):\n", - " if my_language_name_vm['stack']:\n", - " removed = my_language_name_vm['stack'].pop()\n", - " print(f\"Popped parameter: {removed}\")\n", - " \n", - " # 3. Restaurar los Caller-Saved registers (siempre son 4)\n", - " print(\"--- 4. Restoring Caller Registers ---\")\n", - " caller_saved_order = ['R3', 'R2', 'R1', 'R0']\n", - " for reg in caller_saved_order:\n", - " if my_language_name_vm['stack']:\n", - " restored_val = my_language_name_vm['stack'].pop()\n", - " my_language_name_vm['regs'][reg] = restored_val\n", - " print(f\"Restored {reg} <- {restored_val}\")" - ] - }, - { - "cell_type": "markdown", - "id": "5397697f", - "metadata": {}, - "source": [ - "VERY GOOD\n", - "Now check the state of the machine before and after\n", - "\n", - "Try different combinations: One function call, multiple function calls, recursive calls, etc." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "b58fbf72", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "--- 1. Saving Caller State ---\n", - "--- 2. Allocating Parameters ---\n", - "\n", - "[STATE AFTER CALL]\n", - "Registers: {'RA': 'int_a', 'RB': 'Padded_Bools(2)', 'RC': 'double_b', 'RD': 'SP_Backup', 'R8': 'SP_Backup', 'R9': 'SP_Backup'}\n", - "Stack: [0, 0, 0, 0, 'SP_for_RD', 'SP_for_R8', 'SP_for_R9', 'LARGE_big_struct']\n", - "\n", - "========================================\n", - "\n", - "--- 3. Cleaning Up Stack ---\n", - "Popped parameter: LARGE_big_struct\n", - "Popped parameter: SP_for_R9\n", - "Popped parameter: SP_for_R8\n", - "Popped parameter: SP_for_RD\n", - "--- 4. Restoring Caller Registers ---\n", - "Restored R3 <- 0\n", - "Restored R2 <- 0\n", - "Restored R1 <- 0\n", - "Restored R0 <- 0\n", - "\n", - "[STATE AFTER RETURN]\n", - "Registers: {'RA': 'int_a', 'RB': 'Padded_Bools(2)', 'RC': 'double_b', 'RD': 'SP_Backup', 'R8': 'SP_Backup', 'R9': 'SP_Backup'}\n", - "Stack: []\n" - ] - } - ], - "source": [ - "# Execute the call simulation\n", - "do_function_call(input_params, output_return)\n", - "\n", - "print(\"\\n[STATE AFTER CALL]\")\n", - "print(\"Registers:\", {k: v for k, v in my_language_name_vm['regs'].items() if v != 0})\n", - "print(\"Stack:\", my_language_name_vm['stack'])\n", - "print(\"\\n\" + \"=\"*40 + \"\\n\")\n", - "\n", - "# Execute the cleanup simulation\n", - "undo_function_call(input_params, output_return)\n", - "\n", - "print(\"\\n[STATE AFTER RETURN]\")\n", - "print(\"Registers:\", {k: v for k, v in my_language_name_vm['regs'].items() if v != 0})\n", - "print(\"Stack:\", my_language_name_vm['stack'])" - ] - }, - { - "cell_type": "markdown", - "id": "4f700ac0", - "metadata": {}, - "source": [ - "**Setup and Helper Function**\n", - "First, let's create a quick helper to reset the VM so each test starts with a clean slate." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "d225a397", - "metadata": {}, - "outputs": [], - "source": [ - "def reset_vm():\n", - " global my_language_name_vm\n", - " my_language_name_vm['stack'] = []\n", - " for k in my_language_name_vm['regs']:\n", - " my_language_name_vm['regs'][k] = 0\n", - "\n", - "# Standard parameters for testing\n", - "test_params = [{'name': 'data', 'size': 8}]\n", - "test_returns = [{'name': 'ret', 'size': 8}]" - ] - }, - { - "cell_type": "markdown", - "id": "77df0216", - "metadata": {}, - "source": [ - "**Test - Sequential Calls**\n", - "This tests if the VM can call a function, clean up, and immediately call another function without the stack growing infinitely." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "70347484", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "=== TEST 1: MULTIPLE SEQUENTIAL CALLS ===\n", - "[Calling Function A]\n", - "--- 1. Saving Caller State ---\n", - "--- 2. Allocating Parameters ---\n", - "--- 3. Cleaning Up Stack ---\n", - "Popped parameter: SP_for_R9\n", - "Popped parameter: SP_for_R8\n", - "Popped parameter: SP_for_RD\n", - "Popped parameter: SP_for_RC\n", - "Popped parameter: SP_for_RB\n", - "--- 4. Restoring Caller Registers ---\n", - "Restored R3 <- 0\n", - "Restored R2 <- 0\n", - "Restored R1 <- 0\n", - "Restored R0 <- 0\n", - "\n", - "[Calling Function B]\n", - "--- 1. Saving Caller State ---\n", - "--- 2. Allocating Parameters ---\n", - "--- 3. Cleaning Up Stack ---\n", - "Popped parameter: SP_for_R9\n", - "Popped parameter: SP_for_R8\n", - "Popped parameter: SP_for_RD\n", - "Popped parameter: SP_for_RC\n", - "Popped parameter: SP_for_RB\n", - "--- 4. Restoring Caller Registers ---\n", - "Restored R3 <- 0\n", - "Restored R2 <- 0\n", - "Restored R1 <- 0\n", - "Restored R0 <- 0\n", - "\n", - "Final Stack (Should be empty): []\n" - ] - } - ], - "source": [ - "print(\"=== TEST 1: MULTIPLE SEQUENTIAL CALLS ===\")\n", - "reset_vm()\n", - "\n", - "print(\"[Calling Function A]\")\n", - "do_function_call(test_params, test_returns)\n", - "undo_function_call(test_params, test_returns)\n", - "\n", - "print(\"\\n[Calling Function B]\")\n", - "do_function_call(test_params, test_returns)\n", - "undo_function_call(test_params, test_returns)\n", - "\n", - "print(\"\\nFinal Stack (Should be empty):\", my_language_name_vm['stack'])" - ] - }, - { - "cell_type": "markdown", - "id": "27f37c95", - "metadata": {}, - "source": [ - "**Test - Recursive / Nested Calls**\n", - "This is the most critical test. If Function A calls Function B, the VM must push a second frame onto the stack without destroying Function A's caller-saved registers (R0-R3)." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "0c46e3f2", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "=== TEST 2: NESTED / RECURSIVE CALLS ===\n", - "\n", - "[1. Calling Outer Function]\n", - "--- 1. Saving Caller State ---\n", - "--- 2. Allocating Parameters ---\n", - "Outer function modifies R0: IMPORTANT_OUTER_DATA\n", - "\n", - "[2. Calling Inner Function (Nested)]\n", - "--- 1. Saving Caller State ---\n", - "--- 2. Allocating Parameters ---\n", - "Stack depth during nested call: 18\n", - "\n", - "[3. Returning from Inner Function]\n", - "--- 3. Cleaning Up Stack ---\n", - "Popped parameter: SP_for_R9\n", - "Popped parameter: SP_for_R8\n", - "Popped parameter: SP_for_RD\n", - "Popped parameter: SP_for_RC\n", - "Popped parameter: SP_for_RB\n", - "--- 4. Restoring Caller Registers ---\n", - "Restored R3 <- 0\n", - "Restored R2 <- 0\n", - "Restored R1 <- 0\n", - "Restored R0 <- IMPORTANT_OUTER_DATA\n", - "Did R0 survive the nested call?: IMPORTANT_OUTER_DATA\n", - "\n", - "[4. Returning from Outer Function]\n", - "--- 3. Cleaning Up Stack ---\n", - "Popped parameter: SP_for_R9\n", - "Popped parameter: SP_for_R8\n", - "Popped parameter: SP_for_RD\n", - "Popped parameter: SP_for_RC\n", - "Popped parameter: SP_for_RB\n", - "--- 4. Restoring Caller Registers ---\n", - "Restored R3 <- 0\n", - "Restored R2 <- 0\n", - "Restored R1 <- 0\n", - "Restored R0 <- 0\n", - "\n", - "Final Stack (Should be empty): []\n" - ] - } - ], - "source": [ - "print(\"=== TEST 2: NESTED / RECURSIVE CALLS ===\")\n", - "reset_vm()\n", - "\n", - "# 1. We enter the Outer Function\n", - "print(\"\\n[1. Calling Outer Function]\")\n", - "do_function_call([{'name': 'outer_arg', 'size': 8}], test_returns)\n", - "\n", - "# Let's simulate the Outer Function doing some math and saving it in R0\n", - "my_language_name_vm['regs']['R0'] = \"IMPORTANT_OUTER_DATA\"\n", - "print(\"Outer function modifies R0:\", my_language_name_vm['regs']['R0'])\n", - "\n", - "# 2. Outer Function calls the Inner Function\n", - "print(\"\\n[2. Calling Inner Function (Nested)]\")\n", - "do_function_call([{'name': 'inner_arg', 'size': 8}], test_returns)\n", - "\n", - "print(\"Stack depth during nested call:\", len(my_language_name_vm['stack']))\n", - "# Notice that \"IMPORTANT_OUTER_DATA\" is now safely backed up inside the stack!\n", - "\n", - "# 3. Inner Function returns\n", - "print(\"\\n[3. Returning from Inner Function]\")\n", - "undo_function_call([{'name': 'inner_arg', 'size': 8}], test_returns)\n", - "\n", - "# 4. Check if the Outer Function's data survived\n", - "print(\"Did R0 survive the nested call?:\", my_language_name_vm['regs']['R0'])\n", - "\n", - "# 5. Outer Function returns\n", - "print(\"\\n[4. Returning from Outer Function]\")\n", - "undo_function_call([{'name': 'outer_arg', 'size': 8}], test_returns)\n", - "\n", - "print(\"\\nFinal Stack (Should be empty):\", my_language_name_vm['stack'])" - ] - }, - { - "cell_type": "markdown", - "id": "2439376d", - "metadata": {}, - "source": [ - "**1. External Interrupt**" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "48b4d8f2", - "metadata": {}, - "outputs": [], - "source": [ - "def trigger_external_interrupt(interrupt_handler_address):\n", - " global my_language_name_vm\n", - " print(f\"\\n--- [EXTERNAL INTERRUPT] jumping to {hex(interrupt_handler_address)} ---\")\n", - " \n", - " # 1. Guardar el registro de banderas (RF) en el stack\n", - " my_language_name_vm['stack'].append(my_language_name_vm['regs']['RF'])\n", - " \n", - " # 2. Guardar el valor actual de RV en el stack (para no perderlo)\n", - " my_language_name_vm['stack'].append(my_language_name_vm['regs']['RV'])\n", - " \n", - " # 3. El manual dice que se genera un function call al valor de RV\n", - " # Seteamos el destino en RV\n", - " my_language_name_vm['regs']['RV'] = interrupt_handler_address\n", - " \n", - " # 4. Activar el bit de \"Interrupt Request\" en el registro de banderas\n", - " # Asumiendo que es el Bit 2 (según convención estándar de este manual)\n", - " my_language_name_vm['regs']['RF'] |= (1 << 2)\n", - " \n", - " # 5. Si existe un IFH (Interrupt Finish Handle), se prepara para después\n", - " # (Por ahora simulamos que el PC/RI salta a la dirección de RV)\n", - " my_language_name_vm['regs']['RI'] = interrupt_handler_address \n", - " \n", - " print(\"Estado guardado: RF y RV están en el stack. Bit de interrupción activo.\")" - ] - }, - { - "cell_type": "markdown", - "id": "6ccdacec", - "metadata": {}, - "source": [ - "**2. Internal Interrupt**" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "6d3f0026", - "metadata": {}, - "outputs": [], - "source": [ - "def execute_internal_interrupt(interrupt_code):\n", - " global my_language_name_vm\n", - " \n", - " # El manual especifica el código 0x0A para llamadas al Host\n", - " if interrupt_code == 0x0A:\n", - " print(\"\\n--- [INTERNAL INTERRUPT 0x0A] Calling Host Function ---\")\n", - " \n", - " # 1. Obtener el 'handle' de la función desde RV\n", - " function_handle = my_language_name_vm['regs']['RV']\n", - " \n", - " # 2. Verificar si la función existe en la tabla del Host\n", - " # (Simulamos una tabla de funciones simple)\n", - " host_functions = {\n", - " 1: lambda: \"Hello from Host!\",\n", - " 2: lambda: 42\n", - " }\n", - " \n", - " if function_handle in host_functions:\n", - " # 3. Ejecutar y devolver resultado en registros de retorno (RA, RB, RC, RD)\n", - " result = host_functions[function_handle]()\n", - " print(f\"Executing handle {function_handle}: Result = {result}\")\n", - " \n", - " # Según la convención, el resultado va a RA\n", - " my_language_name_vm['regs']['RA'] = result\n", - " else:\n", - " # 4. Si no existe, RV debe ser seteado a cero\n", - " print(f\"Error: External function handle {function_handle} not found.\")\n", - " my_language_name_vm['regs']['RV'] = 0\n", - " else:\n", - " print(f\"Unknown internal interrupt code: {hex(interrupt_code)}\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/docs/Spider Instructions.xlsx b/docs/Spider Instructions.xlsx index fd32457c7c452ecf54f02111e7b6553646daf262..d9da6068a43bdacdb34aad901d8a5f52d7370038 100644 GIT binary patch literal 113130 zcmeFYbyQUi*F6d-NC+wt($Wpmf^$FJM9^Wfp&K0bhh zdkTk)01~mXv@@`@(^YY@Hn7!ZaVwV`ahU~9#v_}i5HKja65?Z zTiy$jL&Xw%#~o5SmVy3tAMUA*`4b$0SsA6XL!uv_6|p|6k~58mA_v7Ek+yLSLeN6g+&n6C1agC)dHeArnZxiUwR`)fWl4Ub5xuUq zhe;Sb5l@h|WBRH4?wO&ELmA|Z>U&s1+bRaD2O{(ILGFlvo(_L|r8$NVVGV~t2>v6c z+F$&Qx;WuXEp0)54=+)-!+4mko)T?cg<(X!3aI9tai>5uT!af8;Tz2HXhGm9>i)rN-T+KMch9@(}0QWxHzal-?H!3CuB;uhXAAp0_H8())n@GHmWo3tB;6q4+%o zP0kU|M?Y@pW(nI5`t%*m5oIZ*S`NWChG7WPwG?)M0zCt;yxVQ z)zv*Xh5v~0GSwI4`+#s|fDlFlVqDk8z}%LZ>H7QsjqU$~1NyH^&j-uOx4d}hza?=V z&~XHt`ubQ{+CfO7hE&DfQ*!cAS!fys!Bhh^;bRqipL?%8>fFz}CZ>2pS35`#=h^c^ zFtJ{dmpefGqfbBBKcJ(si4y;iKiB%?BkTZn81q`niRNS77rMO4>=fzF8FKNV9nqr4 z{Y>ikC{Hs8{c-qWyfoWoHKz5Bq3|$aZ*+k`ZkhGL80-#P zJ)<$GYlk`M!3n;qvN5+wpjAu%+$6nQsJO-C) zK#CK@f#F!=+7)foqALc^bSRt++Fl!BSkN1gp~94=r>`&0VoO2-44X)ssWmGc%^ij?eKQmg@}p`ZDC8DRtrah7(FBGqY+2VL&9HUi2?!h9koYQxO8Odvhka zlB?AyF89my2@7mqxCHQ8e4iWf5hzYBs)>91dp_5jDjuagiVM!7Je_&{byU#6E8KM^ zH)|rWna!@a>ccPjj$7gR&ad;QQ66dtg!&6=hN`(*PgDP>CFcS))MyXI^Og<5tX19G z{DM`WX52WeQaKdACAM0=T6CHqn<53>iTelK26w45edI&XXjS46S`-o}(>eV1`R zhba3hKOcWxvR$xsJpNo&S?;-mpzvFa(w93sQoL_tOgQ>qpSJ3{KYcs5>p-`}-(=9) zWgyWiUTn(!j#h(Tjh)h!Hnwlpp4LPtidMRHS0?$GmEh7x^g}AIzPGyO^2XWgM_%xg zTl&Y(tB|&awuyyz0%xATc+yPLcD+Pdr`o9avKHX%7sx@|J9WAmyzd zigv2S52yH#Z^lH?PJG@^F>`5;Wf7HRLdW)aGnUuKk}~l9L*h? z$rFpx7yba61AWKg+xTc0qd5FXn3FI4KBB|(5&R=airJg61-#9-#sv39ib8`3#=}Ow zG}CNHXbl^6UI_%-hR3)c)hRQu^(=WW=-<=rZ#6_@6_?WS&T>N^m3;5CfAwLYtww3K zUu5a1<+sPgG4juq#jf6+p-2L1U89h(NSCd&wr*S3jpZE%gK30=Pd&rm&X< zcuLVLO$lOR6J$0ok^Z;f9#1>Zmj=RK2N4bq9}XEF2<|^c@b3`6D~Rxb*#%zvfA&{x z#J>fB&LQ@r5Bfkgk)XsYYpoi+uFQfQCuD_{H z1z(qO#7HcNiW*1snkgI3TO8Qg)064F;Aa2%mWoqCkENmZTix4x>m-V*6XXQeA<}m|HAea!UMUX-Yh(i7+bzrE`Mn)vYe^^l)>%k|5O6~O zN+5XHAu!j+4td#7;n_61`|c6Bs5W771My(u1%K0Y9h!jy(%Ar1nEob@agyZc>Z;fh9>2`EtC8NAzEc%?I*lYmflpTj%|6Y?cpf{FOc&qBVJ z1x0<1m~HVwkQXENF*~{fNw1IMPoA%7;pdYsP;Z}qIN52L_q1H2_iPMQIQyhd%5Fyu%>;&E0!ZLf>5yy^nO zx>CNAiHhPFB^9)IJbomc>t#oDCHqaEjBwpPt`UvSElIl5?rjF{=y5{f7@S!_cdr9a z|8c|d0p5@JQV~}?=P8eRt;JZ@N%1y9EWE1->mn_?wmncwQ$v^rD1@NZBJWLj=(o=< zFOtV|--0vwc)eKguHu!nF0Edh8wdw`ov3Y|^lM+Z+cE?QZ^}3d@4a40={k0^i|)%T zvFmb~a^Q7^*H-hwH^Kbju1>gjUW!nVt=U;*%uCe#rt^8HJGt~Ropz2{|3j=PU5EH8 zHk!{87^9^|TgX*Sj|UF(f=^MhEd#qXyq=x5(H}kV)ovLuDV{EqXeY31k|gSAuI&u~ ztxWX>r=&zP19$&_>cjA|gY>>UJls`0+W(tASa0-^U}j5L0nTi&YQ21bC?GS+Qr^0` zik1_`E)QT)Ia0y;xz2!?7F{rS@CFw-~DnUI{I}*cXyKf=R{YJ+Ov&?sc5T) zsRrKDwac>~9u22SR|{phMSF4v}xvS!>H zu0nZ}>iJyjT+**xkC(=dW=J--_<#DB@V4}b4xC)J|nb*jAD-~DC3axxYtcclL-bu}5b za^~SCf9byKc=YAyNOx0!cUrlO=e0a>!v%l!)&BAFWjAnxjEHjgu1*d&*3KR|=x$P5 z;)Ivk$|ODF+Pm7>m=Mrzrl)gWrvp*js5hK#AD{G}QFS^+JMWxbLFpGSF|a?19YxBo z*=u-cW+#wr2~1t=Eba7GFt7EKka)N`+3nhm674^jy8JO+aeP?daFpb6auAja^N>1p zrsKal9yz%R>HOxGuW2)Dr#r=zDg7ehzL(pQ^8;Q{4u>V(7f(=Q#e3Z5W6j!w z3~QF%6Yb|k)8u{4SyYi#T?Jq~AKKF;6@Fa!{%+mbRC(8)3_hFN1P z2)J?`$s~1dy6Y3g9a6sQw>w&xzucyzn+PbZA;CL(t-*2BGN+*E_~YVrL!9d&y>!;* z_o6u0-5U8kAsAmy7@~M_%~eN@z~SB{*5P1@fA>N3(8<)oR37f5nacxTHF$R68IJ~A zv)oPFXsEdB){FU|4d|$oh{e&0!TFxW`JVRq9^IuA(N#SAOpZ#Z0`3vwp~I?@#~2J& z{mG*~)T2JcL#IukU?C}dd5sl57Jf{@;GfI_&~8z#rfP=aWWu`Xw)@^Fq#)t_W1HJjL7)BR zV#0Pqd`vb;y}09r^DIdxLAUmIea+~3;Wwzq@y<$kQlg4Lz2jjgBj4vG&qOYiUva#y z&DDCDT7{^AKk9oTaMLczQF2zxzC25I_;K_b23vY$C9gw#wV%E>6rR@mqrOkC(ehC2 zaPK1p`g@aa5-lqDhJ!C=2o5h!7hBXTUS@9EN7V!b)HHmK&EmttcjjgH(qyTRJs&vd zD$APK8hSx^bvzV)RIxCo=j?uFc+%1@pj($T`B_(&!QIj0L%HML=7Z{Hd3EZ3BWi)m zW91`{i)}-mY9i&R@m<^F0+OjKg}#@$gidHKOSBQ{mjd;?mm?nMyT`gyNuNEMRW~&A zPKTO;>y5A>)Dl~7J{@7oB!Ol@@H6fG8ylv(D&+^JX@9JBCAnQFy(b|$aeNm)+5M^ z%I{NvOAvz&yO{Nty1yFd(g~8~{eq|Pj%VB;PJzG4xADzA7EgC zB4Ibw$>1B4YR`EF6rZ$?BQ=Jv(=3)lAr9$+UYdOjTxpvWNgRBz8 zgy^;Mjm1c(dsM|8Cm!jZHfl|e71NR;e+-GIU(`yADHo!w=%}K9b`KZiU4bzdDi1cu zDiW)$lGJMf1t_$aDCU`gT0yVpWcmAFDJM}j#}UKmq81#(nVCV`%gw!xPf5PmR?K)w zvDF4;W#BSVIXRI}3mUQ-*K(+HdveVZo~-YgdllN)6ozB(xAW9C!k84)TPZ0tPFjTbJvIJL=A}7gK zpl_+FMloycQLJ3S3?|^0pw_rJ3Qpj6173o%>Tc)`Yaq@6O@BGP z_%joyw#s^MRd&)bu_hr6(`uI}KO_jC{T&+~`*ds`VIzU{XV*h4tF!GuE|ZvCrCT-d zc~vB~f(o8l@il|wXCc6y3~NBQIx7clXKE@2a@j^cnSSHMc(KtWuR=8kJmx*R!8?JYta*YLKf1gv~3da~QI-Vj>Z zROq8k$6kDLjqYrM#W~u1+&rw8stt^+^9}=LQKAd}EHOQ)(Vc5m`2nTKY z6v4_ZsKT9P`qa0gz7h03#F5;CVEWLaVpg^+^|9459eHgLDoHblhZ1Yr(-vEtBZTY4 z5NGxx4z~j$TW4F;EJWUMAzXjV1h@m1;L+`$)Db)8!>i*sJ3qN*W! znL%JPc66?PIe%;^;roa4Fl&HwWG;%>Kb)g*u|Jk`M+mZZR;da4=FPk~xjB!}%n=tx zB$9?dKkK#{Gr-GDl<-_j*R?|X1w>mnzlg~euT^Oq@}-k$5&CtH=jDQrU{zNQOY5hH zEbm2n?yG(bj%Qnp-;=Ijp!Rc4QSN>{c;QIhR!9jEd)>jz6Ux~9)1u1g)zT|mVK2pj zV8pgvu^mZL^Ip}@g>|)y*zP2BwO58(#fq3DzMw@d(iMDeuAZEqpC#NB2j*%@TP6;0 z*-uqWicSC;ietr|MOe@mU*|cBJT<+*xzt_<&ET+;fx}0PL{r2|2!))W*wD9bj7{Sa za$8nss~1RZzDERZW!6ANc`M76n)gb-jv6#W+MO`@-rp<(s#D@LRvGvzy46goWQ0)Z#Tp&fqt&m$W7XBJ;WoNYm{k=z z#Ny@QbZvdVZ9i7{r(mDJcHC&&Yy>4p#VX!N{Ge17R!63-Wz>UeO8|=SvlJs;?omYw zdCBp(`)w!V{8wAQc(dh*ke7c_9fm^@r3|^B@3$wzTxE=`z4@`p;NizjrR_K|h6=LT zJ7k$AFwvuZPqK3U(qZ@angMa@ALdDAZH4Kmm5x*oqcW^=s#cuby?`8H)u|&-2e(L{leMO$N$cl6=w!5%{~!o|d~po>OsOW6(S0P(EoV1u zGc_5TDXQR&v){}C5b7ZOs+j0OM`@XHz(w5u&oAlLROxjx5Y zr)IhqB~r>#?4|(B95_GCbw(l@C!iFqMT@N#;GRU>W*GAw5Bq*GjJu$VbT8+t z9SeM-2+MAC)kD<8w?{LP@?R;}IBce$uOM@O@8A~dqqXV#YD*lC;~0FAs$I1f`7mQU zoiSazXsv8wl#CY!RY&jl)-D*3J#23bLEZ@3_hc#ZPn&$=mYYR~_Bke-5J`@|dFkAolz1dPYRrB{7 zUA>k1G>CK?<{QDil~e6Fz^MzS$>U#^breFl70|dAPFIVbrtGSU3r5Dh`VR>p(2air zy|DOb5>R2)o&iml3JE0)Wki70;zbu*{E@35hk5(bM(IIRB?-_dErKvMYBGQALB;VMzBRQ0R3HFIST!fh!8yvR`)wlrR=EsmljTt zL9#0{Hb&P2PAR1m&uhC)zT(e~ZQevYuPqc%GYW>$TcF^u=}BsDnm;LDwrKuG7LaMG zeD#9UaHwzpeGriwc8^xFNuq2#V(aT|4TuSB<(X1r<7k+K9)iI7^*kC)3dJZK$QvhXVJn@MG( zH*OQINL|3XBfr*Vuy{m4Va26R=} zH%-kz)Va-<;#5Yft&|K4s@%BqF4`=MvGS!{{Rx}b#QbHRjVdQ{oP%8T)&EAhJ3e&u>cc9ahC;VBX2rPx)NHCcJ> zI3{@?<@3rcZs=`be=!)7_*oy79~rtiBs^F~KD@RNm=SkOJ}O z)njJOtA{cUswD&$n1HP5_<`6f-&S$e<*O&`R|CKk=hW+`r5mHUv%d3_0y@Z+_~7!{ z(F^US(ho(Hr5OvGf6_%*`7-%-&Z3(Bb(bIka=Txj37J!W7+B7eE9HI`KU6L=qrlOO zkoH`Vxbuc=uCnT6!3pK6oNKmaA5o~60x_6GgmP&4kcC{NXY?@}3X2>!l_slLAD&I$ zNe0MRdPe#;=|v=OdeXy;(u}8D^dBTVV54LfFw%?I@^w4A(O|@~H>Ii87G_Y^R0!{! zTc^0>51jbC24TvPj;eQZViWtZrWR&f+uGxE8_b=?`#FR2lEUvpN;#4`8@pF3aRkc*-c$D26J#hvT z@t1&DG~&eW3duNrsYZ;v@iLn|+FUZPXx=_^ z-B^eY3{~|5 zOD;D73C0xz&DI`{u~?Mxh!$8(yl?k6lNFYUDo>_lQ?UWEv@j^8BsX326QF3y->Q_u zda8gPRZUrBClJb>U5BCq<8t12lelYsl|pX#-EIAs-?BG<_)TV{ZE5}VMk)H$wJsRN z|JB8?9-xcQ<)@0Db2a*Q2^db%BeS$rTPHgN{g#^0p4m1G*JuX3eo`F z4*=X|$RHSiTZ!1!eg}7wj8Q`fxL=t865Gdb)y&6kx$14cvrDGqZnC#2p^YC^7woO0b{Xt@Wj!>+~#q-n# zxyyLr#ai(`f<;2om1o@49o#ob!)NGuf5saO@|@*9?`XfF8&Hx!?8C;N;jpp%rc8=W+m6cP8vU^nJ|`XHDNy~`n#ahL zdV^W+N(vb)`I+*9SX?#lqEdotBw483XGui*}20}}_}xkI#%_zFi#87K8jR%mt*BVS3r239s6^|2I^s7lY1+Y~RUQs&UocWVvL&<-j!kd1z%h^cHbQ{cz7Xs!&qj9$ViDC{Cd{#SG%D5O}eN=D+~ zNvS7OIIW^YssXfmmS1_R{V_mDs2)Py>R$>3OH{?-ruvhS6<%an{&)=iY8x6)u&e?n zOHZMyd52g@{~9rq18}h=QXzNE92`e>sjy2p_OE&mrN>005-|F3ec0Ucgv*Y^-emN$ zZv;V(mcspP*DCvKw85ep{4HKaSsQw}abMvi-lG54kY;ikjaykhxVS?BRb7egz?UX( zWRy&6LQDe@@SBo$02+|z{4o|4%A@TRE65b!PY>2QdH7&mNUOfQo7uVuIN z%6m+IkiHoFFvFS>q9iW?bp~R&Oxs5Fde~)Ci6aGdJ$R`F+<$9TFg>RfDpbPe)7DLGjUz}?JCol`rHv?luy=?M)jN0 zw$)uN_q0@s?IMlL&nOrIGU*>HY6C!jjYB_O1Jy=H{ZF7Nc>`1j>CFI8J4zEJd769x z=wO-lyFWmyap>{^pxOXXJ5^KwXfRabAG-@2-U79w4yDG3@(9y$nV$JF`Fx! zFQW%jjeAqpnw#bo7c8-ef>4kDz%$Ro?R7#45$5yR@)bOST^R*~tm^^FwVAZ`yUe9N zPzQQarl1&SVGkHE->=+g82xiCvpAP}KstM138b^iGmR%RHl!EW1j0fKHw&Pac+^S> zkK5~Mq=ejEPb0@#!QJ&BYx!JWUk|*x$IraQBdyT|AAV*1GK2~Yu6su^@#oddyb`&jOTV+=n!uVBR5vXca zri~K_)@yk0!1{`}?LK_vqE)2+&LJ_6>8qze1Nyt!t6N2Lqml9C2NcSCUN#e9n4iDc z{Q@^)Tdn?K_mTpd7Kxo_gce8R{Irqs+1w-uQUxN%VSp2 zylBU9nt%?{8Mk@som7aYNCBb8XuYQ@UaLyS2q>jOBIB+x0uKK$JAqp{9I0Z`Gy$Az zre>m8emk3}K#Ei|wsO^pI~h<5@V)PrIcOSSmZtcEzaY}6?kBE`Q|la^u76eXedw;i zo9pO%tOuz2B;Q-pz6T^C`3S*c(K7V@a!r9PZFQvmBNu}`2kSP|4O<_dVi z-nlMy0km2(Dw%YqX`jiOV5pxk^&nDOM{YISaI-fuPvBhFCF7u%0(DX9#mSeKa6z{y6{Y1C49+WxOE>zC^kDP+ z2=h~q)6hr?g=YNbQ%`l!e@moLRU+wBsS%J!Ie0gR`Mwq)k+JbhHqcFWHZn``1SG;N z2PBh_p^Kg%b6M&%&3J^B;Lrk^Kiz+M=12qr)Ei?4XpP>|2bJAgcl|t##(!G6a{T*R zDRrImDjvsqqR4HySu%~VzMtatZ{O$f#+1!q8E&r!?bKKcg+cgO%$RJs>DtuNXLj*0 zCXWgBL8S0{W-fqb>;G#*QK(7-pl-N9y`96n54u4Oow*SqOj8qO*yX%X}V-G-geUW~iPy_aOTp>r=jFi4oJVd4ez>0Yh5KtE(v)>0l)xcp-rUXb!IQqT_%_0P^E7h*iLgribj_43%xmnh(29|VP#;!pH6lxx zf$FZPx-O5OnY?90wY3mDv~JM>Ggh~&Yw;INRD&Ujv_S@4PE^Tfw(G0W-^KVh4j46OP!JUgj7XF))zN)t zO$SEFBqtEnZ?e}FKMj`F$!d{-X?<5H`JXW>xK!KvfM*W{g25+C6p@p+x*h#GlTR&@w;hJN{5mjIQcy# z3Mi1SJWI7-+CRngJafC5`Tdm!o?{oMdts>qB1lh{!bko9OD+=oS{{=3M+AeyA0h#h zV*;3*bSW(Wr59FE-Yv@O!`n2FPLY0>2GR{bVBe(yA=Ag|euwR67d-)ovn|6yF_pO( z6~(HF^Q&mKKEc(I>{lehd-;U!DTIDPnFG}q%?oKG4Zx5f+jh+Zi zW6f=$E5iQ$ht^6jNP5vN;4p~c)IWg7Ob4`qyk!m}S#RlAO8DG(nQA)Ff$@nscaaua z&+eiKi=GF@?7Auku;#KH_(z!Mu4~K@uuL7&mH%a@W$#c9r_upNQqlsdfhU;G(}mZ+r1Ug>WbfXM1qnM zcO8*n?>ybV<@q`EPkHw8@TJ>q?w>x+mUB+iwqNiDH>l#uo=EgGea$f2(>L7XS8PC=6-^-&C;Z*jo!T{YiQCL#FGP$7VuHv$T9ys9ugyVRfU@3p1)fP(`0BMq+-irhPG9| zuSiNVHw2>s1gl&VoZG5`pDZ(q5Iuor$^wx5?Uv;G3Y3|`X?8b{I^FDE1jD}Nz8zl& zW@T^@zRI_=GK67<%)5L*CWx+=J1~7enVSXX^;8YXKrfeP@}YuLWiBvw%GFV1VNum3 zE&}(azy-Ie08R1tY$O&{2~XlQ{8klz-oN%lyI6vEKr6v_KNbcoFIUmkp;zA?m>oLDTFG zg)S9L5_Dhx>(r$j=`Y3nCMGe%pea{VvGOTQ%b@hFDn8xcx19ysBpWre_p_e#$5gP6 z6flYIMK%hN;V{d->v=jb;w_rEBiVqojB(E|o+7ON?(CRl(!r)Zu zj{1KUo}wlT3fnB1eSk~;Usjud+kMCWm527)?cNu^ml6)B6Imf6d=Rdz`yzYrae3(T34cN4EJR8zB8 ztQnPM&sbtFaAL`iq&Qi(uQfKp_3+ zLqLV9#-aX7EMoqHe)N)|{=zIA=H_9Ljo_S{>9~go7G0+6!Dxa9P+B2UEI=&Pe-^&8 z0KpImmfN=6oYFqxdLE)<6k^UnpLs`YhnkNbU1@YZ8aGFGsX|LRNv!kDe@N&pbiT|~ zuIjzNUqjpJsx31jaDKekDKDQ(qRV@xauplQ3%Q!q^-fc*ceW9F0ueb`r41KJ!$!$; z^}g4w=JS@00?z96zei=ssuIAZya3WyDR|JB=Dsp}K|Et>nf8l6LxxfuRNzuxY62rnCw6VWy@~+1wS>4Z@2wIDfs1`ic4b=mG4w6nkV!EdpvJoRprS?+Tp?{inE9& zBUebO^2C9w(rl&}OJ`KL5emxnR)D*8ILrAdvMS@|e{Xa$T9kh9@S9>~$J~E0|5h3K zlfM!b0M{H`Z%m`F)Y6VqGYwrnf5&!$iTN3=*S$-e#@wi-tWUE&~-8- zxvmTE*y=JPByX!3rzGZGHRJ4MrM;_WdPC2{Q8!da8I(EE8M`t)Wu1m|n0u?Tr&(DH zh7{@yOideYjLkC#(fwqBosX&vZmm?J)vcZ-13SPcS9gS#7P~ric7wGioCCO>&Xj)ROJ77a!*;Mm$#lg zP_|?>=x$~@%ATDl?1IhNy)V;ZnAPy1jP?-=kZ3t!HI$h~__+?!vgm_^ZbH))z`|#` z_g>o|2i^aCN@uzkjdVbvD+X|h;)C$$e(@%wqhxp!OENcvQom1$?^OR1&H^&nx76v3 z8K9Z^XJ#WNPGNL=_gTSqlD9dGHFinn?(S2h3H4!(6L4|uFd0wxQcnz@_zbXe4;7AO zS}kVrRu4xnpQ{vn`4(@ItwX}W(RhBJ^((z@(D|~$Vy#f$6PwRrw%+kKYk1z5jOSRI zNhvA}VJQ(w6bE>yZG(kHV(xTp;OU9hVRA4ACnjnPcTKNj>mMpMzVYuDc_GPr(|o8?M49LMn&PS>DnA@q^OMF#kk@Ms63jaNeVax1$^s{`U=Ulc$io zz2WYOnDi%q_K=HN8u6lcdq{WuR!P7G2(Znk3%QDS96Kpd$>p|yFzhjoBUV12Hq-Lg zWX%&_wLehZ40WrEu}x=qZxBP%t)c-uhN~XsS6r(el~FuN*Da;-v#VG!3R1itv9!*> zv6I3OE*Z}r=X)_^Sk2~sFs~dsuDeCNDX@8z{DbEFWVMp|3+KKc$Y1GlpuGb(#OIY- zR8X-@q(LTwt$_wjw~K)WT{omSKf(aQKwvON*Da@EOcRbVFQQRSd)8V^`^uGJiPo&1 zT^H67UByJR>BSw!Y-`Is+^t0t;lb$jzdhcDAH{*yjdP#cW`zR}HJXFEwEI+az4oxY zF#p3PPUl;I%W7{duDUcN4|Bh@!077_=PSX9oh z^?P`P+G9tKb!G9j{WCvuI(kQV+O)JUw-3{&Eo9)h#|byMqC#rM;=Xb)eP0xxC;$01p`et@6hf$LnKi7wyA z@6iRU!fE5&2{M#!N<21q8y{oQS6OJ+J5|RsA`*K_Rn6q0A~E(@2RY^20qK)a|Ae7c z9}(l>!QfnvS>*kv6$yj&4b>P{uRfFIGcI`<*R#J)bA7+&jmh4{RUShq6*>PNgMm>y zM3;Ce>01i;-)74sq7v9d-Pht0hPboF~MXcztp_mERP+d8WuQzrAI zkI>OXKWcDyo3 z9o(9po{Lto_Xd8cT*RC>j$uj>@3yjI->+`tbf=Qa9=WuX?^%`}h>m*nQP3k7Ta(Kv zHmR0G(~9pNcxE)%cwr@BW^|LVWq0VzTU4O&o;wett}~;qQ|E}zZfLaY8s&^r=aCs} zi+rxI`@E*<{oHfWC%aE!N&<{Up-DTq6sUE_a2q}SdW`l0bumdbS?fDP!%8k``<>G6 zhhW{>#SvPQR+VLjK7eY=8Rm@xo^4(&F{Xwx1XiiW*=@e^K#qLxbDOD zw^({L-2=l@77nxNXT6}OPDW%~vWq@J=VPM$u^rS;Pt3`5Wft>-T-n05sJy=q=kDz( zM``Y?3@PD8x-2xFu^zNHDcI~x=1t2yqWu5z7AdZ!vWLnL3`l259{y$dY=7NBX>OG* zkze3&uKya%$1hFdflSWZGs0Ov*ZoFzGooFWD0N*rxpa0R(XK0$GX0uM`D%ME0;0@Z%CJuqG|kS%%)Nt&+BALBEy(s+;hBU3SzvYndwWK7z9 z2drBcv(qc>&a7qqLv8wH@~=;Zt*^Cgf-JgY?MU%8Q^|)!c!2v`ZV<{SnntZENd9F+ z-eaBARr9OGd-<~B5-Rxxu*C76G2b3or|FW6u1(tcYP*(1pWlBjL*4P`m+jdGFP*uV zk=@8>*A2=U$Ic3!-Gpe@1}e7NbTEXPiB}}KOIpR8PjPN+2y?;_4>u9}MwHQQ%_V>+ znXg5eLCYH_-nl(Ui*UAHc0Nzp;LNrV7k#c%IhzXE#uPJTC+D9BOPenkRBu0I{PARd z33wwDw0;I=i^#DPyc9GmDx65e@Nr#()0x&fwcwwNCYihK%xMQbBF^+@A=y~UzuVgO z+#e_9XqVPhbtly>hHz9R_>46_PjQMIsFgFGcBDT0c@s-3Nrx3LJU^1b61aYdCwEM| z;`~uRL^aM=zN@xtE7s#h%;8G2FI+ktqA4bG8Ii#F@aIzJ+m2Nkkf>rXf7ENrK3ob`|ab#C!wGH zbt*=Yv}%gV5uq2-GxwmXL|cz^+$PNoreqU!=5`I)(hl}pV%&*n5A$UY$u_JZeV7wLq-QKFP$}c@nJ- zyunb7McNV<55Dsh@QX!n1tK(~iP##lYB!$vv5$UI6YscA3CVqK%0zq(ud=n}hG_Y> ze_$^aB2~)miV4)#(CZ2B(WN*g4Ag3HxYUq2cRJ|oUYrlXTjwC1^|@GIW6o{gQjv7O z!OT~Ai&>A-NuUm|5=de2BPw9|G=0xC6?>0E&Fgr~N{5GD%HEsI`81xuIdg#ch2F^; zkjcKpyC923S#|J&@ysvdU-lsujb)LGIF;q*u8%5TwJl{msE@0`id_!rj^nLsUfM9f z#(l0Mqk;;2&nKaPgW8#?d?lFW>BPO*=C}S1UyE&-@04&1;mR|_t(23Wc4D0A7a)R* z4ldu)a{ercU70;rul)PO4fxbhhb^Z4`Fo{o)*%@y7yE{@n~B8_CRyH2uxau6UQ@Bh zUO&7W5`E4?iEe#hg+D7-!UG4bo<*5W?TNq5CylbviGLCPy9y8r{WKty1i43(yhoZG z&f!^J-DfkOezGa{O0#Kyc6T+@iQQN~b6XMiy_9~W6YF&5UcgvqR9UVC<8KM&D0td% z(7x9Bm$X%#W~$VPyy&bI7u~Wn4{nsbb#|+495dM2@7~5KK7&V(>*OMWrVRDe&lB^Xm-3|o^N(Dq9BQQ)MK-3 z_kc?NUbI8cZ-~)!tb?I*%k~1>USE&pGxx$;drrhFWr2{3W@hG-LFxKka6#Q70rSb9 zL^7hEx{Wp-BVPOdxDNPB1hSYh`Mym&@eP0LnGO(&6Cv|1MfBbD$c?I&3@7(A^)2I_LnF zR5bxMVH=IvVQ5Wv2RqJNR82VBPeobJy%cc`<|vMnJL4^{zl5vRtomtP=hH=?bwN5~ zTQGPcSQo(%_-vT7H)mV_B*A&x?7hlbwc%QZ*KZ~tiuC6w=E@WNoSzfE%TUwMAhmh& zmZl*GNqxCM=-seIqqP{4wf+`Oj>Q>jBkA$NWw@;NlGduq)VWD@v%GLX&f|G~OAB#s zYhV2cM`}bli4v?IZ6A>lO#$W)89HiY%fNF#u96(C>wT4SnNb4D=j@~zG=Eo$}Yy1 z8m*yDmj!Is;_zG2mc5@V#wZDG(}nvAEUdb#`*8U)do`xyrD<88l1#}P2}*9$z(#U& zAw&DTou95sa~SPQf4?3Dcbdiu(3bXJYm640SBJN~)q9e~6!I}pnNTOxi2vfKpT!(n)@Q1vBb?pQOHX66_yL>3@Rc5VH4Jx<`g5b$B z5CmD|dpQd0>+43TI$T3eKfo?O!fkI^O^$fl5fkF-V8^HW;bITx;i`GVi&v%d{Ow$eLEqwNw|hX4FXWGu!)<=ht|2zSUoDt}d|393LKZTJ^G1V>>#* zoK2`C^gt@w~rjFgF^(*U|e`dKoU`Xoj^M{?>BTLLv zt>I(Vp93Bf4OfT;xLQ|;l?ipzhtCY~L@(S{@jE3s)sbcqw6h`H-Iz|dt1<01Op?V| z?-ld*hRNsK4C2IGv;2rxL)n=`Rvd{8zG}Zl-nVX(eeAX~xK<@))+1jw@K(zL$-g{r=2CjOuO2#GM zX;860D@LLDW_QD`!oxEw+|gLZ<>9v?OiYrp0hvV6Y!L_EO*lKa>*p^J8O&(J8L6&0A%-T6a33OQzqtnHULZu2_)JY27XN6|z^naE>okDVI>v&x!OtYc%+ki;MP8 z-0VNUhRm(#v2gbz9tJy;oH+}9w4G{1cuGHeY~wSyiwOgqY9JkQc1QFef`$5)C#xij zqX~Mh{8_fkL|iW++hq5vw`Xn|sS`9r)r$HRG(<1nTX@Il5_Gsab$f^ucW@UWj`0zL z@!C1XrH;N_RpA$!x$in=V?s(V-HqcgAJhAw&9a9~NOgZr1wk@%NW2aOw?z=f_!(Mo zFY}>xZg&So3xU;8sTiRzX;>NmVt|Z<_G}7ex@JOs!Syc(398=uSn)tjhU#v$Y}^S> zi$hQO!dbqU`?8Y7g_#0mlz8_uDA8rZ`Dva-I7b!Ok~LnOigW4k3rpD-arfHO93ppW zD~S}kUMYT6^VasJr^^cmh3kTZ%_LSIHm%CByVH-7b)FLh|69d_Vi_trc*d7BKVtVV zc7ZXy3j)A+*_6)M60PNF`W@9#dn@VPm@$9!2eK+5*Lc1IYiJMg%r-4nN- zGzNjH^##BGgnt~`GUL3F^EqA%&*Ia$lfv8a3pR1}D{EjLfR><6{h7=?u0U)c&0ml% z{E7K4GOq0B$K3A~b{6v(=?XC{NUK~&CcDd8AD_5&Z~SCHaX76hh`#FXJ0G+MKYp_m za&r+_gq@zksP@;=*T`=3w!`jjJKZa2bFNUj>pEzB=VHN61#J7vcq-q4MH}n^4u;nL zor4Di!dWc+1Hcm7&$9T$NPOys99;8`o=n!s<&!p>m4L=nBYn8iUK?fm5$~Ca21k2N zizp?Y=3>7XTnXcNn@DB7Wh+mUkFIb}ntq~H2XL(VH~%t)0{^o3-pFD&p-ZDiOBP59 z7w|9-Vuu?6Fu>aYj>$T3ih>&FYyykRO!@bP!uB~l7RuqcHIN1EOMJiH{boE%xOb=b z-XkEJgA8@}X6TN*Z-%lzeNj2pU3&k8#=a?BfxEu+)T?4~BlAP7NQT%qw?y)+Uec2Z ztsWH)G|#Z(?AA+X_Q__Y zP2j@pA>h*Ca{yYmNtZbTR4TXTTjnx&-Rpw7nh3;W6w3*+3nNU`%GFo3f1E~7+i61o#_7zmWe z0%b7$6NgAjwbxAr&vSi+2mE)A)o$2wY~DA=k`-(^*5On4rTXHQ>0$d_oqOi%LTc$w zcz1GLk7+I*5W#eUphAsY$bT5<#9cE5{<~$?zhf2|;?#SmE4R(obao}6I?28M!>eKv z-NsANhK)iV*T>)U<&$Fs*k828&V?p0iz((dmV6F7>TVQ=v#<*jqIHiO))N@JEmrF$ zV^a9GE!A{3BxFVN-RgCX?$aQ#ook!EV%=*V!Xg;LKqKwzQOulcap*wyuqs(9bH+;C z%JQdX>9LP=WZtmo35}jQC%D}Xj_4ArGMAO&t`4!a7OmCEjxO`GwUyp|y*y^h;1@li zHSvuPiz6*mu-537Vh4$~?lj%wi;V()B(?5KTmactdfzY&MPhd-yFh4;3@`WnDuGEd z8aarxj+}ac~F?0dk=M|`NK*CijILLMIec!#&Vr_PFvxL2N}v< z7hDL|)stq2yBqHK^2lAe((XKpeOqxTvkvdK4B=e$8QA{fTwce^1!di)F;x~pwq&AN z5pNc|Gw;c=u$F31g`19_6rzKFz6k6qwQsE`u+IFF*7zOC?HmNblqZzn=~-N6Y#Sef zCF@ZUN^3I}r*!veGj%Usz_}J1XA2z^TYk)}2mwdH;yd8H5BLr^GiE&p+)HmtOc6o2 z?#^o?+cNnMY7;nC&BZ#4A6=q`%vG)(t(ddUYFN2>|3xe+*~*et@O;VX(3t@FchfzWX>flto4mzrdig#d%}mQcFS zyjKM|2<#TY9X!KF0=w0wS_(a->8J+jswvFhN>I8_IiEWlz<^Ilt&89}!a!)aCx7Zr zo7Z8b({w!huK%=|uA=~ZGK*{HFfaXS{=9R#2@g!@2T(=PN05@xp67Cb91G>Io!_T&kuUc1cVtvam7eIbl}Ai=LR z%O)e}g93-;4V&HE$x+v4)?RC_xI8UNyLM$x!ZI;)Ib1uOwOa{IQN{R)Gi~tdNUL$fy zFDXZU{n4dE7ge+dN7IEbD*6uZ%$4_5yN{DEWG#Gd=dTOb5N5B|9||U=z8teUYRISY zS;Xs6io)X4wcK;6=UXZWa%HIMY%*L^{D`f?*ds^v?(?wh85%Ik3<-)fl3Lj}BfsW` zu3~(Pb`htvrifX6gxi*@G2(L4S%E|%J~Vd^hMR16uKgGG^)FxG1YbT!vBSeMIcYBSs-9|9$V>(>dXQ}BpKX3RuqPd|d1P_lOzx`N!E(m8DR`T0 zR`52r0Gkbe*X9pfHp9NNnW*-g&E%6z{;|Mje*|PRc}Fd`b@gM9DET^G+M_u7e&g4p z2a$w7`*u4Fa*yg4plRMLB#fRoF%*1s^-{ja8k7G731<%@aFRH=%WEN5PU=a4s`Wfv|e?+bmjzCj=R^|r(Gi?#ur(BWm=1?9>agYa#5r*id3=nj)#%8>v&717O_LQoWv6-mn0CaVwR<= z9;S7aR~6F>$u4{j+t*-=lbL*FibabIrLYuSunm^k0UkIdJQSG!P;EIdzoU{N2A!4GV6u4D zx*GmCe_=0dDuzey)KD;27?!>?#Tqq2ZXKor2WSSo?3&W}9iYtz^tNLhMQkW2Vy@j= zP1g)}c}X+J960D3|G+d#xUi1?d|=g-Z`0T1b_A-9zBe**^k9)ou)BZS?ji6iF@J+* zk1b@}6Wv1d!i}1CTVz96s)RdkNA|+ycDdbG*y>=ruUYw0o8B2OnzdTC`;aF|;r}4z z-t%nRm-Is;Iy$Qf}zkHHyc9ro-Z-*3!jxgg18!A|fDR4N~3sN$_MZW$M( z<$CV=7%Q`;lG-RHmA>?RbXr1jyWpf;=tbLYdMS-!H%F(9;tICE+M~Xf=i^3@p+LTm zNl0~DTg3xI8LIQms#E#ITzks!#g!{N<-%FnZG8+%=WAMq-*CHrvRPzKa1C8J2^K)A zx76Zvjsoqx*!$L49)>C!kJhv!e;ZSjMSzPr%B!@^g2#cLA+Whor|l*sylL1y`7Zk5 zHldUUJK6<^!Yy{%ec6Aj`tDP>&bVX0P_pb&CJS=1))5clsbYY__vhLY`;+*>p zrFh-5dGb1HhdX1A@!r$obBL!89B7>X8Yti_=wXQBnj)L5RS)k%eyzr}ytbc?crB;S zrj^F8^k_wxQRKd5dymYR9yePU`-ynJQVqbf*)mi-K(5P1&c8V*G37%lUMU;dcZpJB zwX7^%qA8z$(#Pkb?L?d*O2LUh>731+*d-t^^Fc^C5%lX_AY<9%A)q=@^6KWN>Ea>ZNKBOR>O}ad`SHw7A`T63{sNJo+bW%1lcC>ztCrhOC$dJ@? zTjE@4IlBY7cZ#!m8|d`oBMtXjM9JUN_2>}Uy<$sJM?W(vq_W}{Qc7_$jwAfM;7`n3 z6UrVblyPe4EA`2z18y`PFJH51#Rz;Q;eCqd%E&8#5>i0Lp9|``*HtomzKH)TLJ$qR zFeRSSa6qZ9+T{iz2&%mp2BkVABf9lI=f2nHZF3p+SS#ITxS%}p1%Py9z^{%M^#<$# zkF}4>6~*1TWn!5Q2lv2Cwx!8NLWZ>ww)1|zM?mTA`bCB4K>5*aZGyT0T?94&T{R&` zf`h`(A2zE_$0ZATUFiSV8BDHpp06{Q&_Crt`U37Ow{6_+z6JzJHnPk!Q3(`wd-PcL z0DRu4t|0h$&L{#n<20YkO2}IxJ&XD};qA{H0Jz7KFX(Q2mCp-dbFw+fsYNz&OlxlV zYy79Blf2!OOkBKuSD8Xg8ro~?*|v9HBlTsNVBY=l4yqFKMuo}9%9S|7kNBAhVwvoj zF1ah6_qIM2A|@gIz2N^gvZmre`n@;e6citxj1Q>HVdzTpEcLpoJy@A&yQ;~aO<}e_ zYqPaVS~N9`!x7vIeM^w>v&r{CLEX9x$+Tys+Lxw?&g0~W`|`$j_-xmk#XN~8uq?C9 zoP`m#t=dFz`bxd`mFLpj{#9NpoG7D>D|v;Eux(8JR08QojYbds4^>w`jT-OKD;IDr zKLFeb&#+_f*1La;WzXzZrV{{y_HO6N`Vt~oFG{f4iC=;{m9EW}Cu(=@uCD7)vRE>G zs?>EIi^h~6(4{+Q4OH5Co_wGI<@OVM_xJ04sK-}&)_8;Q*%&f7Mq*hd3SX1NQ0)W$<$B#+2x_fJhvgM+If4RoAj@kbJ_$dqFUtD-nO9@t4_a5B@CP#f-u5^j zLOA6ZNJ#2e3Nv>G@js{SG1y;Mf!@U|?_}cq;#@aH%P!xcY`Oy#V*w6V zsOep}*CX*QT|!vy+?oQ<+4tGW+#(Hr^vf~jN0+hXN9&lV?(a+AS>kc|mZWoZ@Y@XY zqBKdDA!z~TT#nH8CzT5$bt>nstohN`n{*RhT|Q37(`xsjz^Yzm#O=vL#Z$t`Og5(! ztB*7p`@_}LY9)EcTQ0{uGwe(qr@KvpcoTKgFqmCF$Cv@3@y450(A}JQaR0N)BTW96 zzEHWlqRA^2k6yU8_l&w##0dD0o)M11tXd>$H{y;Fjy`$-MHtpSg)p=krzMtR$8f zB#O4&DcKL1Z0>#O{K(FjXO+i?SQO-ZCGYvO-X3O2i5HuRznFlC@48@EAaouGdrAc0 z>gSc02#Kya-Fx^?wjwg(4j*r^@??!3FdDB{Iael$m3yS9?jY;UvA`&@FPo`JGpli? zeks5Y{Ur9em)n~ss&p5Z3q!@Eu4u;e-7?}kKbmYYvO9JFn-ibCOab#9?4_HQgWnoG zc#JSxoo}ByXBn}vAW^I3&b0phx2lfp_qpV1QZW6_(_qDrby#*rYSHiIn~1kBoW&`P zuOD9_GX@c9{O-l7HKHindW6&X-ra2^>W}iLB$=qTXQ%Hp_qyzA!cO3)Lq7kC5pja^ z!_9t4G`!c1eody}go)_Kkg3 zd3t%lTusgBP`D`-Vr8hxVSzpxNB`)vyxpe}^g%b^@d~tCnS!of= zN}VqF=rQrW`DXW5#$$H$-sdM&h+@l+-VmkQo&wB@5dVO(^ca@8B{eTQb70jE{UPG* zLl^O;u=g(~#y{`+iun-s9v)}UaxyH}f#ncOK|Y)86GjHIaO7jz>Q`9{v@`;pa@?kPNb6$7&P}feN zb#^9I+#0+Rxg*4sNPb4`9XY#F#y&HmJ@edg6E)Zh;|UPvvL1!)NKr-Fo_95r9$kXF zTW;S<9#@nhoCI-Wr+y^QZC-__r2Hro*rmzzogTiI&pWacFzS-;7xO$?Vs(41;t=Kj zQ_PxAcC+xYhT1D0={!UU-ybnfw%-h;aM^Jf4J+}bQ1bI-`t8!hW-)eL^0!wj>@o z7{t*65Gy?(eU+5=l58y46Te_4ZFU0W6mwI_@e*(P2X_wc?|QR)@}3_Njdb~;N$4rp z4+wcEyNNKbYFP80b(%OZ&Awz^$=Yd5(xzVP!OwV%-2Y=V;jf zDMC$fE*`8I?FB2P&Lu1X9c*$fK>U-&50-)si!q5Z=s|e;-n|s5p3)wHwW)PaUW~pI z2UuXdeF31D8NvltLUoMQ87qVvd}uexP04@`rS4K7o4k`))oFim8FN$O3^ z@TLyi*K%nsSt4=1yDNc7l<#qVtMlxn(>4!Z-ycyNd54{#XR7nXG3J?1d605~PI>NNENKz$57Lw_vR zsEZ@ClmuxS@Fd~mnsDga*Osm|Y$5pPAjDP|I|_9VFONl(zReM^U9}V7DnQVMBA$`^ ziaZ`QWJCc1!?Z3x<^`oVT$enJ*4q`MLNr!(^cFwWeZBOZt<_6w!9mR>Wp?%{w6e85 zox+)u*5Z_Kin7LwwyrR~@bJX4M$l1cz0Gy>G`TP1#sjXE;vXQBzVleMY~Be@ZDsb@ zvv2zBIprQ<@+J>LQUz3Mt<{HQTME?2yvPv`Fr{x_7N@k?Oyy;jk={7`D86JO&@EoE zGbPFPsU^QUdalcUTF>E78mnx!1g-6DdhZ`&4DcodRwRpDR>qw@18o9QLaTG>rLZFoWeajfY0 z$;+D|#`ClR!m188z-s!jZZ*+Pm3tf)&I*l(2LfKe`k4U2HE>#8P6K_9l6_NXFcw)g zpgftbMVj~nA#9NR7U#bEYMd7Zaqi=3Tg01Rv)&5B zW=~bz|0+L*>qiDb3^>$+6PE&0yb5eHShbZ9nC=?bobFj_;TZtY))c z%y)F+vm3(Lz1CpQzFXJUP1*G@CGpgn$)Y7#c{MKy0Dhn0dHCb91ZcMRW- z@HtP%^{EX#aWkGM+r#w^2Z$5xG*S;wQuk6`j?VQe^iZBI(yS-P?B{y%k?oxC-7l1w zVHxsCq{7_(!tnWQFWFBuvac?zhLSr~cof_b?>ZAT?hj~-vP4%UTC9(fzMgc_+VqIEagmJRu5Z9r;jo>ELH#HGM{BM84y)C=g@W+p~DJufE}HAliL zz3o`J#tQ>6JDF2K@8A8 z^wl6QfB<%aFdcHq;0U|x8bv8~lm=I}qeK$YLTpb*rCUEq?|8Etb(o~L-PRk%eMl({ zb?Aj~WaEMs~SOyy5wEA8lYnk_uoX?|G7^0n&)>NnozqFv6sc1{(0R;iqj5Zb#1E#(rJZ4zGb@22ZNAVd}AsE_%P={b;{o|%x>}S<|Zz_ z-rB^tF1%soz_1_#%hu!j7;mDAy)rkjwe26VWzb2~1W`l*3XQR)PEUiiI`KmkF$a4s z^qvzn&MB)j79fKu#T_Dfgt1%RbUP~^Vb)%knGEpa2Gx`K<}mTtYu4Y@d`o^f)})j!Tcw9xwTsadN^$) zK3_JzO${&c0go;sR~{lut9trYx``Z|_EMujYJ~$WxWOz4y!fd*MRh+KuLZ}v=6voP zOoKpvPl688f_Us(lq5Uxx8_sPTU?LGlKyO<^-gPF{tO}NVP$MODtmJ5z^?i#?B~2( zOv!Ui{iom8Eq2-7nl-KYG=VfnoAgo276@2d3||y2{PKZ!=mCqJ8iqocQz>x358AdO zlcXq5!I@J$A0v38xDMC1JQ-5IGM#@02$Tn~z24LA8ivfd+Bwznq0*!P^bf&-Qre!Y zWAcq|A}Dl<&e2mz@DNdNSSGcV*~(5-ah<$5B3Z&ZowmaOIBlAhnE>9)`~$k~yoPuy zupNn$M|m}kR&pXC-g=APjaguF8pJ84tAq07mkwj}xr3G<3V^mT=JD1xY8V=IVGWh9 z9itrMjP?6`X-B*F;Y5tKYMax?$c%+1)3KNL(pQoO<<(s87C zgXP{suo{3Fg8Zn9M_XA;_AEwc(=8RUNtv+FA0HTTv`Kh##Ka1mI z)gh09gVKyN3|n%gv8sqe4t@Dv*`zQ0POfX?x9Da_8+%3r z`m%me%!yUqJ4RMjDGCS8MO3=Nj*UfrONoGGpRohr-pjl}K>_!X#;VyOV5K8Azz`2W z^csc`(T~Za!V~u$25snHCZNeT^_vMu{?b+g;zZ&T&`|_PKw*7p(n~uDQNU z1^%HUl*{t$9HYx!ouU*FrlXw5M3wxMF?l@WN+&~%3o~pnvO)fCRBX^lAk8-#K_oln zv{F)BB}RD<6SbV_mgiZ*YP#RPy^%Rj5&lEwJl~L~8t=IaRTcwJhGKmtH$&P4D$6*L zP+0~?z!Eu;P+0~JdednCMOn6d_v{;2d?|)PgSPjEER#0DqDoVOBw1Tw*H})Ct?JEo zTTr#Y7k-esTKiv;Fy%9-8{%W@n;u4%efe42gI?&_}&J$O8vI0smOC zDF#jv*zN;^xLoO>_MCNP-IIxFM>w>?WF3o5b$XmC_kJCGG9-OvnwNPofZQqd zTHcA2ThzrzSB`-AHf=TGVI9PWskW^+|JcO?DD?ELT25q0kmT+}Ol+-A%UDi_x>ynJ zbk;!)!%=eBSQ(sVBRsz`$+{>5(DGCO&`Lz1O#!she}oo>>^IZ7#GAu2{u3{N;BUN2hPqRT=}1f35E??aLC$>Gv|iqPE0liZ z+ncrsOi2t}_b0wp`m><#eEe_m!#`|d!XM)Y!Li^KxY@s#0-9ik{1ymIE08|lWpUF# znZ>J}Q8_?fl;Z-bb@}0y+kPlMHg*syBCQWx_TOtfntK>1vVN%@>Gr@X_$Z{R@f_a* zk6V;V1}&psR*}C3)vlD=WAaNC>ww=-`*C}}q3K&VuB&~Z#~`(j_}@YMMi=m>+9;TR z4Q^I_4%Mt2vSCO))orM^*!s_=|ja%pI25g){k4i2Z#Q-_l_@ zK!=^+MAH7G!;=3~9Y#AQN(nQ(9)Xk&T7f%^lE8QQU)QxY>1{iHAS%%P;gHgm>2u8X ze&qSp9-X(v$FCj~?kJ53N?+2`F!WH2z>0cGV?DPR9=oOh=M;KDC(-Ui`G9R#-IH@% z{?rf97o*RDQxZN&zKXE-uU%C?vBxtOed<^%7yiu5UY*&)LztBzEJvw{6Y#H0p>X`n zE{70Nm6-%NB6-}vHh=Ou%F}Jm>5iYv$MfSnb-ss(;`UBk^?%`g8wJZQZKhyFa$~YO zWE8>gZ|SJ3)Zv0m+llM_gS*DcrLcF%uXbZhdo$a^!gD%Oov)*q@19aL9990@lu~0* zm-6`g>-4L~b*7?JhURrRMF33y_GO0{{a~Ox z&e-0xA6&r=&>h~e|3o!o-j2X5BM~(Lxh`&%SQ*rUl#jQGwj9c7Br61gZbsIQ!#R#3 z?%I0FSTdfuR@;&9qt`#|z8BZDjDo=`9i3GQCp2RMTBjS;nJuU0nHFy7=1jCHg+1q016dGR(1$foDo#so0R*Htp9H4IlMKVpI^A1b;Q`Z|&RN z9N94Vls^r1M^O}f32eOrBH1VcX+(bYGD_O|MI&xH57QxeGu+75fj1TGStN|~^^ceK z8B*;AM|Sj=NDM+A)x?Gj0amFXe1Nl~SU=?6H8a7&A4Pra5WPH^? zbtK-yj>zx88t(k*@-x`!CwhK_>#$Cjko z=Y9CoRdM#=)v5FwZf@{6usx}0)0+s4P7EK2VNa>#G`cKW;4h?nB4#lKUM?zt9a*`w zz90o?Sw%85MbQgxEni;1lO^`B?8Zk{0iKS~P{7?`McQC9w?ZExqyK$OXE|`)H1v@j zH~@th;Kt*D=BcqrlxAk2^sz`TvRy+}d#9ClES@9GuRh-{Fk0-+jruej6xbvbb*K)m?~a;G{=f0dI+D%*#HGVgdT(lfbS0q3Ni3h zWkcIUG%j797BHN6%uN-tb|3%td^JSVp9ncYtPIE`zIy%d;5o`u?M*RzK{^`$SNPUU zMdJXzzqtvIZ-+mMZ^qx}Y-rau!1O(5C;my!UivpUyM+yjQZk(TiL*8TC}&IjHfKj{ zaW;rHhyM;|Q~0-oy!J~Uy~aR!ZNk(x0gVGf#MHlCAb{3nIT+>b)!`}_fs?q-Nx zK>hE8*t+`Lx}RtS0a)8$?#EBJN?p^ti-u} z>xufh0hFkI6I<#WRFX{`U)N&YSVn@gE-Q*oJkp3&vO)r$xsPShY}C5R^b+7D)f$w36~ZZ7J#U5{Ysz0>$e-!br62hNgSR1eP-hu+ z=#1V=LN^a5VEV;lSb0&cRI~9In_R<|{i+BN7}q8lu_EJflZd=thrAPm&-44#v$1Tr zN>vH|kE)lxzvg8weH4s1$Sd$s5d5Y|es1WlqPLut?_|S5ZK`gnl39{*(7Gjr0>)<> z1p2DRe(hQ2W9WJX-OYm@PnbaZ>e!%L#lobxQ~9k|=LF-_`M?sW`aj3X)OZG%s4p#t zx61o@g$ACzJ@>{VaNh#o+G1mfY_GySU$ZN%U&r3;Tr*r1Nyiz8b`?y>R0Z7st73-? zyvvU_5N^=+mJ_d)@CLS%LI(auN=iW5tqbijMyPYK7aqqfJQZsxljVQIe>hU1?codbjP6B2qnf28Mm=WZvGicW95@eH{>5CqpdVMEgll@*RzZ}+V!#R<-|a-8%W8Zzz&x4GaGM; zE!lq(TUX_P*wU>kYe_T;4DcDnt8L{RV}Bsn>oU0G4Rfr26)7=l-Wysg_jcx1oprY@ z8(G_qL`O$qj$f}Z;1~6uo4@mrqZWzE4{k}p{ap0{%?%1aP|=(Mg`cT$+q}IEwjsj; zh8J!l;P>}HZdBvjp@a?iWv*5jT6jPOj)Kp@;L{iE)LtCv%J)$s55gH6t2ROu=vWT|iA)CbV<>Qj8*+ zdp0Tv)3z~C8{^k>LM___5~IAJ4!x={uUgQVk-Qd76;bKn$Ws(B*pAVxHd3BDyH$T~ zeE@~%U497Gc^y6+v|6dFrqI6ipdb`9aj4%Gyvv_uy!Q{;W!df{+b>dZSi5SY@^koE z_^oTdYr(Q!pz@$U*h&GVcJBm1jo)uv>qY?b!|vD{M}$?iW;^*V2#7IXo1y zciP0YL?5-B$AEMQQsX<(6o9?O(Qzc(SU1<8Wq(tK2ySTA#iAPOZJotQ>T6!H zvse2V+XiWJ-ri_YeAfwDC(Vs+8U2WV`v>{dOW(R>_%=}dA8G@wCzaygm+*f@629$n z;}1#rmvFI=@Jfe6zbtVUw;>AkJXBk>6VO2~*IulcumKIdomy#U(2fFc)bgbIRJG(;L4*zg9W^6@P2n#v;J274s5Sn&@9>b*jzw<5m6!LOQ|R(`C}&k=x7uF>&Fm0( zhi9b{bV|0ToxbrpiYZrqDr7|k5ypP>R9=UP<4x#NF1BaRWF9aSJAem(|Tz-*q}ja+(M2)rfo(*dW( zuMRk6fU?!|Z$I^uvi+k6oN+()760V{XBben6|6{wp8%Ecp8;y?fD?Z-CHtfF{~O8n z?Py9d6)kfU5%$y3l)@iv-P8P1*KQrR#(~72A%#8oE%8Igtzm!kxV7=u8I448<@lvf zxiShdWzoxldjsr&gWw}uhb>`&3M(wg|D=fAJRyG=5tD*mJp**)*X3g$lK-E;v>&{-R4RG0LZgRkog4cO;F_}FEk?7Jow(y6zgw5+!bGF)|6qD045Yy}`BbZKto7fR zUJ(Ijj^9tO{F2;j0J$6cw+sG6?tk>qXz<@5cgRhw$nV^QZ(F4NNpi3KH^^Nh6t`+h0g< zwq)Z^6{SlmB8;580?WIDyxv*m2MMWj+deJ*9F(iI-BTwejn0|4Lr|D64eS9PK@jPYZk!y$}N#W3B*~;!TKF-jS&cxG*CCX=91JJCJ%laRu z2Efc)Ap!ecMBbDpK~QLq8(ePLa^_7>oco;h2(O?oQQT2|%q){W>5(6=ZXwd{4#!UP z7p6f(qEHJeH`B&uu(int;b#?<2!^Nx%TsU~*b!jfzdq#CXBz@TR5eZ`eWBwckYV^E zzE>%xu%%;zfys%|#0);NI~ZI@$CJc_W)m6vg++Se6jDF7j~wA ztuSuwg5z?z%gS)C*lGh?5EoCK^5LP;z0-VzPJZ_bNT1Dr3XW)b6RH)v`1I-w&nR`` zxTcO1e{4u7soV^v_o>$+4$2;?Eg*Z;fb3x@6I%1P*+VcB${t-l!zTtoe|?4?>aT~E zTl?{Nq>O{?(QL~_RerEjkYAK-a3Xz&rKWtSgrMv`f)TWlC4-=Bci0pdlj%>=J=&La z?_^YA z8tfkdw)yVC+g2}oxhD6-qT}b!ogq4XNreY2oA+;B1&#X)s!5bc$@oH~3Igpb=5&sC zNwY7MfhWs-1x0tLZpEBD$HK3-+h}%kySWy=ZTAZ^*b=+`9urne&7#oI&|(s*kN4g! z%GESpdUS3kI8=g0@p-1{(~V=|^}}NPeIg7T7K@?`&7V!7m-5jLh18=fnmXhBvEY=r zGc}E_kItbm&~RKCbSDLUoy;wpm)t{nAA;-CS?FGT_MsX6mz5zPFW=#W@33J6Qre6WGs{O*VA1YMG8P|P%rV(;F z8RTwgR<+M~MN2^LBXo8?rNp$gn+n7!MiKqS^)i=hr2G8*rk3xQNr@9D&7U)#>ZX7tt`C4IMyLwXR*u~A`3BRAzF8CAb3JeoQcVf$);BF@nyn5M% zRa2WgkoZ0jI156y+%6Kt~m_32>BjLX)X>iutXs+4c>bE-n%bny8;F=-g_s?F*% z?O)jh28?SA&Fyl8lJ58@7{9k<{WIPk*)Yf+ zUO3lG8LpHD71-K}wpgwJwBM+*{i5P9o?3B<1%iMuD4n% zm0D*udO3T}{_9@O?Sw(7my@p|V(U5c8Q;rkvI4!Fk$3-2FGmDq1gMwOWc6JyCmibK z)WX=+w|Y4~_+HMjvya4>)C+r3;5P4no}$2q+dX+`UX>FkKi3FGZdkV~@5L-_T8+li~!%9xq6Nspt1Eps~k-$=iKgTVszS15>?V>~XcjX4g*a zh}p)#$T|&No$3ao9dWTeSb45a&YO8Kok{#SW)FUj);mWUY4;m*v?g0~w06)~|N0!Q zR}OxTmiLtK-6?`Xk)i@0N8Kl{)C&*vQKP2fOI4QSAQ$5H%&T)(J|T1}QI;ByXjJ^6e5dE%#D*%rI=Uua*m z$a@mqzkuq-f+2rxSi?^T;Lw0Ieqj6>eqdY&g=Wk4j=2@6l8#5c4j%PhSosyRj$gyR zIdK#ATIpM`pJUCQ5KJXLPFc#iy)w~j1>54{`1OdHtCr~Ev~^Y?^8%LxZQknV&U~je zRM%Pub{}J?GZ@BN(~c6!d&RKoeE4~l6}egJz~!V48u6qfKV6?=k9-cU^`@Z{7q&48 zv~MY^NDpxm=yl1QLdVLKc&30o7pFsIOCyb-J@){!)8wNomr7_Zf=dIs7b(*eCF5tO zJ(6#MJtv<-P*@ZgL3@7CBH|qRxQ)q$l7JvZ@w{WFP~$dSjF!&V(z{iQ@>=LGR9TgR zw*n{=g=h{Y9{K57jy{sKux+KVOLX~5;M!{6rPbpjy|Zstm&^)RR@Ow9BUfll%x{dL z(_kZ{9iWq4(5Lw7(}3L2(Jh9*Q(XH1b@{!(u--v1tXFEd6I{m)pgV=ZP9yxV zo)=OL4C@^P!+PlpkMXa1q&tlqM75+5m#WFg%ZFlCo+zjh<(F?79v?x&wWPP>DDi$Nu^4k$9nDnXX-n{hFr6PSvg(rfLSKuUkq>gij468%mejI*R z7d&;S4!i@Co_-0XD3k@>fnkM@xhW)dimjvJWi$kfYXAzbAoY5x*(=jL>V|Q|xzYil zv(P&*rLzcyF-`Z`_*SEIL8H8RtJE2{2g72!(W%b;wfUbD4N6m5#!C0?8uHd9_{(&q zXRXeHoG|O`IbQv13Ds>)!I?(JHD%TcNk%) z^!XOt_fCrvt_0n8t~@WMOs46^=5<@$Smd=JZR7QHtayJg4=|0m^yzS{%CnY`%t)0g zvEAc3snVP;9H@mvPUV1^8XXBQ`FZd588#g2P4}N22E28WFJj@WfPleBRmx1knBntg z-r3uDZ&l&F#f4%>@Pg*YbU;9sf|nW6X)c26Ds(Rrrzr}?2c%B&v5ijuDZZ{ih)`Iw zWy5sl7BeDMq(xZ0U=7bgb>iZBG$mBNPP-Az8Lq;TaH^tWDOz@^$EDAoyy+se6_iOa zU=L*NY3L3LA@y49rQyhcF&gy@ZX2)bS$aT>wYI*1C32{Omvkt>%T=dtjx%~S?FW}s z19U&pu)p~eBv=m`HK_>5orKJo;y4TmR-GmEDR}DfJzhv-UAeL0H_QXeUBwIIg^tq^ zYjbU>Ys>vDYu&XwI+vF`3)zE{M~*N=L|uzh{T_&v=ed2!%L;v=!Ou3QOLOD%)WUaRjLf#1VYAS_}z) zgCnq%n;b#7#Szu~x0JoPz_#l6fNf>z$R3}qaEIJ;L=w1%^V&v$uZKDQo)!SYTr|S~ z@Tj6KY}BTu>0F9Y5(?r`Ia@rBVr-I|Vc=CTr7`d-m`c9OMqFQo0z60(1U2+3n0%6r z29VegPgS?TAQ7@oUl<$Yd=zj_GvpjElO@wsHuys(%F>Y{qQ7?y^qSLd9WtA+5l--$ z)5$dP5t>m@$($=aF_Kbbd1DNE&B@jusOxm_nv)KA&1s$UjzQ$7eH0KL{xzrcW($x; zAzblk*>0hJ3aqZj+e;@<#VtZT3Ktx%(oxVc>IIy0IX(CEh4ldX?p~w@f@$Gn?1ygH zrgKLAYtA|M8_pSE4uNoE(}L8rg(c&1%W{n%+}J2XxM_y97-E!uomNP^?7nj>Kni6tcK1anCpMG(y8||8eR?x2bMZ!CmveB;5nZlcc=SzTV40}QRNw_Dk zJmW#S*uhe;XCoxU(0iyVupmcgsFRQJcfFCc3g61a_#DjG24$55l<7?F=pCCDj%FB? zRpL?jtb)r`8cq3i4u(ux&%vXdoU3au!=w|BU43z9P3n0fd%SiLW?5BnHZ~H)c1H8C zo-j3Gbscg3(DgHWKNUtW8z$f^FBgwd+}FHHhq`00wDbjg&lkComq3J8LlN4d!W`E+ z?39i*?SR6wUtt}G^IN%S{R5ubeT^Y%Z-V96V{9^WN2x|rAZka$AZk~!#U$7$W9xsF zk?55-Gt%F9*oW8BE3A{c1DBoLO8!9cVB#K%pX>mC{{N=@lUEi9z8e`*a(-O3qV2qPcrcJqtvqQhC8lJLkRt>q{P>Tz%k5f^mR9cD$QDrnhppSc- z*mm3m6v67%^k~<*7W)3)3@IWBK2oy(_nU$%%}tzao4#eQWn5^_EMmSEyozcq=XDsq zK(IIy^G$S#6o1>XJ2lk(|v2%L`m3g@h;O^XPisYOK~%W?MaRHJZ< zA1uAPN}Cw~nfsEsu<}_*2@C)xc~MNzRq%;^F8M}mpS6LpxHs8!6*@dvGK+i6i_upr&9wjI)&`z0~cQv zy7<61$vLi2kB-Nyk38i9F2D>yAe`z+QwFB|=|X0gSyN69r;M_C($uU^pYGah_?cGh zn@(Ai1v!Wmw$8pL!N}E9*4|z#B8{LCpWXu|Ulf>p<*<%v(a)J^83}P#Nj*^q<_%U_ zR&lI?@f;wa8K4JekuZ-CmyTng!^L5xfWHsNCYes`u!oZt`r@rw3T99K50Y{MTkvhF z{G}(G>nFfE#IS6aLz+CA!TYNwt;$xkI~tz}!Z4BpiP4Z70Vmr1;SlEvxry=Up%#bcvSzm#V=^NEkUX$4VDpE9~c6xRuUx2au* za@_A`mQHZ*g8+johp@>YMe2*jqsC8lS%#cJ`+_xFR*_W&gHKc>z0mltZ3H)#Y zG6If5P1Bh%Kt|S@U6%72AO??d=UX0==$HnP6w1yitfx6`lnX+3|1*O_3Zqrb`v*D^S`g5p0}Ar{48^^KFfA&DdR(ZgIde>p=xcxp1v%|K zQlTzjZbl@U`@-dy&#HhU$Ti&mNglUDt}Wv24!hEWn!DfQ*9`J4v5ALu>a?&%Yb2)-T|~B04q8!TItazrd=NlkIUi!!jA5TpxSDUXM2?@RJc>e$TLN zz{K}h*4d0G#AGqg##^(&mYiQ_oMdK?C~$x7{TTPH`<=LN-SL?)`|C6XNW*pK+Muh@JW!N9@A)b`Y>? zp&-g1@d|f&in`a_lEsNr-z|px#;m*zPxjd{+rpNZx*vgSsr506M@mE6n zt^|ovwbAT^p)1u$#`snR;W>=SD<7p+*O zPC{9ewU9F^JjdcB0%Q>_%?e3{a!b1kWj-HTA-3znW z)Y$D8n~tzGi=(%eI%vTx_Eu2v+icC5Oe=}acXn#3L|^yQI8Ynk@N8pUww#?-dKg5p zgU~eZ<7F0Gdc)PD=Ew?A0H&<=7*+Mv#L3|J6*%)l$IqE#PZ>Ersd^|*XLxTFPQ%z| z1pO0Y32lgLl1 z&QRg#qhozGI>D6WR$5R&{uF7|GJpJC>Gk|dh^_8(IZ(p!WVRMUh{cI-*bdewVOY{N z3F5#}i4O!Rkjao&Q-;$DF>Z<)0`4ps3{KmBf|g{;+1q=EpE8Pc&~m<`C9?(xD-aOg zX`wii&q`wFN3tPNBqUpM*DP2fPOBEv0@9@2;vk6!SO@*j5BJZC<2qHq;M|k{F5M3c zXAo3fBO>PzR)I6QToQ{rjNN`$3!>^Pa4kTjiCufmzEQUH*(8k;_=+I6@s z#FvH(7@bo_aCAm##em>~=1#n{YFeD2To&ti3K&sZMoDbgW~YjIadn^DGbJl5h>9av z)WDM}Ek`K;WPgM}c4svb%AE&5cKzIPgIOTk38^?(q}I8%N~@@xnh~jV61;#^I^E!_ zpp2P6w^=ir+oW`vMfyx$(UZe&P+Fw??k_|LXX4Z838_9mx>bgepsHwIF8!*ih`UnV z^l$5qQvQUBZ$^ZP(c92gE9h@tccpBkse7c;Hc>pY+`Od9T_#L;#dlqJ!(elF{Zy;a;5;FZPIo1$d+Je1ZdkUS?Wtgs^jU|9)i1ln&{7Q`e1eg~77 zWz=7+G5Mb-Wd508u3<>~Q)qs+9Yk zs8a4{QRM;(JO0_EltRe5Xz&x{k7lOlmQ*`gqIy@0U*;g|qNz0YVBt;emnkiMZ#L)# zQ*CNbp>XWg8dJRX&^ogU=flvG_9s0!P*oFDT2-FRHVr8Vp zlk5{$s_QxntP0X%3{r$Kx9yM*tYjReofvfl`^IgW>uLc%ixkhnDjZWFH)>lElE?)? z;x(|P$^!BWv7mN=oIU)pFrrT+75}cluJm{8aOvN)!~bkj z_{ny7_g}QbIwU)ssZx)2{FmEdhQDoxWk6vjNYFu&{$+L;N4CR5M{{&Q9b$TIE5ouL z%>f7uf3>uj{FIr-v*?M6&7AcvGg(Yu;Q3+G2-H7%e(JyD`Kiyi=-+#O0GNPFBYqA{ zfO0HOH9%`oh(SA=i?8Xu-=K7W+?tA!CWqw{^)^`F#|!OFw`lJXsR zgdj%(!Nh?AdAspO;#9Hxq+spj!rZl*BK`>XXVdt#pqaaUI-ve zP~HAZ3at4>gY^~&asg|O7mi$Lz|==lPZ~&-0ZpIvmn(a&Ar9*A)T3`*xUv`-xUVu=9#?Pfl={N9#G}W1MyT4itts0*m zr(~`^$7MGB9hW)!Z@SF?H%K{w#ed71{mBG2Qw%LPTMP~KD(PQV3{93`q!>ExFBU_C zEOc~*I)2X7p!z#mXoJ6(g--itlcE%pzB%Y5739xfvBeE!6xkoFIs4b6$ceKkGE#A} za1{9`OALP-MXsN5Q2~mKB*tfQc?&|3mB4Z+@-octP-L~=F@F9(F@6g|k&VGT^^4Vx ze-}lDt3m&;MCO<1B)QlaOi=$Nh1?qg!u$ivLZ?GmTTi9HrC!s{i)BKM!OEo}avo$k zuC(~~Tw*eh`mAKi)&HU$23Z-hiqBF5%1)Gi#|~fmn|Am=OiC3|zWU|h2`?ty;dnuV zilv;-z6MlZpkej*sv3$roXN0c#gYy0wS-vd>G4rwN zb0bR;aEb&`kx{DI1!8~Zh=kA6&Egjjl^V9kz*^|QLr_E+uW_8JE-2hiVA!@q$J65id=s>D4I6m z8lL_{h1;>N;g?0zhe48z3J15rMAjeCih*~xw1Mp47(n_DDa?SY9%aFzR8W|aNqjAf z>s<5G!i<@M;8+c?w%ZdSiChrOV$^+AL=oq+#YSQNz6V2|U<=H-Z5Y6`0^2Z1+nl~a zTFX2RDyGXgg0zTZn#9qe>PD)RDFHi)z%KKH(-U~z$&|)k;`D&sPSBE)#jbftMPmHB z>AncNse&NlpoHDJ-cysz_nfK z3!%5jv4cGHr>2KD>Z4XxT`!cFyh_Zro$l_AmXB|oG}7%YaL?*!!cvvySrYr6--U+{ ze0~4m?kPjqi{|r1=geHk+&r7k{g35e!E%NJbrGd`V@ta(-I2oO$$Y?eHnqNOT$hq3 zkj*SVEW^Cdv~9X&Ft1iXg4m=PXE)h#C8ZT@Ibvk>46W||?DO)VdnWJprAh3@#wlv_ zy+4D0s3Q6Op?6ZUa4$=j;J$~~xpBrrXI!45s3typJWUiw?~uE%b?3{4W)-LUs4!3w zA}kBK^gUAPW!X`=9vrP;FX_tlxgXbGL%Q^xG?E1sArDjK0~`m!kct_{iSkGLG@a^s zKR-?C9xYraAQ_Hj>C#7=YW!wACJRon-BYsX@ROOtO7SCIzmfW z24}pBj!~hl>IgTe3vqLetcvx65x%`rN0Bp4Nw#1 zB0@n(xq&EH-GLg2tSXu2$!e|&o0JyCSWXzF*QcS5DV@0*)1!DL=I)&1z0ckEm&B{} zuUzRWcdGATJY&^x3J^bXmlBngk>@b#Irq#n{c z=&BQjn@Ew{Gw_);yR*VrTq5%y9`Xw*U=^TH}>aeCOp$_%VREoeny{gasJ3i!L1+nErsRW0ea zI;Kdhx(Ha6rt(u(_J|N{~RmnB1+FOJaPZBBonCR98 zkaB01l(z3k;m0KU0aC&cQkIZNQ3a$J|B4jxT1099DVbFzmRPkelGKn$5x_(bFMyN> zv!slCBgISrW355J(QCY3m-ifg`K5%T>v@17)nX&PZ7{8`z*FBl9K`0i9t7TZx%X7pDs6CLS zD^TsR8(Z2cm}M|H^as#$fGOG;P;|wJGk@b*X0W10wg7Y%a|4~lPO3MWohxjeM*h%3Jg||j?4NhF1J1fjf@KNH@gHWoAdV5;*UbLiHXbMF3!O|p+ucR z8+CjTW(M7$L_jwvw~F=PkoyQ=cV7@x!Gb;kABZ7UNg5L*`9&h$F89w1lP`!dewSgs|Vm={Y#U;FwlDWnM zp!)AEc0CgX%k%x+Krc8Z&^CKVd&tKz>Qno4m?B!1#&XgMwDVZN|6MEzkuYEv~8~Mx?VeI)RCaQB;6Z zu>j2F^H^wF^?s67lr`7*#;O2(|4YSXC9EB+{Ui?sT>FVgo_|k<+q>A@XZtXbLSAmJ0wL7>I*WeEx7a5GX<*_(w}Ca6ZlHE=ArkXpR$|(8W+kTHVpd}MMtnLln*H^B zYh%SQ>}+%eos~;x#dh`t$ZtWbsXwK|J1lmfxvfG1;nO6-{Ir26-sJ^%OPvo@U_mM2 zpHE-BN0s-V-Up}8vH-Y_*_kBGZD?y_Iw>4hCdt#Zi!aORe~-{iVgCn(rZ+<`;e^{| z>*PbJxRHV_6JL1N-kK;I>@8@BuQpgu{l2&$5$t8Eyr~^c`K_S(#_JL6bUh)qvqm<6 z!P}rMDY4X$K`efk&A!U@6&45TKXel>?o^v7Bl=>kG|a%_niM80yFLdLO~k;@7T37J zUVZYnM}ebkvk!I#X@i}xK7r04`{>zgExKcJIjsSSHQ4?sY=P~VAJp|xCM%+&zgxwj zRU|t$`&t7GT1gvNEqlgKG+sS(pynKJl5+q^To&vQjnBO%UIhzC+yELrkJ}O34$|+4 zj%5wN<`*QlLo7aktnJV+PgkMR>pRVt^~etd0fqnCe6=>Vlwdnj@(xsxkew?fNj(|h zSq0S!?vvK<%)ktl8tP)p`7s)(PA32Mj8(uiV+U#!#o|G9BMMqAnu1n~ByD{h3caec zp=>XZR*NE)PN2B(3gZ2U3BZbKGIcfQzFB4#E29)O^DgPb+>jt(fnK+PdOi`7pNG88 zQnL^9AEbsnPt01 zO+n31O3=a1kyTn7ll(;mc6@2%d9Gpr6igj>zK9fGfsOaFEkJjWc_u9-vzf4>(E=`1 zAcYkH_)=~cCzP*&Jt!h+L;E+dAm03+%@s`k?=Ej<5-*Soz{fRMbo2Vu;7UQaI}}X- z=ytbH2&0j1&;}OB&g1W>egNI>NZ|ycPn^l{US~$2u}^yjEan@5#eCPgrgB)^ezCx1AF{v&aF@jm6!YN`x!H#S@0Jx| zG_0a`t_ngi24T7er>hohi=lqo09&lai;(npY;or{dmUggdov)+zzki&u~I`5@{B$i zcfryQM91IT;_Jj5wE*SCxxX~U!@v}q1mMNzm}2GMF~ze^vKU}m{X(5&U~x2iGlnZI zx=}w`9Gl;^<1O7iF1)>+_yXm0N&*c^WryXC}Z{K%nM> z1q2OXzr2#@c|)0BO;N+-DQYrvyJ&p&$zJ!%XLuZ@#^B@aw}H8al!FP2U!uFQRTN_^RArj&+C}03Gwh zhc5)+*?^fDzXCeu4Opg~3mHH<<`saBdBxa~<#zji(J`+X>6j-9J?lUE#muvQG4LoR zz8JbOAD0H$))a@asM2z-S@)B40^GiRLeL3?Zr{40Qo;pnIV6efgpOT+9rG3tl0!Lu z<_Y=Mj?g;8+p z_g2MuF}Gj&pvy@<=-TOq-2wP-BGar=@Arv>*?;#6q_?RGN^hUYj6RW6e3lyQfauxZ z@FYZ4W`er!Jc)fI>HVW>lj6%+)&A#_LN6AdugiEl8>msYZ@l1&9{I9t7OU(_(TAiD z3b?OqSERHAn+DJHFJ)ovx8b#;lV`Si48o|2UX**K1v7N9s0ucRh{i|wgE<%W|FHQE zqWF3L4+NrkGO)SK0R{ShpfzCs4>xA;?odJi{sXs5Zd+A;1T$onW>zZz-Dt%N8tj_G zQD~33C?J3UQ8Tk9L8Ujtja~*Ji4m9dnUZYHdrvn z4v6Oe7-<&#PNaG4Z$_HGNlN)Ku)DK}(2qelkQ*3;Z|kT+W=xP~JT47#S9|9q8(=yN zNi)`g_Oe(7zzlPZV}uMh?7(K2W^4oX=5DS5cx;Wu{AtEt;Q@b<6nWMmt7W@fMCAbd z_qCT!g%|At2mp{P2@Zh0OB*vl2apBG@Xw}hJ<`;j)2Id?lKcl$i-T-yKAVFk(g5>Q%I3LZ=SKvV&zqrOf~ui2gBrLuDdfEO zcUpev1kmy*a}5qchTI%2kNh1iFZzkW`C>}SnvKp$5yAY>EFutL*@jLiCD8te2n0m^ z1|kp;Gn18kPpzu`w#*wW$_)hxEO6{tZWKw;0spw+W2p=xR;At)B99LZ{|BXsvzn zBs12up$P4-jQ0$|Lt}a0Sqe6G{*hC4~Zh%URH6C<1gD zdZr=?4;lEnQAV-~=`wT%`vp`kJOQ+FmmWhwzl9rYL)UCAh)D>28q&Od(K*Gd6B%i} z;**yxH^Ev8?PHo}ykhv3J!0<8Ir>0()Ftr-;7N6zbq(mOs49xWD#YaHmme284Jpz_ z?ZreXL5l8!3LK7enRe1jlJGbVUsI(euOk&WUNJ*}BDQLAv{#8TLXlUu0!Ov=UQ7bf zBVHP#f6&V-pg{^?_Wacw9^Pk4p147;>|ZRv5V=TA}ob42}WJCiP&9e zFIjEWoiD7_4_yPIs$r$nc2E#-925k2RjdccnUC<5|Ks`wq#%IZ@Fu8~k_PEi?SX2f zQc8OQJWh~nfOEA@~wv-DdR zYbuY?R-bIA2(JV3^&7oAg;R71`K4G!#xe)(wWsT=%1Wr~tEhYwCR>w-+ts`>B}OF^ z9PLNA5{rWNy!Tx*xOa(7@xex9NBAPREzEmY*AB@9u)S9rY%sK}$PK(>tv2p5Qask= zZPZc*2I*L>fTnks^hxd@?Ous%3JGaf4kc_p{N0fYJgbB;ThL-CL17;z&H<$x9bdYO zi4lzVk$p-krOVZ<&dVt#fUNU8EZeTtbi_s*?Bc6E(DZGbSlj~m2+yQ3MF+h!8BPj> z0(5UG?bVcilXpy6K0#Cyj7+olk1~x2bk-**(D&T}2pv_` zAF-w<3!p%Ix*-BBiirzffIuGwqeBwti0=ei6qEe?>DKD)OOKzxSZ*ijmJZOZo?q%# z6C|Y^kkVaMU4u0>LP+^QB1H@nm%IQ{6lY0E`HmDZOmYGsB@7{jgG9b(`(U~Qs;5$SL+R$ow;so*irvn5#JZMd4H{C|G8di{zgZe)ee>;Fc^8Rj(R5Kjjer@u|rPka_k7nP-v_2@QqT=0lH8w7jUm#-b;P~^^^#u9m!*#0YaHK2Du-E#fM`oL<{ z1ciQd9D}B=VR|WcbTd@9eh|obx#I9IRjolFqmTgVCAEj9+0Lzn$9DMIv~_J0X-Bby zN(@MBBBn^w8YVVRAQlRTufFEur0r|HjjOsN>93N)llAW+CG&rnlrR#1VGeeyVWBnfSNQDv~c+C^qQz~4}e~e0`%Iy7=eqqY&k%O zCcdHumPxkiUvy~Fh8>zXv+@Vos=@YMIAr@S?SetJa~?+hXe`syzT?UL`bBakkgnsH z7iwBumYp37sJ_U65J8CN)Bv6a?##wU03Zn-nMabDMPO zzog6=7&vLP(nwEX4xJ3;SLnxuPS!5-kp(+BqdR7eA8eMl5OZ7u3V}%G*cmAVBAMgS zG?f{1?8BKgEtDw_GSKP?PuFrCS5oF6dzvJF6M4NZBPlJ!(f~H!@(KXLk_mp_k9Nd? zQmLXHPM}oE!-zMFzoHqI-^{O4oa|s1+Jv!YWb>^An@)Crfh>L>)LHiQ&y2^53=6{lpaj_L>9@)8`I zLGczlqjS7r(kLw6(gte{ioo`~q!8c)j0JL!LZ1Y#HPDXj21S2lZTfz0h$hbsXA%I@ zK=Iagu^Nw$9Ou*nz%12&{5zcjS_ahW`W~oO(irZnxS?i(0S>m0im7l+3Iwm`3z z!L7(ubRWYsRH<9tuMx$@d3hnF(kX{fp zg3Y%$X7q`q;D`qr`_lBIubF~=$)zgf^Hl8&(RAx1ii?V#W8qynkNYJWEq3l1wk)xcz|Bu@DRO_TNrwA z3bEk;y>Nna_zZf{Ot>T>HG^JoAn1jjlJd}1D196naVx*qt%xF3Dul;81*h5xQkTn~KW5~p~z zIX-dp@A$-tf6pg|q!1&z>MYqs;_emSx}(z^K{QNl|^IMP?uKL5#7r zVp4yYt1V4J8+s!vqo%|`A^JrL*cGRoj@~fhUF@v2A@z~427`>p<@&gy(>J=Xq6dW< zM{{$!UtcQR61_xwz%{<6bK@%Q*euW6T@?e`6UA2x1MAnXOt?x|>fwr9LmRb$mC>1^ zT4iZr{?;oz^f&#-nq?W}Ju(ff6*K!4)moxUUE@vBH;h91w?AITDkhv2RWtfgDtl%1 zfan?z*LW84uQ_pB0dY5vVpr6?WsG;;UYKl*|IB%CScRF@-^9A<6Gm%~wtK~*gt2_( z%jh-B5|kRH4-a=*BustTr~S_O-qPw+^kP5(`2oKXmrCdSszf)Wy=sb{-VUvW24qo-CLac`|z3)+>8VGWdO1Ytz)d zpHft#!1HAF-?6WCEb%y?w7jsDQ8TGx7j2=c%@R;S-9nIv3*@NPbdwzJx-0GBs>VUS z+_!;(kE(`U;Zee1l6F1K`+wD7S@(xKa}1#|0y23|p8P$m{`azb+oUC&?`sq^E^)eidcKl{dMHB0a z%F!s(7Q%TT7kbt!BbF2b`HB+Cdhx;J@NmYuCE6{79Mb5VW z#ei$RvJ@~80yE43RDQ?WwtR-+GB)RY1~-2;C^D{$nr}KN5)@iiujbYcTL5d@F(qz` z5d+bYuPpWhYYk`21qLC@p{shWXODJE&o^+$R84-i#&XxMwqB4K#pO7Po6 z#c$RQ5+i9rIHP9wtYPiQ$A5_<8L@3EtN+79{YCb%0-+*LIX@cw6fmQWousu%yAUPa z)E+I*Q0OXP^brd97G)rLt^!}oD5?o%r`dQGFex5QF~pE8n5=MC&FrKI1ix548pY|6 zG)`%2;+T);7#Ps*o_`twwhvg=2(jvy{dcAY#m)(4U8%F?_)kdtpAOd}fd;ewr3g`G zg(3ZST1ZoWOTOLG&CtqAy@tkA z-lN;?&0b`ZT$#|;Nu$kHB$Ra`8nwbaK|Sbh7l}rDV7E^9XtShbtgKG;`=hS|M4#0k z^72SnbiVQjM$NE_@Hcg%qCoC{JG~&;UT{@g(H;Zv8HEeyecK~ z#Wz^@j~5dss`IEc_gg!-udkaL-4e8Wvd@{JSKM-}Oa>p(tK9~t`b4qnM8>W4MI>Qt zk`tnb|7K(yIDychkTv9|qe_ur+7kWDRp9dc8e&Ai$dc!%v3!Pa8Un|o;1sLjkn86F z$ZHup5nGN0s>pCuzv5uNvVKzJZsDv_;2t~X`(6QRTQ|yW&?3Y5I}UBw_j7^oUvty` zeLN-`l1$4$BRi3Gka>rMj067Q^T5f$7J5x@Nd9c5 zIP>07uipws^hy53t6sjc(X@rpbx=q%qocV)?mxo5=(eI^-xiMp>1@aUeKaSOr2E}a@?+;l{le*qu#VaTyy7N(5-b8}%eVC6HW!B6 z*l))N3R^LiirZYl9AjTm5KDV-AN`_S?27enM{iu=U3?ovnM}^Fl2n$)wK|IcPj)nF zgVLasihfemZsA-Y__>Z!4}swK)ve$$*me>K{%sh^?E{e<>DR$@&J;~5OO=33>_sBE zx-?A?$u)sU?n>5%yKrt;FRrwFMH}PAVufwILmT4bOj4qr7cTE@m?pGP^|N%BY5IoQ z>^PUI+hb`LF`Of&6Vc@DSa!0zZ2KFzyaJQ(0M*-3U4q(g%jEbtPGL6Ry00HGeCc6A zS)Xy!3xx@WAaEw%tRI0Xd`I&)UFzgJHgF}H&)hNMZNtnR19qnyAP*Tu9wtB} zatbc}r>B{Ym10HJJ4S@P9%qW%ZW@@R92@VFamq`flI@Xa7qPOLJd;UqWY>*%*JMIx zdVcO2>MuSWNBZ`nS3^=>iTDDC^O`2`tJWR_@&|Mpmj}DpY_ab793BU(7%jWyJ&$MS z8DGPDOdVgDE9FvcXtHEABR1VLNx0#*>&8TUL+5%SE%R-L#Lo%OH=u@VBmy{$UiU~< zPOqfBxGldcDdJhKRF|)CYpJg}argeEX6|w9g?wz*5xAWx+3Iz67}oE|j$9 z<7X%``jjsXHiZ_|JHA+REo{^08cEz_&%$H(1;4=#BaQqc|E4JCaxA}{;hZS%j~*7e(MXD|Ez)on+1)VzSBCUu7L<%c!b z%8;=*{GnTNXY~fx-gAKhzcoOn_gO!98^1qBhGWeJgd<=h> zt}I*3no=N;^-$phI0F(5INrY~A5Q}=xP|4TMJC{J!SWC4ChWVctgNd(4oQ8iFB~2{ z=t*#8zhvSbHb!s_P511^j#?xEkuiQj^->?OQC-qt(`R6@q!7l!PoM?^#*v8CF9nPX z2aJP4CA+5(xwBlTjt7b8R$|+|OCJ7Eb|m&fcGbPuf?NTzzRVK&*+cj<0{BLNbTO-N z4fqNoNN3WrK5Y41NtPaAD9U8%ArpaI;+yn9A`t0uCEqYeI-T*!fx=h^r!k2Qeus>q zJQK?ip(E1{h3+RmLkV>sGCpwjEu+^Q(h<54Nt;7LI*tCO&r;;4mk-_LKMXn6N<0D> ziF{R|40%ctTXy-AuZuh|nKHYruGKG=L$;ep|0%Ixpl7c|9%y86Bs}wtz~EUvdq|{t zLgoocac2KazOG4#IwZt|UB^SLgw-65tOPK20hc_|NlLCYEVri+`Hno0m52j>Jcl>_ z_FHHPdQ_=q)!*;{qSH_`;)Y0)2p$=^IDBODap_9Z)k8&QJ_nNpuq1p7+_`S$X%-#tAvaL6sqw|;*SL~zM;zYTwHQ4?OWo&*q~i|qlrL3Dio z$1C_hgNA>~HFQnF$2AGaIhakA{SGP3$k>TJh0w~6aCkjb*QY#3x;}LxPYEkBzrX>X zIVVX3dD?-)^CzeO*xyZwBjbf|^h6L&HAxo>XJJ!dp_F2m&nQUDHvye{3S}rp(0=a6 zB*mKjbZ~+dOt@ve&;5~$|3~jS0IaY!^a89RlzLvQ|N7oLHgqGk8n%}q&pnjNoyl_d z1MMqD6@%J59ZT4&oNVm2*s?#GeD56@nkJB}C4UL$&i<4Ie2F#%#WVa;X;M0O^vOuX z$6H0$j%9DBmY}YeOFVA0JuQ<^w9?5qVvIc;d=gad6niA4%!OLb(Ktfh5T_JUt1ssW zKjKK%;`z`m7|m<0s$$V@qp5#&dvdc8ezA-ZE(=8kueL`9TrI%Xo;?}7F(timM&2Zn z-gqN#28ypmEPLqCV4hBYQH!Ss!}t2NQeAgV%Xutaw)clyCyj8u+Aof!X+;m?57~By z)OIMS_j3a>0!d_~BV?2TGM-tqPidyp8zL8}LN2mR14{?4YYaXb4pa^&E^~-YtxdW? zqt-t$9C(gfAt`&E7UhTT1GL-W^NHxbEW1@I*()D*G@!~UU469}{Pl2!H}Ymb@}^zc z2v;9>ClG#QHOZ6QY>dApZ-gU0h^i34Dozmk_@eFveQ^`o*}tt{Gg6TFTB$kvjQ(mG zHOG-|!6i7QW*f1~T3S5)SpluVRVOmMJ1n&*`{nLldh+muwiVtx@-z<9y-&h^tg@c`o{9REHOQ)Mo@1ez0iir((jNMn8Z1TLMiCZV$<);iL*nt4l-zYGWp8N}9F2N` zbQEIz{C&ju_8l0UKC5cx1h3Xdt9CWnP*VrFGzA@e|y^1h5$&t#`9K;RrvYKL@`c zyr@~Jy!%FaDjiy^i^mvO&wnZMj&9`9w`XK~iB0#;88n?U=%{|y*Y-BCeCwsia1IX6 zv;flI<$<7E5}hj-s<6wH7|AuX%x1H{4mTf@FWmra66v6&31&*0GDsy z8B_n&EmMAWOV92X0#5$>0RMF(!*rkKW^$5l&_GoGf!?3~_&a(F7e+4_z6A}>e79TR z@cb)p#}64}9t9;pKKWxpd6;gzHcv_S>fSKqFS{SK4&M>yU|4j|2eK#ZrOlIfZ*XU8 ztagWUDCiq&whvtM?9&Tk0M#ST{7y|eHQjqBn3de`@i!6hY7qx_AJxWeSOoq zCJotRqj`4wGbYBHBB&Z|C-R&H8m0%*M_4j5GMJP!Gpt5CpZaFkY7lL$#&Rmg)^%KIq*%lM^#{{x%2I_s^+Y)am+f9}D zvSeD1bohn^d|FPloao7(h#zPnE~lU%5|>b%l3B8pmV%OE1qB5K8-?$d!!a)xQBe3S zp`h3ZKDllrU~Y2F&{R)H$IMg!`EL*Z^~*+&y=6_F?p%MjmuE;qCCi@e^O9526+({5 z4q!$y?sePrYE?3@{EkW!jpnSY)VX}0QA=;xZ`;b;I`p+aRQ2nk%HvO0Z+6(QJ@^h+ zSlsII3A~Ur*VRCRSBjM6p?9C!TRNL+zv^{0?4<}~J(PY+sKHzWB_|l1x>|PmW^-;7 z-N?oozn7(p1so)!bi6tJ_Ta+884erwUVIqkwYXA>iB`|&NhHac8&U<*{bZ?nlJpa)f2kA=; zB`Mvyyr}aop|#V!xvv#2HAxOHnLHw!wSz0rHKvGzcWkSXcTzAqFn?|T z@SFje&CAN#WU2Qb_4j2h5+WFFcvq&!I29JH!*w;+M)~z&#rF{p6DqFle3yRv>4b@_ zr9h8M^$26U%C=60YS|u4U$g)A?Pn+7j|a7mGHcgg7n~M+{3PGD(85B)o~E6D>761Y z-t^YMZ7D5#CqE_o)OgZIu^Aq6%)Ak@9^YU#RlRJhdA`-txYPF2%OCH##ue$(j}OL+ zH9V`30L=U&yV2s0^t~x5C|ovEP|%RrZKkJlSw{eQ-32+_bxzH>R*KeEU{GR3rdZbT zgv{5BM%8jPT|3wap`WiBxyKf{2}i-}_EKymMP< zYQup&Ua^mc_W2iwzu0c568gcs)Y`Q4gD``7hM7Qk=>|EGi^pqYHJ+uelgl?c>~*d- zb1&0RZQ*ux9g6ZQ| ziCi)$_D@0q4>-6)DYJL+;kh3KGi~!qmAj>N#mYu>JF06Y{C;iq$#``$P7*#j;A#1@~pHJ`F%}I3@H*XoJDEoG4y`jd&R%)5~hAp9xW<7d~ z-A$#mpVsw>ljM;i&h4dJ9vwY(-Sqy>btMl}bxuX**^Ld9KX6)6lOvtzlW}8Zqn?*F zlek>b`4{!_InmLF0wt_4U;8?W@-*eQ91yh_HEl?_rc*JrtQZ%RgTTsp;a!yjB*3w#U0}My2 zUKVL>489|=CCuc~E|>MYcuy_O;)|Quy88y+=U&Yfb)&m|m{r`UB^nxadsDX@={USz z=AH7>DvF*xQt7-&l%JxyWSsl1c)sllh*-^RPV;1&S|i&Dm!%^NrXI>#rkkXyf-USr zjs$O#dw%8f9?U(gj+yz2UCn9o`CKhV+>gaxcWl*KTjb&5a+upC&ST@(gclobpJl{W zXLp-zN^(tea6ieOL4QxRkZRZ7-0Pe8mO5SLci;@Sd^O^6&xoDMr$eP+=;e)*?{@0Q z+1(OJsXi}%F+=rZ{H@%ovMhODtmDaLA}_}3BwacRw}`FTM*A-I@p0;oD)~{i`<&N| zcV4vb-7~P(bHro$eIwbC%eP$3g7}uE96XOcar9;(hjY1Caq+`Py)9mH8BovU2LTC?PoG@C|)KIvS;6ZMrT2* zrbelAty~NTUO(mibi!=+-g}O(A|;R4VZQX?D-P0xu{o(FQQqo{-;Q5=ZY;&qKGgqs zei_%6)d#v&on6c@t5*f--x-SBZD;lTh4yOckwbza7%4N)h9jr6Y@c#3*~iA@W*2o% zkYj1-9{gdY^2SICNgfoI+~-%c zayUS@J~6^zlZdRKvq;$~IuXMf+~Ab#*Uiyd)O%HQKE@`m&3KxY&pN8T2o;<|NI6XW){h%#gA$dN3m+dR6SUddM3&E^@;TOGnql=b>% zq$zXlos!Ee@1L?v>Q&~+H11w>l6R|9wC(T*9g5|r%^ulVp6+H0(rm6cS9@odbMZ+V z4KAMM&H~u2&;wNRgOkyNJUhSh*EvkS>v+b+kHR%dJUZ6h{;dqut^!y zH(X08D7fh;DAtnZFjF%NBOOyXdzGuy8n+0ow-I=6w|+FPUF*2#nqp@(^^?^`&J@RQ zW__gAp?M*L&Y zj~)H4jGkF_?&31_msk8$sm}{qp2jgXqPIol-haB~;`uKQH_oaw#2Sb(D7w-GC`eVL zT$jFh5=#Oz7$mfudIqUB|GZd%_q(Z`i5)>6J2ut*!}G#MI&Z399OSo zNiP0e=8^IK>eTXtl&?oZUwM8GG#Gf&5lVZ0uM)q~`7ln35Y=TZV*Jz1kEWN>Z@DDP zQ6fy(vS(wz$DV-Cw^r(N?PS)AV{A&@I_0wZZTtB%2V!5-=@4wI@Jj-c94zRT)e{aK z8)&a)N_>~}%2bY#tf^`B4Pib(XWSkA8dGhqD0v4fp%Y%8 z_pfPrFEdFoEf)RGq2oS7==P&dA;Gm}>m_SP*1vJzc>^_8x+d3L*CT^v$;*ckoP_D~ z%KpPce8$p@xsPO|u2PR3?|ONtj=3GR(d-zNaqaoS#UYjXc>R=0Dp?Mf`>Q^CnPJPb zPn4^kctU%9xFa<9I@`WWHL{nL)~vlzvJxdMnlN=*{FSkcb9_|H8O={84!V@DGcLQG zzEjXDBkO6u?29e6H->CJS?`al@Tpz9MXh^L&dmqzyxtX=|(w4Yx;ImZ|=V$G!IkgnM<=_U2peHdJ zukdvGgSWPBqF-t<#Kw31MXJfgC6XrVb;Uy));I;{QXM}nmdaw46hIs`-A?<`Cp5HM zZOlbd4{hB2&}zEbt#cHW<(^yoCN{5S<+=$v=`QcuzMUUd3V(TiZ_&zr1@kK_9OW-; z;vKn=srGz|<@!-cXOk8>_f#{hb&W;m$~LqSpHlA0GcxhkH#V#MQt2Vf$TeYq+s5Bg zEzQj{q|t1X)1jlZVKTWmZo_@6mSGXb$n};CVRFAeqBvLVZMigf|hJk^e$f0(N-|K zrf;l^n3hn+YD{hFP-fd8%TB+t$olJ!55Ab~NN#&it4Zi(Bu2Mf1+jZ?A_JLpc|AQ z$)s?|HzC84T3`cv4BrN(%)HcFCA%^O4;!B2-+6xUcBQuT2UXf_S#lc#*K;_%Ub*Q; zc;SsVz0&Sq?gVGN=MfkzUaeuVD8R>cfD?5qs_f|2(?xGPf`TQPTt85AJh*>L_t74+ zBYRG6)qKTx&~Kyp)YqEJkJ;H}^a`c3F0dCi-*X)D-#V!gpRZrKG-L6o_iL{HfZY%5 z7xzY6I6HhEO|h6RTD)(gOB%nI^A~Lj-}CzksH1Nj3Jlu2DLi?upKaH6pm`B`gdv(& zz{KUzDfjc#k?2*8iWFY=gFNix-cl7EdUcR*kpH4Xd+Dg=2kM9oOap#zmFZj0uMa9g z?GqeacOyqt=AIWru<2KoE&TUHh$sBQE*~~c&{<+9Ig+8Aql-VQXmew2_~=%~Xgg(_ zGje&opHCd{szFUvnJd ztc-|t3w`?zE8V@~P=)>V3&*s#H!ZoebpNI?sb}mLl)r4aTCUk~<|WhMqLjk8rS5{; z9&8O{_7qBcKe~Cig4rbXPQZuYllu1)vSs>wi+L}~+{G!zUvg_Kv?Ij#zR%>}8|jelkd*Gm-&`Bd>p8yXcklP!=RVK<<6a&Q zthMGGV~+UDF~;0$&v~$2t)K1M)bCxLtQ*v0%Y5U|uH(bFQ|6=o_Nx|NfCk##Vgtno z7_vy(xw7jAVFJr7*ag8iI*gQ9^GVs%UFO}4I5BH6xS=715isGa(1K~_xfaf@+;&m0DYHn|-~{ULIq$kEo99fP2W z7ChkyG2hzU>3Ecff$vxyioVl`B>AcuelJqsd?;oUv-Xf4F)b^~5Z5Ed4D0FxIzy~B zq)eTY6%=&w{5MB8r4Cu_G(zmwjkYuNpMj6`EZ@mUvlg1NCXc>X){ z{I0IBcEU4}A!$S_+NpZ+l5Xb@-F6)@edpd91B0@qQ;AwmPJy<5R6Ska8GZEMGrL|l zuWWxrhZ+3r{0?=M|CJQ0TN&4LLSy%ipP;@HF)}o;yy8vwV$) ziC2IyXZoktWQw%-0WH}&WI7bzS9DVm*LMe;$A(T_({rhe?;6?R=9r2UrwHhp+WVfW zlBxJ4?68vO%}Zcl3^w9K#kQ20aWCF1Cw4WLwK+M*z1o>{dlqLy!pkcH^?l|I$M45% zTvU3|VuUUEU#MPqsvqmzCAcSam_6|D);qe?hVU0uT>grvgWp|=M+H(An8Qh0>?N;{ z9RH>xtJDRx-eWb50KU%V`_U!cWK5@TWRoh(?NP?~qi>j^jE@>i>QP9S@? zUPBs{$tY-7pyx$6_nmK%o9XX@c|wFuy1r)ekb&jZF3jfjDcWAH|&;CPagn3IuWl4s7uCIN!eKaV`^u`?RqpSBhZWabMqc59SPS4T|1Epr^3_kh}eXn@p%2hW0 zE3J4F$7IA>U#Huf9PcLPSoc5A`=A}GFbR{|K)khh69dncWQKC)mgag@_Jq^p^4)i~ zOYdJ~oX;W`Q8$w9uXb)rD6I_>tx{%#!=FH32$Pn z+a5jjpuAyhi_IcI{MDZ8a3jL`v1*NGkWT*%)kzJc!O?p!VyCW(J;Z0cYJGKwB3R>& zvGol_*KgP9WN&ZvagS@vB`~gU3FRyuds`r{VGY(+gTK%GJ{QvHy`GYm2`y4Patl+Z zmmqF>QAmnPnQE*qu7P%Cg}ikCIsr9-(xIo91`L^;fr8H~6VDF+wR7c<+NWZ%MZNt* zAq1FpGBb~(8U=ksERrfxbElhd#;{LYi(;4#(u&YTd(F5bIq^=fiC=T-zMvFN>5XFQ zlL<#bLqbIx{H$vAy$hl1lV|^$lJk+F#2p%rmi1cQH)koc$Gr$jb7qjXdwi!=;Ng|9n%Jr{UF_!W)U zF=0-a6-=;f|M4l*mH=)3K4iVY=B@PyU8!;J#>|U_yc@%| zz)?EpzcXU|DqE;tOo>!Zu8QSwkJ8t5Bj26Fk~FE7F)^~+ywvvAI@`EV_?rtVwBGu; zHp~3ghJEdl!D9*5u{vIgLDIPbnXBqq8T)7W6$8kHlia(c44T80W-q)=T`=#0&!QE~ zgufr}v273$^6TBn~;-xCZYO;v{Ls_ONKDXgSky zn|ijS_)MiLBuY7!qzabi`jGhyFt84%sz0%}usdhf=)7aT`Z4}mV=cw~hN$}5M{x7__dPM_Y@4Hg?D(!1%XS5`Gg4 ze#8I70$k8XF@IUWqLBkfYSZt`XT;^UV8H!g+Q;{(hUv}`r1i(s4(^$i(jK2KkN8Tw zX?!xpq35ARy#LDY2{mR8OpMBpM=GAhHA$o-FZGeob$5ARqTJTr$}WY&pjR>4a{^B_ z1|^;u617>k*u*~H|NKBE%UIE5U+qbp;=$~=ikX8_A>TqC@p(Y`ehNRtz8RbTJ$1tyR^h;=+6!+5>gIcetz-iZD8LNN^Cdj3ZM zfJr0-1nf%?See)x8XMXhLOL6(DyWch;?!u)fwyGVRa68LMU@Ol3sSTX8GZ~Fd<{~s zHFh!AQ2*&-TJ3vBL24KVAC{z+G=V$o4cWxYuRr0}9Bt4~kH}zz!C`eFh zQ&Uq89ajT3BOk5bI>mAAq)eGU6N|p1P3?L^1_keBdp_@?$9AU@b|ysv(Hs`;cC>e& z)B7h(F7kV|*40iEmUjjl5JD5$;<+B*f>jsK?D#f6_*Tgo{#-zcbM`97A}NVzO<}I# zSDfJ9TvfLXn%Bs*afe7M&qgkOknqo+Ms~=bWa^xlGMA2j2uo9Q#Tsnhr+w&pyq~2V z=%+o9CQ?iEs@9D9O0n}DS7DM19L}}aJK8xLA1SX|`^8_!#xPb`l^}McUito%_nX0{ zfMb`ck?NM09f2{|)Qd>jwwhw#QXcSmBK@UHZNQ@6-o*BSiM>6v z`e*;+o|DbU9JUtOaj#K~!2c(&elRH^3Ljh3hoatZFUPgwGowB-$}>$8ky53~%hROI zNw}i()dbJb93kZD1s);5_EJXD0_BKdzTAy*c5xBh5ux*s(DOrY;GRSx-+m+&;qJ*% zj4z|!R7d1a631yZhqx|~6Xq4K@<26LK{&*LS7EZ-LN|Lk|7pWMyUf%3QY$RdD|~O( zjK+n&*g?rxP4IqWDh_G7#6AzO{6!WOBUX$S;e# z+It*BpgN~5j!37W`t-9HXMT&8fpXmQ2#xR>gRWct9?b}J)Z`I_}xYC3MoI~Sx^3QFHCKcIdTdBD?d+0wldNm=bM=f@{i3m-wXM8MoCW+=_f+_Om+?x6I^Bk%hiYYr9;WTF5v$V8tlVs zF-AwEqD1la#KA$55JUgljR67DCh+TjPv+r*h5XY0OP=St^nB&LMgxMcKh3KMhzU`M z(Vj;VX_Htd&<63nE#b+rk1(P^;bAln&g2ioo}J4^7xBiPS)-goE?fTjicnhWZW;R0 zDgSi&;_c&bGGfF7TpEc`TThhT%syWHHIVde*?n0fQ%2@iC2dgTc-VlzbWA@l_ z{WkA`cXX8N?{p$aNJGLzy8Da?GrXD7u!JbyCR5*?=tdXW)bcC&5lhI1fM9Ekh=6mc))T{LPbAF@&0&y6 z_DKqPw0yR{hgZ%hNUBQ*rFZrkZ*;M+86;W}t|@Jj#2?6c4v@%s8~$_&Fr04x9C*S@ zT-K>bN1-my#iYEW;&Gh!*xh|M<*~=fx1SEDOODpluIC4hc^>C0%hc~A$4u_|wFBW=!9$|Z&%y#sMR-GL!WLR52Y%HAy--!86 z;c<5UxaM@@kiz}!q$6hf=kai@$2nb_$Jq%ut>>b*w)T9za{A}R_%OT2`T5tp$3Kr2 zmNr`|9XD%Fr3tIfcT?P7?v5W?i`J%CPoM3bkMAFJ^;ooz^F6*e+;n7&Dr6FE|B*J` z&VC}eT)Ok>V(IXEvHDPQ;l!9-p2tJsp=6hH@;%Yo;nuTh1}&FvTg#s63)THcE*txf zy+6MUr8c5Wh1O`~;M0}(iC zu>*UcE)Y+OtqTzY_v|z6pDs620MU(zO0fbCCUn3g4Bp`V+Eu2~a50=Av7dw!z5 zynuQ_e3kAEUuJ_60h=g{>po}zWTKM{fSIqtF3*jr~FmqJk(o&hSuGtq{V9o&{$ z(0b!%=$5;i?}f&3@rBBkkR~wI?it3=stQLkWRREc-rHv=-?f1Bub1d=^uW6eV)yLQ z2WqCwIORfyIK*$tUME+y!PgajwrLQYP{(TUw$u@)xWtj8OKC>LAPwA6t}CXudKG>p`f*);GrO`@)(!d zRRxcC3;G24%|z}Qh+OHC#hCC0pXO~+iW8C=5{{?xWuZ(l#n+2l6CjAC@JX7xyOQZ6GW`!uhQ3%km7Bsti@S3<-AvNuw}i#*Z$)fQho+t(R2&zPHYO zUz#vOnn**M*moG8DNq?6Wuu#qpj()M(Q)7O`iIQ;)7en$Vd2f?*2i^vU5~SyAj8yifG%qtSswj$* z@f!-=(goNd`ZJpK+2z6|nQ3`Gq~!QIZRy^AnUQ`C%7`wscPgayDoQgsX~JYw_esU? zLz;DC_>H0aTR^^4mK%_{{}8_nJ9yn!CP)q`<&}cXJ|}vJ1yZT!zAFyN9q95P?Ot}`p2SeOE1`nU{ECHl!C5K+` zUh=`o14?csV@p(Bq0$GU%m`EXzPv6`6<_CyGj|7ln*{aQ=mUws;TwPmpd*ncC4l3L z_>EBphR##O8>5u3KLgeGl4ZG3FX zE{)k?ii0%_+&X1vbaJg>_R=Z*6Hw1iGwUf`P;@rJX>lUTS&?h8tbRyBx!s@E@99KHP(NzqsZ6e(0inE&pGX`wvkf{$EPj{f8VHIszEE>?9Vll}@h;Cwf2v z+-v|gKtc@23IHJgeF=$pn+%2r_X}iLEt~Nd=g=I6*t3*%xglJVTN73-fidLa4tm)` ze>oxtg>R!$!z>-#S(GIz;PUw(@T=If6nF#V;zWE+D?H5{I2fJ}(p@xRc|4KjpJ;kK zI@_~$wl z!Hp??>hPD^X5A}?{)IEVE_fK1Mlb%mkRY%?7P`cGtw`c8%s@;oF#~Dv4>JP5iA>xU zfhK};&&uH&z&b(v*I+qm`@lz+@@x0}8t<4Aa^R(t|4si(U;eh)D>zgh!J$&;QiC3# za|xA0S6r-8_=G`RJ*Fmu;X1#nNcMyiiz1$+#Sl|V!dV+YAq@vm;QIgc5}M>haLPZ%!v7^J9H@T@^|ZEOPc!x> zaDd;(nr z7}O4r@V`t94`L8G+?M6Ff3>gt+fdy=9=K!vN%eo?flW2wfs!F0KV)=k!u8o-{)JHT zmw(~t{WbVBnCF+~TZb(0pAk2pD5UEq1hFagJUjz|;xf{1C5xg5xWGd(^3*Pf+rUHc zDer-Ub@*2-2hVQ(lhtKd|KC2WA4F?H?xyVvml6>oWX9^nj z6=CANN4t@fWt_EwMlxOm_`OjCN;8f8&ix{S2BzRKJ;F%|HzyxPO<;c2xraoPBAmxi57?a#O4 zF4vTbr*-VTD&5?g62?zs#9^C{(FWbE`%pIy_RpI6T~ z3o*PigxF;EPfRUIy&XSA|1h@6T2VJy!=~J|etws(^bj)+KDuLq>ec&J*t0u_kv)EfNW{cxeiLE5{DnLCYrVJnwq~%5z%<)vGM? z2k^%FC8SGE3LR(1Uhjm}2tIh8W{)x6^J*@9YaFd}WK)o_A>PJUSvNJZOCxJ1w~cZ1 zH7jWj|50Yj&6Jt%K_~Lt7%T(HE|}$AM<|aC=A%JVD{FJcZoeX_aj?qPP1)iHu1J{s zyx;L%G1aUYMZEmRB)3=2bWTB@4Vt4^wKn-nSmrJ<#~4LR-0qS!zMIZ_6?+0@=LOFi_u1E z%b>gbmQJYYf(Q(21qCf7X(3wK#(=7{T+-Wmm_&b!3bK!2`tEy&Ro3;e8RRmH4060j znNWM)@{gR=b}DI_qlH&wU_6S(R;r{)pxyS^0>^t?*Txu0APQB0y@jCYM(J^SEQ%Du zpfV?L&-iQkI=cJTjC2rl&Xx3=53Rl4=39%&^T*d6$Qx`=DC0@mDR5%!oVBt_)8&Va zPq2!Aq1=ylP%wCR&>|Wp68|ZH;kyr6$ONevK4JBUIT(J{YN}2V)cwKY0NG z=jQ00)?DTQUwTA^MJ@R;%a>mKg%2bS-(#?FiC=wLt~5Y8!e^_H3BJq*oNt>Dj=>;g zs}PRCG9OLd-?nbt zT1L!B4SRRsN`(bR^Sg-QfyJ;n9GldKf{<%Pxv>z#@15Va2Xfw$C{^)SUuAtaUe}_w z4sbN5b$B%qwvy#ljgk8}qHT^6vpmF1>X5KCXEjTIgsN}yitUZ(nUfYaZhFfV$mM>8 zq*|?3iIdCSDEs)`FynUzb)!~^>BYR+HV({_mT4Y?Se!w?9D(xoEfPF#--H2L*fiK(YpbH!SlwU_2MO1a!U=nk|2OjEy6H1P}Qu>OThrx>(Skv7=t=;AM^VcB+&F^2T+IE zpMUTC(mU}DhQY;^=`h9$LSrtQ1#H$u_Xmgvx8<6d0s!V}b7nuZO1-xJ0-rq=808-( z@gAAoFe{CGy@_}R;x)YSzBP~rx|_t~tSNL5=xjylv=T^fmC}V1(j(gGz|2#mbT>ci zVR6$Tn(AON(&2UpT6zqrYwWw@)h6Ut-(61o%$9FvuU43#6D-rT35&59#eydJ1Qnu= zO9p1y0AsLx9eNCy^i7*=dI8RX(@J2@aAJ&%{a|grJ?Ch;ZX0`g+sGjXwinS2Q>`R> zN=B{BrziFCIGr5td4;TPMfP%tI6~739cFRBfqdJ_N9I1Blw0Kw+1JAYyM*6%=}Gsg zfRPtr>RLAZpT-Hv0=txkzmVI9>wpXXf#qxwX_YScRf8 ztJfxsW^_V*zVO~N*q1P!yOp#F32dMGx72v3dHJ-=!no;h6B1w*4>B0Qh0E=P%3z}~ z^8l%58yZofjpZt!(`0$Z6kamQne}zsjflYhqzYTP@F4!l7cq}rUZBeZJthe<4|+$} zZ`;J^%-Q!Zc*)|Al%RfN7GBk;UjzZIZYUbWrKZhWZJW8&9{xeVHWt{;8S{?)dVww& z`m!?nNbH^)N&{PqB0;f}A6CbSj2t5TCY~B2C6}DYoASZ$7L%bi(&`Vw_}i7MB&`S6 z@V_aY!73EgA~v3@oOi~eJhQsao-}!Bd3ydi#~9c(cEbtP(?Yh-pS@_G^69~xdSArq z889nxRgO!?mY`iJDY3|il{(v~xLXKexoPv`D}ljV!SZdJw}6k4-W%Z5Cb0070;J_s zmnMi!vd&I6ZRRG3jZ^mXl>zauzbDa`sEC*r4xFAunNoouFub)03wktVZ};i0bS15k zQ>d|%W_Vt9(+=d=ni|@UgpK=yjq|FC`)Z2R?v8rd+M&4Hl@AWhO23Rj+P~1Vw3CC7 z(w~%P(Q_VCVXC)2HUatq`N^0|2_oK(3Il2QysCMcHt9f0eS)`Lxgw$cBG?FA$nI2T zw>~DBbBq8=m1J&6C0GR*OySKS z-q(Qzj%}EM<>rS~7XxT);5wk&k1QI3h+nKPCg^Gt><96JW!eBu!kv7AkiZ2cB9f8U zGIgT>9Ws!C%Dc>@Sgb2Vw4ccL1wNXh(V9{xD7*(<=44qu%Ix^mQyR(kWom_b)rSRC zX)-)%< zg!_#lPk;Y$vcub2r<0c5tuEL^57Gd#VcO}p!Eyet;knvKnT~qz^v`bty>G2wIan2V zll#;B+GzOJH+64uLV%V&@&o#jex-I%+sFLJD)X@PwZ~;i?c^#D1 z3G6UOz>MBQG>oUeQ`yDp8pW(Pe#qyA&DER{(WwUunif_taKXsuZ=Dl}SkRLeX@y&T z-z|>psVi{U%E=a92gFO+PMzS~Uhjo3HSoIWm#S1+aSMtBxhs~9=)d7+{iIrV^n$3Pk%a0IRb1HhurZs~;8*|?y8MOS3zSEZN(R{X zxhm;7D--I_qSJ6~>IZu!=y3}x?Vr3{L6Pm;i0j;73jT^df@u7%56#z{uCOw=fmNEu z$e}dL6~;}1TkC>XTZzHK@9DP)pDzl0i=YC8;N zc^yV~KW{rtuA3VoO+d%zta)%K5U~n;ly9@J4AxEt$O*@l^v|mk>Wsj^Z4%X8u~NsC z3d26g3t(=SU)}+66scPd6(`sdPi&AJgOn*J4G*kT{g8V;PK3)hs1X`ANMUZdT(3|YRkT41AnT9_D zoU}NuIFr$}I1aG|l)uEcR`ZDTDxoE`+Z zS+Z#-xosym?S?UQ2~$6&G$o^sK1^qsQZjfB;tO}-OHI|iA(|Nfm@wEcsPcD`<1K7< zJMSZykWoJcljBsr6C}{_*OK5U`W{v{$M4%A6ygSF?Wmv~UER%iT&qt-es*bp#R^#xtwx*di6` zOHyg;l{J|&kiYkNk0&FJCY21lkXW#w@#plUr*zuqz<3I#rJZxajISK=Us{{@NNH7> z+ExQ#CafVCIhEdX)!-HZvm41y=e^uEZ~+|P=jlgMH>-8jr^a8aME1GheFsxYL{)z? z?)4^9Fjz(cpJunaBy0!Wn2y+Sh7i5AVeAUfv`PC?IDXkME$P9)sqUtJ-hzkkrVooWQxB_U6tQnZxH>Z8ouuL-n;Un z>#Wt&`)eO8U1sRYTByF<7yVAA3CgMw`fxvg#G{DS+jg4PLDPB_Q#w$HELZk+u)}28 z{C2&x4oXfT);8+%K8h^XAn;c^2)wq_CG?XF2K8Pyv=mhBE6A&DV3@q|XoM=(*-_Squ|MB~nDTm@e<5 z5;vHxf;7)y3XDl@V_QM|ydt4)F`9qUcw4t^C6{`W^?60xoEg%lRST#R^6*|-&#uXU zid=@SeJ-iu2NnmCnr1E+9ViId^+M&Lf)WZ2i5ox-PkWG>TR!Ck&vB+fRVTpKjRg@< z$-UYE*s{`L@HlKgn}lY3D;#-KU`?ueu_1j7;;xHA<%fAk_I6O{9OQy%%A(IF-4k^N z;6D4I6TsaV%+J0+sCr|+z75hFJnTY|6{>#o=0T9TmM6;@La`nZI9mO7R8M*~OxY^3 z5EL7E3S5=M3u_>yz`QWUh~fu94ZX%T8LNJ`9=Fhi7Q}L+Fh)AnMSy2)TS#ZP5JVAm zbL9}9sqtQ6xl+u}DQzqIO)DVC#Rm2(5&bZgp_{Xh$rV++v_R{n1wf+euYTJPN}X(9 zCfp1#f9w)mfZ?j|%|PKhzn609vdr{R+y=!Ma~!aSk79-ZJd=d&@_<|;-MK-RFD8Do zT9XUl)L9`zV9v2L>vL(_j(%icCB|Af(kma9WM)vi%vZB=l~&UFf+aIp?iExi45t_y zIYBFd?I38bV=;<=kU?7u6nqI?3R-H4a&tjx?R^Rm^wLayDtEi!6P;aYBatEI(7SWO zna^yAVD0&J5UimE#WnVPWKi+g^`Ho?S3{}H2c)ulPaO%5Kl^WpSLhk+#wBi`3X~tx z<(q+d-X?M0X$Dzie-;&UKf0!gHp2x`Qm6X5KEg^nm77lo%haop38k4vpxKOvcG)S6p?I#2+GY;e?F)* zRp9fFF;Y`Ep`zBBdSwerfqfz<6y-u?aSzi1G_jN%#C9r)w*kmbXge z!y_Y}d27gRxWiFC@?i5;p_{Ln#$k*;5B z+tjZcno6i6S5pM}8FD5;qXIlMX1TruKI(7*%ftxTaKI4W2+bH4kU$SXvMs10E&$1X zO8s&W)xBt_ih_qt#ikv7sCe3BdV@3U+fODbpmr=6ay@%_w#_K0jGBV4OR|5A zjmv_ty+Oy?G4dK*+I1xg+jx6vGfsR5%R0kIA#Yfla&EWdHFC^=0mM0Mxe zQ2j+^Fad?-HFx+O>skcBsF&)o902BD0UX@@lMYOU1}Zq34FfKD>IBL_Tpl^!25l2o zePwwH{90sMr@P@m)~f*^PI`binFiykq>!Ge*+~W%!l37eKA{PC2%x}U4?=qk^@A@} z6qj~SoN1M)4k1?~l(uH%0dpE=2p`_JS{WuSsCr{sVa(< z$6M$#)Co1$d%1_mvEwcn-P85qxnvT?SH)IuC5}-MAVt2&tL|6PW|-^4))w;!csbaf zr$Wfd4W~SVZJcr&fhOyH^#_cuY`!UTxv_2a#}d79D{!U8q#@^ zzSzqIEa!7Ej|{%+`pG`-4-iiT&t1K_=K4eF#XRy-Bz2Jq&J~gNuzRN&C;F|f?={}) zonFzuQW5P1GeI~{a^JYWFnsvReGLK7%p?$q$)xil05N3G=4Lz^z^>yXPMMI(pLS|@)qWkK7>VIkMo7HF5=}? zk?_-leialBl!8s=)4pP4?c&eTDeb zW7Ko~n0h?tj6awVJC$0CUz}j; z@Sq*mI~~-hx4V%XJg?tAaP0(bd9!H__1=cKQ=GU5eFdA1HFmExwE63&B~w}Jsh zOWN}`*$bY4htw=4{8!GA_Z(;PN^C7f*QP0xwv`7oj7snd2=^S@HFW_RM{2z;l#SKr zvedMVfRG7SrTUSfuP&X_+R|~bV&AJ)=qCk+@jMd zFQ%9Z%=-Eig_<|~Ja855M3B~+R)Zq^M9hQ!;uftrDm41NuUE^}v8h+VKvhC%3#uFH zU?5LfEsY>|K)|`~DddPVjs^OG@9jSb(gn}*=d^(Y)I@qwkEhwGJ8>Ul!6Cn79;I`- zg3RLXRUMGOZ%)KfNLS{bPKl|G`gMb@?7$nUC9yqgz&9@HX2CKRd8QD0Gc8WkYPExi z^Afzx<@b&7bL}}rnb+$O8SA_8J9mV{A@IVL*Vvef0wIXc z>lERBBH%-`0{CpjNBG^q2H&+9MrtGKEJ-~iJHr3k;)^NP%9pN7xr8K7+*%h4C7&S% zBb8@TDbUvhED1Omcr=P+RKLi6>3vkMnG#|~tTc0;dM7xRm{gS=dhbml9Ypa?X^Zvh zkjac{4N)x@&Epce;|yy0qO8`ok4zPxR*SRM-O}w{MybUUg7ptmyLvx$eA}VW|J2G@ z%hWz3OU-I-vPy$E*g@3x?%_Nm^25lS&?4DypyeAS)I$EI=*xb1)}qO)0S>4?9+CON zi0oB-==Tq7^MwffAnx=i73JHBFGs2Me1dJ)Xx@1jf#0}Z;P-d5vv2JMp((Ys&$j#R z2^U7bVpo2MdO|U*FVFn-;_Q=kwd6L<C74C=g z=xC3g*ah@v^$ew~TANEFEyUn5zEO{SLV@A^Au6Y**kN8<&^Cv>eCSQYsrv8xaH&0$ z|Fq~@%H|f+43C9duDAY;;Q#f<*cU7dEjL7zQ|~8w?Pu1ZMUK>rm9^<`Z-sp!jE*qCn>|N^2{wY zx$=Uh4D50dh9x4yV-?ZaKiZ2+atkd0rT|~A%$TZ7dFkz;MO4{u!KJ);8%}KIbBVo>``MCHy0x!EUi8|Xy_f!&uim?r$&Xv9qEpbo)eBkdy0byQ7=H`0z1T^`~Giqebn6AVHJZ9yic4)VNrr zr#Q-^0L=4?DLy)U%eZi#zJmDcozheV-M)8s_o6T*lB@9+I|nI= zeVX{~7+a$#vGvNa=EIr$x^z)?s-hIcs1q=rJw5AruaOpi^Njm|*z52bZF8xW^zniK zXBTw}Z{yiXTtRJYY!^rEB;7}?YhSrKM;PA88c_m@f5SWf;R5nJ$ZHI=YhP_b>D)zX~iO!HHymb zELBp}oSijxgg$mZIavDleQp?!`KYSEt_UlzTLu>a9nskO$$eXE8$0$V*0v_lcgQKz zP!JhX5kQy!Z~wSPD5y+u;C$VTIw7Z?F6@@9^eiSF@aFgOmC8z+(sg-sEr@)y(AV`; zIk~bZQw=LQ4x9^VTN1PRg0R{PyJeJIK@;Ou9aBcgx6gD~S9p7L zi{!pV(A&ehGOfU85*Edj2|jsOJT=IeGV6_IR+tuKS-tZbGl>0LgTC;N+!^S9xWTBC z%~_T??W5&uHJ&@>%HZ=u<@o#LdSkD}vuC2rsGmnHXnPG%o1-a0?XLz*v!~kFvtL1t zL<{OB{^Cs>U+Nf+q>>PhZ1Cp5&ciSFg+7{*Yd(4!6@xWNy49PTBK&fCZJv%rQ}oCu zE}E`7Z}qy`E(rGpgsb8%LS74m4yD%|woorqD|}H(oPTbs`n3E}f6O^a*4l12b$nNT zaDhoL?sd)A*|9XDyVw-V8F!ip~dZ1PTF= z$N4+t4Q*`xf5iWu<%tpXuyKxS{+q}LSpFL!6HgiZ#WV^&kZK#$Bk^~2$18r7u#ykE zK{M4KTB16<;XD>HuX1)IcW-Xv+kiYK6^SXgL-jo^B#p|3kq0fwSkrkTg}2kb_+=&e zy?%i+nsjy~zUH%w(<`Rf+R*Y^J#j8cf8;YGzLrw1}Ov?oV5*?t6>= zNzPRnt=pe#tQ7sr4sdk6BXC?*zW(Gn`cn1oi0j+ccV6BmPpmn-!}6tsZhWS? zU^!%(5o}r&*skN)dBb1Mhw3|DmO!JN9~!;Lzv@2z>gGrPs#oYrJ7%~N{HKm|KrtCfJzbUf(550{q1KS z%%IDy(D3cQe-gSs*_zDRP_ZR;r?skC_|FOIHUw0e-$@I^ytG}7H zy8Ta>!Z))1$@I@Xk-wQXfn(GDb%*4iEdJbo_?tz7C!EDUb|d~t{m;_#H!T9fR4yXI qe-)yClK(S}|DC+A;BVx=lKOoGRIoD?ih%eCL?EQp6oHt4@V@|u1WT^~ literal 106726 zcmeFYbySvX*F8!JNFyE6Dcudy9io7Amvl&XrywAmDxlK+Al)5;2uOE#_qiWJeZTj7 zf1EMS80U}Q*<Gg@C|- zfQQl)wXt?IwszEg9fXXL916==gaqq zd@YKiqEfQ>JXTYKVhApA4BBF@f?*(_dBXV@+A9^90Fj?Pg-%;%UhRA{?{+xTihd<_ zwGDoGA@B+d7NY>MN8-xO4c9{jiveu!|TI+SDL7-22?RAGWXS?WQK>%vb+dN+5Y z)jF218)?=qtUJa!YQ)_GG!tgJ7EysJyt#pfQ2LKnu25knKLq}Z9MGwVKr8Fo8(TUs zF@pd3|F`h}!F~JBN6(LuS8QQM3fhsn4DLJ`nTkdek#!c9sv&*l?BgZu^534=+S9OdUS@b^3sgQyx1V!o|nv3*T}N* zKrE#JwshjW#*B$MmhUlPnv5h*W;GF&fPA*aN;l1z*PJ1CW$j0 zI?jQHfanLtAGnQNESa2b>@5szY%IXDE?-64CXXAj>Nx~QoeY#2d4<}G z6f0snI5|Ts+h2)PDsOKto~C%btY(EV4OE7Rt|(N6Mdu zAY15VW0vM11nrNTbH)7lsLhtM-fhQ%lA65VzKw3+`Z$P2HoZ)2QM(U+#9vDF#iPRs zj+t_}a^41*!kqo=iA=4Z1U|3#!t%JF-)O!i8pt3ZUHb-A=GZ>j-NSTqWo+} zqt_Z zWVsyG04cW7>CZ)0D#e{pg85!l?M1~}2v_Nttj7vui{gnC!q`+UQeHkRtRW77}CCAHu9=i;5^^PRaH<6eY;t zn1VK)IR15IhL~fNLd)Yc!aUyM z*@*Jc_|0MytCz&L#auLy#aV#@E8atEtf408kZz1=N z!Xh!xer8D)?;u%!;*!7Tb}-I4|5RY4|4ouu38q!&v+wS;pbvhymMD>BUyP$D zxW>=M&+!OmZ9~3&Cr8(!H&LWzgO zzFhD3TY>NsJKTH5$9r>^>CeQ{NhCsl4oa`+#drrLd8UuVFtd`n3P!#`NU3LkD-xh(2K?kY} z7x<3*f#G0gZ0zX3bo+$`JULQhWo;&yk$iTbkBMQX49BH^mkXyFn5oeRL$(lYslPYZ z454s~*{2D*IvG;f!tA8{qAwd~=7mXXZ|7VbwABa~$+)5(V-KsKpQZibK&XLOk}EZk zMw=9wxAP1U#;fY`(!4~n;W5W^BQaajmA4UnS|OQlidiYfe8}ZPr@N(ObwdYTqQy;( zB5`xqDvFi)yeN9FD3R!83uYlle))wa*xo{*-Tu%#@~)-XR0_nHwpCu>@$tSakdEV_YGizZD=*ng4DQz>Pg9G7O`;+zKg> zlVV|>=@Gao$(tcgFEI9TXCL?;!oh)XBn_E8ne6hrR@$U&+=w?x8@W3JbOZbS8+npk z>>66Le?*K2SE=95klOD@CYhfbhK$;igftxOTXQBTm+=k7CW_vyQ)VVhV{}`G;$E~7 zoZz%twG3LU#}*3MPiIEytVZ|p5^nX_wT-RK-ygZN)b!`a$TV=4` zRz{k(13`66&JLHsjlU=k#x`yZgI6rk1jban(V3_b7H#Rba|3e6N&6~8%O1LoLmpGE z;|80L2x4SxFVs7e67kA(DV|e62#TrH1?XI^2sL=Q9*%BZMGZL5=%hz@2@1G6UTiH) z?PN4u?d=NVfq z=)3a1y1E#Sa@K7S#qhqkTsmlJ_${GG^xkWs)y=`-S{AmAr#mwzs?}yONoOj2r zckIGM`FEGxq70$wnJdu6;VxVGW&TE)ocEFC(dM$Dne=kTNUz!X=Jj#WfHhRf*FEnd z*-z?b77>y1*C~;GqK4L>?TnkNgB>Qt>z%fZrA-4jL2oxFmJES3onCB3Z@d9XMQ_)u z4G$LeKCimOhHG!?BAxP$&mixk`HMc{s+x)5tCRWbAGrglqt1`ui&YiV>)iI}#jdXL zumcDJBu}a`bkZ+*-L89>KJD4hef*u-vNGX)8KNWP20EMAKJMA-2-aNvwYvDDW$FaA zDuYO8#_McGENJ+G;u<4svc?(mO8 zM?ok5{aq%mPNi?z2Dm1H7X+qWrgl<%)K&WiEbgi<{|lru0ud?y-OtB+w?|NwmRoi%9OJ5$&iSvyMjBXF}E1~)skbM7XwMD_w+TjXq z^z|n?A&Z9a-w8OU`^fdRtqC@JOMD*H+x303SIsHS<*PQl*43NSH&D9uO$iC7`waCS z!AzrDJ*Imp&Asb3yiHtf2{yY+l=U9rOfz#m9QBudbp#QG7u!I`LQ5PJsl^U=g`0Xe zsm)2AHh@fvZ4cAsOHBXc&$8By;d(nG_q(;h339t<*t4XP&KGe-3pCqIz^G+Ew?$um zgQ8nFk?^^un0;aUT(HiG6^U(@2I;^Ycd>ASbTP5BT8S}WKj-CltH7S?q2T9Gb7>NX zY12W`3w(7L-R@Z)Xx$%_eu<33XQRo`#uX?z>G*n!Xc#8{dJE5!Q-RYhO!GnMO%{8J zhzY^+OZxu3wSicyvkdZ2IyJUqCG8m%BYq72Vn~tP3Ft5J?MTT@*yrVO(3xU*B0-yE z^N)Jm&Q&Go%?WmlTEir26VSx9yk%+)Id6z@$_i;VdY8+9fkyL^Dxht>iAmMavEbGG3v=^h#3 zf=}!~QjKy*Jq*8!cchTCAt!o~c3J{85iaV3*$O?bNF%Z@2Fr`)2#Y z;iegr3Daw|D|Tu^=^ZR79S-}~mi3HJj>bLe)NH8qTfH|2D@GC@k6R8_`mVNiuFLk_ zjxLXywQW4CZFJ2u4Tvww3eRv~VPM;%kb>$=Ki5Yebr8PNmcoDa`WMu!Wa`M$`q>f- z-SdEp!J;4@CrcLF2t+ll*ADtEfqsZfFFI$(!aioolg^K=XTLYhTWJfk&sTx!$h7q_ zJWHF|@1Nj~A5jT3?C!2s?LL+n7pBdNE7hR2*oVUuK_=7`5E}eCT_H1@n6gg)t{{E1 zJnI|q!>ay-&V=@zvj4j0`P;20u+OSm6b( zE5mH(2R5RTujBZowk7n41Tp(H`L@z2TNcWloXhS7yO~(38u|rToI!JMOJD_?^h9#I zE_Z6NaYy>Su|H>0QHW^x=W8Z5BL}L!FU{{7tE4Y~)l1qd(KpB=Y z*t%Ghf7^XZ!H#|2ksxV}6Y6^;?i4Tb8thV>^(RE95wlJML;x}QRB28A4|#Qg(ckPl z70v#tuiuNn_G!>rBDHK7FgOxGPOV<F?o>&)Wo`LcZ_TnsVBS{uiGH3zf)px|Us z{_B}=o@+K%p(yFl)~SSKHX4hulKm>Di59NI_sBj+0_ds9zVOwcu`k2X)=Gk6Rfah& z>XxL2GF2t-t;e;0tzs8JR@xVJv4_{Cl)9n(hWc7=Vo^}cLjMHEB5MM7Rbs^(?qG-g zb4tn$|My5=qjHYU?<3LHhQd{&hc)|L$=0$}v^ogN-%BK?e66QM&Fwb?>-8lV*~UL~ zCLMf(z<)e7cD+5>Mly9eTn2_dRYQSy)Xy~t&78dqSFrp+6@(H9U%Ws-+6Yn((%^yc z_vk#fY=-1yfwqK#NMZJQiw}j=jn~+JcD$LWhSDg8E#YJAtPY)63R_rVK5Y>QS5QnA zXyA_R90C-E_`CrFL<&Uy9nBB`&2Yt!8^dmChO%U>6(G<13XLlg1Qo$!0M(e9?!MPW z^enwvvV&0XvWeWamVZf+2!lb&=k3lAfN!_XMnL_*U)AN7U8v15L>OGPZY4T6Jw0r4 zh!lGt`96pgsKy*5y|f?*|9w)Qrw84TiJi^x#hZ*45HGPiD>(b^%J#Do1pRh2#Ov!_ z&Rs@qA9+YU$7|~K^3r5mz|*k^`7!a2j~*9qYr8=JMQ~DZ0wMR+HG4!WSOjLQgy8`r8*DKi z+*mJCF&>0vJH#(@cxD=6s4; zd^%_#0Lbs{^CoIEfuQ@1Z#4A=zIdFuQR+KGqlpV*7*wx1TQ=Kf#YNZiW0Z)gTA_mv zhCY35vE5^#yf})_YO10%qaij7c#%qivu!+a<~M%w)P#8^pdSd5FN;d_sz~(mwvs?Z z(UL(_D-XrL6~b#BdODd3ZEFoXO9;Vj3bDx!LlTDyxeFXSggCYYgo!gAWGAutW^-{( z@X_Y=c7-Zv6aiI3UmW2P#6pxmgdV`|9vR+oQsgqkbKVD(Rt}Kos8Cn}PNL4g> z8VlyED5#GhP0?!*ZGI4U%1BI=07fz6iyyVr$^aif5A3k!9iD0{0o7gW%v8*o@|oW+vArzde><| zNZplFqViG!JWagFcm|^Uk>V)Nmte0Wft0dkaA&gEs(;ZQ&_iC zYoNi0rFBKv?nrish@q(!iuL{(1^y%^^u%_W{P3!5&p>^Wbd|{K>|$tfsH8MAy>)>R zw0^1*FhIYHM$gMNpg0Wu{>HjRz^p*36m)*>50zSDjnVsWDDl=+^ByH7q;A+p`_ACd~De!VOsC7k8H;E zLnt88R#uwEBFi#B89w{-PT|a0&}$h=Yfs{of*r%%_fbhlQx;N``kq3@(6t;!a|Y_z z63>jCc|Jbb*kyF&F46w}3jr8(!gTrN%@5=06;ujeiZ^bGs^~Lg&6zAJismmr&7~;K zJxvKhXUx8*%LoXGI0hR~el^;wXUm&apP;!gR&+G26M$cwd^CsZt-9&9L-r$RF~)%1 zYllFJ08NAxDwOZXD4EH98CFX7t_Un!zeUTRpeXi=O49V4G>4~{Q%!iz3K}6bM4s|B=+JoasS>f0H9V6zxO-3Wvq7 zTV0}9Q(b9j%UV01nLo6O9V}ExFRv~;EvOjY#mhHzhrVGDVcTu4L=jSo|i4`HYJ{~WQ zFov~ZIk84TxHtxrKGkrU_o*{}%qx&W+px%OBT=N`S2+P4FZHcjq07wx2men0f3p?< zAAq@*@t26QZDQ%!Ow%PFvUKtmZ(wpX{KW6K_%V)SZ)Jw9qhdfP`FS3s)g(SIcyyy;_%X0LGu~jh<`9|tv+>Jt0uiAAiD(Ue69xm$d$*#| z`W++=KM^?`}zUsb&cc^b`92fqV;={F)xJr z-n@BDA@1&q))wA0^ZXM936Cfm+P+5LXbvsj>)q05lQvC{DT zH0bYUISKaD%f?P*=;$Tp-DdwBzZ)#`2JbSfzZK_3!JMBzha)UjMHY*KR=l?1+)Vfd8s(>ZF|Le@$BQ~WY@WW1c8hD@KoY8hFe zpGI=VPv%;HK)jz&J2WXbPmzj;qcz68l)tDy5O^VN{{3mic?70_(@;s10`L6F^l5j1 zMza+9gmgl)6e;po02%Er7+Ha#yV>X2ZWXg*+%oKL37SBq?#xA{a96I5NnZrN4;p$a zglur@AmC4EL3wpseLq=wl{`;qDq^&MeZgYFD;ZTrIQilBM2ZjGM3_I7f7u%1>fl&Z z7d^6m$$7(vtCve!QTp_YQkhAC@UMcPpD`$}_5xHhO!S*9&i4zd02uskF_nAqDPh$2N_Em;2!o2S*`G4pjjzY zdB>1k*nw@Iew|iJG`ik8tMPQN%)-OikHO2d2MjN*Kn(GTW{Jgzlr2x__$k#deq+4# zqGMK}i4{us4GgE*i^e-wsfw0A1{Jj$Fs?zJ7Bm)9smj@@DT>V)-|TGEs_K-$VQEgy zD=8~6Jw9~jg3hdE?>CJxC`3A-`g$9N(KN>^RUfL)5;|fH3DY+Z~{$0ThKI{FP}YV3jmFicWzk?4DHiK zK$7k)v}HA42LCfG)|@fcWL?jbRalmBV`Rb$Cl=j9DtWlrYX+OpS#m=O+80r zK*J%O@D1oDE)niEJfuMXfKGnYFt6j1ca5c?(v7k5l!dL{KB55Y#Iick2mFOnBYI33 zrK;`_IkC7c>cur0J}@2sQD;lxCnYv|&8TLuO<@e&TQ1EgX6cUj2C{^M^pmK-(W3Q~ zGH+J`OPancUnUP29W4i{Mqd~vf~7eeJ3&xYXt47s4_PmVW3n~{7~X}CiCMv2cZ}f+ zW+vrql#Cd9Cm!N1-WHw~KDh8^Vw_n*7`$W!fB3bkZaQJ(ggW`xdJn8}|EGOu!Y+$f z1PK$t&{Z~C3F^b1N#~MQ1|jc*amkh#vv*!>|CmxO?ZK~P2bLfzyI;Q^lzHr-bH}ZG z@zU@5BBa35pZ}pRz>i_qjw(oRc*ALjJry8YKjKi*Hc-0v;c;Rs!`T?=fH$ryu<07e zI&@yZ%GEH;MWaT}TFY`Tiuc|Ni(a^E5A`G|svnl79#;l)@a1Qqcv?_gZ-r%ym3I*k zmP$ZainDnZKT*bxS^Z@W#kB=+-n%B7m5s;)fFwh2vbU;MiW1#R^6g{5O)-6#Q?=+$ zzmE|vo}S?iuDejp{StAVRIy|*v@$TXu_xGPgYX8jum44s1Rx^=Bbx<~h2J5=en6)2 z7nwR3S!2A(`%&<$&;y=$d!$^@ntH)t*Kk*HWT<~DE}Z|i;;eYr_ByL>`{55RNiRz4 zE>oAqtC~Yxl0lDDD<3qXvt5)BhPn4R5B}euVVN<*HVSaBmcG><&HVeZ3ZjeHBvlX^@1@_Xuy(3>y~u%Y=-DF^nhfG@1jqVOaBd!SMLKLf-PAwPnd zCvpWSQym!iLM=dbraI7uEkx3x_O66u{={KGTM1On5$0jMb;g4e%DLzzTh;|ocfp_^ ziyBD+a_QChGs-}TO&-lw`y{WM9$oK0F6&a{MQ-A-jO7B4G6cp?^3%>yesn;yY9-4H zYOsc0#Va3Vj^s;ajoFxUKAdV*INb1$?6pbc+OSznyR6cD{7?q{0_k=7LEbdzUwirq!b0nz2oD{891aurYjf zj({pa?4*6<_-JQRkz7}sO>a%6Sx;Nvei!GMb}5%2O=RI0W*qG-nc_5rC7B1ejU)s6 zoh064HFuH$)el|!rEQO5lIFApq;{c4BLjeuuB;f36iBWz!|Cz1<3}HSwy}mqV5Gi_ zc0QywbK;=+n}A)7=W2X6>ejAb9)~J9x-w)Ub_Y-Hvrjn^i4$#+W%?~WScUFrAst2@Oz5aTXIG};t zUS^>!c8bwr{psj7Yy(>F$RO7lfzmY@XLa%flf9UMo+wnzmoo!K={J?uqj9yNo;@=`) z3N!Yx?PxN;mvvbdC7-i@@s~7|>ck0;Zh-@m*IkcH4rmX075R|6I5v}ROHqdLlPOS& zF+eFsY9*TjrTEz1Jl(ax1laAX*#~O%T~b_Jf_EI6^oYiQ$S-KI`?y!MFS!C7pT$^= zu_+E8Ew1x4dHr5UvN_VS-z%%~FqUDotH4cJmL#{U7^@CltCx?KE$h3`N$jMwJjg<) zNGR?LPrP63NO9Ow6|1cPWv*`Y7c{OsGY39>kk!GhGIw#X=rEYva+VSWxIL|8E1f*` z_aeYY<+Q<_rXrd~viB7S*W2=pxm2O$#2-}#KZ0Fbv5@Fy?dO>j#`Uo3040u)caK`m zqJdC`ptJCg^l)uCozK6c-5J~7daMDwZHy7=FxW3WV|S1EyT5m~@vpqxPK9fdVJuEn zOmgu04g5L!E48HI46Vxccxeaq?v4XsLsjU~6>^~^GbgB_xX(-g4#xbny78@V(?_-N z*_e9`jG>$0dC)-cg8&VT&FjEq*|O`utvEa_U_-`ei1gm}i`Fu{mTh}Q5TljsI$fnl zmcTp^EMYr9*?aJ3t?O*FTzP4o4n}92rkLb3#)$9kg zw{98y$UC>}&dA(d1}sGoKuLVCN)JxvxLx3Z(sfPG+0aH8fD@H-@4c%!qy%uQYNIpK zkl{Fs1KceRT^`gw!l(}L7G(EZd~)sjXU|wP=s%!6831+3;F25or{sigOYZFbQF({Z z%zE|WJhk0fcbwL|pqgbSab%k(<60)Mw7q#p?`_4=AKq5n;J+1@p;#SwTXF7!#@Oe# z6~}ORS8>MWgBRN`>?v#V-^-Q_O3G3RGj1i`cSE`1GIGmAYfFkSV{y-4(z5;`Ef65B zYs5JtuR}y=E45Bt;ng;p03gHFr%c$|O64o_x$rq)-uMr1c?-VfjmYgE-nIeW2En`~ z0=$Xd@fQ5R8u3uGff6bbgPPO@#9#2EEI0z<7jAXMkiP^(V7^5~X71S<&ulSR< z0bqK437)p_)lw2%%*tJJvp?e3Ohrfa6k}`&JuviorZz!yg;@OQaf9d%ctY?Ue&wX7 zW=E~FX)0YoP>I%R7G*NHzlQ|!3wxH6GcdH`7{tqcw&ko0AbYSF6TO|SaSalvbvs1k z4%y(sI{*q#V!OKh?i!)ZGSndi_7ByQlR7kNjQr z4jK;d0gV&=N8?Zhz#6wQd4{()D7mprt33!Gd~~KYaU%Z{6`CtJ^Bzj;jH8+?nmV3V2YG zgypPT4;l?T@y>(#Yt1J7)!+Ytt%_XD2!_&Byf-9RkW6i5vyU7{C_T?AF2W{f3BOOc$4?R2W$L&nY^6$(@yAOVH11i10m_fFv1Ksm9CU{5sjwy?~5${#Z3I!s$ma54rAfrint zsdqp`s_*Oz{!Q@IJ9h1xy6JS-b{9(J(63HDBCXEZq}mfN zMFxiQ)~Y76_Ivm$Lo=8z%E@>C%qb5)wrwXE@DzRApEzL$gj*n*q|c13`mlH21=zPtSK z69^ZnaonH3-3I!yB&8MS*1A=F0*l(56B1a|CSLp_YKpe)Q}4i{#@U4Dz}L?Uwnt9v zx1kf`r->hb?9l|vtv$L!2iT*kPq+4nt@Ba8#C@t$T?+7bpXw~)JMj%U3RIt`>mGrg zn!;8s1Y~@kr;E*NqkX`p$?*R%Ha9NxOyo7yU(-ya>wPevF`|5p2@X;3ZHZME% z?v#o!mKuR3Ui?>>6Lg^kcH`?#hZ-ceZd?*@(!0gI1J<*N zANOt?_%VUfm0LHy>=Y3nG3j7_cbn-kkbQT_jcxB+_8z?M4}*pX3^{^n@% z@jRTwX*VEbFI;xj~?UWYkMzYuj&fV@GYk zx>UbrdKnsz7*@Y_hEZTdu*um^K>X7oawuExJV!{i$;PcvEAWKB{Vy9chnuObJVIOO zFdJL~gt6SFxdQz_cdrF2y5AQ0xx5Yk7EtA0!_+nTp2G{@&~%qa0i`hAySu3Pvp_AS z5Ggnr-L3Op!=@R>@EoM*PLV_Ar}9D`zkwt39%dW6*$bNZ{JP71w3d|lr+nv5B!<}G9;G=4TbzDbm0nh?g3GXQQpdS+*#C;C$P6%AHd;Y zz7M~-BpnYTQQLGil${>}d+%cDAPHceQ_()8alu->dfY3V(rEdMP~LN?;}k1^PsOj4 zzD-&w6Mj&w)kt=M7X!vVDm;cHnCiG>xc_uQl_q+j_f!HClj`w(G6D!=3WYp)DmCZ0 z7ZRl`P8!563dNrQeF;%PP_u~NA31S2O z?ga8NfW2*F+@AZ$dJdzUc*IS;g1tg$2^KX5!#w^5R=$l26id>LEj- z9#v{=7J5LEt-_y?<%@Sf*kA1coNaHTJ-2CpmuoI*Z%|t7tpV3Jaa1_pevt?m@FqD2 z1qoRyNVYznui#(={KUIq0NdM0*>#t81*lg#Jb6gFOj`P-lM92@qgLFf7g8;cCK08s zFI;t#V!|`j7r_pVEnL}3%HF(Rdd4qQtC{00nA;yABocv#E4)S@4DUn&24 zk<8lpsAQ3?VYXiyEn-o_$HBfSH5L#``z7dpX<*PN1@`eI%@_x28FksNe7?V&&t@3D zzhFeJs@G%A8ve<%R`I;h>AEa67JLb+NLh#7`DjTL%o$)F9qfOAIRjSsPgLL)-fMUo zTy0!iFCQqo7g`79{}9^rmPgJCV4($3;PmoTuY!fvVd!3H0jB>5ZR-Cfw6ZaOgm#7E zuh6E&-U)3Uy<2K*LAo@f*X!=Pu;_uakI2`~YSX8Q=?pmO4GDEiPddbcoZ)f8|G9u~ zY(sgiwQEQQPPF>fw2BSMaMFTi@dc^w5P~8)#DH?M1pDY z`df#PfVQA3``KDsnPQR7<IH#6gya167hf@mc&F~w~S(<3e{83ET9mF95L5_!)`Xopc^ZZ*@g zyWF4RcDLp8AV*q0Z(R0X;V{xX7LIwaGM2!%eztUwSlr>7@oEe{;qi!w@@_N#ffqMY z_PL#Ucl_;`0oU|^hjAE#morc}WAn}{FReQ1+QuaMwzTU57e5$W7$TNzPX|APr<|+B zVY$CR2k!jh5=}ju(oRTTXTiiDJ#v_4;ziD4->kh0N+~}b06V2M2r&4WpLuowrT2-s z4@!MvN`vm+kqAQ6I==5Z8e_hlhpx*4et+~$Zg_usO4ZBx zl`p5=m@@O}ye!R3tpZ1d&~^lD$AUJO7l)HcBK{>HwvnnAPXteQQ93E+{Qu(S(~8?GQqg?ur4J0MxRR{eqeTMo#-4P%!5sW+r2lZHHYHTq;Ub1LrR zMoyVo*ZZxAm39IS6+FpJzYRxAw+OlgT!HrW&$At+<_W}>h(BJ0q#ISR=c+f-(+0g z1aNoPa%D{bcO^+fmH@Ue%&@*V6aRbiOc3aI?#Z(?o|t_g4~WqHflb`@h+7gzApJy@ z*aaK6u}$#>aNPom2cxTHYGXL+N67b=EvvmyNNl8}-?>Fs`!Bk1CeYGTFgm(=z4((` zbPPKW=xYC>s|BAdW8Z!u_+%jxOkD54!Gap6`|sutkjpPUeV9L5E%DCDg>Y&acI6%W z^{Wve*MzW3M^fD+KiSDw)bS_Tps&+!pTi|AyPTvk`^s`pi;}}L&bjNTMw!SrK zcehkP{@%g&pr)Xpr#tN0sD(r`tEC-#)9clIj9w@SMTDY~*P*P$m}#2Se~rB|jb_$n zfIUN8of3-3*8pY2>`*NGrFsfZ9gxM|{K6;q;<$3RZO7f0{vJ!dYqPN9sP!6-GHL(u z#yG!%r8h)J_(&7XRbSGSvy!wW` z_qrP{+XhlHu)4|zn11RlU&;R*HZu~HWAZgotHqpqUD{3ljQ?}sO{!_AW8f*l`&l#o zgN`*jM|e8yO7`e*hGK>NXdj$~o1;Y3oxlrG86DUa3f0I|kalHPV|XIQ)5Rz~>Y~gK zCNuf-juH@MZ!w(B6vF~*?(QB#(vj^rc+K6&x?OXx@o$1Ec8IFUq;Ke9vx*U&Bh@+kooxdGcL-bV5Z20+ zlUj}l=9u=3ylsXlG{l0zQ7deACo=pSL)o$z&csY$fCr)nz@ws;6ZncJ{q{Xt;EKon z(MC=HH351XfHKLxWkM653ii zqXf(ejJ?&eiJCfAzwh~(f7II-!X zkLUq+fF|yJ2bk#}K6HSIenh++Z~>)`dmDiAG4?f^-L}A-dn0oq96(|bDX5eo;(rce-ShaQATH zrQ*2$yjDl}ytpE4#o%I@(7QP1zg9l^{J}Mn^f)u#?~+UEqvV%6p=k`+8Aj#vQBK-Q zhZX(ATT~OXoO;0aChVtpQMLn#_)^9N?otOQ2lG!PJhRc;U$U5kiIzXJF}wVl^<{VI z@UFY(SeyaamL9rKnaS);eVW+-a{if(j#gX zxBq@5ehPfy9S>?uFp=M5NMw`^;GkspJALx&FUV7aoOhH}IX-%AI4->Ly~(A(J@jZX zN87CptdIDGIU^8O1myi5PjeMpMs0i3snW$JNy&4%L%y;Z;J1i@UL)2w7T+TaDYC>s z{2AbZThEKUM=4LgX|T%Mu?P+W;>(X{JU4a;e)^Ria zwiNjtH*wr_mUv(_U%3+HBrEpc{}BW)4yjd`-nS(z<2Sq?x*Z*Ng#iYzD`8EWr_p&&YH7L(Gvd<_wTS{Plz7Ru4Ri9<^4`QEs>j z0vKuLYq8PbmM&cdCAAEssB&En;#!kK*jsDWO^(P)nq&}HeexRN0I=Ln-AFdPdv!#lD0m;#* zhFZX{7p0^9?CkNW(M4$%+$Q7c{3l{=P_BE`sFp|JOAG3bCm)GNEO=vZ|7bU(#Kpf286d0jH}~O*FtqN$a@O?IGbRKvsP$S^1Fy7B7Ejz+>V*hNVZc(i z1Kx;bo4XBvA;|EUeeW>)jfC6>^p~cs>_MTnCD`r0OtA%VPvruKqwU6nB}9NaWGMuG zJ(NI;OPy=R+BBgZXD3kK`=Kd;XF;eBSbrDBOm@H!4Z&~9yw^)z?g7?I+z#zTViEFA z?tk74ZsA@w)3Vd0f>&+#g>z{0NXkmwWt37~*L;&xQ8BW@rv$rF6Y?{vt zL=af#cAMqipEN@RbQKjqVIl&U!l$W982kDW8|+4@jzZnZ0UL~y2gD>`}m zx_cMhadwyQ{Sm`(JBWEGeoHYk9xsG?rcO1l&9I-Rr6?5!l>T{%jQL#>vD#$wW4{k} zvz}Tkh%12Ovb)JBW1C2#;EFlQV_*LU7oFKH@NyMwL2MW1!-+2;U)*RK(NQ&ueeTl7Yd!q>REkZPDk>Qp5^ma+8UG49(=r)XUhjy$yfs5Vc2u;F$ z?1lD2E0%W_(*qc~`h+_xp9Tl0g%7Hk(Q^uzQQl_hXVP&({Zb$Jg!?a&%tAe&7QmnO>`QMe=<)~AB$HTQMn?gr<_tpH zuUwZ|2^)UHNk)*p7xNFtqVHg+O~+6RmHpkDpJ=uglp#+)#hMc*AT-7K0PyytEsWsKKyK3|8X{c8qj`RVm zxK4KG2Bzyl2u%cH#ZA?!-t)|E?zrn2KmR$WDEWv5l%V^{bYwo9>%*(!USw#0j1uIk zOjki(n}I4KMEt1l@0nW%{=w+PoJqO=IHIP5s@;kQS3{-Uo6&0CEh6p{-u8G7p zoD&W>Z-1d#Y)h0XcS{4pDjv*I7eA+d(8stP8LNQNotOmFs{Rammg%6|$ zJs9Nz%;_Thvq|&gsuB^x5*(211vbY zeC!`;bR&13#=DJE4kC~2Tled#5ckMi5nWUhy1f@=0%{heu0MB>qE?|jEujr3TVcHnnTUS4o-lY8IrlATJQ-utB@rb4!trJ7k zXFh-M;^yjlGrZyEWOP8O@mhuaY{u*6%I4-`GyE8FNS-hgH}c795sLU2*&w4xiR4qv zYVD6PD4DoO81S#MUgMurVLqA>>$G+?{1O6ze!T)A&IrW^f=?Y*Q^!cigf9})60|`F z0Y7Gp8pu)EN`~qFQ}{grZM}IzVq$ZBz^o!h`Epw znXMC_30lg<_57KcNQm{4D{5k%5DL>!^f^n=^K@LO6_XEhNMTJeKEKR!UstMTV)z>{ ztMPwC37gb?Aq}V0yY>L^lX#~!a#$_(^MLUGfzLr)OVGz4ikGH42hqYZRGjAci$9sO z4!x&f@Kv{>_GWsK3)42vE1LG$3W*IK08@01y;4MxNW7c6-+Vlz;o%E^gHk=YDS%iE ziCbd#ThTJP=_pN=kceQ*6_n`RSq4LeSwJjAFW|(jJHLE}rdf9UrbLhIi4o?twBu_-$$_8nu)tf z5Cvw#_SFz1rUS1EO?*)OPRZx@9h|))TX|%-2rt;N#wPzdi2# z|2*y;$xdsl+)j5WF_?>BGAKS5#o5&Q?qm>*_^H7BJ|wsVUmW|sHk75mD`-5UwS#e= z`LL%(Czm=l1;Q-pWn3BqPGP~t88Dcp@1jL7L;c%yj`6}Y)1!Y#B8PQhvA$i%#8nxi zZAZ(*6(vzbf($ELcY}*2=Fn}5J&<&j-3TQ{Yin+!!yh0c5OnX z?mEoTsS8aWw@2-9nv)FRb9sJgz=WtY$@)G*@QsojXUr{Q6kUHATiOL0B-r=Y<1k~P z$Gj{wu##QmKqbjjesF|nOI5%M%g(Y9d10Fnu=y+VmN5U&{~(N8=7BJ$nm3y{5Tj+Gv!4fp?- z%fBtQO6C91mKzzcw)pvruRR9N^-~nr}&eGrpp&MIZT-5+> zPpyl40wF`ltEUWn4&|F4KN*Wr(@9>rS+j*~;d|Y$8B3kh*}k98@B4WC{&;h|ALsRQ&2?Yb^Lk#- z>$;t$mvX1;XNV~AN!EY4;FY~zb>qVol7%I%khISA?qr=ymsIzOHlE@3Jnem}I%CM# zu4Im&*oQs<=*<^v1fjT;NGvO{@!Xanzrmucq;y!eT}1LMUL-N>mne?>&nJEbNCE4m zrhArfJ=*3iy6L5kiqY>1s{5=_gcJ77XyNcA2Fi(SBh_9Ctv}&!n)FCdWRtUd{RyE> z2Wj;umTecfYdExV_V2Ttdf154abn|m#`0>v%56&I%wMhjs>5U?4ia`V@}kam#eLg9 z-Ssnh3{{UKe~0$A&ai1<%mqv3YW0ZOcl{(*EaUldRQuK9B^#CYZLoe(;<{zN=W&7e zTH3GTAc%Oiw@FP2JbnC%9!QHw!oEvE33~98D?dGku;fP9t;7$~8Eg8jYvFGWArIZS@wloG!ar`xOND4DVZRMW)=I z%Gv@o+>RC2Cu`fS`&(^hd3F!vme}I*dqeX_FJC-tTT)uEA!wO(MP+->N1GD!;KZ;` z-P$bwQikd9K`vD_d4}=UQ?mT=E7DTKj+s97HMV?w1)!ICV%gLx;~91=s9IcPuC`aP zFv@W?5$$b<_HEEvyJCh&VcMKqtU8k##(QKg)?N5!75O3F;p6O}>Z_`7*Z1@9hxxlar0ky^!M@2H;n$l_>O9B4 z^J?e}FX_t(;Yav;@FYVQ1(mfCoyRNs99`uq`nnUI8n=CIGd<&aZmykqGoyQ z=a>EN?#~a>^t&6G%acEQsqE#I8N*~^isOX=r^3<(1?7GxfQk3~V zY(Y}2yOe$65q<%g%Uy-uQu6qWX^9@so=O`Gb+q2hR9k+#I)7`ekX6-;kkTYyT&C2+ zQky;NW-nZ?e>pQH*01ncrQQXF+_$&Ay4)J2?ekOk57;VjO+$72Uc{H(WeaWz>bwmz zGYZ)=6bdk&Ga(jl7tS%|dtp827D9QmadUwjvcG`-@}L1&y%DhB7x zpTE#bM?}s+4Ct6edsjyFgVML8hr3z=82+cKr^yD@3!eClGK%59ul3lWh~&L3Rl|`R zmHuFy$nw82js@lVat=-JV>jwX_0F~B61lncz(yX1ftwF`x@PHd(gVGOYi$1f!R0!JDqE-YjzV%)_BuS+H&zXbk)18{ zWl#t2Q}5rheWCL?`lhL8NA$PoFD1w2PHhVjOB1p6C&iy@w!&rjYi=ExHrj>v9M*5~ z+VaHli22RTVRW#nz;3VU_J!oFCXSP zWu2~m9(Z_YqadH5%nYAWa(BsdbkIxZ-t}AVpvV95#m!6~U!HtJ@wA;c zGu>~5ocQzz3{C6Ae39hKxbA>=>8?m@D_CTjWqQf6b9z2v7E!%{IVWI*XuBj@PBQpwkVd;cm2wuI#{J=>bYB^<6nd&n&ZApRi^SH z8!R&IIZ%p}FLx-Jr*q|ICXgqVg|va={Q>6BWsd$r5nL(p;gv5((GyRmLx}XiZ;Y_k z*k8{Y>=~TnFOu7SCN6!4)CWf6%PRDPeqGuElHZqkwzo;i*F5FqgXZOy`ba&X&C7jc z9kO!cZqX!tqbFH!U-h-h;I}8}1Uz<{_NHOooo%WMB9el3=&W=8N(+qoFlN?r_5ESR zLrUMuZ8!41sigYq_V0;|ZFRDFN;#}0B}$%I=ae)rH`hbzo7fzZAz|^7kxo&;$eM_r zr$WodI*-$KcQ#z88eV8MmNvcVtXOHz+9eTsBek(Ay@g}d$9odK;xBo1^?j1I4*_(u zP{_R<psUG0>9VYQN=M*5j@&=JASmczoTHVZQieEUrBDWb_z(f zFdB`725(ABa(CXi-J}v+Y)wJW(|*Jt=t;&~rgV6wJqgpG@f1nnpIs-t;hI-APGP*2 zs(ev-h()X;gOjd~_arl#&MMlg)5`YcwA9R?irIMfdm5jO@MAnbS$&!ItV!R^T#hea z-z^J4a^wn=%k`E9PDeyvedNramrGWHW(nGnBm5sdq&Dcr`ufU^uv>nt zwm|M1Fn^KgE`%@-XE+^*&5cLMobD%)WVN41_MFh7TrFp5u_;{fvF&gIJJMphO5V-! z!Z12yh7({6{ml$=|7nAPcGrEIeHqVNVw=?REf4yEL(5zad1V}xHQQa+uYO7`f4|#U z^YeBQ>RiWNoSrE&G~BXNw$4@0y?u0LyzeEdC#r8*G~N zm0}o`D~51c&K_`?#jw9O3{t>g084?oaql_C&d4&>2?5Ww#G2|{nQM6dJ|QO8C!hcP z5$kyIps>{>i^LgOSeE8GSpvn5>AF5c=e5DWG9KC8(OptFo$Uq#!?trrYqq}c2WM@P z5OI_Hra7f&iqx+wN;J9{y30+mmq%94U;xoD{kq|kx;1`#GaL+A{d=pyz=@f%&&OSl z6|_n>H&ai&xuc^+U!A@Z7MLE0%*_fxj4_=0bqI zIvIeym@Ykjod^1LB>Y{!=&t@gxo;UaA9Ws?JBsR(!GPP;4hr+&G_89x4nWb>kM80X zg36QIUlzKdq_zDSyXTD0)jqO8Y5WMXx(4xwdDCwSebA6nGkJYe=)s6w@1f{7!Os$n zb!=|5%nYoty_{ixnY?E(DF<4B+nN*N60!FN$(-73jLRqr5hV61(bPW`H|;$!npJfu z8jlm!kHV8pn;)CC%vUvD9dLJlNPs@js*nJnRjjW+Ay*$Y54ql#d%kkxO}Xcmml=mb zJe77|{Fb16v&u1i&mDmbdf7=K*8Jtc1oVT|FT0QS4{1V^x^7{($7V5Q(tIZ z@$vn#S-5_%qrum6o={X~$vVSdm{Ouj-p!APS58k%6DiFR1E~4nP<}b{$*`ZG{imz< z7v(1HS$0@t)4=8BT31~8MIuF%hE57uOZstlEn_`-;+1w{+FhlCqF(c~Eh`;1XtpaL zsL9wdb35Hrm|J*xzDEl`NZEbgZpmkqsN6hq*fuPs_!XD1wsCE}Kw*tmi}&Y}=SoU% zgk3#Sj<0e{c>iMc^<|d|89Kjizfxegu=M0T_Z$8vv>g}LpS(v~XtiC0ynIDC_fimQ zwu4Y}-6QdWA?z8sc?MSxOuX;L>y z2)mVSMIm^he#gPkoBTB~>$rqFpIkhzc&1#sFS~^Y8B6zQal0Rd7cLVhbTbk4BY5I( z`xA^S`aQy~9yvVI#Y5?m1NM!lD{r1 z>Os&KUgm+m;7;n{wL1QGTp(9 z6L)%MEcmodvS6OQqQGN(h0m+U^tjf?SKQLGu3j4uzG~+=x~V~gYXvosGQ;K8P1QpI ziJeXZW@B$9)g1tcjuUUkDR=6#oc=WqMza_>HQk+#GNH`O|~ zq9&%!9Bbd*s>#V0)8C40-G1fqu%k_K(pMEV`IQg*Yu;4U-SJN@-ezwyeaV&9f@8Ae zJzBD(>-w7AC7vc_$%Y=7E9Cs@^ty+KK1rWBl)~@VC|!Kb%lTYJ$72ufmwHw`Atu%K z39XH!2WAU(Y3D*xQ+#nc3u6KVD_R>Xi`VKhWCRqIlld1MP~aM3ed|u+Y{vpZh*EaNFAUb-x-LXy_9>fFEs$(HKdrQ`Vd(n>BWI{>vlB1fC{krVdheG&1u| zTmx{jwGYg!_gLNNvE6l-4j({)>tzbRY?Czm2ZGbIuuq}pVjYa+pPAOfV}&1@F?e}{X93QLd6AI8;D{q=lAodwjudNHmS8O z!QT1HLMz#~ryrrJCEKY>`x1NSv-6jzO4YmHO#D+kzo?~l$`CfCbCsr$hkRpVcdV}H z%+vGknt3?t_RN;TQ*AZcb*n`)8`3l9`Zh{$xZ}lfQh_Txg`f39_Id>_o4(fSr8r;m z>Ux^()q$KDv4Rgb+i#KxcN6c1GGX~ZNMnDDuL2anud&U%PS)6dNRF?ims$eV zb&L6KC#bHzjeSp@Rm3<;_w#I_3N0$sV*k)#A(R}mM|iD;vt{&Njq=lP1a}WOxUX(o z+`4E*`2(?1&hR6JLv_2|EFrFa8?W=S9~Q^nbPGL^E*YvK~A`tUAa8+36 z+!8*mUR@!FU7LcJLli9ceU3L&54m!7lgyT+PhmH|qNaDzdU%J_Ud8rVz9!T=c;1K? zVEmbmlDEjv}8AhG@VlOxs1)+!B^O5$%fm%He#jGJ4^NeHuOPmXs@ zRO#J8`SOB`kiyUWDD8aNi-WAdbs(8vz8rx<_Q~f@fb=mIS~1Ia)}ljqP1KekBwabp zNk4t-aoE9M?VOcA8*wsr1pB2$Ylt%M2OPMsk(SZ`>M_d>mQgNR`*}oLGsBkRnApX=~mhb=dyJ9Z3YDeX)m;5 zT({70y>CvdF%I30`b+Pb1O)ryL8yBl> z7We={ErC~Hzm$Zta)chQDWnAR<8@xPcV}VV&7=q!MxvB(DSK@Oyq&(jH9N|PSq$L9 z1lfYILSR2f(@`_EZ|@zg4$`;Th{&JukudFAb+90%WjS?EpM=cX7LKXjnQ~;N`Lp;e z-dQYN`{7~7Wwkr^KF_PBEN;zSmRtvFBpuX90;rKZ5%rgakBczD$ts=;$g^D(Jr~5S zT)|;lIE&_XcrZ^)7g>~6SA6dm(VX{TIJ%KpG6z}t+B!$UXBT@q6iTe=E!$HYGFFcs zxMQM{pBpb}egE9svR|if%lJ^btibrm(=-VM|Cb%Ns?5JbI`$7A0J&_J9!{$|F;i`6 z@B-;i)v<$chpNdMKK#j?rrlfkd>JkJQpNzx;e$sH*}TFM=G6X6)honYjzOxlB4kc8 zqCR%}bg}v@0zCD#(4c!gILTxA9hGKE)H{{;IM#oBq@A$$(MezD!qCPAWbn)MajQz0u~ zQT!Q{m(2&&c1xTA>Ef?4vnSf^6F0)+#~lYr$X~qTJ}i1WY7TrL@MaLWx1J1Dv$E z8Tc9!gOO&w$(Bdxz%x$zGpk1fhS|myHuMjlzr5--O?oZlla;B!MHmd`p0F%iT7gTz zDr=`OU+I!P@1r{8)cjYsi5MTlP~{~;l@bH%=+u{|09Ry!<(*j&c_JC%WtW>*wk9?; zr8i0nyy8RfMy@uv3B)?{hGC$lyUAnuaH zL_L~X2ONV@9f*6RS8ZUu>hzmssV}iQa1*NoF`xCVZdSk)m#n^*UCxRrsJ1Z$#9Z7^ zLosi+cqYMv?lF%Lwz~BO-NgMy&PnSiJxkj_TU4)Y z(K*4aoq}fVa7yniSlr`>>ex;wESq~v&>Aa`Y8m6@kzCzkwQ51WG@)~JhW&;QEmi_I zBa#gyJFa{(>T8L1jA87Mnq)DPlt$D7oHcy-4&g(zOn*gGN2aR(aH~l59xROGu`qV9 zicXFHyD(0iF&@SaZWCeL5p#X-0u;vUPQc$AeDc)ntquLzPTltw=fb8P3NWE$yt5w?N%Tzji{OzqG}_Hci^-A_iv3z-PUqc;hvu5va6BY5zJk3;oOwX zw@ag1cSQq4)1mi(C*bkBbtsav#Q+(w-h*;Sa+$oOGop4@x91>;#ttp*2II8CJ?o7Q z#2buL?Xi1;EK*~>#14fOzIi3JvA2ypd*r^miEQX?&*q!bwz2LtJVFWNJWdS-xHZxrR<^N~JcR`5HjA#9^+%%Z2wGO)0R9W}+>Zzw(T> zESrpwDrxZvsP2@nQG^^OG;@RFF-ff*(U}eUbdryE5}oAA&xC&*|0=(W zPNE7`S!|9eBob+}mvs^fiI(1s5Gugv3`Ph-8(6?#AgGBV&@RpACCqK|UBt!uDzKa( zrLn@iHtYOIZ|iV>ZN~5yAE$4F?XUV3Ge_!LUL|SR_w-gD$jbBK8sl_V@zF6<*FzNp z7qZP+84dvZ=fFa)1gIWsH*lL0H0Cn#4A*>QFred!fn!67z;h92XG1pn24Q|_M|ele ziTVVsZD46N(UN_j2nBFhoKu_kTjAJo{s$b$jzTOMaA5I7pkppfZoujYyiOn+aG-`` z7QJq}o->soa4UysT#@r))+~U4y4``}Y@KzctV*_1TbPfsw5d3y1Fsq|(ufZvAqXJQ zFbE)8#;MZ&4g!QGAb@yj0s_pSZ+*>ep=P ze4>ijL!-VEPlz&2v!y>7StZue!>G;Bx6xgxk-oTW|FWo>=-UV#;o;Y^*>Iu=>(N(3 zLfc6y+C!o@;-}gH#RiK^^r?6cS`=L9pLRlxLHR0^O{DX_Qe%~|6C9AdYOEZd@(nN` z;CFv_7v+6t883*Jw#=s=&mwAri%>7qr1O0*fqKrAG)&f_%@mK*Xh$p?mE^1K63?uDS?+~1o!6{Zv z#qR-|n(^YO(i8Qe(q94FDv0_Epw@$`#cC5bJVTwmiy~^GQSZdWQk(;$U<|2AhKMtM zLnpPn4xDQauv}-=8=_BJ+PD>W7WG8M1`TGs9DPztP9W>gj@ zWiNa1$mZph%&F_24<0Rza~6j6PoAb?cQO-(x>Ot@AKAoEVS=D672zOPmzCtXsJtLr zMyb&hj%TH8f?qZPo0d3Z>j^Hx_VS+wcaafK2jZ{aW&JBG>vQ}W4WDD*W)toC=2GMs zAqBzJa?WC#fM?<7u)iL>R*%2q_0AiTOaUd?g@Th`1Gd30$2bv&h7+9Vk6CYMfg3z2 zL?;=_ax~eqB?C2D@jP_gLLjcN9MyrquzkL%s!yU-+R&9U;|lYNl#sgH)nN@F(gZ<; z%LTs1{swTEyL4B-r3%sunu_mr;8Xpm&2xUh!>9>79M?c5BpxOv@mSLve*nY}7NDv? zqNV!r9>fxD8Uv!K&02!~%ti+|5s4c(QL;f3#)es71gFMg({ND0rdbEoh)@0TprRQe zAVdEZnZ9sof=pw9#3Iww=0}bAQ)1;teOO#u$EXi__DaC%*nWFoC;>e9kEJ%vz-M;= z7T1{uYljOVtQ9~NVHXNwU~8-`(srOi=U(BWds4T|=ET0bxIx_w7X7rldY$IDw)2yN zI$HoybEZ13lR)dd`v`##a`6;gX8$w=p0UV5@QgzE-amq8PCDv&O1;azvj?;$HLU4j z1r8!2*?f6{q}uQvf>BZ%%BdNIl#oB96QX_45E87QjM9wyKH^hR=uvUTp+LDNss;GU zph@TKUu$1K+QVuNiIz$eMZIMm<4wCN@(ve}3{<=RB)g#n`(F#1!=lbwl$s1qaYESz zdTf;y1(2DS{?n@E;)bdgH{m+9d6x~&_%+ee1ItbkIti2_Ml(KDKad1Uk?ZxHqU^Rn z1ru8baYvDhaZ$8Buhd9X^!iq0P|Lb#Bzm5MOx_vdPX0#UN#1f#9k0KI23;( zY!E=$$hokCAqBz)As%uGiWDHM%5*9Y2^%ydY&1LoVT1k?VS|8#4GQjRGY{jby$V*c zIO&U3U4-XU5G_{=WS4rw40j6fxk)sI73`p#dyCSWjiapUK2gvy*X#q=6gpC`PP!&Y zzTb~Lmk#Ro-+87-)CH3=zDw;?l-l}~`#l7^w$+r;1&k1FA7Gn%RaAt3#Wp-%>+izO@V1Bi_k+t`{_FCS>UEiv%V%I)Z@RDN#9s}Cs4!_8$|x39zcs+(RhbW zLM<{QmVruD27ME0^^s&qSSMqfBh-kN9g|!8$PGw}@Gs zj~P7+#VN@o&0uUT^f?RHLV;S%#YSJ$Kp-S_(ek98P&ll{IPoN9DPqVH5%0~x7|Zqv zmIHc*4Hhuyh?HkQ&6V27!}=<^n@)1vcS9oLJ5!Xhfiwcs2L=!agzJL^q;;kDkBp1m zf{b?}GGd1cUT8u19ug)BD^Z~LT8(jQ;d&3`Okb5xo0XL5O$%m=5t>IY1*B9Ykk9JN^3z{^`K# zCtX8oERj~p+xJNa3*QUGk8v+QZSh%Sq)6i_iC5d$8z5~P;%*`ry2rEmiL|ZorjPSw z)IEs=b42y}<~J46NlD-q&>@x{VuTDH6>2KhRLwV~Lp5;GGd$LLW4=SYySi+sk7x6B z>7o65A!0aX8neGl2b2uVet*lS5vvByRM0gvLse;Ja7dLFPX**qWyvR&TP)!H8en9J ztNtfE{O^I+pZ8$*?h&X0Cb)Z86;PyoFc_H+sr>Dcon`uTa*gmL`=!J%5W3WL7@@;S zPTIi;F@j2>+*G`RrMgV0B)cb6l5yfZAtST!CDmXpl5M8+boH^eNMeV>##$5`I?$;a z+p`6O<^yVJ*sc%=cUj zW7aH$xF$HzXff)5P!~0*EM`V-LO4jXOPo$Xv*s-&EqAEc% zX7r!IuKM+azV@u>%9AHX??6*b^vZy&%7#Xwpfn z>#6G-X59*q!o?Q0FxIEx${rr-4?K zHTKLYaBLv0Ofqxm%Yg$U0w(L}UD-xC<>D$Ffn&YI zxva~JK3jg(x6s+Um@_qTVKS8aBhpKkF=slK+*5Vd8`ko-=4kpr7NtiS9dJee@?732 z)@Q>mlG&|%PMM{;AJpjtBe1$%>}JlSIjZV6it24Nip{6xd=V=BlsCV&GG#|vKmW<} zRwv=;Cp7bTVa0FKGCYJnjRI{e2`;*79(;4vQq7Anul*KT*QL9DNbB|Ou}JR&dC3F1 z83ufmQ(3ZQIIvI1jqMl{dG+YF+01gO4Phi_JsQ&sKAY3+3QB93Dl*GC5gw{^)SbUy z+)J{8Wuk_=75M-mWrEGc|MkRfjmO?KcgjlnS=kA$w8 zN12w@yh|ec(6v zUY7i#HJ8e@`xbp%X*(1d^wrBReB9OTV#g{u=~T776bRet?l%~ z7L6k!>(wcORejzP&niC3Q+BXyJJOx^KAM|wHmi9+XOl}B^TSN8(GA0nC7;42O>{ zuW?mW;plpxJZ2B&O?$(j)=Y(~yp*r-l1=-wnsr2+?PM6XIlO>!O%Jcu zaGUny=EyK!A(Uz3gz%esRyoq(^2{>bXD%w&iI%?ykZ7T`_)ubb3^!pGRknmtP-=HZ zMu1TstC$ldCct`lBBgUQQA*FC=L^lKY7%xsXS0?z4^kR)RVLB$oieSJSB%~r8(6T$ zR*-JKlBS@nkkjHvdJYK@q&0deh=C!mFIEj4# zU59YLOwFMJ{Hom|6jk`6JX~~d;?YY74?V|=-_9Q(&RM`q*-VYx!$%ovoDF!ZLbHXZ z&2bW6Ux!TbMbm=UA;=T(1|?zEZzo7lf9KDUF2JYGT1MGi(YVr|q+iOEA1ai(L!zO$ z_ak{s#apl&@D}}Yj))_;`BK^bO0?(4EVB3FLlPVa7AT8r@rPG3uQck!v;C`YfMy}*b5HqEre99M!@ zeGIRBhTr;_o6uy<4psQ|4`ip<&&jw#R8jEaX4Lb$u~XL^r!;TECB=t|@X=!XDbJIv z7gj;p$;`p0zD{0e@kc+b7d~Kg{IyhW-L{+;c-4=EAtcO*RtWyf#2Y90D2(=_IsU1A zzaYOE>Skkxvrl9`^~8QrJ}e$saQ3|;NV*&y>iEhJ9BoZooC0eq_eNBY5KAc)PSJ60 zm(6`{d)$^GuNQ{!T!?EyQHs9Fmr7-~s7b8GXA}KNv~;4SEOsy%5Nj)GbD$POoCGC~ z=kIv}z~59rBOpMFqLEODPMAbFDX)${1s@1PRCY$TF~!WxnUB%pK)0%NpjdY<>d`e8 zm<6vnA03Ci?R!Wg14W^b8;hkNxI7)H?$|M_ybjp}SOO9AfOsPfoYQxhjm#%35#-yK zNEtSFJ`yLpBoZ_a4RatsZ3!Sj;%Z^IUyD~2;bkfi)~?OwZt7KMs3MTJ0gx9J|8tN} zD7I0B3P@c=!(E^@>+}YYSP{?47YLf8g&`mQHfyK4#1++up~m76Sq__=loZZ|gou9l zTk`!m?=vpWBs?kRn5Z!mAPeZ>>W0vRlm2Ju0f-B3I*t3ps(wEKd3kT0cPv7HG8ZTt z2J&lZ-gb>T83)zzLv7%XHMUK4#gvLs@19l1`zXKjJJ_gb)~bcrkef4vhnSZfDViFW zea}ZTg6l=;1t@nMq8;TMiGHiKGJ!GlP)(UMKUuGKZ0ydR)LKx-~|rU=44Y`1#n0>AcQFP z7m1esz+(X%fyYiFli^1{Qj(Na{gvoKi&eD9@SSwbhURzh5`^wJCcWwfizxvPJOrjR ziOB-Wjm63G&x@|T10oAvWMTVELKs#X{-p`LjL1s74Ap(B_`k4#fLVaUoFFJOo-ots zC2%@e>V9BVm$G5PB%<*|>|Q(&328g!qp-?L_I!hYhNC#$UoS#+DFDO4V|CtlmWi{_$_WZ&S6AVBKLODJ-5FV#+))Za4kJ8n~$y;TAUvTv4 zkh-ddWA&^GGup%kM)WOV3+;SO1A^3```aN!0LHu=sjO->0b>OdFxE}k@;x`BVBAcQ z<_W>cB1M_RJZ7n(J)xWxoQ5LKz*#?V2-4wb+8z&M6)!3kL$YpNW9)4ctQBKtf!@H* z=&wVL)ZkS`sm=4SPsggeP{_UaQe|y`&9~+w!VM@?+>ENjKqx7pxc1m;I@kBdGlhRZ z!u|o=xydV3I3|Am1RVme91Q8SET_OmJ5HjfvG}1M38JKLqV$FlEnnXu0d~0lb-qq@ z2}XB;0UUwC=Srn=ucMGV8y=K(Tuij%n@>3v@*^8VEF5q{;5*#N$E!}_2JmKh-5dPN zzvQbJ6~Wq@-a-UnEWT=v3&hBf13@LjC-G{{1%k@{Cs_^YSN5*QuhOiQxLVv#ZVnW- z?YyK;2$7^0`$#QWi0h6>=50C&=y6mM7wAc}^n`L}lCxL(B|gnq zJngfLsg@I9DIuhY+`LDo*XTH~!)f#f8(U=jFc_{@55gja!xUceYu;)aS&K8-rv3r& z67b8Ju>Nc)HF+LAs~YCeD{VPghduR#I3mVRDDX>Taa8l#h{+S`dDy#f9L@eZQU*62 zf-dCGJj2se3rX}3Ar(1=1*uxpW)%AW*O2=7U!XdIRQl3!Nd1Qv{4Jzb{wbsa%Z0uh zs*5HIR^`vV4yp3xGSxpzzE0fq%PdA{Ej^TIi5S)YEk!J2abYdk8awjRGBaI@3A$oAEECi#Pv6~iPr_VjPrr6GW?MG^O zL|}f;Iwt#tKu<18e_e6oG(!#Tp(>1tbrfB@95bqCwL-<-E`59YD%7`>kKqMr7_&p) z0K|&y?4j5{E4u-t`4gC;L?g2b70V-=sm(W5)6OBy$V8q^ZzuXFwlq?w^Ie$%922CW z76|edj1r>eVxHuO~g8aSVGHBNZHE(Qp90g;ABgOk+Nm~m6V~3 zg~oeUS2htagq$V_90(e3w`miW6zXgtbVKJ$fTI{S9CsD7KtS+UNBw+3u1^O+0a+iX!l{QR<%#- zGlQ|bs8||m{r2pvxXP9TrZnVH!T>T05px{M+uIue1$jN{um7eQ&dJ4^;cn`ZH8UpK zaH(nB&?};PUW>O)zeD2uE}vM^#7;z>U-MuFumCUNcO{w`X$D9W7wF?i15Jew(mGiE z=Y$pvC<$6H5);^1seA-?^;Nwy*6>m4*$$b)-F)^?Wu2$8g1?8m9uzj1IB`UUw(x&~ z!FHd*@qX9;vXlWHByIcz^s)0mO#TA2cSrsQFc)H$+3_so2UJ;zI~n5A31TaaglVo* zzIj=?H?3bQg=*kBGAKqW1Xdaq{86p}vc?ALA5_;qO5_incs`B9lCTzfvEVjavUzM| z&};0|n6u5I{@(oCtZByRntuX)%wEK5eL|r71B$&KXf0|+C&C6I`S^eB(1A`Kr;L6w zR1i7J^?J1|PH4(@QJM z2;OYPC(UiKVh@Lf1XsN(Po5ROd)w^UZ>1K+ktn(}=A+KrZ>i)A80k;~=d?S&ZB|`>+&BVsj_znN0oDsB;b^RM z*B7^OJEl&?=br-UCmoH1YOM}~^i%)DfG>S0uB@!WD%F8*py;RZe$0+=d$jM}=GuCz zb6rNK_~M@#4EIMN9oGbO+!{^|k(8kNi~e1I6m!i$%&qS`xhgdBXjYno+~#sUl~CJ0 z&$n}QH`5wz$zH&>V>{2%T<9w;E)^`S* z`41DVE6#2SGzs(WRe5iqUmEc?RCc{qT5A*>gSfRps6>})()Ik)t#59hxB4u1L<_xU z;@RV$qb>Gc2|n{sH~aMC7+b6C81p?!^U^n`Mel(_w5})%GGe*unMm-x@|&Knin}Gm74LoV*ri3c8V&++Gzoj$t3ou?FFn6Px=hb9A!r}Gxb7e* z&G9g;VGS7zazJUG@@V$y=Q*G>=bU~RoBOq{w=$aB#DUK%hq+qS5XGZSLXhWni~d(G zg^#)xo^>-f$Z1wR9g7#JW{(#FaHSe0cc$%Iw)T50n=3h)JCOye53n!qqVmFT}%syL?_ZJ}7kc zSFk;A)@k_?-0a}07nDFCFWHYkB!hKCO%AT;zQ2L7Zey5jKz-tY6LlA zD%{oeb4MCLrd7P8;rsOYsJhegs@UI#ndv5dIZ?+%|C|IfdmVzrae{R+r#~+)yJ1G5vON|PulMcTtGE1bl$J*mLfDhZNl#Rt z{!vfReB=c{^GP$rG@ohOjcVlB%RiG^%nOjz^6}vMPZAFz>JP5h;){XVjW}+1C`cUe ze?7Q(^RH#}ce}@BbTz|C89m3ghMLgI+rP2ASK$qa#?!|r73vly&mTB$ICd#hO+2JC zuvkr|w`RHnD8`_2kha(tyg;IH(RE|3Uxp=`s1IX;!i)ipDYx7o#h8h0duL!%`Kx1r ze_G#M!d2t1*AqiE)Itu>i(x1iBRsSs5eB&282e6}v*XaLK)mUoo zxN6+FV^TFXZ@o|yfM!4tD#(t(X^UHt(z1_bg~Z~Qh`741(ge;MYDQ|!n?E4kgf zZ|WAJvCTwr-6D+ihN76AB)yw3(mVO=$|IYuzB>F3?{Srj5C&BZ@9CwZ`_-qq7Fws)%|@MFHie4R5_NlNwysr?W^$Gb!E29 zE{C1Y6&4{^WG{AGGd-v#UE(N+IlOLQ)6%kSMQI67`B4G{|y>ewkGR9 z-@m)S4Kxev(SwD_I?(qYT=7QlojQFBBy&usrqaBG&0^r(gduoI$=nXd8@21EHPw|I z8g;S9y6kJe+uwNmg%`SPa=2=qhdx`otPe}a!R({HETuEJoHFoPZ7;d#!mE~)NX?>> zbJ(Qp6PlE5e$_IlG(J4_^7-<;cmiZ|)FoxB6$tG)SVlI-ree@@NUvujYe!>-|X@dDepUo)XRQew{uhok@~zI{76_6BJ~5>Q)jS1>YH|9y8;u_wd@vD z00Xyqot#jmoscTM?lv}%)v#5N&H*j>GN;pBhp}cZMpvUAnO?m!xlMA`o)O`QH`0GT zW`l_~=@h~KZt%CTrgZpZ@U2-A6NNRp78&99f2(dU!;@&FPNgW1gSbJLDd;qd$;xR zuw+GAhVNix-2eBcDB6wcW-M}iY&jUIKJqrOvN@1O0yds^VSeJ!>PVrXjuV$MZ8SUS z#db2iInzgA^fyzgTSCUk(}lzZAud>RE3F7UJYB9MK>)Uy4k(U26Do zKr0Dl`N#C_j#!q5_skgyy^UqL*3>L7>-NGnEe@bf3-oxlf43L5X|X+YV$(tqZCW_$ zqD>2UiS&#!k`>&9wHLGPV8~Gc0_8B}L~^TBK@_aDp#=kMgA5@@o(HyagrRtnxg(%> zr23$iBJ7;q+oGyiqKKjR0Sv{nnty2%W6!Yd_1|KPPUDkWE;^dj!ur?YIpcd5onq*) zG@_yJCD$t2rVMFu(sLCn?L!sUQcu{%VDc?XZqkT8z1p>tEg8Y$!w<_a7yLnSY7vGd z5R*`1Z|T$tLlA5I@JGohVI?Lx(OEOoKN%M)f_!UN53{+>JR;^EOuto!X`u^irL8`X zwGjr4x*l65!%LfMV)7R<1{2zUxkJKY=m+`BM4tS^bdFWvR4qicCjb!BD$ldEu-;wl zLE-3z%S6^`{f(T=(o`fXKvVg}9G4*i-@eyWGXC?{!?wv0oq6BC8PWZ38q)s%(vZPZ zxN3D+8hRbPSYn~s*l^nz;c1DQhPHTI<<5$6h5N0YQAWo*zm`DdvhM-exW=_-9n!dK zErPt@4?s*A8}hNnh7zWj#=WNaUu)cfpwD&Y?S-8x_M8aDsUE^jXj1f~57tzg?O=KJ zdm&Z`n=eyg2q6Z4N?~#cF;&w3$!-~Jm2BpuCr#OKo3a34znYfo0UGWDpH|wRsoGf$ zD(s<|3^s&f>B+#Y4FY=5GD0u`X7ApO#VN3RgZ4rsvWZF8c}+nKL1=J9i<7lt##*vE z{yM~BFP<-@eJ3GG1>nU~s$PDW`P`T5ES*uK=9&kYZKCSysFel(; zauMMBi8p;MjR6yHZETf~8Qzs_g1KvNZin7)bYX5*T0}^Q06o&6T*ho-K~*;Y}QkzFm^)Hv-tW{Fkhh%oGBu9AUm1avxV?1YA0hP9gj5;y7N4r~_?GY0Jf zGGMI>Rh1vcAGQw(7T8wjj|0WLANK%Qd%&>cmBQZf`sVVOXz5o|0GoJx$Q))lHd6eN zf5Iv+WeE1(Xg;m%aDkEH58*=muOmgqe;p}e*-UMolFb~jEyDQEBSko&|FkU<2-_kl zex#H^K(}7T^b8wKSkZv3;)2<8YAwE?EsZt+ zloyT#gZo~GyhXO4onjc&=g(;@4z&KQ)}qnOftP&b_Q=Nv&9I;$Ce!p zi8Gw9ua+I*fuxIPKBy{CMq9iB%+ElDJ(3%X+x}uG-wHVdG-MoJ(B>#MJ-oA)W&+bg z@&5p|;|pF>_nhJ}Y@51xryhOa_C#Vune&v1 zE(Rm8obWAi`JU?W@goAb*{oF!RSVc_wqot88Z8)nXZ)bNHM z7B&#HW;S4V6V~BjlNcknEG4uh5-Fj0+rj`+Jd850e!s>WUo>$y0ro8ZjPmRCeYa{2 zls}k7`SG?ZSU|$zwCF5OVseT0wKlAf{7erWUu?=~EDU*j7?<(G%GcY8eY}6URy=OZ zcMHz{WC!m5r-oGFRo8#^BUSPC)DlPFkVrgF_;@Lk`iH&Z;-M(p z>9x++bAu&E2h>LUJF;rWMzh97hn;S0{Su{08r3)ZdOTpX|DG+U=~aHJY#F1#uKiArl#;$c39VhJfQ<%D zffZA>d*MNJ4+{JDvBw338;c7cHAl4O2@qg;I127T6^5XDP+$?LZLl*$lc1hRW4bCM z7r_;h8hk1vnFsb|iLey#41W$tEqa^$s@Ea2cgZmBR<5*FwYXm>g>I=e7Nc8g0i^G4 zslmUEZmAK`9Xogn^ztid=$2a3L+2jrVSBl%h~01_tWjtF%t?dFo_P}=8&h)T*A~3j z?sQQ$#~GXMcSXM#iVpS?SR^9zi_UM<;a^6XR&lvRm{8U@`??7Gb3_$}zy+U)X%GC% z4A=#mv>y3xEo^8AYs;Fk6uPt2$eGjVa5q998B^SHr~qH709Q9U8{kG-w*OjMoU%er zR0ThVDcCPZha&8%b(tsvZSuw^hkAJ!kBNCpc-b%cyMrKL2SH%w2~FGp!=vkha8m{r zXrBI)NSHe)NjYiKXgesOdSNFZma&Ao8L z30p8mx`9Y-0lK`X#^{b7qb@-!dV%M=e-nfZnf!nWzptceZgJ2TjGh%1;nRAO>i+8t zc9fMj>fE2wb3t;LLeDiNw!o(W$1KQnf~E!Q)&?ZUv6bu~FIz(+3r^5i2vaZxlQ78i zeJ4N_WQ$BlN`caYhzjh)(YDk=?V;3PX`J2jX(!!}bj1tXZf8ZSvL9*kI@-^8y~pB- z`)C+)uy{QR*vZQq4a0<_e|mYN1b;Yl9YKjUPYk9EyXN0%ls}%)_^uc0 z%2Tby^L~pUkZ|D-N5y>A?tA42f5G>s7vp?dzhwXf`hm{07jCq?4na3sV8v~YZeww~ zXWUo-30;|(!@j=Z`R}i9jNe9cphx`WZM5F)&ak>AgbViv8$dA-8EKsTuW0Om_jNS= zV&9ZNy6N}@3LJK)#kB{b_5xCo2LW&~@%B&G&M=wa*@R5s4tI0@jZ6UTIkv&^v-@bB z4eOr#?d=il>c+&L@g{0>@l+l1CznV5l*2N|ir%O6Zn0i$+8aOf@o&yb_j?R(68+|9 z&pzl=-nm<2ZOsJ^^Ng;}er?eU%gqvgCtRyyYOmQFPOg3sK$}Cz0C!HKf55B0ejQS| zA*TgdU!zQ^IfOgASRv=v*HSBg%Z9JB=MX%IJer4vlxSZ=_~|B3h%*~~S;8d~?y|** zQ@E(I5AiP4{pj{hlp=aEA&g5#iMC-2b4lZD{^|7j)Zfhn(4CJD-9iMT3g_zqq*i%~ zEi^~72r1Am`;(ryxR#+4%rIr9Kf_mU-tT(dk92T}3w&L)gffT9e<@G;Fs_{>M94Tr zo%dSG09)D1f!me4S2KAUbq*7`nv&^oRa)-=_M|p1`7qAKmu^HZo$?>i)sHZA?cE6fZPzyICf|>))xE;CaqMao#N(g zqDY#ytw+~QSAi#szZS(!90$w4^3sjP>LTkcY~hlnA1OK<6TiApRL>%?3?VAW4CndZ zfxEbQcrG#id)$0g2DV685AmKadzn=*Utm^N z@KcxD%q!Y+2o1hL@W1T&wBEe=w7gJ4IBiRZWqE>KJ$@qFAy7=l&nW`D1&YF2xYE~9 zSSkz-fu}bJBj+y3%#(7t9t>m0^`Jie;2OAbjYSLGFZ5#CpW~i~POB|}irp{F1B<}7 zrP_UjC6wn%dvb;N?zyEU3log&S-uY5LgREp524 z1X(Ez*K$AE%V{j?w`2P9nx1OihN9(j6X z_eUr4sBIldClN8N(P(vDO(hKEyw7KZ%g*pu&c zr+@$tT*^I~D2e*PDd6D-d=3@BA1~kwhtd00#9Q4uK z2S(5cKX;kBlm(D7P;7)WyoSF8D?)$fK#%R8NwVVh&^Y$ zFA~F9SNLqHaEWjlofVV#+n`wgng6-q`rM-`O}H5?Wn<670POqN=&LF~ufexYiAN^B zqv6ayLQ?!Vl9mLJ3jPO>6fUa$dnAovOdu(`)d^ZPt1?U=DY~8YpOKU>6-k>U8jCSl z7nedP@ndx<5gtF2A#`JYYF=P5vGY&sn}-`#-!9b4d;6-XbD3fYz9o>CY>w;0YK^xR z=lO1ro)@!<&2PQKs|v!c!b1@UoY%&tby|#eI*qk;YK-()rjPaoM;Hy}J{$WsA~TZI zRps>UTd>@%v8#Tg3r1UpcV>NSR~#EEs2%N;>{ydlE3zx%%l~2S%>$uo-~Vx~(qe5R z#V|;#A{p6Y2!*ssiqe9z#gy!d8l-GRGIk}EC?c{{RJ4pWdq`qrtB~x!>pn9y_15#$ z`+0t!@B5!Ki#hkX@9Vy<*Y&!Va}=&>ZS?aj==I|}d1^5}_MoA1 zNr8CaiP6Dm!*!>oac?swJh>I@cTt~B92|<_``6rt@BKdUkv(E$@Gz3@Qg*K^Lzm!@ z3W=)gVcMrGcDn1W!l7wDKX!{R(}t~8D$wt!3e2Kf&~C|{ujW}|5d&Ing1Fa@(tGvg zgD1xEI2R1Z=Wqust7<9P?(e5EUo^B$qutj-W%RLEJDtw9)+Mz7_8XpUMjIg(( z%AxR4x}V?m2A^r(^*S|*4>MLz^_Z$HghR{*kLTn*@9BYoc{$b0&kuq56*;lhxUf9{ z=IZKWU@o{E*Q?Q~SX2l;PR!r$(Z!h*qViH`j03#ru zA$1uU(JAys@ws9 zs$=2^JHoxqBC>%WsfS6!UUl{D*3TxNWnKb^RY`q?5O;~f+|#878{#%9Z-blojK5Ga zJxE7Eq=Gn+AYto^FX7(sb-;UI*(Y~2;JLYh8)I7`DU7SKz%{JM@E-#ZHVpuf)i?wo z!G7A3Z1K`tt=aV)Q-Pqb!pDls96YVeJOF(!x!BAEydSkDgp~^7;^AQzYwSTWW$(in zetz69xn!PyfFuFpf^bp91!3bD+7#mN*PhC0J^$@E>GD8sJ=hPqb=XH^p3I(W*S>3I z)x2|g75?Ddt=_;)tlrT1AA{$jkGtoRdv=Aj;nua+U7yWeA`V*V?Lqp&y$vY$WHxb# z7fNB++a8xfVLG3Wv?e(G#JuP{Fl*=PA7t|K$&f)Wa(fdfrgNjuw3+h9nO4PQBRZ72 zY63FYRz7@9 zCCitfh(Qd9EqELG;}|b(^^#=wQa!HD;a`gYI*;&8H4dJdwM>>;FsKS7f^8@|&t|H2 z*MhKnF1nV$!JdU)V~lWG6l1kc5Jre80vmK_Tp>EHFgfaBARHdd`{dAe%ynDvxW8$- z1X7yv11d-*@!UswG=i`<7VL3{o?dzD=={)05lFdKPj?5!v1FZfUfg{YT%_#JJu(B z^RjJA9#|wcBTM0Q(IRe#&B|TsG!6@HVbDuz4MzNRRPW3;c-=^g+Wkn$)iAzK~R0(%)lZBL{90XU_O_vDKaH!DnJvN4zVj0 z5*KM;O3PhZ+BzD~DmR+wXJbC1YF}^s(h%;L3ad zk}C(ROqg|G;>wJ^4#yv}4ydo=zvjwg8i8dU{#ql#Q6dHt3HA(>pSQ%hal-Iv1r|Q# z^ZYUu1RVqCbtpQPZZ64raHl$ivg{j%Cuf>{sDJNs_8f4aN4L)VY#hrgAvOITOi~!Z zB!To5wf`_>Kz<{b91re+cZ}u57EEhUwN^-;gYlHhJmvl*#SlCxd*hB71zQ{Bpb?>T=cE=ynW>U1)Eil4C#9y|vBh6P9oJl^4VvWDr5tl=hF>{Hw-rEd7)%t>mBM*uEnu2le|n#yf^%PeWCL{{1V^)E_ME^1rrPHyU_wtk!Ki72PXcS!PP%y-(DQ=mBV+_i3{GGf z%FwmY&v+nx$WTJ zPlEO20mZ;X;?f8Y$oqLq#zLkE({Re+zf42@sFLW>7RR}5O$SZ%uyp))-TqE<{{PsP zZ@R;f^AIL%U4><8x7+5Yd|CbIxpHn-oJ9jVi8!PtLD2VwPz~*BB))15N3ntq0L$Tqn-9BQ(Lx02 zFek{cZTWo&>&9vwkKyqZtneIwe*r@{{>+uxj~Afa;fWq7*@80X{~&8j{(ZneS#!DZ z0vr^;IG`v&hb`)H0<>67qyfw>Y!jn&!R$ieF_MM@vRICTo;ijmYBoAjQ11F!xqIEs z=ZK(;h3M$x-KFqR78=khv$S|$MZr@fd!W1wyMgi*C_sWb9ihh$p3ejIILW#d3>fA% zh0+()h=Rdjzd)!KpY{=X)$u8zY~rmt%)$PNap*u%lD;R1i`ql|>xZi3S1)?fg@7ep z#u4x?+}Z(27ah#8k57S#SmaLR*Pk8rz^Yvn6-NJky#U|F08x8$cKO*@;<(w*?1Pb; zFP#l9hsx;0)g1;}V3;+I7R*VopM1*Sl@{cws7f3`FOe4T#F;&90O}boGa+)aPzH42 z@#Ot7P?S9MxPSMnD9ELMr=IusQseHO%%Q+DdAA##=AqmxJhUmtuSk!3Kux(`gSM#| zP`ufSQtf_ki3xUE+vfvN=LkNVo^$*w5ZHN9%|(A$X<5Pu4upGXucLma)B%rcgrf1M zykAwieE$$L#!D?RfEho;?|)xuDil~IhXnx4rMCae2~1S#`omHmR`tYgcY<1z@4ow1L|} zM_E9f7BdU(gZDKaT~BR8)NWeK{VOVZ%s5F8(b=fKZV2dKG(kr|r`32%K-izP1e_R4 zGQu?Wje!)sB|va+6lFU{70E{?>aiJz%ZSwR(44t4z3&gRZHvdE)Hk6j70glUFG8Xp z+!v#Y1g#q1vpE@<|9VWI2Z{D%Ldt~)7*|$jYE|-5&Eu~oLuDGBpjE@65!z)i+rY5$XOaB31oMAUC3tUfVR=cW_POsJLleToKZtv3n6_Xl z<@&r(6@!R*f5|BA7XdEZYsiELU&3u2D6IA(HW#@hPqw9<{eXY`7r9K=_Y)*DhcAp} zGcEtnKIYKvV-uQ&!5?Qc#k7Z0zW0YP7iFZ8^O)Llg5JbsYs@}8-XO988bn$)Ga5vk z2L?J6T}E`~jgEXQbS-hsRdgP04bB<KTx1g0cRr%rPuW5FQeXli2@5{)pPh4QucI-{jJesQ42hTgu2IYGV zS~^=bdxVl=qL&w+S5ha5IB?DIy2G0VEuB%vxV&mV_s96fKwn9^VJtQJR>gUTH$|7* zRMSEXcPyGuO27~Gk~R$YR&-x;a^HxTyW&fZsB<0c4|aVx(ytSD;cUe_%fhd|uLLub z{45oRKOD|}HvMVWRnm+D&h5S`jmz&sUEN7!J`~Ee^OOOZvmGp2q<5>|jO}+=hVPvp zz`i4aFMIMVs3(6uu~$1N5hmNOxdNXQ!*r@wBJZpM%USP^eZBzwr$z>EK3z6Y|F|OC zVOG4}9HaEJq)>hJ`?ymM^K>GX+AUtyXa3ftX|JjJcAIB2&*p1LL7xJ_>)cdjA+chZ zOeKyFiv0eijvLZ8s%#U{qBef1%{)gswo^qr5*7JvpvWJ9;!SkU$sJ92KJFP_6r##x zoWEoYD)Kk2cmg$BA*j>Z*v!!gQ`Js{B0o;7!p~B2PQ3Jf8}>BE)J{p8RdTW7go9+| zCj1gKKpq+(@Dwy`Eac*VB7c7C)3BNbDDsP%_}g37sbt)TF+QOpKLLvT1yJMdZ!`Zr6#4z3o05=Dj-?94^+A!}FVImv?aT2Y5e{q)71$h3 zUU)Z+%S@A6>B~uY@28OP9M-_zD&ow~4Id3lp5q=v8bCx|j|gc13NJC%z>t_RkE^v= z6)0Abm!S892=(Ho zCZPa`^ZJ8(5{~8N#Gg_1iQo-pV`nZ<)<6U|BR@uDp_WIi zCP$lSCwA6O=h3*_BWY3$QXyhek??0oC4vCm!2y9+)c0>v)ixFafoN=j&7CbN8t``h zmsk3f@i~YF$eyRv5kJDFS_-{ABD&4uQ4{~FZD8?#GG0*^k4=}}8fGNfYPz)iY7+emPb*h*Mtj9#aPz+T}F&1Eof#eW!+#gen zwsFNcj}*hs9~6V>$tquygZEbqu`cFVHKNmfB!Z5i}8e06Q9y}5|6dFl%^DPC++^)RWz{PZOM z>rFmd-t`fqRZm9=fuQsIh5h~V+03EM#>eeKlQI_}EIX!d3ZYawV7hn{NxB5I&Br44 zl?@Rk&TJrYh8Iin&%fwRd88(U^XI8l$Kw}@n#aCP%`2pQi1egT)v9lvqg28~RJBcn zq3KQATsX`~%RDx2`W9{10+TKU;TGa1hZ0}IAW`o~ZA%2@0ng=$ys#2&c`6pj{Fd)YY4|Tv2-n;Bjet zlW(EGhi_$|8PXRtP5etk)C^#gLe)SXr8Klj^l9@ z*}2%fC~RcYw3Qx|xF`9;pScL=q8o_UlJi^nqhbDDi=(@5d8zc2xfQe~_O}CqzS=-6 z6kdhKSsRcKM{aJyX%(XK87^zjy-S7S0xioN1x>1PC4y%uR2&lQU6o7v7xSTCeKU$Y z(M79tnPyI;dZ?t-%vaW~QXcu{39Z=ZnkD*8B=%z1$UOGq{x^9zhog_0ditEc0)RFz zj&9+?hT+v!+YE(-> zYckC~PlRxAbYoZfd%t{Wk++n`un&FQ4=qxbVKvZpQcO}@VQRY*H=$V`SFLXXrBGFk8Z zw=$8pm2FkaBAfh)R)AsaLUR-5aKg^*!jip9Hu_=90IaAJl5n#54fEiy#R zFn$n$Dt%A2+d08N`J*udRYV4AQipR`a$G|jh5^fjBUmQVO&>QE%rZ%sWwQGtguoQb zXL0lo2x0AsA;kE^ZAAH_--1(pG5^c+O-<$i3hkVi0XuCyQ^7>-JV{TRU%Iy3MoQsA zwQWMoiMA>u`KpKGdore=WT`rdhj$GSsXPWH@Va~6rR!uN!ExE#`k ze`p5yE5EeuIJ<75LSXU|fo4wB^E$Y}1U_!(`pCKX2)iygwVpoPaDzTxLYK8C^zt?N zh_Hc&2eyGjPDO@@*ajK;pz>RT@7f_)gqS$=34iT6Ye@H(BK!6 z2*`&cB3&v|0WOYvevR^^7-kS=v->YIvzgD;(y%xh^7~+*aM#gyz=Cs<0I-gGB2K^# z6qUkD28xO^xqB8UD(Zhi+fk<9)B`dB?nS0a*m@qFA{v(y(OsKSm~T&3fs6ni26&{- zGz?G+9PmyXht_5Z8RE^@0(~OI-OiI8@P~~bI`x>G2b>AcPKNt6G?45-Gm!-8V({@)ffnDUo|4xG ztUY&V1SWgRuy%1S-UIk6Lj;ok-Dki#;4_fa81sK6Lxg)32 zo%;%hxD{P5g!u-K9zpvuI*8rdupaH-)4aRAO3PvkD5#QVZsy#Wg35kIE z&V^cz;U%6w8oDE~4Q1EcjTaSF$ z;43->pU^1$OsK}Q;8rvnIz;@ZPPSMpnzR9%_`ly0c)Z6V2?BYLz=R55O$#*`Hih)! zv8N1i5IDr@xBSz|aQn_g>!TQx6{Z zyjX{W9(C_CY=Sun{>~N@`DEte;J(ZNa0~nKOnW+2xRDb&{|Q+nTYi3_ zoh3~xgs8zcdDH3q)FSIQnc+hniz-_5%)DE~UHF3vuGVO|; z=f$TuS^8?|$OOLUU^xyNL^aTDsSGX}3voEy_qZPbmwsDn!h#NxFgk6+EK;mVDxnfrJ#af8N=t?RSz2mBr6oIRDFP;umUtPWSQjUh;0c@YHlEP^ zDMN(rPYqOBYMS_7)BX)uX^BA08rXtvHU-~(_&{eDl$N%@-KHv}tAA!3W@E+y(|{Y4 z=*EGSmd*>darSDAd}(>_Iy}@ixZbEPd$51~g~1d-MU+PS3AG+eAk>;vNEtBuj#SLF z%Ir5#lLr5&J$Ol#zwqYKdGGF&xlPZ=9#*vGhzv{d)_0X*Jjwv?f zH*j&CoKXvb9T)SiYbskDy}p_A!<4mz&_3I88#U?ze)y;ADmKg5{jEj)wjcNOz|)V9 z)Q@|1YDgk_oN(NelPyrvOU4RftXr_8$GDkWSewk_ctlKSCD`;2sBT2U2vDLQsh%o_ zf>m)Q_s-USokTcR=C|F>bL(t?Uz!h}%}4g)MYf(_CWTO54-$?Mgj;5@7oT{BBg`YK z%kbpGdX%~8$NjM~#J*TwfSc}e8KS30K?squzKb*K4J@gFbK3POHmRjv0g|LvZ2C#j z%n}qd$-~`y8SN)orEEFqMp=gmf9Z4xQb=lZ2q(z2mFX<<96^oGwbQ%=(HxzEPHHCGud_b%L>MU znnbhfwu4M4tLKL&6b33$?YY$@btV&9G+18Au{D+1>1(sg8|b9^)hGy>TtLF$@-EFA zO77+RO+(UEpG-f_7H0R~ zH~)j=|MK=+AQ1cAwosdgDfcP<-P6eM@9q7NdQ-*>4Kuo5+p6F8aa%3m&FI0jYqu`5 zg8NA}a#kJI%?~lhr8z56G5HJ4bq9_l3s#n)(zBmkS0OT>+XyohWo_FXCq3_6?V+We&eToFUPW4j2}BNn!(uy|>z6`QNJh84 zRLVlM{U~=g3;1t`f2g}``9NSmPjW!d`GB5V0X+tXfW)J)tgku7?we=8*&v4VQv#W89o^qvi76s0}N^5beL63citf zDj0+ezxs{saZ!pSBCDP86xkRRgEaXoDwjC&o6PG9^h9V_Wkhc)2wkS^-j%VLY4eBGydpJwKxYnnf4Czkc{cT27!WBf_ozv zt&lT_5Iarj#`_%!pK3!5WVr&^9N%@1!tan8{)6qtdG(vL(UJa7Hb4pIsca%oacY&^pe9CtNs5tk&> zvUl^4Z%Bp-5)K9{2*oA6blI`1M@*#EM5J|rNUNSmYg+!Qmj(U`V&#IbpA(2CJz*64 zK~v1X?v3d7$qwWZzp2s#kBCwb3{19HG+AlVkhNHwBR z|Eh}q7AH?0Bg8sgobrg>{$sAOWtCDP1O_{7T85ybP9BzLv;6i@*EjLkM`Gcvb9l z;s97+l-Q>Nad1~o3A(v@Z>5xvU%lcw*(l~*Vuo4Iq3gN|5)H@H-nIC)e2put*EOyF zR`1&VvTO8%YrE^Ww>3|n6o%S4mv3BnmQ{iK#^7^>{Vi*!vD})Wq0G&Eq{YtA=!>ml z-EH+rZV`^nUt)jYo9-TE?vpz%@;#cVyluZMi}{8y8fztlNR!~~C*G5jy#0V3VaL-U zT)2W&=f6ynj^AWC$da_~D9f!`8cV0|&+>!lVE+kRYk^0s)BdlMzHYx(+w%IQ!ZCtM zi;{XHjZ!mLDb5(rront{xM+-rV2#!@voLv004H0Fq?x>q6&@5La=SzT1dOr}Fcu@0 zBRfx6W4CVP_B8<>c*arE7!M@0D5O?6&Djk|D6Q-Qe(sd8I(6BY>0ufEJ%`k`DG0_S z+t&bG(fAi?@Q2xkO{VR*gvYTlAEmZkighfR9ai_wURsk|=m1GHv8DBLESLvrrY1;3 z2_d*FAUH8D8V?9gTBaG`Hmko3R1TWG@*A4J6jx1fSVFD}A3)poX5AmXG zXoYjR%^7Xm6y1QOvWd~Un|7!VG~)2i@p$KJc;^JXa}3`37T&ofK$Mo}+gQi7Z;=?A z|5DkCCVWDj24FZ1FkGw^FkCDiFkBWeT=|z6esL*=;Tk4Ai^BlJwYeci+PkU8Cp!i( zJTPUgn7DvnaaCp)1a2gD3jQKBee37G=j&FrEH5G`@)X6ZgSya;+Pm`s$ zVS*Vp?cG+g2UdCJ(io77cxq|@kPC^yM|^~v<(9N}#N`{uvfF6L6L z6c-#oy|FQFl}OY=TFY3-+)+yQR% zBh~XVgwz{NzWCOD?Vog-8!nuHX^JMMDVI~$E~g9SGbWVVNGRJTk(TYj_WApfPkc{_ zyxBSJuFtnG1bL`03@hl+&k9N@hebt-Kuk@7m^vB}9&~C_v{GEO2vT?KXhPf!F?FOQ zn>tuc*t(-d@yEbwWV3?6YGhBWG&{V9uB;z0Wi>_08VAani7D&%qtv!cOj!+^^cSrL z+m#KhO?FsqmZ0md{dhBE7HE)JP^F6@lP-qMm>AHJ>KTlQVXYrz7G#l$^#yF5O>$V> z>cdC+Xjt+hGuBB-&7_-JxQALq_!J-`+p=w1QM@On5Z{lcv7U6bC`gtz#?<1WNv|C~*;;5xrm8552r4-$?v zB%f$y7SWfhz}thV+()L;Juj3d`++meTMOcP+75F_qtTC2+sq*cH#^KQM}JW$giNx5 z0m%-brkI9^{-`15LYSe5Vj6;uR8K9sp`07jkTfr(A)%0aB7KxDeqjzl8)!%!(vW^{ zEmD|`r}k4(ZYpC5jD?6xL(q0^ObQFbGz#>yv@kQ-&-0_1Nc$r*0Z|~YfQ}}4qL`W3 ztBjdR4H21%7G@@)rU#{gf&!+0Hd!e~liGA5l(vj7YWrWJX^WBo;q>8$TS4AHInno?msCKqzU;I79Z5*_zL)e79t`2vyO!IWqw1MQw_Q>pQBSY|gn5CdvUL%qzXJgC z!T@ae$T4$BjncN%6*XH#Cm;X|g-8|w*xWEkIz^)s5r~FD(usbYBP6lclZ`U$l=4L zg5%XnSrZCL9`J362s*NjdG^KeW73oa^ci2sX*JMWovTr$ZR-sV^5D4Dz(%F5cr1Rf zQ5ppFm~Gu&%5308ym!4IpohJK9HbIr2p^@nyiaRe@q_^YzZI>%q6K*snt5FXW`6X1}ztp|LrBVTKKgXmdnT1$|PlL?LlclJ08zSv#3+ zKhocr2e@Fwn0CI?0pO_0)Jk~+gNy@*%g2eg#&jXJH4(Cb>&K~>7NTM`5KKpIPa8MX zz7tG_3czd4FwkF_sV4Pz%~TdM(`jJ^i-5t?Zetpuyym;bE=u;oyvU&JxEBFhJFye_ z=Qc`ruRnT_FecTAEaiV=5q-fIqntYT=kmfp>i4 z4y7HrRpd~rz@Z@JLVD5dJTNKUl`Yyel$M!4STBk+6#);T>OZ^JCvn{2@>jSM6u~1VG2oN_qq=Sp-&<$M**)9@w z!7QE177e8qIkp=i7!~D2RP-Yl3^_bW><3^sGag}c#N5nZ84I(PW7_#O9=w|)@@^w# zA(tp`Ylvu&nbMGrK+!BMj!w^i_VK6BVLtv#yyUOwmkH1>L^Rg@7L?O^242@yLiMqD zf=Mt!>i@7)5=Mg|r2Ykt|Gzg8Rwkg>7)Q8SL)0st5vE+SfCJaMS)_HjNb50?)J$)Yrb)BYStcnF1A~uCHn~C3|fJ-|7&C0(^B{i)eQyP@m9V zC=p`;LYcfTrM;-ClDMf>R5oBe=@drnF} zq%ww^O)>O#!lMZ5#=n7FkALk^{{tjYfW|-OPYIb?q%vln#mHm)X@Evk-=e}IfesWqb>$R$FIxStU<{!VBzSO&a22Jv#&kKk9|Swus% z@q3ImmSpU(FI7&5}aRlGU0e ziJB!={)Y<+P8*u+ahHmCs6|p;O$zD|t|G?EXtme1WkxTM-R^Dr}<(AJ(sJJv_Y=1OyE2NboMM=$@4NkmGbNvLiV%f#h4 zyQtTQZJHx{ICSZ}DdRKh8B#Zowoy`xb2Vzw2XcN!tH%X`NLUVm2j#Lfx#>q!d?j%e z);Fb*o@y?NLk=8xLoIBsoBMyX|Nr*^*H4sdDtZz!A=gub*1h9?7 z5$7-y$h*ywE*^xm2FT#U7A0W*;t+YFW2FCno^;4lhq<_aoE~-{bcUD)jU-(>ZynSe zi2n4X8$F;0AwodUH2ospBri)y%Xa%0+1Jw}`WMo=%ce8da5$9K?_Wv$;O3(}noUiH zaC%xOZ5R?funZfB8=1CMJ;`e?WZkrLHlA>&CTV#D;z_chG;cl<)dDn=DWnHwf{>nR zBWbfMiD^*BV6)1%qKEW9Z^e~Zw~Jak*z;*UU2SrZSO7js*Gy_U+iB)p=vZzPt!YeV9H&SZTR_(5$)Yce%tDo@CS-k*z3yNMmX&nsGthSe z%56VT(yj&13nvck6Ct!WL!rHNae#UBQ%I8lpAXDx99G?e*R|U=-o}P3%rj&ghqd z3xj=q$L+aY4n%C2H$i#~5m%r|bm9uTw)x*6u0eL8`BBN0lfQl4HF=)pqdGkaMdxn^ zg(|=30qmJ5beRY&{GDtjgue7_=J_=t*A+Ql6njeem(Q71R2Xrb=6bg$y+*EQwD<#h&T11=xazSZY zdNLD=GG5h0R5rEE-hJu`bbHA{R^T<3RX8mHIJ~_c$`3sr@;?OQ+C1Glm8f**8wo4h+lZn15`$ZexV^tFG5+@@sK5ZS|?&gVqgcgcw0nBOT+p%4%&Pn`-i zjsG{IpD&g?`lOLI$;A>n_udZ5f0~+IIaO#+XrFz#&DVvk^J-AREWz6X3TCD|&4qD{ zW6C!37$}$}7#8aD)xeDQ1l~(NRfA@<>#;Nx%uFqyqV!y3+Vg7euL(DGTGB+}jl~(AmeMDw9`dTWeGgpv3P*aj z^W3PAA0eG2SL^PsXe#YD&^37CV(^XR!e_d00 zOMB!s-~7}wtA;~|jqfHzE+74x{Uy!5>D1`Wx&W-3nC@4j5ug8jsIW4Y6{zJ5(~k%RP~`@=;#7cOE9P)~EtM&F>z zu6KyA8XMq3T?_UTG(b#WzZwki@L)Uos}Xz?*VnJj7_uH_5Xcz7&LN^}Y=E%3mJR3{ zXaM;6Mr;6n#sEW+^l#9d6lu;bevAP)93lk9253usu|CKCgW^@E?4rt{U8LbPhmG#m zjpToFRQ2k+b2Mw%Ld)QBXLs*cu@C0c4B$2RlKHfUg%vddoOkD$zpkip?6$x@w?$iE ze-GM0|GkZp!Q;y8x;n4J%PXC;>kOwITz02#x70)Y`Bxp;dsaVAPoUMew0-EkKW})@ zDT@@88tod9SdsRi#(Ts$+tA3+eEC3Mzk{<$9QM238yWOhkLwAvWalhCU#+ud`Bh6E zX$~I0)%yJHa+>pq7g84efKbaYXVuW-$2!w{m(iTV4J@-}Iz+TwG)O#C*OLCO{8nV2 zePr$Gz!r$B{T%|Ywst+|&^*-g_Buzda5Wm$_bgOxK-F3UQ40iqkP+Fy`NBTTM355V(`~ z@SqmB{bn;U1xt^*P?^MNXmLWj)?|nZw7KA ztSXEw`}VnCK+{)LbA6rG)yBl zGN#kt2YWR(oqE_<>_lv1)dsB>A%k%B8RP3#8@-NfEAbQ4J&*%;_IwrKhy#^(qk>wAaf-p)NXu%0SX!m&jn zeZ$t!xiFR^tr*0GW`YLq8MKC-!IYD}NV;;4Ef^{I_`ZMgx^DTXQ==_XFuWaSY8L+k0@PfBm)H zb3qvT>${UoI43p+e-81EooV+Y2EZI)Iv=lf0=g}7mp@pAO-t|1Xzlm{e_Xj=q4oG> zX`^>ix34}?$WS6o1dJ`f-v4waQU=Ckz`hJWhJ)75i)Ad|b?0z>q1|`6jQ<$ZobSTM zAd?}CK0@!dzA^2iPn@oO=sjjB-=&4Y6JwKVTgo=SwFQrGW^5@8I3FJu^nva-z-GU1 z5C*jj5q2_!hPednJmxW;$za%l6mH|7H7mnduL`7a*m17D51`UhF%(%(-ryO$2Y>`z z>BgM#zjSrGy9ji`-f?#!ykYI##_{F*wz1NcSMZp2R++mK9iY~MFgK3j(Dv26-_J$Y z&n%;RJcoGJ&)YU*`#s?O!2MJ_GQ`^i=Z)WglFfA8O&9x?4@A6UuO@Gx<6w_s?qZm~ zAKiHR4l(^@R9?}P=~UK^+{H`~35%d#>K9)-E7tlCT6BoLWGomykDmgIZ@dpr%YMDHO-&=YKv?7(Ml7+Z?( zMul8}EXG`%&VkDT5I`2wKYLR>hg}l`daxg4E&Jh21cD5?f&Unv73h5zc>^LNpn7ys z($!|7CBTozuZUD{Y&o5_11=B13(7w9U<_QhbESZW@SP=s>xOsnAFX^CV|~Llxnjy8 z%1BAfxpZ%tvYdBqlh$gx_Uq<4sq%lU@9AaXjmw#~H8(u&{nk;Heez1rTI&aH9H?vj z;xEufM7?r-n7fD9s5!=b=Mnjza8VY=lzwbxs0)iG@+;y4|EYw+2ej2;qR=*^x`{ zIxFRVCtV*KJbxf(wHBbl;HIy$JP4|~xa`c;m;OZ+XbLv@RFQeh|;en{R zeUr>uqRx#zR2pfRaxtn2R5YzpRg$nN1f|(uWdT!s;`8mJ51&qA^1zN1pB5;@lJu6Tb5M6 zz;prUx^`QkUSr){1+fxs!K0NeQwGB1%909MQx*E7A3zPUgwvtHtt*n{mc z5Bg=b*NrGSCEwP84dk!)zicKHy=67sk;Iq5@oDqQTTz27IV^Y42g21iMb2)8I=9bt zP8kw@b(E&S60ASxE$f4Hblh#V3%0IJ%vd<7e)IftofWJDj^tjR1$8=mJsr*;_@=Ob zIPYv9&jR$9e5Xo<2Kd;^^K#N!_8QjAhzCh7#)KjPbi&a_;|~itPAMKgFq~)Ows+C{ zNnK*AZb$59_dEXmYoFXxj|RPFwTT5yImG{L3S4Bj;$424Z|;ECtnr^ucoC&%U<_mP zkTDnd$No>Bo@pM`-d%Krv_?1ZxDN`Jc{l$*BE$MiK{p3|&KF|3d&o7EuT*-4@Zq1Y) zQ`WC}LOQQl&?VNuc(1;Cz}G|Ua%;YI@M=jUxz8?|qBA=@J+XH`D{mz0#kq2hMs1JT z*D7)Fi=UdFQ|`X_kVL((&TL2HvH8s&n+%R=SZtc-kKvIX!pVfaF9Uw&M#z9RQs<^zH7i=`Qk6~nfqHRT-{gEr|IS?$$!<|FARm*nW*u?&`c-W7Dq z%JzBvYCQp?i$+5US=q9^4+qi(>;~W4AHPv^azS0T8OM>@t|f-9;pa+U7JuFAB5>X8 zlv7sE)Yk-76w#kDr2E&S*)qmK1$mP0Axg}z;lEfOQA?91=CPGVsh9i76mb@P;|b6KXd z%wS<*!LgiB2r&zs&cfou$HKw`-<&dEO)@=fahQHwv+9(EdAq*B`5LvkE~|SKXJl>2 z*0`6Ix5&IoySiNz*B0A!+}t;z;G&e8WZea}(*bh5*S4x}Hk#?&rXoH^s;DS<0vH;$$*5AUYXFB*Hc7}?T#(BqdM7Ai`OsMmq}WEoyw(6IG|CJV0hyJyY@44<{8Z+#UrJWmom4z{~FKe5|dbHU?E*QJ+EvtN4}?YE^o zN*3RI5Z@pjc3DhZc6!d5l@-e_NAe2?JkUO4Z0+bQD{`=X_O;D+b{{fz-br)qmG&`n z5Zre#SNVV#d8b#y<|QR%1m%qd;+miTnzQJqD z$Pt@|wfk*$Z+E_)T%57JusbU<`D-G}4)ex=3ob<*GyZtGsYYyN2TKm&yj_%eAZa03xeK(=pm=t_%3X8g+ z>KXjS-PF%>FGP8(5DS)yP?vBc+Jvk`Tjji4^ zz=>Z$yI^n1Tb;+ZZfy)#bUgXxQ)@x4kEz612d5Ys)~R>h|^f60c~!gC7~C>q?Yl{(*W zmzLUCN*r+SlI))2-{;4A$y}??;>-n7#LB5@N_$Ues-DglJ6{&?^5vC~uJ-}jT)UP{ zskTyg*b*SwJACQh;Hb~Nnso#GQg1uI?JLU+QP!DUibcJ2lasA)!C7{7R$=0 zHd+3mo2)~ucxKnGP<`=CBjlTpCrwb#a98YeSDTKK5T)y?i8N@mD?}71j&J9H}Q0Pu`cjuV={RmujV~-1Z8uo91VF zn-4cDQ7B67{FiMN?be#0yX;CU*=} zHRm|2oqH=SDzex#+js9~F2c1rQpK0gh*FQ&%=xH5xp1L4vqSqpJxB0o{-flV(^f}I z%E&D`FXi~IUQNGQe1Uvk%!&q0(%N;NUXS8cG-^+N_*C&miRT*5+u;86GoKPgDkkgq zr}?|bhH5-36<;z-zGKgMAJWNLGb7B-_QtPubxcY*G)uj2qZHw!8p*$oxYgJtX4w=O z9REevoBC2>Q>l^_%Dc+yDGCKW7SW4hPA%%-7@B0xBGBOLh78%qKtCQw#cms z$$7lVoyWG!;JY6!>3;Q4rg-kQTUY&DPNCjJ4bjya8XnMuv$ zYnr89!I>F);_HSXRR28eaKB4$d6s3zq%A9iyl=UDEk4Y`s!IxSbvCB<@j=VwvSw(uiSi2!>7mk ztiVJ4rw@CYkq}fpg@wg{n}uZ#-G|wd?9C6`BJWkUTg$3OhBIqH<*3r9JG9&YW8R?i zvKN!4RjaxkI-OO*eVFH(`bt$+oAV=m>>^c1Qne0>nO&8y6x!7EK9rYgn%`QJ+DHq! zc}~OMc=T1Sr}y6ZTW)U~>eFiWS#wm1YudYQMRTpp-0P_$rz9Qzbo?USrD7T^rCqQo6bZ0?rG5qT_;>>-jRw2g)!nHPwliY36xn!Td6TG4oT1X4B zwodeYTO}2|cUkP?&HH1uh169CxfXaNUo$?kTVvU?v@98kGt|4e54=x@Tqs(%`RlBR zd(_LfkBMFt6CBd`qBDApkRgy*+7NejbFsR%tY+#*=_7IGQ>xce`;J_^5VBDs^odK^ z4zJm=rl$4g$0Y8#6}85nc)w&}*0w`!ti_*s+}1Cjeg4haj%r&UDal2TH!Kp-uvwz| zK40eyr%PBxaIUrJ%<2-Mr^hQ3%;FCWInMszxX>dfY-3LiFTOB8(sp`#&b1xWV%zsc z4mJ!LN`>0&IXYwW(_P29%kG^Uy;jCoQfmFU^n~qlEkisPKy$rryh9zsGqdAENF0AXK2Ti$ESC?`M*A@ zxX3@Fxn_2m1e-POF-4_ovB`4XVwXqeGxhIwMc?1iF1bajRf^mIkD1XdcSeXs;qmUQGda7i6-(YcWY5{yx6|R%p%X?=ScBdQc4uoo)Svs(#^UO&u@S9ny9eA9+csAy7_`y=Sdl z?~`la$U1Gw{`nnIhk9O#D~C#+(%aIhcUo|nsfP64`gWu1--<@mXQjqJ(#pND{N(Zz ztp1HEgYNO>!t}UN?H1Pv)88QoKBj8@#s zo0WM!v0UpBPv@kJ^Rt$|9I`I4ez0<@`@JdsZSE_c?uv`64@-7SeJ#&s+_kUCQCs?p zlbBCICGYc?`~o4x-FfeZ*1ixr@7R++IJvNQc%=EUpRefEotGrRp=>eO=hqjY!%q&eXEQnoHV^i~>H%oGu z_4dh(W9w6$s_@BgE9;^}ii0+#d2YL%Qp$S8LquEs%p`TAfg-D}NlFE4In-aYs&Fro zThGtZ5}vFW(da2Bfl~>mq-j?_U-^VPg7v^XIjh$uo$tC<3Q1m_D%Hrg!Af4TYM{F@ z(UlOmR@f~xzq@?d%M!(l7h`jb*Ic#;zc)3z)|RVuw#&Si!XY!&rlcFMI3E*J`u@G| zrZsZ{=YO^jKh%=oE0*JG>MzHZ({lS@P@OPGR_Vwaib7w}%c~NxC8yWn?H&yzsFhTX@{z zM{M(?)P|}L_y`_Yx$0nA>*8ng%)J_(;FXS$DEnepn%A~N25o+` znft%SviMuYg9`$W+Bnqy$=}mSGl)!C|+j2PZ z(V%hNM+L&r;SlG0EbQd>mK+67*RJ*0yeho+uF!|vgVH^zZuuf|vZQ-4ynD7qpO<_6 zLO^uOQei=_GTF1v^W5<7EbdiYu2QJ#UU=hdovOLO+mO};DS2ir&;P&n-a4$RZu=iq z8Yz(u0Yy-{*>s42l%PmAn~qINhcwcmw17xTx3qw4x*MdVOHz>j&5iGS-t+aGd++c5 zcb|Lje)i*DYpyvybIeh5%*7hZdisNa6EYH`uDE-Y#XX*<}8PhDSf=pKML-Zv=9WxIc^o(x%-wkX&iB;NW z!O=)p3>MC^RocaxAh8x9I6`5Uk;-gqIF`O^RqkP+66@Bp(;@S7bnEDLDQo^cCw1wb z^(o(kft7`Ney6$<9s1mez^*fjzUcP5E6<6upRZ}%UHj(Cq4)T6prBAvPD09 z&+*x_3u)P0j7#cUFe`*Ud5cKVWo{#(fvk~w{;)YH{vEp967SnbWk3C|4o(YY!~#gC z4W$K@zvd8dFj}QlF`VAQ_!0AdqetRpB`5QD8-iXjgRTe6_Y!Z6`h3>!sQmF@-Lv03 zQze*?o$BNG0>@MKmo852{7;j_s6IUAvhW};^ZBA?A$UB@&p#WmY8Lj)y_Hk`C6a1$ z($>WjR&jkoDuxSEvOedx&14@a+|8Zj<_Uc2d#SV|qq%fHhUbi`hgxv|dKtc|^RdVl^f+7{K>qU8hnmgK;0BB`$;>NWR2s|6+!nTHe)yfxhzoH9x_)FB*D z{eG9yXtO|lL+G;ynS0t`NbTv`Sn@|!wn(KS_V0X8JU7*h)#*A&n;+K3cWE!^5M@RNBD(K)*5SM&Sg}{QGIDxmyST~Ny zO-cMM%sHj|3&QK3^v7Kp63oa)M9-Ta4nD~$$qRl#Z9E=$rz2g$G3M6g4GpvOCk)uS zhw|waz9}uew;LD>3mHObB3!=g3NzJ@1w68y&3sG!P%ZC0B*r7ZONhkX@ToG{WU?In zQMg()U)4?caE%!9RPQ&psj)MU^rCx40)`Iwg{C6aY5dxzj{bGeQ+gUU_gUUA*=PCt zZ)8Nu$`fc;B<{ZbhD9}vpVF)!hUD-tgwMZDNq^p`?GYnfr*4>v^PUc|I1#+0?B1)_ zDz0pIZ_%Zm330rW$;HgIHPXrT|8!U4=Vx=g$r^@k`)E?QqXf?65i4WS&pRrj{2PHU zF63Sc(A^34ns;h;D^4_>mEMt($B_4)4Yo4Ik)=Y3~#7~v&b`Gq^11=gC zI3I776X0r)pIXRp;f(sTSdTEf#`@%lzYf;oe2B~(dX8zJZhy}Ye|$x$h^~&qMO;#3 zNi!zWH&%Gl)_T3ml1jiQm}$VBV7ex`<5)M1R?ZkB%WLrwuA^^Z$gP+DcUB!>#X%`~ z(b*mkaa1zRxA?IfwNMrf@yyeiXo*RJn9)A6+S=JI?UU#6*4x_MDEFdKF$fD?Ot60I z=9Kd&+u2)?&OPZ%Bd5oY_G2Z><(k5;Q$G8*IB{o`mz1i^&63!dyQHVuCp=LbWOUy> zeYIvLO4?u|jf~}vDl*?Wl>0I1_{L`06?t`Fse1^{;-;TVCEnqkXLg~P{*CxqVbhf* zvoSC4sYf`nwW#@|NYexNQ*QbFm^=vz^k*dY?c}!4b`Y*pro}#>N8Bv)pS6DzS`b@o z{9WsA-`My`=G+UG9`$O9X!qAau8-?6($M%YKDVprdF7w)H|}=_b+J(w>OB+nc&(bL z{{7oGY?}1NfS_}^x1OBum9_e1j^iDN%9K=pZQiVLR~4pnmoOj3FNctIZyoDT_`E?U zP7j3&BnlqO%&h29L zc>*(r+$mPuhvFD|Wf)nHlQq7?ck%8u^HPiPr)3%WpfRt?d@;Chsb<@)HK1ar#q;fm zm0e_{U}>gY3_WRPV>}Ze}9Kz2|6Mqd(Ou1X{}*P~Vd|#?w`#?s>S8IEUU! zDM})ZX!ZYI)HN{li&RtKAu1i|Y1L7EX#ZwQfbl0wgL}0l?0V`IjU|Wj#C^BJMcpq9 z;`yR~ScyBsbkO-x@}6rJi8DEUTrW5_Y}1ad@_HF-a5FUpDZEg9uEqG#cM=vlRjtvF;)o8|w1W(&XhUS?y;4!%MP5XOK;A~@W>0oAT?C8LzXK!rfz;=CdeV>~Zaqb`49MZy0D0z&0DdFNC zI~IT~p$xhIS!EU3@N^1oIzH-{@WQ>E()i2rvTgq|Z}OQ?9)$^RH1kL;Qos_F#H?i3 zeTt3XA9p)uZH9rC27aEsa5uVgSu#ZiBPxt%%W%#4?MKYf9cSvsU zzcv)#bUsS8^u$HUw(jXZIKupI5+L}>OwjVbBLPmty^_BrVA0Bc`^iqgx!;8Q1HmAr z5IQ~Cd*k#MHzakZGmd1$`%NPdO}K<{G}!o=#Nq^0)WOchRtx*(=hYjcdoJ)eZB(U+*xS7a&B?Nf)EfpYc?9(!Ew7$ z?YpRYqfPxi!p9YLkC2w1(7k-LF4PJE z*QAphxPo2M-CS{Y?Jt7A7*8P^Sx&g>=y7&eek5qwpgDO+m@j$QnJ+{z%US%Eco);u zt8HnXuWz69M63=1Qi^Hr3f}j~<$|xpT2N9?kn6 zq*5q%T)IklSG@On6!3DXlZn6M;_t=z4!VAXGP=tgHrX_|ezW8mZMhMd+?m9wM+IxB zoZt6vQy!}0h_>T@!m)6ReT9Ntw6VO%p#65pK+$v0AGBe}bcx4EidGYs8{~XTXK%Y@ zPII+RO_{2vv!XIyc;Jq<{iJ*8aq{z%W^jP!NQOugacGm-eY8q99uHyi%iA1V2|SvG zKeB0V*#sov;9(lcZ9XP(zQ4X`!aJnD!|&Yt-0=CXj{~6*=k9W_I?c1Dl!T#+|Ef~S zsLsYppi*w48#f;QR;ex6CUKZ*5v&0a|$rSkO)u@`wFhxPZH+x&%5K1qto&x_=Q z!<~5LX8J6&^VdpDT7I%gnJ7J3XO>)tL~JMJdl%Y_kQdT@qb*)GEw-5npX;Migix3l ziq>Qjo;aff&W%1IX)=wmbgg4_Mswzq#@`$`i6?yiT~qufz3Ow50x^yfxQ70-M7vnk z=*DMFPjs@>;IbP!B^l6KsfGwu(yv~68okf@BWLD&q-PF=hJEg$dnGu=(A*lVxZ9sM zBE;t%DtUhCYvi2^xR5P=c@JeWP88-ODarV0u7?vkcFBpqRic83GZ8vd^k4R zz0`L;)0O3Rb*hh7)1SnscG8Vpc&^Zux^F6mi+|S35iy^0H@mHIu^hrZNpYI;@LS}d z@&2)Vvim}Cjmj9GWaQoUWr7W%(ZM@#BaEB(Xi)rL-@c9XSPbLePV@PHqi(%=C(=fEx>zOmp)teNrKxvn)Kg^Ee8g%c7v3hw6u63_6H z>M`1iDEAMqY?~O@A3-0+m~r(-s%{-U?v~0o9TCf?%SCOyJodslQ+?7F+rM%n2;b;I zXAj2yvR1R``PtR!X7Subf7;dF8JqXnb`V~Bljr&FOn=kGVYTSh{qcE9N5Y4x1f#gPx2x{Rrt>2m&0pKc)FS80 zX;T|tfY2Wf3No^j5NT?m%aj7>zldk_;dIV$hjGEJOhq~7lC@rp~lUit@l_^7$0)QVn~-Eu;n zFp0x*qT1+lTj`b-V{?UpL$%e9xLzI1Y@Fm~IcBDvlgd^-LeeA)l zV!`yJo?b0D#WxPqBJT8%^G@3w1vDiVvj9%ZtrOax&%-I1w5mzB>_~su5q{yYo*;n@ zv>Qyc8_Y`+gq5Be4VIyl2c8@#R;jW)GCusq9@i=scV{I2xmcIg%>8_E<{$%RX&;8+ zKuJ|Ujfgv8c08Y#+3T0tzhoi!vu@SKMb<&^$M(%OzV&rHf`2T?)-wAp;`+gAU=tD{wBLY6k)VevLDc)Z&|EKIUvCTR%FuH4 z4iMIKAj4f$s@_sgZ&=BY!RH}^FE0?n^5;(ND#>d7lJ$Eqk9GFfdB25~fQy_ctHkl~ zbtb>;Nb{SyQ8v=pDGhzQv`CeNF=G=l=U+*xTZnrXM^6|w}v!t`Sczc zFh}_2o8Wy-V{0u<(ieI6>%iD-jB&u?_mL_=SPmz*C0SBsiZAWw@0v#e@t{v{&At=% zm1dxKp>GX*jr_6_`^v(15)bIRDQ-cJE|;yfL$G^7(6U>z5K{^dTSqIfh(%%?A?Hb6 z;(pGsLcsN#*>3hKV^S@ISxpC)vb0Vl=})kSS(Cx5u%VW|=B@c z>AUpCFr-0vwe{K*r(+?e37%CI4g#8|xx|2UniD}f24v7%#o-xeUGZn!c9z)+$k8sWpOPDvHfRl%whtC+LIaw2SsMVha7xwJBalYl_-yVLSQQlmn6f zO=?wz<&n&@gf;gU079b_P@o4yXU_#VDNr>JA_{?d^ZqS)9Gz)|7J)TZfngA1@E)Su zpJMU1PBzr**B{EZ>r)crNA5k|P?=)VvkcTXPBPW3RGq zO1U1ug|T(wNLfiQkYnO6$b^1qIWQbvU^v-08i?5ep8vKH9AIz=bFjW<3UoMY0Rs9T zoFe#exF$lFH>nk1(;Apb7!|ObzxYQ)tiJ((HcP-4G1YSGCcU+w0>j_2l=x^j6Dqy|{Y=keEOoI`DZb*5t5q$mD4R9s|-EYbM ztC1f>*6!_Q^4J0XZ$0}ZTl zI3}K5+fvD7)tqeVZ%LSd*$n^7xdpe?5)rycnJ(s3{3{S_d)(USW=ESgUz;*V_~R6Zy5-{W<`|zv;iGr3IG0N9YO>1%|~U#6yYnP_pnG!J3yeQqpNrCk2fJc+Sa8MyoA z?EZ+nO46q;dzI^9UF5K#g4@*@ITxxGKn~69nh%hx#5nl=j;p_MuNSp{$(#4T z3q7S0ja`n;m^Z^X~-zHuD2J5%f&_33X4D(Nz1ucf~mH4o2#$tLnd?dlNyTf%jZydVihZD$hbvO zW-836o+@n}Mp5PNZZ6oMPDE%Nh`pdSS@%J?+y5mAJ%-#h6--AC5B!Cu=h;k!Wux@` zFVal(JN_bQy~r}*Lj6|4XzT7M^O52Q!Y^piOgA~6&e5(SbGS61$<(d*WWoz$U z2VpyJh-gN1E%^8!QurN;*-PR3DMQeT8&pWJvz#7pDbAq&yF|qiC zD|n(tI%0dqpizy|5gLZJ8`+Wv0`?CG{0;@|WeNONUS&$9w%7L^{L1dlEOcMWeOQ>h z6HUI(;u)Djl2yIp4lV~ZuDbeA z#a|tEEiIFE_f+XbYyIBij#ASp9=r!ULyB%R{DKOi)<0=^_Jvl0Ql;}pwfF-Y)XHY3 zyx;t2y>m9p=xxJgc2>N)2jeo!r|#6a7$x$@SHdaPb2%doC61A>`4-;|bF)1DBpDa*V=u z8sVsvtehaAJE>HEsx{a8S(725D9W}R9fW0EWTM9$oF5Jg0o@!Vpu15Ws@Vh(+KT!U z?wa|QQpJ#0BlBks*Ph&4gQp|@Ary|vEbilypGn}Hqdg2D&D_D4lE8j8L(07+&1u|D zGcFb*B#2gXb!SHCO`(^qjpkJ4Xyg*A?B-Cc0} zn(lfx58rQ`$1pB8GLtt%L&7sts%OfeH&%8i<@G|}fI?m1=~LD$tt>h=zsJvNv~C?p z6JQq~SZ!!+a&%n8+iDr^x+xM}+fUEXaYy8U;h3#yUi4}WaE(K;ma;b*ZZw18;zjPM zZ#rE=ytwG{DS?siLE~L^ zmLjt!Fxp`m*PYNNlFuq_hSoNx1YrruDU~DP%-n@+*9J^V>_Jp%`=OUBot^n!w-k1C z3MHJ|g9v|1cHVLzl9sRz+P+9EUUP&lTP{Q|@bgp0VRHZ>I~ zKJkk2tj?FDaw3x<7=gUeGY7^hY|kY##WUwOX7egkX7hvV`_=xI?z%3;jst9mRbplB z&5oVUVe?ap!EgrtY0dt$gzCo5*^pXuwIfvpc9Dox#qnfut+@_QW)91I%DiZwtexnJ zSTc1)nCnM&%=zJJeo;{w@$F5DQ}3}5>UMehc;4I$UNNm`2Z)6NFKChFifNlR`o92M zC)Cctgkv3^fAGdBc!2tOdYLzpo)kPbh4F1;EZJnNKEh}xOann<;`5_o+7Vvx7=i|D zDi7N*it6d-E;3#I(K2_>>ws{+$XmY>6gE@8g!Cg}c_XOaq>kayMa5|3UQ(e{V7%8; z^)3!euMU@95SMFC@#E~V?SDeUOzI{dp{)n`r&0R(vO${9MG$cs?*a2N2<4noT(4|i z*}Z7Uf*V)K#Zf7+pVG^)7!r4s&5Sr!Cnp(>c|>v~k&yMOa6>TQW>p}nh{tVGQV;s#$sdYxqSiCe`jt=5&+c$0#qY*KqaKypC2G-@2OWw5 z8B9-e#;yeUU!)wzA;kGRR7$|jinJD{;$62@3t>9{QE5%c+Y<|O(!RN3s_~;OYd2t;i1y+|FIrV^v@zq;Kq1Ny;iX!@k<(p0 zlc6zTxTWqAkJ_N42iy`NU4CeB_vMs3lj)WdhrVWftW$opcs7L7$zi>(Evqyc_|Om@ z0A`EYZVH=0ERUP_7J1@X-OM)cRe0rZ;#$&&4_c|wifnPVv69-MYA?IjN!f{UEb%16 zuyq}L5NpgLk1}MN{0JJhQd?SzQ?OkhHfVJ$zT%2~cCXkKQ;we&#so06!hu>1;Fj62 zS|};^R5(M12;7Wy=Hw0O$4TI*p1|hvlBuT1gTq!Nr5uP9a$sR5`O%0~b^V?vu$jDM zr{2x<87-YU4eB7E-!rpnr-*m2_u@AN`b`F$bnRPBd#3v25H2kMH_nD(Cyk5OaYz-2jmICaFV>qbWP@W!Y%3#*Zrh z#FWI8+Vu~vccC2P7d6)O+nMi~P3qzyiiU#BWeM@@vBMJgg#oYOJ&}HwaKOm0O)XRx zaD-qa>Dd=`V6FYF1gvEV+f@tL%ncEH@puSpqlZO z&j{+#m_f`hYyBh_rDX$R^h^blZab@5-)_tCgl9L|jda26@i{t^rW)ag1e>Xhk41Zt$%<=ucti=^Xbc!uQCl$8 z>eMcXZkA$=4=bh%I-$E`cVWhlc6`}9=7T~nKeq;&!}Jno84Ne)oa8lnC}Lr*6hADdwLjUNn^k~C+BSSGfBU1iHG=Z zImkny{3bcDQ}cXkD8!~LIUj?o6A@~)Xj_S1d#6Nb7n>!eYu6zfhG{$_OOvZhlauxP zG7G&rV6$)-%(rxmE5c#)7cXbEf|CPLZ=ye9wNFpXXu|i}_Y_6t34$Agpoz!e`4P0( zgS^PGSt#5t5mM8m;@`Xk>$c}EpE(Rqm73^SPfh_Ea1mt@JfIJ)2^o+uI8YA{`%EL8 z3=GOw!+=98JfWc|T70DzM8Yh=nHr8HM5NdxjZdsy51#K~UFA$K|OjI>vJDSK7?eX`Iw zi5)DB>cy5gZ5BBp&6MiXuF>7~oyJA?4+n&zj7?286A@MqrnHU%A_~aR8bOpB>CK0_ z0HHx#5gb^CKiGe^(h{h7U-HD7lZJ(u=6liJL48#bCk7HO4*x*RgTC^5rPdx2-fv3V);`1%q-3I3Oc|} z)!kR$X$b5Ze!YYv1Lb{=SW;_@XEo^`xLbk9cH%;791RBQaWxU?ER;zZ;%9y-wa?p5 z1wn8M7Yp#|8MgOUj>OM=lVblZgo{mW(1U9k>08j~n(u;Kr}C_Q=#K_WDXX_& z&yk~P#AE|yf;4kmUc&jhlQqDk{H$^`;{t%+peMRS+Qn7d#U<;bFn71rcWMA##dVa~ z#ZCUOjxE=gWS5kmoanNGWUsvn%h9eq=;p5aooIJvrzn0^<&X15gnHqq(sy~uiv1pu z#=5gT_1cmSxF62gXIM$oP#supx@*3nv|^H)PFj59WH4VzjzC02 zKPBxhm!GM}ThR&oP~WLkbRRqKy%w1wkf0uUkxf`mJ$Fj?j&y=Lv~li#~=GBJyT zNPH+@^e8RPx(216=k>Zs(){ShR7HBb8vf4r9yzcn9&af2G6FbB!UEekKYBIMYr~1N z9|$}>oevCTXZR{68DN>|f(e)ZJiKlB9`HZ|$xd#>lwLKeLU42dfh)iidYy?Z-zz7; zUDeiKg}sxX!DhG!-;0)WF3?P#f2Dz#!DcdJ3rL6M6Si`a^syPZnA70WAVhXWljG&v z33f^sWlSorW$PRW^ptqSya9vK{R$uLh@H?3nv7HIuG03kUxG_#!_Z>$DWUh3Av#gY zj2mEs8D1JG=j=rc7dP4D!05>iVRsh`QGmQBrka;IvLkAq|7k&2h-E*Fav%uSbliP& z$|ZWz%N32qH?R~VYBl^*b0!KXb@|U}L~jMZ7={xAo}_d)4Bfp8Zd`lJ4J>Y4PLQwu z$PDuY_EOG{dz}H~FsC7mHzlO}CuwF52R-L2E}0ecFh7qNKW#}DbE}8OiEp)(!L#G& zCl&Ht3hWsf#xIJ9FwbjBzixv-b$PYqkJ$Q*L*U}9Iti63&vhZS`Nu#XxQS=dq4Af=(UPl=o&#%$?Z*h5(kaa zZFgzU3iV3b$;)1mYpskhej(EQ@|h^Acs9(fLnUG_LXJfE?E%9zAzTm)2o~+F#n`Py z#+HYM>Jg=plWwOn#nAf2AxY8R%_vWg7*B1<@}L3F1Q?N$@Z}e}2Y~?FWmWL)a4n=hTmkuJ?9uK9DfhlI|oRZY+dzfT7Vqb_QhD#8G6o z-jaTjY+=#JeF%XIiUdfesI{NtsQ0cvRO63>)Hn_*YAvfDEfJ*5yAv&hS2nyeR)i^p zFVOA$;-0m`?7}2nOsK7n)m~&w5@x=$uU@PP|7%Ph)*1d-IA0YxM|WieM?~IPZpJvr zx-Wmwp>Q1J1i_-dZB=sP;3nzfXGf0Al~>Ga`!ch3L<^%FTNCzlU@`bIbWD2o3q_fq zz(luwqW$4yI|ysQ>G?Ve^ClIGUWL8!@Ks9zEjcKyG>IKK#_}-VgZ+k@EMh@E#)$u=Tgz@%$I_kP!3hO{PJjEbi<2Gsi+sW&J;c@Qmb*HcXy^bcx{P0RdPZDVWHj5jiCMOU!jgl*(_Mz)Ec%@^`5CQ%#Y@*+pq7 zBX&G-5+^8@{IsTx?e>q-mS_3jl0WWjq2GHOJKq&cPP&h+rDOCjlS(gk=Am_UM}n3|@AyFAvhc2A=-XGyXV(u|=M zCj-`qXZEomW|s$d3>Or7CCHpSfYgNOBl3qAAc!nvp_h4dnO^UhWPa~IG=K%YBL}O? zSLTLjyEue4YfiZO_GJ*OgsN*T%nFQ>q6j2X=s~Vkg9$fW()frw)}bsC@G50z*vSB{ zTt%KJ1FnMw&c(-y?xjKl?hXZ5skm2SYw?DyeOJFUMi(ODjg@gezF#bsr#mf(==w@R zQKP})yJ&MAsvy*&XiYjoWhc69jF`Zh*0s@Y@wK4j-SxEuRQCZ#sM3Vr?`yY^j6n2G z5Vl!jR>SY{6*j8{w?lQiC_+aSK{y&ws4F`)r~{e0G8i$q97H(n@y`ti28OK$6ZBfk zM_o#Ol76*$@CgHPulFsHA^~=!Y}J19vNCJ4L#!#d`Luv@&G6cX6eo@F1XQh)aI5P; zEC5$U#{(~%yAKFL>mMTVq%SXxe!&hA^)V@9 z?s$5u-nMzl+wHZQB2w>p)#+565otdgn`slXsmr@aDB1mEEJco4thV#H!)JCH@--9Zq zXI8^-mytR>>=*GM9xqbpc;o$!j-TVE=N=UvPs%dzilGS3;QY2UPJ7);KIFL;wu z>%9n^>rjWZ)Ry#9$I(nrY{6u3xDwn4}$rN-BZ8AS;sanx~qEH0KJ>=GeKNzV!-(oyEg}kTywyv=5rnb(s9&Cy(v#$9VUSjQGEk~))SM|J#4*jqdV>*s2Dbsq<3hU;X!AVAV zi9%x)U1*i|pwyUDHzYflH-eX&I*xiOchbm&f}^fWuStZ~H1skY#d^^cYx2~&t1Zs<&cVviHi0)Qhhn!T!v%o z((Y=i8hqTzSf((qi+eutv@T9X{m^D_yEz+b}J_qg-kr9&WD-Ve2>HDs#6)>$l*sYN}Z2uA(yQ~n6X)w z4|EpS$R$Zw=AQQQm=q0IQD@9`=^e|Wo7bptV?0&Z6?mgc+jEDXSn%m!;r#@nrA~{l zTd%^W#WP?;%>|S(Ae0dWpV8=4hv=&+!4NkQ9H<{`tK#?E^6Ue_R%{ksrVgaTzHVTv zi~8mVjXCJ3gu7fQg?($wGpa%hWW1u*C>J{fDPaVZ5A0ES#A95$zBsx#(B6l zB|Luqgf`nxyB1{1zQ=~Ou4q`(nL~HuM5{63vI7&2s*6rhifWQ;IjA-t=Ci7a>tzZB z{W(Zd%lOe3Cse|D(;Ts+N(93U#!-qhMe?H;vb3UlKCkCcLc#WsiD$`b!Hvg0p1|V+ zPM@8JsMw6`AT|v{(gKYniFNOuo9LH$nL#05#X;;9hNPeYh9o_UkQHBENe{Ou=8U!+ z>BgpGWd8FPUvt{uxL5o-><}Sg5fScd{n!Scqqnc%JK~G=6ty)=x*s8229*qjMz(gE z*=^a?ldwbxM|95Or9iWSp^>rah{o^upz#@fMq4R*6*V}tkFTfhV2S~x>1*KnO=4+4 zzjb@?`vh{5r|4_j>|iKfCc7r3yS^);4JVYiohnzcg8c}qq~{FDDCU0H1=7fEmavN! zdI3$+vj7|z;@WiUaR82X2;wNs%wUVe3z-zrW#vAi%Ul|QN4o8^7JDv9O80O1w*enx z8UP;Zc?TS3oSh-H3xg}RZD5Azasps<_*9#E9jPUW+2@_mQYVfv*1sE|+lB=?VU_=n zX(Y3RK(|c_X2L3yOP#pJVDPD4^}7EzG%mCJ+^NqJkyO8T06#J_aBfNN`4}*RxkK)~ ziZjR1^27gFPa3O^U>0(hW$W3-ixrz+CKV-u3%zYS^;&$A6YqDA<`7gAjvoU`S8+-Q zTP6;0$AN9Q=C2Fx+*QDbr$X$cu%P{QoQMwLQHTyz@Z;LOU4HZWO?FKWH@N0(Q+x=p z1k-K!K1$EKHwLo16hth=&8IrK^o1 z<9-9^8qU2_&qWWs3tZEW`Hh71*RRc9pWyx9h=rKfh|9uA*T2SNXUAQfdc~Ab7Ke(Q z`@-~4>t!aJ-r-gDG1aMU)o7~N(m4LixkL#8fc(QUv5k-DZ=nEJQ z=xZ~@yBlaB#04=4Bf=*7_Krh|{h6&C{82Ma^95-&H0(C^?QfwRLhJ&zwD5^917CDV zAqHVspeUV@{gLfe+cpU;5=8HtI|rrhYFju7^rpm3XB}*mFl2uS87e7Cu(f?%8^)I# zV%o7k(q_{rSWdl$YUgBXp5gbyYWnYo^AWk8%FHSHS~2c##hn!xx{EAQtjF$TDrN_p zR(~_SdwB8SVKz(ZjD4Eq)Qlj59mDrdu44`KV+|vpED!>~FHP3{_SCZizl0TW`Ga|p zP4K13mWgYY?|kQz_B@DUBh;0?`Ss!xx0|a8evWnmqG`Ju9;5<7ddmy!ifXRhJr34X z*bb7uc8y}6Fv%AZ+4L=h9NbfOyifPW(`K*s7ulLF_OAYGF$9(NR8bQshA;y~GWa(z zZW`G@mF#V79oV2Y_Qr@O;%PEaZazxC0lNHu`{NO-pt#6>J8*|-kNWMp=p+5m{)U=sZ*csI-Q$jW`Ti%hcQhW? zd;d6gpz`@SGUENlGeC6FNW~WLlfJ6C z_VvE3xldodw5UFAPOLy{ud;$zxKgABkU(S1${F0nzVmWjE%mRGX@N-Dtr^zoqP9P+ z(M%?=&9sP1=l#vI*0o)uYo4)W)}WIu;a7v(g)A%skF>n`Ye!2~47CF;*1Z@JLu7NQ zGTN-8QXhG9Aq>57sYSo>95fx`gN)AvE`4i^1+W&g4)k`(%jhIgdCH-%tm@ZBN0v`+^_U?Q%RXQL#~PWQ zo^HC{?71nm2B)aGl|x^ncnfaM63Y{0Rsz*=-Upsm5?#*=&z+wZJkIvMDmyi5ARK|1 zdGcKtktbJM%tDlGXC}z7g&u&FLB1-Xaf~APL~mZW^|kQ4m0uov*@asOUyGNMV@m9g zz*OCo4{5lA=RdD_`1tf67=*<&V$QR^B>%_;zjzvHuu4s{ILuiTYVYnJOtfvIJ*FPT zG$m1CwC@u)6uu-tJzOE=E2#g|Xz#@uY|P6=Wa9{?TFw#E)R2*X#B`=0=nD(tj}fJz<| zzJeDc{oAJ-xX$nD=j)2!KMCKO4jpBKE`8t?p@@pve?Ex9EKqiZD55sBv9bJbquN}x z>{9`@U!vT&0p2P4Z=cp%*TlaE{&$G~%7k5f(WfPVgAZ^>{|yDav=qGK?Jp+&s^tEs zhWpQ{KrSJ+0{k~`G_>9N14R(b?7yH~*Fpb@^5;uZ|6wQp=}iR6pRY{)6X4G`)cpfs zqj(MQ&-?2BB>nTfR{xMXD*q<^^DS3@BK%ne{|`d2-ZjGiRZaY#fPWU1{{tAJ|9=Ab zPl@@TfPa=~{{t9qa1HqH1>1iT|5*(D53xQd6a>ooqZIhh^Xt;!KSBSjGyMlt)A)Y} z^t$TwPtZRL82SG@7R052uP(*OVf diff --git a/pygen.ipynb b/pygen.ipynb index 5b814a6..79251c1 100644 --- a/pygen.ipynb +++ b/pygen.ipynb @@ -144,7 +144,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "id": "58645013", "metadata": {}, "outputs": [ @@ -152,16 +152,16 @@ "name": "stdout", "output_type": "stream", "text": [ - "Real instructions : 128\n", - "Reserved slots : 14\n", + "Real instructions : 132\n", + "Reserved slots : 10\n", "Duplicate check : PASSED\n", "\n", "Groups found:\n", "group\n", "Integer 19\n", + "Boolean 16\n", "System 15\n", "Bit Wise 14\n", - "Boolean 12\n", "Branch 12\n", "Floating Point 10\n", "Casts 10\n", @@ -283,7 +283,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "id": "452bc76c", "metadata": {}, "outputs": [ @@ -292,7 +292,7 @@ "output_type": "stream", "text": [ "Masks written to: .//autogen/InstructionMasks.hpp\n", - "Lines generated : 272\n" + "Lines generated : 280\n" ] } ], @@ -357,7 +357,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "id": "5aaebef0", "metadata": {}, "outputs": [ @@ -365,7 +365,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Instructions formatted: 128\n", + "Instructions formatted: 132\n", "\n", "--- Preview (first 2 instructions) ---\n", " // [System] 0x000 — NOP: No Operation\n", @@ -380,7 +380,7 @@ "\n", "\n", "CPU.hpp updated successfully at: .//src//spider/runtime/cpu/CPU.hpp\n", - "Total lines in updated file: 883\n" + "Total lines in updated file: 911\n" ] } ], @@ -451,7 +451,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "id": "instrmap_gen", "metadata": {}, "outputs": [ @@ -460,9 +460,9 @@ "output_type": "stream", "text": [ "InstrMap.cpp written to: .//src//spider/runtime/instr/InstrMap.cpp\n", - " Size : 34,157 bytes\n", - " Array entries : 512 (128 populated, 384 nullptr)\n", - " Switch cases : 128\n", + " Size : 33,581 bytes\n", + " Array entries : 512 (132 populated, 380 nullptr)\n", + " Switch cases : 132\n", " Line endings : LF-only verified\n" ] } @@ -545,11 +545,11 @@ " mnem = opcode_to_mnem.get(opc)\n", " if mnem:\n", " name = opcode_to_name[opc]\n", - " L.append(f' &CPU::{mnem + \",\":<28s}// 0x{opc:03X} — {name}')\n", + " L.append(f' &CPU::{mnem + \",\":<22s}// 0x{opc:03X} — {name}')\n", " else:\n", " tag = ''\n", " if opc in reserved_opcodes:\n", - " tag = ' (reserved)'\n", + " tag = ' (reserved)'\n", " L.append(f' {\"nullptr,\":<28s}// 0x{opc:03X}{tag}')\n", "\n", "L.append('};')\n", @@ -681,7 +681,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.14.3" + "version": "3.13.7" } }, "nbformat": 4, diff --git a/src/spider/SpiderRuntime.cpp b/src/spider/SpiderRuntime.cpp index 8c84608..fd35d78 100644 --- a/src/spider/SpiderRuntime.cpp +++ b/src/spider/SpiderRuntime.cpp @@ -1,18 +1,10 @@ #include "SpiderRuntime.hpp" -#include - #include namespace spider { - const u32 RUNTIME_VERSION_NO = 0x00000000; // v0.1 - const std::string RUNTIME_VERSION = "alpha v0.1"; - + const u32 RUNTIME_VERSION_NO = 0x00000001; // v0.1 + const std::string RUNTIME_VERSION = "alpha v0.1"; } - -int main() { - spider::liveDebugMain(); - return 0; -} diff --git a/src/spider/runtime/cpu/CPU.cpp b/src/spider/runtime/cpu/CPU.cpp index 7bba8a4..92159a9 100644 --- a/src/spider/runtime/cpu/CPU.cpp +++ b/src/spider/runtime/cpu/CPU.cpp @@ -76,8 +76,8 @@ namespace spider { void CPU::fetchOperDst() { // Move the operand ptrs - _alu = &ALU0; _opers[1] = _opers[0]; + _opers[0] = &ALU0; // call specific addressing mode (this->*(CPU::addrModes[_addrm & 0b111]))(); // mask added here too @@ -85,7 +85,7 @@ namespace spider { void CPU::fetchOperSrc() { // set ALU - _alu = &ALU1; + _opers[0] = &ALU1; // call specific addressing mode (this->*(CPU::addrModes[_addrm & 0b111]))(); // mask keeps index within 0-7 @@ -95,13 +95,23 @@ namespace spider { _addrm++; } + void CPU::fetchOperReg() { + _dst = &GPR[_reel->readU8(RI++) & 0xF]; + } + + void CPU::fetchOperRegReg() { + // read the full byte + u8 reg = _reel->readU8(RI++); + _src = &GPR[(reg >> 4) & 0xF]; + _dst = &GPR[ reg & 0xF]; + } void CPU::execute() { (this->*(CPU::instrMap[_opcode]))(); // no null check needed + // vvv MUST PROFILE: Is this faster than executing an empty function? if(_post) (this->*_post)(); } - // Addressing Modes // /** @@ -115,8 +125,7 @@ namespace spider { * Immediate Addressing Mode */ void CPU::imm() { - _reel->loadRegister(RI, _size, _alu); - _opers[0] = _alu; + _reel->loadRegister(RI, _size, _opers[0]); _post = &CPU::imp; RI += 1 << _size; } @@ -127,19 +136,19 @@ namespace spider { void CPU::abs() { // Load the actual ptr into the ALU u8 mm = u8(getFlag(CPU::FLAG_MEMORY_MODE)); - _reel->loadRegister(RI, mm, _alu); + _reel->loadRegister(RI, mm, _opers[0]); RI += 1 << mm; // read the memory from RAM - _store = _alu->_u64; - _ram->loadRegister(_store, _size, _alu); + _store = _opers[0]->_u64; + _ram->loadRegister(_store, _size, _opers[0]); _post = &CPU::psw; } /** * Register Addressing Mode */ - void CPU::reg() { // NOT FINISHED + void CPU::reg() { // Two consecutive registers can be declared // Shift if the top part will become .reg too u8 sh = ((_addrm & 0b11000) == 0b11000) * 4; @@ -147,12 +156,11 @@ namespace spider { // get byte u8 reg = (_reel->readU8(RI) >> sh) & 0xF; - _alu = &GPR[reg]; - _opers[0] = _alu; // explicitly sets _opers[0] = _dst + _opers[0] = &GPR[reg]; // explicitly sets _opers[0] = _dst RI += use; // store no-op - _post = &CPU::imp; + _post = nullptr; } /** diff --git a/src/spider/runtime/cpu/CPU.hpp b/src/spider/runtime/cpu/CPU.hpp index 07709e9..73f9c66 100644 --- a/src/spider/runtime/cpu/CPU.hpp +++ b/src/spider/runtime/cpu/CPU.hpp @@ -64,7 +64,6 @@ namespace spider { struct { register_t* _dst; register_t* _src; - register_t* _alu; }; register_t* _opers[2]; }; @@ -172,6 +171,18 @@ namespace spider { */ void fetchOperSrc(); + /** + * Fetches special addressing where + * one register is addressed. + */ + void fetchOperReg(); + + /** + * Fetches special addressing where + * two registers are addressed. + */ + void fetchOperRegReg(); + /** * Executes an opcode, by means of directly * accessing the instruction map and @@ -469,36 +480,56 @@ namespace spider { // Operation: # of 1's into Dst void CNT(); - // [Boolean] 0x030 — EQ: Equal + // [Boolean] 0x02E — EQ: Equal // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Operation: Dst == Src into Dst void EQ(); - // [Boolean] 0x031 — NE: Not Equal + // [Boolean] 0x02F — NE: Not Equal // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Operation: Dst != Src into Dst void NE(); - // [Boolean] 0x032 — GT: Greater Than + // [Boolean] 0x030 — GT: Greater Than // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Operation: Dst > Src into Dst void GT(); - // [Boolean] 0x033 — GE: Greater or Equal Than + // [Boolean] 0x031 — GE: Greater or Equal Than // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Operation: Dst >= Src into Dst void GE(); - // [Boolean] 0x034 — LT: Lower Than + // [Boolean] 0x032 — LT: Lower Than // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Operation: Dst < Src into Dst void LT(); - // [Boolean] 0x035 — LE: Lower or Equal Than + // [Boolean] 0x033 — LE: Lower or Equal Than // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Operation: Dst <= Src into Dst void LE(); + // [Boolean] 0x034 — GTU: Greater Than, Unsigned + // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F + // Operation: Dst > Src into Dst + void GTU(); + + // [Boolean] 0x035 — GEU: Greater or Equal Than, Unsigned + // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F + // Operation: Dst >= Src into Dst + void GEU(); + + // [Boolean] 0x036 — LTU: Lower Than, Unsigned + // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F + // Operation: Dst < Src into Dst + void LTU(); + + // [Boolean] 0x037 — LEU: Lower or Equal Than, Unsigned + // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F + // Operation: Dst <= Src into Dst + void LEU(); + // [Branch] 0x038 — JMP: Jump to absolute position // Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F // Operation: Dst -> Instruction Register @@ -541,22 +572,22 @@ namespace spider { // [System] 0x040 — SFB: Store (User) Flag Bit // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F - // Operation: + // Operation: void SFB(); // [System] 0x041 — LFB: Load (User) Flag Bit // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F - // Operation: + // Operation: void LFB(); // [Branch] 0x042 — JUF: Jump to absolute position, if user flag is true // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F - // Operation: + // Operation: void JUF(); // [Branch] 0x043 — JUR: Jump to relative position, if user flag is true // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F - // Operation: + // Operation: void JUR(); // [Memory] 0x044 — PUSH: Push to stack @@ -601,7 +632,7 @@ namespace spider { // [Floating Point] 0x050 — FLI: Float Load Immediate // Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C - // Operation: + // Operation: void FLI(); // [Floating Point] 0x051 — FNEG: Float negate @@ -816,89 +847,73 @@ namespace spider { // [Matrix] 0x080 — MADD: Matrix Addition // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void MADD(); // [Matrix] 0x081 — MSUB: Matrix Subtraction // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void MSUB(); // [Matrix] 0x082 — MMUL: Matrix Multiply // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void MMUL(); // [Matrix] 0x083 — MINV: Matrix Inverse // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void MINV(); // [Matrix] 0x084 — MTRA: Matrix Transpose // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void MTRA(); // [Matrix] 0x085 — MDET: Matrix Determinant // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void MDET(); // [Quaternion] 0x086 — QMKA: Quaternion Make from Angles // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void QMKA(); // [Quaternion] 0x087 — QMUL: Quaternion Multiply // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void QMUL(); // [SIMD] 0x08A — XADD: SIMD Addition // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void XADD(); // [SIMD] 0x08B — XSUB: SIMD Subtract // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void XSUB(); // [SIMD] 0x08C — XAMA: SIMD Alternate Multiply-Add // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void XAMA(); // [SIMD] 0x08D — XMUL: SIMD Multiply // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void XMUL(); // [SIMD] 0x08E — XDIV: SIMD Divide // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void XDIV(); // [Easter Eggs] 0x0F0 — UPY: Will place "YUPI" in memory // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: + // Operation: void UPY(); - - //[Easter Egg] 0x0F1 - LLGS: Injects the custom 8x4 ASCII spider logo - // into RAM [0x80-0x9F] and signs Register RA with the "LLGS" hex literal. - void LLGS(); - - // [Easter Eggs] 0x0F6 — DGANT: "In kaaba Spider" (Yucatec Maya: My name is Spider) - // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 - // Operation: Writes "IN KAABA SPIDER" one char per GP register - void DGANT(); - - /** - * @brief BRAD (0xF7) - Memory Integrity Checksum - * Escanea los primeros 256 bytes de memoria y valida contra una firma de seguridad. - * Implementado por Bradley Vergara Lara - Estancia 2026. - */ - void BRAD(); // // diff --git a/src/spider/runtime/debug/LiveDebug.cpp b/src/spider/runtime/debug/LiveDebug.cpp deleted file mode 100644 index 0c81c3f..0000000 --- a/src/spider/runtime/debug/LiveDebug.cpp +++ /dev/null @@ -1,402 +0,0 @@ -#include "LiveDebug.hpp" - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -namespace spider { - - void drawHead(Terminal& t) { - t.move(1, 1) - .style(Terminal::FG_YELLOW) - .print(" Spider Runtime Live Debug ") - .style(Terminal::RESET).print(" | ") - .style(Terminal::FG_B_CYAN).print(" Sintek Analytics @ 2026 ") - .style(Terminal::RESET).print(" | ") - .style(Terminal::FG_B_BLACK).print("Press ESC to exit") - .style(Terminal::FG_BLACK) - .style(Terminal::BG_YELLOW) - .move(3, 1).print(" // __ \\\\").print(" ") // 27 - .move(4, 1).print(" \\\\( )//").print(" SPIDER v0.1 ") - .move(5, 1).print(" //()\\\\ ").print(" alpha ") - .move(6, 1).print(" \\\\ // ").print(" ") - .style(Terminal::RESET) - .style(Terminal::FG_B_BLACK) // 4x8 for the menu - .move(3, 28).print("[ STEP ]") - .move(4, 28).print("[ STOP ]") - .move(5, 28).print("[ RUN ]") - .move(6, 28).print("[ MENU ]") - .style(Terminal::RESET) - ; - } - - void drawCPUTempl(Terminal& t) { - i32 r = 8, c = 1; - i32 w = 35, h = 31; - t.drawBox(r, c, w, h, "CPU"); - - const std::string regs[] = { - "RA", "RB", "RC", "RD", - "RX", "RY", "R0", "R1", - "R2", "R3", "R4", "R5", - "R6", "R7", "R8", "R9", - "RF", "RI", "RS", "RZ", - "RE", "RN", "RV", "RM", - "ALU0", "ALU1" - }; - const std::string alt[] = { - Terminal::FG_WHITE, - Terminal::FG_B_BLACK, - }; - - r++; - c++; - - t.move(r++, c); - t.style(Terminal::FG_B_YELLOW); - t.print_center(w - 2, "GP Registers"); - t.style(Terminal::RESET); - for (i32 i = 0; i < 8; i++) { - t.style(alt[i & 1]); - t.move(r + i * 2, c); - t.print(regs[i * 2]); - t.move(r + i * 2, c + 17); - t.print(regs[i * 2 + 1]); - } - - t.move(r += 16, c); - t.style(Terminal::FG_B_CYAN); - t.print_center(w - 2, "System Registers"); - t.style(Terminal::RESET); - r++; - for (i32 j = 0, i = 8; i < 12; j++, i++) { - t.style(alt[j & 1]); - t.move(r + j * 2, c); - t.print(regs[i * 2]); - t.move(r + j * 2, c + 17); - t.print(regs[i * 2 + 1]); - } - - t.move(r += 8, c); - t.style(Terminal::FG_GREEN); - t.print_center(w - 2, "Extra Registers"); - t.style(Terminal::RESET); - r++; - for (i32 j = 0, i = 12; i < 13; j++, i++) { - t.style(alt[j & 1]); - t.move(r + j * 2, c); - t.print(regs[i * 2]); - t.move(r + j * 2, c + 17); - t.print(regs[i * 2 + 1]); - } - - t.flush(); - } - - void printU64Hex(u64 n) { - std::ios state(nullptr); - state.copyfmt(std::cout); - std::cout - << std::hex - << std::uppercase - << std::setfill('0') - << std::setw(16) - << n; - std::cout.copyfmt(state); - } - - void drawCPU(Terminal& t, CPU& cpu) { - i32 r = 8, c = 1; - - const register_t* regs[] = { - &cpu.RA, &cpu.RB, &cpu.RC, &cpu.RD, - &cpu.RX, &cpu.RY, &cpu.R0, &cpu.R1, - &cpu.R2, &cpu.R3, &cpu.R4, &cpu.R5, - &cpu.R6, &cpu.R7, &cpu.R8, &cpu.R9, - //&cpu.RF, &cpu.RI, &cpu.RS, &cpu.RZ, - //&cpu.RE, &cpu.RN, &cpu.RV, &cpu.RM, - &cpu.ALU0, &cpu.ALU1 - }; - const u64* sys_regs[] = { - &cpu.RF, &cpu.RI, &cpu.RS, &cpu.RZ, - &cpu.RE, &cpu.RN, &cpu.RV, &cpu.RM, - }; - const std::string alt[] = { - Terminal::FG_WHITE, - Terminal::FG_B_BLACK, - }; - - r++; - c++; - t.move(r++, c); - t.style(Terminal::RESET); - r++; - for (i32 i = 0; i < 8; i++) { - t.style(alt[i & 1]); - t.move(r + i * 2, c); - printU64Hex(regs[i * 2]->_u64); - t.move(r + i * 2, c + 17); - printU64Hex(regs[i * 2 + 1]->_u64); - } - - t.move(r += 16, c); - r++; - for (i32 j = 0; j < 4; j++) { - t.style(alt[j & 1]); - t.move(r + j * 2, c); - printU64Hex(*sys_regs[j * 2]); - t.move(r + j * 2, c + 17); - printU64Hex(*sys_regs[j * 2 + 1]); - } - - t.move(r += 8, c); - r++; - for (i32 j = 0; j < 1; j++) { - t.style(alt[j & 1]); - t.move(r + j * 2, c); - printU64Hex(regs[16 + j * 2]->_u64); - t.move(r + j * 2, c + 17); - printU64Hex(regs[16 + j * 2 + 1]->_u64); - } - - t.flush(); - } - - u32 addressWidth(isize ramSize) { - if (ramSize == 0) return 1; - isize maxAddr = ramSize - 1; - u32 digits = 0; - // Shift by increments of 4 (one hex nibble) - // We use a do-while to ensure at least 1 digit is returned for small RAMs - do { - digits++; - maxAddr >>= 4; - } while (maxAddr > 0); - - return digits; - } - - /** - * Draws a vertical scrollbar - * @param x The column where the bar should be placed (usually box_x + width - 1) - * @param y The starting row of the track (usually box_y + 1) - * @param trackHeight The internal height of the box (box_height - 2) - * @param progress The current progress - * @param total The total - */ - void drawScrollThumb(Terminal& term, u32 x, u32 y, u32 trackHeight, isize progress, isize total) { - if (total == 0 || trackHeight <= 0) return; - - // 1. Draw the background track (Light Shade: ░) - term.style(Terminal::FG_B_BLACK); // Dim the track - for (u32 i = 0; i < trackHeight; ++i) { - term.move(i32(y + i), i32(x)).print("░"); - } - - // 2. Calculate Thumb Position - // Cap progress to total to avoid overflow - if (progress > total) progress = total; - - // Calculate ratio (0.0 to 1.0) - f64 ratio = f64(progress) / f64(total); - - // Map to track coordinates - u32 thumbOffset = u32(ratio * (trackHeight - 1)); - - // 3. Draw the Thumb (Full Block: █) - term.move(i32(y + thumbOffset), i32(x)); - term.style(Terminal::FG_WHITE).print("█"); - term.style(Terminal::RESET); - } - - /** - * Draws a hex dump of memory within a styled terminal box. - * @param term Reference to your Terminal instance - * @param ram The RAM - * @param scrollPos The starting address to display - * @param x Starting column - * @param y Starting row - * @param width Width of the box - * @param height Height of the box - */ - void drawRAM(Terminal& term, RAM& ram, u64 scrollPos) { - // 1. Draw the container box - u32 y = 3; - u32 height = 36; - - // 2. Configuration for the hex layout - u32 addrWidth = addressWidth(ram.size()); - u32 bytesPerRow = 8; - u32 displayRows = height - 2; // Subtract top/bottom borders - u32 width = (2 + 2 + 16 + 7 + 3 + 8 + 4) + addrWidth; - u32 x = 37; - - // create box - term.drawBox(i32(y), i32(x), i32(width), i32(height), "RAM"); - drawScrollThumb(term, x + width - 2, y + 1, height - 2, scrollPos, ram.size()); - - // Ensure scrollPos is within bounds and aligned - //if (scrollPos < 0) scrollPos = 0; - if (scrollPos > ram.size()) scrollPos = ram.size(); - - for (u32 i = 0; i < displayRows; ++i) { - isize currentRowAddr = scrollPos + (i * bytesPerRow); - - // address lock - if (currentRowAddr >= ram.size()) { - term.move(i32(y + 1 + i), i32(x + 1)); - term.print(std::string(width - 3, ' ')); - continue; - } - - std::stringstream ssaddr; - std::stringstream ss; - - // setup ss - ssaddr << std::setfill('0') << std::uppercase << std::hex; - ss << std::setfill('0') << std::uppercase << std::hex; - - // address - ssaddr << std::setw(i32(addrWidth)) << currentRowAddr << " "; - - // Hex Bytes - std::string asciiPart = ""; - for (u32 j = 0; j < bytesPerRow; ++j) { - isize targetAddr = currentRowAddr + j; - if (targetAddr >= ram.size()) { - ss << ""; // Padding for end of memory - asciiPart += ""; - continue; - } - - u8 byte = ram[targetAddr]; - ss << std::setfill('0') << std::setw(2) << std::hex << u32(byte) << " "; - asciiPart += (std::isprint(byte) ? char(byte) : '.'); - } - - // --- Combine and Print --- - term.move(i32(y + 1 + i), i32(x + 2)); // Move inside the box - term.style(Terminal::FG_B_CYAN).print(ssaddr.str()); // Hex part in Cyan - term.style(Terminal::FG_WHITE).print(ss.str()); - term.style(Terminal::FG_B_YELLOW).print(" | "); - term.style(Terminal::FG_WHITE).print(asciiPart); // ASCII part in White - } - - term.style(Terminal::RESET); - term.flush(); - } - - std::string getTimestamp() { - std::time_t t = std::time(nullptr); - std::tm lt; -#if defined(SPIDER_OS_WINDOWS) - localtime_s(<, &t); -#endif -#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS) - localtime_r(&t, <); -#endif - return std::format("{:02}:{:02}:{:02} {:02}/{:02}/{}", - lt.tm_hour, lt.tm_min, lt.tm_sec, - lt.tm_mday, lt.tm_mon + 1, lt.tm_year + 1900); - } - - void drawTime(Terminal& t) { - //auto now = std::chrono::system_clock::now(); - //auto now_l = std::chrono::current_zone()->to_local(now); - //auto now_s = std::chrono::floor(now_l); - //std::string time_str = std::format("{:%H:%M:%S}", now_s); // Format: HH:mm:ss - //std::string date_str = std::format("{:%d/%m/%Y}", now_s); // Format: dd/MM/YYYY - - t.move(1, 76); - t.style(Terminal::RESET); - t.print(" | ").style(Terminal::FG_GREEN).print(getTimestamp()); - } - - void redraw(Terminal& t, Runtime& r, u64 scroll) { - // draw CPU, RAM - drawCPU(t, r.cpu); - drawRAM(t, r.ram, scroll); - } - - int liveDebugMain() { - Terminal t; - Runtime runtime(1024); - - - InstrReelFixed fix(100); - - - - runtime.hookReel(&fix, false); - - - - bool running = true, update = true; - u64 ramScroll = 0; - u8 key = Terminal::UNKNOWN; - - t.println("Starting Spider live debug..."); - t.altbuff(true).cursor(false); - - drawTime(t); - drawHead(t); - drawCPUTempl(t); - - // delay for time - auto last_exec = std::chrono::steady_clock::now(); - auto delay = std::chrono::milliseconds(1000); - - while (running) { - // draw time - auto now = std::chrono::steady_clock::now(); - if (now - last_exec >= delay) { - drawTime(t); - last_exec = now; - } - - // redraw something if it updated - if (update) { - redraw(t, runtime, ramScroll); - update = false; - } - - // Handle Input - key = t.getKeyNb(); - switch (key) { - case Terminal::ESC: - running = false; - break; - case Terminal::UP: - if (ramScroll >= 16) ramScroll -= 16; - update = true; - break; - case Terminal::DOWN: - if (runtime.ram.size() >= 16 && ramScroll <= runtime.ram.size() - 16) ramScroll += 16; - update = true; - break; - case Terminal::ENTER: - update = true; - runtime.cpu.fetchInstr(); - runtime.cpu.execute(); // looks up instrMap[_opcode] & calls the correct instruction method (e.g. FMUL) - break; - default: - break; - } - - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - - t.altbuff(false).println("Stopped Spider live debug.").flush(); - return 0; - } - -} diff --git a/src/spider/runtime/debug/LiveDebug.hpp b/src/spider/runtime/debug/LiveDebug.hpp deleted file mode 100644 index 69140cb..0000000 --- a/src/spider/runtime/debug/LiveDebug.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace spider { - - int liveDebugMain(); - -} diff --git a/src/spider/runtime/instr/InstrMap.cpp b/src/spider/runtime/instr/InstrMap.cpp index 35e8f78..c6a29c0 100644 --- a/src/spider/runtime/instr/InstrMap.cpp +++ b/src/spider/runtime/instr/InstrMap.cpp @@ -35,149 +35,149 @@ namespace spider { * if (fn) (cpu.*fn)(); */ CPU::Fn CPU::instrMap[] = { - &CPU::NOP, // 0x000 — No Operation - &CPU::SPDR, // 0x001 — Will place the Spider version of the interpreter in RA - &CPU::MMODE, // 0x002 — Set Memory Mode - &CPU::INT, // 0x003 — Interrupt - &CPU::LRV, // 0x004 — Load Interrupt Vector Register - &CPU::FSR, // 0x005 — Fetch System Register - &CPU::FIR, // 0x006 — Fetch Instruction Register - &CPU::FZR, // 0x007 — Fetch Stack Base Register - &CPU::LSR, // 0x008 — Load System Register - &CPU::FVR, // 0x009 — Fetch Interrupt Vector Register - &CPU::MOV, // 0x00A — Moves values - &CPU::MOR, // 0x00B — Moves registers - &CPU::AMOV, // 0x00C — Array Move, uses X and Y as ptrs, A as amount - &CPU::SWP, // 0x00D — Swap registers - &CPU::AHM, // 0x00E — Ask Host for Memory - nullptr, // 0x00F (reserved) - &CPU::COM, // 0x010 — One's complement - &CPU::NEG, // 0x011 — Two's complement - &CPU::EXS, // 0x012 — Extend Sign - &CPU::INC, // 0x013 — Increment - &CPU::DEC, // 0x014 — Decrement - &CPU::ADD, // 0x015 — Addition - &CPU::SUB, // 0x016 — Subtraction - &CPU::MUL, // 0x017 — Multiplication - &CPU::UMUL, // 0x018 — Unsigned Multiplication - &CPU::DIV, // 0x019 — Division - &CPU::UDIV, // 0x01A — Unsigned Division - &CPU::MOD, // 0x01B — Modulus - &CPU::UMOD, // 0x01C — Unsigned Modulus - &CPU::DMOD, // 0x01D — Division and Modulus - &CPU::UDMD, // 0x01E — Unsigned Division and Modulus - &CPU::FBT, // 0x01F — Test and update Flag Register (Integer) Bits - &CPU::STB, // 0x020 — Set Bit - &CPU::CRB, // 0x021 — Clear Bit - &CPU::TSB, // 0x022 — Test Bit - &CPU::BOOL, // 0x023 — Sets the booleaness of a value - &CPU::NOT, // 0x024 — Sets the inverse booleaness of a value (! BOOL) - &CPU::AND, // 0x025 — Boolean AND operation - &CPU::OR, // 0x026 — Boolean OR operation - &CPU::XOR, // 0x027 — Boolean XOR operation - &CPU::SHL, // 0x028 — Arithmetic Shift Left - &CPU::SHR, // 0x029 — Arithmetic Shift Right - &CPU::SSR, // 0x02A — Signed Shift Right - &CPU::ROL, // 0x02B — Rotate Left - &CPU::ROR, // 0x02C — Rotate Right - &CPU::CNT, // 0x02D — Counts bits - nullptr, // 0x02E (reserved) - nullptr, // 0x02F (reserved) - &CPU::EQ, // 0x030 — Equal - &CPU::NE, // 0x031 — Not Equal - &CPU::GT, // 0x032 — Greater Than - &CPU::GE, // 0x033 — Greater or Equal Than - &CPU::LT, // 0x034 — Lower Than - &CPU::LE, // 0x035 — Lower or Equal Than - nullptr, // 0x036 (reserved) - nullptr, // 0x037 (reserved) - &CPU::JMP, // 0x038 — Jump to absolute position - &CPU::JEQ, // 0x039 — Jumps to position if EQ flag is set - &CPU::JNE, // 0x03A — Jumps to position if EQ flag is cleared - &CPU::JIF, // 0x03B — Jumps if value provided is booleanly true - &CPU::JMR, // 0x03C — Jump Relative - &CPU::JER, // 0x03D — Jumps to relative position if EQ flag is set - &CPU::JNR, // 0x03E — Jumps to relative position if EQ flag is cleared - &CPU::JIR, // 0x03F — Jumps to relative position if value provided is booleanly true - &CPU::SFB, // 0x040 — Store (User) Flag Bit - &CPU::LFB, // 0x041 — Load (User) Flag Bit - &CPU::JUF, // 0x042 — Jump to absolute position, if user flag is true - &CPU::JUR, // 0x043 — Jump to relative position, if user flag is true - &CPU::PUSH, // 0x044 — Push to stack - &CPU::POP, // 0x045 — Pop from stack - &CPU::ALLOC, // 0x046 — Allocate to heap - &CPU::HFREE, // 0x047 — Delete from heap - nullptr, // 0x048 (reserved) - nullptr, // 0x049 (reserved) - &CPU::CALL, // 0x04A — Call function at instruction index - &CPU::RET, // 0x04B — Return from a function - &CPU::EDI, // 0x04C — Enable/Disable External Interrupts - &CPU::SHSS, // 0x04D — Set Hotswap Signal Bit - nullptr, // 0x04E (reserved) - nullptr, // 0x04F (reserved) - &CPU::FLI, // 0x050 — Float Load Immediate - &CPU::FNEG, // 0x051 — Float negate - &CPU::FADD, // 0x052 — Float add - &CPU::FSUB, // 0x053 — Float subtract - &CPU::FMUL, // 0x054 — Float multiplication - &CPU::FDIV, // 0x055 — Float division - &CPU::FMOD, // 0x056 — Float modulus - &CPU::FDMOD, // 0x057 — Float division and modulus - &CPU::FEPS, // 0x058 — Sets the float epsilon value, for comparison - &CPU::FEEP, // 0x059 — Float Enable/Disable Epsilon - &CPU::FEQ, // 0x05A — Float Equal - &CPU::FNE, // 0x05B — Float Not Equal - &CPU::FGT, // 0x05C — Float Greater Than - &CPU::FGE, // 0x05D — Float Greater or Equal Than - &CPU::FLT, // 0x05E — Float Lower Than - &CPU::FLE, // 0x05F — Float Lower or Equal Than - &CPU::F2D, // 0x060 — F32 (Float) to F64 (Double) - &CPU::D2F, // 0x061 — F64 (Double) to F32 (Float) - &CPU::I2F, // 0x062 — I32 (Integer) to F32 (Float) - &CPU::I2D, // 0x063 — I32 (Integer) to F64 (Double) - &CPU::L2F, // 0x064 — I64 (Long) to F32 (Float) - &CPU::L2D, // 0x065 — I64 (Long) to F64 (Double) - &CPU::F2I, // 0x066 — F32 (Float) to I32 (Integer) - &CPU::F2L, // 0x067 — F32 (Float) to I64 (Long) - &CPU::D2I, // 0x068 — F64 (Double) to I32 (Integer) - &CPU::D2L, // 0x069 — F64 (Double) to I64 (Long) - nullptr, // 0x06A (reserved) - nullptr, // 0x06B (reserved) - &CPU::SIN, // 0x06C — Sine Function - &CPU::COS, // 0x06D — Cosine Function - &CPU::TAN, // 0x06E — Tangent Function - &CPU::ASIN, // 0x06F — Arc Sine Function - &CPU::ACOS, // 0x070 — Arc Cosine Function - &CPU::ATAN, // 0x071 — Arc Tangent Function - &CPU::ATAN2, // 0x072 — Arc Tangent Function with 2 Arguments - nullptr, // 0x073 (reserved) - &CPU::EXP, // 0x074 — Exponential Function - &CPU::LOG, // 0x075 — Natural Logarithm - &CPU::LOGAB, // 0x076 — Logarithm A of B - &CPU::POW, // 0x077 — Power Function - &CPU::SQRT, // 0x078 — Square Root - &CPU::ROOT, // 0x079 — General Root - nullptr, // 0x07A (reserved) - nullptr, // 0x07B (reserved) - &CPU::ADC, // 0x07C — Add with Carry - &CPU::SWC, // 0x07D — Subtract with Carry (Borrow) - &CPU::MWO, // 0x07E — Multiply with Overflow - &CPU::UMO, // 0x07F — Unsigned Multiply with Overflow - &CPU::MADD, // 0x080 — Matrix Addition - &CPU::MSUB, // 0x081 — Matrix Subtraction - &CPU::MMUL, // 0x082 — Matrix Multiply - &CPU::MINV, // 0x083 — Matrix Inverse - &CPU::MTRA, // 0x084 — Matrix Transpose - &CPU::MDET, // 0x085 — Matrix Determinant - &CPU::QMKA, // 0x086 — Quaternion Make from Angles - &CPU::QMUL, // 0x087 — Quaternion Multiply + &CPU::NOP, // 0x000 — No Operation + &CPU::SPDR, // 0x001 — Will place the Spider version of the interpreter in RA + &CPU::MMODE, // 0x002 — Set Memory Mode + &CPU::INT, // 0x003 — Interrupt + &CPU::LRV, // 0x004 — Load Interrupt Vector Register + &CPU::FSR, // 0x005 — Fetch System Register + &CPU::FIR, // 0x006 — Fetch Instruction Register + &CPU::FZR, // 0x007 — Fetch Stack Base Register + &CPU::LSR, // 0x008 — Load System Register + &CPU::FVR, // 0x009 — Fetch Interrupt Vector Register + &CPU::MOV, // 0x00A — Moves values + &CPU::MOR, // 0x00B — Moves registers + &CPU::AMOV, // 0x00C — Array Move, uses X and Y as ptrs, A as amount + &CPU::SWP, // 0x00D — Swap registers + &CPU::AHM, // 0x00E — Ask Host for Memory + nullptr, // 0x00F (reserved) + &CPU::COM, // 0x010 — One's complement + &CPU::NEG, // 0x011 — Two's complement + &CPU::EXS, // 0x012 — Extend Sign + &CPU::INC, // 0x013 — Increment + &CPU::DEC, // 0x014 — Decrement + &CPU::ADD, // 0x015 — Addition + &CPU::SUB, // 0x016 — Subtraction + &CPU::MUL, // 0x017 — Multiplication + &CPU::UMUL, // 0x018 — Unsigned Multiplication + &CPU::DIV, // 0x019 — Division + &CPU::UDIV, // 0x01A — Unsigned Division + &CPU::MOD, // 0x01B — Modulus + &CPU::UMOD, // 0x01C — Unsigned Modulus + &CPU::DMOD, // 0x01D — Division and Modulus + &CPU::UDMD, // 0x01E — Unsigned Division and Modulus + &CPU::FBT, // 0x01F — Test and update Flag Register (Integer) Bits + &CPU::STB, // 0x020 — Set Bit + &CPU::CRB, // 0x021 — Clear Bit + &CPU::TSB, // 0x022 — Test Bit + &CPU::BOOL, // 0x023 — Sets the booleaness of a value + &CPU::NOT, // 0x024 — Sets the inverse booleaness of a value (! BOOL) + &CPU::AND, // 0x025 — Boolean AND operation + &CPU::OR, // 0x026 — Boolean OR operation + &CPU::XOR, // 0x027 — Boolean XOR operation + &CPU::SHL, // 0x028 — Arithmetic Shift Left + &CPU::SHR, // 0x029 — Arithmetic Shift Right + &CPU::SSR, // 0x02A — Signed Shift Right + &CPU::ROL, // 0x02B — Rotate Left + &CPU::ROR, // 0x02C — Rotate Right + &CPU::CNT, // 0x02D — Counts bits + &CPU::EQ, // 0x02E — Equal + &CPU::NE, // 0x02F — Not Equal + &CPU::GT, // 0x030 — Greater Than + &CPU::GE, // 0x031 — Greater or Equal Than + &CPU::LT, // 0x032 — Lower Than + &CPU::LE, // 0x033 — Lower or Equal Than + &CPU::GTU, // 0x034 — Greater Than, Unsigned + &CPU::GEU, // 0x035 — Greater or Equal Than, Unsigned + &CPU::LTU, // 0x036 — Lower Than, Unsigned + &CPU::LEU, // 0x037 — Lower or Equal Than, Unsigned + &CPU::JMP, // 0x038 — Jump to absolute position + &CPU::JEQ, // 0x039 — Jumps to position if EQ flag is set + &CPU::JNE, // 0x03A — Jumps to position if EQ flag is cleared + &CPU::JIF, // 0x03B — Jumps if value provided is booleanly true + &CPU::JMR, // 0x03C — Jump Relative + &CPU::JER, // 0x03D — Jumps to relative position if EQ flag is set + &CPU::JNR, // 0x03E — Jumps to relative position if EQ flag is cleared + &CPU::JIR, // 0x03F — Jumps to relative position if value provided is booleanly true + &CPU::SFB, // 0x040 — Store (User) Flag Bit + &CPU::LFB, // 0x041 — Load (User) Flag Bit + &CPU::JUF, // 0x042 — Jump to absolute position, if user flag is true + &CPU::JUR, // 0x043 — Jump to relative position, if user flag is true + &CPU::PUSH, // 0x044 — Push to stack + &CPU::POP, // 0x045 — Pop from stack + &CPU::ALLOC, // 0x046 — Allocate to heap + &CPU::HFREE, // 0x047 — Delete from heap + nullptr, // 0x048 (reserved) + nullptr, // 0x049 (reserved) + &CPU::CALL, // 0x04A — Call function at instruction index + &CPU::RET, // 0x04B — Return from a function + &CPU::EDI, // 0x04C — Enable/Disable External Interrupts + &CPU::SHSS, // 0x04D — Set Hotswap Signal Bit + nullptr, // 0x04E (reserved) + nullptr, // 0x04F (reserved) + &CPU::FLI, // 0x050 — Float Load Immediate + &CPU::FNEG, // 0x051 — Float negate + &CPU::FADD, // 0x052 — Float add + &CPU::FSUB, // 0x053 — Float subtract + &CPU::FMUL, // 0x054 — Float multiplication + &CPU::FDIV, // 0x055 — Float division + &CPU::FMOD, // 0x056 — Float modulus + &CPU::FDMOD, // 0x057 — Float division and modulus + &CPU::FEPS, // 0x058 — Sets the float epsilon value, for comparison + &CPU::FEEP, // 0x059 — Float Enable/Disable Epsilon + &CPU::FEQ, // 0x05A — Float Equal + &CPU::FNE, // 0x05B — Float Not Equal + &CPU::FGT, // 0x05C — Float Greater Than + &CPU::FGE, // 0x05D — Float Greater or Equal Than + &CPU::FLT, // 0x05E — Float Lower Than + &CPU::FLE, // 0x05F — Float Lower or Equal Than + &CPU::F2D, // 0x060 — F32 (Float) to F64 (Double) + &CPU::D2F, // 0x061 — F64 (Double) to F32 (Float) + &CPU::I2F, // 0x062 — I32 (Integer) to F32 (Float) + &CPU::I2D, // 0x063 — I32 (Integer) to F64 (Double) + &CPU::L2F, // 0x064 — I64 (Long) to F32 (Float) + &CPU::L2D, // 0x065 — I64 (Long) to F64 (Double) + &CPU::F2I, // 0x066 — F32 (Float) to I32 (Integer) + &CPU::F2L, // 0x067 — F32 (Float) to I64 (Long) + &CPU::D2I, // 0x068 — F64 (Double) to I32 (Integer) + &CPU::D2L, // 0x069 — F64 (Double) to I64 (Long) + nullptr, // 0x06A (reserved) + nullptr, // 0x06B (reserved) + &CPU::SIN, // 0x06C — Sine Function + &CPU::COS, // 0x06D — Cosine Function + &CPU::TAN, // 0x06E — Tangent Function + &CPU::ASIN, // 0x06F — Arc Sine Function + &CPU::ACOS, // 0x070 — Arc Cosine Function + &CPU::ATAN, // 0x071 — Arc Tangent Function + &CPU::ATAN2, // 0x072 — Arc Tangent Function with 2 Arguments + nullptr, // 0x073 (reserved) + &CPU::EXP, // 0x074 — Exponential Function + &CPU::LOG, // 0x075 — Natural Logarithm + &CPU::LOGAB, // 0x076 — Logarithm A of B + &CPU::POW, // 0x077 — Power Function + &CPU::SQRT, // 0x078 — Square Root + &CPU::ROOT, // 0x079 — General Root + nullptr, // 0x07A (reserved) + nullptr, // 0x07B (reserved) + &CPU::ADC, // 0x07C — Add with Carry + &CPU::SWC, // 0x07D — Subtract with Carry (Borrow) + &CPU::MWO, // 0x07E — Multiply with Overflow + &CPU::UMO, // 0x07F — Unsigned Multiply with Overflow + &CPU::MADD, // 0x080 — Matrix Addition + &CPU::MSUB, // 0x081 — Matrix Subtraction + &CPU::MMUL, // 0x082 — Matrix Multiply + &CPU::MINV, // 0x083 — Matrix Inverse + &CPU::MTRA, // 0x084 — Matrix Transpose + &CPU::MDET, // 0x085 — Matrix Determinant + &CPU::QMKA, // 0x086 — Quaternion Make from Angles + &CPU::QMUL, // 0x087 — Quaternion Multiply nullptr, // 0x088 nullptr, // 0x089 - &CPU::XADD, // 0x08A — SIMD Addition - &CPU::XSUB, // 0x08B — SIMD Subtract - &CPU::XAMA, // 0x08C — SIMD Alternate Multiply-Add - &CPU::XMUL, // 0x08D — SIMD Multiply - &CPU::XDIV, // 0x08E — SIMD Divide + &CPU::XADD, // 0x08A — SIMD Addition + &CPU::XSUB, // 0x08B — SIMD Subtract + &CPU::XAMA, // 0x08C — SIMD Alternate Multiply-Add + &CPU::XMUL, // 0x08D — SIMD Multiply + &CPU::XDIV, // 0x08E — SIMD Divide nullptr, // 0x08F nullptr, // 0x090 nullptr, // 0x091 @@ -275,13 +275,13 @@ CPU::Fn CPU::instrMap[] = { nullptr, // 0x0ED nullptr, // 0x0EE nullptr, // 0x0EF - &CPU::UPY, // 0x0F0 — Will place "YUPI" in memory - &CPU::LLGS, // 0x0F1 — Spider ASCII art (LLGS easter egg) + &CPU::UPY, // 0x0F0 — Will place "YUPI" in memory + nullptr, // 0x0F1 nullptr, // 0x0F2 nullptr, // 0x0F3 nullptr, // 0x0F4 nullptr, // 0x0F5 - &CPU::DGANT, // 0x0F6 + nullptr, // 0x0F6 nullptr, // 0x0F7 nullptr, // 0x0F8 nullptr, // 0x0F9 @@ -622,12 +622,16 @@ void CPU::executeSwLk() { case 0x02D: CNT(); break; // ── Boolean ───────────────────────────────────── - case 0x030: EQ(); break; - case 0x031: NE(); break; - case 0x032: GT(); break; - case 0x033: GE(); break; - case 0x034: LT(); break; - case 0x035: LE(); break; + case 0x02E: EQ(); break; + case 0x02F: NE(); break; + case 0x030: GT(); break; + case 0x031: GE(); break; + case 0x032: LT(); break; + case 0x033: LE(); break; + case 0x034: GTU(); break; + case 0x035: GEU(); break; + case 0x036: LTU(); break; + case 0x037: LEU(); break; // ── Branch ────────────────────────────────────── case 0x038: JMP(); break; @@ -737,8 +741,6 @@ void CPU::executeSwLk() { // ── Easter Eggs ───────────────────────────────── case 0x0F0: UPY(); break; - case 0x0F1: LLGS(); break; - default: break; diff --git a/src/spider/runtime/instr/Instr_000-01F.cpp b/src/spider/runtime/instr/Instr_000-01F.cpp index d946869..3b39bab 100644 --- a/src/spider/runtime/instr/Instr_000-01F.cpp +++ b/src/spider/runtime/instr/Instr_000-01F.cpp @@ -4,15 +4,16 @@ */ #include +#include namespace spider { void CPU::NOP() { - // TODO: Implement NOP + // DONE ! // } void CPU::SPDR() { - // TODO: Implement SPDR + RA._u64 = spider::RUNTIME_VERSION_NO; } void CPU::MMODE() { @@ -21,10 +22,13 @@ namespace spider { void CPU::INT() { // TODO: Implement INT + // We need to implement an interrupt + // table and interrupt system! } void CPU::LRV() { - // TODO: Implement LRV + fetchOperReg(); + RV = _dst->_u64; } void CPU::FSR() { @@ -32,11 +36,13 @@ namespace spider { } void CPU::FIR() { - // TODO: Implement FIR + fetchOperReg(); + _dst->_u64 = RI; } void CPU::FZR() { - // TODO: Implement FZR + fetchOperReg(); + _dst->_u64 = RZ; } void CPU::LSR() { @@ -44,23 +50,63 @@ namespace spider { } void CPU::FVR() { - // TODO: Implement FVR + fetchOperReg(); + _dst->_u64 = RV; } void CPU::MOV() { - // TODO: Implement MOV + fetchOperSrc(); + fetchOperDst(); + switch (_size) { + case 0b00: //byte + _dst->_u8 = _src->_u8; + break; + case 0b01: //short + _dst->_u16 = _src->_u16; + break; + case 0b10: //int + _dst->_u32 = _src->_u32; + break; + case 0b11: //long + _dst->_u64 = _src->_u64; + break; + } } void CPU::MOR() { - // TODO: Implement MOR + fetchOperRegReg(); + *_dst = *_src; } void CPU::AMOV() { - // TODO: Implement AMOV + // AMOV potential is capped at 256 bytes! + u64 amt = RA._u16; + u64 from = RX._u64; + u64 to = RY._u64; + if(amt > 256) return; + + // are RX and RY in valid regions of memory? + u64 ramsize = _ram->size(); + if (from >= ramsize || amt > (ramsize - from)) return; + if (to >= ramsize || amt > (ramsize - to)) return; + + // Use std::copy_backward if destination overlaps ahead of source + auto ram_begin = _ram->begin(); + if (to > from && to < from + amt) { + // Overlap case where destination is ahead of source: copy from back to front + std::copy_backward(ram_begin + from, ram_begin + from + amt, ram_begin + to + amt); + } else { + // No overlap, or destination is behind source: copy front to back + std::copy(ram_begin + from, ram_begin + from + amt, ram_begin + to); + } } void CPU::SWP() { - // TODO: Implement SWP + // get registers in _dst and _src + fetchOperRegReg(); + ALU0 = *_dst; + *_dst = *_src; + *_src = ALU0; } void CPU::AHM() { @@ -69,321 +115,307 @@ namespace spider { void CPU::COM() { fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_u8 = ~_dst->_u8; - break; - case 0b01: //short - _dst->_u16 = ~_dst->_u16; - break; - case 0b10: //int - _dst->_u32 = ~_dst->_u32; - break; - case 0b11: //long - _dst->_u64 = ~_dst->_u64; - break; + switch (_size) { + case 0b00: //byte + _dst->_u8 = ~_dst->_u8; + break; + case 0b01: //short + _dst->_u16 = ~_dst->_u16; + break; + case 0b10: //int + _dst->_u32 = ~_dst->_u32; + break; + case 0b11: //long + _dst->_u64 = ~_dst->_u64; + break; } } void CPU::NEG() { - // TODO: Implement NEG fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_u8 = 1 + ~_dst->_u8; - break; - case 0b01: //short - _dst->_u16 = 1+ ~_dst->_u16; - break; - case 0b10: //int - _dst->_u32 = 1 + ~_dst->_u32; - break; - case 0b11: //long - _dst->_u64 = 1 + ~_dst->_u64; - break; + switch (_size) { + case 0b00: //byte + _dst->_u8 = 1 + ~_dst->_u8; + break; + case 0b01: //short + _dst->_u16 = 1 + ~_dst->_u16; + break; + case 0b10: //int + _dst->_u32 = 1 + ~_dst->_u32; + break; + case 0b11: //long + _dst->_u64 = 1 + ~_dst->_u64; + break; } } void CPU::EXS() { fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_i16 = static_cast(_dst->_i8); - break; - case 0b01: //short - _dst->_i32 = static_cast(_dst->_i16); - break; - case 0b10: //int - _dst->_i64 = static_cast(_dst->_i32); - break; - case 0b11: //long - _dst->_i64 = _dst->_i64; - break; + switch (_size) { + case 0b00: //byte + _dst->_i16 = static_cast(_dst->_i8); + break; + case 0b01: //short + _dst->_i32 = static_cast(_dst->_i16); + break; + case 0b10: //int + _dst->_i64 = static_cast(_dst->_i32); + break; + case 0b11: //long + _dst->_i64 = _dst->_i64; + break; } } void CPU::INC() { - // TODO: Implement INC fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_u8 += 1; - break; - case 0b01: //short - _dst->_u16 += 1; - break; - case 0b10: //int - _dst->_u32 += 1; - break; - case 0b11: //long - _dst->_u64 += 1; - break; + switch (_size) { + case 0b00: //byte + _dst->_u8 += 1; + break; + case 0b01: //short + _dst->_u16 += 1; + break; + case 0b10: //int + _dst->_u32 += 1; + break; + case 0b11: //long + _dst->_u64 += 1; + break; } } void CPU::DEC() { - // TODO: Implement DEC fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_u8 -= 1; - break; - case 0b01: //short - _dst->_u16 -= 1; - break; - case 0b10: //int - _dst->_u32 -= 1; - break; - case 0b11: //long - _dst->_u64 -= 1; - break; + switch (_size) { + case 0b00: //byte + _dst->_u8 -= 1; + break; + case 0b01: //short + _dst->_u16 -= 1; + break; + case 0b10: //int + _dst->_u32 -= 1; + break; + case 0b11: //long + _dst->_u64 -= 1; + break; } } void CPU::ADD() { - // TODO: Implement ADD fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_u8 += _src->_u8; - break; - case 0b01: //short - _dst->_u16 += _src->_u16; - break; - case 0b10: //int - _dst->_u32 += _src->_u32; - break; - case 0b11: //long - _dst->_u64 += _src->_u64; - break; + switch (_size) { + case 0b00: //byte + _dst->_u8 += _src->_u8; + break; + case 0b01: //short + _dst->_u16 += _src->_u16; + break; + case 0b10: //int + _dst->_u32 += _src->_u32; + break; + case 0b11: //long + _dst->_u64 += _src->_u64; + break; } } void CPU::SUB() { - // TODO: Implement SUB fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_u8 -= _src->_u8; - break; - case 0b01: //short - _dst->_u16 -= _src->_u16; - break; - case 0b10: //int - _dst->_u32 -= _src->_u32; - break; - case 0b11: //long - _dst->_u64 -= _src->_u64; - break; + switch (_size) { + case 0b00: //byte + _dst->_u8 -= _src->_u8; + break; + case 0b01: //short + _dst->_u16 -= _src->_u16; + break; + case 0b10: //int + _dst->_u32 -= _src->_u32; + break; + case 0b11: //long + _dst->_u64 -= _src->_u64; + break; } } void CPU::MUL() { - // TODO: Implement MUL fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_i8 = _src->_i8 * _dst->_i8; - break; - case 0b01: //short - _dst->_i16 = _src->_i16 * _dst->_i16; - break; - case 0b10: //int - _dst->_i32 = _src->_i32 * _dst->_i32; - break; - case 0b11: //long - _dst->_i64 = _src->_i64 * _dst->_i64; - break; + switch (_size) { + case 0b00: //byte + _dst->_i8 = _src->_i8 * _dst->_i8; + break; + case 0b01: //short + _dst->_i16 = _src->_i16 * _dst->_i16; + break; + case 0b10: //int + _dst->_i32 = _src->_i32 * _dst->_i32; + break; + case 0b11: //long + _dst->_i64 = _src->_i64 * _dst->_i64; + break; } } void CPU::UMUL() { - // TODO: Implement UMUL fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_u8 = _src->_u8 * _dst->_u8; - break; - case 0b01: //short - _dst->_u16 = _src->_u16 * _dst->_u16; - break; - case 0b10: //int - _dst->_u32 = _src->_u32 * _dst->_u32; - break; - case 0b11: //long - _dst->_u64 = _src->_u64 * _dst->_u64; - break; + switch (_size) { + case 0b00: //byte + _dst->_u8 = _src->_u8 * _dst->_u8; + break; + case 0b01: //short + _dst->_u16 = _src->_u16 * _dst->_u16; + break; + case 0b10: //int + _dst->_u32 = _src->_u32 * _dst->_u32; + break; + case 0b11: //long + _dst->_u64 = _src->_u64 * _dst->_u64; + break; } } void CPU::DIV() { - // TODO: Implement DIV fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_i8 = _dst->_i8 / _src->_i8; - break; - case 0b01: //short - _dst->_i16 = _dst->_i16 / _src->_i16; - break; - case 0b10: //int - _dst->_i32 = _dst->_i32 / _src->_i32; - break; - case 0b11: //long - _dst->_i64 = _dst->_i64 / _src->_i64; - break; + switch (_size) { + case 0b00: //byte + _dst->_i8 = _dst->_i8 / _src->_i8; + break; + case 0b01: //short + _dst->_i16 = _dst->_i16 / _src->_i16; + break; + case 0b10: //int + _dst->_i32 = _dst->_i32 / _src->_i32; + break; + case 0b11: //long + _dst->_i64 = _dst->_i64 / _src->_i64; + break; } } void CPU::UDIV() { - // TODO: Implement UDIV fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_u8 = _dst->_u8 / _src->_u8; - break; - case 0b01: //short - _dst->_u16 = _dst->_u16 / _src->_u16; - break; - case 0b10: //int - _dst->_u32 = _dst->_u32 / _src->_u32; - break; - case 0b11: //long - _dst->_u64 = _dst->_u64 / _src->_u64; - break; + switch (_size) { + case 0b00: //byte + _dst->_u8 = _dst->_u8 / _src->_u8; + break; + case 0b01: //short + _dst->_u16 = _dst->_u16 / _src->_u16; + break; + case 0b10: //int + _dst->_u32 = _dst->_u32 / _src->_u32; + break; + case 0b11: //long + _dst->_u64 = _dst->_u64 / _src->_u64; + break; } } void CPU::MOD() { - // TODO: Implement MOD fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_i8 = _dst->_i8 % _src->_i8; - break; - case 0b01: //short - _dst->_i16 = _dst->_i16 % _src->_i16; - break; - case 0b10: //int - _dst->_i32 = _dst->_i32 % _src->_i32; - break; - case 0b11: //long - _dst->_i64 = _dst->_i64 % _src->_i64; - break; + switch (_size) { + case 0b00: //byte + _dst->_i8 = _dst->_i8 % _src->_i8; + break; + case 0b01: //short + _dst->_i16 = _dst->_i16 % _src->_i16; + break; + case 0b10: //int + _dst->_i32 = _dst->_i32 % _src->_i32; + break; + case 0b11: //long + _dst->_i64 = _dst->_i64 % _src->_i64; + break; } } void CPU::UMOD() { - // TODO: Implement UMOD fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - _dst->_u8 = _dst->_u8 % _src->_u8; - break; - case 0b01: //short - _dst->_u16 = _dst->_u16 % _src->_u16; - break; - case 0b10: //int - _dst->_u32 = _dst->_u32 % _src->_u32; - break; - case 0b11: //long - _dst->_u64 = _dst->_u64 % _src->_u64; - break; + switch (_size) { + case 0b00: //byte + _dst->_u8 = _dst->_u8 % _src->_u8; + break; + case 0b01: //short + _dst->_u16 = _dst->_u16 % _src->_u16; + break; + case 0b10: //int + _dst->_u32 = _dst->_u32 % _src->_u32; + break; + case 0b11: //long + _dst->_u64 = _dst->_u64 % _src->_u64; + break; } } void CPU::DMOD() { - // TODO: Implement DMOD fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - RX._i8 = _dst->_i8 / _src->_i8; - RY._i8 = _dst->_i8 % _src->_i8; - break; - case 0b01: //short - RX._i16 = _dst->_i16 / _src->_i16; - RY._i16 = _dst->_i16 % _src->_i16; - break; - case 0b10: //int - RX._i32 = _dst->_i32 / _src->_i32; - RY._i32 = _dst->_i32 % _src->_i32; - break; - case 0b11: //long - RX._i64 = _dst->_i64 / _src->_i64; - RY._i64 = _dst->_i64 % _src->_i64; - break; + switch (_size) { + case 0b00: //byte + RX._i8 = _dst->_i8 / _src->_i8; + RY._i8 = _dst->_i8 % _src->_i8; + break; + case 0b01: //short + RX._i16 = _dst->_i16 / _src->_i16; + RY._i16 = _dst->_i16 % _src->_i16; + break; + case 0b10: //int + RX._i32 = _dst->_i32 / _src->_i32; + RY._i32 = _dst->_i32 % _src->_i32; + break; + case 0b11: //long + RX._i64 = _dst->_i64 / _src->_i64; + RY._i64 = _dst->_i64 % _src->_i64; + break; } } void CPU::UDMD() { - // TODO: Implement UDMD fetchOperSrc(); fetchOperDst(); - switch(_size){ - case 0b00: //byte - RX._u8 = _dst->_u8 / _src->_u8; - RY._u8 = _dst->_u8 % _src->_u8; - break; - case 0b01: //short - RX._u16 = _dst->_u16 / _src->_u16; - RY._u16 = _dst->_u16 % _src->_u16; - break; - case 0b10: //int - RX._u32 = _dst->_u32 / _src->_u32; - RY._u32 = _dst->_u32 % _src->_u32; - break; - case 0b11: //long - RX._u64 = _dst->_u64 / _src->_u64; - RY._u64 = _dst->_u64 % _src->_u64; - break; + switch (_size) { + case 0b00: //byte + RX._u8 = _dst->_u8 / _src->_u8; + RY._u8 = _dst->_u8 % _src->_u8; + break; + case 0b01: //short + RX._u16 = _dst->_u16 / _src->_u16; + RY._u16 = _dst->_u16 % _src->_u16; + break; + case 0b10: //int + RX._u32 = _dst->_u32 / _src->_u32; + RY._u32 = _dst->_u32 % _src->_u32; + break; + case 0b11: //long + RX._u64 = _dst->_u64 / _src->_u64; + RY._u64 = _dst->_u64 % _src->_u64; + break; } } void CPU::FBT() { - // TODO: Implement FBT fetchOperDst(); - switch(_size){ - case 0b00: //byte - RF = u8((RF & ~(0x3 << 9))) | ((_dst->_u8 >> 9) & 0x3) << 9; - break; - case 0b01: //short - RF = u16((RF & ~(0x3 << 9))) | ((_dst->_u16 >> 9) & 0x3) << 9; - break; - case 0b10: //int - RF = u32((RF & ~(0x3 << 9))) | ((_dst->_u32 >> 9) & 0x3) << 9; - break; - case 0b11: //long - RF = u64((RF & ~(0x3 << 9))) | ((_dst->_u64 >> 9) & 0x3) << 9; - break; + switch (_size) { + case 0b00: //byte + RF = u8((RF & ~(0x3 << 9))) | ((_dst->_u8 >> 9) & 0x3) << 9; + break; + case 0b01: //short + RF = u16((RF & ~(0x3 << 9))) | ((_dst->_u16 >> 9) & 0x3) << 9; + break; + case 0b10: //int + RF = u32((RF & ~(0x3 << 9))) | ((_dst->_u32 >> 9) & 0x3) << 9; + break; + case 0b11: //long + RF = u64((RF & ~(0x3 << 9))) | ((_dst->_u64 >> 9) & 0x3) << 9; + break; } } diff --git a/src/spider/runtime/instr/Instr_LLGS.cpp b/src/spider/runtime/instr/Instr_LLGS.cpp deleted file mode 100644 index 8df5e36..0000000 --- a/src/spider/runtime/instr/Instr_LLGS.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @brief LLGS — Easter egg by Arturo Balam (Data - 7A) - * - * Opcode: 0x0F1 - * - * Writes a Spider ASCII art into RAM starting at address 0x00, - * and loads the author signature into RA as a packed ASCII string. - * This version matches the custom mechanical spider design - * and is formatted to fit an 8-byte RAM viewer width. - * - * RAM layout after LLGS executes (8 characters per row, 4 rows total): - * 0x00: "// _ \\" (Row 1) - * 0x08: "\\( )// " (Row 2) - * 0x10: " //()\\ " (Row 3) - * 0x18: " \\ // " (Row 4) - * - * RA after execution: 0x4C4C475300000000ULL ("LLGS" in ASCII, zero-padded) - * (L=0x4C, L=0x4C, G=0x47, S=0x53) - */ - -#include -#include - -namespace spider { - - void CPU::LLGS() { - - // -- Write Spider ASCII art into RAM --------------------------------- - // Padded with exact spaces to ensure it never wraps in an 8-byte viewer - - // Row 0: "// _ \\ " - _ram->at(0x00) = '/'; _ram->at(0x01) = '/'; - _ram->at(0x02) = ' '; _ram->at(0x03) = '_'; - _ram->at(0x04) = ' '; _ram->at(0x05) = '\\'; - _ram->at(0x06) = '\\'; _ram->at(0x07) = ' '; - - // Row 1: "\\( )// " - _ram->at(0x08) = '\\'; _ram->at(0x09) = '\\'; - _ram->at(0x0A) = '('; _ram->at(0x0B) = ' '; - _ram->at(0x0C) = ')'; _ram->at(0x0D) = '/'; - _ram->at(0x0E) = '/'; _ram->at(0x0F) = ' '; - - // Row 2: " //()\\ " - _ram->at(0x10) = ' '; _ram->at(0x11) = '/'; - _ram->at(0x12) = '/'; _ram->at(0x13) = '('; - _ram->at(0x14) = ')'; _ram->at(0x15) = '\\'; - _ram->at(0x16) = '\\'; _ram->at(0x17) = ' '; - - // Row 3: " \\ // " - _ram->at(0x18) = ' '; _ram->at(0x19) = '\\'; - _ram->at(0x1A) = '\\'; _ram->at(0x1B) = ' '; - _ram->at(0x1C) = ' '; _ram->at(0x1D) = '/'; - _ram->at(0x1E) = '/'; _ram->at(0x1F) = ' '; - - // -- Load mnemonic into RA ------------------------ - // "LLGS" packed as ASCII bytes into RA - RA._u64 = 0x4C4C475300000000ULL; - - } - -} // namespace spider \ No newline at end of file diff --git a/src/spider/test_instrucciones.cpp b/src/spider/test_instrucciones.cpp deleted file mode 100644 index dab20b6..0000000 --- a/src/spider/test_instrucciones.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif -#ifndef M_E -#define M_E 2.71828182845904523536 -#endif - -#include -#include -#include - -using namespace spider; - -void check(const char* name, double result, double expected, double tolerance = 1e-9) { - bool ok = std::abs(result - expected) <= tolerance; - std::cout << (ok ? "[PASS] " : "[FAIL] ") << name - << " = " << result - << " (expected " << expected << ")\n"; -} - -int main() { - std::cout << "=== Spider VM Instruction Test: 0x068-0x079 ===\n\n"; - - CPU cpu; - cpu._post = &CPU::imp; - - std::cout << "-- Cast Instructions --\n"; - - cpu.RA._f64 = 3.9; - cpu._dst = &cpu.RA; - cpu.D2I(); - check("D2I (3.9 -> 3)", cpu.RA._u32, 3.0); - - cpu.RA._f64 = 1e12; - cpu._dst = &cpu.RA; - cpu.D2L(); - check("D2L (1e12)", (double)cpu.RA._u64, 1e12); - - std::cout << "\n-- Trigonometric Instructions --\n"; - - cpu.RA._f64 = M_PI / 2.0; - cpu._dst = &cpu.RA; - cpu.SIN(); - check("SIN(pi/2)", cpu.RA._f64, 1.0); - - cpu.RA._f64 = 0.0; - cpu._dst = &cpu.RA; - cpu.COS(); - check("COS(0)", cpu.RA._f64, 1.0); - - cpu.RA._f64 = M_PI / 4.0; - cpu._dst = &cpu.RA; - cpu.TAN(); - check("TAN(pi/4)", cpu.RA._f64, 1.0); - - cpu.RA._f64 = 1.0; - cpu._dst = &cpu.RA; - cpu.ASIN(); - check("ASIN(1.0)", cpu.RA._f64, M_PI / 2.0); - - cpu.RA._f64 = 1.0; - cpu._dst = &cpu.RA; - cpu.ACOS(); - check("ACOS(1.0)", cpu.RA._f64, 0.0); - - cpu.RA._f64 = 1.0; - cpu._dst = &cpu.RA; - cpu.ATAN(); - check("ATAN(1.0)", cpu.RA._f64, M_PI / 4.0); - - cpu.RA._f64 = 1.0; - cpu.RB._f64 = 1.0; - cpu._dst = &cpu.RA; - cpu._src = &cpu.RB; - cpu.ATAN2(); - check("ATAN2(1,1)", cpu.RA._f64, M_PI / 4.0); - - std::cout << "\n-- Exponential Instructions --\n"; - - cpu.RA._f64 = 1.0; - cpu._dst = &cpu.RA; - cpu.EXP(); - check("EXP(1)", cpu.RA._f64, M_E); - - cpu.RA._f64 = M_E; - cpu._dst = &cpu.RA; - cpu.LOG(); - check("LOG(e)", cpu.RA._f64, 1.0); - - cpu.RA._f64 = 100.0; - cpu.RB._f64 = 10.0; - cpu._dst = &cpu.RA; - cpu._src = &cpu.RB; - cpu.LOGAB(); - check("LOGAB(100,10)", cpu.RA._f64, 2.0); - - cpu.RA._f64 = 2.0; - cpu.RB._f64 = 10.0; - cpu._dst = &cpu.RA; - cpu._src = &cpu.RB; - cpu.POW(); - check("POW(2,10)", cpu.RA._f64, 1024.0); - - cpu.RA._f64 = 9.0; - cpu._dst = &cpu.RA; - cpu.SQRT(); - check("SQRT(9)", cpu.RA._f64, 3.0); - - cpu.RA._f64 = 27.0; - cpu.RB._f64 = 3.0; - cpu._dst = &cpu.RA; - cpu._src = &cpu.RB; - cpu.ROOT(); - check("ROOT(27,3)", cpu.RA._f64, 3.0); - - std::cout << "\n=== Tests complete ===\n"; - return 0; -} \ No newline at end of file