Пример #1
0
	void compile(RuntimeBlockInfo* block, bool force_checks, bool reset, bool staging, bool optimise) {
		mov(rax, (size_t)&cycle_counter);

		sub(dword[rax], block->guest_cycles);

		sub(rsp, 0x28);

		for (size_t i = 0; i < block->oplist.size(); i++) {
			shil_opcode& op  = block->oplist[i];
			switch (op.op) {

			case shop_ifb:
				if (op.rs1._imm)
				{
					mov(rax, (size_t)&next_pc);
					mov(dword[rax], op.rs2._imm);
				}

				mov(call_regs[0], op.rs3._imm);

				call(OpDesc[op.rs3._imm]->oph);
				break;

			case shop_jdyn:
				{
					mov(rax, (size_t)op.rs1.reg_ptr());

					mov(ecx, dword[rax]);

					if (op.rs2.is_imm()) {
						add(ecx, op.rs2._imm);
					}
					mov(dword[rax], ecx);
				}
				break;

			case shop_mov32:
			{
				verify(op.rd.is_reg());

				verify(op.rs1.is_reg() || op.rs1.is_imm());

				sh_to_reg(op.rs1, mov, ecx);

				reg_to_sh(op.rd, ecx);
			}
			break;

			case shop_mov64:
			{
				verify(op.rd.is_reg());

				verify(op.rs1.is_reg() || op.rs1.is_imm());

				sh_to_reg(op.rs1, mov, rcx);

				reg_to_sh(op.rd, rcx);
			}
			break;

			case shop_readm:
			{
				sh_to_reg(op.rs1, mov, call_regs[0]);
				sh_to_reg(op.rs3, add, call_regs[0]);

				u32 size = op.flags & 0x7f;

				if (size == 1) {
					call(ReadMem8);
					movsx(rcx, al);
				}
				else if (size == 2) {
					call(ReadMem16);
					movsx(rcx, ax);
				}
				else if (size == 4) {
					call(ReadMem32);
					mov(rcx, rax);
				}
				else if (size == 8) {
					call(ReadMem64);
					mov(rcx, rax);
				}
				else {
					die("1..8 bytes");
				}

				if (size != 8)
					reg_to_sh(op.rd, ecx);
				else
					reg_to_sh(op.rd, rcx);
			}
			break;

			case shop_writem:
			{
				u32 size = op.flags & 0x7f;
				sh_to_reg(op.rs1, mov, call_regs[0]);
				sh_to_reg(op.rs3, add, call_regs[0]);

				if (size != 8)
					sh_to_reg(op.rs2, mov, call_regs[1]);
				else
					sh_to_reg(op.rs2, mov, call_regs64[1]);

				if (size == 1)
					call(WriteMem8);
				else if (size == 2)
					call(WriteMem16);
				else if (size == 4)
					call(WriteMem32);
				else if (size == 8)
					call(WriteMem64);
				else {
					die("1..8 bytes");
				}
			}
			break;

			default:
				shil_chf[op.op](&op);
				break;
			}
		}

		verify(block->BlockType == BET_DynamicJump);

		add(rsp, 0x28);
		ret();

		ready();

		block->code = (DynarecCodeEntryPtr)getCode();

		emit_Skip(getSize());
	}
Пример #2
0
struct code encode(struct instruction instr)
{
    switch (instr.opcode) {
    case INSTR_ADD:
        return add(instr.optype, instr.source, instr.dest);
    case INSTR_NOT:
        return not(instr.optype, instr.source);
    case INSTR_MUL:
        return mul(instr.optype, instr.source);
    case INSTR_XOR:
        return xor(instr.optype, instr.source, instr.dest);
    case INSTR_DIV:
        return encode_div(instr.optype, instr.source);
    case INSTR_AND:
        return and(instr.optype, instr.source, instr.dest);
    case INSTR_OR:
        return or(instr.optype, instr.source, instr.dest);
    case INSTR_SHL:
        return shl(instr.optype, instr.source, instr.dest);
    case INSTR_SHR:
        return shr(instr.optype, instr.source, instr.dest);
    case INSTR_SAR:
        return sar(instr.optype, instr.source, instr.dest);
    case INSTR_CALL:
        return call(instr.optype, instr.source);
    case INSTR_CMP:
        return cmp(instr.optype, instr.source, instr.dest);
    case INSTR_MOV:
        return mov(instr.optype, instr.source, instr.dest);
    case INSTR_MOVSX:
        return movsx(instr.optype, instr.source, instr.dest);
    case INSTR_MOVZX:
        return movzx(instr.optype, instr.source, instr.dest);
    case INSTR_MOVAPS:
        return movaps(instr.optype, instr.source, instr.dest);
    case INSTR_PUSH:
        return push(instr.optype, instr.source);
    case INSTR_SUB:
        return sub(instr.optype, instr.source, instr.dest);
    case INSTR_LEA:
        return lea(instr.optype, instr.source, instr.dest);
    case INSTR_LEAVE:
        return leave();
    case INSTR_REP_MOVSQ:
        assert(instr.optype == OPT_NONE);
        return rep_movsq();
    case INSTR_RET:
        return ret();
    case INSTR_JMP:
        return jmp(instr.optype, instr.source);
    case INSTR_JA:
        return jcc(instr.optype, TEST_A, instr.source);
    case INSTR_JG:
        return jcc(instr.optype, TEST_G, instr.source);
    case INSTR_JZ:
        return jcc(instr.optype, TEST_Z, instr.source);
    case INSTR_JAE:
        return jcc(instr.optype, TEST_AE, instr.source);
    case INSTR_JGE:
        return jcc(instr.optype, TEST_GE, instr.source);
    case INSTR_SETZ:
        return setcc(instr.optype, TEST_Z, instr.source);
    case INSTR_SETA:
        return setcc(instr.optype, TEST_A, instr.source);
    case INSTR_SETG:
        return setcc(instr.optype, TEST_G, instr.source);
    case INSTR_SETAE:
        return setcc(instr.optype, TEST_AE, instr.source);
    case INSTR_SETGE:
        return setcc(instr.optype, TEST_GE, instr.source);
    case INSTR_TEST:
        return test(instr.optype, instr.source, instr.dest);
    default:
        return nop();
    }
}
Пример #3
0
	void compile(RuntimeBlockInfo* block, bool force_checks, bool reset, bool staging, bool optimise) {
		mov(rax, (size_t)&cycle_counter);

		sub(dword[rax], block->guest_cycles);

		sub(rsp, 0x28);

		for (size_t i = 0; i < block->oplist.size(); i++) {
			shil_opcode& op  = block->oplist[i];
			switch (op.op) {

			case shop_ifb:
				if (op.rs1._imm)
				{
					mov(rax, (size_t)&next_pc);
					mov(dword[rax], op.rs2._imm);
				}

				mov(call_regs[0], op.rs3._imm);

				call((void*)OpDesc[op.rs3._imm]->oph);
				break;

			case shop_jcond:
			case shop_jdyn:
				{
					mov(rax, (size_t)op.rs1.reg_ptr());

					mov(ecx, dword[rax]);

					if (op.rs2.is_imm()) {
						add(ecx, op.rs2._imm);
					}

					mov(rdx, (size_t)op.rd.reg_ptr());
					mov(dword[rdx], ecx);
				}
				break;

			case shop_mov32:
			{
				verify(op.rd.is_reg());

				verify(op.rs1.is_reg() || op.rs1.is_imm());

				sh_to_reg(op.rs1, mov, ecx);

				reg_to_sh(op.rd, ecx);
			}
			break;

			case shop_mov64:
			{
				verify(op.rd.is_reg());

				verify(op.rs1.is_reg() || op.rs1.is_imm());

				sh_to_reg(op.rs1, mov, rcx);

				reg_to_sh(op.rd, rcx);
			}
			break;

			case shop_readm:
			{
				sh_to_reg(op.rs1, mov, call_regs[0]);
				sh_to_reg(op.rs3, add, call_regs[0]);

				u32 size = op.flags & 0x7f;

				if (size == 1) {
					call((void*)ReadMem8);
					movsx(rcx, al);
				}
				else if (size == 2) {
					call((void*)ReadMem16);
					movsx(rcx, ax);
				}
				else if (size == 4) {
					call((void*)ReadMem32);
					mov(rcx, rax);
				}
				else if (size == 8) {
					call((void*)ReadMem64);
					mov(rcx, rax);
				}
				else {
					die("1..8 bytes");
				}

				if (size != 8)
					reg_to_sh(op.rd, ecx);
				else
					reg_to_sh(op.rd, rcx);
			}
			break;

			case shop_writem:
			{
				u32 size = op.flags & 0x7f;
				sh_to_reg(op.rs1, mov, call_regs[0]);
				sh_to_reg(op.rs3, add, call_regs[0]);

				if (size != 8)
					sh_to_reg(op.rs2, mov, call_regs[1]);
				else
					sh_to_reg(op.rs2, mov, call_regs64[1]);

				if (size == 1)
					call((void*)WriteMem8);
				else if (size == 2)
					call((void*)WriteMem16);
				else if (size == 4)
					call((void*)WriteMem32);
				else if (size == 8)
					call((void*)WriteMem64);
				else {
					die("1..8 bytes");
				}
			}
			break;

			default:
				shil_chf[op.op](&op);
				break;
			}
		}

		mov(rax, (size_t)&next_pc);

		switch (block->BlockType) {

		case BET_StaticJump:
		case BET_StaticCall:
			//next_pc = block->BranchBlock;
			mov(dword[rax], block->BranchBlock);
			break;

		case BET_Cond_0:
		case BET_Cond_1:
			{
				//next_pc = next_pc_value;
				//if (*jdyn == 0)
				//next_pc = branch_pc_value;

				mov(dword[rax], block->NextBlock);

				if (block->has_jcond)
					mov(rdx, (size_t)&Sh4cntx.jdyn);
				else
					mov(rdx, (size_t)&sr.T);

				cmp(dword[rdx], block->BlockType & 1);
				Xbyak::Label branch_not_taken;

				jne(branch_not_taken, T_SHORT);
				mov(dword[rax], block->BranchBlock);
				L(branch_not_taken);
			}
			break;

		case BET_DynamicJump:
		case BET_DynamicCall:
		case BET_DynamicRet:
			//next_pc = *jdyn;
			mov(rdx, (size_t)&Sh4cntx.jdyn);
			mov(edx, dword[rdx]);
			mov(dword[rax], edx);
			break;

		case BET_DynamicIntr:
		case BET_StaticIntr:
			if (block->BlockType == BET_DynamicIntr) {
				//next_pc = *jdyn;
				mov(rdx, (size_t)&Sh4cntx.jdyn);
				mov(edx, dword[rdx]);
				mov(dword[rax], edx);
			}
			else {
				//next_pc = next_pc_value;
				mov(dword[rax], block->NextBlock);
			}

			call((void*)UpdateINTC);
			break;

		default:
			die("Invalid block end type");
		}


		add(rsp, 0x28);
		ret();

		ready();

		block->code = (DynarecCodeEntryPtr)getCode();

		emit_Skip(getSize());
	}