コード例 #1
0
ファイル: cpurec.cpp プロジェクト: V10lator/emumaster
/*!
	Compiles a stub needed to call C++ translator.process() from asm code.
 */
inline void NesCpuTranslator::mTranslateCaller()
{
	// r0 - PC address
	// lr - caller address - lr will not be used to return to the caller,
	//		it's used to fix branch instruction
	__ bind(&m_translateCallerLabel);
	mSaveInternalFlags();

	// adjust lr to point to branch instruction and move it to r1 as an argument
	// for translateStub() function
	__ sub(r1, lr, Operand(4));
	mCallCFunction(offsetof(NesCpuRecData,translate));

	mRestoreInternalFlags();
	// translate function returns address of recompiled code
	// just jump to it
	__ mov(pc, r0);
}
コード例 #2
0
template <typename Visitor> void enumerateFields_gen(OperandAddress obj,  Visitor & vis) {
  enumerateFields_gen(Operand(obj), vis);
  vis(obj.symbol(),"symbol");
  vis(obj.reg(),"reg");
  enumerateFields(obj.offset(), vis);
}
コード例 #3
0
//-----------------------------------------------------------------------
void FunctionInvocation::pushOperand(ParameterPtr parameter, Operand::OpSemantic opSemantic, int opMask, int indirectionLevel)
{
    mOperands.push_back(Operand(parameter, opSemantic, opMask, indirectionLevel));
}
コード例 #4
0
ファイル: ModuleEx.cpp プロジェクト: JFreaker/CodeReverse
void CR_ModuleEx::CreateFlowGraph64(CR_Addr64 entrance) {
    auto cf = Info64()->CodeFuncFromAddr(entrance);
    assert(cf);

    CR_Addr64Set leaders;
    leaders.insert(entrance);

    // insert jumpees
    auto& jumpees = cf->Jumpees();
    leaders.insert(jumpees.begin(), jumpees.end());

    // insert exits' next
    auto& exits = cf->Exits();
    for (auto addr : exits) {
        auto op_code = Info64()->OpCodeFromAddr(addr);
        auto size = op_code->Codes().size();
        auto next_addr = static_cast<CR_Addr64>(addr + size);
        leaders.insert(next_addr);
    }

    // insert jumpers' next
    auto& jumpers = cf->Jumpers();
    for (auto addr : jumpers) {
        auto op_code = Info64()->OpCodeFromAddr(addr);
        auto size = op_code->Codes().size();
        auto next_addr = static_cast<CR_Addr64>(addr + size);
        leaders.insert(next_addr);
    }

    // sort
    std::vector<CR_Addr64> vecLeaders(leaders.begin(), leaders.end());
    std::sort(vecLeaders.begin(), vecLeaders.end());

    // store leaders
    cf->Leaders() = std::move(leaders);

    const size_t size = vecLeaders.size() - 1;
    for (size_t i = 0; i < size; ++i) {
        // for every pair of two adjacent leaders
        auto addr1 = vecLeaders[i], addr2 = vecLeaders[i + 1];
        // prepare a basic block
        CR_BasicBlock64 block;
        block.m_addr = addr1;
        CR_Addr64 next_addr = cr_invalid_addr64;
        for (auto addr = addr1; addr < addr2; ) {
            if (cf->Leaders().count(addr)) {
                // set label at each leader
                block.AddLeaderLabel(addr);
            }
            // op.code from addr
            auto op_code = Info64()->OpCodeFromAddr(addr);
            if (op_code == NULL) {
                break;
            }
            auto type = op_code->OpCodeType();
            if (type == cr_OCT_JMP) {
                // jump
                auto oper = op_code->Operand(0);
                if (oper->GetOperandType() == cr_DF_IMM) {
                    block.m_jump_to = oper->Value64();  // jump to
                }
                next_addr = cr_invalid_addr64;
            } else if (type == cr_OCT_RETURN) {
                next_addr = cr_invalid_addr64;
            } else if (type == cr_OCT_JCC || type == cr_OCT_LOOP) {
                // conditional jump or loop
                auto oper = op_code->Operand(0);
                if (oper->GetOperandType() == cr_DF_IMM) {
                    block.m_jump_to = oper->Value64();  // jump to
                }
                block.m_cond_code = op_code->CondCode();
                next_addr =
                    static_cast<CR_Addr64>(addr + op_code->Codes().size());
            } else {
                next_addr =
                    static_cast<CR_Addr64>(addr + op_code->Codes().size());
            }
            // add op.code
            block.m_stmts.emplace_back(*op_code);
            // go to next addr
            addr += static_cast<CR_Addr64>(op_code->Codes().size());
        }
        // add label at last
        block.AddLeaderLabel(addr2);
        // set next addr
        block.m_next_addr = next_addr;
        // add block
        cf->BasicBlocks().emplace_back(block);
    }
} // CR_ModuleEx::CreateFlowGraph64
コード例 #5
0
ファイル: CCodeGenerator.cpp プロジェクト: mfichman/jogo
void CCodeGenerator::enter_scope() {
    return_val_ = Operand();
    block_has_return_ = false;
    scope_.push_back(new Scope);
}
コード例 #6
0
ファイル: CCodeGenerator.cpp プロジェクト: mfichman/jogo
void CCodeGenerator::operator()(FloatLiteral* expression) {
    return_ = Operand(expression);
}
コード例 #7
0
template <typename Visitor> void enumerateFields_gen(OperandString obj,  Visitor & vis) {
  enumerateFields_gen(Operand(obj), vis);
  vis(obj.string(),"string");
}
コード例 #8
0
ファイル: SharedIC-arm64.cpp プロジェクト: luke-chang/gecko-1
bool
ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler& masm)
{
    // Guard that R0 is an integer and R1 is an integer.
    Label failure;
    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
    masm.branchTestInt32(Assembler::NotEqual, R1, &failure);

    // Add R0 and R1. Don't need to explicitly unbox, just use R2.
    Register Rscratch = R2_;
    ARMRegister Wscratch = ARMRegister(Rscratch, 32);
#ifdef MERGE
    // DIV and MOD need an extra non-volatile ValueOperand to hold R0.
    AllocatableGeneralRegisterSet savedRegs(availableGeneralRegs(2));
    savedRegs.set() = GeneralRegisterSet::Intersect(GeneralRegisterSet::NonVolatile(), savedRegs);
#endif
    // get some more ARM-y names for the registers
    ARMRegister W0(R0_, 32);
    ARMRegister X0(R0_, 64);
    ARMRegister W1(R1_, 32);
    ARMRegister X1(R1_, 64);
    ARMRegister WTemp(ExtractTemp0, 32);
    ARMRegister XTemp(ExtractTemp0, 64);
    Label maybeNegZero, revertRegister;
    switch(op_) {
      case JSOP_ADD:
        masm.Adds(WTemp, W0, Operand(W1));

        // Just jump to failure on overflow. R0 and R1 are preserved, so we can
        // just jump to the next stub.
        masm.j(Assembler::Overflow, &failure);

        // Box the result and return. We know R0 already contains the
        // integer tag, so we just need to move the payload into place.
        masm.movePayload(ExtractTemp0, R0_);
        break;

      case JSOP_SUB:
        masm.Subs(WTemp, W0, Operand(W1));
        masm.j(Assembler::Overflow, &failure);
        masm.movePayload(ExtractTemp0, R0_);
        break;

      case JSOP_MUL:
        masm.mul32(R0.valueReg(), R1.valueReg(), Rscratch, &failure, &maybeNegZero);
        masm.movePayload(Rscratch, R0_);
        break;

      case JSOP_DIV:
      case JSOP_MOD: {

        // Check for INT_MIN / -1, it results in a double.
        Label check2;
        masm.Cmp(W0, Operand(INT_MIN));
        masm.B(&check2, Assembler::NotEqual);
        masm.Cmp(W1, Operand(-1));
        masm.j(Assembler::Equal, &failure);
        masm.bind(&check2);
        Label no_fail;
        // Check for both division by zero and 0 / X with X < 0 (results in -0).
        masm.Cmp(W1, Operand(0));
        // If x > 0, then it can't be bad.
        masm.B(&no_fail, Assembler::GreaterThan);
        // if x == 0, then ignore any comparison, and force
        // it to fail, if x < 0 (the only other case)
        // then do the comparison, and fail if y == 0
        masm.Ccmp(W0, Operand(0), vixl::ZFlag, Assembler::NotEqual);
        masm.B(&failure, Assembler::Equal);
        masm.bind(&no_fail);
        masm.Sdiv(Wscratch, W0, W1);
        // Start calculating the remainder, x - (x / y) * y.
        masm.mul(WTemp, W1, Wscratch);
        if (op_ == JSOP_DIV) {
            // Result is a double if the remainder != 0, which happens
            // when (x/y)*y != x.
            masm.branch32(Assembler::NotEqual, R0.valueReg(), ExtractTemp0, &revertRegister);
            masm.movePayload(Rscratch, R0_);
        } else {
            // Calculate the actual mod. Set the condition code, so we can see if it is non-zero.
            masm.Subs(WTemp, W0, WTemp);

            // If X % Y == 0 and X < 0, the result is -0.
            masm.Ccmp(W0, Operand(0), vixl::NoFlag, Assembler::Equal);
            masm.branch(Assembler::LessThan, &revertRegister);
            masm.movePayload(ExtractTemp0, R0_);
        }
        break;
      }
        // ORR, EOR, AND can trivially be coerced int
        // working without affecting the tag of the dest..
      case JSOP_BITOR:
        masm.Orr(X0, X0, Operand(X1));
        break;
      case JSOP_BITXOR:
        masm.Eor(X0, X0, Operand(W1, vixl::UXTW));
        break;
      case JSOP_BITAND:
        masm.And(X0, X0, Operand(X1));
        break;
        // LSH, RSH and URSH can not.
      case JSOP_LSH:
        // ARM will happily try to shift by more than 0x1f.
        masm.Lsl(Wscratch, W0, W1);
        masm.movePayload(Rscratch, R0.valueReg());
        break;
      case JSOP_RSH:
        masm.Asr(Wscratch, W0, W1);
        masm.movePayload(Rscratch, R0.valueReg());
        break;
      case JSOP_URSH:
        masm.Lsr(Wscratch, W0, W1);
        if (allowDouble_) {
            Label toUint;
            // Testing for negative is equivalent to testing bit 31
            masm.Tbnz(Wscratch, 31, &toUint);
            // Move result and box for return.
            masm.movePayload(Rscratch, R0_);
            EmitReturnFromIC(masm);

            masm.bind(&toUint);
            masm.convertUInt32ToDouble(Rscratch, ScratchDoubleReg);
            masm.boxDouble(ScratchDoubleReg, R0, ScratchDoubleReg);
        } else {
            // Testing for negative is equivalent to testing bit 31
            masm.Tbnz(Wscratch, 31, &failure);
            // Move result for return.
            masm.movePayload(Rscratch, R0_);
        }
        break;
      default:
        MOZ_CRASH("Unhandled op for BinaryArith_Int32.");
    }

    EmitReturnFromIC(masm);

    switch (op_) {
      case JSOP_MUL:
        masm.bind(&maybeNegZero);

        // Result is -0 if exactly one of lhs or rhs is negative.
        masm.Cmn(W0, W1);
        masm.j(Assembler::Signed, &failure);

        // Result is +0, so use the zero register.
        masm.movePayload(rzr, R0_);
        EmitReturnFromIC(masm);
        break;
      case JSOP_DIV:
      case JSOP_MOD:
        masm.bind(&revertRegister);
        break;
      default:
        break;
    }

    // Failure case - jump to next stub.
    masm.bind(&failure);
    EmitStubGuardFailure(masm);

    return true;
}
コード例 #9
0
template <typename Visitor> void enumerateFields_gen(OperandOperandList obj,  Visitor & vis) {
  enumerateFields_gen(Operand(obj), vis);
  vis(obj.elements(),"elements");
}
コード例 #10
0
template <typename Visitor> void enumerateFields_gen(OperandRegister obj,  Visitor & vis) {
  enumerateFields_gen(Operand(obj), vis);
  vis(obj.regKind(),"regKind");
  vis(obj.regNum(),"regNum");
}
コード例 #11
0
template <typename Visitor> void enumerateFields_gen(OperandConstantBytes obj,  Visitor & vis) {
  enumerateFields_gen(Operand(obj), vis);
  vis(obj.type(),"type");
  vis(obj.bytes(),"bytes");
}
コード例 #12
0
template <typename Visitor> void enumerateFields_gen(OperandCodeRef obj,  Visitor & vis) {
  enumerateFields_gen(Operand(obj), vis);
  vis(obj.ref(),"ref");
}
コード例 #13
0
template <typename Visitor> void enumerateFields_gen(OperandAlign obj,  Visitor & vis) {
  enumerateFields_gen(Operand(obj), vis);
  vis(obj.align(),"align");
}
コード例 #14
0
ファイル: cpurec.cpp プロジェクト: V10lator/emumaster
void NesCpuTranslator::mSync()
{
	// r0 - 6502.PC address of the next instruction

	__ bind(&m_syncLabel);
	Label exitSync;
	Label handleEvent;
	mSaveInternalFlags();
	// IRQ can be cleared, so we must fetch additional cycles every time
	mFetchAdditionalCycles();
	mHandleInterrupts();

	// IRQ may be pending and P.I can be set, in this case we may not call
	// nesSync if mCycles < 0
	__ mov(mCycles, mCycles, SetCC);
	__ b(&m_checkInterruptsForNextInstruction, mi);

	__ bind(&m_syncWithoutInterruptHandling);

	int preserved = r0.bit() | lr.bit();
#if defined(FRAME_POINTER_FOR_GDB)
	preserved |= fp.bit();
#endif
	__ stm(db_w, sp, preserved);
#if defined(FRAME_POINTER_FOR_GDB)
	__ add(fp, sp, Operand(2*4));
#endif

	Label dontSyncWithApuAndClock;
	__ ldr(ip, MemOperand(mDataBase, offsetof(NesCpuRecData,startCycles)));
	__ add(r0, mCycles, ip, SetCC);
	__ b(&dontSyncWithApuAndClock, eq);
	mCallCFunction(offsetof(NesCpuRecData,apuClock));
	if (nesMapper->hasClock()) {
		__ ldr(ip, MemOperand(mDataBase, offsetof(NesCpuRecData,startCycles)));
		__ add(r0, mCycles, ip, SetCC);
		mCallCFunction(offsetof(NesCpuRecData,mapperClock));
	}
	__ bind(&dontSyncWithApuAndClock);

	__ mov(r0, mCycles);
	mCallCFunction(offsetof(NesCpuRecData,nesSync));
	__ str(r0, MemOperand(mDataBase, offsetof(NesCpuRecData,startCycles)));
	__ rsb(mCycles, r0, Operand(0), SetCC);
	__ ldm(ia_w, sp, preserved);

	// if r0 >= 0 then it means we should handle an event
	__ b(&handleEvent, pl);

	// interrupts handling is a little tricky:
	//   - once interrupt occurs save cycles in the memory
	//   - force mSync to be called next time by setting mCycles to zero
	//   - handle interrupt in the new mSync call
	__ bind(&m_checkInterruptsForNextInstruction);
	mClearAlert();
	__ ldr(ip, MemOperand(mDataBase, offsetof(NesCpuRecData,interrupts)));
	__ mov(ip, ip, SetCC);
	__ b(&exitSync, eq);
	// interrupt is pending here
	__ str(mCycles, MemOperand(mDataBase,
							   offsetof(NesCpuRecData,additionalCycles)));
	__ mov(mCycles, Operand(0));
	__ b(&exitSync);

// handleEvent:
	__ bind(&handleEvent);
	__ rsb(r1, mCycles, Operand(0));
	__ mov(mCycles, Operand(0));
	__ str(mCycles, MemOperand(mDataBase, offsetof(NesCpuRecData,startCycles)));
	mHandleEvent();
	__ b(&m_syncWithoutInterruptHandling);

// exitSync:
	__ bind(&exitSync);
	mRestoreInternalFlags();
	// r0 must be loaded here with 6502.PC address of the next instruction
	__ mov(pc, lr);
}
コード例 #15
0
template <typename Visitor> void enumerateFields_gen(OperandWavesize obj,  Visitor & vis) {
  enumerateFields_gen(Operand(obj), vis);
}
コード例 #16
0
ファイル: cpurec.cpp プロジェクト: V10lator/emumaster
void NesCpuTranslator::mClearAlert()
{
	__ mov(ip, Operand(NesCpuRecData::AlertOff));
	__ str(ip, MemOperand(mDataBase, offsetof(NesCpuRecData,alert)));
}
コード例 #17
0
ファイル: sync.cpp プロジェクト: nezticle/EmuMasterPi
void NesSyncCompiler::mClock(int ppuCycles)
{
	/*
		Here the compiler will generate following function:

		syncData.baseCycleCounter += baseCycles;
		u64 cpuCyclesNow = syncData.baseCycleCounter / nesEmu.clockDividerForCpu();
		syncData.cpuCycleCounter += additionalCpuCycles;
		int newCpuCycles = cpuCyclesNow - syncData.cpuCycleCounter;
		if (newCpuCycles > 0) {
			syncData.cpuCycleCounter += newCpuCycles;
			return newCpuCycles;
		}
		return 0;

		If return value != 0 it will return to the cpu emulation also.
	*/
	int baseCycles = ppuCycles * nesEmu.clockDividerForPpu();
	Q_ASSERT(baseCycles >= 0);
	__ Ldrd(r0, r1, MemOperand(m_dataBase, offsetof(NesSyncData,baseCycleCounter)));
	__ add(r0, r0, Operand(baseCycles), SetCC);
	__ adc(r1, r1, Operand(0));
	__ Strd(r0, r1, MemOperand(m_dataBase, offsetof(NesSyncData,baseCycleCounter)));

	if (nesEmu.clockDividerForCpu() == 12
	#if !defined(CAN_USE_ARMV7_INSTRUCTIONS)
		|| nesEmu.clockDividerForCpu() == 16
	#endif
		) {
		__ mov(r2, Operand(nesEmu.clockDividerForCpu()));
		__ mov(r3, Operand(0));
		u8 *uldiv = reinterpret_cast<u8 *>(&__aeabi_uldivmod);
		__ mov(ip, Operand(reinterpret_cast<u32>(uldiv)));
		__ blx(ip);
#if defined(CAN_USE_ARMV7_INSTRUCTIONS)
	} else if (nesEmu.clockDividerForCpu() == 16) {
		__ bfi(r0, r1, 0, 4);
		__ mov(r0, Operand(r0, ROR, 4));
		__ mov(r1, Operand(r1, LSR, 4));
#endif
	} else {
		UNREACHABLE();
	}

	__ Ldrd(r2, r3, MemOperand(m_dataBase, offsetof(NesSyncData,cpuCycleCounter)));
	__ add(r2, r2, m_additionalCpuCycles, SetCC);
	__ adc(r3, r3, Operand(0));
	__ Strd(r2, r3, MemOperand(m_dataBase, offsetof(NesSyncData,cpuCycleCounter)));

	// clear additionalCpuCycles here because mClock can be executed multiple
	// times in single synchronization step
	__ mov(m_additionalCpuCycles, Operand(0));

	__ sub(r0, r0, r2);
	__ cmp(r0, Operand(0));
	__ mov(r0, Operand(0), LeaveCC, le);

	Label holdCpu;
	__ b(&holdCpu, le);

	__ add(r2, r2, r0, SetCC);
	__ adc(r3, r3, Operand(0));
	__ Strd(r2, r3, MemOperand(m_dataBase, offsetof(NesSyncData,cpuCycleCounter)));

	mLeaveToCpu();

	__ bind(&holdCpu);
}
コード例 #18
0
ファイル: processor.cpp プロジェクト: MakSim345/MS-VC08
void Processor::RunMemoryProg(int _n_trace)
    /*
      MemCell* memory //pointer to an array!,
      Processor* pProc,
      int Trace*/
{
    int  StopFlag = 0;
    char cInput[20];
    char cInTrace[20];

    Trace = _n_trace;
    setInstructionCounter(START_ADDRESS); // set counter to the start == 0
 
    do  
     {
        // copy next memory cell to the Register:
        this->InstructionRegister(memory->GetCellValue(this->InstructionCounter()) );
        // get an operation code and operand from Register:
        this->GetCOPO(); 
        // save an address of memory cell where data is:        
        memory->SetCellCounter(Operand());

        switch ( this->OperationCode() )
        {
         case READ: // 10 - read a word from the terminal to the memory cell
            printf (" Enter value: > ");
            gets(cInput);
            memory->SetCellValue(cInput); //
            this->incInctructionCounter();
            break;

         case WRITE:// 11 - print a word from the memory cell to the terminal
            // memory->PrintCurCellNumber(); 
            printf ("Output: \n");
            printf ("**************\n");
            memory->PrintCellValue();
            printf ("\n**************\n\n");
            this->incInctructionCounter();
            break;
         
         case LOAD: // 20 - save a word from the memory cell to an accumulator
            this->Accumulator( memory->GetCellValue() ); 
            this->incInctructionCounter();
            break;

        case STORE: // 21 - //save a word from accumulator to memory cell
            memory->SetCellValue(this->Accumulator()); 
            this->incInctructionCounter();
            break;

         case ADD:
            this->Accumulator(this->Accumulator() + memory->GetCellValue());
            this->incInctructionCounter();
            break;

         case SUBTRACT:
            this->Accumulator(this->Accumulator() - memory->GetCellValue()); //
            this->incInctructionCounter();
            break;

         case DIVIDE:
            if (this->Accumulator() == 0)
            {
                printf ("ERROR: divide to zero!\n");
                printf ("Program complete by error.\n");
                StopFlag = 1;
            }
            else
            {
                this->Accumulator(memory->GetCellValue() / this->Accumulator());
            }            
            this->incInctructionCounter();
            break;

         case MULTIPLY:
            this->Accumulator(this->Accumulator() * memory->GetCellValue()); //
            this->incInctructionCounter();
            break; 

         case BRANCH: //GOTO
            this->setInstructionCounter(Operand());
            break;

         case BRANCHNEG: // branch if accumulator is negative
            if (this->Accumulator() < 0) 
                this->setInstructionCounter(Operand());
            else
                this->incInctructionCounter();
            break;

         case BRANCHZERO:
            if (this->Accumulator() == 0) 
                this->setInstructionCounter(Operand());
            else
                this->incInctructionCounter();
            break;

         case HALT:
            printf ("Program complete.\n");
            StopFlag = 1;
            break;      
                
         default: 
            printf ("Unexpected value in the address %d\n", Operand());
            StopFlag = 1;
        }// case
        
        if (Trace)
        {
          memory->PrintMemoryDump ();
          this->PrintProcState();
          printf("\nPress Enter to TRACE >> ");
          gets(cInTrace);
        }

    } while (!StopFlag);

    this->PrintProcState();

};
コード例 #19
0
ファイル: sync.cpp プロジェクト: nezticle/EmuMasterPi
void NesSyncCompiler::mPpuSetVBlank(bool on)
{
	__ mov(r0, Operand(static_cast<int>(on)));
	mCallCFunction(offsetof(NesSyncData,ppuSetVBlank));
}
コード例 #20
0
ファイル: CCodeGenerator.cpp プロジェクト: mfichman/jogo
void CCodeGenerator::operator()(IntegerLiteral* expression) {
    //return_ = alloc_temp(expression->type());
	//out_ << expression->value()->string() << ";\n";
    return_ = Operand(expression);
}
コード例 #21
0
ファイル: test3.minivm.c プロジェクト: elopez/AC
#include <minivm/language.h>

/* Prints 0 1 2 3 using the stack. */
Instruction code[15] = {
    Instruction(PUSH, Operand(IMM, 3)),
    Instruction(MOV, Operand(IMM, 2), Operand(REG, R0)),
    Instruction(PUSH, Operand(REG, R0)),
    Instruction(MOV, Operand(IMM, 1), Operand(REG, R1)),
    Instruction(PUSH, Operand(REG, R1)),
    Instruction(PUSH, Operand(REG, ZERO)),
    Instruction(POP, Operand(REG, R0)),
    Instruction(PRINT, Operand(REG, R0)),
    Instruction(POP, Operand(REG, R0)),
    Instruction(PRINT, Operand(REG, R0)),
    Instruction(POP, Operand(REG, R0)),
    Instruction(PRINT, Operand(REG, R0)),
    Instruction(POP, Operand(REG, R0)),
    Instruction(PRINT, Operand(REG, R0)),
    Instruction(HLT)
};
コード例 #22
0
ファイル: CCodeGenerator.cpp プロジェクト: mfichman/jogo
void CCodeGenerator::operator()(BooleanLiteral* expression) {
    return_ = Operand(expression);
}
コード例 #23
0
ファイル: cpurec.cpp プロジェクト: V10lator/emumaster
/*!
	Translates 6502 instructions starting from \a instrPointer.
	\a instrPointer contains value of the 6502.PC register
	\a caller is a pointer to the branch instruction which initiated the
		translation
 */
inline void *NesCpuTranslator::process(u16 instrPointer, u8 *caller)
{
	int count = 128;
	if (instrPointer < 0x4000) {
		count = 16;
		memset32(m_labels + m_lastRecompilationInRam,
				 -m_translateCallerLabel.pos()-1,
				 count * 4);
		m_lastRecompilationInRam = instrPointer;
	}
	// check if already translated
	if (m_labels[instrPointer] == m_translateCallerLabel) {
		Q_ASSERT(!m_checkAlertAfterInstruction);
		m_recPc = instrPointer;

		int page = nesCpuPageByAddr(instrPointer);
		int recompiledStart = m_pageTranslationOffset[page];
		m_masm->setPcOffset(recompiledStart);

		// recompile here
		while (m_labels[m_recPc] == m_translateCallerLabel &&
			   nesCpuPageByAddr(m_recPc) == page &&
			   count > 0) {

			m_labels[m_recPc].unuse();
			__ bind(&m_labels[m_recPc]);

#if defined(ENABLE_DEBUGGING)
			__ mov(r0, Operand(currentPc()));
			__ bl(&m_debugStepLabel);
#endif

#if !defined(DISABLE_RECOMPILER_OPTIMIZATIONS)
			if (!mTryOptimize())
#endif
				mSingleInstruction();

			if (m_checkAlertAfterInstruction) {
				mCheckAlert();
				m_checkAlertAfterInstruction = false;
			}

			count--;
		}
		// in the end jump to next instruction label
		u16 endRecPc = m_recPc;
		m_recPc = instrPointer;
		mJump(endRecPc);

		// flush const pool or any other pending data in the assembler
		m_masm->flush();
		// save translation end pointer for this page
		int recompiledEnd = m_masm->pcOffset();
		m_pageTranslationOffset[page] = recompiledEnd;
		Q_ASSERT(page == 0 || recompiledEnd < (page+1) * BlockSize);
		// flush instruction cache
		int recompiledSize = recompiledEnd - recompiledStart;
		Cpu::flushICache(m_codeBuffer + recompiledStart, recompiledSize);
		// mark translation page used
		m_pageUsedMask |= 1 << page;

		// handle section boundary because 6502 has variable length of
		// instructions (m_recPc == 0 on KIL instruction so omit that value)
		int pageNow = nesCpuPageByAddr(m_recPc);
		if (m_recPc && pageNow != page)
			saveTranslationBoundary(page, m_recPc & NesCpuBankMask);
	}
	fixCallerInstruction(instrPointer, caller);
	return m_codeBuffer + m_labels[instrPointer].pos();
}
コード例 #24
0
ファイル: ModuleEx.cpp プロジェクト: JFreaker/CodeReverse
BOOL CR_ModuleEx::_DisAsmAddr64(CR_Addr64 func, CR_Addr64 va) {
    if (!IsModuleLoaded() || !Is64Bit())
        return FALSE;

    // calculate
    int len;
    char outbuf[256];
    CR_Addr64 addr;

    // add or retrieve the code function
    auto cf = Info64()->CodeFuncFromAddr(func);
    if (cf == NULL) {
        Info64()->MapAddrToCodeFunc().emplace(func, make_shared<CR_CodeFunc64>());
        cf = Info64()->CodeFuncFromAddr(func);
    }
    assert(cf);
    if (func == va) {
        cf->Addr() = func;
    }

    auto pCode = CodeSectionHeader();
    assert(pCode);

    DWORD rva = RVAFromVA64(va);
    LPBYTE input = m_pLoadedImage + rva;
    LPBYTE iend = m_pLoadedImage + pCode->RVA + pCode->SizeOfRawData;
    while (input < iend) {
        // add or retrieve op.code
        auto oc = Info64()->OpCodeFromAddr(va);
        if (oc == NULL) {
            Info64()->MapAddrToOpCode().emplace(va, make_shared<CR_OpCode64>());
            oc = Info64()->OpCodeFromAddr(va);
            // set op.code address
            oc->Addr() = va;
        }
        assert(oc);
        if (oc->FuncAddrs().count(func) > 0)
            break;


        // add function address for this op.code
        oc->FuncAddrs().emplace(func);
        if (oc->FuncAddrs().size() > 1) {
            cf->FuncFlags() |= cr_FF_FUNCINFUNC;   // function in function
        }

        if (oc->Codes().empty()) {
            // disassemble
            len = disasm(input, outbuf, sizeof(outbuf), 64, va, false, 0);

            // parse insn
            if (!len || input + len > iend) {
                len = 1;
                oc->Name() = "???";
                oc->OpCodeType() = cr_OCT_UNKNOWN;
                // don't decompile if any unknown instruction.
                cf->FuncFlags() |= cr_FF_INVALID;
            } else {
                oc->Parse(outbuf);
            }

            // complement operand size
            oc->DeductOperandSizes();

            // add asm codes to op.code
            oc->Codes().insert(oc->Codes().end(), input, &input[len]);
        } else {
            len = int(oc->Codes().size());
        }

        BOOL bBreak = FALSE;
        switch (oc->OpCodeType()) {
        case cr_OCT_JCC:    // conditional jump
            switch (oc->Operand(0)->GetOperandType()) {
            case cr_DF_IMM:
                addr = oc->Operand(0)->Value64();
                cf->Jumpers().emplace(va);
                cf->Jumpees().emplace(addr);
                break;

            default:
                break;
            }
            break;

        case cr_OCT_JMP:    // jump
            switch (oc->Operand(0)->GetOperandType()) {
            case cr_DF_IMM:
                if (func == va) {
                    // func is jumper
                    cf->FuncFlags() |= cr_FF_JUMPERFUNC;

                    addr = oc->Operand(0)->Value64();
                    Info64()->Entrances().emplace(addr);
                    cf->Callers().emplace(addr);

                    auto newcf = Info64()->CodeFuncFromAddr(addr);
                    if (newcf == NULL) {
                        Info64()->MapAddrToCodeFunc().emplace(
                            addr, make_shared<CR_CodeFunc64>());
                        newcf = Info64()->CodeFuncFromAddr(addr);
                    }
                    newcf->Addr() = addr;
                    newcf->Callees().emplace(func);
                } else {
                    addr = oc->Operand(0)->Value64();
                    cf->Jumpers().emplace(va);
                    cf->Jumpees().emplace(addr);
                }
                break;

            case cr_DF_MEMIMM:
                if (func == va) {
                    // func is jumper
                    cf->FuncFlags() |= cr_FF_JUMPERFUNC;

                    bBreak = TRUE;
                }
                break;

            default:
                break;
            }
            bBreak = TRUE;
            break;

        case cr_OCT_CALL:   // call
            switch (oc->Operand(0)->GetOperandType()) {
            case cr_DF_IMM:
                // function call
                addr = oc->Operand(0)->Value64();
                Info64()->Entrances().emplace(addr);
                cf->Callees().emplace(addr);
                {
                    auto newcf = Info64()->CodeFuncFromAddr(addr);
                    if (newcf == NULL) {
                        Info64()->MapAddrToCodeFunc().emplace(
                            addr, make_shared<CR_CodeFunc64>());
                        newcf = Info64()->CodeFuncFromAddr(addr);
                    }
                    newcf->Addr() = addr;
                    newcf->Callers().emplace(func);
                }
                break;

            default:
                break;
            }
            break;

        case cr_OCT_RETURN: // return
            if (oc->Operands().size() && oc->Operand(0)->GetOperandType() == cr_DF_IMM) {
                cf->StackArgSizeRange().Set(oc->Operand(0)->Value64());
            } else {
                if (func == va) {
                    cf->FuncFlags() |= cr_FF_RETURNONLY;
                }
            }
            cf->Exits().insert(va);
            bBreak = TRUE;
            break;

        default:
            break;
        }

        if (bBreak)
            break;

        // move to next position
        input += len;
        va += len;
    }

    return TRUE;
} // CR_ModuleEx::_DisAsmAddr64
コード例 #25
0
ファイル: cpurec.cpp プロジェクト: V10lator/emumaster
/*!
	Increments cycle counter \a n times.
 */
inline void NesCpuTranslator::mAddCycles(int n, Condition cond)
{
	__ add(mCycles, mCycles, Operand(n), LeaveCC, cond);
}
コード例 #26
0
ファイル: instruction.cpp プロジェクト: episeclab/medusa
//TODO: Need more work
bool Instruction::GetOperandReference(Database const& rDatabase, u8 Oprd, Address const& rAddrSrc, Address& rAddrDst) const
{
  medusa::Operand const* pOprd = Operand(Oprd);
  TOffset Offset = 0x0;

  rAddrDst = rAddrSrc;

  // XXX: Should never happen
  if (pOprd == NULL) return false;

  if (pOprd->GetType() & O_NO_REF)
    return false;

  if ((pOprd->GetType() & O_REL) || ((pOprd->GetType() & O_REG_PC_REL) && (pOprd->GetType() & O_MEM)))
  {
    switch (pOprd->GetType() & DS_MASK)
    {
      case DS_8BIT:   Offset = static_cast<s8> (pOprd->GetValue()) + GetLength(); break;
      case DS_16BIT:  Offset = static_cast<s16>(pOprd->GetValue()) + GetLength(); break;
      case DS_32BIT:  Offset = static_cast<s32>(pOprd->GetValue()) + GetLength(); break;
      case DS_64BIT:  Offset = static_cast<s64>(pOprd->GetValue()) + GetLength(); break;
      default:        Offset = pOprd->GetValue() + GetLength();
    }

    rAddrDst = rAddrSrc + Offset;
    return true;
  }

  else if ((pOprd->GetType() & O_ABS) || (pOprd->GetType() & O_IMM) || (pOprd->GetType() & O_DISP))
  {
    switch (pOprd->GetType() & DS_MASK)
    {
      case DS_8BIT:   rAddrDst.SetOffset(static_cast<s8> (pOprd->GetValue())); break;
      case DS_16BIT:  rAddrDst.SetOffset(static_cast<s16>(pOprd->GetValue())); break;
      case DS_32BIT:  rAddrDst.SetOffset(static_cast<s32>(pOprd->GetValue())); break;
      case DS_64BIT:  rAddrDst.SetOffset(static_cast<s64>(pOprd->GetValue())); break;
      default:        rAddrDst.SetOffset(pOprd->GetValue());
    }

    return true;
  }

  else if ((pOprd->GetType() & O_MEM))
  {
    if (pOprd->GetType() & O_REG_PC_REL)
      Offset += rAddrSrc.GetOffset();

    switch (pOprd->GetType() & DS_MASK)
    {
      case DS_8BIT:   Offset += static_cast<s8> (pOprd->GetValue()) + GetLength(); break;
      case DS_16BIT:  Offset += static_cast<s16>(pOprd->GetValue()) + GetLength(); break;
      case DS_32BIT:  Offset += static_cast<s32>(pOprd->GetValue()) + GetLength(); break;
      case DS_64BIT:  Offset += static_cast<s64>(pOprd->GetValue()) + GetLength(); break;
      default:        Offset += pOprd->GetValue() + GetLength();
    }

    rAddrDst.SetOffset(Offset);
    TOffset RawOffset;
    MemoryArea const* pMemArea = rDatabase.GetMemoryArea(rAddrDst);
    if (pMemArea == nullptr)                   return false;
    if (!pMemArea->Convert(Offset, RawOffset)) return false;

    BinaryStream const& rBinStrm = pMemArea->GetBinaryStream();

    u64 ReadOffset = 0x0;
    try
    {
      switch (pOprd->GetType() & MS_MASK)
      {
      case MS_8BIT:  rBinStrm.Read(RawOffset, ReadOffset); ReadOffset &= 0xff;       break;
      case MS_16BIT: rBinStrm.Read(RawOffset, ReadOffset); ReadOffset &= 0xffff;     break;
      case MS_32BIT: rBinStrm.Read(RawOffset, ReadOffset); ReadOffset &= 0xffffffff; break;
      case MS_64BIT: rBinStrm.Read(RawOffset, ReadOffset);                           break;
      default: return false;
      }
    }
    catch(Exception&) { return false; }

    rAddrDst.SetOffset(ReadOffset);
    return true;
  }

  return false;
}
コード例 #27
0
ファイル: test8.minivm.c プロジェクト: elopez/AC
#include <minivm/language.h>

/* 3 will print a 3 and exit. Under 3 will ask for another number.
 * 4+ will exit immediately. */
Instruction code[7] = {
    Instruction(READ, Operand(REG, R0)),
    Instruction(CMP, Operand(REG, R0), Operand(IMM, 3)),
    Instruction(JMPE, Operand(IMM, 5)),
    Instruction(JMPL, Operand(REG, ZERO)),
    Instruction(JMP, Operand(IMM, 6)),
    Instruction(PRINT, Operand(REG, R0)),
    Instruction(HLT)
};