Our server costs ~$56 per month to run. Please consider donating or becoming a Patron to help keep the site running. Help us gain new members by following us on Twitter and liking our page on Facebook!
Current time: November 23, 2024, 7:13 pm

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
PicoBlaze Simulator in JavaScript
#52
RE: PicoBlaze Simulator in JavaScript
So, @bennyboy , I have tried to convert that huge if-else to switch-case. However, the simulator stopped working then. Can you figure out what is going on?
Code:
"use strict";
function simulateOneInstruction() {
  try {
    PC = PC %
         4096; // If you are at the end of a program, and there is no "return"
    // there, jump to the beginning of the program. I think that's
    // how PicoBlaze behaves, though I haven't tried it.
    if (breakpoints.includes(machineCode[PC].line)) {
      alert("Reached breakpoint on the line #" + machineCode[PC].line + ".");
      if (playing)
        clearInterval(simulationThread);
      playing = false;
      document.getElementById("fastForwardButton").disabled = false;
      document.getElementById("singleStepButton").disabled = false;
      document.getElementById("UART_INPUT").disabled = false;
      document.getElementById("playImage").style.display = "inline";
      document.getElementById("pauseImage").style.display = "none";
    }
    document.getElementById("PC_label_" + formatAsAddress(PC)).innerHTML = "";
    const currentDirective = parseInt(machineCode[PC].hex, 16);
    // "bennyboy" from "atheistforums.org" thinks my program can be
    // speeded up by using a switch-case instead of the large if-else (that a
    // switch-case would compile into a more efficient assembly code), so it
    // would be interesting to investigate whether that's true:
    // https://atheistforums.org/thread-61911-post-2112817.html#pid2112817
    let port, firstRegister, secondRegister, firstValue, secondValue, result,
        value;
    switch (currentDirective & 0xff000) {
    //    if ((currentDirective & 0xff000) === 0x00000) {
    case 0x00000:
      // LOAD register,register
      registers[regbank][parseInt(machineCode[PC].hex[2], 16)] =
          registers[regbank][parseInt(machineCode[PC].hex[3], 16)];
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x01000) {
      break;
    case 0x01000:
      // LOAD register,constant
      registers[regbank][parseInt(machineCode[PC].hex[2], 16)] =
          parseInt(machineCode[PC].hex.substr(3), 16);
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x17000) {
      break;
    case 0x17000:
      // STAR register,constant ;Storing a constant into an inactive register
      registers[!regbank | 0 /*That is how you convert a boolean to an integer
                                        in JavaScript.*/
      ][parseInt(machineCode[PC].hex[2], 16)] =
          parseInt(machineCode[PC].hex.substr(3), 16);
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x16000) {
      break;
    case 0x16000:
      // STAR register,register ;Copying from an active register into an
      // inactive one.
      registers[!regbank | 0][parseInt(machineCode[PC].hex[2], 16)] =
          registers[regbank][parseInt(machineCode[PC].hex[3], 16)];
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x2e000) {
      break;
    case 0x2e000:
      // STORE register,(register) ;Store the first register at the memory
      // location where the second register points to.
      memory[registers[regbank][parseInt(machineCode[PC].hex[3], 16)]] =
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)];
      document
          .getElementById(
              "memory_" +
              formatAsByte(
                  registers[regbank][parseInt(machineCode[PC].hex[3], 16)]))
          .innerHTML = formatAsByte(
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)]);
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x2f000) {
      break;
    case 0x2f000:
      // STORE register,memory_address ;Copy a register onto a memory address.
      memory[parseInt(machineCode[PC].hex.substr(3), 16)] =
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)];
      document.getElementById("memory_" + machineCode[PC].hex.substr(3))
          .innerHTML = formatAsByte(
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)]);
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x0a000) {
      break;
    case 0x0a000:
      // FETCH register,(register) ;Dereference the pointer in the second
      // register.
      registers[regbank][parseInt(machineCode[PC].hex[2], 16)] =
          memory[registers[regbank][parseInt(machineCode[PC].hex[3], 16)]];
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x0b000) {
      break;
    case 0x0b000:
      // FETCH register,memory_address ;Copy the value at memory_address to the
      // register.
      registers[regbank][parseInt(machineCode[PC].hex[2], 16)] =
          memory[parseInt(machineCode[PC].hex.substr(3), 16)];
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x08000) {
      break;
    case 0x08000:
      // INPUT register,(register) ;Read a byte from a port specified by a
      // register.
      /*const*/ port = registers[regbank][parseInt(machineCode[PC].hex[3], 16)];
      if ((port === 2 || port === 3) && is_UART_enabled) {
        if (port === 3) {
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)] =
              document.getElementById("UART_INPUT")
                  .value.charCodeAt(currentlyReadCharacterInUART);
          currentlyReadCharacterInUART++;
        } else
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)] =
              currentlyReadCharacterInUART <
                      document.getElementById("UART_INPUT").value.length
                  ? 0b00001000 /*U_RX_D*/
                  : 0;
      } else
        registers[regbank][parseInt(machineCode[PC].hex[2], 16)] = parseInt(
            document
                .getElementById("input_" +
                                formatAsByte(registers[regbank][parseInt(
                                    machineCode[PC].hex[3], 16)]))
                .value,
            16);
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x09000) {
      break;
    case 0x09000:
      // INPUT register, port_number
      /*const*/ port = parseInt(machineCode[PC].hex.substr(3), 16);
      if ((port === 2 || port === 3) && is_UART_enabled) {
        if (port === 3) {
          // UART_RX_PORT
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)] =
              document.getElementById("UART_INPUT")
                  .value.charCodeAt(currentlyReadCharacterInUART);
          currentlyReadCharacterInUART++;
        } else if (port === 2)
          // UART_STATUS_PORT
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)] =
              currentlyReadCharacterInUART <
                      document.getElementById("UART_INPUT").value.length
                  ? 0b00001000 /*U_RX_D*/
                  : 0;
        else {
          alert(
              "Internal simulator error: The simulator got into a forbidden state!");
          stopSimulation();
        }
      } else
        registers[regbank][parseInt(machineCode[PC].hex[2], 16)] = parseInt(
            document.getElementById("input_" + machineCode[PC].hex.substr(3))
                .value,
            16);
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x2c000) {
      break;
    case 0x2c000:
      // OUTPUT register,(register) ;Output the result of the first register to
      // the port specified by the second register.
      /*const*/ port = registers[regbank][parseInt(machineCode[PC].hex[3], 16)];
      /*const*/ value =
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)];
      if ((port === 3 || port === 4) && is_UART_enabled) {
        if (port === 3)
          // UART_TX_PORT
          document.getElementById("UART_OUTPUT").innerText +=
              String.fromCharCode(value);
        else if (port === 4)
          // UART_RESET_PORT
          document.getElementById("UART_OUTPUT").innerText = "";
        else {
          alert(
              "Internal simulator error: The simulator got into a forbidden state!");
          stopSimulation();
        }
      } else
        output[registers[regbank][parseInt(machineCode[PC].hex[3], 16)]] =
            registers[regbank][parseInt(machineCode[PC].hex[2], 16)];
      displayOutput();
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x2d000) {
      break;
    case 0x2d000:
      // OUTPUT register, port_number
      /*const*/ port = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ value =
          registers[regbank][parseInt(machineCode[PC].hex[2], 16)];
      if ((port === 3 || port === 4) && is_UART_enabled) {
        if (port === 3)
          // UART_TX_PORT
          document.getElementById("UART_OUTPUT").innerText +=
              String.fromCharCode(value);
        else if (port === 4)
          // UART_RESET_PORT
          document.getElementById("UART_OUTPUT").innerText = "";
        else {
          alert(
              "Internal simulator error: The simulator got into a forbidden state!");
          stopSimulation();
        }
      } else {
        output[parseInt(machineCode[PC].hex.substr(3), 16)] =
            registers[regbank][parseInt(machineCode[PC].hex[2], 16)];
        displayOutput();
      }
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x2b000) {
      break;
    case 0x2b000:
      // OUTPUTK constant, port_number
      /*const*/ value = parseInt(machineCode[PC].hex.substr(2, 2), 16);
      /*const*/ port = parseInt(machineCode[PC].hex[4], 16);
      if ((port === 3 || port === 4) && is_UART_enabled) {
        if (port === 3)
          // UART_TX_PORT
          document.getElementById("UART_OUTPUT").innerText +=
              String.fromCharCode(value);
        else if (port === 4)
          // UART_RESET_PORT
          document.getElementById("UART_OUTPUT").innerText = "";
        else {
          alert(
              "Internal simulator error: The simulator got into a forbidden state!");
          stopSimulation();
        }
      } else {
        output[parseInt(machineCode[PC].hex[4], 16)] =
            parseInt(machineCode[PC].hex.substr(2, 2), 16);
        displayOutput();
      }
      PC++;
      /*    } else if (currentDirective === 0x37000) {
            // REGBANK A
            regbank = 0;
            PC++;
          } else if (currentDirective === 0x37001) {
            // REGBANK B
            regbank = 1;
            PC++;
      */
      break;
    case 0x37000:
      if (currentDirective % 2 === 0)
        regbank = 0;
      else
        regbank = 1;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x22000) {
      break;
    case 0x22000:
      // JUMP label
      PC = parseInt(machineCode[PC].hex.substr(2), 16);
      /*    } else if (machineCode[PC].hex.substr(0, 2) === "14" &&
                     machineCode[PC].hex.substr(3) === "80") {
            // HWBUILD register
            flagC[regbank] =
                1; // Have a better idea? We can't simulate all of what this
         directive
            // does, but we can simulate this part of it.
            PC++;
      */
      break;
    case 0x14000:
      if ((currentDirective & 0x000ff) === 0x00080) {
        flagC[regbank] = 1;
      }
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x10000) {
      break;
    case 0x10000:
      // ADD register, register
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      if ((firstValue + secondValue) % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (firstValue + secondValue > 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] += secondValue;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x11000) {
      break;
    case 0x11000:
      // ADD register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      if ((firstValue + secondValue) % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (firstValue + secondValue > 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] += secondValue;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x12000) {
      break;
    case 0x12000:
      // ADDCY register, register
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      /*const*/ result = firstValue + secondValue + flagC[regbank];
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result > 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x13000) {
      break;
    case 0x13000:
      // ADDCY register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ result = firstValue + secondValue + flagC[regbank];
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result > 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x18000) {
      break;
    case 0x18000:
      // SUB register, register
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      /*const*/ result = firstValue - secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result < 0)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x19000) {
      break;
    case 0x19000:
      // SUB register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ result = firstValue - secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result < 0)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x1a000) {
      break;
    case 0x1a000:
      // SUBCY register, register
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      /*const*/ result = firstValue - secondValue - flagC[regbank];
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result < 0)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x1b000) {
      break;
    case 0x1b000:
      // SUBCY register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ result = firstValue - secondValue - flagC[regbank];
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result < 0)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x03000) {
      break;
    case 0x03000:
      // AND register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ result = firstValue & secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result % 256 === 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x02000) {
      break;
    case 0x02000:
      // AND register, register
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      /*const*/ result = firstValue & secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result % 256 === 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x04000) {
      break;
    case 0x04000:
      // OR register, register
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      /*const*/ result = firstValue | secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result % 256 === 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x05000) {
      break;
    case 0x05000:
      // OR register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ result = firstValue | secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result % 256 === 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x06000) {
      break;
    case 0x06000:
      // XOR register, register
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      /*const*/ result = firstValue ^ secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result % 256 === 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x07000) {
      break;
    case 0x07000:
      // XOR register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ result = firstValue ^ secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result % 256 === 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      registers[regbank][firstRegister] = result;
      PC++;
      /*    } else if ((currentDirective & 0xff000) === 0x0c000 ||
                     (currentDirective & 0xff000) === 0x0e000) {
      */
      break;
    case 0x0c000:
    case 0x0e000:
      // TEST register, register ;The same as "AND", but does not store the
      // result (only the flags). I am not sure if there is a difference between
      // "0c" and "0e", they appear to be the same.
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      /*const*/ result = firstValue & secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result % 256 === 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      // registers[regbank][firstRegister] = result;
      PC++;
      /*    } else if ((currentDirective & 0xff000) === 0x0d000 ||
                     (currentDirective & 0xff000) === 0x0f000) {*/
      break;
    case 0x0d000:
    case 0x0f000:
      // TEST register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ result = firstValue & secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result % 256 === 255)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      // registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x1c000) {
      break;
    case 0x1c000:
      // COMPARE register, register
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      /*const*/ result = firstValue - secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result < 0)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      // registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x1d000) {
      break;
    case 0x1d000:
      // COMPARE register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ result = firstValue - secondValue;
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result < 0)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      // registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x1e000) {
      break;
    case 0x1e000:
      // COMPARECY register, register
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      /*const*/ result = firstValue - secondValue - flagC[regbank];
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result < 0)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      // registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x1f000) {
      break;
    case 0x1f000:
      // COMPARECY register, constant
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = parseInt(machineCode[PC].hex.substr(3), 16);
      /*const*/ result = firstValue - secondValue - flagC[regbank];
      if (result % 256 === 0)
        flagZ[regbank] = 1;
      else
        flagZ[regbank] = 0;
      if (result < 0)
        flagC[regbank] = 1;
      else
        flagC[regbank] = 0;
      // registers[regbank][firstRegister] = result;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x14000) {
      break;
    case 0x14000:
      // Bit-shifting operations...
      /*const*/ registerIndex = parseInt(machineCode[PC].hex[2], 16);
      /*let*/ registerValue = registers[regbank][registerIndex];
      console.log("DEBUG: Shifting the bits in register s" +
                  registerIndex.toString(16));
      const set_flags_after_shift_left = () => {
        flagC[regbank] = (registerValue > 255) | 0;
        flagZ[regbank] = (registerValue % 256 === 0) | 0;
      };
      const set_flags_before_shift_right = () => {
        flagC[regbank] = registerValue % 2;
        flagZ[regbank] = (Math.floor(registerValue / 2) === 0) | 0;
      };
      switch (machineCode[PC].hex.substr(3)) {
      case "06": // SL0
        registerValue <<= 1;
        set_flags_after_shift_left();
        break;
      case "07": // SL1
        registerValue = (registerValue << 1) + 1;
        set_flags_after_shift_left();
        break;
      case "04": // SLX
        registerValue = (registerValue << 1) + (registerValue % 2);
        set_flags_after_shift_left();
        break;
      case "00": // SLA
        registerValue = (registerValue << 1) + flagC[regbank];
        set_flags_after_shift_left();
        break;
      case "02": // RL
        registerValue = (registerValue << 1) + Math.floor(registerValue / 128);
        set_flags_after_shift_left();
        break;
      case "0e": // SR0
        set_flags_before_shift_right();
        registerValue >>= 1;
        break;
      case "0f": // SR1
        set_flags_before_shift_right();
        registerValue = (registerValue >> 1) + 128;
        break;
      case "0a": // SRX
        set_flags_before_shift_right();
        registerValue =
            (registerValue >> 1) + Math.floor(registerValue / 128) * 128;
        break;
      case "08": // SRA
        const oldFlagC = flagC[regbank];
        set_flags_before_shift_right();
        registerValue = (registerValue >> 1) + oldFlagC;
        break;
      case "0c": // RR
        set_flags_before_shift_right();
        registerValue = (registerValue >> 1) + 128 * (registerValue % 2);
        break;
      default:
        alert('The instruction "' + machineCode[PC].hex +
              '", assembled from line #' + machineCode[PC].line +
              ", hasn't been implemented yet, sorry about that!");
      }
      registers[regbank][registerIndex] = registerValue;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x32000) {
      break;
    case 0x32000:
      // JUMP Z, label
      if (flagZ[regbank])
        PC = parseInt(machineCode[PC].hex.substr(2), 16);
      else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x36000) {
      break;
    case 0x36000:
      // JUMP NZ, label
      if (!flagZ[regbank])
        PC = parseInt(machineCode[PC].hex.substr(2), 16);
      else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x3a000) {
      break;
    case 0x3a000:
      // JUMP C, label
      if (flagC[regbank])
        PC = parseInt(machineCode[PC].hex.substr(2), 16);
      else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x3e000) {
      break;
    case 0x3e000:
      // JUMP NC, label
      if (!flagC[regbank])
        PC = parseInt(machineCode[PC].hex.substr(2), 16);
      else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x26000) {
      break;
    case 0x26000:
      // JUMP@ (register, register) ; Jump to the address pointed by the
      // registers (something like function pointers, except that "return" won't
      // work).
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      PC = (firstValue % 16) * 256 + secondValue;
      //    } else if ((currentDirective & 0xff000) === 0x20000) {
      break;
    case 0x20000:
      // CALL functionName
      callStack.push(PC);
      PC = parseInt(machineCode[PC].hex.substr(2), 16);
      //    } else if ((currentDirective & 0xff000) === 0x30000) {
      break;
    case 0x30000:
      // CALL Z, functionName ; Call the function only if the Zero Flag is set.
      if (flagZ[regbank]) {
        callStack.push(PC);
        PC = parseInt(machineCode[PC].hex.substr(2), 16);
      } else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x34000) {
      break;
    case 0x34000:
      // CALL NZ, functionName ; Call the function only if the Zero Flag is not
      // set.
      if (!flagZ[regbank]) {
        callStack.push(PC);
        PC = parseInt(machineCode[PC].hex.substr(2), 16);
      } else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x38000) {
      break;
    case 0x38000:
      // CALL C, functionName ; Call the function only if the Carry Flag is set.
      if (flagC[regbank]) {
        callStack.push(PC);
        PC = parseInt(machineCode[PC].hex.substr(2), 16);
      } else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x3c000) {
      break;
    case 0x3c000:
      // CALL NC, functionName ; Call the function only if the Carry Flag is not
      // set.
      if (!flagC[regbank]) {
        callStack.push(PC);
        PC = parseInt(machineCode[PC].hex.substr(2), 16);
      } else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x24000) {
      break;
    case 0x24000:
      // CALL@ (register, register) ; Jump the function pointed by the function
      // pointer stored in the registers.
      /*const*/ firstRegister = parseInt(machineCode[PC].hex[2], 16);
      /*const*/ secondRegister = parseInt(machineCode[PC].hex[3], 16);
      /*const*/ firstValue = registers[regbank][firstRegister];
      /*const*/ secondValue = registers[regbank][secondRegister];
      callStack.push(PC);
      PC = (firstValue % 16) * 256 + secondValue;
      //    } else if ((currentDirective & 0xff000) === 0x25000) {
      break;
    case 0x25000:
      // RETURN
      if (callStack.length)
        PC = callStack.pop() + 1;
      else {
        if (playing)
          clearInterval(simulationThread);
        alert("The program exited!");
      }
      //    } else if ((currentDirective & 0xff000) === 0x31000) {
      break;
    case 0x31000:
      // RETURN Z ; Return from a function only if the Zero Flag is set.
      if (flagZ[regbank]) {
        if (callStack.length)
          PC = callStack.pop() + 1;
        else {
          if (playing)
            clearInterval(simulationThread);
          alert("The program exited!");
        }
      } else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x35000) {
      break;
    case 0x35000:
      // RETURN NZ ; Return from a function only if the Zero Flag is not set.
      if (!flagZ[regbank]) {
        if (callStack.length)
          PC = callStack.pop() + 1;
        else {
          if (playing)
            clearInterval(simulationThread);
          alert("The program exited!");
        }
      } else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x39000) {
      break;
    case 0x39000:
      // RETURN C ; Return from a function only if the Carry Flag is set.
      if (flagC[regbank]) {
        if (callStack.length)
          PC = callStack.pop() + 1;
        else {
          if (playing)
            clearInterval(simulationThread);
          alert("The program exited!");
        }
      } else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x3d000) {
      break;
    case 0x3d000:
      // RETURN NC ; Return from a function only if the Carry Flag is not set.
      if (!flagC[regbank]) {
        if (callStack.length)
          PC = callStack.pop() + 1;
        else {
          if (playing)
            clearInterval(simulationThread);
          alert("The program exited!");
        }
      } else
        PC++;
      //    } else if ((currentDirective & 0xff000) === 0x28000) {
      break;
    case 0x28000:
      // INTERRUPT ENABLE|DISABLE
      flagIE = machineCode[PC].hex[4] | 0;
      PC++;
      //    } else if ((currentDirective & 0xff000) === 0x29000) {
      break;
    case 0x29000:
      // RETURNI ENABLE|DISABLE
      flagIE = machineCode[PC].hex[4] | 0;
      if (callStack.length)
        PC = callStack.pop() + 1;
      else {
        if (playing)
          clearInterval(simulationThread);
        alert("The program exited!");
      }
      //    } else {
      break;
    default:
      alert(
          'Sorry about that, the simulator currently does not support the instruction "' +
          machineCode[PC].hex + '" (' + currentDirective + " & " + 0xff000 +
          " = " + (currentDirective & 0xff000) + "), assembled from line #" +
          machineCode[PC].line + ".");
      stopSimulation();
    }
    displayRegistersAndFlags();
    document.getElementById("PC_label_" + formatAsAddress(PC)).innerHTML =
        "-&gt;";
  } catch (error) {
    if (playing)
      clearInterval(simulationThread);
    alert("The simulator crashed! Error: " + error.message);
  }
}



Messages In This Thread
PicoBlaze Simulator in JavaScript - by FlatAssembler - November 5, 2020 at 9:34 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - November 14, 2020 at 3:35 pm
RE: PicoBlaze Simulator in JavaScript - by Sal - November 15, 2020 at 7:37 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - November 15, 2020 at 7:45 am
RE: PicoBlaze Simulator in JavaScript - by Sal - November 15, 2020 at 8:10 am
RE: PicoBlaze Simulator in JavaScript - by LadyForCamus - August 16, 2022 at 7:24 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 17, 2022 at 2:03 pm
RE: PicoBlaze Simulator in JavaScript - by BrianSoddingBoru4 - November 14, 2020 at 3:37 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - November 15, 2020 at 4:56 am
RE: PicoBlaze Simulator in JavaScript - by BrianSoddingBoru4 - November 15, 2020 at 4:59 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - November 15, 2020 at 8:11 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - December 20, 2020 at 3:12 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - September 7, 2021 at 5:52 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - February 8, 2022 at 1:20 pm
RE: PicoBlaze Simulator in JavaScript - by arewethereyet - February 8, 2022 at 1:23 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - February 8, 2022 at 1:33 pm
RE: PicoBlaze Simulator in JavaScript - by BrianSoddingBoru4 - February 8, 2022 at 2:38 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 7, 2022 at 7:24 am
RE: PicoBlaze Simulator in JavaScript - by arewethereyet - August 7, 2022 at 6:59 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 9, 2022 at 2:32 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 12, 2022 at 7:26 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 12, 2022 at 1:43 pm
RE: PicoBlaze Simulator in JavaScript - by HappySkeptic - August 12, 2022 at 9:24 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 12, 2022 at 1:41 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 15, 2022 at 6:55 am
RE: PicoBlaze Simulator in JavaScript - by arewethereyet - August 15, 2022 at 6:57 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 16, 2022 at 12:37 pm
RE: PicoBlaze Simulator in JavaScript - by HappySkeptic - August 12, 2022 at 4:37 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 15, 2022 at 6:48 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 12, 2022 at 6:34 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 15, 2022 at 6:44 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 15, 2022 at 9:35 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 16, 2022 at 12:38 pm
RE: PicoBlaze Simulator in JavaScript - by HappySkeptic - August 16, 2022 at 1:23 pm
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 16, 2022 at 5:39 pm
RE: PicoBlaze Simulator in JavaScript - by arewethereyet - August 15, 2022 at 6:47 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 17, 2022 at 2:02 pm
RE: PicoBlaze Simulator in JavaScript - by HappySkeptic - August 17, 2022 at 3:08 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 17, 2022 at 3:25 pm
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 17, 2022 at 3:25 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 17, 2022 at 3:30 pm
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 17, 2022 at 3:34 pm
RE: PicoBlaze Simulator in JavaScript - by HappySkeptic - August 18, 2022 at 11:06 am
RE: PicoBlaze Simulator in JavaScript - by HappySkeptic - August 17, 2022 at 3:57 pm
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 17, 2022 at 4:43 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 18, 2022 at 6:43 am
RE: PicoBlaze Simulator in JavaScript - by HappySkeptic - August 18, 2022 at 9:31 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 18, 2022 at 9:08 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 18, 2022 at 9:41 am
RE: PicoBlaze Simulator in JavaScript - by HappySkeptic - August 18, 2022 at 10:10 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 18, 2022 at 12:00 pm
RE: PicoBlaze Simulator in JavaScript - by HappySkeptic - August 18, 2022 at 12:12 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 19, 2022 at 9:41 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 19, 2022 at 9:44 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 21, 2022 at 5:31 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 21, 2022 at 10:10 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 21, 2022 at 11:05 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 21, 2022 at 7:12 pm
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 21, 2022 at 7:31 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 22, 2022 at 9:07 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 22, 2022 at 11:38 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 22, 2022 at 11:49 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 22, 2022 at 5:19 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 23, 2022 at 2:33 pm
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 23, 2022 at 6:04 pm
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 24, 2022 at 7:18 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 24, 2022 at 7:43 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 25, 2022 at 7:33 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - August 31, 2022 at 7:12 am
RE: PicoBlaze Simulator in JavaScript - by bennyboy - August 31, 2022 at 11:13 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - September 2, 2022 at 12:59 am
RE: PicoBlaze Simulator in JavaScript - by FlatAssembler - September 14, 2022 at 9:31 am

Possibly Related Threads...
Thread Author Replies Views Last Post
  A weird bug in the preprocessor of PicoBlaze Simulator in JavaScript FlatAssembler 81 9205 December 19, 2023 at 4:46 pm
Last Post: BrianSoddingBoru4
  Reformatting tools for JavaScript FlatAssembler 0 449 June 14, 2020 at 10:13 am
Last Post: FlatAssembler
  Anatomy of religion in RELIGION SIMULATOR game gravitysoftware 12 3370 February 8, 2015 at 12:52 pm
Last Post: c172
  Analysis of a Facebook social engineering/Javascript "hack" Autumnlicious 4 3492 March 2, 2011 at 9:29 am
Last Post: fr0d0



Users browsing this thread: 1 Guest(s)