<commit_before>#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "machine.h"
#include "tokenize.h"
#include "exception.h"

static
xsm_cpu _thecpu;

static
xsm_options _theoptions;

const char *instructions[]=
{
   "MOV",
   "ADD",
   "SUB",
   "MUL", 
   "DIV",
   "MOD",
   "INR",
   "DCR",
   "LT",
   "GT", 
   "EQ",
   "NE", 
   "GE", 
   "LE",
   "JZ",
   "JNZ",
   "JMP",
   "PUSH",
   "POP",
   "CALL",
   "RET",
   "BRKP",
   "INT",
   
   "LOADI",
   "LOAD",
   "STORE",
   "ENCRYPT",
   "BACKUP",
   "RESTORE",
   "PORT",
   "IN",
   "INI",
   "OUT",
   "IRET",
   "HALT"
};

int
machine_init (xsm_options *options)
{
   xsm_word *ipreg;

   _theoptions = *options;

   /* Set up the registers. */
   if (!registers_init ())
      return XSM_FAILURE;

   if (!memory_init())
      return XSM_FAILURE;

   if (!debug_init())
      return FALSE;

   /* Initialize machine. */
   word_store_string(memory_get_word(0), "LOAD 1, 0");
   word_store_string(memory_get_word(2), "JMP 512");

   disk_read_block(memory_get_page(1), 0);

   /* Set up IP.. */
   ipreg = machine_get_ipreg ();
   word_store_integer(ipreg, 512);

   machine_set_mode(PRIVILEGE_KERNEL);

   /* The disk and console is idle.*/
   _thecpu.console_state = XSM_CONSOLE_IDLE;
   _thecpu.disk_state = XSM_DISK_IDLE;

   return XSM_SUCCESS;
}

int
machine_get_opcode (const char* instr)
{
   int i;
   
   for (i = 0; i < XSM_INSTRUCTION_COUNT; ++i)
   {
      if (!strcasecmp(instr, instructions[i]))
         return i;
   }
   
   return XSM_ILLINSTR;
}

/* When the lexer calls, serve him with the instruction to execute.
 * Here we have a problem. The read_bytes need to be of type yy_size_t.
 * If this argument raises a warning, then investigate what yy_size_t means,
 * and change it here accordingly.
 */
 
int
machine_serve_instruction (char _output_ *buffer, unsigned long _output_ *read_bytes, int _input_ max)
{
   int ip_val, i;
   xsm_word *ip_reg;
   int bytes_to_read;
   xsm_word *instr_mem;

   bytes_to_read = XSM_INSTRUCTION_SIZE * XSM_WORD_SIZE;

   ip_reg = machine_get_ipreg();
   ip_val = word_get_integer(ip_reg);

   ip_val = machine_translate_address(ip_val, FALSE);
   instr_mem = machine_memory_get_word(ip_val);

   memcpy (buffer, instr_mem, bytes_to_read);

   /* Trim. */
   for (i = 0; i < bytes_to_read; ++i)
   {
      if (buffer[i] == '\0')
         buffer[i] = ' ';
   }

   buffer[bytes_to_read - 1] = '\0';
   *read_bytes = bytes_to_read;

   return TRUE;
}

/* Raises an exception. This function never returns. */
void
machine_register_exception (char* message, int code)
{
   int mode;

   mode = machine_get_mode();
   exception_set(message, code, mode);
   /* Abandon ship! Abandon ship! */
   longjmp (_thecpu.h_exp_point, XSM_EXCEPTION_OCCURED);
}

xsm_word*
machine_memory_get_word (int address)
{
   xsm_word *result;

   result = memory_get_word(address);

   if (NULL == result)
   {
      /* Doomsday! */
      exception_set_ma(address);
      machine_register_exception("Illegal memory access", EXP_ILLMEM);
   }

   return result;
}

xsm_word *
machine_get_ipreg ()
{
   return registers_get_register("IP");
}

xsm_word *
machine_get_spreg ()
{
   return registers_get_register("SP");
}

void
machine_pre_execute(int ip_val)
{
   /* Clear the potential watchpoint trigger. */
   _thecpu.mem_low = -1;

   /* If debugging was requested, activate the debug command line. */
   if (_theoptions.debug)
   {
      debug_next_step (ip_val);
   }
}

int
machine_instr_req_privilege (int opcode)
{
   if (opcode >= TOKEN_KERN_LOW && TOKEN_KERN_HIGH >= opcode)
      return PRIVILEGE_KERNEL;
   return PRIVILEGE_USER;
}

int
machine_run ()
{
   int token, opcode;
   YYSTYPE token_info;
   xsm_word *ipreg;
   int ipval;
   int exp_occured;

   ipreg = machine_get_ipreg ();

   while (TRUE){
      /* Set the exception point. */
      exp_occured = setjmp (_thecpu.h_exp_point);

      if (exp_occured == XSM_EXCEPTION_OCCURED)
      {
         if (XSM_SUCCESS != machine_handle_exception())
            break;
      }

      /* Flush the instruction stream. */
      tokenize_clear_stream ();
      tokenize_reset ();

      ipval = word_get_integer(ipreg);
      machine_pre_execute (ipval);

      token = tokenize_next_token (&token_info);

      /* IP = IP + instruction length. */
      ipval = ipval + XSM_INSTRUCTION_SIZE;
      word_store_integer (ipreg, ipval);

      if (token != TOKEN_INSTRUCTION)
      {
         machine_register_exception("The simulator has encountered an illegal instruction", EXP_ILLINSTR);
      }

      opcode = machine_get_opcode(token_info.str);

      if (XSM_ILLINSTR == opcode)
      {
         machine_register_exception("The instruction is not available in this architecture", EXP_ILLINSTR);
      }

      if (machine_instr_req_privilege(opcode) == PRIVILEGE_KERNEL &&
         machine_get_mode() == PRIVILEGE_USER)
      {
         machine_register_exception("This instruction requires more privilege.", EXP_ILLINSTR);
      }

      if (XSM_HALT == machine_execute_instruction (opcode))
         break;

      /* TODO: Post executing instruction. */
      machine_post_execute ();
   }

   return TRUE;
}

/* Return the memory range accessed by the CPU for the last operation. */
void
machine_get_mem_access (int _output_ *mem_low, int _output_ *mem_high)
{
   *mem_low = _thecpu.mem_low;
   *mem_high = _thecpu.mem_high;
}

int
machine_handle_exception()
{
   char *message;
   int code, mode;
   int curr_ip;

   xsm_word *reg_eip, *reg_epn, *reg_ec, *reg_ema;

   /* Get the details about the exception. */
   mode = machine_get_mode ();
   code = exception_code ();
   message = exception_message();

   /* Get the exception registers. */
   reg_eip = registers_get_register("EIP");
   reg_epn = registers_get_register("EPN");
   reg_ec = registers_get_register("EC");
   reg_ema = registers_get_register("EMA");

   /* After the fetch, IP = IP + 2, undo.  */
   curr_ip = word_get_integer(registers_get_register("IP")) - 2;
   word_store_integer(reg_eip, curr_ip);

   switch(mode)
   {
      case EXP_ILLMEM:
         word_store_integer (reg_ema, exception_get_ma());
         break;

      case EXP_PAGEFAULT:
         word_store_integer (reg_epn, exception_get_epn());
         break;
   }

   if (PRIVILEGE_USER == mode)
   {
      machine_execute_interrupt_do(XSM_INTERRUPT_EXHANDLER);
      return XSM_SUCCESS;
   }

   fprintf (stderr, "%s: System halted.\n", message);
   /* TODO May print the machine status if required. */
   fprintf (stderr, "Trace:\nEIP %s\tEPN %s\t EC %s\t EMA %s\n",
      word_get_string(reg_eip), word_get_string(reg_epn), word_get_string(reg_ec), word_get_string(reg_ema));
   return XSM_FAILURE;
}

void
machine_post_execute ()
{
   /* Tick the timers. */
   _thecpu.timer--;

   if (_thecpu.timer == 0)
   {
      machine_execute_interrupt(XSM_INTERRUPT_TIMER);
      _thecpu.timer = _theoptions.timer;
   }
   /* Handle the disk interrupt. */
   if (_thecpu.disk_state == XSM_DISK_BUSY)
   {
      _thecpu.disk_wait--;

      if (_thecpu.disk_wait == 0)
      {
         if (XSM_DISKOP_LOAD == _thecpu.disk_op.operation)
         {
            machine_execute_load_do (_thecpu.disk_op.dest_page, _thecpu.disk_op.src_block);
            machine_execute_interrupt_do(XSM_INTERRUPT_DISK);
         }
         else if (XSM_DISKOP_STORE == _thecpu.disk_op.operation)
         {
            machine_execute_store_do (_thecpu.disk_op.dest_page, _thecpu.disk_op.src_block);
            machine_execute_interrupt_do(XSM_INTERRUPT_DISK);
         }

         _thecpu.disk_state = XSM_DISK_IDLE;
      }
   }<commit_msg>timer bug<commit_after>#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "machine.h"
#include "tokenize.h"
#include "exception.h"

static
xsm_cpu _thecpu;

static
xsm_options _theoptions;

const char *instructions[]=
{
   "MOV",
   "ADD",
   "SUB",
   "MUL", 
   "DIV",
   "MOD",
   "INR",
   "DCR",
   "LT",
   "GT", 
   "EQ",
   "NE", 
   "GE", 
   "LE",
   "JZ",
   "JNZ",
   "JMP",
   "PUSH",
   "POP",
   "CALL",
   "RET",
   "BRKP",
   "INT",
   
   "LOADI",
   "LOAD",
   "STORE",
   "ENCRYPT",
   "BACKUP",
   "RESTORE",
   "PORT",
   "IN",
   "INI",
   "OUT",
   "IRET",
   "HALT"
};

int
machine_init (xsm_options *options)
{
   xsm_word *ipreg;

   _theoptions = *options;

   /* Set up the registers. */
   if (!registers_init ())
      return XSM_FAILURE;

   if (!memory_init())
      return XSM_FAILURE;

   if (!debug_init())
      return FALSE;

   /* Initialize machine. */
   word_store_string(memory_get_word(0), "LOAD 1, 0");
   word_store_string(memory_get_word(2), "JMP 512");

   disk_read_block(memory_get_page(1), 0);

   /* Set up IP.. */
   ipreg = machine_get_ipreg ();
   word_store_integer(ipreg, 512);

   machine_set_mode(PRIVILEGE_KERNEL);

   /* The disk and console is idle.*/
   _thecpu.console_state = XSM_CONSOLE_IDLE;
   _thecpu.disk_state = XSM_DISK_IDLE;

   return XSM_SUCCESS;
}

int
machine_get_opcode (const char* instr)
{
   int i;
   
   for (i = 0; i < XSM_INSTRUCTION_COUNT; ++i)
   {
      if (!strcasecmp(instr, instructions[i]))
         return i;
   }
   
   return XSM_ILLINSTR;
}

/* When the lexer calls, serve him with the instruction to execute.
 * Here we have a problem. The read_bytes need to be of type yy_size_t.
 * If this argument raises a warning, then investigate what yy_size_t means,
 * and change it here accordingly.
 */
 
int
machine_serve_instruction (char _output_ *buffer, unsigned long _output_ *read_bytes, int _input_ max)
{
   int ip_val, i;
   xsm_word *ip_reg;
   int bytes_to_read;
   xsm_word *instr_mem;

   bytes_to_read = XSM_INSTRUCTION_SIZE * XSM_WORD_SIZE;

   ip_reg = machine_get_ipreg();
   ip_val = word_get_integer(ip_reg);

   ip_val = machine_translate_address(ip_val, FALSE);
   instr_mem = machine_memory_get_word(ip_val);

   memcpy (buffer, instr_mem, bytes_to_read);

   /* Trim. */
   for (i = 0; i < bytes_to_read; ++i)
   {
      if (buffer[i] == '\0')
         buffer[i] = ' ';
   }

   buffer[bytes_to_read - 1] = '\0';
   *read_bytes = bytes_to_read;

   return TRUE;
}

/* Raises an exception. This function never returns. */
void
machine_register_exception (char* message, int code)
{
   int mode;

   mode = machine_get_mode();
   exception_set(message, code, mode);
   /* Abandon ship! Abandon ship! */
   longjmp (_thecpu.h_exp_point, XSM_EXCEPTION_OCCURED);
}

xsm_word*
machine_memory_get_word (int address)
{
   xsm_word *result;

   result = memory_get_word(address);

   if (NULL == result)
   {
      /* Doomsday! */
      exception_set_ma(address);
      machine_register_exception("Illegal memory access", EXP_ILLMEM);
   }

   return result;
}

xsm_word *
machine_get_ipreg ()
{
   return registers_get_register("IP");
}

xsm_word *
machine_get_spreg ()
{
   return registers_get_register("SP");
}

void
machine_pre_execute(int ip_val)
{
   /* Clear the potential watchpoint trigger. */
   _thecpu.mem_low = -1;

   /* If debugging was requested, activate the debug command line. */
   if (_theoptions.debug)
   {
      debug_next_step (ip_val);
   }
}

int
machine_instr_req_privilege (int opcode)
{
   if (opcode >= TOKEN_KERN_LOW && TOKEN_KERN_HIGH >= opcode)
      return PRIVILEGE_KERNEL;
   return PRIVILEGE_USER;
}

int
machine_run ()
{
   int token, opcode;
   YYSTYPE token_info;
   xsm_word *ipreg;
   int ipval;
   int exp_occured;

   ipreg = machine_get_ipreg ();

   while (TRUE){
      /* Set the exception point. */
      exp_occured = setjmp (_thecpu.h_exp_point);

      if (exp_occured == XSM_EXCEPTION_OCCURED)
      {
         if (XSM_SUCCESS != machine_handle_exception())
            break;
      }

      /* Flush the instruction stream. */
      tokenize_clear_stream ();
      tokenize_reset ();

      ipval = word_get_integer(ipreg);
      machine_pre_execute (ipval);

      token = tokenize_next_token (&token_info);

      /* IP = IP + instruction length. */
      ipval = ipval + XSM_INSTRUCTION_SIZE;
      word_store_integer (ipreg, ipval);

      if (token != TOKEN_INSTRUCTION)
      {
         machine_register_exception("The simulator has encountered an illegal instruction", EXP_ILLINSTR);
      }

      opcode = machine_get_opcode(token_info.str);

      if (XSM_ILLINSTR == opcode)
      {
         machine_register_exception("The instruction is not available in this architecture", EXP_ILLINSTR);
      }

      if (machine_instr_req_privilege(opcode) == PRIVILEGE_KERNEL &&
         machine_get_mode() == PRIVILEGE_USER)
      {
         machine_register_exception("This instruction requires more privilege.", EXP_ILLINSTR);
      }

      if (XSM_HALT == machine_execute_instruction (opcode))
         break;

      /* TODO: Post executing instruction. */
      machine_post_execute ();
   }

   return TRUE;
}

/* Return the memory range accessed by the CPU for the last operation. */
void
machine_get_mem_access (int _output_ *mem_low, int _output_ *mem_high)
{
   *mem_low = _thecpu.mem_low;
   *mem_high = _thecpu.mem_high;
}

int
machine_handle_exception()
{
   char *message;
   int code, mode;
   int curr_ip;

   xsm_word *reg_eip, *reg_epn, *reg_ec, *reg_ema;

   /* Get the details about the exception. */
   mode = machine_get_mode ();
   code = exception_code ();
   message = exception_message();

   /* Get the exception registers. */
   reg_eip = registers_get_register("EIP");
   reg_epn = registers_get_register("EPN");
   reg_ec = registers_get_register("EC");
   reg_ema = registers_get_register("EMA");

   /* After the fetch, IP = IP + 2, undo.  */
   curr_ip = word_get_integer(registers_get_register("IP")) - 2;
   word_store_integer(reg_eip, curr_ip);

   switch(mode)
   {
      case EXP_ILLMEM:
         word_store_integer (reg_ema, exception_get_ma());
         break;

      case EXP_PAGEFAULT:
         word_store_integer (reg_epn, exception_get_epn());
         break;
   }

   if (PRIVILEGE_USER == mode)
   {
      machine_execute_interrupt_do(XSM_INTERRUPT_EXHANDLER);
      return XSM_SUCCESS;
   }

   fprintf (stderr, "%s: System halted.\n", message);
   /* TODO May print the machine status if required. */
   fprintf (stderr, "Trace:\nEIP %s\tEPN %s\t EC %s\t EMA %s\n",
      word_get_string(reg_eip), word_get_string(reg_epn), word_get_string(reg_ec), word_get_string(reg_ema));
   return XSM_FAILURE;
}

void
machine_post_execute ()
{
   /* Tick the timers. */
   _thecpu.timer--;

   if (_thecpu.timer == 0)
   {
      machine_execute_interrupt_do(XSM_INTERRUPT_TIMER);
      _thecpu.timer = _theoptions.timer;
   }
   /* Handle the disk interrupt. */
   if (_thecpu.disk_state == XSM_DISK_BUSY)
   {
      _thecpu.disk_wait--;

      if (_thecpu.disk_wait == 0)
      {
         if (XSM_DISKOP_LOAD == _thecpu.disk_op.operation)
         {
            machine_execute_load_do (_thecpu.disk_op.dest_page, _thecpu.disk_op.src_block);
            machine_execute_interrupt_do(XSM_INTERRUPT_DISK);
         }
         else if (XSM_DISKOP_STORE == _thecpu.disk_op.operation)
         {
            machine_execute_store_do (_thecpu.disk_op.dest_page, _thecpu.disk_op.src_block);
            machine_execute_interrupt_do(XSM_INTERRUPT_DISK);
         }

         _thecpu.disk_state = XSM_DISK_IDLE;
      }
   }
{'fraction_non_alphanumeric': 0.1171153468264885, 'fraction_numerical': 0.002882033143381149, 'mean_word_length': 2.9843423799582465, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1133784', 'n_tokens_mistral': 5656, 'n_tokens_neox': 5492, 'n_words': 1161}