removed unnecessary things, updated and audited the code

This commit is contained in:
2026-06-13 11:31:07 -06:00
parent 29797fb707
commit a36705a931
13 changed files with 529 additions and 1718 deletions
+8
View File
@@ -58,6 +58,10 @@ constexpr u8 ADDR_MODE_MASKS[][2] = {
{ 0x1E, 0xFF }, // GE { 0x1E, 0xFF }, // GE
{ 0x1E, 0xFF }, // LT { 0x1E, 0xFF }, // LT
{ 0x1E, 0xFF }, // LE { 0x1E, 0xFF }, // LE
{ 0x1E, 0xFF }, // GTU
{ 0x1E, 0xFF }, // GEU
{ 0x1E, 0xFF }, // LTU
{ 0x1E, 0xFF }, // LEU
{ 0xFF, 0x00 }, // JMP { 0xFF, 0x00 }, // JMP
{ 0xFF, 0x00 }, // JEQ { 0xFF, 0x00 }, // JEQ
{ 0xFF, 0x00 }, // JNE { 0xFF, 0x00 }, // JNE
@@ -190,6 +194,10 @@ constexpr u8 TYPE_SIZE_MASKS[] = {
0x0F, // GE 0x0F, // GE
0x0F, // LT 0x0F, // LT
0x0F, // LE 0x0F, // LE
0x0F, // GTU
0x0F, // GEU
0x0F, // LTU
0x0F, // LEU
0x0F, // JMP 0x0F, // JMP
0x0F, // JEQ 0x0F, // JEQ
0x0F, // JNE 0x0F, // JNE
-658
View File
@@ -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
}
Binary file not shown.
+16 -16
View File
@@ -144,7 +144,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 3,
"id": "58645013", "id": "58645013",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -152,16 +152,16 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Real instructions : 128\n", "Real instructions : 132\n",
"Reserved slots : 14\n", "Reserved slots : 10\n",
"Duplicate check : PASSED\n", "Duplicate check : PASSED\n",
"\n", "\n",
"Groups found:\n", "Groups found:\n",
"group\n", "group\n",
"Integer 19\n", "Integer 19\n",
"Boolean 16\n",
"System 15\n", "System 15\n",
"Bit Wise 14\n", "Bit Wise 14\n",
"Boolean 12\n",
"Branch 12\n", "Branch 12\n",
"Floating Point 10\n", "Floating Point 10\n",
"Casts 10\n", "Casts 10\n",
@@ -283,7 +283,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 4,
"id": "452bc76c", "id": "452bc76c",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -292,7 +292,7 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Masks written to: .//autogen/InstructionMasks.hpp\n", "Masks written to: .//autogen/InstructionMasks.hpp\n",
"Lines generated : 272\n" "Lines generated : 280\n"
] ]
} }
], ],
@@ -357,7 +357,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 5,
"id": "5aaebef0", "id": "5aaebef0",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -365,7 +365,7 @@
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Instructions formatted: 128\n", "Instructions formatted: 132\n",
"\n", "\n",
"--- Preview (first 2 instructions) ---\n", "--- Preview (first 2 instructions) ---\n",
" // [System] 0x000 — NOP: No Operation\n", " // [System] 0x000 — NOP: No Operation\n",
@@ -380,7 +380,7 @@
"\n", "\n",
"\n", "\n",
"CPU.hpp updated successfully at: .//src//spider/runtime/cpu/CPU.hpp\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", "cell_type": "code",
"execution_count": 7, "execution_count": 8,
"id": "instrmap_gen", "id": "instrmap_gen",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -460,9 +460,9 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"InstrMap.cpp written to: .//src//spider/runtime/instr/InstrMap.cpp\n", "InstrMap.cpp written to: .//src//spider/runtime/instr/InstrMap.cpp\n",
" Size : 34,157 bytes\n", " Size : 33,581 bytes\n",
" Array entries : 512 (128 populated, 384 nullptr)\n", " Array entries : 512 (132 populated, 380 nullptr)\n",
" Switch cases : 128\n", " Switch cases : 132\n",
" Line endings : LF-only verified\n" " Line endings : LF-only verified\n"
] ]
} }
@@ -545,11 +545,11 @@
" mnem = opcode_to_mnem.get(opc)\n", " mnem = opcode_to_mnem.get(opc)\n",
" if mnem:\n", " if mnem:\n",
" name = opcode_to_name[opc]\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", " else:\n",
" tag = ''\n", " tag = ''\n",
" if opc in reserved_opcodes:\n", " if opc in reserved_opcodes:\n",
" tag = ' (reserved)'\n", " tag = ' (reserved)'\n",
" L.append(f' {\"nullptr,\":<28s}// 0x{opc:03X}{tag}')\n", " L.append(f' {\"nullptr,\":<28s}// 0x{opc:03X}{tag}')\n",
"\n", "\n",
"L.append('};')\n", "L.append('};')\n",
@@ -681,7 +681,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.14.3" "version": "3.13.7"
} }
}, },
"nbformat": 4, "nbformat": 4,
+2 -10
View File
@@ -1,18 +1,10 @@
#include "SpiderRuntime.hpp" #include "SpiderRuntime.hpp"
#include <spider/runtime/debug/LiveDebug.hpp>
#include <iostream> #include <iostream>
namespace spider { namespace spider {
const u32 RUNTIME_VERSION_NO = 0x00000000; // v0.1 const u32 RUNTIME_VERSION_NO = 0x00000001; // v0.1
const std::string RUNTIME_VERSION = "alpha v0.1"; const std::string RUNTIME_VERSION = "alpha v0.1";
} }
int main() {
spider::liveDebugMain();
return 0;
}
+20 -12
View File
@@ -76,8 +76,8 @@ namespace spider {
void CPU::fetchOperDst() { void CPU::fetchOperDst() {
// Move the operand ptrs // Move the operand ptrs
_alu = &ALU0;
_opers[1] = _opers[0]; _opers[1] = _opers[0];
_opers[0] = &ALU0;
// call specific addressing mode // call specific addressing mode
(this->*(CPU::addrModes[_addrm & 0b111]))(); // mask added here too (this->*(CPU::addrModes[_addrm & 0b111]))(); // mask added here too
@@ -85,7 +85,7 @@ namespace spider {
void CPU::fetchOperSrc() { void CPU::fetchOperSrc() {
// set ALU // set ALU
_alu = &ALU1; _opers[0] = &ALU1;
// call specific addressing mode // call specific addressing mode
(this->*(CPU::addrModes[_addrm & 0b111]))(); // mask keeps index within 0-7 (this->*(CPU::addrModes[_addrm & 0b111]))(); // mask keeps index within 0-7
@@ -95,13 +95,23 @@ namespace spider {
_addrm++; _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() { void CPU::execute() {
(this->*(CPU::instrMap[_opcode]))(); // no null check needed (this->*(CPU::instrMap[_opcode]))(); // no null check needed
// vvv MUST PROFILE: Is this faster than executing an empty function?
if(_post) (this->*_post)(); if(_post) (this->*_post)();
} }
// Addressing Modes // // Addressing Modes //
/** /**
@@ -115,8 +125,7 @@ namespace spider {
* Immediate Addressing Mode * Immediate Addressing Mode
*/ */
void CPU::imm() { void CPU::imm() {
_reel->loadRegister(RI, _size, _alu); _reel->loadRegister(RI, _size, _opers[0]);
_opers[0] = _alu;
_post = &CPU::imp; _post = &CPU::imp;
RI += 1 << _size; RI += 1 << _size;
} }
@@ -127,19 +136,19 @@ namespace spider {
void CPU::abs() { void CPU::abs() {
// Load the actual ptr into the ALU // Load the actual ptr into the ALU
u8 mm = u8(getFlag(CPU::FLAG_MEMORY_MODE)); u8 mm = u8(getFlag(CPU::FLAG_MEMORY_MODE));
_reel->loadRegister(RI, mm, _alu); _reel->loadRegister(RI, mm, _opers[0]);
RI += 1 << mm; RI += 1 << mm;
// read the memory from RAM // read the memory from RAM
_store = _alu->_u64; _store = _opers[0]->_u64;
_ram->loadRegister(_store, _size, _alu); _ram->loadRegister(_store, _size, _opers[0]);
_post = &CPU::psw; _post = &CPU::psw;
} }
/** /**
* Register Addressing Mode * Register Addressing Mode
*/ */
void CPU::reg() { // NOT FINISHED void CPU::reg() {
// Two consecutive registers can be declared // Two consecutive registers can be declared
// Shift if the top part will become .reg too // Shift if the top part will become .reg too
u8 sh = ((_addrm & 0b11000) == 0b11000) * 4; u8 sh = ((_addrm & 0b11000) == 0b11000) * 4;
@@ -147,12 +156,11 @@ namespace spider {
// get byte // get byte
u8 reg = (_reel->readU8(RI) >> sh) & 0xF; u8 reg = (_reel->readU8(RI) >> sh) & 0xF;
_alu = &GPR[reg]; _opers[0] = &GPR[reg]; // explicitly sets _opers[0] = _dst
_opers[0] = _alu; // explicitly sets _opers[0] = _dst
RI += use; RI += use;
// store no-op // store no-op
_post = &CPU::imp; _post = nullptr;
} }
/** /**
+57 -42
View File
@@ -64,7 +64,6 @@ namespace spider {
struct { struct {
register_t* _dst; register_t* _dst;
register_t* _src; register_t* _src;
register_t* _alu;
}; };
register_t* _opers[2]; register_t* _opers[2];
}; };
@@ -172,6 +171,18 @@ namespace spider {
*/ */
void fetchOperSrc(); 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 * Executes an opcode, by means of directly
* accessing the instruction map and * accessing the instruction map and
@@ -469,36 +480,56 @@ namespace spider {
// Operation: # of 1's into Dst // Operation: # of 1's into Dst
void CNT(); void CNT();
// [Boolean] 0x030 — EQ: Equal // [Boolean] 0x02E — EQ: Equal
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst == Src into Dst // Operation: Dst == Src into Dst
void EQ(); void EQ();
// [Boolean] 0x031 — NE: Not Equal // [Boolean] 0x02F — NE: Not Equal
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst != Src into Dst // Operation: Dst != Src into Dst
void NE(); void NE();
// [Boolean] 0x032 — GT: Greater Than // [Boolean] 0x030 — GT: Greater Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst > Src into Dst // Operation: Dst > Src into Dst
void GT(); void GT();
// [Boolean] 0x033 — GE: Greater or Equal Than // [Boolean] 0x031 — GE: Greater or Equal Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst >= Src into Dst // Operation: Dst >= Src into Dst
void GE(); void GE();
// [Boolean] 0x034 — LT: Lower Than // [Boolean] 0x032 — LT: Lower Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst < Src into Dst // Operation: Dst < Src into Dst
void LT(); void LT();
// [Boolean] 0x035 — LE: Lower or Equal Than // [Boolean] 0x033 — LE: Lower or Equal Than
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: Dst <= Src into Dst // Operation: Dst <= Src into Dst
void LE(); 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 // [Branch] 0x038 — JMP: Jump to absolute position
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F // Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0F
// Operation: Dst -> Instruction Register // Operation: Dst -> Instruction Register
@@ -541,22 +572,22 @@ namespace spider {
// [System] 0x040 — SFB: Store (User) Flag Bit // [System] 0x040 — SFB: Store (User) Flag Bit
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: // Operation:
void SFB(); void SFB();
// [System] 0x041 — LFB: Load (User) Flag Bit // [System] 0x041 — LFB: Load (User) Flag Bit
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: // Operation:
void LFB(); void LFB();
// [Branch] 0x042 — JUF: Jump to absolute position, if user flag is true // [Branch] 0x042 — JUF: Jump to absolute position, if user flag is true
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: // Operation:
void JUF(); void JUF();
// [Branch] 0x043 — JUR: Jump to relative position, if user flag is true // [Branch] 0x043 — JUR: Jump to relative position, if user flag is true
// Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F // Params: 2 | AddrMask1: 1E AddrMask2: FF | TypeMask: 0F
// Operation: // Operation:
void JUR(); void JUR();
// [Memory] 0x044 — PUSH: Push to stack // [Memory] 0x044 — PUSH: Push to stack
@@ -601,7 +632,7 @@ namespace spider {
// [Floating Point] 0x050 — FLI: Float Load Immediate // [Floating Point] 0x050 — FLI: Float Load Immediate
// Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C // Params: 1 | AddrMask1: FF AddrMask2: 00 | TypeMask: 0C
// Operation: // Operation:
void FLI(); void FLI();
// [Floating Point] 0x051 — FNEG: Float negate // [Floating Point] 0x051 — FNEG: Float negate
@@ -816,89 +847,73 @@ namespace spider {
// [Matrix] 0x080 — MADD: Matrix Addition // [Matrix] 0x080 — MADD: Matrix Addition
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void MADD(); void MADD();
// [Matrix] 0x081 — MSUB: Matrix Subtraction // [Matrix] 0x081 — MSUB: Matrix Subtraction
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void MSUB(); void MSUB();
// [Matrix] 0x082 — MMUL: Matrix Multiply // [Matrix] 0x082 — MMUL: Matrix Multiply
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void MMUL(); void MMUL();
// [Matrix] 0x083 — MINV: Matrix Inverse // [Matrix] 0x083 — MINV: Matrix Inverse
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void MINV(); void MINV();
// [Matrix] 0x084 — MTRA: Matrix Transpose // [Matrix] 0x084 — MTRA: Matrix Transpose
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void MTRA(); void MTRA();
// [Matrix] 0x085 — MDET: Matrix Determinant // [Matrix] 0x085 — MDET: Matrix Determinant
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void MDET(); void MDET();
// [Quaternion] 0x086 — QMKA: Quaternion Make from Angles // [Quaternion] 0x086 — QMKA: Quaternion Make from Angles
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void QMKA(); void QMKA();
// [Quaternion] 0x087 — QMUL: Quaternion Multiply // [Quaternion] 0x087 — QMUL: Quaternion Multiply
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void QMUL(); void QMUL();
// [SIMD] 0x08A — XADD: SIMD Addition // [SIMD] 0x08A — XADD: SIMD Addition
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void XADD(); void XADD();
// [SIMD] 0x08B — XSUB: SIMD Subtract // [SIMD] 0x08B — XSUB: SIMD Subtract
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void XSUB(); void XSUB();
// [SIMD] 0x08C — XAMA: SIMD Alternate Multiply-Add // [SIMD] 0x08C — XAMA: SIMD Alternate Multiply-Add
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void XAMA(); void XAMA();
// [SIMD] 0x08D — XMUL: SIMD Multiply // [SIMD] 0x08D — XMUL: SIMD Multiply
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void XMUL(); void XMUL();
// [SIMD] 0x08E — XDIV: SIMD Divide // [SIMD] 0x08E — XDIV: SIMD Divide
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void XDIV(); void XDIV();
// [Easter Eggs] 0x0F0 — UPY: Will place "YUPI" in memory // [Easter Eggs] 0x0F0 — UPY: Will place "YUPI" in memory
// Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00 // Params: 0 | AddrMask1: 00 AddrMask2: 00 | TypeMask: 00
// Operation: // Operation:
void UPY(); 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();
// </pygen-target> // // </pygen-target> //
-402
View File
@@ -1,402 +0,0 @@
#include "LiveDebug.hpp"
#include <spider/runtime/reel/InstrReelFixed.hpp>
#include <spider/runtime/Runtime.hpp>
#include <spider/runtime/util/Terminal.hpp>
#include <spider/runtime/native/distro.hpp>
#include <vector>
#include <string>
#include <iomanip>
#include <iostream>
#include <chrono>
#include <format>
#include <thread>
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(&lt, &t);
#endif
#if defined(SPIDER_OS_LINUX) || defined(SPIDER_OS_MACOS)
localtime_r(&t, &lt);
#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<std::chrono::seconds>(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;
}
}
-7
View File
@@ -1,7 +0,0 @@
#pragma once
namespace spider {
int liveDebugMain();
}
+154 -152
View File
@@ -35,149 +35,149 @@ namespace spider {
* if (fn) (cpu.*fn)(); * if (fn) (cpu.*fn)();
*/ */
CPU::Fn CPU::instrMap[] = { CPU::Fn CPU::instrMap[] = {
&CPU::NOP, // 0x000 — No Operation &CPU::NOP, // 0x000 — No Operation
&CPU::SPDR, // 0x001 — Will place the Spider version of the interpreter in RA &CPU::SPDR, // 0x001 — Will place the Spider version of the interpreter in RA
&CPU::MMODE, // 0x002 — Set Memory Mode &CPU::MMODE, // 0x002 — Set Memory Mode
&CPU::INT, // 0x003 — Interrupt &CPU::INT, // 0x003 — Interrupt
&CPU::LRV, // 0x004 — Load Interrupt Vector Register &CPU::LRV, // 0x004 — Load Interrupt Vector Register
&CPU::FSR, // 0x005 — Fetch System Register &CPU::FSR, // 0x005 — Fetch System Register
&CPU::FIR, // 0x006 — Fetch Instruction Register &CPU::FIR, // 0x006 — Fetch Instruction Register
&CPU::FZR, // 0x007 — Fetch Stack Base Register &CPU::FZR, // 0x007 — Fetch Stack Base Register
&CPU::LSR, // 0x008 — Load System Register &CPU::LSR, // 0x008 — Load System Register
&CPU::FVR, // 0x009 — Fetch Interrupt Vector Register &CPU::FVR, // 0x009 — Fetch Interrupt Vector Register
&CPU::MOV, // 0x00A — Moves values &CPU::MOV, // 0x00A — Moves values
&CPU::MOR, // 0x00B — Moves registers &CPU::MOR, // 0x00B — Moves registers
&CPU::AMOV, // 0x00C — Array Move, uses X and Y as ptrs, A as amount &CPU::AMOV, // 0x00C — Array Move, uses X and Y as ptrs, A as amount
&CPU::SWP, // 0x00D — Swap registers &CPU::SWP, // 0x00D — Swap registers
&CPU::AHM, // 0x00E — Ask Host for Memory &CPU::AHM, // 0x00E — Ask Host for Memory
nullptr, // 0x00F (reserved) nullptr, // 0x00F (reserved)
&CPU::COM, // 0x010 — One's complement &CPU::COM, // 0x010 — One's complement
&CPU::NEG, // 0x011 — Two's complement &CPU::NEG, // 0x011 — Two's complement
&CPU::EXS, // 0x012 — Extend Sign &CPU::EXS, // 0x012 — Extend Sign
&CPU::INC, // 0x013 — Increment &CPU::INC, // 0x013 — Increment
&CPU::DEC, // 0x014 — Decrement &CPU::DEC, // 0x014 — Decrement
&CPU::ADD, // 0x015 — Addition &CPU::ADD, // 0x015 — Addition
&CPU::SUB, // 0x016 — Subtraction &CPU::SUB, // 0x016 — Subtraction
&CPU::MUL, // 0x017 — Multiplication &CPU::MUL, // 0x017 — Multiplication
&CPU::UMUL, // 0x018 — Unsigned Multiplication &CPU::UMUL, // 0x018 — Unsigned Multiplication
&CPU::DIV, // 0x019 — Division &CPU::DIV, // 0x019 — Division
&CPU::UDIV, // 0x01A — Unsigned Division &CPU::UDIV, // 0x01A — Unsigned Division
&CPU::MOD, // 0x01B — Modulus &CPU::MOD, // 0x01B — Modulus
&CPU::UMOD, // 0x01C — Unsigned Modulus &CPU::UMOD, // 0x01C — Unsigned Modulus
&CPU::DMOD, // 0x01D — Division and Modulus &CPU::DMOD, // 0x01D — Division and Modulus
&CPU::UDMD, // 0x01E — Unsigned Division and Modulus &CPU::UDMD, // 0x01E — Unsigned Division and Modulus
&CPU::FBT, // 0x01F — Test and update Flag Register (Integer) Bits &CPU::FBT, // 0x01F — Test and update Flag Register (Integer) Bits
&CPU::STB, // 0x020 — Set Bit &CPU::STB, // 0x020 — Set Bit
&CPU::CRB, // 0x021 — Clear Bit &CPU::CRB, // 0x021 — Clear Bit
&CPU::TSB, // 0x022 — Test Bit &CPU::TSB, // 0x022 — Test Bit
&CPU::BOOL, // 0x023 — Sets the booleaness of a value &CPU::BOOL, // 0x023 — Sets the booleaness of a value
&CPU::NOT, // 0x024 — Sets the inverse booleaness of a value (! BOOL) &CPU::NOT, // 0x024 — Sets the inverse booleaness of a value (! BOOL)
&CPU::AND, // 0x025 — Boolean AND operation &CPU::AND, // 0x025 — Boolean AND operation
&CPU::OR, // 0x026 — Boolean OR operation &CPU::OR, // 0x026 — Boolean OR operation
&CPU::XOR, // 0x027 — Boolean XOR operation &CPU::XOR, // 0x027 — Boolean XOR operation
&CPU::SHL, // 0x028 — Arithmetic Shift Left &CPU::SHL, // 0x028 — Arithmetic Shift Left
&CPU::SHR, // 0x029 — Arithmetic Shift Right &CPU::SHR, // 0x029 — Arithmetic Shift Right
&CPU::SSR, // 0x02A — Signed Shift Right &CPU::SSR, // 0x02A — Signed Shift Right
&CPU::ROL, // 0x02B — Rotate Left &CPU::ROL, // 0x02B — Rotate Left
&CPU::ROR, // 0x02C — Rotate Right &CPU::ROR, // 0x02C — Rotate Right
&CPU::CNT, // 0x02D — Counts bits &CPU::CNT, // 0x02D — Counts bits
nullptr, // 0x02E (reserved) &CPU::EQ, // 0x02E — Equal
nullptr, // 0x02F (reserved) &CPU::NE, // 0x02F — Not Equal
&CPU::EQ, // 0x030 — Equal &CPU::GT, // 0x030 — Greater Than
&CPU::NE, // 0x031 — Not Equal &CPU::GE, // 0x031 — Greater or Equal Than
&CPU::GT, // 0x032 — Greater Than &CPU::LT, // 0x032 — Lower Than
&CPU::GE, // 0x033 — Greater or Equal Than &CPU::LE, // 0x033 — Lower or Equal Than
&CPU::LT, // 0x034 — Lower Than &CPU::GTU, // 0x034 — Greater Than, Unsigned
&CPU::LE, // 0x035 — Lower or Equal Than &CPU::GEU, // 0x035 — Greater or Equal Than, Unsigned
nullptr, // 0x036 (reserved) &CPU::LTU, // 0x036 — Lower Than, Unsigned
nullptr, // 0x037 (reserved) &CPU::LEU, // 0x037 — Lower or Equal Than, Unsigned
&CPU::JMP, // 0x038 — Jump to absolute position &CPU::JMP, // 0x038 — Jump to absolute position
&CPU::JEQ, // 0x039 — Jumps to position if EQ flag is set &CPU::JEQ, // 0x039 — Jumps to position if EQ flag is set
&CPU::JNE, // 0x03A — Jumps to position if EQ flag is cleared &CPU::JNE, // 0x03A — Jumps to position if EQ flag is cleared
&CPU::JIF, // 0x03B — Jumps if value provided is booleanly true &CPU::JIF, // 0x03B — Jumps if value provided is booleanly true
&CPU::JMR, // 0x03C — Jump Relative &CPU::JMR, // 0x03C — Jump Relative
&CPU::JER, // 0x03D — Jumps to relative position if EQ flag is set &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::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::JIR, // 0x03F — Jumps to relative position if value provided is booleanly true
&CPU::SFB, // 0x040 — Store (User) Flag Bit &CPU::SFB, // 0x040 — Store (User) Flag Bit
&CPU::LFB, // 0x041 — Load (User) Flag Bit &CPU::LFB, // 0x041 — Load (User) Flag Bit
&CPU::JUF, // 0x042 — Jump to absolute position, if user flag is true &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::JUR, // 0x043 — Jump to relative position, if user flag is true
&CPU::PUSH, // 0x044 — Push to stack &CPU::PUSH, // 0x044 — Push to stack
&CPU::POP, // 0x045 — Pop from stack &CPU::POP, // 0x045 — Pop from stack
&CPU::ALLOC, // 0x046 — Allocate to heap &CPU::ALLOC, // 0x046 — Allocate to heap
&CPU::HFREE, // 0x047 — Delete from heap &CPU::HFREE, // 0x047 — Delete from heap
nullptr, // 0x048 (reserved) nullptr, // 0x048 (reserved)
nullptr, // 0x049 (reserved) nullptr, // 0x049 (reserved)
&CPU::CALL, // 0x04A — Call function at instruction index &CPU::CALL, // 0x04A — Call function at instruction index
&CPU::RET, // 0x04B — Return from a function &CPU::RET, // 0x04B — Return from a function
&CPU::EDI, // 0x04C — Enable/Disable External Interrupts &CPU::EDI, // 0x04C — Enable/Disable External Interrupts
&CPU::SHSS, // 0x04D — Set Hotswap Signal Bit &CPU::SHSS, // 0x04D — Set Hotswap Signal Bit
nullptr, // 0x04E (reserved) nullptr, // 0x04E (reserved)
nullptr, // 0x04F (reserved) nullptr, // 0x04F (reserved)
&CPU::FLI, // 0x050 — Float Load Immediate &CPU::FLI, // 0x050 — Float Load Immediate
&CPU::FNEG, // 0x051 — Float negate &CPU::FNEG, // 0x051 — Float negate
&CPU::FADD, // 0x052 — Float add &CPU::FADD, // 0x052 — Float add
&CPU::FSUB, // 0x053 — Float subtract &CPU::FSUB, // 0x053 — Float subtract
&CPU::FMUL, // 0x054 — Float multiplication &CPU::FMUL, // 0x054 — Float multiplication
&CPU::FDIV, // 0x055 — Float division &CPU::FDIV, // 0x055 — Float division
&CPU::FMOD, // 0x056 — Float modulus &CPU::FMOD, // 0x056 — Float modulus
&CPU::FDMOD, // 0x057 — Float division and modulus &CPU::FDMOD, // 0x057 — Float division and modulus
&CPU::FEPS, // 0x058 — Sets the float epsilon value, for comparison &CPU::FEPS, // 0x058 — Sets the float epsilon value, for comparison
&CPU::FEEP, // 0x059 — Float Enable/Disable Epsilon &CPU::FEEP, // 0x059 — Float Enable/Disable Epsilon
&CPU::FEQ, // 0x05A — Float Equal &CPU::FEQ, // 0x05A — Float Equal
&CPU::FNE, // 0x05B — Float Not Equal &CPU::FNE, // 0x05B — Float Not Equal
&CPU::FGT, // 0x05C — Float Greater Than &CPU::FGT, // 0x05C — Float Greater Than
&CPU::FGE, // 0x05D — Float Greater or Equal Than &CPU::FGE, // 0x05D — Float Greater or Equal Than
&CPU::FLT, // 0x05E — Float Lower Than &CPU::FLT, // 0x05E — Float Lower Than
&CPU::FLE, // 0x05F — Float Lower or Equal Than &CPU::FLE, // 0x05F — Float Lower or Equal Than
&CPU::F2D, // 0x060 — F32 (Float) to F64 (Double) &CPU::F2D, // 0x060 — F32 (Float) to F64 (Double)
&CPU::D2F, // 0x061 — F64 (Double) to F32 (Float) &CPU::D2F, // 0x061 — F64 (Double) to F32 (Float)
&CPU::I2F, // 0x062 — I32 (Integer) to F32 (Float) &CPU::I2F, // 0x062 — I32 (Integer) to F32 (Float)
&CPU::I2D, // 0x063 — I32 (Integer) to F64 (Double) &CPU::I2D, // 0x063 — I32 (Integer) to F64 (Double)
&CPU::L2F, // 0x064 — I64 (Long) to F32 (Float) &CPU::L2F, // 0x064 — I64 (Long) to F32 (Float)
&CPU::L2D, // 0x065 — I64 (Long) to F64 (Double) &CPU::L2D, // 0x065 — I64 (Long) to F64 (Double)
&CPU::F2I, // 0x066 — F32 (Float) to I32 (Integer) &CPU::F2I, // 0x066 — F32 (Float) to I32 (Integer)
&CPU::F2L, // 0x067 — F32 (Float) to I64 (Long) &CPU::F2L, // 0x067 — F32 (Float) to I64 (Long)
&CPU::D2I, // 0x068 — F64 (Double) to I32 (Integer) &CPU::D2I, // 0x068 — F64 (Double) to I32 (Integer)
&CPU::D2L, // 0x069 — F64 (Double) to I64 (Long) &CPU::D2L, // 0x069 — F64 (Double) to I64 (Long)
nullptr, // 0x06A (reserved) nullptr, // 0x06A (reserved)
nullptr, // 0x06B (reserved) nullptr, // 0x06B (reserved)
&CPU::SIN, // 0x06C — Sine Function &CPU::SIN, // 0x06C — Sine Function
&CPU::COS, // 0x06D — Cosine Function &CPU::COS, // 0x06D — Cosine Function
&CPU::TAN, // 0x06E — Tangent Function &CPU::TAN, // 0x06E — Tangent Function
&CPU::ASIN, // 0x06F — Arc Sine Function &CPU::ASIN, // 0x06F — Arc Sine Function
&CPU::ACOS, // 0x070 — Arc Cosine Function &CPU::ACOS, // 0x070 — Arc Cosine Function
&CPU::ATAN, // 0x071 — Arc Tangent Function &CPU::ATAN, // 0x071 — Arc Tangent Function
&CPU::ATAN2, // 0x072 — Arc Tangent Function with 2 Arguments &CPU::ATAN2, // 0x072 — Arc Tangent Function with 2 Arguments
nullptr, // 0x073 (reserved) nullptr, // 0x073 (reserved)
&CPU::EXP, // 0x074 — Exponential Function &CPU::EXP, // 0x074 — Exponential Function
&CPU::LOG, // 0x075 — Natural Logarithm &CPU::LOG, // 0x075 — Natural Logarithm
&CPU::LOGAB, // 0x076 — Logarithm A of B &CPU::LOGAB, // 0x076 — Logarithm A of B
&CPU::POW, // 0x077 — Power Function &CPU::POW, // 0x077 — Power Function
&CPU::SQRT, // 0x078 — Square Root &CPU::SQRT, // 0x078 — Square Root
&CPU::ROOT, // 0x079 — General Root &CPU::ROOT, // 0x079 — General Root
nullptr, // 0x07A (reserved) nullptr, // 0x07A (reserved)
nullptr, // 0x07B (reserved) nullptr, // 0x07B (reserved)
&CPU::ADC, // 0x07C — Add with Carry &CPU::ADC, // 0x07C — Add with Carry
&CPU::SWC, // 0x07D — Subtract with Carry (Borrow) &CPU::SWC, // 0x07D — Subtract with Carry (Borrow)
&CPU::MWO, // 0x07E — Multiply with Overflow &CPU::MWO, // 0x07E — Multiply with Overflow
&CPU::UMO, // 0x07F — Unsigned Multiply with Overflow &CPU::UMO, // 0x07F — Unsigned Multiply with Overflow
&CPU::MADD, // 0x080 — Matrix Addition &CPU::MADD, // 0x080 — Matrix Addition
&CPU::MSUB, // 0x081 — Matrix Subtraction &CPU::MSUB, // 0x081 — Matrix Subtraction
&CPU::MMUL, // 0x082 — Matrix Multiply &CPU::MMUL, // 0x082 — Matrix Multiply
&CPU::MINV, // 0x083 — Matrix Inverse &CPU::MINV, // 0x083 — Matrix Inverse
&CPU::MTRA, // 0x084 — Matrix Transpose &CPU::MTRA, // 0x084 — Matrix Transpose
&CPU::MDET, // 0x085 — Matrix Determinant &CPU::MDET, // 0x085 — Matrix Determinant
&CPU::QMKA, // 0x086 — Quaternion Make from Angles &CPU::QMKA, // 0x086 — Quaternion Make from Angles
&CPU::QMUL, // 0x087 — Quaternion Multiply &CPU::QMUL, // 0x087 — Quaternion Multiply
nullptr, // 0x088 nullptr, // 0x088
nullptr, // 0x089 nullptr, // 0x089
&CPU::XADD, // 0x08A — SIMD Addition &CPU::XADD, // 0x08A — SIMD Addition
&CPU::XSUB, // 0x08B — SIMD Subtract &CPU::XSUB, // 0x08B — SIMD Subtract
&CPU::XAMA, // 0x08C — SIMD Alternate Multiply-Add &CPU::XAMA, // 0x08C — SIMD Alternate Multiply-Add
&CPU::XMUL, // 0x08D — SIMD Multiply &CPU::XMUL, // 0x08D — SIMD Multiply
&CPU::XDIV, // 0x08E — SIMD Divide &CPU::XDIV, // 0x08E — SIMD Divide
nullptr, // 0x08F nullptr, // 0x08F
nullptr, // 0x090 nullptr, // 0x090
nullptr, // 0x091 nullptr, // 0x091
@@ -275,13 +275,13 @@ CPU::Fn CPU::instrMap[] = {
nullptr, // 0x0ED nullptr, // 0x0ED
nullptr, // 0x0EE nullptr, // 0x0EE
nullptr, // 0x0EF nullptr, // 0x0EF
&CPU::UPY, // 0x0F0 — Will place "YUPI" in memory &CPU::UPY, // 0x0F0 — Will place "YUPI" in memory
&CPU::LLGS, // 0x0F1 — Spider ASCII art (LLGS easter egg) nullptr, // 0x0F1
nullptr, // 0x0F2 nullptr, // 0x0F2
nullptr, // 0x0F3 nullptr, // 0x0F3
nullptr, // 0x0F4 nullptr, // 0x0F4
nullptr, // 0x0F5 nullptr, // 0x0F5
&CPU::DGANT, // 0x0F6 nullptr, // 0x0F6
nullptr, // 0x0F7 nullptr, // 0x0F7
nullptr, // 0x0F8 nullptr, // 0x0F8
nullptr, // 0x0F9 nullptr, // 0x0F9
@@ -622,12 +622,16 @@ void CPU::executeSwLk() {
case 0x02D: CNT(); break; case 0x02D: CNT(); break;
// ── Boolean ───────────────────────────────────── // ── Boolean ─────────────────────────────────────
case 0x030: EQ(); break; case 0x02E: EQ(); break;
case 0x031: NE(); break; case 0x02F: NE(); break;
case 0x032: GT(); break; case 0x030: GT(); break;
case 0x033: GE(); break; case 0x031: GE(); break;
case 0x034: LT(); break; case 0x032: LT(); break;
case 0x035: LE(); break; case 0x033: LE(); break;
case 0x034: GTU(); break;
case 0x035: GEU(); break;
case 0x036: LTU(); break;
case 0x037: LEU(); break;
// ── Branch ────────────────────────────────────── // ── Branch ──────────────────────────────────────
case 0x038: JMP(); break; case 0x038: JMP(); break;
@@ -737,8 +741,6 @@ void CPU::executeSwLk() {
// ── Easter Eggs ───────────────────────────────── // ── Easter Eggs ─────────────────────────────────
case 0x0F0: UPY(); break; case 0x0F0: UPY(); break;
case 0x0F1: LLGS(); break;
default: default:
break; break;
+272 -240
View File
@@ -4,15 +4,16 @@
*/ */
#include <spider/runtime/cpu/CPU.hpp> #include <spider/runtime/cpu/CPU.hpp>
#include <spider/runtime/memory/RAM.hpp>
namespace spider { namespace spider {
void CPU::NOP() { void CPU::NOP() {
// TODO: Implement NOP // DONE ! //
} }
void CPU::SPDR() { void CPU::SPDR() {
// TODO: Implement SPDR RA._u64 = spider::RUNTIME_VERSION_NO;
} }
void CPU::MMODE() { void CPU::MMODE() {
@@ -21,10 +22,13 @@ namespace spider {
void CPU::INT() { void CPU::INT() {
// TODO: Implement INT // TODO: Implement INT
// We need to implement an interrupt
// table and interrupt system!
} }
void CPU::LRV() { void CPU::LRV() {
// TODO: Implement LRV fetchOperReg();
RV = _dst->_u64;
} }
void CPU::FSR() { void CPU::FSR() {
@@ -32,11 +36,13 @@ namespace spider {
} }
void CPU::FIR() { void CPU::FIR() {
// TODO: Implement FIR fetchOperReg();
_dst->_u64 = RI;
} }
void CPU::FZR() { void CPU::FZR() {
// TODO: Implement FZR fetchOperReg();
_dst->_u64 = RZ;
} }
void CPU::LSR() { void CPU::LSR() {
@@ -44,23 +50,63 @@ namespace spider {
} }
void CPU::FVR() { void CPU::FVR() {
// TODO: Implement FVR fetchOperReg();
_dst->_u64 = RV;
} }
void CPU::MOV() { 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() { void CPU::MOR() {
// TODO: Implement MOR fetchOperRegReg();
*_dst = *_src;
} }
void CPU::AMOV() { 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() { void CPU::SWP() {
// TODO: Implement SWP // get registers in _dst and _src
fetchOperRegReg();
ALU0 = *_dst;
*_dst = *_src;
*_src = ALU0;
} }
void CPU::AHM() { void CPU::AHM() {
@@ -69,321 +115,307 @@ namespace spider {
void CPU::COM() { void CPU::COM() {
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = ~_dst->_u8; _dst->_u8 = ~_dst->_u8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 = ~_dst->_u16; _dst->_u16 = ~_dst->_u16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 = ~_dst->_u32; _dst->_u32 = ~_dst->_u32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 = ~_dst->_u64; _dst->_u64 = ~_dst->_u64;
break; break;
} }
} }
void CPU::NEG() { void CPU::NEG() {
// TODO: Implement NEG
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = 1 + ~_dst->_u8; _dst->_u8 = 1 + ~_dst->_u8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 = 1+ ~_dst->_u16; _dst->_u16 = 1 + ~_dst->_u16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 = 1 + ~_dst->_u32; _dst->_u32 = 1 + ~_dst->_u32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 = 1 + ~_dst->_u64; _dst->_u64 = 1 + ~_dst->_u64;
break; break;
} }
} }
void CPU::EXS() { void CPU::EXS() {
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_i16 = static_cast<i16>(_dst->_i8); _dst->_i16 = static_cast<i16>(_dst->_i8);
break; break;
case 0b01: //short case 0b01: //short
_dst->_i32 = static_cast<i32>(_dst->_i16); _dst->_i32 = static_cast<i32>(_dst->_i16);
break; break;
case 0b10: //int case 0b10: //int
_dst->_i64 = static_cast<i64>(_dst->_i32); _dst->_i64 = static_cast<i64>(_dst->_i32);
break; break;
case 0b11: //long case 0b11: //long
_dst->_i64 = _dst->_i64; _dst->_i64 = _dst->_i64;
break; break;
} }
} }
void CPU::INC() { void CPU::INC() {
// TODO: Implement INC
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 += 1; _dst->_u8 += 1;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 += 1; _dst->_u16 += 1;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 += 1; _dst->_u32 += 1;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 += 1; _dst->_u64 += 1;
break; break;
} }
} }
void CPU::DEC() { void CPU::DEC() {
// TODO: Implement DEC
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 -= 1; _dst->_u8 -= 1;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 -= 1; _dst->_u16 -= 1;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 -= 1; _dst->_u32 -= 1;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 -= 1; _dst->_u64 -= 1;
break; break;
} }
} }
void CPU::ADD() { void CPU::ADD() {
// TODO: Implement ADD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 += _src->_u8; _dst->_u8 += _src->_u8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 += _src->_u16; _dst->_u16 += _src->_u16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 += _src->_u32; _dst->_u32 += _src->_u32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 += _src->_u64; _dst->_u64 += _src->_u64;
break; break;
} }
} }
void CPU::SUB() { void CPU::SUB() {
// TODO: Implement SUB
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 -= _src->_u8; _dst->_u8 -= _src->_u8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 -= _src->_u16; _dst->_u16 -= _src->_u16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 -= _src->_u32; _dst->_u32 -= _src->_u32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 -= _src->_u64; _dst->_u64 -= _src->_u64;
break; break;
} }
} }
void CPU::MUL() { void CPU::MUL() {
// TODO: Implement MUL
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_i8 = _src->_i8 * _dst->_i8; _dst->_i8 = _src->_i8 * _dst->_i8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_i16 = _src->_i16 * _dst->_i16; _dst->_i16 = _src->_i16 * _dst->_i16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_i32 = _src->_i32 * _dst->_i32; _dst->_i32 = _src->_i32 * _dst->_i32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_i64 = _src->_i64 * _dst->_i64; _dst->_i64 = _src->_i64 * _dst->_i64;
break; break;
} }
} }
void CPU::UMUL() { void CPU::UMUL() {
// TODO: Implement UMUL
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = _src->_u8 * _dst->_u8; _dst->_u8 = _src->_u8 * _dst->_u8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 = _src->_u16 * _dst->_u16; _dst->_u16 = _src->_u16 * _dst->_u16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 = _src->_u32 * _dst->_u32; _dst->_u32 = _src->_u32 * _dst->_u32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 = _src->_u64 * _dst->_u64; _dst->_u64 = _src->_u64 * _dst->_u64;
break; break;
} }
} }
void CPU::DIV() { void CPU::DIV() {
// TODO: Implement DIV
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_i8 = _dst->_i8 / _src->_i8; _dst->_i8 = _dst->_i8 / _src->_i8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_i16 = _dst->_i16 / _src->_i16; _dst->_i16 = _dst->_i16 / _src->_i16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_i32 = _dst->_i32 / _src->_i32; _dst->_i32 = _dst->_i32 / _src->_i32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_i64 = _dst->_i64 / _src->_i64; _dst->_i64 = _dst->_i64 / _src->_i64;
break; break;
} }
} }
void CPU::UDIV() { void CPU::UDIV() {
// TODO: Implement UDIV
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = _dst->_u8 / _src->_u8; _dst->_u8 = _dst->_u8 / _src->_u8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 = _dst->_u16 / _src->_u16; _dst->_u16 = _dst->_u16 / _src->_u16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 = _dst->_u32 / _src->_u32; _dst->_u32 = _dst->_u32 / _src->_u32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 = _dst->_u64 / _src->_u64; _dst->_u64 = _dst->_u64 / _src->_u64;
break; break;
} }
} }
void CPU::MOD() { void CPU::MOD() {
// TODO: Implement MOD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_i8 = _dst->_i8 % _src->_i8; _dst->_i8 = _dst->_i8 % _src->_i8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_i16 = _dst->_i16 % _src->_i16; _dst->_i16 = _dst->_i16 % _src->_i16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_i32 = _dst->_i32 % _src->_i32; _dst->_i32 = _dst->_i32 % _src->_i32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_i64 = _dst->_i64 % _src->_i64; _dst->_i64 = _dst->_i64 % _src->_i64;
break; break;
} }
} }
void CPU::UMOD() { void CPU::UMOD() {
// TODO: Implement UMOD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
_dst->_u8 = _dst->_u8 % _src->_u8; _dst->_u8 = _dst->_u8 % _src->_u8;
break; break;
case 0b01: //short case 0b01: //short
_dst->_u16 = _dst->_u16 % _src->_u16; _dst->_u16 = _dst->_u16 % _src->_u16;
break; break;
case 0b10: //int case 0b10: //int
_dst->_u32 = _dst->_u32 % _src->_u32; _dst->_u32 = _dst->_u32 % _src->_u32;
break; break;
case 0b11: //long case 0b11: //long
_dst->_u64 = _dst->_u64 % _src->_u64; _dst->_u64 = _dst->_u64 % _src->_u64;
break; break;
} }
} }
void CPU::DMOD() { void CPU::DMOD() {
// TODO: Implement DMOD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
RX._i8 = _dst->_i8 / _src->_i8; RX._i8 = _dst->_i8 / _src->_i8;
RY._i8 = _dst->_i8 % _src->_i8; RY._i8 = _dst->_i8 % _src->_i8;
break; break;
case 0b01: //short case 0b01: //short
RX._i16 = _dst->_i16 / _src->_i16; RX._i16 = _dst->_i16 / _src->_i16;
RY._i16 = _dst->_i16 % _src->_i16; RY._i16 = _dst->_i16 % _src->_i16;
break; break;
case 0b10: //int case 0b10: //int
RX._i32 = _dst->_i32 / _src->_i32; RX._i32 = _dst->_i32 / _src->_i32;
RY._i32 = _dst->_i32 % _src->_i32; RY._i32 = _dst->_i32 % _src->_i32;
break; break;
case 0b11: //long case 0b11: //long
RX._i64 = _dst->_i64 / _src->_i64; RX._i64 = _dst->_i64 / _src->_i64;
RY._i64 = _dst->_i64 % _src->_i64; RY._i64 = _dst->_i64 % _src->_i64;
break; break;
} }
} }
void CPU::UDMD() { void CPU::UDMD() {
// TODO: Implement UDMD
fetchOperSrc(); fetchOperSrc();
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
RX._u8 = _dst->_u8 / _src->_u8; RX._u8 = _dst->_u8 / _src->_u8;
RY._u8 = _dst->_u8 % _src->_u8; RY._u8 = _dst->_u8 % _src->_u8;
break; break;
case 0b01: //short case 0b01: //short
RX._u16 = _dst->_u16 / _src->_u16; RX._u16 = _dst->_u16 / _src->_u16;
RY._u16 = _dst->_u16 % _src->_u16; RY._u16 = _dst->_u16 % _src->_u16;
break; break;
case 0b10: //int case 0b10: //int
RX._u32 = _dst->_u32 / _src->_u32; RX._u32 = _dst->_u32 / _src->_u32;
RY._u32 = _dst->_u32 % _src->_u32; RY._u32 = _dst->_u32 % _src->_u32;
break; break;
case 0b11: //long case 0b11: //long
RX._u64 = _dst->_u64 / _src->_u64; RX._u64 = _dst->_u64 / _src->_u64;
RY._u64 = _dst->_u64 % _src->_u64; RY._u64 = _dst->_u64 % _src->_u64;
break; break;
} }
} }
void CPU::FBT() { void CPU::FBT() {
// TODO: Implement FBT
fetchOperDst(); fetchOperDst();
switch(_size){ switch (_size) {
case 0b00: //byte case 0b00: //byte
RF = u8((RF & ~(0x3 << 9))) | ((_dst->_u8 >> 9) & 0x3) << 9; RF = u8((RF & ~(0x3 << 9))) | ((_dst->_u8 >> 9) & 0x3) << 9;
break; break;
case 0b01: //short case 0b01: //short
RF = u16((RF & ~(0x3 << 9))) | ((_dst->_u16 >> 9) & 0x3) << 9; RF = u16((RF & ~(0x3 << 9))) | ((_dst->_u16 >> 9) & 0x3) << 9;
break; break;
case 0b10: //int case 0b10: //int
RF = u32((RF & ~(0x3 << 9))) | ((_dst->_u32 >> 9) & 0x3) << 9; RF = u32((RF & ~(0x3 << 9))) | ((_dst->_u32 >> 9) & 0x3) << 9;
break; break;
case 0b11: //long case 0b11: //long
RF = u64((RF & ~(0x3 << 9))) | ((_dst->_u64 >> 9) & 0x3) << 9; RF = u64((RF & ~(0x3 << 9))) | ((_dst->_u64 >> 9) & 0x3) << 9;
break; break;
} }
} }
-61
View File
@@ -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 <spider/runtime/cpu/CPU.hpp>
#include <spider/runtime/memory/RAM.hpp>
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
-118
View File
@@ -1,118 +0,0 @@
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_E
#define M_E 2.71828182845904523536
#endif
#include <spider/runtime/cpu/CPU.hpp>
#include <iostream>
#include <cmath>
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;
}