/* 
   Pcm: a PC eMulator
   Copyright (C) 1992 Electronetics, Inc.  All rights reserved.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include "sim.h"

unsigned char *unk_op(ip)
unsigned char *ip; {
  pcmexit("unknown instruction 0x%x\n",*(ip-1));
}

unsigned char *(*ifun[256])() = {
/* 0x00 - 0x0f */
  i_00,   i_01,   i_02,   i_03,   i_04,   i_05,   i_06,   i_07,
  i_08,   i_09,   i_0a,   i_0b,   i_0c,   i_0d,   i_0e,   i_0f,
/* 0x10 - 0x1f */
  i_10,   i_11,   i_12,   i_13,   i_14,   i_15,   i_16,   i_17,
  i_18,   i_19,   i_1a,   i_1b,   i_1c,   i_1d,   i_1e,   i_1f,
/* 0x20 - 0x2f */
  i_20,   i_21,   i_22,   i_23,   i_24,   i_25,   i_26,   i_27,
  i_28,   i_29,   i_2a,   i_2b,   i_2c,   i_2d,   i_2e,   unk_op,
/* 0x30 - 0x3f */
  i_30,   i_31,   i_32,   i_33,   i_34,   i_35,   i_36,   i_37,
  i_38,   i_39,   i_3a,   i_3b,   i_3c,   i_3d,   i_3e,   unk_op,
/* 0x40 - 0x4f */
  i_40,   i_41,   i_42,   i_43,   i_44,   i_45,   i_46,   i_47,
  i_48,   i_49,   i_4a,   i_4b,   i_4c,   i_4d,   i_4e,   i_4f,
/* 0x50 - 0x5f */
  i_50,   i_51,   i_52,   i_53,   i_54,   i_55,   i_56,   i_57,
  i_58,   i_59,   i_5a,   i_5b,   i_5c,   i_5d,   i_5e,   i_5f,
/* 0x60 - 0x6f */
  unk_op, unk_op, unk_op, unk_op, unk_op, unk_op, unk_op, unk_op,
  unk_op, unk_op, unk_op, unk_op, unk_op, unk_op, unk_op, unk_op,
/* 0x70 - 0x7f */
  i_70,   i_71,   i_72,   i_73,   i_74,   i_75,   i_76,   i_77,
  i_78,   i_79,   i_7a,   i_7b,   i_7c,   i_7d,   i_7e,   i_7f,
/* 0x80 - 0x8f */
  i_80,   i_81,   i_80,   i_83,   i_84,   i_85,   i_86,   i_87,
  i_88,   i_89,   i_8a,   i_8b,   i_8c,   i_8d,   i_8e,   i_8f,
/* 0x90 - 0x9f */
  i_90,   i_91,   i_92,   i_93,   i_94,   i_95,   i_96,   i_97,
  i_98,   i_99,   i_9a,   i_9b,   i_9c,   i_9d,   i_9e,   i_9f,
/* 0xa0 - 0xaf */
  i_a0,   i_a1,   i_a2,   i_a3,   i_a4,   i_a5,   i_a6,   i_a7,
  i_a8,   i_a9,   i_aa,   i_ab,   i_ac,   i_ad,   i_ae,   i_af,
/* 0xb0 - 0xbf */
  i_b0,   i_b1,   i_b2,   i_b3,   i_b4,   i_b5,   i_b6,   i_b7,
  i_b8,   i_b9,   i_ba,   i_bb,   i_bc,   i_bd,   i_be,   i_bf,
/* 0xc0 - 0xcf */
  unk_op, unk_op, i_c2,   i_c3,   i_c4,   i_c5,   i_c6,   i_c7,
  unk_op, unk_op, i_ca,   i_cb,   i_cc,   i_cd,   i_ce,   i_cf,
/* 0xd0 - 0xdf */
  i_d0,   i_d1,   i_d2,   i_d3,   i_d4,   i_d5,   unk_op, i_d7,
  i_esc,  i_esc,  i_esc,  i_esc,  i_esc,  i_esc,  i_esc,  i_esc,
/* 0xe0 - 0xef */
  i_e0,   i_e1,   i_e2,   i_e3,   i_e4,   i_e5,   i_e6,   unk_op,
  i_e8,   i_e9,   i_ea,   i_eb,   i_ec,   i_ed,   i_ee,   i_ef,
/* 0xf0 - 0xff */
  i_f0,   unk_op, i_f2,   i_f3,   i_f4,   i_f5,   i_f6,   i_f7,
  i_f8,   i_f9,   i_fa,   i_fb,   i_fc,   i_fd,   i_fe,   i_ff
};

unsigned int count;
unsigned int old_mem;
int debug = 0;

unsigned char *interpret(ip)
unsigned char *ip; {
  if (--TIMELEFT == 0) {
    ip = do_interrupt(ip);
  }
#ifdef DEBUG
  if (debug)
    dis_86(ip,pc_mem,CS);
#endif /* DEBUG */
  return (*ifun[*ip])(ip+1);
}

#ifdef notdef
/*
 * This is defined in sim.h, so as to function as an "inline function"
 * Fortunately, all the places that use it don't try to play fancy
 * post increment games....
 */
unsigned char *atomic_interpret(ip)
unsigned char *ip; {
/*  dis_86(ip,pc_mem,CS);*/
  return (*ifun[*ip])(ip+1);
}
#endif

unsigned char s1, s2;
#define DMEM (0x289d0+0x1d0a)

unsigned char *interpret_loop(start)
unsigned char *start; {
  register unsigned char *ip;
  ip = start;
  while (1) {
    if (--TIMELEFT == 0) {
      ip = do_interrupt(ip);
    }
#ifdef DEBUG
    if (pc_mem[DMEM] != s1 || pc_mem[DMEM+1] != s2) {
      printf("changed to 0x%02.2x%02.2x at %04.4x:%04.4x\n",
        s2=pc_mem[DMEM+1],s1=pc_mem[DMEM],CS,ip-CSPTR);
    }
    if (debug) 
      dis_86(ip,pc_mem,CS);
#endif /* DEBUG */
    ip = (*ifun[*ip])(ip+1);
  }
}
