#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "fedex.h"

/* ----------------------------------------------------- */

void FEDEX (int debug)
{
  struct codeData instruction = fetchInstruction ();
  char* code = instruction.opcode;
  char* op1 =  instruction.oper1;
  char* op2 =  instruction.oper2;
  char* op3 =  instruction.oper3;

  if (debug)
    printf ("%s\n",code);

  if (strcmp(code,"HALT") == 0)
    exit (EXIT_SUCCESS);

  else if (strcmp(code,"I2F") == 0)
  {
    if ((!isIreg(op2)) || (!isFreg(op1)))
    {
      printf ("invalid I2F operands: %s,%s\n",op1,op2);
      exit (EXIT_FAILURE);
    }
    klunk* src_address = addrReg(op2);
    klunk* dst_address = addrReg(op1);
    *dst_address =
      flt2klunk ((flt64)(klunk2int(*src_address)));
  }
  else if (strcmp(code,"F2I") == 0)
  {
    if ((!isFreg(op2)) || (!isIreg(op1)))
    {
      printf ("invalid F2I operands: %s,%s\n",op1,op2);
      exit (EXIT_FAILURE);
    }
    klunk* src_address = addrReg(op2);
    klunk* dst_address = addrReg(op1);
    *dst_address =
      int2klunk ((int64)(klunk2flt(*src_address)));
  }

  else if (strcmp(code,"LDA") == 0)
  {
    if (op2[0] != '=')
    {
      printf ("invalid LDA second operand: %s\n",op2);
      exit (EXIT_FAILURE);
    }
    if (isIreg(op1))
    {
      klunk* reg = addrReg(op1);
      char* memLabel = op2+1;
      long long loc = memoryAddress (memLabel);
      if (loc == -1)
      {
        printf ("invalid LDA second operand: %s\n",op2);
        exit (EXIT_FAILURE);
      }
      *reg = loc;
    }
    else
    {
      printf ("invalid LDA first operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
  }

  else if (strcmp(code,"LDR") == 0)
  {
    if (!isIreg(op2))
    {
      printf ("invalid LDR second operand: %s\n",op2);
      exit (EXIT_FAILURE);
    }
    klunk* src_address = addrReg(op2);
    klunk* dst_address;
    if (isIreg(op1) || isFreg(op1))
      dst_address = addrReg(op1);
    else
    {
      printf ("invalid LDR first operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    *dst_address = peek(*src_address);
  }
  else if (strcmp(code,"STR") == 0)
  {
    if (!isIreg(op2))
    {
      printf ("invalid STR second operand: %s\n",op2);
      exit (EXIT_FAILURE);
    }
    klunk* dst_address = addrReg(op2);
    klunk* src_address;
    if (isIreg(op1) || isFreg(op1))
      src_address = addrReg(op1);
    else
    {
      printf ("invalid STR first operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    poke (*dst_address,*src_address);
  }

  else if (strcmp(code,"MOV") == 0)
  {
    klunk* dst_address;
    klunk* src_address;
    if (isIreg(op1) || isFreg(op1))
      dst_address = addrReg(op1);
    else
    {
      printf ("invalid MOV first operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    if (isIreg(op2) || isFreg(op2))
      src_address = addrReg(op2);
    else
    {
      printf ("invalid MOV second operand: %s\n",op2);
      exit (EXIT_FAILURE);
    }
    *dst_address = *src_address;
  }

  else if (strcmp(code,"MOVI") == 0)
  {
    klunk* dst_address;
    if (isIreg(op1) || isFreg(op1))
      dst_address = addrReg(op1);
    else
    {
      printf ("invalid MOVI first operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk imm_value = literal2klunk (op2);
    *dst_address = imm_value;
  }

  else if (strcmp(code,"PUSH") == 0)
  {
    if (isIreg(op1) || isFreg(op1))
    {
      (*addrReg("SP"))--;
      poke (*addrReg("SP"),*addrReg(op1));
    }
    else
    {
      printf ("invalid PUSH operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
  }
  else if (strcmp(code,"POP") == 0)
  {
    if (isIreg(op1) || isFreg(op1))
    {
      *addrReg(op1) = peek (*addrReg("SP"));
      (*addrReg("SP"))++;
    }
    else
    {
      printf ("invalid POP operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
  }

  else if (strcmp(code,"ADD") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid ADD operands: %s, %s, %s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 =
      int2klunk ((klunk2int) (*address2) +
                 (klunk2int) (*address3));
  }
  else if (strcmp(code,"SUB") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid SUB operands: %s, %s, %s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 =
      int2klunk ((klunk2int) (*address2) -
                 (klunk2int) (*address3));
  }
  else if (strcmp(code,"MUL") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid mul operands: %s, %s, %s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 =
      int2klunk ((klunk2int) (*address2) *
                 (klunk2int) (*address3));
  }
  else if (strcmp(code,"DIV") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid DIV operands: %s, %s, %s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    if ((klunk2int)(*address3) == 0)
    {
      printf ("division by 0 not permitted!\n");
      exit (EXIT_FAILURE);
    }
    *address1 =
      int2klunk ((klunk2int) (*address2) /
                 (klunk2int) (*address3));
  }
  else if (strcmp(code,"MOD") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid MOD operands: %s, %s, %s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    if ((klunk2int)(*address3) == 0)
    {
      printf ("division by 0 not permitted!\n");
      exit (EXIT_FAILURE);
    }
    *address1 =
      int2klunk ((klunk2int) (*address2) %
                 (klunk2int) (*address3));
  }
  else if (strcmp(code,"NEG") == 0)
  {
    if (!isIreg(op1))
    {
      printf ("invalid NEG operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk* address = addrReg(op1);
    *address = int2klunk (- (*address));
  }

  else if (strcmp(code,"UADD") == 0)
  {
    if ((!isIreg(op1)) || (!isIreg(op2)) || (!isIreg(op3)))
    {
      printf ("invalid UADD operands: %s, %s, $s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 = *address2 + *address3;
  }
  else if (strcmp(code,"USUB") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid USUB operands: %s, %s, $s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 = *address2 - *address3;
  }
  else if (strcmp(code,"UMUL") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid UMUL operands: %s, %s, $s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 = *address2 * *address3;
  }
  else if (strcmp(code,"UDIV") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid UDIV operands: %s, %s, $s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    if (*address3 == 0ULL)
    {
      printf ("division by 0 not permitted!\n");
      exit (EXIT_FAILURE);
    }
    *address1 = *address2 / *address3;
  }
  else if (strcmp(code,"UMOD") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid UMOD operands: %s, %s, %s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    if (*address3 == 0ULL)
    {
      printf ("division by 0 not permitted!\n");
      exit (EXIT_FAILURE);
    }
    *address1 = *address2 % *address3;
  }

  else if (strcmp(code,"FADD") == 0)
  {
    if ((!isFreg(op1)) ||
        (!isFreg(op2)) ||
        (!isFreg(op3)))
    {
      printf ("invalid FADD operands: %s, %s, $s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 =
      flt2klunk (klunk2flt (*address2) +
                 klunk2flt (*address3));
  }
  else if (strcmp(code,"FSUB") == 0)
  {
    if ((!isFreg(op1)) ||
        (!isFreg(op2)) ||
        (!isFreg(op3)))
    {
      printf ("invalid FSUB operands: %s, %s, $s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 =
      flt2klunk (klunk2flt (*address2) -
                 klunk2flt (*address3));
  }
  else if (strcmp(code,"FMUL") == 0)
  {
    if ((!isFreg(op1)) ||
        (!isFreg(op2)) ||
        (!isFreg(op3)))
    {
      printf ("invalid FMUL operands: %s, %s, $s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 =
      flt2klunk (klunk2flt (*address2) *
                 klunk2flt (*address3));
  }
  else if (strcmp(code,"FDIV") == 0)
  {
    if ((!isFreg(op1)) ||
        (!isFreg(op2)) ||
        (!isFreg(op3)))
    {
      printf ("invalid FDIV operands: %s, %s, $s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    if ((klunk2flt)(*address3) == 0.0)
    {
      printf ("division by 0 not permitted!\n");
      exit (EXIT_FAILURE);
    }
    *address1 =
      flt2klunk (klunk2flt (*address2) /
                 klunk2flt (*address3));
  }
  else if (strcmp(code,"FNEG") == 0)
  {
    if (!isFreg(op1))
    {
      printf ("invalid FNEG operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk* address = addrReg(op1);
    *address = flt2klunk (- klunk2flt(*address));
  }

  else if (strcmp(code,"LAND") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid LAND operands: %s, %s, %s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 = *address2 && *address3;
  }
  else if (strcmp(code,"LOR") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid LOR operands: %s, %s, %s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 = *address2 || *address3;
  }
  else if (strcmp(code,"LXOR") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid LXOR operands: %s, %s, %s\n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 =
      ((*address2 && (!*address3)) ||
      ((!*address2) && *address3));
  }
  else if (strcmp(code,"LNOT") == 0)
  {
    if (!isIreg(op1))
    {
      printf ("invalid LNOT operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk* address = addrReg(op1);
    *address = !*address;
  }

  else if (strcmp(code,"BAND") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid BAND operands: %s, %s, %s/n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 = *address2 & *address3;
  }
  else if (strcmp(code,"BOR") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid BOR operands: %s, %s, %s/n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 = *address2 | *address3;
  }
  else if (strcmp(code,"BXOR") == 0)
  {
    if ((!isIreg(op1)) ||
        (!isIreg(op2)) ||
        (!isIreg(op3)))
    {
      printf ("invalid BXOR operands: %s, %s, %s/n",
              op1,op2,op3);
      exit (EXIT_FAILURE);
    }
    klunk* address1 = addrReg(op1);
    klunk* address2 = addrReg(op2);
    klunk* address3 = addrReg(op3);
    *address1 = *address2 ^ *address3;
  }
  else if (strcmp(code,"BNOT") == 0)
  {
    if (!isIreg(op1))
    {
      printf ("invalid BNOT operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk* address = addrReg(op1);
    *address = ~*address;
  }

  else if (strcmp(code,"CMP") == 0)
  {
    if ((isIreg(op1)) && (isIreg(op2)))
    {
      klunk* address1 = addrReg(op1);
      klunk* address2 = addrReg(op2);
      int64 diff =
        klunk2int(*address1) - klunk2int(*address2);
      if (diff == 0LL)
        setEQ ();
      else if (diff > 0LL)
        setGT ();
      else // (diff < 0LL)
        setLT ();
    }
    else
    {
      printf ("invalid CMP operands: %s, %s\n");
      exit (EXIT_FAILURE);
     }
  }
  else if (strcmp(code,"UCMP") == 0)
  {
    if ((isIreg(op1)) && (isIreg(op2)))
    {
      klunk* address1 = addrReg(op1);
      klunk* address2 = addrReg(op2);
      if (*address1 == *address2)
        setEQ ();
      else if (*address1 > *address2)
        setGT ();
      else // (*address1 < *address2)
        setLT ();
    }
    else
    {
      printf ("invalid UCMP operands: %s, %s\n");
      exit (EXIT_FAILURE);
     }
  }
  else if (strcmp(code,"FCMP") == 0)
  {
    if ((isFreg(op1)) && (isFreg(op2)))
    {
      klunk* address1 = addrReg(op1);
      klunk* address2 = addrReg(op2);
      flt64 diff =
        klunk2flt(*address1) - klunk2flt(*address2);
      if (diff == 0.0)
        setEQ ();
      else if (diff > 0.0)
        setGT ();
      else // (diff < 0.0)
        setLT ();
    }
    else
    {
      printf ("invalid FCMP operands: %s, %s\n");
      exit (EXIT_FAILURE);
     }
  }

  else if (strcmp(code,"JMP") == 0)
  {
    long long pc = labelAddress (op1);
    if (pc < 0LL)
    {
      printf ("undefined label: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    else
      setPC (pc);
  }

  else if (strcmp(code,"JEQ") == 0)
  {
    long long pc = labelAddress (op1);
    if (pc < 0LL)
    {
      printf ("undefined label: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    if (EQ)
      setPC (pc);
  }
  else if (strcmp(code,"JGT") == 0)
  {
    long long pc = labelAddress (op1);
    if (pc < 0LL)
    {
      printf ("undefined label: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    if (GT)
      setPC (pc);
  }
  else if (strcmp(code,"JLT") == 0)
  {
    long long pc = labelAddress (op1);
    if (pc < 0LL)
    {
      printf ("undefined label: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    if (LT)
      setPC (pc);
  }
  else if (strcmp(code,"JNE") == 0)
  {
    long long pc = labelAddress (op1);
    if (pc < 0LL)
    {
      printf ("undefined label: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    if (!EQ)
      setPC (pc);
  }
  else if (strcmp(code,"JGE") == 0)
  {
    long long pc = labelAddress (op1);
    if (pc < 0LL)
    {
      printf ("undefined label: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    if (!LT)
      setPC (pc);
  }
  else if (strcmp(code,"JLE") == 0)
  {
    long long pc = labelAddress (op1);
    if (pc < 0LL)
    {
      printf ("undefined label: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    if (!GT)
      setPC (pc);
  }

  else if (strcmp(code,"ROL") == 0)
  {
    if (!isIreg(op1))
    {
      printf ("invalid ROL register: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk* address = addrReg(op1);
    char* imm = op2;
    int shift = atoi(imm) & 0X3F;
    klunk parta = *address << shift;
    klunk partb = *address >> (64-shift);
    *address = parta | partb;
  }
  else if (strcmp(code,"ROR") == 0)
  {
    if (!isIreg(op1))
    {
      printf ("invalid ROR register: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk* address = addrReg(op1);
    char* imm = op2;
    int shift = atoi(imm) & 0X3F;
    klunk parta = *address >> shift;
    klunk partb = *address << (64-shift);
    *address = parta | partb;
  }
  else if (strcmp(code,"SHL") == 0)
  {
    if (!isIreg(op1))
    {
      printf ("invalid SHL register: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk* address = addrReg(op1);
    char* imm = op2;
    int shift = atoi(imm) & 0X3F;
    *address = *address << shift;
  }
  else if (strcmp(code,"SHR") == 0)
  {    if (!isIreg(op1))
    {
      printf ("invalid SHR register: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk* address = addrReg(op1);
    char* imm = op2;
    int shift = atoi(imm) & 0X3F;
    *address = *address >> shift;
  }
  else if (strcmp(code,"ASHL") == 0)
  {    if (!isIreg(op1))
    {
      printf ("invalid ASHL register: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    klunk* address = addrReg(op1);
    char* imm = op2;
    int shift = atoi(imm) & 0X3F;
    *address = *address << shift;
  }
  else if (strcmp(code,"ASHR") == 0)
  {
    if (!isIreg(op1))
    {
      printf ("invalid ROL register: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    // note: bit pattern must be considered as
    // a signed and not an unsigned value
    int64* address = (int64*)(addrReg(op1));
    char* imm = op2;
    int shift = atoi(imm) & 0X3F;
    *address = *address >> shift;
  }

  else if (strcmp(code,"CALL") == 0)
  {
    long long lbl = labelAddress (op1);
    *(addrReg("RP")) = PC;;
    setPC (lbl);
  }
  else if (strcmp(code,"RET") == 0)
  {
    long long ret = *(addrReg("RP"));
    if (ret >= 0)
      setPC (ret);
    else
      exit (EXIT_SUCCESS);
  }

  else if (strcmp(code,"INC") == 0)
  {
    if (!isIreg(op1))
    {
      printf ("invalid INC operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    (*(addrReg(op1)))++;
  }
  else if (strcmp(code,"DEC") == 0)
  {
    if (!isIreg(op1))
    {
      printf ("invalid DEC operand: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    (*(addrReg(op1)))--;
  }

  else if (strcmp(code,"MALLOC") == 0)
  {
    if ((!isIreg(op1)) || (!isIreg(op2)))
    {
      printf ("invalid MALLOC operands: %s, %s\n",op1,op2);
      exit (EXIT_FAILURE);
    }
    klunk* reg_addr = addrReg(op1);
    klunk no_klunks = *addrReg(op2);
    *reg_addr = *(addrReg("HP"));
    *(addrReg("HP")) += no_klunks;
  }
  else if (strcmp(code,"DALLOC") == 0)
  {
    if ((!isIreg(op1)) || (!isIreg(op2)))
    {
      printf ("invalid DALLOC operands: %s, %s\n",op1,op2);
      exit (EXIT_FAILURE);
    }
    else
    {
       // yes, do nothing!
    }
  }

  else if (strcmp(code,"NOP") == 0)
    return;

  else if (strcmp(code,"GET") == 0)
  {
    (*(addrReg("SP")))--;
    char* fmt = op1;
    if (strcmp(fmt,"INT") == 0)
    {
      int64 data;
      scanf ("%lld",&data);
      poke (*(addrReg("SP")),int2klunk(data));
    }
    else if (strcmp(fmt,"FLT") == 0)
    {
      flt64 data;
      scanf ("%lf",&data);
      poke (*(addrReg("SP")),flt2klunk(data));
    }
    else if (strcmp(fmt,"CHR") == 0)
    {
      chr64 data;
      scanf ("%c",&data);
      poke (*(addrReg("SP")),chr2klunk(data));
    }
    else if (strcmp(fmt,"STR") == 0)
    {
      char* data = (char*) malloc (LITERAL_SIZE);
      scanf ("%s",data);
      printf ("%s\n",data);
      poke (*(addrReg("SP")),str2klunk(data));
    }
    else
    {
      printf ("invalid format entry: %s\n", op1);
      exit (EXIT_FAILURE);
    }
  }
  else if (strcmp(code,"GETLN") == 0)
  {
    while (getchar()!='\n');
  }

  else if (strcmp(code,"PUT") == 0)
  {
    klunk data = peek (*(addrReg("SP")));
    char* fmt = op1;
    if (strcmp(fmt,"INT") == 0)
      show_int (data);
    else if (strcmp(fmt,"FLT") == 0)
      show_flt (data);
    else if (strcmp(fmt,"CHR") == 0)
      show_chr (data);
    else if (strcmp(fmt,"STR") == 0)
      show_str (data);
    else if ((strcmp(fmt,"HEX") == 0) ||
             (strcmp(fmt,"PTR") == 0))
      show_hex (data);
    else
    {
      printf ("invalid format entry: %s\n",op1);
      exit (EXIT_FAILURE);
    }
    (*(addrReg("SP")))++;
  }
  else if (strcmp(code,"PUTLN") == 0)
    printf ("\n");

  else
  {
    printf ("invalid instruction: %s\n",code);
    exit (EXIT_FAILURE);
  }
}

/* ----------------------------------------------------- */
