示例#1
0
static UINT32 process_rop(UINT32 src, UINT32 dst, UINT32 pat, const char* rop,
                          UINT32 format)
{
	DWORD stack[10] = { 0 };
	DWORD stackp = 0;

	while (*rop != '\0')
	{
		char op = *rop++;

		switch (op)
		{
			case '0':
				stack[stackp++] = FreeRDPGetColor(format, 0, 0, 0, 0xFF);
				break;

			case '1':
				stack[stackp++] = FreeRDPGetColor(format, 0xFF, 0xFF, 0xFF, 0xFF);
				break;

			case 'D':
				stack[stackp++] = dst;
				break;

			case 'S':
				stack[stackp++] = src;
				break;

			case 'P':
				stack[stackp++] = pat;
				break;

			case 'x':
				op_xor(stack, &stackp);
				break;

			case 'a':
				op_and(stack, &stackp);
				break;

			case 'o':
				op_or(stack, &stackp);
				break;

			case 'n':
				op_not(stack, &stackp);
				break;

			default:
				break;
		}
	}

	return stack[0];
}
示例#2
0
static int
op_oplevel(int level)
{
   int             precision;

   bwx_DEBUG(__FUNCTION__);

   /* set the precision */

   if ((precision = op_getprecision(level)) == OP_ERROR)
   {
      op_pulldown(2);
      sprintf(bwb_ebuf, "exp_operation(): failed to set precision.");
      bwb_error(bwb_ebuf);
      return FALSE;
   }
   /* precision is set correctly */

   else
   {

      switch (CURTASK exps[level].operation)
      {
      case OP_ADD:
         op_add(level, precision);
         break;

      case OP_SUBTRACT:
         op_subtract(level, precision);
         break;

      case OP_MULTIPLY:
         op_multiply(level, precision);
         break;

      case OP_DIVIDE:
         op_divide(level, precision);
         break;

      case OP_ASSIGN:
         op_assign(level, precision);
         break;

      case OP_EQUALS:
         op_equals(level, precision);
         break;

      case OP_LESSTHAN:
         op_lessthan(level, precision);
         break;

      case OP_GREATERTHAN:
         op_greaterthan(level, precision);
         break;

      case OP_LTEQ:
         op_lteq(level, precision);
         break;

      case OP_GTEQ:
         op_gteq(level, precision);
         break;

      case OP_NOTEQUAL:
         op_notequal(level, precision);
         break;

      case OP_MODULUS:
         op_modulus(level, precision);
         break;

      case OP_INTDIVISION:
         op_intdiv(level, precision);
         break;

      case OP_OR:
         op_or(level, precision);
         break;

      case OP_AND:
         op_and(level, precision);
         break;

      case OP_NOT:
         op_not(level, precision);
         break;

      case OP_XOR:
         op_xor(level, precision);
         break;

      case OP_IMPLIES:
         op_imp(level, precision);
         break;

      case OP_EQUIV:
         op_eqv(level, precision);
         break;

      case OP_EXPONENT:
         op_exponent(level, precision);
         break;

      case OP_NEGATION: /* JBV */
         op_negation(level, precision);
         break;

      case OP_POSATION:
         op_posation(level, precision);
         break;

      default:
         sprintf(bwb_ebuf, "PROGRAMMING ERROR: operator <%d> not (yet) supported.", CURTASK exps[level].operation);
         op_pulldown(2);
         bwb_error(bwb_ebuf);
         return FALSE;
         break;
      }     /* end of case statement for operators */
   }        /* end of else statement, precision set */

   return TRUE;

}           /* end of function op_oplevel() */
示例#3
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++;
}
示例#4
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;
}
示例#5
0
文件: mc6809.c 项目: jedie/XRoar
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);

}
示例#6
0
文件: regex.c 项目: digoal/pgbouncer
static int parse_posix_basic(struct ParseCtx *ctx, const char *re)
{
	int err = 0;
	unsigned c;
	int glevel = 0;
loop:
	if (err)
		return err;
	c = *re++;
	switch (c) {
	case 0:
		return (glevel == 0) ? 0 : REG_EPAREN;
	case '*':
		if (ctx->last_elem && ctx->last_elem->type != OP_BOL)
			err = op_count_simple(ctx, 0, MAX_COUNT);
		else
			err = op_char(ctx, '*');
		break;
	case '.':
		err = op_simple(ctx, OP_ANY);
		break;
	case '[':
		err = op_class(ctx, &re);
		break;
	case '^':
		if (!ctx->last_elem)
			err = op_simple(ctx, OP_BOL);
		else
			err = op_char(ctx, c);
		break;
	case '$':
		if (!*re || (re[0] == '\\' && re[1] == ')'))
			err = op_simple(ctx, OP_EOL);
		else
			err = op_char(ctx, c);
		break;
	case '\\':
		goto escaped;
	default:
		err = op_char(ctx, c);
	}
	goto loop;

escaped:
	c = *re++;
	switch (c) {
	case 0:
		return REG_EESCAPE;
	case '(':
		glevel++;
		err = op_gstart(ctx);
		break;
	case ')':
		glevel--;
		if (glevel < 0)
			return REG_EPAREN;
		err = op_gend(ctx);
		break;
	case '{':
		err = op_count_full(ctx, &re);
		break;
	case '.': case '^': case '$': case '*':
	case '[': case ']': case '\\':
		err = op_char(ctx, c);
		break;
	case '1': case '2': case '3': case '4': case '5':
	case '6': case '7': case '8': case '9':
		err = op_bref(ctx, c);
		break;
	case '|':
		err = STRICT ? REG_BADPAT : op_or(ctx);
		break;
	default:
		err = parse_relaxed_escapes(ctx, c);
	}
	goto loop;
}
示例#7
0
文件: regex.c 项目: digoal/pgbouncer
static int parse_posix_ext(struct ParseCtx *ctx, const char *re)
{
	int err = 0;
	unsigned c;
	int glevel = 0;
loop:
	if (err)
		return err;
	c = *re++;
	switch (c) {
	case 0:
		return (glevel == 0) ? 0 : REG_EPAREN;
	case '(':
		glevel++;
		err = op_gstart(ctx);
		break;
	case ')':
		if (glevel > 0) {
			glevel--;
			err = op_gend(ctx);
		} else  {
			err = op_char(ctx, c); /* POSIX bug */
		}
		break;
	case '|':
		err = op_or(ctx);
		break;
	case '*':
		err = op_count_simple(ctx, 0, MAX_COUNT);
		break;
	case '?':
		err = op_count_simple(ctx, 0, 1);
		break;
	case '+':
		err = op_count_simple(ctx, 1, MAX_COUNT);
		break;
	case '[':
		err = op_class(ctx, &re);
		break;
	case '{':
		err = op_count_full(ctx, &re);
		break;
	case '.':
		err = op_simple(ctx, OP_ANY);
		break;
	case '^':
		err = op_simple(ctx, OP_BOL);
		break;
	case '$':
		err = op_simple(ctx, OP_EOL);
		break;
	case '\\':
		goto escaped;
	default:
		err = op_char(ctx, c);
	}
	goto loop;

escaped:
	c = *re++;
	if (c == 0)
		err = REG_EESCAPE;
	else if (c >= '0' && c <= '9')
		err = STRICT ? REG_BADPAT : op_bref(ctx, c);
	else if (isalpha(c))
		err = parse_relaxed_escapes(ctx, c);
	else
		err = op_char(ctx, c);
	goto loop;
}