Пример #1
0
// perform wrapping and output
static void op_enc_perform(op_enc_t* enc) { 
  io_t wrap = 0;
  io_t dif = 0;
  if (enc->wrap) { // wrapping...
    // if value needs wrapping, output the applied difference
    while (enc->val > enc->max) { 
      dif = op_sub(enc->min, enc->max);
      wrap = op_add(wrap, dif);
      enc->val = op_add(enc->val, dif);
    }
    while (enc->val < enc->min) { 
      dif = op_sub(enc->max, enc->min);
      wrap = op_add(wrap, dif);
      enc->val = op_add(enc->val, dif);
    }
  } else { // saturating...
    if (enc->val > enc->max) {
      enc->val = enc->max;
      dif = 1; // force wrap output
    }
    if (enc->val < enc->min) {
      enc->val = enc->min;
      dif = -1; // force wrap output
    }
  }

  // output the value
  net_activate(enc->outs[0], enc->val, enc);

  // output the wrap amount
  if (dif != 0) {
    net_activate(enc->outs[1], wrap, enc);  
  }
}
Пример #2
0
// wrap and output
void op_accum_wrap_out(op_accum_t* accum) {
  io_t wrap = 0;
  io_t dif = 0;

  if (accum->wrap) { // wrapping...
    // if value needs wrapping, output the applied difference
    while (accum->val > accum->max) { 
      dif = op_sub(accum->min, accum->max) - 1;
      wrap = op_add(wrap, dif);
      accum->val = op_add(accum->val, dif);
    }
    while (accum->val < accum->min) { 
      dif = op_sub(accum->max, accum->min) + 1;
      wrap = op_add(wrap, dif);
      accum->val = op_add(accum->val, dif);
    }
  } else { // saturating...
    if (accum->val > accum->max) {
      wrap = dif = op_sub(accum->val, accum->max);
      accum->val = accum->max;
    }
    if (accum->val < accum->min) {
      wrap = dif = op_sub(accum->val , accum->min);
      accum->val = accum->min;
    }
  }

  // output the value
  net_activate(accum->outs[0], accum->val, accum);

  // output the wrap amount
  if (dif != 0) {
    net_activate(accum->outs[1], wrap, accum);  
  }
}
Пример #3
0
Файл: pol.c Проект: rforge/muste
void muste_pol(int argc,char *argv[])
        {
// RS REM        int i;
        char *t;

// RS ADD Variable init
mtx=0;
n_row_comments=0;
roots_eps=EPS;
roots_max_iter=MAX_ITER;

        s_init(argv[1]);
        if (g<2) { sur_print("\nIncomplete POL operation!"); WAIT; return; } // RS ADD
        strcpy(xx,word[1]);
        
        p=strchr(xx,'=');
        if (p==NULL)
            {
            sur_print("\n= missing in POL operation!");
            WAIT; return;
            }
        *p++=EOS;
        if (g>2)
            {
            if (strncmp(p,"LAG(",4)==0)
                { op_lag(p); return; } // 16.8.2006
            }

        q=strchr(p,'*');
        if (q!=NULL) { op_mult(); return; }
        q=strchr(p,'/');
        if (q!=NULL) { op_div(); return; }
        q=strchr(p,'+');
        if (q!=NULL) { op_add(); return; }
        q=strchr(p,'-');
        if (q!=NULL) { op_sub(); return; }

        q=strchr(p,'(');

        if (q!=NULL)
            {
            *q++=EOS;
            t=strchr(q,')');
            if (t==NULL)
                {
                sur_print("\n) is missing!");
                WAIT; return;
                }
            *t=EOS;
            muste_strupr(p);
            if (strncmp(p,"PROD",4)==0) { op_product(); return; }
            if (strncmp(p,"ROOT",4)==0) { op_roots(); return; }
            if (strncmp(p,"DER",3)==0) { op_der(); return; }

            op_value();  /* POL V=P(X) */
            }

        }
Пример #4
0
int executeInstruction(struct Instruction *instr, struct FunctionContext *func, struct RuntimeContext *ctx) {
	switch (instr->opcode) {
	case PUSH:
		op_push(instr, func);
		break;
	case ADD:
		op_add(instr, func);
		break;
	case SUB:
		op_sub(instr, func);
		break;
	case MUL:
		op_mul(instr, func);
		break;
	case DIV:
		op_div(instr, func);
		break;
	case LCALL:
		op_lcall(instr, func, ctx);
		break;
	case IJMP:
		op_ijmp(instr, func);
		break;
	case RARG:
		op_rarg(instr, func);
		break;
	case MKARR:
		op_mkarr(instr, func, ctx);
		break;
	case SETELEM:
		op_setelem(instr, func, ctx);
		break;
	case GETELEM:
		op_getelem(instr, func, ctx);
		break;
	case SETVAR:
		op_setvar(instr, func);
		break;
	case GETVAR:
		op_getvar(instr, func);
		break;
	case JLE:
		op_jle(instr, func);
		break;
	case RET:
		op_ret(instr, func);
		return 0;
	}

	if (instr->opcode != IJMP) {
		if (func->next +1 <= func->opCount)
			func->next++;
	}

	return 1;
}
Пример #5
0
/**
 * Runs the instruction at the program counters position in memory.
 */
void vm_exec()
{
	cycles++;
	Instruction* op = mem_load_instr(pcounter);
	print_instr(op);

	switch(op->op)
	{
		case OP_NAP: break;

		case OP_ADD: 	op_add(op); 	break;
		case OP_SUB: 	op_sub(op); 	break;

		case OP_EXP:	op_exp(op);		break;
		case OP_SIN:	op_sin(op);		break;
		case OP_COS:	op_cos(op);		break;
		case OP_TAN:	op_tan(op);		break;

		case OP_LW: 	op_lw(op);		break;

		case OP_SW:		op_sw(op);		break;
		case OP_SB:		op_sb(op);		break;

		case OP_J:		op_j(op); 		return; // Jump
		case OP_JR:		op_jr(op);		return;
		case OP_JAL:	op_jal(op);		return;
		case OP_JZ:		op_jz(op);		return;
		case OP_JNZ:	op_jnz(op);		return;
		case OP_JEQ:	op_jeq(op);		return;
		case OP_JNQ:	op_jnq(op);		return;

		case OP_PUSH:	op_push(op);	break;
		case OP_POP:	op_pop(op);		break;

		case OP_PRTI:	op_prti(op);	break;

		case OP_EXIT: 	
			vm_exit(op->k); 
			return;

		/* Unsupported operation */
		default:
			printf("Error: Invalid operation at %d\n", pcounter);
			print_instr(op);
			vm_exit(-1);
			return;
	}

	pcounter = pcounter + 8;
}
Пример #6
0
void StackInterpreter::processOpCode(const OpCode& oc)
{
   ++opcount_;

   //handle push data by itself, doesn't play well with switch
   if (oc.opcode_ == 0)
   {
      op_0();
      return;
   }

   if (oc.opcode_ <= 75)
   {
      stack_.push_back(oc.dataRef_);
      return;
   }

   if (oc.opcode_ < 79)
   {
      //op push data
      stack_.push_back(oc.dataRef_);
      return;
   }

   if (oc.opcode_ == OP_1NEGATE)
   {
      op_1negate();
      return;
   }

   if (oc.opcode_ <= 96 && oc.opcode_ >= 81)
   {
      //op_1 - op_16
      uint8_t val = oc.opcode_ - 80;
      stack_.push_back(move(intToRawBinary(val)));
      return;
   }

   //If we got this far this op code is not push data. If this is the input
   //script, set the flag as per P2SH parsing rules (only push data in inputs)
   if (outputScriptRef_.getSize() == 0)
      onlyPushDataInInput_ = false;

   switch (oc.opcode_)
   {
   case OP_NOP:
      break;

   case OP_IF:
   {
      BinaryRefReader brr(oc.dataRef_);
      op_if(brr, false);
      break;
   }

   case OP_NOTIF:
   {
      op_not();
      BinaryRefReader brr(oc.dataRef_);
      op_if(brr, false);
      break;
   }

   case OP_ELSE:
      //processed by opening if statement
      throw ScriptException("a wild else appears");

   case OP_ENDIF:
      //processed by opening if statement
      throw ScriptException("a wild endif appears");

   case OP_VERIFY:
      op_verify();
      break;

   case OP_TOALTSTACK:
      op_toaltstack();
      break;

   case OP_FROMALTSTACK:
      op_fromaltstack();
      break;

   case OP_IFDUP:
      op_ifdup();
      break;

   case OP_2DROP:
   {
      stack_.pop_back();
      stack_.pop_back();
      break;
   }

   case OP_2DUP:
      op_2dup();
      break;

   case OP_3DUP:
      op_3dup();
      break;

   case OP_2OVER:
      op_2over();
      break;

   case OP_DEPTH:
      op_depth();
      break;

   case OP_DROP:
      stack_.pop_back();
      break;

   case OP_DUP:
      op_dup();
      break;

   case OP_NIP:
      op_nip();
      break;

   case OP_OVER:
      op_over();
      break;

   case OP_PICK:
      op_pick();
      break;

   case OP_ROLL:
      op_roll();
      break;

   case OP_ROT:
      op_rot();
      break;

   case OP_SWAP:
      op_swap();
      break;

   case OP_TUCK:
      op_tuck();
      break;

   case OP_SIZE:
      op_size();
      break;

   case OP_EQUAL:
   {
      op_equal();
      if (onlyPushDataInInput_ && p2shScript_.getSize() != 0)
      {
         //check the op_equal result
         op_verify();
         if (!isValid_)
            break;

         if (flags_ & SCRIPT_VERIFY_SEGWIT)
            if (p2shScript_.getSize() == 22 ||
               p2shScript_.getSize() == 34)
            {
               auto versionByte = p2shScript_.getPtr();
               if (*versionByte <= 16)
               {
                  processSW(p2shScript_);
                  return;
               }
            }

         processScript(p2shScript_, true);
      }
      break;
   }

   case OP_EQUALVERIFY:
   {
      op_equal();
      op_verify();
      break;
   }

   case OP_1ADD:
      op_1add();
      break;

   case OP_1SUB:
      op_1sub();
      break;

   case OP_NEGATE:
      op_negate();
      break;

   case OP_ABS:
      op_abs();
      break;

   case OP_NOT:
      op_not();
      break;

   case OP_0NOTEQUAL:
      op_0notequal();
      break;

   case OP_ADD:
      op_add();
      break;

   case OP_SUB:
      op_sub();
      break;

   case OP_BOOLAND:
      op_booland();
      break;

   case OP_BOOLOR:
      op_boolor();
      break;

   case OP_NUMEQUAL:
      op_numequal();
      break;

   case OP_NUMEQUALVERIFY:
   {
      op_numequal();
      op_verify();
      break;
   }

   case OP_NUMNOTEQUAL:
      op_numnotequal();
      break;

   case OP_LESSTHAN:
      op_lessthan();
      break;

   case OP_GREATERTHAN:
      op_greaterthan();
      break;

   case OP_LESSTHANOREQUAL:
      op_lessthanorequal();
      break;

   case OP_GREATERTHANOREQUAL:
      op_greaterthanorequal();
      break;

   case OP_MIN:
      op_min();
      break;

   case OP_MAX:
      op_max();
      break;

   case OP_WITHIN:
      op_within();
      break;

   case OP_RIPEMD160:
      op_ripemd160();
      break;

   case OP_SHA256:
   {
      //save the script if this output is a possible p2sh
      if (flags_ & SCRIPT_VERIFY_P2SH_SHA256)
         if (opcount_ == 1 && onlyPushDataInInput_)
            p2shScript_ = stack_back();

      op_sha256();
      break;
   }

   case OP_HASH160:
   {
      //save the script if this output is a possible p2sh
      if (flags_ & SCRIPT_VERIFY_P2SH)
         if (opcount_ == 1 && onlyPushDataInInput_)
            p2shScript_ = stack_back();

      op_hash160();
      break;
   }

   case OP_HASH256:
      op_hash256();
      break;

   case OP_CODESEPARATOR:
   {
      opcount_ = 0;
      if (outputScriptRef_.getSize() != 0)
         txStubPtr_->setLastOpCodeSeparator(inputIndex_, oc.offset_);
      break;
   }

   case OP_CHECKSIG:
      op_checksig();
      break;

   case OP_CHECKSIGVERIFY:
   {
      op_checksig();
      op_verify();
      break;
   }

   case OP_CHECKMULTISIG:
      op_checkmultisig();
      break;

   case OP_CHECKMULTISIGVERIFY:
   {
      op_checkmultisig();
      op_verify();
   }

   case OP_NOP1:
      break;

   case OP_NOP2:
   {
      if (!(flags_ & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY))
         break; // not enabled; treat as a NOP

      //CLTV mechanics
      throw ScriptException("OP_CLTV not supported");
   }

   case OP_NOP3:
   {
      if (!(flags_ & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY))
         break; // not enabled; treat as a NOP

      //CSV mechanics
      throw ScriptException("OP_CSV not supported");
   }

   case OP_NOP4:
      break;

   case OP_NOP5:
      break;

   case OP_NOP6:
      break;

   case OP_NOP7:
      break;

   case OP_NOP8:
      break;

   case OP_NOP9:
      break;

   case OP_NOP10:
      break;

   default:
   {
      stringstream ss;
      ss << "unknown opcode: " << (unsigned)oc.opcode_;
      throw runtime_error(ss.str());
   }
   }
}
Пример #7
0
void	flt_mod (mval *u, mval *v, mval *q)
{
	int	exp;
	int4	z, x;
	mval	w;			/* temporary mval for division result */
	mval	y;			/* temporary mval for extended precision promotion
					   to prevent modifying caller's data */
	mval	*u_orig;		/* original (caller's) value of u */
	error_def(ERR_DIVZERO);

	u_orig = u;
	MV_FORCE_NUM(u);
	MV_FORCE_NUM(v);

	if ((v->mvtype & MV_INT) != 0  &&  v->m[1] == 0)
		rts_error(VARLSTCNT(1) ERR_DIVZERO);

	if ((u->mvtype & MV_INT & v->mvtype) != 0)
	{
		/* Both are INT's; use shortcut.  */
		q->mvtype = MV_NM | MV_INT;
		eb_int_mod(u->m[1], v->m[1], q->m);
		return;
	}
	else if ((u->mvtype & MV_INT) != 0)
	{
		/* u is INT; promote to extended precision for compatibility with v.  */
		y = *u;
		promote(&y);		/* y will be normalized, but not in canonical form */
		u = &y;			/* this is why we need u_orig */
	}
	else if ((v->mvtype & MV_INT) != 0)
	{
		/* v is INT; promote to extended precision for compatibility with u.  */
		y = *v;
		promote(&y);
		v = &y;
	}

	/* At this point, both u and v are in extended precision format.  */

	/* Set w = floor(u/v).  */
	op_div (u, v, &w);
	if ((w.mvtype & MV_INT) != 0)
		promote(&w);
	exp = w.e;
	if (exp <= MV_XBIAS)
	{
		/* Magnitude of w, floor(u/v), is < 1.  */
		if (u->sgn != v->sgn  &&  w.m[1] != 0  &&  exp >= EXPLO)
		{
			/* Signs differ (=> floor(u/v) < 0) and (w != 0) and (no underflow) => floor(u/v) == -1 */
			w.sgn = 1;
			w.e = MV_XBIAS + 1;
			w.m[1] = MANT_LO;
			w.m[0] = 0;
		}
		else
		{
			/* Signs same (=> floor(u/v) >= 0) or (w == 0) or (underflow) => floor(u/v) == 0 */
			*q = *u_orig;	/* u - floor(u/v)*v == u - 0*v == u */
			return;
		}
	}
	else if (exp < EXP_IDX_BIAL)
	{
		z = ten_pwr[EXP_IDX_BIAL - exp];
		x = (w.m[1]/z)*z;
		if (u->sgn != v->sgn  &&  (w.m[1] != x  ||  w.m[0] != 0))
		{
			w.m[0] = 0;
			w.m[1] = x + z;
			if (w.m[1] >= MANT_HI)
			{
				w.m[0] = w.m[0]/10 + (w.m[1]%10)*MANT_LO;
				w.m[1] /= 10;
				w.e++;
			}
		}
		else
		{
			w.m[0] = 0;
			w.m[1] = x;
		}
	}
	else if (exp < EXP_IDX_BIAQ)
	{
		z = ten_pwr[EXP_IDX_BIAQ - exp];
		x = (w.m[0]/z)*z;
		if (u->sgn != v->sgn  &&  w.m[0] != x)
		{
			w.m[0] = x + z;
			if (w.m[0] >= MANT_HI)
			{
				w.m[0] -= MANT_HI;
				w.m[1]++;
			}
		}
		else
		{
			w.m[0] = x;
		}
	}

	op_mul (&w, v, &w);		/* w = w*v = floor(u/v)*v       */
	op_sub (u_orig, &w, q);		/* q = u - w = u - floor(u/v)*v */
}
Пример #8
0
void Step()
{
	Opcodes OP = (Opcodes)Fetch8();
	//printf("%08X:%08X\n", Registers[sp], Registers[pc]);
	switch (OP)
	{
	case O_NOP:
		op_nop();
		break;
	case O_MOV:
		op_mov();
		break;
	case O_ADD:
		op_add();
		break;
	case O_SUB:
		op_sub();
		break;
	case O_MUL:
		op_mul();
		break;
	case O_DIV:
		op_div();
		break;
	case O_LI:
		op_li();
		break;
	case O_MOVF:
		op_movf();
		break;
	case O_ADDF:
		op_addf();
		break;
	case O_SUBF:
		op_subf();
		break;
	case O_MULF:
		op_mulf();
		break;
	case O_DIVF:
		op_divf();
		break;
	case O_LIF:
		op_lif();
		break;
	case O_XOR:
		op_xor();
		break;
	case O_AND:
		op_and();
		break;
	case O_MOD:
		op_mod();
		break;
	case O_OR:
		op_or();
		break;
	case O_NOT:
		op_not();
		break;
	case O_SHR:
		op_shr();
		break;
	case O_SHL:
		op_shl();
		break;
	case O_PUSH:
		op_push();
		break;
	case O_POP:
		op_pop();
		break;
	case O_STB:
		op_stb();
		break;
	case O_LDB:
		op_ldb();
		break;
	case O_STH:
		op_sth();
		break;
	case O_LDH:
		op_ldh();
		break;
	case O_STW:
		op_stw();
		break;
	case O_LDW:
		op_ldw();
		break;
	case O_LDF:
		op_ldf();
		break;
	case O_STF:
		op_stf();
		break;
	case O_CMP:
		op_cmp();
		break;
	case O_B:
		op_b(0);
		break;
	case O_BC:
		op_b(1);
		break;
	case O_BEQ:
		op_bcond(ctr0_eq);
		break;
	case O_BNE:
		op_bcond(ctr0_ne);
		break;
	case O_BGT:
		op_bcond(ctr0_gt);
		break;
	case O_BLT:
		op_bcond(ctr0_lt);
		break;
	case O_BTC:
		op_btc();
		break;
	case O_INC:
		op_inc();
		break;
	case O_DEC:
		op_dec();
		break;
	default:
		Error("Error: Unknown Opcode PC = %d OP = %08X\n", Registers[pc], OP);
	}

	Ticks++;
}
Пример #9
0
void doop(Mips * emu, uint32_t op) {
    switch(op & 0xfc000000) {
        case 0x8000000:
            op_j(emu,op);
            return;
        case 0xc000000:
            op_jal(emu,op);
            return;
        case 0x10000000:
            op_beq(emu,op);
            return;
        case 0x14000000:
            op_bne(emu,op);
            return;
        case 0x18000000:
            op_blez(emu,op);
            return;
        case 0x1c000000:
            op_bgtz(emu,op);
            return;
        case 0x20000000:
            op_addi(emu,op);
            return;
        case 0x24000000:
            op_addiu(emu,op);
            return;
        case 0x28000000:
            op_slti(emu,op);
            return;
        case 0x2c000000:
            op_sltiu(emu,op);
            return;
        case 0x30000000:
            op_andi(emu,op);
            return;
        case 0x34000000:
            op_ori(emu,op);
            return;
        case 0x38000000:
            op_xori(emu,op);
            return;
        case 0x3c000000:
            op_lui(emu,op);
            return;
        case 0x50000000:
            op_beql(emu,op);
            return;
        case 0x54000000:
            op_bnel(emu,op);
            return;
        case 0x58000000:
            op_blezl(emu,op);
            return;
        case 0x80000000:
            op_lb(emu,op);
            return;
        case 0x84000000:
            op_lh(emu,op);
            return;
        case 0x88000000:
            op_lwl(emu,op);
            return;
        case 0x8c000000:
            op_lw(emu,op);
            return;
        case 0x90000000:
            op_lbu(emu,op);
            return;
        case 0x94000000:
            op_lhu(emu,op);
            return;
        case 0x98000000:
            op_lwr(emu,op);
            return;
        case 0xa0000000:
            op_sb(emu,op);
            return;
        case 0xa4000000:
            op_sh(emu,op);
            return;
        case 0xa8000000:
            op_swl(emu,op);
            return;
        case 0xac000000:
            op_sw(emu,op);
            return;
        case 0xb8000000:
            op_swr(emu,op);
            return;
        case 0xbc000000:
            op_cache(emu,op);
            return;
        case 0xc0000000:
            op_ll(emu,op);
            return;
        case 0xcc000000:
            op_pref(emu,op);
            return;
        case 0xe0000000:
            op_sc(emu,op);
            return;
    }
    switch(op & 0xfc00003f) {
        case 0x0:
            op_sll(emu,op);
            return;
        case 0x2:
            op_srl(emu,op);
            return;
        case 0x3:
            op_sra(emu,op);
            return;
        case 0x4:
            op_sllv(emu,op);
            return;
        case 0x6:
            op_srlv(emu,op);
            return;
        case 0x7:
            op_srav(emu,op);
            return;
        case 0x8:
            op_jr(emu,op);
            return;
        case 0x9:
            op_jalr(emu,op);
            return;
        case 0xc:
            op_syscall(emu,op);
            return;
        case 0xf:
            op_sync(emu,op);
            return;
        case 0x10:
            op_mfhi(emu,op);
            return;
        case 0x11:
            op_mthi(emu,op);
            return;
        case 0x12:
            op_mflo(emu,op);
            return;
        case 0x13:
            op_mtlo(emu,op);
            return;
        case 0x18:
            op_mult(emu,op);
            return;
        case 0x19:
            op_multu(emu,op);
            return;
        case 0x1a:
            op_div(emu,op);
            return;
        case 0x1b:
            op_divu(emu,op);
            return;
        case 0x20:
            op_add(emu,op);
            return;
        case 0x21:
            op_addu(emu,op);
            return;
        case 0x22:
            op_sub(emu,op);
            return;
        case 0x23:
            op_subu(emu,op);
            return;
        case 0x24:
            op_and(emu,op);
            return;
        case 0x25:
            op_or(emu,op);
            return;
        case 0x26:
            op_xor(emu,op);
            return;
        case 0x27:
            op_nor(emu,op);
            return;
        case 0x2a:
            op_slt(emu,op);
            return;
        case 0x2b:
            op_sltu(emu,op);
            return;
	case 0x2d:
	    op_addu(emu,op); //daddu
	    return;
        case 0x36:
            op_tne(emu,op);
            return;
    }
    switch(op & 0xfc1f0000) {
        case 0x4000000:
            op_bltz(emu,op);
            return;
        case 0x4010000:
            op_bgez(emu,op);
            return;
        case 0x4020000:
            op_bltzl(emu,op);
            return;
        case 0x4030000:
            op_bgezl(emu,op);
            return;
        case 0x4100000:
            op_bltzal(emu,op);
            return;
        case 0x4110000:
            op_bgezal(emu,op);
            return;
        case 0x5c000000:
            op_bgtzl(emu,op);
            return;
    }
    switch(op & 0xffffffff) {
        case 0x42000002:
            op_tlbwi(emu,op);
            return;
        case 0x42000006:
            op_tlbwr(emu,op);
            return;
        case 0x42000008:
            op_tlbp(emu,op);
            return;
        case 0x42000018:
            op_eret(emu,op);
            return;
    }
    switch(op & 0xfc0007ff) {
        case 0xa:
            op_movz(emu,op);
            return;
        case 0xb:
            op_movn(emu,op);
            return;
        case 0x70000002:
            op_mul(emu,op);
            return;
    }
    switch(op & 0xffe00000) {
        case 0x40000000:
            op_mfc0(emu,op);
            return;
        case 0x40800000:
            op_mtc0(emu,op);
            return;
    }
    switch(op & 0xfe00003f) {
        case 0x42000020:
            op_wait(emu,op);
            return;
    }
    // printf("unhandled opcode at %x -> %x\n",emu->pc,op);
    setExceptionCode(emu,EXC_RI);
    emu->exceptionOccured = 1;
    return;
}
Пример #10
0
static void mc6809_run(struct MC6809 *cpu) {

	do {

		_Bool nmi_active = cpu->nmi && ((cpu->cycle - cpu->nmi_cycle) <= (UINT_MAX/2));
		_Bool firq_active = cpu->firq && ((cpu->cycle - cpu->firq_cycle) <= (UINT_MAX/2));
		_Bool irq_active = cpu->irq && ((cpu->cycle - cpu->irq_cycle) <= (UINT_MAX/2));

		// Prevent overflow
		if (firq_active) cpu->firq_cycle = cpu->cycle;
		if (irq_active) cpu->irq_cycle = cpu->cycle;

		switch (cpu->state) {

		case mc6809_state_reset:
			REG_DP = 0;
			REG_CC |= (CC_F | CC_I);
			cpu->nmi = 0;
			cpu->nmi_armed = 0;
			cpu->state = mc6809_state_reset_check_halt;
			// fall through

		case mc6809_state_reset_check_halt:
			if (cpu->halt) {
				NVMA_CYCLE;
				continue;
			}
			REG_PC = fetch_byte(cpu, MC6809_INT_VEC_RESET) << 8;
			REG_PC |= fetch_byte(cpu, MC6809_INT_VEC_RESET + 1);
			NVMA_CYCLE;
			cpu->state = mc6809_state_label_a;
			continue;

		// done_instruction case for backwards-compatibility
		case mc6809_state_done_instruction:
		case mc6809_state_label_a:
			if (cpu->halt) {
				NVMA_CYCLE;
				continue;
			}
			cpu->state = mc6809_state_label_b;
			// fall through

		case mc6809_state_label_b:
			if (cpu->nmi_armed && nmi_active) {
				peek_byte(cpu, REG_PC);
				peek_byte(cpu, REG_PC);
				stack_irq_registers(cpu, 1);
				cpu->state = mc6809_state_dispatch_irq;
				continue;
			}
			if (!(REG_CC & CC_F) && firq_active) {
				peek_byte(cpu, REG_PC);
				peek_byte(cpu, REG_PC);
				stack_irq_registers(cpu, 0);
				cpu->state = mc6809_state_dispatch_irq;
				continue;
			}
			if (!(REG_CC & CC_I) && irq_active) {
				peek_byte(cpu, REG_PC);
				peek_byte(cpu, REG_PC);
				stack_irq_registers(cpu, 1);
				cpu->state = mc6809_state_dispatch_irq;
				continue;
			}
			cpu->state = mc6809_state_next_instruction;
			// Instruction fetch hook called here so that machine
			// can be stopped beforehand.
			DELEGATE_SAFE_CALL0(cpu->instruction_hook);
			continue;

		case mc6809_state_dispatch_irq:
			if (cpu->nmi_armed && nmi_active) {
				cpu->nmi = 0;
				REG_CC |= (CC_F | CC_I);
				take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_NMI);
				cpu->state = mc6809_state_label_a;
				continue;
			}
			if (!(REG_CC & CC_F) && firq_active) {
				REG_CC |= (CC_F | CC_I);
				take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_FIRQ);
				cpu->state = mc6809_state_label_a;
				continue;
			}
			if (!(REG_CC & CC_I) && irq_active) {
				REG_CC |= CC_I;
				take_interrupt(cpu, CC_I, MC6809_INT_VEC_IRQ);
				cpu->state = mc6809_state_label_a;
				continue;
			}
			cpu->state = mc6809_state_cwai_check_halt;
			continue;

		case mc6809_state_cwai_check_halt:
			NVMA_CYCLE;
			if (cpu->halt) {
				continue;
			}
			cpu->state = mc6809_state_dispatch_irq;
			continue;

		case mc6809_state_sync:
			if (nmi_active || firq_active || irq_active) {
				NVMA_CYCLE;
				NVMA_CYCLE;
				instruction_posthook(cpu);
				cpu->state = mc6809_state_label_b;
				continue;
			}
			NVMA_CYCLE;
			if (cpu->halt)
				cpu->state = mc6809_state_sync_check_halt;
			continue;

		case mc6809_state_sync_check_halt:
			NVMA_CYCLE;
			if (!cpu->halt) {
				cpu->state = mc6809_state_sync;
			}
			continue;

		case mc6809_state_next_instruction:
			{
			unsigned op;
			// Fetch op-code and process
			op = byte_immediate(cpu);
			switch (op) {

			// 0x00 - 0x0f direct mode ops
			// 0x40 - 0x4f inherent A register ops
			// 0x50 - 0x5f inherent B register ops
			// 0x60 - 0x6f indexed mode ops
			// 0x70 - 0x7f extended mode ops
			case 0x00: case 0x01: case 0x02: case 0x03:
			case 0x04: case 0x05: case 0x06: case 0x07:
			case 0x08: case 0x09: case 0x0a: case 0x0b:
			case 0x0c: case 0x0d: case 0x0f:
			case 0x40: case 0x41: case 0x42: case 0x43:
			case 0x44: case 0x45: case 0x46: case 0x47:
			case 0x48: case 0x49: case 0x4a: case 0x4b:
			case 0x4c: case 0x4d: case 0x4f:
			case 0x50: case 0x51: case 0x52: case 0x53:
			case 0x54: case 0x55: case 0x56: case 0x57:
			case 0x58: case 0x59: case 0x5a: case 0x5b:
			case 0x5c: case 0x5d: case 0x5f:
			case 0x60: case 0x61: case 0x62: case 0x63:
			case 0x64: case 0x65: case 0x66: case 0x67:
			case 0x68: case 0x69: case 0x6a: case 0x6b:
			case 0x6c: case 0x6d: case 0x6f:
			case 0x70: case 0x71: case 0x72: case 0x73:
			case 0x74: case 0x75: case 0x76: case 0x77:
			case 0x78: case 0x79: case 0x7a: case 0x7b:
			case 0x7c: case 0x7d: case 0x7f: {
				uint16_t ea;
				unsigned tmp1;
				switch ((op >> 4) & 0xf) {
				case 0x0: ea = ea_direct(cpu); tmp1 = fetch_byte(cpu, ea); break;
				case 0x4: ea = 0; tmp1 = RREG_A; break;
				case 0x5: ea = 0; tmp1 = RREG_B; break;
				case 0x6: ea = ea_indexed(cpu); tmp1 = fetch_byte(cpu, ea); break;
				case 0x7: ea = ea_extended(cpu); tmp1 = fetch_byte(cpu, ea); break;
				default: ea = tmp1 = 0; break;
				}
				switch (op & 0xf) {
				case 0x1: // NEG illegal
				case 0x0: tmp1 = op_neg(cpu, tmp1); break; // NEG, NEGA, NEGB
				case 0x2: tmp1 = op_negcom(cpu, tmp1); break; // NEGCOM illegal
				case 0x3: tmp1 = op_com(cpu, tmp1); break; // COM, COMA, COMB
				case 0x5: // LSR illegal
				case 0x4: tmp1 = op_lsr(cpu, tmp1); break; // LSR, LSRA, LSRB
				case 0x6: tmp1 = op_ror(cpu, tmp1); break; // ROR, RORA, RORB
				case 0x7: tmp1 = op_asr(cpu, tmp1); break; // ASR, ASRA, ASRB
				case 0x8: tmp1 = op_asl(cpu, tmp1); break; // ASL, ASLA, ASLB
				case 0x9: tmp1 = op_rol(cpu, tmp1); break; // ROL, ROLA, ROLB
				case 0xb: // DEC illegal
				case 0xa: tmp1 = op_dec(cpu, tmp1); break; // DEC, DECA, DECB
				case 0xc: tmp1 = op_inc(cpu, tmp1); break; // INC, INCA, INCB
				case 0xd: tmp1 = op_tst(cpu, tmp1); break; // TST, TSTA, TSTB
				case 0xf: tmp1 = op_clr(cpu, tmp1); break; // CLR, CLRA, CLRB
				default: break;
				}
				switch (op & 0xf) {
				case 0xd: // TST
					NVMA_CYCLE;
					NVMA_CYCLE;
					break;
				default: // the rest need storing
					switch ((op >> 4) & 0xf) {
					default:
					case 0x0: case 0x6: case 0x7:
						NVMA_CYCLE;
						store_byte(cpu, ea, tmp1);
						break;
					case 0x4:
						WREG_A = tmp1;
						peek_byte(cpu, REG_PC);
						break;
					case 0x5:
						WREG_B = tmp1;
						peek_byte(cpu, REG_PC);
						break;
					}
				}
			} break;

			// 0x0e JMP direct
			// 0x6e JMP indexed
			// 0x7e JMP extended
			case 0x0e: case 0x6e: case 0x7e: {
				unsigned ea;
				switch ((op >> 4) & 0xf) {
				case 0x0: ea = ea_direct(cpu); break;
				case 0x6: ea = ea_indexed(cpu); break;
				case 0x7: ea = ea_extended(cpu); break;
				default: ea = 0; break;
				}
				REG_PC = ea;
			} break;

			// 0x10 Page 2
			case 0x10:
				cpu->state = mc6809_state_instruction_page_2;
				continue;
			// 0x11 Page 3
			case 0x11:
				cpu->state = mc6809_state_instruction_page_3;
				continue;
			// 0x12 NOP inherent
			case 0x12: peek_byte(cpu, REG_PC); break;
			// 0x13 SYNC inherent
			case 0x13:
				peek_byte(cpu, REG_PC);
				cpu->state = mc6809_state_sync;
				continue;
			// 0x14, 0x15 HCF? (illegal)
			case 0x14:
			case 0x15:
				cpu->state = mc6809_state_hcf;
				goto done_instruction;
			// 0x16 LBRA relative
			case 0x16: {
				uint16_t ea;
				ea = long_relative(cpu);
				REG_PC += ea;
				NVMA_CYCLE;
				NVMA_CYCLE;
			} break;
			// 0x17 LBSR relative
			case 0x17: {
				uint16_t ea;
				ea = long_relative(cpu);
				ea += REG_PC;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				push_word(cpu, &REG_S, REG_PC);
				REG_PC = ea;
			} break;
			// 0x18 Shift CC with mask inherent (illegal)
			case 0x18:
				REG_CC = (REG_CC << 1) & (CC_H | CC_Z);
				NVMA_CYCLE;
				peek_byte(cpu, REG_PC);
				break;
			// 0x19 DAA inherent
			case 0x19: {
				unsigned tmp = 0;
				if ((RREG_A&0x0f) >= 0x0a || REG_CC & CC_H) tmp |= 0x06;
				if (RREG_A >= 0x90 && (RREG_A&0x0f) >= 0x0a) tmp |= 0x60;
				if (RREG_A >= 0xa0 || REG_CC & CC_C) tmp |= 0x60;
				tmp += RREG_A;
				WREG_A = tmp;
				// CC.C NOT cleared, only set if appropriate
				CLR_NZV;
				SET_NZC8(tmp);
				peek_byte(cpu, REG_PC);
			} break;
			// 0x1a ORCC immediate
			case 0x1a: {
				unsigned data;
				data = byte_immediate(cpu);
				REG_CC |= data;
				peek_byte(cpu, REG_PC);
			} break;
			// 0x1b NOP inherent (illegal)
			case 0x1b: peek_byte(cpu, REG_PC); break;
			// 0x1c ANDCC immediate
			case 0x1c: {
				unsigned data;
				data = byte_immediate(cpu);
				REG_CC &= data;
				peek_byte(cpu, REG_PC);
			} break;
			// 0x1d SEX inherent
			case 0x1d:
				WREG_A = (RREG_B & 0x80) ? 0xff : 0;
				CLR_NZ;
				SET_NZ16(REG_D);
				peek_byte(cpu, REG_PC);
				break;
			// 0x1e EXG immediate
			case 0x1e: {
				unsigned postbyte;
				uint16_t tmp1, tmp2;
				postbyte = byte_immediate(cpu);
				switch (postbyte >> 4) {
					case 0x0: tmp1 = REG_D; break;
					case 0x1: tmp1 = REG_X; break;
					case 0x2: tmp1 = REG_Y; break;
					case 0x3: tmp1 = REG_U; break;
					case 0x4: tmp1 = REG_S; break;
					case 0x5: tmp1 = REG_PC; break;
					case 0x8: tmp1 = RREG_A | 0xff00; break;
					case 0x9: tmp1 = RREG_B | 0xff00; break;
					// TODO: verify this behaviour
					case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break;
					case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break;
					default: tmp1 = 0xffff; break;
				}
				switch (postbyte & 0xf) {
					case 0x0: tmp2 = REG_D; REG_D = tmp1; break;
					case 0x1: tmp2 = REG_X; REG_X = tmp1; break;
					case 0x2: tmp2 = REG_Y; REG_Y = tmp1; break;
					case 0x3: tmp2 = REG_U; REG_U = tmp1; break;
					case 0x4: tmp2 = REG_S; REG_S = tmp1; break;
					case 0x5: tmp2 = REG_PC; REG_PC = tmp1; break;
					case 0x8: tmp2 = RREG_A | 0xff00; WREG_A = tmp1; break;
					case 0x9: tmp2 = RREG_B | 0xff00; WREG_B = tmp1; break;
					// TODO: verify this behaviour
					case 0xa: tmp2 = (REG_CC << 8) | REG_CC; REG_CC = tmp1; break;
					case 0xb: tmp2 = (REG_DP << 8) | REG_DP; REG_DP = tmp1; break;
					default: tmp2 = 0xffff; break;
				}
				switch (postbyte >> 4) {
					case 0x0: REG_D = tmp2; break;
					case 0x1: REG_X = tmp2; break;
					case 0x2: REG_Y = tmp2; break;
					case 0x3: REG_U = tmp2; break;
					case 0x4: REG_S = tmp2; break;
					case 0x5: REG_PC = tmp2; break;
					case 0x8: WREG_A = tmp2; break;
					case 0x9: WREG_B = tmp2; break;
					case 0xa: REG_CC = tmp2; break;
					case 0xb: REG_DP = tmp2; break;
					default: break;
				}
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
			} break;
			// 0x1f TFR immediate
			case 0x1f: {
				unsigned postbyte;
				uint16_t tmp1;
				postbyte = byte_immediate(cpu);
				switch (postbyte >> 4) {
					case 0x0: tmp1 = REG_D; break;
					case 0x1: tmp1 = REG_X; break;
					case 0x2: tmp1 = REG_Y; break;
					case 0x3: tmp1 = REG_U; break;
					case 0x4: tmp1 = REG_S; break;
					case 0x5: tmp1 = REG_PC; break;
					case 0x8: tmp1 = RREG_A | 0xff00; break;
					case 0x9: tmp1 = RREG_B | 0xff00; break;
					// TODO: verify this behaviour
					case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break;
					case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break;
					default: tmp1 = 0xffff; break;
				}
				switch (postbyte & 0xf) {
					case 0x0: REG_D = tmp1; break;
					case 0x1: REG_X = tmp1; break;
					case 0x2: REG_Y = tmp1; break;
					case 0x3: REG_U = tmp1; break;
					case 0x4: REG_S = tmp1; break;
					case 0x5: REG_PC = tmp1; break;
					case 0x8: WREG_A = tmp1; break;
					case 0x9: WREG_B = tmp1; break;
					case 0xa: REG_CC = tmp1; break;
					case 0xb: REG_DP = tmp1; break;
					default: break;
				}
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
			} break;

			// 0x20 - 0x2f short branches
			case 0x20: case 0x21: case 0x22: case 0x23:
			case 0x24: case 0x25: case 0x26: case 0x27:
			case 0x28: case 0x29: case 0x2a: case 0x2b:
			case 0x2c: case 0x2d: case 0x2e: case 0x2f: {
				unsigned tmp = sex8(byte_immediate(cpu));
				NVMA_CYCLE;
				if (branch_condition(cpu, op))
					REG_PC += tmp;
			} break;

			// 0x30 LEAX indexed
			case 0x30:
				REG_X = ea_indexed(cpu);
				CLR_Z;
				SET_Z(REG_X);
				NVMA_CYCLE;
				break;
			// 0x31 LEAY indexed
			case 0x31:
				REG_Y = ea_indexed(cpu);
				CLR_Z;
				SET_Z(REG_Y);
				NVMA_CYCLE;
				break;
			// 0x32 LEAS indexed
			case 0x32:
				REG_S = ea_indexed(cpu);
				NVMA_CYCLE;
				cpu->nmi_armed = 1;  // XXX: Really?
				break;
			// 0x33 LEAU indexed
			case 0x33:
				REG_U = ea_indexed(cpu);
				NVMA_CYCLE;
				break;
			// 0x34 PSHS immediate
			case 0x34: psh(cpu, &REG_S, REG_U); break;
			// 0x35 PULS immediate
			case 0x35: pul(cpu, &REG_S, &REG_U); break;
			// 0x36 PSHU immediate
			case 0x36: psh(cpu, &REG_U, REG_S); break;
			// 0x37 PULU immediate
			case 0x37: pul(cpu, &REG_U, &REG_S); break;
			// 0x38 ANDCC immediate (illegal)
			case 0x38: {
				unsigned data;
				data = byte_immediate(cpu);
				REG_CC &= data;
				peek_byte(cpu, REG_PC);
				/* Differs from legal 0x1c version by
				 * taking one more cycle: */
				NVMA_CYCLE;
			} break;
			// 0x39 RTS inherent
			case 0x39:
				peek_byte(cpu, REG_PC);
				REG_PC = pull_word(cpu, &REG_S);
				NVMA_CYCLE;
				break;
			// 0x3a ABX inherent
			case 0x3a:
				REG_X += RREG_B;
				peek_byte(cpu, REG_PC);
				NVMA_CYCLE;
				break;
			// 0x3b RTI inherent
			case 0x3b:
				peek_byte(cpu, REG_PC);
				REG_CC = pull_byte(cpu, &REG_S);
				if (REG_CC & CC_E) {
					WREG_A = pull_byte(cpu, &REG_S);
					WREG_B = pull_byte(cpu, &REG_S);
					REG_DP = pull_byte(cpu, &REG_S);
					REG_X = pull_word(cpu, &REG_S);
					REG_Y = pull_word(cpu, &REG_S);
					REG_U = pull_word(cpu, &REG_S);
					REG_PC = pull_word(cpu, &REG_S);
				} else {
					REG_PC = pull_word(cpu, &REG_S);
				}
				cpu->nmi_armed = 1;
				peek_byte(cpu, REG_S);
				break;
			// 0x3c CWAI immediate
			case 0x3c: {
				unsigned data;
				data = byte_immediate(cpu);
				REG_CC &= data;
				peek_byte(cpu, REG_PC);
				NVMA_CYCLE;
				stack_irq_registers(cpu, 1);
				NVMA_CYCLE;
				cpu->state = mc6809_state_dispatch_irq;
				goto done_instruction;
			} break;
			// 0x3d MUL inherent
			case 0x3d: {
				unsigned tmp = RREG_A * RREG_B;
				REG_D = tmp;
				CLR_ZC;
				SET_Z(tmp);
				if (tmp & 0x80)
					REG_CC |= CC_C;
				peek_byte(cpu, REG_PC);
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
				NVMA_CYCLE;
			} break;
			// 0x3e RESET (illegal)
			case 0x3e:
				peek_byte(cpu, REG_PC);
				push_irq_registers(cpu);
				instruction_posthook(cpu);
				take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_RESET);
				cpu->state = mc6809_state_label_a;
				continue;
			// 0x3f SWI inherent
			case 0x3f:
				peek_byte(cpu, REG_PC);
				stack_irq_registers(cpu, 1);
				instruction_posthook(cpu);
				take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_SWI);
				cpu->state = mc6809_state_label_a;
				continue;

			// 0x80 - 0xbf A register arithmetic ops
			// 0xc0 - 0xff B register arithmetic ops
			case 0x80: case 0x81: case 0x82:
			case 0x84: case 0x85: case 0x86: case 0x87:
			case 0x88: case 0x89: case 0x8a: case 0x8b:
			case 0x90: case 0x91: case 0x92:
			case 0x94: case 0x95: case 0x96:
			case 0x98: case 0x99: case 0x9a: case 0x9b:
			case 0xa0: case 0xa1: case 0xa2:
			case 0xa4: case 0xa5: case 0xa6:
			case 0xa8: case 0xa9: case 0xaa: case 0xab:
			case 0xb0: case 0xb1: case 0xb2:
			case 0xb4: case 0xb5: case 0xb6:
			case 0xb8: case 0xb9: case 0xba: case 0xbb:
			case 0xc0: case 0xc1: case 0xc2:
			case 0xc4: case 0xc5: case 0xc6: case 0xc7:
			case 0xc8: case 0xc9: case 0xca: case 0xcb:
			case 0xd0: case 0xd1: case 0xd2:
			case 0xd4: case 0xd5: case 0xd6:
			case 0xd8: case 0xd9: case 0xda: case 0xdb:
			case 0xe0: case 0xe1: case 0xe2:
			case 0xe4: case 0xe5: case 0xe6:
			case 0xe8: case 0xe9: case 0xea: case 0xeb:
			case 0xf0: case 0xf1: case 0xf2:
			case 0xf4: case 0xf5: case 0xf6:
			case 0xf8: case 0xf9: case 0xfa: case 0xfb: {
				unsigned tmp1, tmp2;
				tmp1 = !(op & 0x40) ? RREG_A : RREG_B;
				switch ((op >> 4) & 3) {
				case 0: tmp2 = byte_immediate(cpu); break;
				case 1: tmp2 = byte_direct(cpu); break;
				case 2: tmp2 = byte_indexed(cpu); break;
				case 3: tmp2 = byte_extended(cpu); break;
				default: tmp2 = 0; break;
				}
				switch (op & 0xf) {
				case 0x0: tmp1 = op_sub(cpu, tmp1, tmp2); break; // SUBA, SUBB
				case 0x1: (void)op_sub(cpu, tmp1, tmp2); break; // CMPA, CMPB
				case 0x2: tmp1 = op_sbc(cpu, tmp1, tmp2); break; // SBCA, SBCB
				case 0x4: tmp1 = op_and(cpu, tmp1, tmp2); break; // ANDA, ANDB
				case 0x5: (void)op_and(cpu, tmp1, tmp2); break; // BITA, BITB
				case 0x6: tmp1 = op_ld(cpu, 0, tmp2); break; // LDA, LDB
				case 0x7: tmp1 = op_discard(cpu, tmp1, tmp2); break; // illegal
				case 0x8: tmp1 = op_eor(cpu, tmp1, tmp2); break; // EORA, EORB
				case 0x9: tmp1 = op_adc(cpu, tmp1, tmp2); break; // ADCA, ADCB
				case 0xa: tmp1 = op_or(cpu, tmp1, tmp2); break; // ORA, ORB
				case 0xb: tmp1 = op_add(cpu, tmp1, tmp2); break; // ADDA, ADDB
				default: break;
				}
				if (!(op & 0x40)) {
					WREG_A = tmp1;
				} else {
					WREG_B = tmp1;
				}
			} break;

			// 0x83, 0x93, 0xa3, 0xb3 SUBD
			// 0x8c, 0x9c, 0xac, 0xbc CMPX
			// 0xc3, 0xd3, 0xe3, 0xf3 ADDD
			case 0x83: case 0x93: case 0xa3: case 0xb3:
			case 0x8c: case 0x9c: case 0xac: case 0xbc:
			case 0xc3: case 0xd3: case 0xe3: case 0xf3: {
				unsigned tmp1, tmp2;
				tmp1 = !(op & 0x08) ? REG_D : REG_X;
				switch ((op >> 4) & 3) {
				case 0: tmp2 = word_immediate(cpu); break;
				case 1: tmp2 = word_direct(cpu); break;
				case 2: tmp2 = word_indexed(cpu); break;
				case 3: tmp2 = word_extended(cpu); break;
				default: tmp2 = 0; break;
				}
				switch (op & 0x4f) {
				case 0x03: tmp1 = op_sub16(cpu, tmp1, tmp2); break; // SUBD
				case 0x0c: (void)op_sub16(cpu, tmp1, tmp2); break; // CMPX
				case 0x43: tmp1 = op_add16(cpu, tmp1, tmp2); break; // ADDD
				default: break;
				}
				NVMA_CYCLE;
				if (!(op & 0x08)) {
					REG_D = tmp1;
				}
			} break;

			// 0x8d BSR
			// 0x9d, 0xad, 0xbd JSR
			case 0x8d: case 0x9d: case 0xad: case 0xbd: {
				unsigned ea;
				switch ((op >> 4) & 3) {
				case 0: ea = short_relative(cpu); ea += REG_PC; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break;
				case 1: ea = ea_direct(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break;
				case 2: ea = ea_indexed(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break;
				case 3: ea = ea_extended(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break;
				default: ea = 0; break;
				}
				push_word(cpu, &REG_S, REG_PC);
				REG_PC = ea;
			} break;

			// 0x8e, 0x9e, 0xae, 0xbe LDX
			// 0xcc, 0xdc, 0xec, 0xfc LDD
			// 0xce, 0xde, 0xee, 0xfe LDU
			case 0x8e: case 0x9e: case 0xae: case 0xbe:
			case 0xcc: case 0xdc: case 0xec: case 0xfc:
			case 0xce: case 0xde: case 0xee: case 0xfe: {
				unsigned tmp1, tmp2;
				switch ((op >> 4) & 3) {
				case 0: tmp2 = word_immediate(cpu); break;
				case 1: tmp2 = word_direct(cpu); break;
				case 2: tmp2 = word_indexed(cpu); break;
				case 3: tmp2 = word_extended(cpu); break;
				default: tmp2 = 0; break;
				}
				tmp1 = op_ld16(cpu, 0, tmp2);
				switch (op & 0x42) {
				case 0x02:
					REG_X = tmp1;
					break;
				case 0x40:
					REG_D = tmp1;
					break;
				case 0x42:
					REG_U = tmp1;
					break;
				default: break;
				}
			} break;

			// 0x97, 0xa7, 0xb7 STA
			// 0xd7, 0xe7, 0xf7 STB
			case 0x97: case 0xa7: case 0xb7:
			case 0xd7: case 0xe7: case 0xf7: {
				uint16_t ea;
				uint8_t tmp1;
				tmp1 = !(op & 0x40) ? RREG_A : RREG_B;
				switch ((op >> 4) & 3) {
				case 1: ea = ea_direct(cpu); break;
				case 2: ea = ea_indexed(cpu); break;
				case 3: ea = ea_extended(cpu); break;
				default: ea = 0; break;
				}
				store_byte(cpu, ea, tmp1);
				CLR_NZV;
				SET_NZ8(tmp1);
			} break;

			// 0x9f, 0xaf, 0xbf STX
			// 0xdd, 0xed, 0xfd STD
			// 0xdf, 0xef, 0xff STU
			case 0x9f: case 0xaf: case 0xbf:
			case 0xdd: case 0xed: case 0xfd:
			case 0xdf: case 0xef: case 0xff: {
				uint16_t ea, tmp1;
				switch (op & 0x42) {
				case 0x02: tmp1 = REG_X; break;
				case 0x40: tmp1 = REG_D; break;
				case 0x42: tmp1 = REG_U; break;
				default: tmp1 = 0; break;
				}
				switch ((op >> 4) & 3) {
				case 1: ea = ea_direct(cpu); break;
				case 2: ea = ea_indexed(cpu); break;
				case 3: ea = ea_extended(cpu); break;
				default: ea = 0; break;
				}
				CLR_NZV;
				SET_NZ16(tmp1);
				store_byte(cpu, ea, tmp1 >> 8);
				store_byte(cpu, ea+1, tmp1);
			} break;

			// 0x8f STX immediate (illegal)
			// 0xcf STU immediate (illegal)
			// Illegal instruction only part working
			case 0x8f: case 0xcf: {
				unsigned tmp1;
				tmp1 = !(op & 0x40) ? REG_X : REG_U;
				(void)fetch_byte(cpu, REG_PC);
				REG_PC++;
				store_byte(cpu, REG_PC, tmp1);
				REG_PC++;
				CLR_NZV;
				REG_CC |= CC_N;
			} break;

			// 0xcd HCF? (illegal)
			case 0xcd:
				cpu->state = mc6809_state_hcf;
				goto done_instruction;

			// Illegal instruction
			default:
				NVMA_CYCLE;
				break;
			}
			cpu->state = mc6809_state_label_a;
			goto done_instruction;
			}

		case mc6809_state_instruction_page_2:
			{
			unsigned op;
			op = byte_immediate(cpu);
			switch (op) {

			// 0x10, 0x11 Page 2
			case 0x10:
			case 0x11:
				cpu->state = mc6809_state_instruction_page_2;
				continue;

			// 0x1020 - 0x102f long branches
			case 0x20: case 0x21: case 0x22: case 0x23:
			case 0x24: case 0x25: case 0x26: case 0x27:
			case 0x28: case 0x29: case 0x2a: case 0x2b:
			case 0x2c: case 0x2d: case 0x2e: case 0x2f: {
				unsigned tmp = word_immediate(cpu);
				if (branch_condition(cpu, op)) {
					REG_PC += tmp;
					NVMA_CYCLE;
				}
				NVMA_CYCLE;
			} break;

			// 0x103f SWI2 inherent
			case 0x3f:
				peek_byte(cpu, REG_PC);
				stack_irq_registers(cpu, 1);
				instruction_posthook(cpu);
				take_interrupt(cpu, 0, MC6809_INT_VEC_SWI2);
				cpu->state = mc6809_state_label_a;
				continue;

			// 0x1083, 0x1093, 0x10a3, 0x10b3 CMPD
			// 0x108c, 0x109c, 0x10ac, 0x10bc CMPY
			case 0x83: case 0x93: case 0xa3: case 0xb3:
			case 0x8c: case 0x9c: case 0xac: case 0xbc: {
				unsigned tmp1, tmp2;
				tmp1 = !(op & 0x08) ? REG_D : REG_Y;
				switch ((op >> 4) & 3) {
				case 0: tmp2 = word_immediate(cpu); break;
				case 1: tmp2 = word_direct(cpu); break;
				case 2: tmp2 = word_indexed(cpu); break;
				case 3: tmp2 = word_extended(cpu); break;
				default: tmp2 = 0; break;
				}
				(void)op_sub16(cpu, tmp1, tmp2);
				NVMA_CYCLE;
			} break;

			// 0x108e, 0x109e, 0x10ae, 0x10be LDY
			// 0x10ce, 0x10de, 0x10ee, 0x10fe LDS
			case 0x8e: case 0x9e: case 0xae: case 0xbe:
			case 0xce: case 0xde: case 0xee: case 0xfe: {
				unsigned tmp1, tmp2;
				switch ((op >> 4) & 3) {
				case 0: tmp2 = word_immediate(cpu); break;
				case 1: tmp2 = word_direct(cpu); break;
				case 2: tmp2 = word_indexed(cpu); break;
				case 3: tmp2 = word_extended(cpu); break;
				default: tmp2 = 0; break;
				}
				tmp1 = op_ld16(cpu, 0, tmp2);
				if (!(op & 0x40)) {
					REG_Y = tmp1;
				} else {
					REG_S = tmp1;
					cpu->nmi_armed = 1;
				}
			} break;

			// 0x109f, 0x10af, 0x10bf STY
			// 0x10df, 0x10ef, 0x10ff STS
			case 0x9f: case 0xaf: case 0xbf:
			case 0xdf: case 0xef: case 0xff: {
				unsigned ea, tmp1;
				tmp1 = !(op & 0x40) ? REG_Y : REG_S;
				switch ((op >> 4) & 3) {
				case 1: ea = ea_direct(cpu); break;
				case 2: ea = ea_indexed(cpu); break;
				case 3: ea = ea_extended(cpu); break;
				default: ea = 0; break;
				}
				CLR_NZV;
				SET_NZ16(tmp1);
				store_byte(cpu, ea, tmp1 >> 8);
				store_byte(cpu, ea+1, tmp1);
			} break;

			// Illegal instruction
			default:
				NVMA_CYCLE;
				break;
			}
			cpu->state = mc6809_state_label_a;
			goto done_instruction;
			}

		case mc6809_state_instruction_page_3:
			{
			unsigned op;
			op = byte_immediate(cpu);
			switch (op) {

			// 0x10, 0x11 Page 3
			case 0x10:
			case 0x11:
				cpu->state = mc6809_state_instruction_page_3;
				continue;

			// 0x113F SWI3 inherent
			case 0x3f:
				peek_byte(cpu, REG_PC);
				stack_irq_registers(cpu, 1);
				instruction_posthook(cpu);
				take_interrupt(cpu, 0, MC6809_INT_VEC_SWI3);
				cpu->state = mc6809_state_label_a;
				continue;

			// 0x1183, 0x1193, 0x11a3, 0x11b3 CMPU
			// 0x118c, 0x119c, 0x11ac, 0x11bc CMPS
			case 0x83: case 0x93: case 0xa3: case 0xb3:
			case 0x8c: case 0x9c: case 0xac: case 0xbc: {
				unsigned tmp1, tmp2;
				tmp1 = !(op & 0x08) ? REG_U : REG_S;
				switch ((op >> 4) & 3) {
				case 0: tmp2 = word_immediate(cpu); break;
				case 1: tmp2 = word_direct(cpu); break;
				case 2: tmp2 = word_indexed(cpu); break;
				case 3: tmp2 = word_extended(cpu); break;
				default: tmp2 = 0; break;
				}
				(void)op_sub16(cpu, tmp1, tmp2);
				NVMA_CYCLE;
			} break;

			// Illegal instruction
			default:
				NVMA_CYCLE;
				break;
			}
			cpu->state = mc6809_state_label_a;
			goto done_instruction;
			}

		// Certain illegal instructions cause the CPU to lock up:
		case mc6809_state_hcf:
			NVMA_CYCLE;
			continue;

		}

done_instruction:
		instruction_posthook(cpu);
		continue;

	} while (cpu->running);

}